aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common.hh50
-rw-r--r--src/script.cc127
-rw-r--r--src/script.hh36
-rw-r--r--src/util.cc174
4 files changed, 369 insertions, 18 deletions
diff --git a/src/common.hh b/src/common.hh
index 204cf2a..124dd84 100644
--- a/src/common.hh
+++ b/src/common.hh
@@ -166,9 +166,59 @@ struct TReadBuffer: TReadStream {
// DATA
// =========================================================================
+ const uint8 *Data;
+ int Size;
+ int Position;
+};
+
+struct TWriteStream {
+ // VIRTUAL FUNCTIONS
+ // =========================================================================
+ virtual void writeFlag(bool Flag); // VTABLE[0]
+ virtual void writeByte(uint8 Byte) = 0; // VTABLE[1]
+ virtual void writeWord(uint16 Word); // VTABLE[2]
+ virtual void writeQuad(uint16 Quad); // VTABLE[3]
+ virtual void writeString(const char *String); // VTABLE[4]
+ virtual void writeBytes(const uint8 *Buffer, int Count); // VTABLE[5]
+};
+
+struct TWriteBuffer: TWriteStream {
+ // REGULAR FUNCTIONS
+ // =========================================================================
+ TWriteBuffer(uint8 *Data, int Size);
+
+ // VIRTUAL FUNCTIONS
+ // =========================================================================
+ void writeByte(uint8 Byte) override;
+ void writeWord(uint16 Word) override;
+ void writeQuad(uint32 Quad) override;
+ void writeBytes(uint8 *Buffer, int Count) override;
+
+ // DATA
+ // =========================================================================
uint8 *Data;
int Size;
int Position;
};
+struct TDynamicWriteBuffer: TWriteBuffer {
+ // REGULAR FUNCTIONS
+ // =========================================================================
+ TDynamicWriteBuffer(int InitialSize);
+ void resizeBuffer(void);
+
+ // VIRTUAL FUNCTIONS
+ // =========================================================================
+ void writeByte(uint8 Byte) override;
+ void writeWord(uint16 Word) override;
+ void writeQuad(uint32 Quad) override;
+ void writeBytes(uint8 *Buffer, int Count) override;
+
+ // TODO(fusion): Appended virtual functions. These are not in the base class
+ // VTABLE which can be problematic if we intend to use polymorphism, although
+ // that doesn't seem to be case.
+ virtual ~TDynamicWriteBuffer(void); // VTABLE[6]
+ // Duplicate destructor that also calls operator delete. // VTABLE[7]
+};
+
#endif //TIBIA_COMMON_HH_
diff --git a/src/script.cc b/src/script.cc
index 9db02f7..009fd86 100644
--- a/src/script.cc
+++ b/src/script.cc
@@ -9,6 +9,8 @@
// - TWriteScriptFile::error
// - TReadBinaryFile::open
// - TReadBinaryFile::error
+// - TWriteBinaryFile::open
+// - TWriteBinaryFile::error
static char ErrorString[100];
// Helper Functions
@@ -158,8 +160,9 @@ void TReadScriptFile::open(const char *FileName){
this->File[Depth] = fopen(this->Filename[Depth], "rb");
if(this->File[Depth] == NULL){
+ int ErrCode = errno;
::error("TReadScriptFile::open: Kann Datei %s nicht öffnen.\n", this->Filename[Depth]);
- ::error("Fehler %d: %s.\n", errno, strerror(errno));
+ ::error("Fehler %d: %s.\n", ErrCode, strerror(ErrCode));
throw "Cannot open script-file";
}
@@ -650,8 +653,9 @@ void TWriteScriptFile::open(char *FileName){
this->File = fopen(FileName, "wb");
if(this->File == NULL){
+ int ErrCode = errno;
::error("TWriteScriptFile: Kann Datei %s nicht anlegen.\n", FileName);
- ::error("Fehler %d: %s.\n", errno, strerror(errno));
+ ::error("Fehler %d: %s.\n", ErrCode, strerror(ErrCode));
throw "Cannot create script-file";
}
@@ -871,15 +875,6 @@ void TReadBinaryFile::seek(int Offset){
// 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);
@@ -894,6 +889,7 @@ uint8 TReadBinaryFile::readByte(void){
if(fclose(this->File) != 0){
::error("TReadBinaryFile::readByte: Fehler %d beim Schließen der Datei.\n", errno);
}
+ this->File = NULL;
SaveFile(this->Filename);
this->error("Error while reading byte");
@@ -914,6 +910,7 @@ void TReadBinaryFile::readBytes(uint8 *Buffer, int Count){
if(fclose(this->File) != 0){
::error("TReadBinaryFile::readBytes: Fehler %d beim Schließen der Datei.\n", errno);
}
+ this->File = NULL;
SaveFile(this->Filename);
this->error("Error while reading bytes");
@@ -935,3 +932,111 @@ void TReadBinaryFile::skip(int Count){
this->seek(this->getPosition() + Count);
}
+
+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);
+ }
+ }
+}
+
+// TWriteBinaryFile
+//==============================================================================
+TWriteBinaryFile::TWriteBinaryFile(void){
+ this->File = NULL;
+}
+
+void TWriteBinaryFile::open(char *FileName){
+ if(this->File != NULL){
+ this->error("File still open");
+ }
+
+ this->File = fopen(FileName, "wb");
+ if(this->File == NULL){
+ int ErrCode = errno;
+ ::error("TWriteBinaryFile::open: Kann Datei %s nicht anlegen.\n", FileName);
+ ::error("Fehler %d: %s.\n", ErrCode, strerror(ErrCode));
+
+ snprintf(ErrorString, sizeof(ErrorString),
+ "Cannot create file %s.", FileName);
+
+ throw ErrorString;
+ }
+
+ strcpy(this->Filename, FileName);
+}
+
+void TWriteBinaryFile::close(void){
+ // TODO(fusion): Check if file is NULL?
+ if(fclose(this->File) != 0){
+ int ErrCode = errno;
+ ::error("TWriteBinaryFile::close: Fehler beim Schließen der Datei.\n");
+ ::error("# Datei: %s, Fehlercode: %d (%s)\n",
+ this->Filename, ErrCode, strerror(ErrCode));
+ }
+ this->File = NULL;
+}
+
+void TWriteBinaryFile::error(char *Text){
+ if(this->File != NULL){
+ if(fclose(this->File) != 0){
+ ::error("TWriteBinaryFile::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;
+}
+
+void TWriteBinaryFile::writeByte(uint8 Byte){
+ int Result = (int)fwrite(&Byte, 1, 1, this->File);
+ if(Result != 1){
+ int ErrCode = errno;
+ ::error("TWriteBinaryFile::writeByte: Fehler beim Schreiben eines Bytes\n");
+ ::error("# Datei: %s, Rückgabewert: %d, Fehlercode: %d (%s)\n",
+ this->Filename, Result, ErrCode, strerror(ErrCode));
+
+ // NOTE(fusion): Close file and make a backup, possibly for further inspection.
+ if(fclose(this->File) != 0){
+ ::error("TWriteBinaryFile::writeByte: Fehler %d beim Schließen der Datei.\n", errno);
+ }
+ this->File = NULL;
+ SaveFile(this->Filename);
+
+ this->error("Error while writing byte");
+ }
+}
+
+void TWriteBinaryFile::writeBytes(uint8 *Buffer, int Count){
+ int Result = (int)fwrite(Buffer, 1, Count, this->File);
+ if(Result != Count){
+ int ErrCode = errno;
+ ::error("TWriteBinaryFile::writeBytes: Fehler beim Schreiben von %d Bytes\n", Count);
+ ::error("# Datei: %s, Rückgabewert: %d, Fehlercode: %d (%s)\n",
+ this->Filename, Result, ErrCode, strerror(ErrCode));
+
+ // NOTE(fusion): Close file and make a backup, possibly for further inspection.
+ if(fclose(this->File) != 0){
+ ::error("TWriteBinaryFile::writeBytes: Fehler %d beim Schließen der Datei.\n", errno);
+ }
+ this->File = NULL;
+ SaveFile(this->Filename);
+
+ this->error("Error while writing bytes");
+ }
+}
+
+TWriteBinaryFile::~TWriteBinaryFile(void){
+ if(this->File != NULL){
+ ::error("TWriteBinaryFile::~TWriteBinaryFile: Datei %s ist noch offen.\n", this->Filename);
+ if(fclose(this->File) != 0){
+ ::error("TWriteBinaryFile::~TWriteBinaryFile: Fehler %d beim Schließen der Datei.\n", errno);
+ }
+ }
+}
diff --git a/src/script.hh b/src/script.hh
index 42ddd2e..16e66fe 100644
--- a/src/script.hh
+++ b/src/script.hh
@@ -114,17 +114,17 @@ struct TReadBinaryFile: TReadStream {
// 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;
+ // TODO(fusion): Appended virtual functions. These are not in the base class
+ // VTABLE which can be problematic if we intend to use polymorphism, although
+ // that doesn't seem to be case.
+ virtual ~TReadBinaryFile(void) override; // VTABLE[8]
+ // Duplicate destructor that also calls operator delete. // VTABLE[9]
+
// DATA
// =========================================================================
FILE *File;
@@ -132,4 +132,28 @@ struct TReadBinaryFile: TReadStream {
int FileSize;
};
+struct TWriteBinaryFile: TWriteStream {
+ // REGULAR FUNCTIONS
+ // =========================================================================
+ TWriteBinaryFile(void);
+ void open(char *FileName);
+ void close(void);
+ void error(char *Text);
+
+ // VIRTUAL FUNCTIONS
+ // =========================================================================
+ void writeByte(uint8 Byte) override;
+ void writeBytes(uint8 *Buffer, int Count) override;
+
+ // TODO(fusion): Appended virtual functions. These are not in the base class
+ // VTABLE which can be problematic if we intend to use polymorphism, although
+ // that doesn't seem to be case.
+ virtual ~TWriteBinaryFile(void);
+
+ // DATA
+ // =========================================================================
+ FILE *File;
+ char Filename[4096];
+};
+
#endif //TIBIA_SCRIPT_HH_
diff --git a/src/util.cc b/src/util.cc
index 5cdd933..30e1ba5 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -80,7 +80,7 @@ void TReadStream::readString(char *Buffer, int MaxLength){
this->readBytes(Buffer, Length);
Buffer[Length] = 0;
}else{
- this->readBytes(Buffer, MaxLength - 1);
+ this->readBytes((uint8*)Buffer, MaxLength - 1);
this->skip(Length - MaxLength + 1);
Buffer[MaxLength - 1] = 0;
}
@@ -176,3 +176,175 @@ void TReadBuffer::skip(int Count){
this->Position += Count;
}
+
+// TWriteStream
+// =============================================================================
+void TWriteStream::writeFlag(bool Flag){
+ this->writeByte((uint8)Flag);
+}
+
+void TWriteStream::writeWord(uint16 Word){
+ this->writeByte((uint8)(Word));
+ this->writeByte((uint8)(Word >> 8));
+}
+
+void TWriteStream::writeQuad(uint32 Quad){
+ this->writeByte((uint8)(Quad));
+ this->writeByte((uint8)(Quad >> 8));
+ this->writeByte((uint8)(Quad >> 16));
+ this->writeByte((uint8)(Quad >> 24));
+}
+
+void TWriteStream::writeString(const char *String){
+ if(String == NULL){
+ this->writeWord(0);
+ return;
+ }
+
+ int StringLength = (int)strlen(String);
+ ASSERT(StringLength >= 0);
+ if(StringLength < 0xFFFF){
+ this->writeWord((uint16)StringLength);
+ }else{
+ this->writeWord(0xFFFF);
+ this->writeQuad((uint32)StringLength);
+ }
+
+ if(StringLength > 0){
+ this->writeBytes((const uint8*)String, StringLength);
+ }
+}
+
+void TWriteStream::writeBytes(const uint8 *Buffer, int Count){
+ if(Buffer == NULL){
+ error("TWriteStream::writeBytes: Übergebener Puffer existiert nicht.\n");
+ throw "internal error";
+ }
+
+ for(int i = 0; i < Count; i += 1){
+ this->writeByte(Buffer[i]);
+ }
+}
+
+// TWriteBuffer
+// =============================================================================
+TWriteBuffer::TWriteBuffer(uint8 *Data, int Size){
+ if(Data == NULL){
+ error("TWriteBuffer::TWriteBuffer: data ist NULL.\n");
+ Size = 0;
+ }else if(Size < 0){
+ error("TWriteBuffer::TWriteBuffer: Ungültige Datengröße %d.\n", Size);
+ Size = 0;
+ }
+
+ this->Data = Data;
+ this->Size = Size;
+ this->Position = 0;
+}
+
+void TWriteBuffer::writeByte(uint8 Byte){
+ if((this->Size - this->Position) < 1){
+ throw "buffer full";
+ }
+
+ this->Data[this->Position] = Byte;
+ this->Position += 1;
+}
+
+void TWriteBuffer::writeWord(uint16 Word){
+ if((this->Size - this->Position) < 2){
+ throw "buffer full";
+ }
+
+ this->Data[this->Position] = (uint8)(Word);
+ this->Data[this->Position + 1] = (uint8)(Word >> 8);
+ this->Position += 2;
+}
+
+void TWriteBuffer::writeQuad(uint32 Quad){
+ if((this->Size - this->Position) < 4){
+ throw "buffer full";
+ }
+
+ this->Data[this->Position] = (uint8)(Quad);
+ this->Data[this->Position + 1] = (uint8)(Quad >> 8);
+ this->Data[this->Position + 2] = (uint8)(Quad >> 16);
+ this->Data[this->Position + 3] = (uint8)(Quad >> 24);
+ this->Position += 4;
+}
+
+void TWriteBuffer::writeBytes(uint8 *Buffer, int Count){
+ if((this->Size - this->Position) < Count){
+ throw "buffer full";
+ }
+
+ memcpy(&this->Data[this->Position], Buffer, Count);
+ this->Position += Count;
+}
+
+// TDynamicWriteBuffer
+// =============================================================================
+TDynamicWriteBuffer::TDynamicWriteBuffer(int InitialSize)
+ : TWriteBuffer(new uint8[InitialSize], InitialSize)
+{
+ // no-op
+}
+
+void TDynamicWriteBuffer::resizeBuffer(void){
+ ASSERT(this->Size > 0);
+ int Size = this->Size * 2;
+ uint8 *Data = new uint8[Size];
+ if(this->Data != NULL){
+ memcpy(Data, this->Data, this->Size);
+ delete[] this->Data;
+ }
+
+ this->Data = Data;
+ this->Size = Size;
+}
+
+void TDynamicWriteBuffer::writeByte(uint8 Byte){
+ while((this->Size - this->Position) < 1){
+ this->resizeBuffer();
+ }
+
+ this->Data[this->Position] = Byte;
+ this->Position += 1;
+}
+
+void TDynamicWriteBuffer::writeWord(uint16 Word){
+ while((this->Size - this->Position) < 2){
+ this->resizeBuffer();
+ }
+
+ this->Data[this->Position] = (uint8)(Word);
+ this->Data[this->Position + 1] = (uint8)(Word >> 8);
+ this->Position += 2;
+}
+
+void TDynamicWriteBuffer::writeQuad(uint32 Quad){
+ while((this->Size - this->Position) < 4){
+ this->resizeBuffer();
+ }
+
+ this->Data[this->Position] = (uint8)(Quad);
+ this->Data[this->Position + 1] = (uint8)(Quad >> 8);
+ this->Data[this->Position + 2] = (uint8)(Quad >> 16);
+ this->Data[this->Position + 3] = (uint8)(Quad >> 24);
+ this->Position += 4;
+}
+
+void TDynamicWriteBuffer::writeBytes(uint8 *Buffer, int Count){
+ while((this->Size - this->Position) < Count){
+ this->resizeBuffer();
+ }
+
+ memcpy(&this->Data[this->Position], Buffer, Count);
+ this->Position += Count;
+}
+
+TDynamicWriteBuffer::~TDynamicWriteBuffer(void){
+ if(this->Data != NULL){
+ delete[] this->Data;
+ }
+}