Skip to content

Commit

Permalink
refactor(zscript): separate zasm code from script data
Browse files Browse the repository at this point in the history
  • Loading branch information
connorjclark committed May 6, 2024
1 parent 19edaac commit 75f981f
Show file tree
Hide file tree
Showing 26 changed files with 246 additions and 389 deletions.
145 changes: 34 additions & 111 deletions src/base/zdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1941,131 +1941,54 @@ struct script_id {
int index;
};

struct script_data
typedef uint16_t zasm_script_id;

struct zasm_script
{
ffscript* zasm;
zasm_meta meta;
script_id id;
size_t size;
zasm_script() = default;
zasm_script(zasm_script_id id, std::string name, std::vector<ffscript>&& zasm) : id(id), optimized(false), name(name), size(zasm.size()), zasm(std::exchange(zasm, {})) {}
zasm_script(std::vector<ffscript>&& zasm) : id(0), optimized(false), name(""), size(zasm.size()), zasm(std::exchange(zasm, {})) {}

zasm_script_id id;
bool optimized;

void null_script(size_t newSize = 1)
{
if (newSize < 1)
newSize = 1;
if(zasm)
delete[] zasm;
zasm = new ffscript[newSize];
zasm[0].clear();
meta.zero();
size = newSize;
optimized = false;
}

std::string name;
size_t size;
std::vector<ffscript> zasm;

// TODO: remove the necessity of this terminal command being here.
bool valid() const
{
return (zasm && zasm[0].command != 0xFFFF);
}

void disable()
{
if(zasm)
{
zasm[0].clear();
size = 1;
optimized = false;
}
return !zasm.empty() && zasm[0] != 0xFFFF;
}

void recalc_size()
{
if(zasm)
{
for(uint32_t q = 0;;++q)
{
if(zasm[q].command == 0xFFFF)
{
size = q+1;
return;
}
}
}
};

size = 0;
}

void set(script_data const& other)
{
if(zasm)
delete[] zasm;
if(other.size)
{
zasm = new ffscript[other.size];
for(size_t q = 0; q < other.size; ++q)
{
other.zasm[q].copy(zasm[q]);
}
size = other.size;
optimized = other.optimized;
}
else
{
zasm = NULL;
null_script();
}
meta = other.meta;
}
struct script_data
{
// The zasm instructions used by this script.
// In quests before 3.0, each script had its own chunk of zasm.
// Since 3.0 all scripts share the same chunk.
std::shared_ptr<zasm_script> zasm_script = nullptr;
zasm_meta meta;
script_id id;

script_data(ScriptType type, int index) : zasm(NULL)
{
id = {type, index};
null_script();
}

script_data(script_data const& other) : zasm(NULL)
{
set(other);
}

~script_data()
{
if(zasm)
delete[] zasm;
}

void transfer(script_data& other)
{
other.meta = meta;
if(other.zasm)
delete[] other.zasm;
other.zasm = zasm;
other.size = size;
other.optimized = optimized;
zasm = NULL;
null_script();
}

script_data& operator=(script_data const& other)
script_data(ScriptType type, int index) : id({type, index}) {}

std::string name() const
{
set(other);
return *this;
if (meta.script_name.empty())
return fmt::format("{}-{}", ScriptTypeToString(id.type), id.index);
else
return fmt::format("{}-{}-{}", ScriptTypeToString(id.type), id.index, meta.script_name);
}

bool equal_zasm(script_data const& other) const
bool valid() const
{
if(size != other.size) return false;
if(valid() != other.valid()) return false;
for(auto q = 0; q < size; ++q)
{
if(zasm[q] != other.zasm[q]) return false;
}
return true;
return zasm_script && zasm_script->valid();
}

bool operator==(script_data const& other) const
void disable()
{
if(meta != other.meta) return false;
return equal_zasm(other);
zasm_script = nullptr;
}
};

Expand Down
6 changes: 3 additions & 3 deletions src/dialog/compilezscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ bool do_compile_and_slots(int assign_mode, bool delay)
fclose(tempfile);

script_data old_init_script(*globalscripts[0]);
uint32_t lastInitSize = old_init_script.size;
uint32_t lastInitSize = old_init_script.zasm_script->size;
map<string, ZScript::ScriptTypeID> stypes;
map<string, disassembled_script_data> scripts;

Expand Down Expand Up @@ -417,10 +417,10 @@ bool do_compile_and_slots(int assign_mode, bool delay)
if(WarnOnInitChanged && noquick_compile)
{
script_data const& new_init_script = *globalscripts[0];
if(new_init_script != old_init_script) //Global init changed
if(new_init_script.zasm_script->zasm != old_init_script.zasm_script->zasm) //Global init changed
{
AlertFuncDialog("Init Script Changed",
"Either global variables, or your global script Init, have changed. ("+to_string(lastInitSize)+"->"+to_string(new_init_script.size)+")\n\n"
"Either global variables, or your global script Init, have changed. ("+to_string(lastInitSize)+"->"+to_string(new_init_script.zasm_script->size)+")\n\n"
"This can break existing save files of your quest. To prevent users "
"from loading save files that would break, you can raise the \"Quest "
"Ver\" and \"Min. Ver\" in the Header menu (Quest>>Options>>Header)\n\n"
Expand Down
107 changes: 53 additions & 54 deletions src/qst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "base/combo.h"
#include "base/msgstr.h"
#include <filesystem>
#include <memory>
#include <optional>
#include <stdio.h>
#include <cstring>
Expand All @@ -32,6 +33,7 @@
#include "defdata.h"
#include "subscr.h"
#include "zc/replay.h"
#include "zc/zasm_utils.h"
#include "zc/zc_custom.h"
#include "sfx.h"
#include "md5.h"
Expand Down Expand Up @@ -11895,6 +11897,8 @@ int32_t setupsubscreens()
return 0;
}

extern std::vector<std::shared_ptr<zasm_script>> zasm_scripts;

extern script_data *ffscripts[NUMSCRIPTFFC];
extern script_data *itemscripts[NUMSCRIPTITEM];
extern script_data *guyscripts[NUMSCRIPTGUYS];
Expand All @@ -11919,6 +11923,7 @@ int32_t readffscript(PACKFILE *f, zquestheader *Header)
numscripts=numscripts; //to avoid unused variables warnings
int32_t ret;
read_scripts.clear();
zasm_scripts.clear();

//section version info
if(!p_igetw(&s_version,f))
Expand Down Expand Up @@ -12734,7 +12739,6 @@ int32_t read_one_ffscript(PACKFILE *f, zquestheader *, int32_t script_index, wor
//Please also update loadquest() when modifying this method -DD
char b33[34] = {0};
b33[33] = 0;
ffscript temp_script;
int32_t num_commands=1000;

if(s_version>=2)
Expand All @@ -12754,8 +12758,9 @@ int32_t read_one_ffscript(PACKFILE *f, zquestheader *, int32_t script_index, wor
{
return qe_invalid;
}

(*script)->null_script(num_commands);

std::vector<ffscript> zasm;
zasm.reserve(num_commands);

if(s_version >= 16)
{
Expand Down Expand Up @@ -12918,90 +12923,84 @@ int32_t read_one_ffscript(PACKFILE *f, zquestheader *, int32_t script_index, wor
(*script)->meta = temp_meta;
}

temp_script.clear();
for(int32_t j=0; j<num_commands; j++)
{
if(!p_igetw(&(temp_script.command),f))
auto& sc = zasm.emplace_back();
if(!p_igetw(&sc.command,f))
{
return qe_invalid;
}

if(temp_script.command == 0xFFFF)
if(sc.command == 0xFFFF)
{
(*script)->zasm[j].clear();
break;
}
else

if(!p_igetl(&sc.arg1,f))
{
if(!p_igetl(&(temp_script.arg1),f))
{
return qe_invalid;
}

if(!p_igetl(&sc.arg2,f))
{
return qe_invalid;
}

if(s_version >= 24)
if(!p_igetl(&sc.arg3,f))
return qe_invalid;
}

if(!p_igetl(&(temp_script.arg2),f))

if(s_version >= 21)
{
uint32_t sz = 0;
if(!p_igetl(&sz,f))
{
return qe_invalid;
}

if(s_version >= 24)
if(!p_igetl(&(temp_script.arg3),f))
return qe_invalid;

if(s_version >= 21)
if(sz) //string found
{
uint32_t sz = 0;
if(!p_igetl(&sz,f))
sc.strptr = new std::string();
char dummy;
for(size_t q = 0; q < sz; ++q)
{
return qe_invalid;
}
if(sz) //string found
{
temp_script.strptr = new std::string();
char dummy;
for(size_t q = 0; q < sz; ++q)
if(!p_getc(&dummy,f))
{
if(!p_getc(&dummy,f))
{
return qe_invalid;
}
temp_script.strptr->push_back(dummy);
return qe_invalid;
}
sc.strptr->push_back(dummy);
}
if(!p_igetl(&sz,f))
{
return qe_invalid;
}
if(sz) //vector found
}
if(!p_igetl(&sz,f))
{
return qe_invalid;
}
if(sz) //vector found
{
sc.vecptr = new std::vector<int32_t>();
int32_t dummy;
for(size_t q = 0; q < sz; ++q)
{
temp_script.vecptr = new std::vector<int32_t>();
int32_t dummy;
for(size_t q = 0; q < sz; ++q)
if(!p_igetl(&dummy,f))
{
if(!p_igetl(&dummy,f))
{
return qe_invalid;
}
temp_script.vecptr->push_back(dummy);
return qe_invalid;
}
sc.vecptr->push_back(dummy);
}
}

temp_script.give((*script)->zasm[j]);
}
temp_script.clear();
}

// If the first command is unknown, invalidate the whole thing.
// Saw this for https://www.purezc.net/index.php?page=quests&id=411 hero script 0
if ((*script)->zasm[0].command >= NUMCOMMANDS && (*script)->zasm[0].command != 0xFFFF)
if (!zasm.empty() && zasm[0].command >= NUMCOMMANDS && zasm[0].command != 0xFFFF)
{
al_trace("Warning: found script with bad instruction, disabling script: %s %d\n", ScriptTypeToString((*script)->id.type), (*script)->id.index);
(*script)->zasm[0].command = 0xFFFF;
zasm.clear();
}

(*script)->recalc_size();
if ((*script)->valid())
read_scripts.push_back(*script);
zasm_script_id id = zasm_scripts.size();
auto& zs = zasm_scripts.emplace_back(std::make_shared<zasm_script>(id, (*script)->name(), std::move(zasm)));
(*script)->zasm_script = zs;

return 0;
}
Expand Down

0 comments on commit 75f981f

Please sign in to comment.