This commit is contained in:
Cooliokid956 2026-04-03 11:42:52 +00:00 committed by GitHub
commit d924d7002f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 2317 additions and 2246 deletions

View file

@ -92,7 +92,7 @@ WINDOWS_AUTO_BUILDER ?= 0
# Setup extra cflags
EXTRA_CFLAGS ?=
EXTRA_CPP_FLAGS ?=
EXTRA_CFLAGS += -Wno-format-security -Wno-trigraphs
EXTRA_CFLAGS += -Wno-format-security -Wno-trigraphs -Wno-missing-braces -Wno-missing-field-initializers
dev:; @$(MAKE) DEVELOPMENT=1

View file

@ -6,6 +6,7 @@ usf_types = ['u8', 'u16', 'u32', 'u64', 's8', 's16', 's32', 's64', 'f32', 'f64']
vec_types = list(VEC_TYPES.keys())
typedef_pointers = ['BehaviorScript', 'ObjectAnimPointer', 'Collision', 'LevelScript', 'Trajectory', 'Texture']
cobject_function_identifier = 'FUNCTION'
cobject_property_identifier = 'PROPERTY'
type_mappings = {
'char': 's8',
@ -149,14 +150,10 @@ def translate_type_to_lvt(ptype, allowArrays=False):
if ptype == cobject_function_identifier:
return "LVT_FUNCTION"
if "struct" in ptype:
if pointerLvl > 1:
return "LVT_???"
if pointerLvl == 1:
return "LVT_COBJECT_P"
return "LVT_COBJECT"
if ptype == cobject_property_identifier:
return "LVT_PROPERTY"
if ptype in override_types:
if "struct" in ptype or ptype in override_types:
if pointerLvl > 1:
return "LVT_???"
if pointerLvl == 1:
@ -174,16 +171,8 @@ def translate_type_to_lot(ptype, allowArrays=True):
pointerLvl = 0
lvt = translate_type_to_lvt(ptype, allowArrays=allowArrays)
if ptype == 'void':
return 'LOT_NONE'
if ptype == 'const char*':
return 'LOT_NONE'
if ptype == 'ByteString':
return 'LOT_NONE'
if 'unsigned' not in ptype and (ptype == 'char*' or ('char' in ptype and '[' in ptype)):
if ptype == ('void', 'const char*', 'ByteString') \
or 'unsigned' not in ptype and (ptype == 'char*' or ('char' in ptype and '[' in ptype)):
return 'LOT_NONE'
# Remove array symbols so they can be identified
@ -199,13 +188,7 @@ def translate_type_to_lot(ptype, allowArrays=True):
if '[' in ptype or '{' in ptype:
return 'LOT_???'
if 'enum ' in ptype:
return 'LOT_NONE'
if ptype in usf_types:
return 'LOT_NONE'
if extract_integer_datatype(ptype):
if 'enum ' in ptype or ptype in usf_types or extract_integer_datatype(ptype):
return 'LOT_NONE'
# Strip out our pointer stars to get the true type.
@ -214,22 +197,10 @@ def translate_type_to_lot(ptype, allowArrays=True):
pointerLvl = ptype.count("*")
ptype = ptype.replace("*", "").strip()
if ptype == 'bool':
return 'LOT_NONE'
if ptype in vec_types:
return 'LOT_' + ptype.upper()
if ptype == 'float':
return 'LOT_NONE'
if ptype == 'LuaFunction':
return 'LOT_NONE'
if ptype == 'LuaTable':
return 'LOT_NONE'
if ptype == cobject_function_identifier:
if ptype in ('bool', 'float', 'LuaFunction', 'LuaTable', cobject_function_identifier, cobject_property_identifier):
return 'LOT_NONE'
if ptype in override_types:
@ -291,22 +262,10 @@ def translate_type_to_lua(ptype):
return '`number`', None
return '`integer`', None
if ptype == 'char':
if ptype in ('char', 'int', 'lua_Integer'):
return '`integer`', None
if ptype == 'int':
return '`integer`', None
if ptype == 'lua_Integer':
return '`integer`', None
if ptype == 'float':
return '`number`', None
if ptype == 'lua_Number':
return '`number`', None
if ptype == 'double':
if ptype in ('float', 'lua_Number', 'double'):
return '`number`', None
if ptype == 'bool':
@ -324,6 +283,9 @@ def translate_type_to_lua(ptype):
if ptype == cobject_function_identifier:
return cobject_function_identifier, None
if ptype == cobject_property_identifier:
return cobject_property_identifier, None
if ptype.count('*') == 1 and '???' not in translate_type_to_lvt(ptype):
ptype = ptype.replace('const', '').replace('*', '').strip()
s = '`Pointer` <`%s`>' % translate_type_to_lua(ptype)[0].replace('`', '').strip()

View file

@ -264,10 +264,17 @@ def table_to_string(table):
for row in table:
for i in range(columns):
if '#' in row[i]:
if '#' in row[i] or row[i][-1] == '\\':
continue
if len(row[i]) > column_width[i]:
column_width[i] = len(row[i])
for row in table:
for i in range(columns):
if row[i][-1] == '\\':
row[i] = row[i][:-1]
row[i+1] = row[i][column_width[i]:] + row[i+1]
row[i] = row[i][:column_width[i]]
s = ''
for row in table:
@ -327,12 +334,21 @@ def parse_struct(struct_str, sortFields = False):
# handle function members
if field['type'].startswith(cobject_function_identifier):
field_function = field['identifier']
field_type, field_id = field['type'].split()
field_function = field['identifier']
field['type'] = field_type.strip()
field['identifier'] = field_id.strip('"').strip()
field['identifier'] = field_id.strip()
field['function'] = field_function.strip()
# handle property members
if field['type'].startswith(cobject_property_identifier):
field_type, field_id, field_get = field['type'].split()
field_set = field['identifier']
field['type'] = field_type.strip()
field['identifier'] = field_id.strip()
field['get'] = field_get.strip()
field['set'] = field_set.strip()
struct['fields'].append(field)
if identifier == 'Object':
@ -496,9 +512,6 @@ def get_struct_field_info(struct, field):
if fid in override_field_mutable[sid] or '*' in override_field_mutable[sid]:
fimmutable = 'false'
if ftype == cobject_function_identifier:
fimmutable = 'true'
if not ('char' in ftype and '[' in ftype and 'unsigned' not in ftype):
array_match = re.search(r'\[([^\]]+)\]', ftype)
if array_match:
@ -549,27 +562,26 @@ def build_struct(struct):
startStr += '#ifndef ' + override_field_version_excludes[fid] + '\n'
endStr += '\n#endif'
startStr += ' { '
if ftype == cobject_function_identifier:
row.append(startStr )
row.append('"%s", ' % fid )
row.append('%s, ' % lvt )
row.append('(size_t) "%s", ' % field['function'])
row.append('%s, ' % fimmutable )
row.append('%s, ' % lot )
row.append('%s, ' % size )
row.append('sizeof(const char *)' )
row.append(endStr )
field_functions.append(field['function'])
row.append(startStr)
row.append('"%s", ' % fid)
row.append('%s, ' % lvt)
if field.get('function'):
row.append('.function = "%s"\\' % field['function'])
elif field.get('get'):
row.append('.get = "%s", ' % field['get'])
row.append('.set = "%s"\\' % field['set'])
else:
row.append(startStr )
row.append('"%s", ' % fid )
row.append('%s, ' % lvt )
row.append('offsetof(%s%s, %s), ' % (struct_str, name, field['identifier']))
row.append('%s, ' % fimmutable )
row.append('%s, ' % lot )
row.append('%s, ' % size )
row.append('sizeof(%s)' % ftype )
row.append(endStr )
row.append('%s, ' % fimmutable)
row.append('%s, ' % lot )
if size != 1:
row.append('%s, ' % size )
row.append('sizeof(%s)' % ftype )
else: row[-1] = row[-1][:-2]
row.extend(['\\'] * (8 - len(row)))
row.append(endStr)
if field.get('function'):
field_functions.append(field['function'])
field_table.append(row)
field_table_str, field_count = table_to_string(field_table)
@ -726,6 +738,10 @@ def doc_struct_field(struct, field):
flink = doc_find_function_link(field['function'])
return '| %s | [`%s`](%s) |\n' % (fid, field['function'], flink), True
if ftype == cobject_property_identifier:
ftype = get_function_signature(field['get'])
ftype = f"`{ftype[ftype.rfind(':')+2:]}`"
restrictions = ('', 'read-only')[fimmutable == 'true']
global total_fields
@ -854,6 +870,9 @@ def def_struct(struct):
# try to get the function signature
if ftype == cobject_function_identifier:
ftype = get_function_signature(field['function'])
elif ftype == cobject_property_identifier:
ftype = get_function_signature(field['get'])
ftype = f"{ftype[ftype.rfind(':')+2:]}"
else:
ftype = translate_to_def(ftype)

View file

@ -1,7 +1,7 @@
import os
import re
import sys
from common import cobject_function_identifier
from common import cobject_function_identifier, cobject_property_identifier
def extract_structs(filename):
with open(filename) as file:
@ -38,7 +38,10 @@ def extract_structs(filename):
txt = txt.replace(' ', ' ')
# handle function members (NOT function pointers)
txt = re.sub(f'{cobject_function_identifier}\\((.*),(.*)\\)', f'{cobject_function_identifier} \\1 \\2', txt)
txt = re.sub(f'{cobject_function_identifier}\\((.*),(.*)\\)', f'{cobject_function_identifier} \\1\\2', txt)
# handle property members
txt = re.sub(f'{cobject_property_identifier}\\((.*),(.*),(.*)\\)', f'{cobject_property_identifier} \\1\\2\\3', txt)
# strip macros
txt = re.sub(r'[^a-zA-Z0-9_][A-Z0-9_]+\(.*\)', '', txt)

View file

@ -1199,6 +1199,10 @@
--- @field public isStream boolean
--- @field public baseVolume number
--- @field public loaded boolean
--- @field public position number
--- @field public looping boolean
--- @field public frequency number
--- @field public volume number
--- @class ModFs
--- @field public mod Mod

View file

@ -1747,6 +1747,10 @@
| isStream | `boolean` | read-only |
| baseVolume | `number` | |
| loaded | `boolean` | read-only |
| position | `number` | |
| looping | `boolean` | |
| frequency | `number` | |
| volume | `number` | |
[:arrow_up_small:](#)

View file

@ -21,6 +21,11 @@
// Optional parameters must be contiguous until the last parameter (a mandatory parameter following an optional parameter is not allowed)
#define OPTIONAL
// A macro to tell autogen the field `name` is a property member of the struct that calls `get` or `set` accessors
// - get: fun(self) -> value
// - set: fun(self, value)
#define PROPERTY(name, get, set)
// A macro to tell autogen the field `name` is a function member of the struct that calls `c_function`
#define FUNCTION(name, c_function)

View file

@ -101,6 +101,7 @@ static const char *sLuaLvtNames[] = {
[LVT_LUATABLE] = "LuaTable",
[LVT_POINTER] = "pointer",
[LVT_FUNCTION] = "function",
[LVT_PROPERTY] = "property",
[LVT_MAX] = "unknown",
};
@ -552,22 +553,30 @@ static int smlua__get_field(lua_State* L) {
// CObject function members
if (data->valueType == LVT_FUNCTION) {
const char *function = (const char *) data->valueOffset;
lua_getglobal(L, function);
lua_getglobal(L, data->function);
LUA_STACK_CHECK_END(L);
return 1;
}
// CObject property
if (data->valueType == LVT_PROPERTY) {
lua_getglobal(L, data->get);
lua_pushvalue(L, 1);
smlua_pcall(L, 1, 1, 0);
LUA_STACK_CHECK_END(L);
return 1;
}
u8* p = ((u8*)(intptr_t)pointer) + data->valueOffset;
if (data->count == 1) {
if (smlua_push_field(L, p, data)) {
LOG_LUA_LINE("_get_field on unimplemented type '%d', key '%s'", data->valueType, key);
if (data->count > 1) {
smlua_push_object(L, LOT_ARRAY, p, data);
if (!gSmLuaConvertSuccess) {
LOG_LUA_LINE("_get_field failed to retrieve value type '%d', key '%s'", data->valueType, key);
return 0;
}
} else {
smlua_push_object(L, LOT_ARRAY, p, data);
if (!gSmLuaConvertSuccess) {
LOG_LUA_LINE("_set_field failed to retrieve value type '%d', key '%s'", data->valueType, key);
if (smlua_push_field(L, p, data)) {
LOG_LUA_LINE("_get_field on unimplemented type '%d', key '%s'", data->valueType, key);
return 0;
}
}
@ -633,7 +642,17 @@ static int smlua__set_field(lua_State* L) {
return 0;
}
if (data->immutable) {
// CObject property
if (data->valueType == LVT_PROPERTY) {
lua_getglobal(L, data->set);
lua_pushvalue(L, 1);
lua_pushvalue(L, 3);
smlua_pcall(L, 2, 1, 0);
LUA_STACK_CHECK_END(L);
return 1;
}
if (data->immutable || data->valueType == LVT_FUNCTION) {
LOG_LUA_LINE("_set_field on immutable key '%s'", key);
return 0;
}
@ -652,6 +671,41 @@ static int smlua__set_field(lua_State* L) {
return 1;
}
int smlua__iter(lua_State *L) {
lua_rawgeti(L, 1, 1);
int i = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, 1, 2);
const CObject *cobj = lua_touserdata(L, -1);
lua_pop(L, 1);
extern struct LuaObjectTable sLuaObjectAutogenTable[];
struct LuaObjectTable* ot = &sLuaObjectAutogenTable[cobj->lot - LOT_AUTOGEN_MIN - 1];
if (i >= ot->fieldCount) { return 0; }
u8* pointer = (u8*)(intptr_t) cobj->pointer;
struct LuaObjectField* data = &ot->fields[i];
lua_pushstring(L, data->key);
smlua_push_field(L, pointer, data);
lua_pushinteger(L, ++i);
lua_rawseti(L, 1, 1);
return 2;
}
int smlua__pairs(lua_State *L) {
lua_pushcfunction(L, smlua__iter);
lua_newtable(L);
lua_pushinteger(L, 0); lua_rawseti(L, -2, 1);
lua_pushvalue (L, 1); lua_rawseti(L, -2, 2);
lua_pushnil(L);
return 3;
}
int smlua__eq(lua_State *L) {
const CObject *a = lua_touserdata(L, 1);
const CObject *b = lua_touserdata(L, 2);
@ -704,6 +758,7 @@ void smlua_cobject_init_globals(void) {
luaL_Reg cObjectMethods[] = {
{ "__index", smlua__get_field },
{ "__newindex", smlua__set_field },
{ "__pairs", smlua__pairs },
{ "__eq", smlua__eq },
{ "__bnot", smlua__bnot },
{ "__metatable", NULL },

View file

@ -36,17 +36,27 @@ enum LuaValueType {
LVT_LUATABLE,
LVT_POINTER,
LVT_FUNCTION,
LVT_PROPERTY,
LVT_MAX,
};
struct LuaObjectField {
const char* key;
enum LuaValueType valueType;
size_t valueOffset;
bool immutable;
u16 lot;
u16 count;
u32 size;
union {
struct {
size_t valueOffset;
bool immutable;
u16 lot;
u16 count;
u32 size;
};
const char* function;
struct {
const char* get;
const char* set;
};
};
};
struct LuaObjectTable {

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,11 @@ struct ModAudio {
bool isStream;
f32 baseVolume;
bool loaded;
PROPERTY(position, audio_stream_get_position, audio_stream_set_position);
PROPERTY(looping, audio_stream_get_looping, audio_stream_set_looping);
PROPERTY(frequency, audio_stream_get_frequency, audio_stream_set_frequency);
PROPERTY(volume, audio_stream_get_volume, audio_stream_set_volume);
};
/* |description|Loads an `audio` stream by `filename` (with extension)|descriptionEnd| */