summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gamedata/engine.txt2
-rw-r--r--src/build/mkentprops.c44
-rw-r--r--src/engineapi.c2
3 files changed, 28 insertions, 20 deletions
diff --git a/gamedata/engine.txt b/gamedata/engine.txt
index 40b8745..87a9620 100644
--- a/gamedata/engine.txt
+++ b/gamedata/engine.txt
@@ -123,7 +123,7 @@ off_SP_offset
Portal2 76
#2013 72 # TODO(compat): not sure about 2013/009 yet pt4
-DT_DataTable 5 # constant value from SendPropType enum (XXX: name okay???)
+DPT_DataTable 5 # constant value from SendPropType enum (XXX: name okay???)
L4Dbased 6
# CBaseServer/CGameServer
diff --git a/src/build/mkentprops.c b/src/build/mkentprops.c
index ef56230..cda1c02 100644
--- a/src/build/mkentprops.c
+++ b/src/build/mkentprops.c
@@ -151,7 +151,8 @@ static struct art_leaf *helpgetleaf(u16 *art, const char *s, int len,
art_leaves[leaf.leafidx].subtree = ART_NULL;
++*countvar;
}
- else if (parsefile) { // it's null if an existing entry is allowed
+ // if parsefile is null then we don't care about dupes (looking at subtable)
+ else if (parsefile && art_leaves[leaf.leafidx].varstr != VAR_NONE) {
dieparse(parsefile, parseline, "duplicate property name");
}
return art_leaves + leaf.leafidx;
@@ -186,7 +187,7 @@ static inline void handleentry(char *k, char *v, int vlen,
}
*nextpart++ = '\0';
sublen = nextpart - propname;
- leaf = helpgetleaf(subtree, propname, sublen, file, line, &leaf->nsubs);
+ leaf = helpgetleaf(subtree, propname, sublen, 0, 0, &leaf->nsubs);
subtree = &leaf->subtree;
vlen -= sublen;
propname = nextpart;
@@ -250,42 +251,45 @@ _( "")
static void dosendtables(FILE *out, u16 art, int indent) {
_i("switch (*p) {")
while (art != ART_NULL) {
+ // stupid hack: figure out char literal in case of null byte
+ char charlit[3] = {art_firstbytes[art], '0'};
+ if_hot (charlit[0]) charlit[1] = '\0'; else charlit[0] = '\\';
if (art_cores[art].slen != 1) {
const char *tail = sbase + art_cores[art].soff + 1;
int len = art_cores[art].slen - 1;
-Fi(" case '%c': if (!strncmp(p + 1, \"%.*s\", %d)) {",
-art_firstbytes[art], len, tail, len)
+Fi(" case '%s': if (!strncmp(p + 1, \"%.*s\", %d)) {",
+charlit, len, tail, len)
}
else {
-Fi(" case '%c': {", art_firstbytes[art])
+Fi(" case '%s': {", charlit)
}
int idx = art_children[art];
// XXX: kind of a dumb and bad way to distinguish these. okay for now...
if (sbase[art_cores[art].soff + art_cores[art].slen - 1] != '\0') {
- dosendtables(out, idx, indent + 1);
+Fi(" p += %d;", art_cores[art].slen)
+ dosendtables(out, idx, indent + 2);
}
else {
+ // XXX: do we actually want to prefetch this before the for loop?
+_i(" int off = baseoff + mem_loads32(mem_offset(sp, off_SP_offset));")
if (art_leaves[idx].varstr != VAR_NONE) {
-_i(" if (mem_loads32(mem_offset(sp, off_SP_type)) != DT_DataTable) {")
-Fi(" %s = mem_loads32(mem_offset(sp, off_SP_offset));",
-sbase + art_leaves[idx].varstr);
-Fi(" --need;")
-_i(" }")
+Fi(" %s = off;", sbase + art_leaves[idx].varstr);
}
if (art_leaves[idx].subtree != ART_NULL) {
-_i(" if (mem_loads32(mem_offset(sp, off_SP_type)) == DT_DataTable) {")
+_i(" if (mem_loads32(mem_offset(sp, off_SP_type)) == DPT_DataTable) {")
+_i(" int baseoff = off;")
_i(" const struct SendTable *st = mem_loadptr(mem_offset(sp, off_SP_subtable));")
_i(" // BEGIN SUBTABLE")
Fi(" for (int i = 0, need = %d; i < st->nprops && need; ++i) {",
-art_leaves[idx].nsubs + art_leaves[idx].varstr != -1)
+art_leaves[idx].nsubs + (art_leaves[idx].varstr != -1))
_i(" const struct SendProp *sp = mem_offset(st->props, sz_SendProp * i);")
_i(" const char *p = mem_loadptr(mem_offset(sp, off_SP_varname));")
dosendtables(out, art_leaves[idx].subtree, indent + 4);
_i(" }")
-Fi(" --need;")
_i(" // END SUBTABLE")
_i(" }")
}
+Fi(" --need;")
}
_i(" } break;")
art = art_cores[art].next;
@@ -296,14 +300,17 @@ _i("}")
static void doclasses(FILE *out, u16 art, int indent) {
_i("switch (*p) {")
for (; art != ART_NULL; art = art_cores[art].next) {
+ // stupid hack 2: exact dupe boogaloo
+ char charlit[3] = {art_firstbytes[art], '0'};
+ if_hot (charlit[0]) charlit[1] = '\0'; else charlit[0] = '\\';
if (art_cores[art].slen != 1) {
const char *tail = sbase + art_cores[art].soff + 1;
int len = art_cores[art].slen - 1;
-Fi(" case '%c': if (!strncmp(p + 1, \"%.*s\", %d)) {",
-art_firstbytes[art], len, tail, len)
+Fi(" case '%s': if (!strncmp(p + 1, \"%.*s\", %d)) {",
+charlit, len, tail, len)
}
else {
-Fi(" case '%c': {", art_firstbytes[art])
+Fi(" case '%s': {", charlit)
}
int idx = art_children[art];
// XXX: same dumb-and-bad-ness as above. there must be a better way!
@@ -316,7 +323,7 @@ Fi(" p += %d;", art_cores[art].slen)
assume(art_leaves[idx].subtree != ART_NULL);
_i(" const struct SendTable *st = class->table;")
Fi(" for (int i = 0, need = %d; i < st->nprops && need; ++i) {",
-art_leaves[idx].nsubs + art_leaves[idx].varstr != -1)
+art_leaves[idx].nsubs + (art_leaves[idx].varstr != -1))
// note: annoyingly long line here, but the generated code gets
// super nested anyway, so there's no point in caring really
// XXX: basically a dupe of dosendtables() - fold into above?
@@ -346,6 +353,7 @@ F( "int %s = 0;", s);
}
_( "")
_( "static inline void initentprops(const struct ServerClass *class) {")
+_( " enum { baseoff = 0 };") // can be shadowed for subtables.
F( " for (int need = %d; need && class; class = class->next) {", nclasses)
_( " const char *p = class->name;")
doclasses(out, art_root, 2);
diff --git a/src/engineapi.c b/src/engineapi.c
index b92de4d..6489d53 100644
--- a/src/engineapi.c
+++ b/src/engineapi.c
@@ -116,7 +116,7 @@ void engineapi_lateinit(void) {
// by doing this at the deferred stage, we avoid having to abs() everything
if (srvdll && has_vtidx_GetAllServerClasses && has_sz_SendProp &&
has_off_SP_varname && has_off_SP_type && has_off_SP_offset &&
- has_DT_DataTable) {
+ has_DPT_DataTable) {
initentprops(GetAllServerClasses(srvdll));
}
}