implement TWriteScriptFile

This commit is contained in:
fusion32 2025-05-22 11:40:04 -03:00
parent de848a4131
commit 297e8450d8
4 changed files with 193 additions and 393 deletions

View File

@ -1,6 +1,8 @@
## TODO NEXT
- TReadScript / TWriteScript
- THREADS
- TReadStream/TWriteStream
- TReadBuffer/TWriteBuffer
- TReadBinaryFile/TWriteBinaryFile
- TCreature
- TPlayer
- TNonPlayer

View File

@ -3594,391 +3594,6 @@ LAB_0804eb1e:
return;
}
// DWARF original prototype: void TWriteScriptFile(TWriteScriptFile * this)
void __thiscall TWriteScriptFile::TWriteScriptFile(TWriteScriptFile *this)
{
this->File = (FILE *)0x0;
return;
}
// DWARF original prototype: void TWriteScriptFile(TWriteScriptFile * this)
void __thiscall TWriteScriptFile::TWriteScriptFile(TWriteScriptFile *this)
{
this->File = (FILE *)0x0;
return;
}
// DWARF original prototype: void ~TWriteScriptFile(TWriteScriptFile * this, int __in_chrg)
void __thiscall TWriteScriptFile::~TWriteScriptFile(TWriteScriptFile *this,int __in_chrg)
{
char *pcVar1;
int iVar2;
int *piVar3;
if (this->File != (FILE *)0x0) {
pcVar1 = "";
if (this != (TWriteScriptFile *)0xfffffffc) {
pcVar1 = this->Filename;
}
::error("TWriteScriptFile::~TWriteScriptFile: Datei %s ist noch offen.\n",pcVar1);
iVar2 = fclose((FILE *)this->File);
if (iVar2 != 0) {
piVar3 = __errno_location();
::error(&DAT_080ef6e0,*piVar3);
}
}
return;
}
// DWARF original prototype: void ~TWriteScriptFile(TWriteScriptFile * this, int __in_chrg)
void __thiscall TWriteScriptFile::~TWriteScriptFile(TWriteScriptFile *this,int __in_chrg)
{
char *pcVar1;
int iVar2;
int *piVar3;
if (this->File != (FILE *)0x0) {
pcVar1 = "";
if (this != (TWriteScriptFile *)0xfffffffc) {
pcVar1 = this->Filename;
}
::error("TWriteScriptFile::~TWriteScriptFile: Datei %s ist noch offen.\n",pcVar1);
iVar2 = fclose((FILE *)this->File);
if (iVar2 != 0) {
piVar3 = __errno_location();
::error(&DAT_080ef6e0,*piVar3);
}
}
return;
}
// DWARF original prototype: void open(TWriteScriptFile * this, char * FileName)
int __thiscall TWriteScriptFile::open(TWriteScriptFile *this,char *__file,int __oflag,...)
{
FILE *pFVar1;
char *pcVar2;
int *piVar3;
undefined4 *puVar4;
int iVar5;
if (this->File != (FILE *)0x0) {
::error("TWriteScriptFile::open: Altes Skript ist noch offen.\n");
iVar5 = fclose((FILE *)this->File);
if (iVar5 != 0) {
piVar3 = __errno_location();
::error(&DAT_080ef7c0,*piVar3);
}
this->File = (FILE *)0x0;
}
pFVar1 = fopen(__file,"wb");
this->File = (FILE *)pFVar1;
if (pFVar1 != (FILE *)0x0) {
this->Line = 0;
pcVar2 = strcpy(this->Filename,__file);
return (int)pcVar2;
}
piVar3 = __errno_location();
iVar5 = *piVar3;
// try { // try from 08050063 to 080500eb has its CatchHandler @ 080500f0
::error("TWriteScriptFile: Kann Datei %s nicht anlegen.\n",__file);
pcVar2 = strerror(iVar5);
::error("Fehler %d: %s.\n",iVar5,pcVar2);
puVar4 = (undefined4 *)__cxa_allocate_exception(4);
*puVar4 = "Cannot create script-file";
// WARNING: Subroutine does not return
__cxa_throw(puVar4,char_const*::typeinfo,0);
}
// DWARF original prototype: void close(TWriteScriptFile * this)
int __thiscall TWriteScriptFile::close(TWriteScriptFile *this,int __fd)
{
int iVar1;
int *piVar2;
FILE *__stream;
__stream = (FILE *)this->File;
if (__stream != (FILE *)0x0) {
iVar1 = fclose(__stream);
if (iVar1 != 0) {
piVar2 = __errno_location();
iVar1 = *piVar2;
::error(&DAT_080ef800,iVar1);
}
this->File = (FILE *)0x0;
return iVar1;
}
::error("TWriteScriptFile::close: Kein Skript offen.\n");
return (int)__stream;
}
// DWARF original prototype: void error(TWriteScriptFile * this, char * Text)
void __thiscall TWriteScriptFile::error(TWriteScriptFile *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 080501b0 to 08050223 has its CatchHandler @ 08050224
::error(&DAT_080ef880,*piVar2);
}
}
this->File = (FILE *)0x0;
snprintf(ErrorString,100,"error in script-file \"%s\", line %d: %s",this->Filename,this->Line,
Text);
puVar3 = (undefined4 *)__cxa_allocate_exception(4);
*puVar3 = ErrorString;
// WARNING: Subroutine does not return
__cxa_throw(puVar3,char*::typeinfo,0);
}
// DWARF original prototype: void writeLn(TWriteScriptFile * this)
void __thiscall TWriteScriptFile::writeLn(TWriteScriptFile *this)
{
undefined4 *puVar1;
if ((FILE *)this->File != (FILE *)0x0) {
putc(10,(FILE *)this->File);
return;
}
// try { // try from 0805026a to 08050298 has its CatchHandler @ 08050299
::error(&DAT_080ef8c0);
puVar1 = (undefined4 *)__cxa_allocate_exception(4);
*puVar1 = "Cannot write linefeed";
// WARNING: Subroutine does not return
__cxa_throw(puVar1,char_const*::typeinfo,0);
}
// DWARF original prototype: void writeText(TWriteScriptFile * this, char * Text)
void __thiscall TWriteScriptFile::writeText(TWriteScriptFile *this,char *Text)
{
char cVar1;
undefined4 *puVar2;
FILE *__stream;
char *Text_00;
__stream = (FILE *)this->File;
if (__stream == (FILE *)0x0) {
Text_00 = &DAT_080ef940;
}
else {
if (Text != (char *)0x0) {
cVar1 = *Text;
if (cVar1 != '\0') {
while( true ) {
Text = Text + 1;
putc((int)cVar1,__stream);
cVar1 = *Text;
if (cVar1 == '\0') break;
__stream = (FILE *)this->File;
}
}
return;
}
Text_00 = "TWriteScriptFile::writeText: Text ist NULL.\n";
}
// try { // try from 080502fe to 0805032c has its CatchHandler @ 08050336
::error(Text_00);
puVar2 = (undefined4 *)__cxa_allocate_exception(4);
*puVar2 = "Cannot write text";
// WARNING: Subroutine does not return
__cxa_throw(puVar2,char_const*::typeinfo,0);
}
// DWARF original prototype: void writeString(TWriteScriptFile * this, char * Text)
void __thiscall TWriteScriptFile::writeString(TWriteScriptFile *this,char *Text)
{
undefined4 *puVar1;
char cVar2;
char *Text_00;
if ((FILE *)this->File == (FILE *)0x0) {
Text_00 = &DAT_080ef9e0;
}
else {
if (Text != (char *)0x0) {
putc(0x22,(FILE *)this->File);
cVar2 = *Text;
while (cVar2 != '\0') {
if ((cVar2 == '\"') || (cVar2 == '\\')) {
putc(0x5c,(FILE *)this->File);
cVar2 = *Text;
}
if (cVar2 == '\n') {
putc(0x5c,(FILE *)this->File);
putc(0x6e,(FILE *)this->File);
}
else {
putc((int)cVar2,(FILE *)this->File);
}
Text = Text + 1;
cVar2 = *Text;
}
putc(0x22,(FILE *)this->File);
return;
}
Text_00 = "TWriteScriptFile::writeString: Text ist NULL.\n";
}
// try { // try from 08050416 to 08050444 has its CatchHandler @ 0805044e
::error(Text_00);
puVar1 = (undefined4 *)__cxa_allocate_exception(4);
*puVar1 = "Cannot write string";
// WARNING: Subroutine does not return
__cxa_throw(puVar1,char_const*::typeinfo,0);
}
// DWARF original prototype: void writeNumber(TWriteScriptFile * this, int Number)
void __thiscall TWriteScriptFile::writeNumber(TWriteScriptFile *this,int Number)
{
undefined4 *puVar1;
char local_2c [4];
char s [20];
if (this->File != (FILE *)0x0) {
sprintf(local_2c,"%d",Number);
// try { // try from 080504a6 to 080504ea has its CatchHandler @ 080504f0
writeText(this,local_2c);
return;
}
::error(&DAT_080efa40);
puVar1 = (undefined4 *)__cxa_allocate_exception(4);
*puVar1 = "Cannot write number";
// WARNING: Subroutine does not return
__cxa_throw(puVar1,char_const*::typeinfo,0);
}
// DWARF original prototype: void writeBytesequence(TWriteScriptFile * this, uchar * Sequence, int
// Length)
void __thiscall
TWriteScriptFile::writeBytesequence(TWriteScriptFile *this,uchar *Sequence,int Length)
{
undefined4 *puVar1;
int i;
int iVar2;
char *Text;
char local_3c [4];
char s [20];
if (this->File == (FILE *)0x0) {
Text = &DAT_080efb20;
}
else if (Sequence == (uchar *)0x0) {
Text = "TWriteScriptFile::writeBytesequence: Sequence ist NULL.\n";
}
else {
if (0 < Length) {
iVar2 = 0;
if (0 < Length) {
do {
if (iVar2 != 0) {
// try { // try from 080505de to 0805061d has its CatchHandler @ 08050648
writeText(this,"-");
}
if (this->File == (FILE *)0x0) {
::error(&DAT_080efa40);
puVar1 = (undefined4 *)__cxa_allocate_exception(4);
*puVar1 = "Cannot write number";
// WARNING: Subroutine does not return
__cxa_throw(puVar1,char_const*::typeinfo,0);
}
sprintf(local_3c,"%d",(uint)Sequence[iVar2]);
// try { // try from 0805057c to 080505d2 has its CatchHandler @ 08050630
writeText(this,local_3c);
iVar2 = iVar2 + 1;
} while (iVar2 < Length);
}
return;
}
Text = &DAT_080efaa0;
}
::error(Text);
puVar1 = (undefined4 *)__cxa_allocate_exception(4);
*puVar1 = "Cannot write bytesequence";
// WARNING: Subroutine does not return
__cxa_throw(puVar1,char_const*::typeinfo,0);
}
// DWARF original prototype: void writeCoordinate(TWriteScriptFile * this, int x, int y, int z)
void __thiscall TWriteScriptFile::writeCoordinate(TWriteScriptFile *this,int x,int y,int z)
{
undefined4 *puVar1;
char local_2c [4];
char s [20];
if (this->File == (FILE *)0x0) {
::error(&DAT_080efbe0);
puVar1 = (undefined4 *)__cxa_allocate_exception(4);
*puVar1 = "Cannot write coordinate";
}
else {
if (((-1 < x) && (-1 < y)) && (-1 < z)) {
sprintf(local_2c,"[%u,%u,%u]",x,y,z);
// try { // try from 080506b4 to 08050710 has its CatchHandler @ 08050725
writeText(this,local_2c);
return;
}
::error(&DAT_080efb80,x,y,z);
puVar1 = (undefined4 *)__cxa_allocate_exception(4);
*puVar1 = "Invalid coordinates";
}
// WARNING: Subroutine does not return
__cxa_throw(puVar1,char_const*::typeinfo,0);
}
// DWARF original prototype: void TReadBinaryFile(TReadBinaryFile * this)

View File

@ -1,6 +1,15 @@
#include "script.hh"
// =============================================================================
// NOTE(fusion): Throwing a character array on the stack as an exception won't
// work because it implicitly decays into a character pointer which would then
// point to invalid data when actually parsed. It is the reason `ErrorString` is
// declared statically, or else you'd need to throw some heap allocated string
// which then becomes ambiguous whether you should free it or not. Used in:
// - TReadScriptFile::error
// - TWriteScriptFile::error
static char ErrorString[100];
// Helper Functions
// =============================================================================
// TODO(fusion): Move to `util.cc`?
@ -104,9 +113,8 @@ static char *findLast(char *s, char c){
return Last;
}
// =============================================================================
// =============================================================================
// TWriteScriptFile
//==============================================================================
TReadScriptFile::TReadScriptFile(void){
this->RecursionDepth = -1;
this->Bytes = (uint8*)this->String;
@ -172,8 +180,6 @@ void TReadScriptFile::close(void){
}
void TReadScriptFile::error(const char *Text){
static char ErrorString[100];
int Depth = this->RecursionDepth;
ASSERT(Depth >= 0 && Depth <= NARRAY(this->File));
@ -615,3 +621,170 @@ int main(int argc, char **argv){
return EXIT_FAILURE;
}
// TWriteScriptFile
//==============================================================================
TWriteScriptFile::TWriteScriptFile(void){
this->File = NULL;
}
TWriteScriptFile::~TWriteScriptFile(void){
if(this->File != NULL){
::error("TWriteScriptFile::~TWriteScriptFile: Datei %s ist noch offen.\n", this->Filename);
if(fclose(this->File) != 0){
::error("TWriteScriptFile::~TWriteScriptFile: Fehler %d beim Schließen der Datei.\n", errno);
}
}
}
void TWriteScriptFile::open(char *FileName){
if(this->File != NULL){
::error("TWriteScriptFile::open: Altes Skript ist noch offen.\n");
if(fclose(this->File) != 0){
::error("TWriteScriptFile::open: Fehler %d beim Schließen der Datei.\n", errno);
}
this->File = NULL;
}
this->File = fopen(FileName, "wb");
if(this->File == NULL){
::error("TWriteScriptFile: Kann Datei %s nicht anlegen.\n", FileName);
::error("Fehler %d: %s.\n", errno, strerror(errno));
throw "Cannot create script-file";
}
strcpy(this->Filename, FileName);
this->Line = 0;
}
void TWriteScriptFile::close(void){
if(this->File == NULL){
::error("TWriteScriptFile::close: Kein Skript offen.\n");
return;
}
if(fclose(this->File) != 0){
::error("TWriteScriptFile::close: Fehler %d beim Schließen der Datei.\n", errno);
}
this->File = NULL;
}
void TWriteScriptFile::error(char *Text){
if(this->File != NULL){
if(fclose(this->File) != 0){
::error("TWriteScriptFile::error: Fehler %d beim Schließen der Datei.\n", errno);
}
this->File = NULL;
}
snprintf(ErrorString, sizeof(ErrorString),
"error in script-file \"%s\", line %d: %s",
this->Filename, this->Line);
throw ErrorString;
}
void TWriteScriptFile::writeLn(void){
if(this->File == NULL){
::error("TWriteScriptFile::writeLn: Kein Skript zum Schreiben geöffnet.\n");
throw "Cannot write linefeed";
}
putc('\n', this->File);
}
void TWriteScriptFile::writeText(char *Text){
if(this->File == NULL){
::error("TWriteScriptFile::writeText: Kein Skript zum Schreiben geöffnet.\n");
throw "Cannot write text";
}
if(Text == NULL){
::error("TWriteScriptFile::writeText: Text ist NULL.\n");
throw "Cannot write text";
}
for(int i = 0; Text[i] != 0; i += 1){
putc(Text[i], this->File);
}
}
void TWriteScriptFile::writeNumber(int Number){
if(this->File == NULL){
::error("TWriteScriptFile::writeNumber: Kein Skript zum Schreiben geöffnet.\n");
throw "Cannot write number";
}
char s[32];
snprintf(s, sizeof(s), "%d", Number);
this->writeText(s);
}
void TWriteScriptFile::writeString(char *Text){
if(this->File == NULL){
::error();
throw "Cannot write string";
}
if(Text == NULL){
::error("TWriteScriptFile::writeString: Text ist NULL.\n");
throw "Cannot write string";
}
putc('"', this->File);
for(int i = 0; Text[i] != 0; i += 1){
if(Text[i] == '\"' || Text[i] == '\\'){
putc('\\', this->File);
putc(Text[i], this->File);
}else if(Text[i] == '\n'){
putc('\\', this->File);
putc('n', this->File);
}else{
putc(Text[i], this->File);
}
}
putc('"', this->File);
}
void TWriteScriptFile::writeCoordinate(int x ,int y ,int z){
if(this->File == NULL){
::error("TWriteScriptFile::writeCoordinate: Kein Skript zum Schreiben geöffnet.\n");
throw "Cannot write coordinate";
}
// TODO(fusion): This is weird because we support loading negative coordinates values.
if(x < 0 || y < 0 || z < 0){
::error("TWriteScriptFile::writeCoordinate: Ungültige Koordinaten [%d,%d,%d].\n", x, y, z);
throw "Invalid coordinates";
}
char s[64];
snprintf(s, sizeof(s), "[%u,%u,%u]", x, y, z);
this->writeText(s);
}
void TWriteScriptFile::writeBytesequence(uint8 *Sequence, int Length){
if(this->File == NULL){
::error("TWriteScriptFile::writeBytesequence: Kein Skript zum Schreiben geöffnet.\n");
throw "Cannot write bytesequence";
}
if(Sequence == NULL){
::error("TWriteScriptFile::writeBytesequence: Sequence ist NULL.\n");
throw "Cannot write bytesequence";
}
if(Length <= 0){
::error("TWriteScriptFile::writeBytesequence: Ungültige Sequenzlänge.\n");
throw "Cannot write bytesequence";
}
for(int i = 0; i < Length; i += 1){
if(i > 0){
putc('-', this->File);
}
snprintf(s, sizeof(s), "%u", Sequence[i]);
this->writeText(s);
}
}

View File

@ -82,7 +82,17 @@ struct TReadScriptFile {
struct TWriteScriptFile {
// REGULAR FUNCTIONS
// =========================================================================
//TWriteScriptFile(void);
TWriteScriptFile(void);
~TWriteScriptFile(void);
void open(char *FileName);
void close(void);
void error(char *Text);
void writeLn(void);
void writeText(char *Text);
void writeNumber(int Number);
void writeString(char *Text);
void writeCoordinate(int x ,int y ,int z);
void writeBytesequence(uint8 *Sequence, int Length);
// DATA
// =========================================================================