aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-05-22 17:09:26 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-05-22 17:09:26 -0300
commitc595a2c2935b5bfcb2c08cc9ec4a22db55bd1ff7 (patch)
tree71cfc1618994dcfce80a2d9d31412992eaf8eaa4
parent74f12f3f2bb6cafc25ba1e943d01583b1ac0d766 (diff)
downloadgame-c595a2c2935b5bfcb2c08cc9ec4a22db55bd1ff7.tar.gz
game-c595a2c2935b5bfcb2c08cc9ec4a22db55bd1ff7.zip
implement TReadStream, TReadBuffer, and TReadBinaryFile
-rw-r--r--TODO.md6
-rw-r--r--reference/game.c773
-rw-r--r--reference/types.hh21
-rw-r--r--src/common.hh34
-rw-r--r--src/script.cc149
-rw-r--r--src/script.hh31
-rw-r--r--src/util.cc136
7 files changed, 351 insertions, 799 deletions
diff --git a/TODO.md b/TODO.md
index 4ddece4..42dd643 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,7 +1,7 @@
## TODO NEXT
-- TReadStream/TWriteStream
-- TReadBuffer/TWriteBuffer
-- TReadBinaryFile/TWriteBinaryFile
+- TWriteStream
+- TWriteBuffer
+- TWriteBinaryFile
- TCreature
- TPlayer
- TNonPlayer
diff --git a/reference/game.c b/reference/game.c
index 975bc84..4692709 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -2057,135 +2057,6 @@ void print(void)
return;
}
-
-// DWARF original prototype: bool readFlag(TReadStream * this)
-
-bool __thiscall TReadStream::readFlag(TReadStream *this)
-
-{
- int iVar1;
-
- // try { // try from 0804d1ce to 0804d1d0 has its CatchHandler @ 0804d1e0
- iVar1 = (*this->_vptr_TReadStream[1])(this);
- return (char)iVar1 != '\0';
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Lo
-// DWARF original prototype: ushort readWord(TReadStream * this)
-
-ushort __thiscall TReadStream::readWord(TReadStream *this)
-
-{
- uchar Hi;
- int iVar1;
- uint uVar2;
- uchar Lo;
-
- // try { // try from 0804d211 to 0804d21e has its CatchHandler @ 0804d232
- iVar1 = (*this->_vptr_TReadStream[1])(this);
- uVar2 = (*this->_vptr_TReadStream[1])(this);
- return (ushort)(byte)iVar1 | (ushort)((uVar2 & 0xff) << 8);
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: hi
-// DWARF original prototype: ulong readQuad(TReadStream * this)
-
-ulong __thiscall TReadStream::readQuad(TReadStream *this)
-
-{
- int iVar1;
- int iVar2;
- int iVar3;
- int iVar4;
- uchar Hi;
- uchar hi;
- uchar lo;
- uchar Lo;
-
- // try { // try from 0804d261 to 0804d284 has its CatchHandler @ 0804d2b0
- iVar1 = (*this->_vptr_TReadStream[1])(this);
- iVar2 = (*this->_vptr_TReadStream[1])(this);
- iVar3 = (*this->_vptr_TReadStream[1])(this);
- iVar4 = (*this->_vptr_TReadStream[1])(this);
- return (uint)CONCAT12((char)iVar3,CONCAT11((char)iVar2,(char)iVar1)) | iVar4 << 0x18;
-}
-
-
-
-// DWARF original prototype: void readString(TReadStream * this, char * Buffer, int MaxLength)
-
-void __thiscall TReadStream::readString(TReadStream *this,char *Buffer,int MaxLength)
-
-{
- uint uVar1;
- undefined4 *puVar2;
- int Length;
-
- if (Buffer != (char *)0x0) {
- // try { // try from 0804d2f2 to 0804d3a4 has its CatchHandler @ 0804d3a5
- uVar1 = (*this->_vptr_TReadStream[2])(this);
- uVar1 = uVar1 & 0xffff;
- if (uVar1 == 0xffff) {
- uVar1 = (*this->_vptr_TReadStream[3])(this);
- }
- *Buffer = '\0';
- if (uVar1 != 0) {
- if ((MaxLength < 0) || ((int)uVar1 < MaxLength)) {
- (*this->_vptr_TReadStream[5])(this,Buffer,uVar1);
- Buffer[uVar1] = '\0';
- }
- else {
- (*this->_vptr_TReadStream[5])(this,Buffer,MaxLength + -1);
- Buffer[MaxLength + -1] = '\0';
- (*this->_vptr_TReadStream[7])(this,(uVar1 - MaxLength) + 1);
- }
- }
- return;
- }
- error(&DAT_080eeba0);
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = "internal error";
- // WARNING: Subroutine does not return
- __cxa_throw(puVar2,char_const*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: void readBytes(TReadStream * this, uchar * Buffer, int Count)
-
-void __thiscall TReadStream::readBytes(TReadStream *this,uchar *Buffer,int Count)
-
-{
- int iVar1;
- undefined4 *puVar2;
- int i;
- int iVar3;
-
- if (Buffer == (uchar *)0x0) {
- error(&DAT_080eebe0);
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = "internal error";
- // WARNING: Subroutine does not return
- __cxa_throw(puVar2,char_const*::typeinfo,0);
- }
- iVar3 = 0;
- if (0 < Count) {
- do {
- // try { // try from 0804d3f5 to 0804d43a has its CatchHandler @ 0804d440
- iVar1 = (*this->_vptr_TReadStream[1])(this);
- Buffer[iVar3] = (uchar)iVar1;
- iVar3 = iVar3 + 1;
- } while (iVar3 < Count);
- }
- return;
-}
-
-
-
// DWARF original prototype: void writeFlag(TWriteStream * this, bool f)
void __thiscall TWriteStream::writeFlag(TWriteStream *this,bool f)
@@ -2282,199 +2153,6 @@ void __thiscall TWriteStream::writeBytes(TWriteStream *this,uchar *Buffer,int Co
return;
}
-
-
-// DWARF original prototype: void TReadBuffer(TReadBuffer * this, uchar * data, int size)
-
-void __thiscall TReadBuffer::TReadBuffer(TReadBuffer *this,uchar *data,int size)
-
-{
- (this->super_TReadStream)._vptr_TReadStream = (_func_int_varargs **)&PTR_readFlag_081267c8;
- this->Data = data;
- this->Size = size;
- this->Position = 0;
- if (data == (uchar *)0x0) {
- error("TReadBuffer::TReadBuffer: data ist NULL.\n");
- }
- else {
- if (-1 < size) {
- return;
- }
- error(&DAT_080eec60,size);
- }
- this->Size = 0;
- return;
-}
-
-
-
-// DWARF original prototype: void TReadBuffer(TReadBuffer * this, uchar * data, int size)
-
-void __thiscall TReadBuffer::TReadBuffer(TReadBuffer *this,uchar *data,int size)
-
-{
- (this->super_TReadStream)._vptr_TReadStream = (_func_int_varargs **)&PTR_readFlag_081267c8;
- this->Data = data;
- this->Size = size;
- this->Position = 0;
- if (data == (uchar *)0x0) {
- error("TReadBuffer::TReadBuffer: data ist NULL.\n");
- }
- else {
- if (-1 < size) {
- return;
- }
- error(&DAT_080eec60,size);
- }
- this->Size = 0;
- return;
-}
-
-
-
-// DWARF original prototype: uchar readByte(TReadBuffer * this)
-
-uchar __thiscall TReadBuffer::readByte(TReadBuffer *this)
-
-{
- uchar uVar1;
- int iVar2;
- undefined4 *puVar3;
- uchar b;
-
- iVar2 = this->Position;
- if (iVar2 <= this->Size + -1) {
- uVar1 = this->Data[iVar2];
- this->Position = iVar2 + 1;
- return uVar1;
- }
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = "buffer empty";
- // WARNING: Subroutine does not return
- // try { // try from 0804d7e3 to 0804d7e7 has its CatchHandler @ 0804d7e8
- __cxa_throw(puVar3,char_const*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: ushort readWord(TReadBuffer * this)
-
-ushort __thiscall TReadBuffer::readWord(TReadBuffer *this)
-
-{
- uchar uVar1;
- uchar uVar2;
- int iVar3;
- ushort w;
- undefined4 *puVar4;
-
- iVar3 = this->Position;
- if (iVar3 <= this->Size + -2) {
- uVar1 = this->Data[iVar3];
- uVar2 = this->Data[iVar3 + 1];
- this->Position = iVar3 + 2;
- return CONCAT11(uVar2,uVar1);
- }
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = "buffer empty";
- // WARNING: Subroutine does not return
- // try { // try from 0804d860 to 0804d864 has its CatchHandler @ 0804d865
- __cxa_throw(puVar4,char_const*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: ulong readQuad(TReadBuffer * this)
-
-ulong __thiscall TReadBuffer::readQuad(TReadBuffer *this)
-
-{
- uchar uVar1;
- uchar uVar2;
- uchar uVar3;
- uchar uVar4;
- int iVar5;
- uchar *puVar6;
- ulong q;
- undefined4 *puVar7;
-
- iVar5 = this->Position;
- if (iVar5 <= this->Size + -4) {
- puVar6 = this->Data;
- uVar1 = puVar6[iVar5 + 3];
- uVar2 = puVar6[iVar5 + 2];
- uVar3 = puVar6[iVar5 + 1];
- uVar4 = puVar6[iVar5];
- this->Position = iVar5 + 4;
- return CONCAT31(CONCAT21(CONCAT11(uVar1,uVar2),uVar3),uVar4);
- }
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = "buffer empty";
- // WARNING: Subroutine does not return
- // try { // try from 0804d8f6 to 0804d8fa has its CatchHandler @ 0804d8fb
- __cxa_throw(puVar7,char_const*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: void readBytes(TReadBuffer * this, uchar * Buffer, int Count)
-
-void __thiscall TReadBuffer::readBytes(TReadBuffer *this,uchar *Buffer,int Count)
-
-{
- undefined4 *puVar1;
-
- if (Buffer == (uchar *)0x0) {
- error(&DAT_080eece0);
- puVar1 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar1 = "buffer not existing";
- }
- else {
- if (this->Position <= this->Size - Count) {
- memcpy(Buffer,this->Data + this->Position,Count);
- this->Position = this->Position + Count;
- return;
- }
- puVar1 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar1 = "buffer empty";
- }
- // WARNING: Subroutine does not return
- // try { // try from 0804d97c to 0804d98c has its CatchHandler @ 0804d9a1
- __cxa_throw(puVar1,char_const*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: bool eof(TReadBuffer * this)
-
-bool __thiscall TReadBuffer::eof(TReadBuffer *this)
-
-{
- return this->Size <= this->Position;
-}
-
-
-
-// DWARF original prototype: void skip(TReadBuffer * this, int Count)
-
-void __thiscall TReadBuffer::skip(TReadBuffer *this,int Count)
-
-{
- undefined4 *puVar1;
-
- if (this->Position <= this->Size - Count) {
- this->Position = Count + this->Position;
- return;
- }
- puVar1 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar1 = "buffer empty";
- // WARNING: Subroutine does not return
- // try { // try from 0804da2d to 0804da31 has its CatchHandler @ 0804da32
- __cxa_throw(puVar1,char_const*::typeinfo,0);
-}
-
-
-
// DWARF original prototype: void TWriteBuffer(TWriteBuffer * this, uchar * data, int size)
void __thiscall TWriteBuffer::TWriteBuffer(TWriteBuffer *this,uchar *data,int size)
@@ -3594,457 +3272,6 @@ LAB_0804eb1e:
return;
}
-
-// DWARF original prototype: void TReadBinaryFile(TReadBinaryFile * this)
-
-void __thiscall TReadBinaryFile::TReadBinaryFile(TReadBinaryFile *this)
-
-{
- (this->super_TReadStream)._vptr_TReadStream = (_func_int_varargs **)&PTR_readFlag_081268c8;
- this->File = (FILE *)0x0;
- return;
-}
-
-
-
-// DWARF original prototype: void TReadBinaryFile(TReadBinaryFile * this)
-
-void __thiscall TReadBinaryFile::TReadBinaryFile(TReadBinaryFile *this)
-
-{
- (this->super_TReadStream)._vptr_TReadStream = (_func_int_varargs **)&PTR_readFlag_081268c8;
- this->File = (FILE *)0x0;
- return;
-}
-
-
-
-// DWARF original prototype: void ~TReadBinaryFile(TReadBinaryFile * this, int __in_chrg)
-
-void __thiscall TReadBinaryFile::~TReadBinaryFile(TReadBinaryFile *this,int __in_chrg)
-
-{
- FILE *pFVar1;
- char *pcVar2;
- int iVar3;
- int *piVar4;
-
- pFVar1 = this->File;
- (this->super_TReadStream)._vptr_TReadStream = (_func_int_varargs **)&PTR_readFlag_081268c8;
- if (pFVar1 != (FILE *)0x0) {
- pcVar2 = "";
- if (this != (TReadBinaryFile *)0xfffffff8) {
- pcVar2 = this->Filename;
- }
- ::error("TReadBinaryFile::~TReadBinaryFile: Datei %s ist noch offen.\n",pcVar2);
- iVar3 = fclose((FILE *)this->File);
- if (iVar3 != 0) {
- piVar4 = __errno_location();
- ::error(&DAT_080efc80,*piVar4);
- }
- }
- return;
-}
-
-
-
-// DWARF original prototype: void ~TReadBinaryFile(TReadBinaryFile * this, int __in_chrg)
-
-void __thiscall TReadBinaryFile::~TReadBinaryFile(TReadBinaryFile *this,int __in_chrg)
-
-{
- FILE *pFVar1;
- char *pcVar2;
- int iVar3;
- int *piVar4;
-
- pFVar1 = this->File;
- (this->super_TReadStream)._vptr_TReadStream = (_func_int_varargs **)&PTR_readFlag_081268c8;
- if (pFVar1 != (FILE *)0x0) {
- pcVar2 = "";
- if (this != (TReadBinaryFile *)0xfffffff8) {
- pcVar2 = this->Filename;
- }
- ::error("TReadBinaryFile::~TReadBinaryFile: Datei %s ist noch offen.\n",pcVar2);
- iVar3 = fclose((FILE *)this->File);
- if (iVar3 != 0) {
- piVar4 = __errno_location();
- ::error(&DAT_080efc80,*piVar4);
- }
- }
- return;
-}
-
-
-
-// DWARF original prototype: void ~TReadBinaryFile(TReadBinaryFile * this, int __in_chrg)
-
-void __thiscall TReadBinaryFile::~TReadBinaryFile(TReadBinaryFile *this,int __in_chrg)
-
-{
- FILE *pFVar1;
- char *pcVar2;
- int iVar3;
- int *piVar4;
-
- pFVar1 = this->File;
- (this->super_TReadStream)._vptr_TReadStream = (_func_int_varargs **)&PTR_readFlag_081268c8;
- if (pFVar1 != (FILE *)0x0) {
- pcVar2 = "";
- if (this != (TReadBinaryFile *)0xfffffff8) {
- pcVar2 = this->Filename;
- }
- ::error("TReadBinaryFile::~TReadBinaryFile: Datei %s ist noch offen.\n",pcVar2);
- iVar3 = fclose((FILE *)this->File);
- if (iVar3 != 0) {
- piVar4 = __errno_location();
- ::error(&DAT_080efc80,*piVar4);
- }
- }
- operator_delete(this);
- return;
-}
-
-
-
-// DWARF original prototype: void open(TReadBinaryFile * this, char * FileName)
-
-int __thiscall TReadBinaryFile::open(TReadBinaryFile *this,char *__file,int __oflag,...)
-
-{
- FILE *pFVar1;
- undefined4 *puVar2;
- int iVar3;
- int *piVar4;
-
- if ((FILE *)this->File != (FILE *)0x0) {
- iVar3 = fclose((FILE *)this->File);
- if (iVar3 != 0) {
- piVar4 = __errno_location();
- // try { // try from 08050984 to 080509dc has its CatchHandler @ 080509dd
- ::error(&DAT_080efce0,*piVar4);
- }
- this->File = (FILE *)0x0;
- sprintf(ErrorString,"error in binary-file \"%s\": %s.",this->Filename,"File still open");
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = ErrorString;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar2,char*::typeinfo,0);
- }
- pFVar1 = fopen(__file,"rb");
- this->File = (FILE *)pFVar1;
- if (pFVar1 != (FILE *)0x0) {
- strcpy(this->Filename,__file);
- this->FileSize = -1;
- return -1;
- }
- sprintf(ErrorString,"Cannot open file %s",__file);
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = ErrorString;
- // WARNING: Subroutine does not return
- // try { // try from 08050961 to 08050965 has its CatchHandler @ 080509f0
- __cxa_throw(puVar2,char*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: void close(TReadBinaryFile * this)
-
-int __thiscall TReadBinaryFile::close(TReadBinaryFile *this,int __fd)
-
-{
- int __errnum;
- char *pcVar1;
- int *piVar2;
- int ErrorCode;
-
- pcVar1 = (char *)fclose((FILE *)this->File);
- if (pcVar1 != (char *)0x0) {
- piVar2 = __errno_location();
- __errnum = *piVar2;
- ::error(&DAT_080efd40);
- pcVar1 = strerror(__errnum);
- ::error("# Datei: %s, Fehlercode: %d (%s)\n",this->Filename,__errnum,pcVar1);
- }
- this->File = (FILE *)0x0;
- return (int)pcVar1;
-}
-
-
-
-// DWARF original prototype: void seek(TReadBinaryFile * this, long Offset)
-
-void __thiscall TReadBinaryFile::seek(TReadBinaryFile *this,long Offset)
-
-{
- FILE *__stream;
- int iVar1;
- int *piVar2;
- undefined4 *puVar3;
-
- __stream = (FILE *)this->File;
- if (__stream == (FILE *)0x0) {
- this->File = (FILE *)0x0;
- sprintf(ErrorString,"error in binary-file \"%s\": %s.",this->Filename,
- "File not open for seek");
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = ErrorString;
- // WARNING: Subroutine does not return
- // try { // try from 08050b6f to 08050b73 has its CatchHandler @ 08050b74
- __cxa_throw(puVar3,char*::typeinfo,0);
- }
- if (-1 < Offset) {
- fseek(__stream,Offset,0);
- return;
- }
- iVar1 = fclose(__stream);
- if (iVar1 != 0) {
- piVar2 = __errno_location();
- // try { // try from 08050ac7 to 08050b1f has its CatchHandler @ 08050b74
- ::error(&DAT_080efce0,*piVar2);
- }
- this->File = (FILE *)0x0;
- sprintf(ErrorString,"error in binary-file \"%s\": %s.",this->Filename,"Negative offset for seek"
- );
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = ErrorString;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,char*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: int getSize(TReadBinaryFile * this)
-
-int __thiscall TReadBinaryFile::getSize(TReadBinaryFile *this)
-
-{
- int iVar1;
- long __off;
- long lVar2;
- int Position;
-
- iVar1 = this->FileSize;
- if (iVar1 == -1) {
- __off = ftell((FILE *)this->File);
- fseek((FILE *)this->File,0,2);
- lVar2 = ftell((FILE *)this->File);
- this->FileSize = lVar2;
- fseek((FILE *)this->File,__off,0);
- iVar1 = this->FileSize;
- }
- return iVar1;
-}
-
-
-
-// DWARF original prototype: int getPosition(TReadBinaryFile * this)
-
-int __thiscall TReadBinaryFile::getPosition(TReadBinaryFile *this)
-
-{
- long lVar1;
-
- lVar1 = ftell((FILE *)this->File);
- return lVar1;
-}
-
-
-
-// DWARF original prototype: void error(TReadBinaryFile * this, char * Text)
-
-void __thiscall TReadBinaryFile::error(TReadBinaryFile *this,char *Text)
-
-{
- int iVar1;
- int *piVar2;
- undefined4 *puVar3;
-
- if ((FILE *)this->File != (FILE *)0x0) {
- iVar1 = fclose((FILE *)this->File);
- if (iVar1 != 0) {
- piVar2 = __errno_location();
- // try { // try from 08050c71 to 08050cd2 has its CatchHandler @ 08050cd3
- ::error(&DAT_080efce0,*piVar2);
- }
- }
- this->File = (FILE *)0x0;
- sprintf(ErrorString,"error in binary-file \"%s\": %s.",this->Filename,Text);
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = ErrorString;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,char*::typeinfo,0);
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Help
-// DWARF original prototype: uchar readByte(TReadBinaryFile * this)
-
-uchar __thiscall TReadBinaryFile::readByte(TReadBinaryFile *this)
-
-{
- char *Filename;
- size_t sVar1;
- int *piVar2;
- char *pcVar3;
- long lVar4;
- int iVar5;
- int iVar6;
- undefined4 *puVar7;
- int Result;
- int ErrorCode;
- uchar Help;
-
- sVar1 = fread((void *)((int)&ErrorCode + 3),1,1,(FILE *)this->File);
- if (sVar1 == 1) {
- return ErrorCode._3_1_;
- }
- piVar2 = __errno_location();
- iVar6 = *piVar2;
- // try { // try from 08050d50 to 08050dc5 has its CatchHandler @ 08050e52
- ::error("TReadBinaryFile::readByte: Fehler beim Lesen eines Bytes\n");
- pcVar3 = strerror(iVar6);
- lVar4 = ftell((FILE *)this->File);
- Filename = this->Filename;
- ::error(&DAT_080efe00,Filename,lVar4,sVar1,iVar6,pcVar3);
- iVar5 = fclose((FILE *)this->File);
- if (iVar5 != 0) {
- ::error(&DAT_080efe60,*piVar2,lVar4,sVar1,iVar6,pcVar3);
- }
- this->File = (FILE *)0x0;
- SaveFile(Filename);
- if ((FILE *)this->File != (FILE *)0x0) {
- iVar6 = fclose((FILE *)this->File);
- if (iVar6 != 0) {
- // try { // try from 08050de9 to 08050e3e has its CatchHandler @ 08050e3f
- ::error(&DAT_080efce0,*piVar2);
- }
- }
- this->File = (FILE *)0x0;
- sprintf(ErrorString,"error in binary-file \"%s\": %s.",Filename,"Error while reading byte");
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = ErrorString;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar7,char*::typeinfo,0);
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: ErrorCode
-// DWARF original prototype: void readBytes(TReadBinaryFile * this, uchar * Buffer, int Count)
-
-void __thiscall TReadBinaryFile::readBytes(TReadBinaryFile *this,uchar *Buffer,int Count)
-
-{
- char *Filename;
- size_t sVar1;
- int *piVar2;
- char *pcVar3;
- long lVar4;
- int iVar5;
- int iVar6;
- undefined4 *puVar7;
- int Result;
- int ErrorCode;
-
- sVar1 = fread(Buffer,1,Count,(FILE *)this->File);
- if (sVar1 == Count) {
- return;
- }
- piVar2 = __errno_location();
- iVar6 = *piVar2;
- // try { // try from 08050ebe to 08050f33 has its CatchHandler @ 08050fc0
- ::error("TReadBinaryFile::readBytes: Fehler beim Lesen von %d Bytes\n",Count);
- pcVar3 = strerror(iVar6);
- lVar4 = ftell((FILE *)this->File);
- Filename = this->Filename;
- ::error(&DAT_080efee0,Filename,lVar4,sVar1,iVar6,pcVar3);
- iVar5 = fclose((FILE *)this->File);
- if (iVar5 != 0) {
- ::error(&DAT_080efe60,*piVar2,lVar4,sVar1,iVar6,pcVar3);
- }
- this->File = (FILE *)0x0;
- SaveFile(Filename);
- if ((FILE *)this->File != (FILE *)0x0) {
- iVar6 = fclose((FILE *)this->File);
- if (iVar6 != 0) {
- // try { // try from 08050f57 to 08050fac has its CatchHandler @ 08050fad
- ::error(&DAT_080efce0,*piVar2);
- }
- }
- this->File = (FILE *)0x0;
- sprintf(ErrorString,"error in binary-file \"%s\": %s.",Filename,"Error while reading bytes");
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = ErrorString;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar7,char*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: bool eof(TReadBinaryFile * this)
-
-bool __thiscall TReadBinaryFile::eof(TReadBinaryFile *this)
-
-{
- long lVar1;
- int iVar2;
- long __off;
- long lVar3;
- undefined4 *puVar4;
- int Position;
-
- if ((FILE *)this->File != (FILE *)0x0) {
- lVar1 = ftell((FILE *)this->File);
- iVar2 = this->FileSize;
- if (iVar2 == -1) {
- __off = ftell((FILE *)this->File);
- fseek((FILE *)this->File,0,2);
- lVar3 = ftell((FILE *)this->File);
- this->FileSize = lVar3;
- fseek((FILE *)this->File,__off,0);
- iVar2 = this->FileSize;
- }
- return iVar2 <= lVar1;
- }
- this->File = (FILE *)0x0;
- sprintf(ErrorString,"error in binary-file \"%s\": %s.",this->Filename,
- "File not open for eof check");
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = ErrorString;
- // WARNING: Subroutine does not return
- // try { // try from 080510be to 080510c2 has its CatchHandler @ 080510c3
- __cxa_throw(puVar4,char*::typeinfo,0);
-}
-
-
-
-// DWARF original prototype: void skip(TReadBinaryFile * this, int Count)
-
-void __thiscall TReadBinaryFile::skip(TReadBinaryFile *this,int Count)
-
-{
- long lVar1;
- undefined4 *puVar2;
-
- if ((FILE *)this->File != (FILE *)0x0) {
- lVar1 = ftell((FILE *)this->File);
- // try { // try from 08051117 to 0805111b has its CatchHandler @ 08051190
- seek(this,lVar1 + Count);
- return;
- }
- this->File = (FILE *)0x0;
- sprintf(ErrorString,"error in binary-file \"%s\": %s.",this->Filename,"File not open for skip");
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = ErrorString;
- // WARNING: Subroutine does not return
- // try { // try from 08051172 to 08051176 has its CatchHandler @ 08051177
- __cxa_throw(puVar2,char*::typeinfo,0);
-}
-
-
-
// DWARF original prototype: void TWriteBinaryFile(TWriteBinaryFile * this)
void __thiscall TWriteBinaryFile::TWriteBinaryFile(TWriteBinaryFile *this)
diff --git a/reference/types.hh b/reference/types.hh
index bee9117..8aecd75 100644
--- a/reference/types.hh
+++ b/reference/types.hh
@@ -643,17 +643,6 @@ struct TWriteStream {
int (**_vptr.TWriteStream)(...);
};
-struct TReadStream {
- int (**_vptr.TReadStream)(...);
-};
-
-struct TReadBuffer {
- struct TReadStream super_TReadStream;
- uchar *Data;
- int Size;
- int Position;
-};
-
struct TWriteBuffer {
struct TWriteStream super_TWriteStream;
uchar *Data;
@@ -806,16 +795,6 @@ struct TWriteBinaryFile {
char Filename[4096];
};
-struct TReadBinaryFile {
- struct TReadStream super_TReadStream;
- undefined field1_0x1;
- undefined field2_0x2;
- undefined field3_0x3;
- FILE *File;
- char Filename[4096];
- int FileSize;
-};
-
struct TNPC {
struct TNonplayer super_TNonplayer;
ulong Interlocutor;
diff --git a/src/common.hh b/src/common.hh
index b057465..204cf2a 100644
--- a/src/common.hh
+++ b/src/common.hh
@@ -137,6 +137,38 @@ void SetPrintFunction(TPrintFunction *Function);
void error(char *Text, ...) ATTR_PRINTF(1, 2);
void print(int Level, char *Text, ...) ATTR_PRINTF(1, 2);
-//
+struct TReadStream {
+ // VIRTUAL FUNCTIONS
+ // =========================================================================
+ virtual bool readFlag(void); // VTABLE[0]
+ virtual uint8 readByte(void) = 0; // VTABLE[1]
+ virtual uint16 readWord(void); // VTABLE[2]
+ virtual uint32 readQuad(void); // VTABLE[3]
+ virtual void readString(char *Buffer, int MaxLength); // VTABLE[4]
+ virtual void readBytes(uint8 *Buffer, int Count); // VTABLE[5]
+ virtual bool eof(void) = 0; // VTABLE[6]
+ virtual void skip(int Count) = 0; // VTABLE[7]
+};
+
+struct TReadBuffer: TReadStream {
+ // REGULAR FUNCTIONS
+ // =========================================================================
+ TReadBuffer(uint8 *Data, int Size);
+
+ // VIRTUAL FUNCTIONS
+ // =========================================================================
+ uint8 readByte(void) override;
+ uint16 readWord(void) override;
+ uint32 readQuad(void) override;
+ void readBytes(uint8 *Buffer, int Count) override;
+ bool eof(void) override;
+ void skip(int Count) override;
+
+ // DATA
+ // =========================================================================
+ uint8 *Data;
+ int Size;
+ int Position;
+};
#endif //TIBIA_COMMON_HH_
diff --git a/src/script.cc b/src/script.cc
index 5c8c7d7..9db02f7 100644
--- a/src/script.cc
+++ b/src/script.cc
@@ -7,6 +7,8 @@
// which then becomes ambiguous whether you should free it or not. Used in:
// - TReadScriptFile::error
// - TWriteScriptFile::error
+// - TReadBinaryFile::open
+// - TReadBinaryFile::error
static char ErrorString[100];
// Helper Functions
@@ -113,7 +115,7 @@ static char *findLast(char *s, char c){
return Last;
}
-// TWriteScriptFile
+// TReadScriptFile
//==============================================================================
TReadScriptFile::TReadScriptFile(void){
this->RecursionDepth = -1;
@@ -788,3 +790,148 @@ void TWriteScriptFile::writeBytesequence(uint8 *Sequence, int Length){
this->writeText(s);
}
}
+
+// TReadBinaryFile REGULAR FUNCTIONS
+//==============================================================================
+TReadBinaryFile::TReadBinaryFile(void){
+ this->File = NULL;
+}
+
+void TReadBinaryFile::open(char *FileName){
+ if(this->File != NULL){
+ this->error("File still open");
+ }
+
+ this->File = fopen(FileName, "rb");
+ if(this->File == NULL){
+ snprintf(ErrorString, sizeof(ErrorString),
+ "Cannot open file %s", FileName);
+ throw ErrorString;
+ }
+
+ strcpy(this->Filename, FileName);
+ this->FileSize = -1;
+}
+
+int TReadBinaryFile::close(void){
+ // TODO(fusion): Check if file is NULL?
+ if(fclose(this->File) != 0){
+ int ErrCode = errno;
+ ::error("TReadBinaryFile::close: Fehler beim Schließen der Datei.\n");
+ ::error("# Datei: %s, Fehlercode: %d (%s)\n",
+ this->Filename, ErrCode, strerror(ErrCode));
+ }
+ this->File = NULL;
+}
+
+void TReadBinaryFile::error(char *Text){
+ if(this->File != NULL){
+ if(fclose(this->File) != 0){
+ ::error("TReadBinaryFile::error: Fehler %d beim Schließen der Datei.\n", errno);
+ }
+ this->File = NULL;
+ }
+
+ snprintf(ErrorString, sizeof(ErrorString),
+ "error in binary-file \"%s\": %s.",
+ this->Filename, Text);
+
+ throw ErrorString;
+}
+
+int TReadBinaryFile::getPosition(void){
+ // TODO(fusion): Check if file is NULL?
+ return (int)ftell(this->File);
+}
+
+int TReadBinaryFile::getSize(void){
+ // TODO(fusion): Check if file is NULL?
+ int Size = this->FileSize;
+ if(Size == -1){
+ long Position = ftell(this->File);
+ fseek(this->File, 0, SEEK_END);
+ Size = (int)ftell(this->File);
+ fseek(this->File, Position, SEEK_SET);
+ this->FileSize = Size;
+ }
+ return Size;
+}
+
+void TReadBinaryFile::seek(int Offset){
+ if(this->File == NULL){
+ this->error("File not open for seek");
+ }
+
+ if(Offset < 0){
+ this->error("Negative offset for seek");
+ }
+
+ fseek(this->File, (long)Offset, 0);
+}
+
+// TReadBinaryFile VIRTUAL FUNCTIONS
+//==============================================================================
+TReadBinaryFile::~TReadBinaryFile(void){
+ if(this->File != NULL){
+ ::error("TReadBinaryFile::~TReadBinaryFile: Datei %s ist noch offen.\n", this->Filename);
+ if(fclose(this->File) != 0){
+ ::error("TReadBinaryFile::~TReadBinaryFile: Fehler %d beim Schließen der Datei.\n", errno);
+ }
+ }
+}
+
+uint8 TReadBinaryFile::readByte(void){
+ uint8 Byte;
+ int Result = (int)fread(&Byte, 1, 1, this->File);
+ if(Result != 1){
+ int ErrCode = errno;
+ int Position = this->getPosition();
+ ::error("TReadBinaryFile::readByte: Fehler beim Lesen eines Bytes\n");
+ ::error("# Datei: %s, Position: %d, Rückgabewert: %d, Fehlercode: %d (%s)\n",
+ this->Filename, Position, Result, ErrCode, strerror(ErrCode));
+
+ // NOTE(fusion): Close file and make a backup, possibly for further inspection.
+ if(fclose(this->File) != 0){
+ ::error("TReadBinaryFile::readByte: Fehler %d beim Schließen der Datei.\n", errno);
+ }
+ SaveFile(this->Filename);
+
+ this->error("Error while reading byte");
+ }
+ return Byte;
+}
+
+void TReadBinaryFile::readBytes(uint8 *Buffer, int Count){
+ int Result = (int)fread(Buffer, 1, Count, this->File);
+ if(Result != Count){
+ int ErrCode = errno;
+ int Position = this->getPosition();
+ ::error("TReadBinaryFile::readBytes: Fehler beim Lesen von %d Bytes\n", Count);
+ ::error("# Datei: %s, Position %d, Rückgabewert: %d, Fehlercode: %d (%s)\n",
+ this->Filename, Position, Result, ErrCode, strerror(ErrCode));
+
+ // NOTE(fusion): Close file and make a backup, possibly for further inspection.
+ if(fclose(this->File) != 0){
+ ::error("TReadBinaryFile::readBytes: Fehler %d beim Schließen der Datei.\n", errno);
+ }
+ SaveFile(this->Filename);
+
+ this->error("Error while reading bytes");
+ }
+}
+
+bool TReadBinaryFile::eof(TReadBinaryFile *this){
+ if(this->File == NULL){
+ this->error("File not open for eof check");
+ }
+
+ return this->getSize() <= this->getPosition();
+}
+
+void TReadBinaryFile::skip(int Count){
+ if(this->File == NULL){
+ this->error("File not open for skip");
+ }
+
+ this->seek(this->getPosition() + Count);
+}
diff --git a/src/script.hh b/src/script.hh
index 0a83196..42ddd2e 100644
--- a/src/script.hh
+++ b/src/script.hh
@@ -101,4 +101,35 @@ struct TWriteScriptFile {
int Line;
};
+struct TReadBinaryFile: TReadStream {
+ // REGULAR FUNCTIONS
+ // =========================================================================
+ TReadBinaryFile(void);
+ void open(char *FileName);
+ int close(void);
+ void error(char *Text);
+ int getPosition(void);
+ int getSize(void);
+ void seek(int Offset);
+
+ // VIRTUAL FUNCTIONS
+ // =========================================================================
+ // TODO(fusion): `TReadStream` itself doesn't have a destructor on its VTABLE
+ // which makes me think there is something else going on here or the compiler
+ // optimized it away because it was never used but it seems problematic.
+ virtual ~TReadBinaryFile(void) override; // VTABLE[8]
+ // Duplicate destructor that also calls operator delete. // VTABLE[9]
+
+ uint8 readByte(void) override;
+ void readBytes(uint8 *Buffer, int Count) override;
+ bool eof(TReadBinaryFile *this) override;
+ void skip(int Count) override;
+
+ // DATA
+ // =========================================================================
+ FILE *File;
+ char Filename[4096];
+ int FileSize;
+};
+
#endif //TIBIA_SCRIPT_HH_
diff --git a/src/util.cc b/src/util.cc
index 74c1bf5..5cdd933 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -40,3 +40,139 @@ void print(int Level, char *Text, ...){
printf("%s", s);
}
}
+
+// TReadStream
+// =============================================================================
+bool TReadStream::readFlag(void){
+ return this->readByte() != 0;
+}
+
+uint16 TReadStream::readWord(void){
+ // NOTE(fusion): Data is encoded in little endian.
+ uint8 Byte0 = this->readByte();
+ uint8 Byte1 = this->readByte();
+ return ((uint16)Byte1 << 8) | (uint16)Byte0;
+}
+
+uint32 TReadStream::readQuad(void){
+ // NOTE(fusion): Data is encoded in little endian.
+ uint8 Byte0 = this->readByte();
+ uint8 Byte1 = this->readByte();
+ uint8 Byte2 = this->readByte();
+ uint8 Byte3 = this->readByte();
+ return ((uint32)Byte3 << 24) | ((uint32)Byte2 << 16)
+ | ((uint32)Byte1 << 8) | (uint32)Byte0;
+}
+
+void TReadStream::readString(char *Buffer, int MaxLength){
+ if(Buffer == NULL || MaxLength == 0){
+ error("TReadStream::readString: Übergebener Puffer existiert nicht.\n");
+ throw "internal error";
+ }
+
+ int Length = (int)this->readWord();
+ if(Length == 0xFFFF){
+ Length = (int)this->readQuad();
+ }
+
+ if(Length > 0){
+ if(MaxLength < 0 || MaxLength > Length){
+ this->readBytes(Buffer, Length);
+ Buffer[Length] = 0;
+ }else{
+ this->readBytes(Buffer, MaxLength - 1);
+ this->skip(Length - MaxLength + 1);
+ Buffer[MaxLength - 1] = 0;
+ }
+ }else{
+ Buffer[0] = 0;
+ }
+}
+
+void TReadStream::readBytes(uint8 *Buffer, int Count){
+ if(Buffer == NULL){
+ error("TReadStream::readBytes: Übergebener Puffer existiert nicht.\n");
+ throw "internal error";
+ }
+
+ for(int i = 0; i < Count; i += 1){
+ Buffer[i] = this->readByte();
+ }
+}
+
+// TReadBuffer
+// =============================================================================
+TReadBuffer::TReadBuffer(uint8 *Data, int Size){
+ if(Data == NULL){
+ error("TReadBuffer::TReadBuffer: data ist NULL.\n");
+ Size = 0;
+ }else if(Size < 0){
+ error("TReadBuffer::TReadBuffer: Ungültige Datengröße %d.\n", Size);
+ Size = 0;
+ }
+
+ this->Data = Data;
+ this->Size = Size;
+ this->Position = 0;
+}
+
+uint8 TReadBuffer::readByte(void){
+ if((this->Size - this->Position) < 1){
+ throw "buffer empty";
+ }
+
+ uint8 Byte = this->Data[this->Position];
+ this->Position += 1;
+ return Byte;
+}
+
+uint16 TReadBuffer::readWord(void){
+ if((this->Size - this->Position) < 2){
+ throw "buffer empty";
+ }
+
+ uint8 Byte0 = this->Data[this->Position];
+ uint8 Byte1 = this->Data[this->Position + 1];
+ this->Position += 2;
+ return ((uint16)Byte1 << 8) | (uint16)Byte0;
+}
+
+uint32 TReadBuffer::readQuad(void){
+ if((this->Size - this->Position) < 4){
+ throw "buffer empty";
+ }
+
+ uint8 Byte0 = this->Data[this->Position];
+ uint8 Byte1 = this->Data[this->Position + 1];
+ uint8 Byte2 = this->Data[this->Position + 2];
+ uint8 Byte3 = this->Data[this->Position + 3];
+ this->Position += 4;
+ return ((uint32)Byte3 << 24) | ((uint32)Byte2 << 16)
+ | ((uint32)Byte1 << 8) | (uint32)Byte0;
+}
+
+void TReadBuffer::readBytes(uint8 *Buffer, int Count){
+ if(Buffer == NULL || Count <= 0){
+ error("TReadBuffer::readBytes: Übergebener Puffer existiert nicht.\n");
+ throw "buffer not existing";
+ }
+
+ if((this->Size - this->Position) < Count){
+ throw "buffer empty";
+ }
+
+ memcpy(Buffer, &this->Data[this->Position], Count);
+ this->Position += Count;
+}
+
+bool TReadBuffer::eof(void){
+ return this->Size <= this->Position;
+}
+
+void TReadBuffer::skip(int Count){
+ if((this->Size - this->Position) < Count){
+ throw "buffer empty";
+ }
+
+ this->Position += Count;
+}