From ea1947ffcc606d757357398b24e74a3f4ecefa07 Mon Sep 17 00:00:00 2001 From: neonloop Date: Wed, 20 Oct 2021 14:54:27 +0000 Subject: Initial commit from steward-fu release --- core/bgdrtm/src/sysprocs.c | 577 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 577 insertions(+) create mode 100644 core/bgdrtm/src/sysprocs.c (limited to 'core/bgdrtm/src/sysprocs.c') diff --git a/core/bgdrtm/src/sysprocs.c b/core/bgdrtm/src/sysprocs.c new file mode 100644 index 0000000..97ebfbe --- /dev/null +++ b/core/bgdrtm/src/sysprocs.c @@ -0,0 +1,577 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include /* Must be fist include */ + +#include +#include +#include +#include + +#include "bgdrtm.h" +#include "dcb.h" +#include "xstrings.h" + +#include + +/* ---------------------------------------------------------------------- */ + +/* Debe existir un header bgdrtm.h */ +extern int bgd_copy_struct( INSTANCE * my, int * params ) ; +extern int bgd_internal_memcopy( INSTANCE * my, int * params ) ; +extern int bgd_internal_copy_string_array( INSTANCE * my, int * params ) ; + +#include "sysprocs.h" +#include "sysprocs_p.h" + +/* ---------------------------------------------------------------------- */ + +HOOK * handler_hook_list = NULL ; +int handler_hook_allocated = 0 ; +int handler_hook_count = 0 ; + +INSTANCE_HOOK * instance_create_hook_list = NULL ; +int instance_create_hook_allocated = 0 ; +int instance_create_hook_count = 0 ; + +INSTANCE_HOOK * instance_destroy_hook_list = NULL ; +int instance_destroy_hook_allocated = 0 ; +int instance_destroy_hook_count = 0 ; + +INSTANCE_HOOK * instance_pre_execute_hook_list = NULL ; +int instance_pre_execute_hook_allocated = 0 ; +int instance_pre_execute_hook_count = 0 ; + +INSTANCE_HOOK * instance_pos_execute_hook_list = NULL ; +int instance_pos_execute_hook_allocated = 0 ; +int instance_pos_execute_hook_count = 0 ; + +INSTANCE_HOOK * process_exec_hook_list = NULL ; +int process_exec_hook_allocated = 0 ; +int process_exec_hook_count = 0 ; + +FN_HOOK * module_initialize_list = NULL ; +int module_initialize_allocated = 0 ; +int module_initialize_count = 0 ; + +FN_HOOK * module_finalize_list = NULL ; +int module_finalize_allocated = 0 ; +int module_finalize_count = 0 ; + +/* ---------------------------------------------------------------------- */ + +#define hook_add(new_hook, hook_list, hook_allocated, hook_count) \ + { \ + if ((hook_count) >= (hook_allocated)) { \ + (hook_allocated) = (hook_count) + 5; \ + (hook_list) = realloc (hook_list, (hook_allocated) * sizeof((hook_list)[0])); \ + } \ + \ + if (!(hook_list)) { \ + fprintf (stderr, "No memory for alloc hook\n"); \ + exit(-1); \ + } \ + (hook_list)[hook_count] = (new_hook); \ + (hook_count)++; \ + } + +/* ---------------------------------------------------------------------- */ + +static SYSPROC ** sysproc_tab = NULL ; + +/* ---------------------------------------------------------------------- */ + +static int tsize( DCB_TYPEDEF orig ); +static DCB_TYPEDEF treduce( DCB_TYPEDEF orig ); + +/* ---------------------------------------------------------------------- */ + +/* Tipos de token */ +static struct +{ + enum { NOTOKEN, IDENTIFIER, NUMBER } type ; + char name[128] ; + int code ; +} token ; + +static const char * token_ptr = NULL; + +/* ---------------------------------------------------------------------- */ + +/* Very simple tokenizer */ + +static void get_token() +{ + char * ptr ; + unsigned int n ; + + while ( isspace( *token_ptr ) ) token_ptr++ ; + + if ( !*token_ptr ) + { + token.type = NOTOKEN ; + return ; + } + + /* Numbers */ + + if ( ISNUM( *token_ptr ) ) + { + int num = 0 ; + + /* Calculate the number value */ + + while ( ISNUM( *token_ptr ) ) num = num * 10 + ( *token_ptr++ - '0' ) ; + token.type = NUMBER ; + token.code = num ; + snprintf( token.name, sizeof( token.name ), "%d", token.code ) ; + return ; + } + + ptr = token.name ; + *ptr++ = TOUPPER( *token_ptr ) ; + if ( ISWORDCHAR( *token_ptr++ ) ) + while ( ISWORDCHAR( *token_ptr ) ) *ptr++ = TOUPPER( *token_ptr++ ) ; + *ptr = 0 ; + + for ( n = 0; n < dcb.data.NID; n++ ) + { + if ( strcmp( (const char *)dcb.id[n].Name, token.name ) == 0 ) + { + token.type = IDENTIFIER ; + token.code = dcb.id[n].Code ; + strcpy( token.name, (char *)dcb.id[n].Name ) ; + return ; + } + } + + token.type = NOTOKEN ; +} + +/* ---------------------------------------------------------------------- */ + +static DCB_TYPEDEF treduce( DCB_TYPEDEF orig ) +{ + int n ; + for ( n = 0; n < MAX_TYPECHUNKS - 1; n++ ) + { + orig.BaseType[n] = orig.BaseType[n+1] ; + orig.Count[n] = orig.Count[n+1] ; + } + return orig ; +} + +/* ---------------------------------------------------------------------- */ + +static int tsize( DCB_TYPEDEF orig ) +{ + unsigned int n, total ; + + switch ( orig.BaseType[0] ) + { + case TYPE_ARRAY: + return orig.Count[0] * tsize( treduce( orig ) ) ; + + case TYPE_POINTER: + case TYPE_STRING: + case TYPE_DWORD: + case TYPE_FLOAT: + case TYPE_INT: + return 4 ; + + case TYPE_WORD: + case TYPE_SHORT: + return 2 ; + + case TYPE_BYTE: + case TYPE_SBYTE: + case TYPE_CHAR: + return 1 ; + + case TYPE_STRUCT: + total = 0 ; + for ( n = 0; n < dcb.varspace[orig.Members].NVars; n++ ) + total += tsize( dcb.varspace_vars[orig.Members][n].Type ) ; + return total ; + + default: + return 0 ; + } +} + +/* ---------------------------------------------------------------------- */ + +static void get_var_info( DLVARFIXUP * varfixup, DCB_VAR * basevar, int nvars, char * basedata ) +{ + unsigned int n ; + DCB_VAR rvar ; + void * rdata = NULL ; + + token_ptr = varfixup->var ; + + /* for Error */ + varfixup->data_offset = NULL; + varfixup->size = -1; + varfixup->elements = -1; + + get_token() ; + if ( token.type != IDENTIFIER ) return ; /* Not a valid expression */ + + /* Busca variable */ + for ( n = 0; n < nvars; n++ ) + { + if ( basevar[n].ID == token.code ) + { + rvar = basevar[n] ; + rdata = ( uint8_t* )basedata + basevar[n].Offset ; + + get_token() ; + break; + } + } + + if ( n == nvars ) return ; /* Error, no es variable */ + + for ( ;; ) + { + if ( token.name[0] == '.' ) + { + DCB_VARSPACE * v ; + DCB_VAR * var ; + + if ( rvar.Type.BaseType[0] != TYPE_STRUCT ) return ; /* not an struct */ + + get_token() ; + if ( token.type != IDENTIFIER ) return ; /* not a member */ + + v = &dcb.varspace[rvar.Type.Members] ; + var = dcb.varspace_vars[rvar.Type.Members] ; + for ( n = 0; n < v->NVars; n++ ) if ( var[n].ID == token.code ) break ; + + if ( n == v->NVars ) return ; /* not a member */ + + rvar = var[n] ; + rdata = ((uint8_t *)rdata) + var[n].Offset ; + + get_token() ; + continue ; + } + + if ( token.name[0] == '[' ) + { + int index; + + if ( rvar.Type.BaseType[0] != TYPE_ARRAY ) return ; /* not an array */ + + get_token() ; + if ( token.type != NUMBER ) return ; /* not an integer */ + index = token.code; + + if ( index < 0 ) return ; /* Index less than zero */ + if ( index >= rvar.Type.Count[0] ) return ; /* Index out of bounds */ + + rvar.Type = treduce( rvar.Type ) ; + rdata = ((uint8_t *) rdata ) + index * tsize( rvar.Type ) ; + + get_token() ; + if ( token.name[0] == ']' ) get_token() ; /* Skip ] */ + + continue ; + } + + varfixup->data_offset = ( void * ) rdata; + varfixup->elements = rvar.Type.BaseType[0] == TYPE_ARRAY ? rvar.Type.Count[0] : 1; + varfixup->size = tsize( rvar.Type ) / varfixup->elements; +/* + printf ("varfixup: %p var: %s offset: %p elements: %d size: %d\n", varfixup, varfixup->var, varfixup->data_offset, varfixup->elements, varfixup->size); +*/ + break ; + } +} + +/* ---------------------------------------------------------------------- */ + +int compare_priority( const HOOK * a1, const HOOK * a2 ) +{ + return ( a2->prio - a1->prio ) ; +} + +/* ---------------------------------------------------------------------- */ + +int sysproc_add( char * name, char * paramtypes, int type, void * func ) +{ + static SYSPROC * sysproc_new = 0 ; + static int sysproc_count = 0 ; + + if ( !sysproc_new ) + { + sysproc_new = sysprocs ; + while ( sysproc_new->name ) + { + sysproc_new++ ; + sysproc_count++ ; + } + } + + if ( sysproc_count >= MAX_SYSPROCS ) + { + fprintf( stderr, "ERROR: Runtime error - too many system functions\n" ) ; + return -1; + } + + sysproc_new->code = -1 ; /* Se llena en el fixup */ + sysproc_new->name = name ; + sysproc_new->paramtypes = paramtypes ; + sysproc_new->params = strlen( paramtypes ) ; + sysproc_new->type = type ; + sysproc_new->func = ( SYSFUNC * ) func ; + sysproc_new->id = getid( name ) ; + + sysproc_new++ ; + sysproc_count++ ; + + sysproc_new->func = NULL ; + + return 0 /*sysproc_new->code*/ ; +} + +/* ---------------------------------------------------------------------- */ + +SYSPROC * sysproc_get( int code ) +{ + return sysproc_tab[code] ; +} + +/* ---------------------------------------------------------------------- */ + +void sysproc_add_tab( DLSYSFUNCS * functions_exports ) +{ + if ( functions_exports ) + { + while ( functions_exports->name ) + { + sysproc_add( functions_exports->name, functions_exports->paramtypes, functions_exports->type, functions_exports->func ); + functions_exports++; + } + } +} + +/* ---------------------------------------------------------------------- */ + +static char * dlsearchpath[] = +{ + "modules", + "mod", + "mods", + "extensions", + "plugins", + "data", + NULL +}; + +/* ---------------------------------------------------------------------- */ + +void sysproc_init() +{ + SYSPROC * proc = sysprocs ; + void * library = NULL ; + const char * filename ; + unsigned int n ; + + DLVARFIXUP * globals_fixup = NULL ; + DLVARFIXUP * locals_fixup = NULL ; + DLSYSFUNCS * functions_exports = NULL ; + FN_HOOK module_initialize ; + FN_HOOK module_finalize ; + INSTANCE_HOOK instance_create_hook ; + INSTANCE_HOOK instance_destroy_hook ; + INSTANCE_HOOK instance_pre_execute_hook ; + INSTANCE_HOOK instance_pos_execute_hook ; + INSTANCE_HOOK process_exec_hook ; + HOOK * handler_hooks = NULL ; + + int maxcode = 0 ; + + char soname[ __MAX_PATH ], fullsoname[ __MAX_PATH ], **spath ; + +#if defined( WIN32 ) +#define DLLEXT ".dll" +#elif defined(TARGET_MAC) +#define DLLEXT ".dylib" +#else +#define DLLEXT ".so" +#endif + + for ( n = 0; n < dcb.data.NImports; n++ ) + { + filename = string_get( dcb.imports[n] ) ; + + snprintf( soname, __MAX_PATH, "%s" DLLEXT, filename ); + + filename = soname ; + + /* Load library */ + + if ( debug ) printf ("Loading... %s\n", filename ); + + fullsoname[0] = '\0'; + + library = NULL; + + spath = dlsearchpath; + while( !library && spath && *spath ) + { + sprintf( fullsoname, "%s%s/%s", appexepath, *spath, filename ); + library = dlibopen( fullsoname ) ; + spath++; + } + + if ( !library ) library = dlibopen( filename ) ; + + if ( !library ) + { + printf( dliberror() ) ; + exit( 0 ); + } + + globals_fixup = ( DLVARFIXUP * ) _dlibaddr( library, "globals_fixup" ) ; + locals_fixup = ( DLVARFIXUP * ) _dlibaddr( library, "locals_fixup" ) ; + functions_exports = ( DLSYSFUNCS * ) _dlibaddr( library, "functions_exports" ) ; + + module_initialize = ( FN_HOOK ) _dlibaddr( library, "module_initialize" ) ; + module_finalize = ( FN_HOOK ) _dlibaddr( library, "module_finalize" ) ; + + instance_create_hook = ( INSTANCE_HOOK ) _dlibaddr( library, "instance_create_hook" ) ; + instance_destroy_hook = ( INSTANCE_HOOK ) _dlibaddr( library, "instance_destroy_hook" ) ; + instance_pre_execute_hook = ( INSTANCE_HOOK ) _dlibaddr( library, "instance_pre_execute_hook" ) ; + instance_pos_execute_hook = ( INSTANCE_HOOK ) _dlibaddr( library, "instance_pos_execute_hook" ) ; + process_exec_hook = ( INSTANCE_HOOK ) _dlibaddr( library, "process_exec_hook" ) ; + + handler_hooks = ( HOOK * ) _dlibaddr( library, "handler_hooks" ) ; + + /* Fixups */ + + if ( globals_fixup ) + { + while ( globals_fixup->var ) + { + get_var_info( globals_fixup, dcb.glovar, dcb.data.NGloVars, globaldata ); + globals_fixup++; + } + } + + if ( locals_fixup ) + { + while ( locals_fixup->var ) + { + get_var_info( locals_fixup, dcb.locvar, dcb.data.NLocVars, NULL ); + locals_fixup++; + } + } + + sysproc_add_tab( functions_exports ) ; + + if ( module_initialize ) + hook_add( module_initialize, module_initialize_list, module_initialize_allocated, module_initialize_count ) ; + + if ( module_finalize ) + hook_add( module_finalize, module_finalize_list, module_finalize_allocated, module_finalize_count ) ; + + if ( instance_create_hook ) + hook_add( instance_create_hook, instance_create_hook_list, instance_create_hook_allocated, instance_create_hook_count ) ; + + if ( instance_destroy_hook ) + hook_add( instance_destroy_hook, instance_destroy_hook_list, instance_destroy_hook_allocated, instance_destroy_hook_count ) ; + + if ( instance_pre_execute_hook ) + hook_add( instance_pre_execute_hook, instance_pre_execute_hook_list, instance_pre_execute_hook_allocated, instance_pre_execute_hook_count ) ; + + if ( instance_pos_execute_hook ) + hook_add( instance_pos_execute_hook, instance_pos_execute_hook_list, instance_pos_execute_hook_allocated, instance_pos_execute_hook_count ) ; + + if ( process_exec_hook ) + hook_add( process_exec_hook, process_exec_hook_list, process_exec_hook_allocated, process_exec_hook_count ) ; + + while ( handler_hooks && handler_hooks->hook ) + { + hook_add( *handler_hooks, handler_hook_list, handler_hook_allocated, handler_hook_count ) ; + handler_hooks++; + } + } + + if ( debug ) printf ("\n"); + + /* System Procs FixUp */ + + sysprocs_fixup(); + + proc = sysprocs ; + while ( proc->func ) + { + if ( maxcode < proc->code ) maxcode = proc->code ; + proc++ ; + } + + sysproc_tab = calloc( maxcode + 1 , sizeof( SYSPROC * ) ); + + proc = sysprocs ; + while ( proc->func ) + { + if ( proc->code > -1 ) sysproc_tab[proc->code] = proc ; + proc++ ; + } + + /* Sort handler_hooks */ + if ( handler_hook_list ) + qsort( handler_hook_list, handler_hook_count, sizeof( handler_hook_list[0] ), ( int ( * )( const void *, const void * ) ) compare_priority ) ; + + /* Initialize all modules */ + if ( module_initialize_count ) + for ( n = 0; n < module_initialize_count; n++ ) + module_initialize_list[n](); +} + +/* ---------------------------------------------------------------------- */ + +extern DCB_SYSPROC_CODE2 * sysproc_code_ref ; + +/* ---------------------------------------------------------------------- */ + +char * sysproc_name( int code ) +{ + DCB_SYSPROC_CODE2 * s = NULL ; + int n; + + s = sysproc_code_ref ; + for ( n = 0; n < dcb.data.NSysProcsCodes; n++, s++ ) + if ( s->Code == code ) return getid_name( s->Id ) ; + + return NULL ; +} + +/* ---------------------------------------------------------------------- */ -- cgit v1.2.3