SCI: Run astyle to make the code be more compliant with our Code Formatting Guidelines: engine dir

svn-id: r38317
This commit is contained in:
Max Horn 2009-02-15 22:28:12 +00:00
parent 7adf721492
commit 57434d955f
28 changed files with 8858 additions and 9698 deletions

View file

@ -39,18 +39,17 @@ extern int bp_flag;
static int static int
_init_vocabulary(state_t *s) /* initialize vocabulary and related resources */ _init_vocabulary(state_t *s) { /* initialize vocabulary and related resources */
{
s->parser_lastmatch_word = SAID_NO_MATCH; s->parser_lastmatch_word = SAID_NO_MATCH;
s->parser_rules = NULL; s->parser_rules = NULL;
sciprintf("Initializing vocabulary\n"); sciprintf("Initializing vocabulary\n");
if ((s->resmgr->sci_version < SCI_VERSION_01_VGA)&&(s->parser_words = vocab_get_words(s->resmgr, &(s->parser_words_nr)))) { if ((s->resmgr->sci_version < SCI_VERSION_01_VGA) && (s->parser_words = vocab_get_words(s->resmgr, &(s->parser_words_nr)))) {
s->parser_suffices = vocab_get_suffices(s->resmgr, &(s->parser_suffices_nr)); s->parser_suffices = vocab_get_suffices(s->resmgr, &(s->parser_suffices_nr));
if ((s->parser_branches = vocab_get_branches(s->resmgr, &(s->parser_branches_nr)))) if ((s->parser_branches = vocab_get_branches(s->resmgr, &(s->parser_branches_nr))))
/* Now build a GNF grammar out of this */ /* Now build a GNF grammar out of this */
s->parser_rules = vocab_build_gnf(s->parser_branches, s->parser_branches_nr); s->parser_rules = vocab_build_gnf(s->parser_branches, s->parser_branches_nr);
} else { } else {
sciprintf("Assuming that this game does not use a parser.\n"); sciprintf("Assuming that this game does not use a parser.\n");
@ -76,8 +75,7 @@ _init_vocabulary(state_t *s) /* initialize vocabulary and related resources */
extern int _allocd_rules; extern int _allocd_rules;
static void static void
_free_vocabulary(state_t *s) _free_vocabulary(state_t *s) {
{
sciprintf("Freeing vocabulary\n"); sciprintf("Freeing vocabulary\n");
if (s->parser_words) { if (s->parser_words) {
@ -99,8 +97,7 @@ _free_vocabulary(state_t *s)
static int static int
_init_graphics_input(state_t *s) _init_graphics_input(state_t *s) {
{
s->pic_priority_table = NULL; s->pic_priority_table = NULL;
s->pics = NULL; s->pics = NULL;
s->pics_nr = 0; s->pics_nr = 0;
@ -108,8 +105,7 @@ _init_graphics_input(state_t *s)
} }
static void static void
_sci1_alloc_system_colors(state_t *s) _sci1_alloc_system_colors(state_t *s) {
{
gfx_color_t white; gfx_color_t white;
gfx_color_t black; gfx_color_t black;
@ -129,8 +125,7 @@ _sci1_alloc_system_colors(state_t *s)
} }
int int
_reset_graphics_input(state_t *s) _reset_graphics_input(state_t *s) {
{
resource_t *resource; resource_t *resource;
int font_nr; int font_nr;
gfx_color_t transparent; gfx_color_t transparent;
@ -141,33 +136,32 @@ _reset_graphics_input(state_t *s)
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if (gfxop_set_color(s->gfx_state, &(s->ega_colors[i]), if (gfxop_set_color(s->gfx_state, &(s->ega_colors[i]),
gfx_sci0_image_colors[sci0_palette][i].r, gfx_sci0_image_colors[sci0_palette][i].r,
gfx_sci0_image_colors[sci0_palette][i].g, gfx_sci0_image_colors[sci0_palette][i].g,
gfx_sci0_image_colors[sci0_palette][i].b, gfx_sci0_image_colors[sci0_palette][i].b,
0, -1, -1)) 0, -1, -1))
return 1; return 1;
gfxop_set_system_color(s->gfx_state, &(s->ega_colors[i])); gfxop_set_system_color(s->gfx_state, &(s->ega_colors[i]));
} }
} else } else {
{
/* Check for Amiga palette file. */ /* Check for Amiga palette file. */
FILE *f = sci_fopen("spal", "rb"); FILE *f = sci_fopen("spal", "rb");
if (f) { if (f) {
s->gfx_state->resstate->static_palette = s->gfx_state->resstate->static_palette =
gfxr_read_pal1_amiga(&s->gfx_state->resstate->static_palette_entries, f); gfxr_read_pal1_amiga(&s->gfx_state->resstate->static_palette_entries, f);
fclose(f); fclose(f);
_sci1_alloc_system_colors(s); _sci1_alloc_system_colors(s);
} else { } else {
resource = scir_find_resource(s->resmgr, sci_palette, 999, 1); resource = scir_find_resource(s->resmgr, sci_palette, 999, 1);
if (resource) { if (resource) {
if (s->version < SCI_VERSION(1,001,000)) if (s->version < SCI_VERSION(1, 001, 000))
s->gfx_state->resstate->static_palette = s->gfx_state->resstate->static_palette =
gfxr_read_pal1(999, &s->gfx_state->resstate->static_palette_entries, gfxr_read_pal1(999, &s->gfx_state->resstate->static_palette_entries,
resource->data, resource->size); resource->data, resource->size);
else else
s->gfx_state->resstate->static_palette = s->gfx_state->resstate->static_palette =
gfxr_read_pal11(999, &s->gfx_state->resstate->static_palette_entries, gfxr_read_pal11(999, &s->gfx_state->resstate->static_palette_entries,
resource->data, resource->size); resource->data, resource->size);
_sci1_alloc_system_colors(s); _sci1_alloc_system_colors(s);
scir_unlock_resource(s->resmgr, resource, sci_palette, 999); scir_unlock_resource(s->resmgr, resource, sci_palette, 999);
} else } else
@ -195,7 +189,8 @@ _reset_graphics_input(state_t *s)
s->priority_first = 42; /* Priority zone 0 ends here */ s->priority_first = 42; /* Priority zone 0 ends here */
if (s->version < SCI_VERSION_FTU_PRIORITY_14_ZONES) if (s->version < SCI_VERSION_FTU_PRIORITY_14_ZONES)
s->priority_last = 200; else s->priority_last = 200;
else
s->priority_last = 190; s->priority_last = 190;
font_nr = -1; font_nr = -1;
@ -214,8 +209,7 @@ _reset_graphics_input(state_t *s)
s->iconbar_port = gfxw_new_port(s->visual, NULL, gfx_rect(0, 0, 320, 200), s->ega_colors[0], transparent); s->iconbar_port = gfxw_new_port(s->visual, NULL, gfx_rect(0, 0, 320, 200), s->ega_colors[0], transparent);
s->iconbar_port->flags |= GFXW_FLAG_NO_IMPLICIT_SWITCH; s->iconbar_port->flags |= GFXW_FLAG_NO_IMPLICIT_SWITCH;
if (s->resmgr->sci_version >= SCI_VERSION_01_VGA) if (s->resmgr->sci_version >= SCI_VERSION_01_VGA) {
{
// This bit sets the foreground and background colors in VGA SCI games // This bit sets the foreground and background colors in VGA SCI games
#if 0 #if 0
gfx_color_t fgcolor; gfx_color_t fgcolor;
@ -225,12 +219,12 @@ _reset_graphics_input(state_t *s)
fgcolor.mask = GFX_MASK_VISUAL; fgcolor.mask = GFX_MASK_VISUAL;
bgcolor.visual = s->gfx_state->resstate->static_palette[255]; bgcolor.visual = s->gfx_state->resstate->static_palette[255];
bgcolor.mask = GFX_MASK_VISUAL; bgcolor.mask = GFX_MASK_VISUAL;
s->titlebar_port = gfxw_new_port(s->visual, NULL, gfx_rect(0, 0, 320, 10), s->titlebar_port = gfxw_new_port(s->visual, NULL, gfx_rect(0, 0, 320, 10),
fgcolor, bgcolor); fgcolor, bgcolor);
#endif #endif
} else } else
s->titlebar_port = gfxw_new_port(s->visual, NULL, gfx_rect(0, 0, 320, 10), s->titlebar_port = gfxw_new_port(s->visual, NULL, gfx_rect(0, 0, 320, 10),
s->ega_colors[0], s->ega_colors[15]); s->ega_colors[0], s->ega_colors[15]);
s->titlebar_port->color.mask |= GFX_MASK_PRIORITY; s->titlebar_port->color.mask |= GFX_MASK_PRIORITY;
s->titlebar_port->color.priority = 11; s->titlebar_port->color.priority = 11;
s->titlebar_port->bgcolor.mask |= GFX_MASK_PRIORITY; s->titlebar_port->bgcolor.mask |= GFX_MASK_PRIORITY;
@ -259,8 +253,7 @@ _reset_graphics_input(state_t *s)
} }
int int
game_init_graphics(state_t *s) game_init_graphics(state_t *s) {
{
#ifndef WITH_PIC_SCALING #ifndef WITH_PIC_SCALING
if (s->gfx_state->options->pic0_unscaled == 0) if (s->gfx_state->options->pic0_unscaled == 0)
sciprintf("WARNING: Pic scaling was disabled; your version of FreeSCI has no support for scaled pic drawing built in.\n"); sciprintf("WARNING: Pic scaling was disabled; your version of FreeSCI has no support for scaled pic drawing built in.\n");
@ -272,8 +265,7 @@ game_init_graphics(state_t *s)
static void static void
_free_graphics_input(state_t *s) _free_graphics_input(state_t *s) {
{
sciprintf("Freeing graphics\n"); sciprintf("Freeing graphics\n");
s->visual->widfree(GFXW(s->visual)); s->visual->widfree(GFXW(s->visual));
@ -291,8 +283,7 @@ _free_graphics_input(state_t *s)
/*------------------------------------------------------------*/ /*------------------------------------------------------------*/
int int
game_init_sound(state_t *s, int sound_flags) game_init_sound(state_t *s, int sound_flags) {
{
if (s->resmgr->sci_version >= SCI_VERSION_01) if (s->resmgr->sci_version >= SCI_VERSION_01)
sound_flags |= SFX_STATE_FLAG_MULTIPLAY; sound_flags |= SFX_STATE_FLAG_MULTIPLAY;
@ -305,8 +296,7 @@ game_init_sound(state_t *s, int sound_flags)
/* Maps a class ID to the script the corresponding class is contained in */ /* Maps a class ID to the script the corresponding class is contained in */
/* Returns the script number suggested by vocab.996, or -1 if there's none */ /* Returns the script number suggested by vocab.996, or -1 if there's none */
static int static int
suggested_script(resource_t *res, unsigned int classId) suggested_script(resource_t *res, unsigned int classId) {
{
int offset; int offset;
if (!res || classId >= res->size >> 2) if (!res || classId >= res->size >> 2)
return -1; return -1;
@ -317,9 +307,8 @@ suggested_script(resource_t *res, unsigned int classId)
} }
int int
test_cursor_style(state_t *s) test_cursor_style(state_t *s) {
{
int resource_nr = 0; int resource_nr = 0;
int ok = 0; int ok = 0;
@ -331,8 +320,7 @@ test_cursor_style(state_t *s)
} }
int int
create_class_table_sci11(state_t *s) create_class_table_sci11(state_t *s) {
{
int scriptnr; int scriptnr;
unsigned int seeker_offset; unsigned int seeker_offset;
char *seeker_ptr; char *seeker_ptr;
@ -349,24 +337,22 @@ create_class_table_sci11(state_t *s)
for (scriptnr = 0; scriptnr < 1000; scriptnr++) { for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
resource_t *heap = scir_find_resource(s->resmgr, sci_heap, resource_t *heap = scir_find_resource(s->resmgr, sci_heap,
scriptnr, 0); scriptnr, 0);
if (heap) { if (heap) {
int global_vars = getUInt16(heap->data + 2); int global_vars = getUInt16(heap->data + 2);
seeker_ptr = (char*)heap->data + 4 + global_vars*2; seeker_ptr = (char*)heap->data + 4 + global_vars * 2;
seeker_offset = 4 + global_vars*2; seeker_offset = 4 + global_vars * 2;
while (getUInt16((byte*)seeker_ptr) == SCRIPT_OBJECT_MAGIC_NUMBER) while (getUInt16((byte*)seeker_ptr) == SCRIPT_OBJECT_MAGIC_NUMBER) {
{ if (getUInt16((byte*)seeker_ptr + 14) & SCRIPT_INFO_CLASS) {
if (getUInt16((byte*)seeker_ptr + 14) & SCRIPT_INFO_CLASS)
{
classnr = getUInt16((byte*)seeker_ptr + 10); classnr = getUInt16((byte*)seeker_ptr + 10);
if (classnr >= s->classtable_size) { if (classnr >= s->classtable_size) {
if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) { if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
fprintf(stderr,"Invalid class number 0x%x in script.%d(0x%x), offset %04x\n", fprintf(stderr, "Invalid class number 0x%x in script.%d(0x%x), offset %04x\n",
classnr, scriptnr, scriptnr, seeker_offset); classnr, scriptnr, scriptnr, seeker_offset);
return 1; return 1;
} }
@ -376,7 +362,7 @@ create_class_table_sci11(state_t *s)
s->classtable_size = classnr + 1; /* Adjust maximum number of entries */ s->classtable_size = classnr + 1; /* Adjust maximum number of entries */
} }
s->classtable[classnr].reg.offset = seeker_offset; s->classtable[classnr].reg.offset = seeker_offset;
s->classtable[classnr].reg.segment = 0; s->classtable[classnr].reg.segment = 0;
s->classtable[classnr].script = scriptnr; s->classtable[classnr].script = scriptnr;
@ -391,8 +377,7 @@ create_class_table_sci11(state_t *s)
return 0; return 0;
} }
static int static int
create_class_table_sci0(state_t *s) create_class_table_sci0(state_t *s) {
{
int scriptnr; int scriptnr;
unsigned int seeker; unsigned int seeker;
int classnr; int classnr;
@ -410,7 +395,7 @@ create_class_table_sci0(state_t *s)
for (scriptnr = 0; scriptnr < 1000; scriptnr++) { for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
int objtype = 0; int objtype = 0;
resource_t *script = scir_find_resource(s->resmgr, sci_script, resource_t *script = scir_find_resource(s->resmgr, sci_script,
scriptnr, 0); scriptnr, 0);
if (script) { if (script) {
if (s->version < SCI_VERSION_FTU_NEW_SCRIPT_HEADER) if (s->version < SCI_VERSION_FTU_NEW_SCRIPT_HEADER)
@ -442,8 +427,8 @@ create_class_table_sci0(state_t *s)
if (classnr >= s->classtable_size) { if (classnr >= s->classtable_size) {
if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) { if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
fprintf(stderr,"Invalid class number 0x%x in script.%d(0x%x), offset %04x\n", fprintf(stderr, "Invalid class number 0x%x in script.%d(0x%x), offset %04x\n",
classnr, scriptnr, scriptnr, seeker); classnr, scriptnr, scriptnr, seeker);
return 1; return 1;
} }
@ -481,15 +466,14 @@ create_class_table_sci0(state_t *s)
/* Architectural stuff: Init/Unintialize engine */ /* Architectural stuff: Init/Unintialize engine */
int int
script_init_engine(state_t *s, sci_version_t version) script_init_engine(state_t *s, sci_version_t version) {
{
int result; int result;
s->max_version = SCI_VERSION(9,999,999); /* :-) */ s->max_version = SCI_VERSION(9, 999, 999); /* :-) */
s->min_version = 0; /* Set no real limits */ s->min_version = 0; /* Set no real limits */
s->version = SCI_VERSION_DEFAULT_SCI0; s->version = SCI_VERSION_DEFAULT_SCI0;
s->kernel_opt_flags = 0; s->kernel_opt_flags = 0;
if (!version) { if (!version) {
s->version_lock_flag = 0; s->version_lock_flag = 0;
} else { } else {
@ -499,16 +483,15 @@ script_init_engine(state_t *s, sci_version_t version)
script_detect_versions(s); script_detect_versions(s);
if (s->version >= SCI_VERSION(1,001,000)) if (s->version >= SCI_VERSION(1, 001, 000))
result = create_class_table_sci11(s); result = create_class_table_sci11(s);
else else
result = create_class_table_sci0(s); result = create_class_table_sci0(s);
sm_init(&s->seg_manager, s->version >= SCI_VERSION(1,001,000)); sm_init(&s->seg_manager, s->version >= SCI_VERSION(1, 001, 000));
s->gc_countdown = GC_INTERVAL - 1; s->gc_countdown = GC_INTERVAL - 1;
if (result) if (result) {
{
sciprintf("Failed to initialize class table\n"); sciprintf("Failed to initialize class table\n");
return 1; return 1;
} }
@ -524,7 +507,7 @@ script_init_engine(state_t *s, sci_version_t version)
s->sys_strings = sm_allocate_sys_strings(&s->seg_manager, s->sys_strings = sm_allocate_sys_strings(&s->seg_manager,
&s->sys_strings_segment); &s->sys_strings_segment);
/* Allocate static buffer for savegame and CWD directories */ /* Allocate static buffer for savegame and CWD directories */
sys_string_acquire(s->sys_strings, SYS_STRING_SAVEDIR, "savedir", MAX_SAVE_DIR_SIZE); sys_string_acquire(s->sys_strings, SYS_STRING_SAVEDIR, "savedir", MAX_SAVE_DIR_SIZE);
@ -561,7 +544,7 @@ script_init_engine(state_t *s, sci_version_t version)
/* Those two are used by FileIO for FIND_FIRST, FIND_NEXT */ /* Those two are used by FileIO for FIND_FIRST, FIND_NEXT */
if (s->version >= SCI_VERSION_FTU_LOFS_ABSOLUTE && if (s->version >= SCI_VERSION_FTU_LOFS_ABSOLUTE &&
s->version < SCI_VERSION(1,001,000)) s->version < SCI_VERSION(1, 001, 000))
sm_set_export_width(&s->seg_manager, 1); sm_set_export_width(&s->seg_manager, 1);
else else
sm_set_export_width(&s->seg_manager, 0); sm_set_export_width(&s->seg_manager, 0);
@ -576,14 +559,12 @@ script_init_engine(state_t *s, sci_version_t version)
void void
script_set_gamestate_save_dir(state_t *s, const char* path) script_set_gamestate_save_dir(state_t *s, const char* path) {
{
sys_string_set(s->sys_strings, SYS_STRING_SAVEDIR, path); sys_string_set(s->sys_strings, SYS_STRING_SAVEDIR, path);
} }
void void
script_free_vm_memory(state_t *s) script_free_vm_memory(state_t *s) {
{
int i; int i;
sciprintf("Freeing VM memory\n"); sciprintf("Freeing VM memory\n");
@ -605,12 +586,11 @@ script_free_vm_memory(state_t *s)
} }
extern void extern void
free_kfunct_tables(state_t *s); free_kfunct_tables(state_t *s);
/* From kernel.c */ /* From kernel.c */
void void
script_free_engine(state_t *s) script_free_engine(state_t *s) {
{
script_free_vm_memory(s); script_free_vm_memory(s);
sciprintf("Freeing state-dependant data\n"); sciprintf("Freeing state-dependant data\n");
@ -622,16 +602,15 @@ script_free_engine(state_t *s)
} }
void void
script_free_breakpoints(state_t *s) script_free_breakpoints(state_t *s) {
{
breakpoint_t *bp, *bp_next; breakpoint_t *bp, *bp_next;
/* Free breakpoint list */ /* Free breakpoint list */
bp = s->bp_list; bp = s->bp_list;
while (bp) { while (bp) {
bp_next = bp->next; bp_next = bp->next;
if (bp->type == BREAK_SELECTOR) sci_free (bp->data.name); if (bp->type == BREAK_SELECTOR) sci_free(bp->data.name);
free (bp); free(bp);
bp = bp_next; bp = bp_next;
} }
@ -644,8 +623,7 @@ script_free_breakpoints(state_t *s)
int int
game_init(state_t *s) game_init(state_t *s) {
{
#ifdef __GNUC__XX #ifdef __GNUC__XX
# warning "Fixme: Use new VM instantiation code all over the place" # warning "Fixme: Use new VM instantiation code all over the place"
#endif #endif
@ -653,7 +631,7 @@ game_init(state_t *s)
dstack_t *stack; dstack_t *stack;
stack = sm_allocate_stack(&s->seg_manager, VM_STACK_SIZE, stack = sm_allocate_stack(&s->seg_manager, VM_STACK_SIZE,
&s->stack_segment); &s->stack_segment);
s->stack_base = stack->entries; s->stack_base = stack->entries;
s->stack_top = s->stack_base + VM_STACK_SIZE; s->stack_top = s->stack_base + VM_STACK_SIZE;
@ -701,8 +679,8 @@ game_init(state_t *s)
if (!s->game_name) { if (!s->game_name) {
sciprintf("Error: script.000, export 0 ("PREG") does not\n" sciprintf("Error: script.000, export 0 ("PREG") does not\n"
" yield an object with a name -> sanity check failed\n", " yield an object with a name -> sanity check failed\n",
PRINT_REG(game_obj)); PRINT_REG(game_obj));
return 1; return 1;
} }
@ -726,18 +704,17 @@ game_init(state_t *s)
} }
int int
game_exit(state_t *s) game_exit(state_t *s) {
{
if (s->execution_stack) { if (s->execution_stack) {
sci_free(s->execution_stack); sci_free(s->execution_stack);
} }
sfx_exit(&s->sound); sfx_exit(&s->sound);
/* Reinit because some other code depends on having a valid state */ /* Reinit because some other code depends on having a valid state */
game_init_sound(s, SFX_STATE_FLAG_NOSOUND); game_init_sound(s, SFX_STATE_FLAG_NOSOUND);
sm_destroy(&s->seg_manager); sm_destroy(&s->seg_manager);
if (s->synonyms_nr) { if (s->synonyms_nr) {
sci_free(s->synonyms); sci_free(s->synonyms);
s->synonyms = NULL; s->synonyms = NULL;

View file

@ -32,8 +32,7 @@ typedef struct _worklist {
} worklist_t; } worklist_t;
static worklist_t * static worklist_t *
fresh_worklist(worklist_t *old) fresh_worklist(worklist_t *old) {
{
worklist_t *retval = (worklist_t*)sci_malloc(sizeof(worklist_t)); worklist_t *retval = (worklist_t*)sci_malloc(sizeof(worklist_t));
retval->used = 0; retval->used = 0;
retval->next = old; retval->next = old;
@ -41,14 +40,12 @@ fresh_worklist(worklist_t *old)
} }
static worklist_t * static worklist_t *
new_worklist() new_worklist() {
{
return fresh_worklist(NULL); return fresh_worklist(NULL);
} }
static void static void
worklist_push(worklist_t **wlp, reg_t_hash_map_ptr hashmap, reg_t reg) worklist_push(worklist_t **wlp, reg_t_hash_map_ptr hashmap, reg_t reg) {
{
worklist_t *wl = *wlp; worklist_t *wl = *wlp;
char added; char added;
@ -71,14 +68,12 @@ worklist_push(worklist_t **wlp, reg_t_hash_map_ptr hashmap, reg_t reg)
} }
static int static int
worklist_has_next(worklist_t *wl) worklist_has_next(worklist_t *wl) {
{
return (wl && wl->used); return (wl && wl->used);
} }
static reg_t static reg_t
worklist_pop(worklist_t **wlp) worklist_pop(worklist_t **wlp) {
{
worklist_t *wl = *wlp; worklist_t *wl = *wlp;
reg_t retval; reg_t retval;
@ -98,8 +93,7 @@ worklist_pop(worklist_t **wlp)
} }
static void static void
free_worklist(worklist_t *wl) free_worklist(worklist_t *wl) {
{
if (wl) { if (wl) {
if (wl->next) if (wl->next)
free_worklist(wl->next); free_worklist(wl->next);
@ -114,13 +108,12 @@ typedef struct {
} normaliser_t; } normaliser_t;
void void
store_normalised(void *pre_normaliser, reg_t reg, int _) store_normalised(void *pre_normaliser, reg_t reg, int _) {
{
seg_interface_t *interfce; seg_interface_t *interfce;
normaliser_t *normaliser = (normaliser_t *) pre_normaliser; normaliser_t *normaliser = (normaliser_t *) pre_normaliser;
interfce = (reg.segment < normaliser->interfaces_nr) interfce = (reg.segment < normaliser->interfaces_nr)
? normaliser->interfaces[reg.segment] ? normaliser->interfaces[reg.segment]
: NULL; : NULL;
if (interfce) { if (interfce) {
reg = interfce->find_canonic_address(interfce, reg); reg = interfce->find_canonic_address(interfce, reg);
@ -129,8 +122,7 @@ store_normalised(void *pre_normaliser, reg_t reg, int _)
} }
static reg_t_hash_map_ptr static reg_t_hash_map_ptr
normalise_hashmap_ptrs(reg_t_hash_map_ptr nonnormal_map, seg_interface_t **interfaces, int interfaces_nr) normalise_hashmap_ptrs(reg_t_hash_map_ptr nonnormal_map, seg_interface_t **interfaces, int interfaces_nr) {
{
normaliser_t normaliser; normaliser_t normaliser;
normaliser.normal_map = new_reg_t_hash_map(); normaliser.normal_map = new_reg_t_hash_map();
@ -148,15 +140,13 @@ typedef struct {
} worklist_manager_t; } worklist_manager_t;
void void
add_outgoing_refs(void *pre_wm, reg_t addr) add_outgoing_refs(void *pre_wm, reg_t addr) {
{
worklist_manager_t *wm = (worklist_manager_t *) pre_wm; worklist_manager_t *wm = (worklist_manager_t *) pre_wm;
worklist_push(wm->worklist_ref, wm->nonnormal_map, addr); worklist_push(wm->worklist_ref, wm->nonnormal_map, addr);
} }
reg_t_hash_map_ptr reg_t_hash_map_ptr
find_all_used_references(state_t *s) find_all_used_references(state_t *s) {
{
seg_manager_t *sm = &(s->seg_manager); seg_manager_t *sm = &(s->seg_manager);
seg_interface_t **interfaces = (seg_interface_t**)sci_calloc(sizeof(seg_interface_t *), sm->heap_size); seg_interface_t **interfaces = (seg_interface_t**)sci_calloc(sizeof(seg_interface_t *), sm->heap_size);
reg_t_hash_map_ptr nonnormal_map = new_reg_t_hash_map(); reg_t_hash_map_ptr nonnormal_map = new_reg_t_hash_map();
@ -210,7 +200,7 @@ find_all_used_references(state_t *s)
/* Init: Explicitly loaded scripts */ /* Init: Explicitly loaded scripts */
for (i = 1; i < sm->heap_size; i++) for (i = 1; i < sm->heap_size; i++)
if (interfaces[i] if (interfaces[i]
&& interfaces[i]->type_id == MEM_OBJ_SCRIPT) { && interfaces[i]->type_id == MEM_OBJ_SCRIPT) {
script_t *script = &(interfaces[i]->mobj->data.script); script_t *script = &(interfaces[i]->mobj->data.script);
if (script->lockers) { /* Explicitly loaded? */ if (script->lockers) { /* Explicitly loaded? */
@ -223,8 +213,8 @@ find_all_used_references(state_t *s)
for (obj_nr = 0; obj_nr < script->objects_nr; obj_nr++) { for (obj_nr = 0; obj_nr < script->objects_nr; obj_nr++) {
object_t *obj = script->objects + obj_nr; object_t *obj = script->objects + obj_nr;
worklist_push(&worklist, worklist_push(&worklist,
nonnormal_map, nonnormal_map,
obj->pos); obj->pos);
} }
} }
} }
@ -238,15 +228,15 @@ find_all_used_references(state_t *s)
reg_t reg = worklist_pop(&worklist); reg_t reg = worklist_pop(&worklist);
if (reg.segment != s->stack_segment) { /* No need to repeat this one */ if (reg.segment != s->stack_segment) { /* No need to repeat this one */
#ifdef DEBUG_GC_VERBOSE #ifdef DEBUG_GC_VERBOSE
sciprintf("[GC] Checking "PREG"\n", PRINT_REG(reg)); sciprintf("[GC] Checking "PREG"\n", PRINT_REG(reg));
#endif #endif
if (reg.segment < sm->heap_size if (reg.segment < sm->heap_size
&& interfaces[reg.segment]) && interfaces[reg.segment])
interfaces[reg.segment]->list_all_outgoing_references(interfaces[reg.segment], interfaces[reg.segment]->list_all_outgoing_references(interfaces[reg.segment],
s, s,
reg, reg,
&worklist_manager, &worklist_manager,
add_outgoing_refs); add_outgoing_refs);
} }
} }
@ -273,8 +263,7 @@ typedef struct {
} deallocator_t; } deallocator_t;
void void
free_unless_used (void *pre_use_map, reg_t addr) free_unless_used(void *pre_use_map, reg_t addr) {
{
deallocator_t *deallocator = (deallocator_t *) pre_use_map; deallocator_t *deallocator = (deallocator_t *) pre_use_map;
reg_t_hash_map_ptr use_map = deallocator->use_map; reg_t_hash_map_ptr use_map = deallocator->use_map;
@ -290,8 +279,7 @@ free_unless_used (void *pre_use_map, reg_t addr)
} }
void void
run_gc(state_t *s) run_gc(state_t *s) {
{
int seg_nr; int seg_nr;
deallocator_t deallocator; deallocator_t deallocator;
seg_manager_t *sm = &(s->seg_manager); seg_manager_t *sm = &(s->seg_manager);
@ -312,8 +300,8 @@ run_gc(state_t *s)
#endif #endif
deallocator.interfce->list_all_deallocatable(deallocator.interfce, deallocator.interfce->list_all_deallocatable(deallocator.interfce,
&deallocator, &deallocator,
free_unless_used); free_unless_used);
deallocator.interfce->deallocate_self(deallocator.interfce); deallocator.interfce->deallocate_self(deallocator.interfce);
} }
@ -327,8 +315,8 @@ run_gc(state_t *s)
for (i = 0; i <= MEM_OBJ_MAX; i++) for (i = 0; i <= MEM_OBJ_MAX; i++)
if (deallocator.segcount[i]) if (deallocator.segcount[i])
sciprintf("\t%d\t* %s\n", sciprintf("\t%d\t* %s\n",
deallocator.segcount[i], deallocator.segcount[i],
deallocator.segnames[i]); deallocator.segnames[i]);
} }
#endif #endif
} }

View file

@ -37,221 +37,213 @@
#define TOKEN_NON_NT (TOKEN_OPAREN | TOKEN_TERMINAL_CLASS | TOKEN_TERMINAL_GROUP | TOKEN_STUFFING_WORD) #define TOKEN_NON_NT (TOKEN_OPAREN | TOKEN_TERMINAL_CLASS | TOKEN_TERMINAL_GROUP | TOKEN_STUFFING_WORD)
#define TOKEN_TERMINAL (TOKEN_TERMINAL_CLASS | TOKEN_TERMINAL_GROUP) #define TOKEN_TERMINAL (TOKEN_TERMINAL_CLASS | TOKEN_TERMINAL_GROUP)
int _allocd_rules = 0; int _allocd_rules = 0;
static void static void
vocab_print_rule(parse_rule_t *rule) vocab_print_rule(parse_rule_t *rule) {
{ int i;
int i; int wspace = 0;
int wspace = 0;
if (!rule) { if (!rule) {
sciprintf("NULL rule"); sciprintf("NULL rule");
return; return;
} }
sciprintf("[%03x] -> ", rule->id); sciprintf("[%03x] -> ", rule->id);
if (!rule->length) if (!rule->length)
sciprintf("e"); sciprintf("e");
for(i = 0; i < rule->length; i++) { for (i = 0; i < rule->length; i++) {
uint token = rule->data[i]; uint token = rule->data[i];
if (token == TOKEN_OPAREN) { if (token == TOKEN_OPAREN) {
if (i == rule->first_special) if (i == rule->first_special)
sciprintf("_"); sciprintf("_");
sciprintf("("); sciprintf("(");
wspace = 0; wspace = 0;
} else if (token == TOKEN_CPAREN) { } else if (token == TOKEN_CPAREN) {
if (i == rule->first_special) if (i == rule->first_special)
sciprintf("_"); sciprintf("_");
sciprintf(")"); sciprintf(")");
wspace = 0; wspace = 0;
} else { } else {
if (wspace) if (wspace)
sciprintf(" "); sciprintf(" ");
if (i == rule->first_special) if (i == rule->first_special)
sciprintf("_"); sciprintf("_");
if (token & TOKEN_TERMINAL_CLASS) if (token & TOKEN_TERMINAL_CLASS)
sciprintf("C(%04x)", token & 0xffff); sciprintf("C(%04x)", token & 0xffff);
else if (token & TOKEN_TERMINAL_GROUP) else if (token & TOKEN_TERMINAL_GROUP)
sciprintf("G(%04x)", token & 0xffff); sciprintf("G(%04x)", token & 0xffff);
else if (token & TOKEN_STUFFING_WORD) else if (token & TOKEN_STUFFING_WORD)
sciprintf("%03x", token & 0xffff); sciprintf("%03x", token & 0xffff);
else else
sciprintf("[%03x]", token); /* non-terminal */ sciprintf("[%03x]", token); /* non-terminal */
wspace = 1; wspace = 1;
} }
if (i == rule->first_special) if (i == rule->first_special)
sciprintf("_"); sciprintf("_");
} }
sciprintf(" [%d specials]", rule->specials_nr); sciprintf(" [%d specials]", rule->specials_nr);
} }
static void static void
_vfree(parse_rule_t *rule) _vfree(parse_rule_t *rule) {
{ free(rule);
free(rule); --_allocd_rules;
--_allocd_rules; rule = NULL;
rule = NULL;
} }
static parse_rule_t * static parse_rule_t *
_vdup(parse_rule_t *a) _vdup(parse_rule_t *a) {
{ parse_rule_t *rule = (parse_rule_t*)sci_malloc(sizeof(int) * (a->length + 4));
parse_rule_t *rule = (parse_rule_t*)sci_malloc(sizeof(int) * (a->length + 4));
rule->id = a->id; rule->id = a->id;
rule->length = a->length; rule->length = a->length;
rule->specials_nr = a->specials_nr; rule->specials_nr = a->specials_nr;
rule->first_special = a->first_special; rule->first_special = a->first_special;
++_allocd_rules; ++_allocd_rules;
memcpy(rule->data, a->data, sizeof(int) * a->length); memcpy(rule->data, a->data, sizeof(int) * a->length);
return rule; return rule;
} }
static parse_rule_t * static parse_rule_t *
_vinsert(parse_rule_t *turkey, parse_rule_t *stuffing) _vinsert(parse_rule_t *turkey, parse_rule_t *stuffing) {
{ int firstnt = turkey->first_special;
int firstnt = turkey->first_special; parse_rule_t *rule;
parse_rule_t *rule;
while ((firstnt < turkey->length) while ((firstnt < turkey->length)
&& (turkey->data[firstnt] & TOKEN_NON_NT)) && (turkey->data[firstnt] & TOKEN_NON_NT))
firstnt++; firstnt++;
if ((firstnt == turkey->length) if ((firstnt == turkey->length)
|| (turkey->data[firstnt] != stuffing->id)) || (turkey->data[firstnt] != stuffing->id))
return NULL; return NULL;
rule = (parse_rule_t*)sci_malloc(sizeof(int) * (turkey->length - 1 + stuffing->length + 4)); rule = (parse_rule_t*)sci_malloc(sizeof(int) * (turkey->length - 1 + stuffing->length + 4));
rule->id = turkey->id; rule->id = turkey->id;
rule->specials_nr = turkey->specials_nr + stuffing->specials_nr - 1; rule->specials_nr = turkey->specials_nr + stuffing->specials_nr - 1;
rule->first_special = firstnt + stuffing->first_special; rule->first_special = firstnt + stuffing->first_special;
rule->length = turkey->length - 1 + stuffing->length; rule->length = turkey->length - 1 + stuffing->length;
++_allocd_rules; ++_allocd_rules;
if (firstnt > 0) if (firstnt > 0)
memcpy(rule->data, turkey->data, sizeof(int) * firstnt); memcpy(rule->data, turkey->data, sizeof(int) * firstnt);
memcpy(&(rule->data[firstnt]), stuffing->data, sizeof(int) * stuffing->length); memcpy(&(rule->data[firstnt]), stuffing->data, sizeof(int) * stuffing->length);
if (firstnt < turkey->length - 1) if (firstnt < turkey->length - 1)
memcpy(&(rule->data[firstnt + stuffing->length]), &(turkey->data[firstnt + 1]), memcpy(&(rule->data[firstnt + stuffing->length]), &(turkey->data[firstnt + 1]),
sizeof(int) * (turkey->length - firstnt - 1)); sizeof(int) * (turkey->length - firstnt - 1));
return rule; return rule;
} }
static parse_rule_t * static parse_rule_t *
_vbuild_rule(parse_tree_branch_t *branch) _vbuild_rule(parse_tree_branch_t *branch) {
{ parse_rule_t *rule;
parse_rule_t *rule; int tokens = 0, tokenpos = 0, i;
int tokens = 0, tokenpos = 0, i;
while (tokenpos < 10 && branch->data[tokenpos]) { while (tokenpos < 10 && branch->data[tokenpos]) {
int type = branch->data[tokenpos]; int type = branch->data[tokenpos];
tokenpos += 2; tokenpos += 2;
if ((type == VOCAB_TREE_NODE_COMPARE_TYPE) if ((type == VOCAB_TREE_NODE_COMPARE_TYPE)
|| (type == VOCAB_TREE_NODE_COMPARE_GROUP) || (type == VOCAB_TREE_NODE_COMPARE_GROUP)
|| (type == VOCAB_TREE_NODE_FORCE_STORAGE)) || (type == VOCAB_TREE_NODE_FORCE_STORAGE))
++tokens; ++tokens;
else if (type > VOCAB_TREE_NODE_LAST_WORD_STORAGE) else if (type > VOCAB_TREE_NODE_LAST_WORD_STORAGE)
tokens += 5; tokens += 5;
else return NULL; /* invalid */ else return NULL; /* invalid */
} }
rule = (parse_rule_t*)sci_malloc(sizeof(int) * (4 + tokens)); rule = (parse_rule_t*)sci_malloc(sizeof(int) * (4 + tokens));
++_allocd_rules; ++_allocd_rules;
rule->id = branch->id; rule->id = branch->id;
rule->specials_nr = tokenpos >> 1; rule->specials_nr = tokenpos >> 1;
rule->length = tokens; rule->length = tokens;
rule->first_special = 0; rule->first_special = 0;
tokens = 0; tokens = 0;
for (i = 0; i < tokenpos; i += 2) { for (i = 0; i < tokenpos; i += 2) {
int type = branch->data[i]; int type = branch->data[i];
int value = branch->data[i + 1]; int value = branch->data[i + 1];
if (type == VOCAB_TREE_NODE_COMPARE_TYPE) if (type == VOCAB_TREE_NODE_COMPARE_TYPE)
rule->data[tokens++] = value | TOKEN_TERMINAL_CLASS; rule->data[tokens++] = value | TOKEN_TERMINAL_CLASS;
else if (type == VOCAB_TREE_NODE_COMPARE_GROUP) else if (type == VOCAB_TREE_NODE_COMPARE_GROUP)
rule->data[tokens++] = value | TOKEN_TERMINAL_GROUP; rule->data[tokens++] = value | TOKEN_TERMINAL_GROUP;
else if (type == VOCAB_TREE_NODE_FORCE_STORAGE) else if (type == VOCAB_TREE_NODE_FORCE_STORAGE)
rule->data[tokens++] = value | TOKEN_STUFFING_WORD; rule->data[tokens++] = value | TOKEN_STUFFING_WORD;
else { /* normal inductive rule */ else { /* normal inductive rule */
rule->data[tokens++] = TOKEN_OPAREN; rule->data[tokens++] = TOKEN_OPAREN;
rule->data[tokens++] = type | TOKEN_STUFFING_WORD; rule->data[tokens++] = type | TOKEN_STUFFING_WORD;
rule->data[tokens++] = value | TOKEN_STUFFING_WORD; rule->data[tokens++] = value | TOKEN_STUFFING_WORD;
if (i == 0) if (i == 0)
rule->first_special = tokens; rule->first_special = tokens;
rule->data[tokens++] = value; /* The non-terminal */ rule->data[tokens++] = value; /* The non-terminal */
rule->data[tokens++] = TOKEN_CPAREN; rule->data[tokens++] = TOKEN_CPAREN;
} }
} }
return rule; return rule;
} }
static parse_rule_t * static parse_rule_t *
_vsatisfy_rule(parse_rule_t *rule, result_word_t *input) _vsatisfy_rule(parse_rule_t *rule, result_word_t *input) {
{ int dep;
int dep;
if (!rule->specials_nr) if (!rule->specials_nr)
return NULL; return NULL;
dep = rule->data[rule->first_special]; dep = rule->data[rule->first_special];
if (((dep & TOKEN_TERMINAL_CLASS) if (((dep & TOKEN_TERMINAL_CLASS)
&& ((dep & 0xffff) & input->w_class)) && ((dep & 0xffff) & input->w_class))
|| ||
((dep & TOKEN_TERMINAL_GROUP) ((dep & TOKEN_TERMINAL_GROUP)
&& ((dep & 0xffff) & input->group))) { && ((dep & 0xffff) & input->group))) {
parse_rule_t *retval = (parse_rule_t*)sci_malloc(sizeof(int) * (4 + rule->length)); parse_rule_t *retval = (parse_rule_t*)sci_malloc(sizeof(int) * (4 + rule->length));
++_allocd_rules; ++_allocd_rules;
retval->id = rule->id; retval->id = rule->id;
retval->specials_nr = rule->specials_nr - 1; retval->specials_nr = rule->specials_nr - 1;
retval->length = rule->length; retval->length = rule->length;
memcpy(retval->data, rule->data, sizeof(int) * retval->length); memcpy(retval->data, rule->data, sizeof(int) * retval->length);
retval->data[rule->first_special] = TOKEN_STUFFING_WORD | input->group; retval->data[rule->first_special] = TOKEN_STUFFING_WORD | input->group;
retval->first_special = 0; retval->first_special = 0;
if (retval->specials_nr) { /* find first special, if it exists */ if (retval->specials_nr) { /* find first special, if it exists */
int tmp, i = rule->first_special; int tmp, i = rule->first_special;
while ((i < rule->length) while ((i < rule->length)
&& ((tmp = retval->data[i]) & TOKEN_NON_NT) && ((tmp = retval->data[i]) & TOKEN_NON_NT)
&& !(tmp & TOKEN_TERMINAL)) && !(tmp & TOKEN_TERMINAL))
++i; ++i;
if (i < rule->length) if (i < rule->length)
retval->first_special = i; retval->first_special = i;
} }
return retval; return retval;
} } else return NULL;
else return NULL;
} }
/************** Rule lists **************/ /************** Rule lists **************/
void void
vocab_free_rule_list(parse_rule_list_t *list) vocab_free_rule_list(parse_rule_list_t *list) {
{
if (list) { if (list) {
_vfree(list->rule); _vfree(list->rule);
vocab_free_rule_list(list->next); /* Yep, this is slow and memory-intensive. */ vocab_free_rule_list(list->next); /* Yep, this is slow and memory-intensive. */
@ -260,19 +252,17 @@ vocab_free_rule_list(parse_rule_list_t *list)
} }
static inline int static inline int
_rules_equal_p(parse_rule_t *r1, parse_rule_t *r2) _rules_equal_p(parse_rule_t *r1, parse_rule_t *r2) {
{
if ((r1->id != r2->id) if ((r1->id != r2->id)
|| (r1->length != r2->length) || (r1->length != r2->length)
|| (r1->first_special != r2->first_special)) || (r1->first_special != r2->first_special))
return 0; return 0;
return !(memcmp(r1->data, r2->data, sizeof(int) * r1->length)); return !(memcmp(r1->data, r2->data, sizeof(int) * r1->length));
} }
static parse_rule_list_t * static parse_rule_list_t *
_vocab_add_rule(parse_rule_list_t *list, parse_rule_t *rule) _vocab_add_rule(parse_rule_list_t *list, parse_rule_t *rule) {
{
parse_rule_list_t *new_elem; parse_rule_list_t *new_elem;
int term; int term;
@ -284,7 +274,7 @@ _vocab_add_rule(parse_rule_list_t *list, parse_rule_t *rule)
new_elem->rule = rule; new_elem->rule = rule;
new_elem->next = NULL; new_elem->next = NULL;
new_elem->terminal = term = ((term & TOKEN_TERMINAL)? term : 0); new_elem->terminal = term = ((term & TOKEN_TERMINAL) ? term : 0);
if (!list) if (!list)
return new_elem; return new_elem;
@ -311,39 +301,34 @@ _vocab_add_rule(parse_rule_list_t *list, parse_rule_t *rule)
} }
static void static void
_vprl(parse_rule_list_t *list, int pos) _vprl(parse_rule_list_t *list, int pos) {
{
if (list) { if (list) {
sciprintf("R%03d: ", pos); sciprintf("R%03d: ", pos);
vocab_print_rule(list->rule); vocab_print_rule(list->rule);
sciprintf("\n"); sciprintf("\n");
_vprl(list->next, pos+1); _vprl(list->next, pos + 1);
} else { } else {
sciprintf("%d rules total.\n", pos); sciprintf("%d rules total.\n", pos);
} }
} }
void void
vocab_print_rule_list(parse_rule_list_t *list) vocab_print_rule_list(parse_rule_list_t *list) {
{
_vprl(list, 0); _vprl(list, 0);
} }
static parse_rule_list_t * static parse_rule_list_t *
_vocab_split_rule_list(parse_rule_list_t *list) _vocab_split_rule_list(parse_rule_list_t *list) {
{
if (!list->next if (!list->next
|| (list->next->terminal)) { || (list->next->terminal)) {
parse_rule_list_t *tmp = list->next; parse_rule_list_t *tmp = list->next;
list->next = NULL; list->next = NULL;
return tmp; return tmp;
} } else return _vocab_split_rule_list(list->next);
else return _vocab_split_rule_list(list->next);
} }
static void static void
_vocab_free_empty_rule_list(parse_rule_list_t *list) _vocab_free_empty_rule_list(parse_rule_list_t *list) {
{
if (list->next) if (list->next)
_vocab_free_empty_rule_list(list->next); _vocab_free_empty_rule_list(list->next);
@ -351,8 +336,7 @@ _vocab_free_empty_rule_list(parse_rule_list_t *list)
} }
static parse_rule_list_t * static parse_rule_list_t *
_vocab_merge_rule_lists(parse_rule_list_t *l1, parse_rule_list_t *l2) _vocab_merge_rule_lists(parse_rule_list_t *l1, parse_rule_list_t *l2) {
{
parse_rule_list_t *retval = l1, *seeker = l2; parse_rule_list_t *retval = l1, *seeker = l2;
while (seeker) { while (seeker) {
retval = _vocab_add_rule(retval, seeker->rule); retval = _vocab_add_rule(retval, seeker->rule);
@ -364,15 +348,13 @@ _vocab_merge_rule_lists(parse_rule_list_t *l1, parse_rule_list_t *l2)
} }
static int static int
_vocab_rule_list_length(parse_rule_list_t *list) _vocab_rule_list_length(parse_rule_list_t *list) {
{ return ((list) ? _vocab_rule_list_length(list->next) + 1 : 0);
return ((list)? _vocab_rule_list_length(list->next) + 1 : 0);
} }
static parse_rule_list_t * static parse_rule_list_t *
_vocab_clone_rule_list_by_id(parse_rule_list_t *list, int id) _vocab_clone_rule_list_by_id(parse_rule_list_t *list, int id) {
{
parse_rule_list_t *result = NULL; parse_rule_list_t *result = NULL;
parse_rule_list_t *seeker = list; parse_rule_list_t *seeker = list;
@ -388,8 +370,7 @@ _vocab_clone_rule_list_by_id(parse_rule_list_t *list, int id)
parse_rule_list_t * parse_rule_list_t *
_vocab_build_gnf(parse_tree_branch_t *branches, int branches_nr, int verbose) _vocab_build_gnf(parse_tree_branch_t *branches, int branches_nr, int verbose) {
{
int i; int i;
int iterations = 0; int iterations = 0;
int last_termrules, termrules = 0; int last_termrules, termrules = 0;
@ -453,27 +434,24 @@ _vocab_build_gnf(parse_tree_branch_t *branches, int branches_nr, int verbose)
} }
parse_rule_list_t * parse_rule_list_t *
vocab_build_gnf(parse_tree_branch_t *branches, int branches_nr) vocab_build_gnf(parse_tree_branch_t *branches, int branches_nr) {
{ return _vocab_build_gnf(branches, branches_nr, 0);
return _vocab_build_gnf(branches, branches_nr, 0);
} }
void void
vocab_gnf_dump(parse_tree_branch_t *branches, int branches_nr) vocab_gnf_dump(parse_tree_branch_t *branches, int branches_nr) {
{ parse_rule_list_t *tlist = _vocab_build_gnf(branches, branches_nr, 1);
parse_rule_list_t *tlist = _vocab_build_gnf(branches, branches_nr, 1);
sciprintf("%d allocd rules\n", _allocd_rules); sciprintf("%d allocd rules\n", _allocd_rules);
vocab_free_rule_list(tlist); vocab_free_rule_list(tlist);
} }
int int
vocab_build_parse_tree(parse_tree_node_t *nodes, result_word_t *words, int words_nr, vocab_build_parse_tree(parse_tree_node_t *nodes, result_word_t *words, int words_nr,
parse_tree_branch_t *branch0, parse_rule_list_t *rules) parse_tree_branch_t *branch0, parse_rule_list_t *rules) {
{ return vocab_gnf_parse(nodes, words, words_nr, branch0, rules, 0);
return vocab_gnf_parse(nodes, words, words_nr, branch0, rules, 0);
} }
@ -481,11 +459,11 @@ static int
_vbpt_pareno(parse_tree_node_t *nodes, int *pos, int base) _vbpt_pareno(parse_tree_node_t *nodes, int *pos, int base)
/* Opens parentheses */ /* Opens parentheses */
{ {
nodes[base].content.branches[0] = (*pos)+1; nodes[base].content.branches[0] = (*pos) + 1;
nodes[++(*pos)].type = PARSE_TREE_NODE_BRANCH; nodes[++(*pos)].type = PARSE_TREE_NODE_BRANCH;
nodes[*pos].content.branches[0] = 0; nodes[*pos].content.branches[0] = 0;
nodes[*pos].content.branches[1] = 0; nodes[*pos].content.branches[1] = 0;
return *pos; return *pos;
} }
@ -493,11 +471,11 @@ static int
_vbpt_parenc(parse_tree_node_t *nodes, int *pos, int paren) _vbpt_parenc(parse_tree_node_t *nodes, int *pos, int paren)
/* Closes parentheses for appending */ /* Closes parentheses for appending */
{ {
nodes[paren].content.branches[1] = ++(*pos); nodes[paren].content.branches[1] = ++(*pos);
nodes[*pos].type = PARSE_TREE_NODE_BRANCH; nodes[*pos].type = PARSE_TREE_NODE_BRANCH;
nodes[*pos].content.branches[0] = 0; nodes[*pos].content.branches[0] = 0;
nodes[*pos].content.branches[1] = 0; nodes[*pos].content.branches[1] = 0;
return *pos; return *pos;
} }
@ -505,154 +483,152 @@ static int
_vbpt_append(parse_tree_node_t *nodes, int *pos, int base, int value) _vbpt_append(parse_tree_node_t *nodes, int *pos, int base, int value)
/* writes one value to an existing base node and creates a successor node for writing */ /* writes one value to an existing base node and creates a successor node for writing */
{ {
nodes[base].content.branches[0] = ++(*pos); nodes[base].content.branches[0] = ++(*pos);
nodes[*pos].type = PARSE_TREE_NODE_LEAF; nodes[*pos].type = PARSE_TREE_NODE_LEAF;
nodes[*pos].content.value = value; nodes[*pos].content.value = value;
nodes[base].content.branches[1] = ++(*pos); nodes[base].content.branches[1] = ++(*pos);
nodes[*pos].type = PARSE_TREE_NODE_BRANCH; nodes[*pos].type = PARSE_TREE_NODE_BRANCH;
nodes[*pos].content.branches[0] = 0; nodes[*pos].content.branches[0] = 0;
nodes[*pos].content.branches[1] = 0; nodes[*pos].content.branches[1] = 0;
return *pos; return *pos;
} }
static int static int
_vbpt_terminate(parse_tree_node_t *nodes, int *pos, int base, int value) _vbpt_terminate(parse_tree_node_t *nodes, int *pos, int base, int value)
/* Terminates, overwriting a nextwrite forknode */ /* Terminates, overwriting a nextwrite forknode */
{ {
nodes[base].type = PARSE_TREE_NODE_LEAF; nodes[base].type = PARSE_TREE_NODE_LEAF;
nodes[base].content.value = value; nodes[base].content.value = value;
return *pos; return *pos;
} }
static int static int
_vbpt_write_subexpression(parse_tree_node_t *nodes, int *pos, _vbpt_write_subexpression(parse_tree_node_t *nodes, int *pos,
parse_rule_t *rule, int rulepos, int writepos) parse_rule_t *rule, int rulepos, int writepos) {
{ uint token;
uint token; while ((token = ((rulepos < rule->length) ? rule->data[rulepos++] : TOKEN_CPAREN)) != TOKEN_CPAREN) {
while ((token = ((rulepos < rule->length)? rule->data[rulepos++] : TOKEN_CPAREN)) != TOKEN_CPAREN) { uint nexttoken = (rulepos < rule->length) ? rule->data[rulepos] : TOKEN_CPAREN;
uint nexttoken = (rulepos < rule->length)? rule->data[rulepos] : TOKEN_CPAREN; if (token == TOKEN_OPAREN) {
if (token == TOKEN_OPAREN) { int wpold;
int wpold; int writepos2 = _vbpt_pareno(nodes, pos, wpold = writepos);
int writepos2 = _vbpt_pareno(nodes, pos, wpold = writepos); rulepos = _vbpt_write_subexpression(nodes, pos, rule, rulepos, writepos2);
rulepos = _vbpt_write_subexpression(nodes, pos, rule, rulepos, writepos2); nexttoken = (rulepos < rule->length) ? rule->data[rulepos] : TOKEN_CPAREN;
nexttoken = (rulepos < rule->length)? rule->data[rulepos] : TOKEN_CPAREN; if (nexttoken != TOKEN_CPAREN)
if (nexttoken != TOKEN_CPAREN) writepos = _vbpt_parenc(nodes, pos, wpold);
writepos = _vbpt_parenc(nodes, pos, wpold); } else if (token & TOKEN_STUFFING_WORD) {
} else if (token & TOKEN_STUFFING_WORD) { if (nexttoken == TOKEN_CPAREN)
if (nexttoken == TOKEN_CPAREN) writepos = _vbpt_terminate(nodes, pos, writepos, token & 0xffff);
writepos = _vbpt_terminate(nodes, pos, writepos, token & 0xffff); else
else writepos = _vbpt_append(nodes, pos, writepos, token & 0xffff);
writepos = _vbpt_append(nodes, pos, writepos, token & 0xffff); } else {
} else { sciprintf("\nError in parser (grammar.c, _vbpt_write_subexpression()): Rule data broken in rule ");
sciprintf("\nError in parser (grammar.c, _vbpt_write_subexpression()): Rule data broken in rule "); vocab_print_rule(rule);
vocab_print_rule(rule); sciprintf(", at token position %d\n", *pos);
sciprintf(", at token position %d\n", *pos); return rulepos;
return rulepos; }
} }
}
return rulepos; return rulepos;
} }
int int
vocab_gnf_parse(parse_tree_node_t *nodes, result_word_t *words, int words_nr, vocab_gnf_parse(parse_tree_node_t *nodes, result_word_t *words, int words_nr,
parse_tree_branch_t *branch0, parse_rule_list_t *tlist, int verbose) parse_tree_branch_t *branch0, parse_rule_list_t *tlist, int verbose) {
{ /* Get the start rules: */
/* Get the start rules: */ parse_rule_list_t *work = _vocab_clone_rule_list_by_id(tlist, branch0->data[1]);
parse_rule_list_t *work = _vocab_clone_rule_list_by_id(tlist, branch0->data[1]); parse_rule_list_t *results = NULL;
parse_rule_list_t *results = NULL; int word;
int word;
for (word = 0; word < words_nr; word++) { for (word = 0; word < words_nr; word++) {
parse_rule_list_t *new_work = NULL; parse_rule_list_t *new_work = NULL;
parse_rule_list_t *reduced_rules = NULL; parse_rule_list_t *reduced_rules = NULL;
parse_rule_list_t *seeker, *subseeker; parse_rule_list_t *seeker, *subseeker;
if (verbose) if (verbose)
sciprintf("Adding word %d...\n", word); sciprintf("Adding word %d...\n", word);
seeker = work; seeker = work;
while (seeker) { while (seeker) {
if (seeker->rule->specials_nr <= (words_nr - word)) if (seeker->rule->specials_nr <= (words_nr - word))
reduced_rules = _vocab_add_rule(reduced_rules, _vsatisfy_rule(seeker->rule, words + word)); reduced_rules = _vocab_add_rule(reduced_rules, _vsatisfy_rule(seeker->rule, words + word));
seeker = seeker->next; seeker = seeker->next;
} }
if (reduced_rules == NULL) { if (reduced_rules == NULL) {
vocab_free_rule_list(work); vocab_free_rule_list(work);
if (verbose) if (verbose)
sciprintf("No results.\n"); sciprintf("No results.\n");
return 1; return 1;
} }
vocab_free_rule_list(work); vocab_free_rule_list(work);
if (word +1 < words_nr) { if (word + 1 < words_nr) {
seeker = reduced_rules; seeker = reduced_rules;
while (seeker) { while (seeker) {
if (seeker->rule->specials_nr) { if (seeker->rule->specials_nr) {
int my_id = seeker->rule->data[seeker->rule->first_special]; int my_id = seeker->rule->data[seeker->rule->first_special];
subseeker = tlist; subseeker = tlist;
while (subseeker) { while (subseeker) {
if (subseeker->rule->id == my_id) if (subseeker->rule->id == my_id)
new_work = _vocab_add_rule(new_work, _vinsert(seeker->rule, subseeker->rule)); new_work = _vocab_add_rule(new_work, _vinsert(seeker->rule, subseeker->rule));
subseeker = subseeker->next; subseeker = subseeker->next;
} }
}
seeker = seeker->next;
}
vocab_free_rule_list(reduced_rules);
} else /* last word */
new_work = reduced_rules;
work = new_work;
if (verbose)
sciprintf("Now at %d candidates\n", _vocab_rule_list_length(work));
if (work == NULL) {
if (verbose)
sciprintf("No results.\n");
return 1;
}
} }
seeker = seeker->next; results = work;
}
vocab_free_rule_list(reduced_rules);
} else /* last word */
new_work = reduced_rules;
work = new_work; if (verbose) {
if (verbose) sciprintf("All results (excluding the surrounding '(141 %03x' and ')'):\n",
sciprintf("Now at %d candidates\n", _vocab_rule_list_length(work)); branch0->id);
if (work == NULL) { vocab_print_rule_list(results);
if (verbose) sciprintf("\n");
sciprintf("No results.\n"); }
return 1;
}
}
results = work; /* now use the first result */
{
int temp, pos;
if (verbose) { nodes[0].type = PARSE_TREE_NODE_BRANCH;
sciprintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", nodes[0].content.branches[0] = 1;
branch0->id); nodes[0].content.branches[1] = 2;
vocab_print_rule_list(results);
sciprintf("\n");
}
/* now use the first result */ nodes[1].type = PARSE_TREE_NODE_LEAF;
{ nodes[1].content.value = 0x141;
int temp, pos;
nodes[0].type = PARSE_TREE_NODE_BRANCH; nodes[2].type = PARSE_TREE_NODE_BRANCH;
nodes[0].content.branches[0] = 1; nodes[2].content.branches[0] = 0;
nodes[0].content.branches[1] = 2; nodes[2].content.branches[1] = 0;
nodes[1].type = PARSE_TREE_NODE_LEAF; pos = 2;
nodes[1].content.value = 0x141;
nodes[2].type = PARSE_TREE_NODE_BRANCH; temp = _vbpt_append(nodes, &pos, 2, branch0->id);
nodes[2].content.branches[0] = 0; /* _vbpt_write_subexpression(nodes, &pos, results[_vocab_rule_list_length(results)].rule, 0, temp); */
nodes[2].content.branches[1] = 0; _vbpt_write_subexpression(nodes, &pos, results->rule, 0, temp);
}
pos = 2; vocab_free_rule_list(results);
return 0;
temp = _vbpt_append(nodes, &pos, 2, branch0->id);
/* _vbpt_write_subexpression(nodes, &pos, results[_vocab_rule_list_length(results)].rule, 0, temp); */
_vbpt_write_subexpression(nodes, &pos, results->rule, 0, temp);
}
vocab_free_rule_list(results);
return 0;
} }

View file

@ -8,64 +8,56 @@
#define assert_in_range(pos) assert(pos>=1000 && pos<=0xffff) #define assert_in_range(pos) assert(pos>=1000 && pos<=0xffff)
static void set_size(heap_t *h, int block_pos, int size) static void set_size(heap_t *h, int block_pos, int size) {
{
assert_in_range(block_pos); assert_in_range(block_pos);
assert(size<=0xffff-1000); assert(size <= 0xffff - 1000);
putInt16(h->start+block_pos, size); putInt16(h->start + block_pos, size);
} }
static void set_next(heap_t* h, int block_pos, int next) static void set_next(heap_t* h, int block_pos, int next) {
{
assert_in_range(block_pos); assert_in_range(block_pos);
assert_in_range(next); assert_in_range(next);
putInt16(h->start+block_pos+2, next); putInt16(h->start + block_pos + 2, next);
} }
static unsigned int get_size(heap_t* h, int block_pos) static unsigned int get_size(heap_t* h, int block_pos) {
{
assert_in_range(block_pos); assert_in_range(block_pos);
return (guint16)getInt16(h->start+block_pos); return (guint16)getInt16(h->start + block_pos);
} }
static unsigned int get_next(heap_t* h, int block_pos) static unsigned int get_next(heap_t* h, int block_pos) {
{
assert_in_range(block_pos); assert_in_range(block_pos);
return (guint16)getInt16(h->start+block_pos+2); return (guint16)getInt16(h->start + block_pos + 2);
} }
/*Allocates a new heap*/ /*Allocates a new heap*/
heap_t* heap_new() heap_t* heap_new() {
{
heap_t* h; heap_t* h;
if((h= (heap_t*)sci_malloc(sizeof(heap_t)))==0) return 0; if ((h = (heap_t*)sci_malloc(sizeof(heap_t))) == 0) return 0;
if((h->start= sci_calloc(SCI_HEAP_SIZE, 1))==0) if ((h->start = sci_calloc(SCI_HEAP_SIZE, 1)) == 0) {
{
free(h); free(h);
return 0; return 0;
} }
h->base=h->start+1000; h->base = h->start + 1000;
h->first_free=1000; h->first_free = 1000;
h->old_ff=-1; h->old_ff = -1;
set_size(h, 1000, 0xffff-1000); set_size(h, 1000, 0xffff - 1000);
set_next(h, 1000, 0xffff); set_next(h, 1000, 0xffff);
return h; return h;
} }
/*Deletes a heap*/ /*Deletes a heap*/
void heap_del(heap_t* h) void heap_del(heap_t* h) {
{
free(h->start); free(h->start);
free(h); free(h);
} }
int heap_meminfo(heap_t* h) int heap_meminfo(heap_t* h) {
{
heap_ptr current = h->first_free; heap_ptr current = h->first_free;
int total = 0; int total = 0;
@ -78,160 +70,134 @@ int heap_meminfo(heap_t* h)
} }
int heap_largest(heap_t* h) int heap_largest(heap_t* h) {
{ int current = h->first_free;
int current=h->first_free; int best_pos = -1, best_size = 0;
int best_pos=-1, best_size=0;
while(current!=0xffff) while (current != 0xffff) {
{ int size = get_size(h, current);
int size=get_size(h, current); int next = get_next(h, current);
int next=get_next(h, current);
if(size>best_size) if (size > best_size) {
{ best_pos = current;
best_pos=current; best_size = size;
best_size=size;
} }
current=next; current = next;
} }
return best_size; return best_size;
} }
heap_ptr heap_allocate(heap_t* h, int size) heap_ptr heap_allocate(heap_t* h, int size) {
{ unsigned int previous = h->first_free;
unsigned int previous=h->first_free; unsigned int current = previous;
unsigned int current=previous;
if (!size) { if (!size) {
fprintf(stderr,"Warning: heap_alloc'd zero bytes!\n"); fprintf(stderr, "Warning: heap_alloc'd zero bytes!\n");
size += 2; size += 2;
} }
size+=2+(size&1); size += 2 + (size & 1);
while(current<0xffff) while (current < 0xffff) {
{ int block_size = get_size(h, current);
int block_size=get_size(h, current); int next = get_next(h, current);
int next=get_next(h, current);
/*Is this block large enough?*/ /*Is this block large enough?*/
if(block_size>=size) if (block_size >= size) {
{
/*Swallow the block whole*/ /*Swallow the block whole*/
if(block_size<=size+4) if (block_size <= size + 4) {
{ size = block_size;
size=block_size;
set_next(h, previous, next); set_next(h, previous, next);
} } else {
else {
/*Split the block*/ /*Split the block*/
int rest=current+size; int rest = current + size;
set_next(h, previous, rest); set_next(h, previous, rest);
set_size(h, rest, block_size-size); set_size(h, rest, block_size - size);
set_next(h, rest, next); set_next(h, rest, next);
next=rest; next = rest;
} }
set_size(h, current, size); set_size(h, current, size);
if(current==h->first_free) h->first_free=next; if (current == h->first_free) h->first_free = next;
return current; return current;
} }
previous=current; previous = current;
current=next; current = next;
} }
/*No large enough block was found.*/ /*No large enough block was found.*/
return 0; return 0;
} }
void heap_free(heap_t* h, unsigned int m) void heap_free(heap_t* h, unsigned int m) {
{
unsigned int previous, next; unsigned int previous, next;
assert_in_range(m); assert_in_range(m);
previous=next=h->first_free; previous = next = h->first_free;
/*Find the previous and next blocks*/ /*Find the previous and next blocks*/
while(next < m) while (next < m) {
{
previous = next; previous = next;
assert(previous<0xffff); assert(previous < 0xffff);
next=get_next(h, previous); next = get_next(h, previous);
if (next <= previous) { if (next <= previous) {
sciprintf("Heap corrupt. Aborting heap_free()...\n"); sciprintf("Heap corrupt. Aborting heap_free()...\n");
return; return;
} }
} }
if (h->first_free > m) if (h->first_free > m)
h->first_free = m; /* Guarantee that first_free is correct */ h->first_free = m; /* Guarantee that first_free is correct */
if(previous==next) if (previous == next) {
{ if (m < previous) {
if(m<previous) h->first_free = m;
{ if (m + get_size(h, m) == previous) {
h->first_free=m; set_size(h, m, get_size(h, m) + get_size(h, previous));
if(m+get_size(h, m)==previous)
{
set_size(h, m, get_size(h, m)+get_size(h, previous));
set_next(h, m, get_next(h, previous)); set_next(h, m, get_next(h, previous));
} } else set_next(h, m, previous);
else set_next(h, m, previous); } else {
} if (previous + get_size(h, previous) == m) {
else set_size(h, previous, get_size(h, previous) + get_size(h, m));
{
if(previous+get_size(h, previous)==m)
{
set_size(h, previous, get_size(h, previous)+get_size(h, m));
set_next(h, previous, 0xffff); set_next(h, previous, 0xffff);
} } else {
else
{
set_next(h, previous, m); set_next(h, previous, m);
set_next(h, m, next); set_next(h, m, next);
} }
} }
} } else {
else
{
set_next(h, previous, m); set_next(h, previous, m);
set_next(h, m, next); set_next(h, m, next);
/*Try to merge with previous*/ /*Try to merge with previous*/
if(previous+get_size(h, previous)==m) if (previous + get_size(h, previous) == m) {
{ set_size(h, previous, get_size(h, previous) + get_size(h, m));
set_size(h, previous, get_size(h, previous)+get_size(h, m));
set_next(h, previous, next); set_next(h, previous, next);
m=previous; m = previous;
} }
/*Try to merge with next*/ /*Try to merge with next*/
if(m+get_size(h, m)==next) if (m + get_size(h, m) == next) {
{ set_size(h, m, get_size(h, m) + get_size(h, next));
set_size(h, m, get_size(h, m)+get_size(h, next));
set_next(h, m, get_next(h, next)); set_next(h, m, get_next(h, next));
} }
} }
} }
void save_ff(heap_t* h) void save_ff(heap_t* h) {
{ h->old_ff = h->first_free;
h->old_ff=h->first_free;
} }
void restore_ff(heap_t* h) void restore_ff(heap_t* h) {
{ h->first_free = h->old_ff;
h->first_free=h->old_ff; set_size(h, h->first_free, 0xffff - h->first_free);
set_size(h, h->first_free, 0xffff-h->first_free);
set_next(h, h->first_free, 0xffff); set_next(h, h->first_free, 0xffff);
} }
void heap_dump_free(heap_t *h) void heap_dump_free(heap_t *h) {
{
int freedomseeker; int freedomseeker;
printf("\tfirst_free= %#x (oldff= %#x)\n\tFree Blocks:\n", h->first_free, h->old_ff); printf("\tfirst_free= %#x (oldff= %#x)\n\tFree Blocks:\n", h->first_free, h->old_ff);
@ -243,8 +209,7 @@ void heap_dump_free(heap_t *h)
} }
} }
void heap_dump_all(heap_t *h) void heap_dump_all(heap_t *h) {
{
int seeker = 1000; int seeker = 1000;
int free_seeker = h->first_free; int free_seeker = h->first_free;
@ -255,7 +220,7 @@ void heap_dump_all(heap_t *h)
if (is_free) if (is_free)
free_seeker = get_next(h, free_seeker); free_seeker = get_next(h, free_seeker);
printf("%04x\t%d\t%s\n", seeker, size, is_free? "FREE": ""); printf("%04x\t%d\t%s\n", seeker, size, is_free ? "FREE" : "");
seeker += size; seeker += size;
} }
} }

View file

@ -35,8 +35,7 @@
typedef guint16 heap_ptr; typedef guint16 heap_ptr;
typedef struct typedef struct {
{
byte* start; byte* start;
byte* base; byte* base;
unsigned int first_free; unsigned int first_free;

View file

@ -195,172 +195,171 @@ static int sci_max_allowed_unknown_kernel_functions[] = {
#define NOFUN(nm) {KF_NONE, nm, {NULL, NULL, NULL}} #define NOFUN(nm) {KF_NONE, nm, {NULL, NULL, NULL}}
sci_kernel_function_t kfunct_mappers[] = { sci_kernel_function_t kfunct_mappers[] = {
/*00*/ DEFUN("Load", kLoad, "iii*"), /*00*/ DEFUN("Load", kLoad, "iii*"),
/*01*/ DEFUN("UnLoad", kUnLoad, "i.*"), /*01*/ DEFUN("UnLoad", kUnLoad, "i.*"),
/*02*/ DEFUN("ScriptID", kScriptID, "Ioi*"), /*02*/ DEFUN("ScriptID", kScriptID, "Ioi*"),
/*03*/ DEFUN("DisposeScript", kDisposeScript, "Oi"), /* Work around QfG1 bug */ /*03*/ DEFUN("DisposeScript", kDisposeScript, "Oi"), /* Work around QfG1 bug */
/*04*/ DEFUN("Clone", kClone, "o"), /*04*/ DEFUN("Clone", kClone, "o"),
/*05*/ DEFUN("DisposeClone", kDisposeClone, "o"), /*05*/ DEFUN("DisposeClone", kDisposeClone, "o"),
/*06*/ DEFUN("IsObject", kIsObject, "."), /*06*/ DEFUN("IsObject", kIsObject, "."),
/*07*/ DEFUN("RespondsTo", kRespondsTo, ".i"), /*07*/ DEFUN("RespondsTo", kRespondsTo, ".i"),
/*08*/ DEFUN("DrawPic", kDrawPic, "i*"), /*08*/ DEFUN("DrawPic", kDrawPic, "i*"),
/*09*/ DEFUN("Show", kShow, "i"), /*09*/ DEFUN("Show", kShow, "i"),
/*0a*/ DEFUN("PicNotValid", kPicNotValid, "i*"), /*0a*/ DEFUN("PicNotValid", kPicNotValid, "i*"),
/*0b*/ DEFUN("Animate", kAnimate, "LI*"), /* More like (li?)? */ /*0b*/ DEFUN("Animate", kAnimate, "LI*"), /* More like (li?)? */
/*0c*/ DEFUN("SetNowSeen", kSetNowSeen, "oi*"), /* The second parameter is ignored */ /*0c*/ DEFUN("SetNowSeen", kSetNowSeen, "oi*"), /* The second parameter is ignored */
/*0d*/ DEFUN("NumLoops", kNumLoops, "o"), /*0d*/ DEFUN("NumLoops", kNumLoops, "o"),
/*0e*/ DEFUN("NumCels", kNumCels, "o"), /*0e*/ DEFUN("NumCels", kNumCels, "o"),
/*0f*/ DEFUN("CelWide", kCelWide, "iOiOi"), /*0f*/ DEFUN("CelWide", kCelWide, "iOiOi"),
/*10*/ DEFUN("CelHigh", kCelHigh, "iOiOi"), /*10*/ DEFUN("CelHigh", kCelHigh, "iOiOi"),
/*11*/ DEFUN("DrawCel", kDrawCel, "iiiiii*"), /*11*/ DEFUN("DrawCel", kDrawCel, "iiiiii*"),
/*12*/ DEFUN("AddToPic", kAddToPic, "Il*"), /*12*/ DEFUN("AddToPic", kAddToPic, "Il*"),
/*13*/ DEFUN("NewWindow", kNewWindow, "iiiiZRi*"), /*13*/ DEFUN("NewWindow", kNewWindow, "iiiiZRi*"),
/*14*/ DEFUN("GetPort", kGetPort, ""), /*14*/ DEFUN("GetPort", kGetPort, ""),
/*15*/ DEFUN("SetPort", kSetPort, "ii*"), /*15*/ DEFUN("SetPort", kSetPort, "ii*"),
/*16*/ DEFUN("DisposeWindow", kDisposeWindow, "ii*"), /*16*/ DEFUN("DisposeWindow", kDisposeWindow, "ii*"),
/*17*/ DEFUN("DrawControl", kDrawControl, "o"), /*17*/ DEFUN("DrawControl", kDrawControl, "o"),
/*18*/ DEFUN("HiliteControl", kHiliteControl, "o"), /*18*/ DEFUN("HiliteControl", kHiliteControl, "o"),
/*19*/ DEFUN("EditControl", kEditControl, "ZoZo"), /*19*/ DEFUN("EditControl", kEditControl, "ZoZo"),
/*1a*/ DEFUN("TextSize", kTextSize, "rZrii*r*"), /*1a*/ DEFUN("TextSize", kTextSize, "rZrii*r*"),
/*1b*/ DEFUN("Display", kDisplay, ".*"), /*1b*/ DEFUN("Display", kDisplay, ".*"),
/*1c*/ DEFUN("GetEvent", kGetEvent, "io"), /*1c*/ DEFUN("GetEvent", kGetEvent, "io"),
/*1d*/ DEFUN("GlobalToLocal", kGlobalToLocal, "o"), /*1d*/ DEFUN("GlobalToLocal", kGlobalToLocal, "o"),
/*1e*/ DEFUN("LocalToGlobal", kLocalToGlobal, "o"), /*1e*/ DEFUN("LocalToGlobal", kLocalToGlobal, "o"),
/*1f*/ DEFUN("MapKeyToDir", kMapKeyToDir, "o"), /*1f*/ DEFUN("MapKeyToDir", kMapKeyToDir, "o"),
/*20*/ DEFUN("DrawMenuBar", kDrawMenuBar, "i"), /*20*/ DEFUN("DrawMenuBar", kDrawMenuBar, "i"),
/*21*/ DEFUN("MenuSelect", kMenuSelect, "oi*"), /*21*/ DEFUN("MenuSelect", kMenuSelect, "oi*"),
/*22*/ DEFUN("AddMenu", kAddMenu, "rr"), /*22*/ DEFUN("AddMenu", kAddMenu, "rr"),
/*23*/ DEFUN("DrawStatus", kDrawStatus, "Zri*"), /*23*/ DEFUN("DrawStatus", kDrawStatus, "Zri*"),
/*24*/ DEFUN("Parse", kParse, "ro"), /*24*/ DEFUN("Parse", kParse, "ro"),
/*25*/ DEFUN("Said", kSaid, "Zr"), /*25*/ DEFUN("Said", kSaid, "Zr"),
/*26*/ DEFUN("SetSynonyms", kSetSynonyms, "o"), /*26*/ DEFUN("SetSynonyms", kSetSynonyms, "o"),
/*27*/ DEFUN("HaveMouse", kHaveMouse, ""), /*27*/ DEFUN("HaveMouse", kHaveMouse, ""),
/*28*/ DEFUN("SetCursor", kSetCursor, "i*"), /*28*/ DEFUN("SetCursor", kSetCursor, "i*"),
/*28*/ DEFUN("MoveCursor", kMoveCursor, "ii*"), /*28*/ DEFUN("MoveCursor", kMoveCursor, "ii*"),
/*29*/ DEFUN("FOpen", kFOpen, "ri"), /*29*/ DEFUN("FOpen", kFOpen, "ri"),
/*2a*/ DEFUN("FPuts", kFPuts, "ir"), /*2a*/ DEFUN("FPuts", kFPuts, "ir"),
/*2b*/ DEFUN("FGets", kFGets, "rii"), /*2b*/ DEFUN("FGets", kFGets, "rii"),
/*2c*/ DEFUN("FClose", kFClose, "i"), /*2c*/ DEFUN("FClose", kFClose, "i"),
/*2d*/ DEFUN("SaveGame", kSaveGame, "rirr*"), /*2d*/ DEFUN("SaveGame", kSaveGame, "rirr*"),
/*2e*/ DEFUN("RestoreGame", kRestoreGame, "rir*"), /*2e*/ DEFUN("RestoreGame", kRestoreGame, "rir*"),
/*2f*/ DEFUN("RestartGame", kRestartGame, ""), /*2f*/ DEFUN("RestartGame", kRestartGame, ""),
/*30*/ DEFUN("GameIsRestarting", kGameIsRestarting, "i*"), /*30*/ DEFUN("GameIsRestarting", kGameIsRestarting, "i*"),
/*31*/ DEFUN("DoSound", kDoSound, "iIo*"), /*31*/ DEFUN("DoSound", kDoSound, "iIo*"),
/*32*/ DEFUN("NewList", kNewList, ""), /*32*/ DEFUN("NewList", kNewList, ""),
/*33*/ DEFUN("DisposeList", kDisposeList, "l"), /*33*/ DEFUN("DisposeList", kDisposeList, "l"),
/*34*/ DEFUN("NewNode", kNewNode, ".."), /*34*/ DEFUN("NewNode", kNewNode, ".."),
/*35*/ DEFUN("FirstNode", kFirstNode, "Zl"), /*35*/ DEFUN("FirstNode", kFirstNode, "Zl"),
/*36*/ DEFUN("LastNode", kLastNode, "l"), /*36*/ DEFUN("LastNode", kLastNode, "l"),
/*37*/ DEFUN("EmptyList", kEmptyList, "l"), /*37*/ DEFUN("EmptyList", kEmptyList, "l"),
/*38*/ DEFUN("NextNode", kNextNode, "n!"), /*38*/ DEFUN("NextNode", kNextNode, "n!"),
/*39*/ DEFUN("PrevNode", kPrevNode, "n"), /*39*/ DEFUN("PrevNode", kPrevNode, "n"),
/*3a*/ DEFUN("NodeValue", kNodeValue, "Zn!"), /*3a*/ DEFUN("NodeValue", kNodeValue, "Zn!"),
/*3b*/ DEFUN("AddAfter", kAddAfter, "lnn"), /*3b*/ DEFUN("AddAfter", kAddAfter, "lnn"),
/*3c*/ DEFUN("AddToFront", kAddToFront, "ln"), /*3c*/ DEFUN("AddToFront", kAddToFront, "ln"),
/*3d*/ DEFUN("AddToEnd", kAddToEnd, "ln"), /*3d*/ DEFUN("AddToEnd", kAddToEnd, "ln"),
/*3e*/ DEFUN("FindKey", kFindKey, "l."), /*3e*/ DEFUN("FindKey", kFindKey, "l."),
/*3f*/ DEFUN("DeleteKey", kDeleteKey, "l."), /*3f*/ DEFUN("DeleteKey", kDeleteKey, "l."),
/*40*/ DEFUN("Random", kRandom, "i*"), /*40*/ DEFUN("Random", kRandom, "i*"),
/*41*/ DEFUN("Abs", kAbs, "Oi"), /*41*/ DEFUN("Abs", kAbs, "Oi"),
/*42*/ DEFUN("Sqrt", kSqrt, "i"), /*42*/ DEFUN("Sqrt", kSqrt, "i"),
/*43*/ DEFUN("GetAngle", kGetAngle, "iiii"), /*43*/ DEFUN("GetAngle", kGetAngle, "iiii"),
/*44*/ DEFUN("GetDistance", kGetDistance, "iiiii*"), /*44*/ DEFUN("GetDistance", kGetDistance, "iiiii*"),
/*45*/ DEFUN("Wait", kWait, "i"), /*45*/ DEFUN("Wait", kWait, "i"),
/*46*/ DEFUN("GetTime", kGetTime, "i*"), /*46*/ DEFUN("GetTime", kGetTime, "i*"),
/*47*/ DEFUN("StrEnd", kStrEnd, "r"), /*47*/ DEFUN("StrEnd", kStrEnd, "r"),
/*48*/ DEFUN("StrCat", kStrCat, "rr"), /*48*/ DEFUN("StrCat", kStrCat, "rr"),
/*49*/ DEFUN("StrCmp", kStrCmp, "rri*"), /*49*/ DEFUN("StrCmp", kStrCmp, "rri*"),
/*4a*/ DEFUN("StrLen", kStrLen, "r"), /*4a*/ DEFUN("StrLen", kStrLen, "r"),
/*4b*/ DEFUN("StrCpy", kStrCpy, "rri*"), /*4b*/ DEFUN("StrCpy", kStrCpy, "rri*"),
/*4c*/ DEFUN("Format", kFormat, "r.*"), /*4c*/ DEFUN("Format", kFormat, "r.*"),
/*4d*/ DEFUN("GetFarText", kGetFarText, "iir"), /*4d*/ DEFUN("GetFarText", kGetFarText, "iir"),
/*4e*/ DEFUN("ReadNumber", kReadNumber, "r"), /*4e*/ DEFUN("ReadNumber", kReadNumber, "r"),
/*4f*/ DEFUN("BaseSetter", kBaseSetter, "o"), /*4f*/ DEFUN("BaseSetter", kBaseSetter, "o"),
/*50*/ DEFUN("DirLoop", kDirLoop, "oi"), /*50*/ DEFUN("DirLoop", kDirLoop, "oi"),
/*51*/ DEFUN("CanBeHere", kCanBeHere, "ol*"), /*51*/ DEFUN("CanBeHere", kCanBeHere, "ol*"),
/*51*/ DEFUN("CantBeHere", kCanBeHere, "ol*"), /*51*/ DEFUN("CantBeHere", kCanBeHere, "ol*"),
/*52*/ DEFUN("OnControl", kOnControl, "i*"), /*52*/ DEFUN("OnControl", kOnControl, "i*"),
/*53*/ DEFUN("InitBresen", kInitBresen, "oi*"), /*53*/ DEFUN("InitBresen", kInitBresen, "oi*"),
/*54*/ DEFUN("DoBresen", kDoBresen, "o"), /*54*/ DEFUN("DoBresen", kDoBresen, "o"),
/*55*/ DEFUN("DoAvoider", kDoAvoider, "o"), /*55*/ DEFUN("DoAvoider", kDoAvoider, "o"),
/*56*/ DEFUN("SetJump", kSetJump, "oiii"), /*56*/ DEFUN("SetJump", kSetJump, "oiii"),
/*57*/ DEFUN("SetDebug", kSetDebug, "i*"), /*57*/ DEFUN("SetDebug", kSetDebug, "i*"),
/*58*/ NOFUN("InspectObj"), /*58*/ NOFUN("InspectObj"),
/*59*/ NOFUN("ShowSends"), /*59*/ NOFUN("ShowSends"),
/*5a*/ NOFUN("ShowObjs"), /*5a*/ NOFUN("ShowObjs"),
/*5b*/ NOFUN("ShowFree"), /*5b*/ NOFUN("ShowFree"),
/*5c*/ DEFUN("MemoryInfo", kMemoryInfo, "i"), /*5c*/ DEFUN("MemoryInfo", kMemoryInfo, "i"),
/*5d*/ NOFUN("StackUsage"), /*5d*/ NOFUN("StackUsage"),
/*5e*/ NOFUN("Profiler"), /*5e*/ NOFUN("Profiler"),
/*5f*/ DEFUN("GetMenu", kGetMenu, "i."), /*5f*/ DEFUN("GetMenu", kGetMenu, "i."),
/*60*/ DEFUN("SetMenu", kSetMenu, "i.*"), /*60*/ DEFUN("SetMenu", kSetMenu, "i.*"),
/*61*/ DEFUN("GetSaveFiles", kGetSaveFiles, "rrr"), /*61*/ DEFUN("GetSaveFiles", kGetSaveFiles, "rrr"),
/*62*/ DEFUN("GetCWD", kGetCWD, "r"), /*62*/ DEFUN("GetCWD", kGetCWD, "r"),
/*63*/ DEFUN("CheckFreeSpace", kCheckFreeSpace, "r"), /*63*/ DEFUN("CheckFreeSpace", kCheckFreeSpace, "r"),
/*64*/ DEFUN("ValidPath", kValidPath, "r"), /*64*/ DEFUN("ValidPath", kValidPath, "r"),
/*65*/ DEFUN("CoordPri", kCoordPri, "i"), /*65*/ DEFUN("CoordPri", kCoordPri, "i"),
/*66*/ DEFUN("StrAt", kStrAt, "rii*"), /*66*/ DEFUN("StrAt", kStrAt, "rii*"),
#ifdef WIN32 #ifdef WIN32
/*67*/ DEFUN("DeviceInfo", kDeviceInfo_Win32, "i.*"), /*67*/ DEFUN("DeviceInfo", kDeviceInfo_Win32, "i.*"),
#else /* !WIN32 */ #else /* !WIN32 */
/*67*/ DEFUN("DeviceInfo", kDeviceInfo_Unix, "i.*"), /*67*/ DEFUN("DeviceInfo", kDeviceInfo_Unix, "i.*"),
#endif #endif
/*68*/ DEFUN("GetSaveDir", kGetSaveDir, ""), /*68*/ DEFUN("GetSaveDir", kGetSaveDir, ""),
/*69*/ DEFUN("CheckSaveGame", kCheckSaveGame, ".*"), /*69*/ DEFUN("CheckSaveGame", kCheckSaveGame, ".*"),
/*6a*/ DEFUN("ShakeScreen", kShakeScreen, "ii*"), /*6a*/ DEFUN("ShakeScreen", kShakeScreen, "ii*"),
/*6b*/ DEFUN("FlushResources", kFlushResources, "i"), /*6b*/ DEFUN("FlushResources", kFlushResources, "i"),
/*6c*/ DEFUN("TimesSin", kTimesSin, "ii"), /*6c*/ DEFUN("TimesSin", kTimesSin, "ii"),
/*6d*/ DEFUN("TimesCos", kTimesCos, "ii"), /*6d*/ DEFUN("TimesCos", kTimesCos, "ii"),
#if 0 #if 0
/*6e*/ NOFUN(NULL), /*6e*/ NOFUN(NULL),
/*6f*/ NOFUN(NULL), /*6f*/ NOFUN(NULL),
#else #else
/*6e*/ DEFUN("6e", kTimesSin, "ii"), /*6e*/ DEFUN("6e", kTimesSin, "ii"),
/*6f*/ DEFUN("6f", kTimesCos, "ii"), /*6f*/ DEFUN("6f", kTimesCos, "ii"),
#endif #endif
/*70*/ DEFUN("Graph", kGraph, ".*"), /*70*/ DEFUN("Graph", kGraph, ".*"),
/*71*/ DEFUN("Joystick", kJoystick, ".*"), /*71*/ DEFUN("Joystick", kJoystick, ".*"),
/*72*/ NOFUN(NULL), /*72*/ NOFUN(NULL),
/*73*/ NOFUN(NULL), /*73*/ NOFUN(NULL),
/* Experimental functions */ /* Experimental functions */
/*74*/ DEFUN("FileIO", kFileIO, "i.*"), /*74*/ DEFUN("FileIO", kFileIO, "i.*"),
/*(?)*/ DEFUN("Memory", kMemory, "i.*"), /*(?)*/ DEFUN("Memory", kMemory, "i.*"),
/*(?)*/ DEFUN("Sort", kSort, "ooo"), /*(?)*/ DEFUN("Sort", kSort, "ooo"),
/*(?)*/ DEFUN("AvoidPath", kAvoidPath, "ii.*"), /*(?)*/ DEFUN("AvoidPath", kAvoidPath, "ii.*"),
/*(?)*/ DEFUN("Lock", kLock, "iii*"), /*(?)*/ DEFUN("Lock", kLock, "iii*"),
/*(?)*/ DEFUN("Palette", kPalette, "i*"), /*(?)*/ DEFUN("Palette", kPalette, "i*"),
/*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"), /*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"),
/* Non-experimental Functions without a fixed ID */ /* Non-experimental Functions without a fixed ID */
DEFUN("CosMult", kTimesCos, "ii"), DEFUN("CosMult", kTimesCos, "ii"),
DEFUN("SinMult", kTimesSin, "ii"), DEFUN("SinMult", kTimesSin, "ii"),
/*(?)*/ DEFUN("CosDiv", kCosDiv, "ii"), /*(?)*/ DEFUN("CosDiv", kCosDiv, "ii"),
/*(?)*/ DEFUN("PriCoord", kPriCoord, "i"), /*(?)*/ DEFUN("PriCoord", kPriCoord, "i"),
/*(?)*/ DEFUN("SinDiv", kSinDiv, "ii"), /*(?)*/ DEFUN("SinDiv", kSinDiv, "ii"),
/*(?)*/ DEFUN("TimesCot", kTimesCot, "ii"), /*(?)*/ DEFUN("TimesCot", kTimesCot, "ii"),
/*(?)*/ DEFUN("TimesTan", kTimesTan, "ii"), /*(?)*/ DEFUN("TimesTan", kTimesTan, "ii"),
DEFUN("Message", kMessage, ".*"), DEFUN("Message", kMessage, ".*"),
DEFUN("DoAudio", kDoAudio, ".*"), DEFUN("DoAudio", kDoAudio, ".*"),
/* Special and NOP stuff */ /* Special and NOP stuff */
{KF_NEW, NULL, {k_Unknown, NULL, NULL}}, {KF_NEW, NULL, {k_Unknown, NULL, NULL}},
{KF_TERMINATOR, NULL, {NULL, NULL, NULL}} /* Terminator */ {KF_TERMINATOR, NULL, {NULL, NULL, NULL}} /* Terminator */
}; };
static const char *argtype_description[] = {"Undetermined (WTF?)", "List","Node","Object","Reference","Arithmetic"}; static const char *argtype_description[] = {"Undetermined (WTF?)", "List", "Node", "Object", "Reference", "Arithmetic"};
/******************** Kernel Oops ********************/ /******************** Kernel Oops ********************/
int int
kernel_oops(state_t *s, const char *file, int line, const char *reason) kernel_oops(state_t *s, const char *file, int line, const char *reason) {
{
sciprintf("Kernel Oops in file %s, line %d: %s\n", file, line, reason); sciprintf("Kernel Oops in file %s, line %d: %s\n", file, line, reason);
fprintf(stderr,"Kernel Oops in file %s, line %d: %s\n", file, line, reason); fprintf(stderr, "Kernel Oops in file %s, line %d: %s\n", file, line, reason);
script_debug_flag = script_error_flag = 1; script_debug_flag = script_error_flag = 1;
return 0; return 0;
} }
@ -368,8 +367,7 @@ kernel_oops(state_t *s, const char *file, int line, const char *reason)
/* Allocates a set amount of memory for a specified use and returns a handle to it. */ /* Allocates a set amount of memory for a specified use and returns a handle to it. */
reg_t reg_t
kalloc(state_t *s, const char *type, int space) kalloc(state_t *s, const char *type, int space) {
{
reg_t reg; reg_t reg;
sm_alloc_hunk_entry(&s->seg_manager, type, space, &reg); sm_alloc_hunk_entry(&s->seg_manager, type, space, &reg);
@ -379,12 +377,10 @@ kalloc(state_t *s, const char *type, int space)
} }
int int
has_kernel_function(state_t *s, const char *kname) has_kernel_function(state_t *s, const char *kname) {
{
int i = 0; int i = 0;
while (s->kernel_names[i]) while (s->kernel_names[i]) {
{
if (!strcmp(s->kernel_names[i], kname)) if (!strcmp(s->kernel_names[i], kname))
return 1; return 1;
i++; i++;
@ -395,8 +391,7 @@ has_kernel_function(state_t *s, const char *kname)
/* Returns a pointer to the memory indicated by the specified handle */ /* Returns a pointer to the memory indicated by the specified handle */
byte * byte *
kmem(state_t *s, reg_t handle) kmem(state_t *s, reg_t handle) {
{
mem_obj_t *mobj = GET_SEGMENT(s->seg_manager, handle.segment, MEM_OBJ_HUNK); mem_obj_t *mobj = GET_SEGMENT(s->seg_manager, handle.segment, MEM_OBJ_HUNK);
hunk_table_t *ht = &(mobj->data.hunks); hunk_table_t *ht = &(mobj->data.hunks);
@ -410,8 +405,7 @@ kmem(state_t *s, reg_t handle)
/* Frees the specified handle. Returns 0 on success, 1 otherwise. */ /* Frees the specified handle. Returns 0 on success, 1 otherwise. */
int int
kfree(state_t *s, reg_t handle) kfree(state_t *s, reg_t handle) {
{
sm_free_hunk_entry(&s->seg_manager, handle); sm_free_hunk_entry(&s->seg_manager, handle);
return 0; return 0;
@ -425,8 +419,7 @@ kfree(state_t *s, reg_t handle)
char *old_save_dir; char *old_save_dir;
reg_t reg_t
kRestartGame(state_t *s, int funct_nr, int argc, reg_t *argv) kRestartGame(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1); char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1);
old_save_dir = strdup(deref_save_dir); old_save_dir = strdup(deref_save_dir);
@ -442,12 +435,10 @@ kRestartGame(state_t *s, int funct_nr, int argc, reg_t *argv)
** Returns the restarting_flag in acc ** Returns the restarting_flag in acc
*/ */
reg_t reg_t
kGameIsRestarting(state_t *s, int funct_nr, int argc, reg_t *argv) kGameIsRestarting(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1); char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1);
if (old_save_dir&&deref_save_dir) if (old_save_dir && deref_save_dir) {
{
strcpy(deref_save_dir, old_save_dir); strcpy(deref_save_dir, old_save_dir);
free(old_save_dir); free(old_save_dir);
old_save_dir = NULL; old_save_dir = NULL;
@ -464,18 +455,16 @@ kGameIsRestarting(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t reg_t
kHaveMouse(state_t *s, int funct_nr, int argc, reg_t *argv) kHaveMouse(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
return make_reg (0, (s->have_mouse_flag return make_reg(0, (s->have_mouse_flag
&& gfxop_have_mouse(s->gfx_state))? -1 : 0); && gfxop_have_mouse(s->gfx_state)) ? -1 : 0);
} }
reg_t reg_t
kMemoryInfo(state_t *s, int funct_nr, int argc, reg_t *argv) kMemoryInfo(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
switch (argv[0].offset) { switch (argv[0].offset) {
case 0: /* Total free heap memory */ case 0: /* Total free heap memory */
case 1: /* Largest heap block available */ case 1: /* Largest heap block available */
@ -484,42 +473,40 @@ kMemoryInfo(state_t *s, int funct_nr, int argc, reg_t *argv)
case 4: /* Amount of free DOS paragraphs- SCI01 */ case 4: /* Amount of free DOS paragraphs- SCI01 */
return make_reg(0, 0x7fff); /* Must not be 0xffff, or some memory calculations will overflow */ return make_reg(0, 0x7fff); /* Must not be 0xffff, or some memory calculations will overflow */
default: SCIkwarn(SCIkWARNING, "Unknown MemoryInfo operation: %04x\n", argv[0].offset); default:
SCIkwarn(SCIkWARNING, "Unknown MemoryInfo operation: %04x\n", argv[0].offset);
} }
return NULL_REG; return NULL_REG;
} }
reg_t reg_t
k_Unknown(state_t *s, int funct_nr, int argc, reg_t *argv) k_Unknown(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
if (funct_nr >= SCI_MAPPED_UNKNOWN_KFUNCTIONS_NR) { if (funct_nr >= SCI_MAPPED_UNKNOWN_KFUNCTIONS_NR) {
SCIkwarn(SCIkSTUB, "Unhandled Unknown function %04x\n", funct_nr); SCIkwarn(SCIkSTUB, "Unhandled Unknown function %04x\n", funct_nr);
return NULL_REG; return NULL_REG;
} else switch(kfunct_mappers[funct_nr].type) { } else switch (kfunct_mappers[funct_nr].type) {
case KF_NEW: case KF_NEW:
return kfunct_mappers[funct_nr].sig_pair.fun(s, funct_nr, argc, argv); return kfunct_mappers[funct_nr].sig_pair.fun(s, funct_nr, argc, argv);
case KF_NONE: case KF_NONE:
default: default:
SCIkwarn(SCIkSTUB, "Unhandled Unknown function %04x\n", funct_nr); SCIkwarn(SCIkSTUB, "Unhandled Unknown function %04x\n", funct_nr);
return NULL_REG; return NULL_REG;
} }
} }
reg_t reg_t
kFlushResources(state_t *s, int funct_nr, int argc, reg_t *argv) kFlushResources(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
run_gc(s); run_gc(s);
SCIkdebug(SCIkROOM, "Entering room number %d\n", UKPV(0)); SCIkdebug(SCIkROOM, "Entering room number %d\n", UKPV(0));
return s->r_acc; return s->r_acc;
} }
reg_t reg_t
kSetDebug(state_t *s, int funct_nr, int argc, reg_t *argv) kSetDebug(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
sciprintf("Debug mode activated\n"); sciprintf("Debug mode activated\n");
script_debug_flag = 1; /* Enter debug mode */ script_debug_flag = 1; /* Enter debug mode */
@ -533,8 +520,7 @@ kSetDebug(state_t *s, int funct_nr, int argc, reg_t *argv)
#define _K_NEW_GETTIME_DATE 3 #define _K_NEW_GETTIME_DATE 3
reg_t reg_t
kGetTime(state_t *s, int funct_nr, int argc, reg_t *argv) kGetTime(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
struct tm* loc_time; struct tm* loc_time;
GTimeVal time_prec; GTimeVal time_prec;
time_t the_time; time_t the_time;
@ -544,12 +530,11 @@ kGetTime(state_t *s, int funct_nr, int argc, reg_t *argv)
/* Reset optimization flags: If this function is called, /* Reset optimization flags: If this function is called,
** the game may be waiting for a timeout */ ** the game may be waiting for a timeout */
s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT
| KERNEL_OPT_FLAG_GOT_2NDEVENT); | KERNEL_OPT_FLAG_GOT_2NDEVENT);
#endif #endif
#ifdef WIN32 #ifdef WIN32
if (TIMERR_NOERROR != timeBeginPeriod(1)) if (TIMERR_NOERROR != timeBeginPeriod(1)) {
{
fprintf(stderr, "timeBeginPeriod(1) failed in kGetTime!\n"); fprintf(stderr, "timeBeginPeriod(1) failed in kGetTime!\n");
} }
#endif /* WIN32 */ #endif /* WIN32 */
@ -558,20 +543,19 @@ kGetTime(state_t *s, int funct_nr, int argc, reg_t *argv)
loc_time = localtime(&the_time); loc_time = localtime(&the_time);
#ifdef WIN32 #ifdef WIN32
if (TIMERR_NOERROR != timeEndPeriod(1)) if (TIMERR_NOERROR != timeEndPeriod(1)) {
{
fprintf(stderr, "timeEndPeriod(1) failed in kGetTime!\n"); fprintf(stderr, "timeEndPeriod(1) failed in kGetTime!\n");
} }
#endif /* WIN32 */ #endif /* WIN32 */
if (s->version<SCI_VERSION_FTU_NEW_GETTIME) { /* Use old semantics */ if (s->version < SCI_VERSION_FTU_NEW_GETTIME) { /* Use old semantics */
if (argc) { /* Get seconds since last am/pm switch */ if (argc) { /* Get seconds since last am/pm switch */
retval = loc_time->tm_sec + loc_time->tm_min * 60 + (loc_time->tm_hour % 12) * 3600; retval = loc_time->tm_sec + loc_time->tm_min * 60 + (loc_time->tm_hour % 12) * 3600;
SCIkdebug(SCIkTIME, "GetTime(timeofday) returns %d\n", retval); SCIkdebug(SCIkTIME, "GetTime(timeofday) returns %d\n", retval);
} else { /* Get time since game started */ } else { /* Get time since game started */
sci_get_current_time (&time_prec); sci_get_current_time(&time_prec);
retval = ((time_prec.tv_usec - s->game_start_time.tv_usec) * 60 / 1000000) + retval = ((time_prec.tv_usec - s->game_start_time.tv_usec) * 60 / 1000000) +
(time_prec.tv_sec - s->game_start_time.tv_sec) * 60; (time_prec.tv_sec - s->game_start_time.tv_sec) * 60;
SCIkdebug(SCIkTIME, "GetTime(elapsed) returns %d\n", retval); SCIkdebug(SCIkTIME, "GetTime(elapsed) returns %d\n", retval);
} }
} else { } else {
@ -579,25 +563,25 @@ kGetTime(state_t *s, int funct_nr, int argc, reg_t *argv)
mode 0 and the others. We assume that this is safe, though */ mode 0 and the others. We assume that this is safe, though */
switch (mode) { switch (mode) {
case _K_NEW_GETTIME_TICKS : { case _K_NEW_GETTIME_TICKS : {
sci_get_current_time (&time_prec); sci_get_current_time(&time_prec);
retval = ((time_prec.tv_usec - s->game_start_time.tv_usec) * 60 / 1000000) + retval = ((time_prec.tv_usec - s->game_start_time.tv_usec) * 60 / 1000000) +
(time_prec.tv_sec - s->game_start_time.tv_sec) * 60; (time_prec.tv_sec - s->game_start_time.tv_sec) * 60;
SCIkdebug(SCIkTIME, "GetTime(elapsed) returns %d\n", retval); SCIkdebug(SCIkTIME, "GetTime(elapsed) returns %d\n", retval);
break; break;
} }
case _K_NEW_GETTIME_TIME_12HOUR : { case _K_NEW_GETTIME_TIME_12HOUR : {
loc_time->tm_hour %= 12; loc_time->tm_hour %= 12;
retval=(loc_time->tm_min<<6)|(loc_time->tm_hour<<12)|(loc_time->tm_sec); retval = (loc_time->tm_min << 6) | (loc_time->tm_hour << 12) | (loc_time->tm_sec);
SCIkdebug(SCIkTIME, "GetTime(12h) returns %d\n", retval); SCIkdebug(SCIkTIME, "GetTime(12h) returns %d\n", retval);
break; break;
} }
case _K_NEW_GETTIME_TIME_24HOUR : { case _K_NEW_GETTIME_TIME_24HOUR : {
retval=(loc_time->tm_min<<5)|(loc_time->tm_sec>>1)|(loc_time->tm_hour<<11); retval = (loc_time->tm_min << 5) | (loc_time->tm_sec >> 1) | (loc_time->tm_hour << 11);
SCIkdebug(SCIkTIME, "GetTime(24h) returns %d\n", retval); SCIkdebug(SCIkTIME, "GetTime(24h) returns %d\n", retval);
break; break;
} }
case _K_NEW_GETTIME_DATE : { case _K_NEW_GETTIME_DATE : {
retval=(loc_time->tm_mon<<5)|loc_time->tm_mday|(loc_time->tm_year<<9); retval = (loc_time->tm_mon << 5) | loc_time->tm_mday | (loc_time->tm_year << 9);
SCIkdebug(SCIkTIME, "GetTime(date) returns %d\n", retval); SCIkdebug(SCIkTIME, "GetTime(date) returns %d\n", retval);
break; break;
} }
@ -619,15 +603,14 @@ kGetTime(state_t *s, int funct_nr, int argc, reg_t *argv)
#define K_MEMORY_POKE 6 #define K_MEMORY_POKE 6
reg_t reg_t
kMemory(state_t *s, int funct_nr, int argc, reg_t *argv) kMemory(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
switch (UKPV(0)) { switch (UKPV(0)) {
case K_MEMORY_ALLOCATE_CRITICAL : case K_MEMORY_ALLOCATE_CRITICAL :
if (!sm_alloc_dynmem(&s->seg_manager, UKPV(1), if (!sm_alloc_dynmem(&s->seg_manager, UKPV(1),
"kMemory() critical", &s->r_acc)) { "kMemory() critical", &s->r_acc)) {
SCIkwarn(SCIkERROR, "Critical heap allocation failed\n"); SCIkwarn(SCIkERROR, "Critical heap allocation failed\n");
script_error_flag = script_debug_flag = 1; script_error_flag = script_debug_flag = 1;
} }
@ -638,14 +621,14 @@ kMemory(state_t *s, int funct_nr, int argc, reg_t *argv)
case K_MEMORY_ALLOCATE_NONCRITICAL : case K_MEMORY_ALLOCATE_NONCRITICAL :
sm_alloc_dynmem(&s->seg_manager, UKPV(1), sm_alloc_dynmem(&s->seg_manager, UKPV(1),
"kMemory() non-critical", &s->r_acc); "kMemory() non-critical", &s->r_acc);
break; break;
case K_MEMORY_FREE : case K_MEMORY_FREE :
if (sm_free_dynmem(&s->seg_manager, argv[1])) { if (sm_free_dynmem(&s->seg_manager, argv[1])) {
SCIkwarn(SCIkERROR, "Attempt to kMemory::free() non-dynmem pointer "PREG"!\n", SCIkwarn(SCIkERROR, "Attempt to kMemory::free() non-dynmem pointer "PREG"!\n",
PRINT_REG(argv[1])); PRINT_REG(argv[1]));
} }
break; break;
@ -667,42 +650,43 @@ kMemory(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
break; break;
} }
case K_MEMORY_PEEK : { case K_MEMORY_PEEK : {
byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2); byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2);
if (!ref) { if (!ref) {
SCIkdebug(SCIkERROR, "Attempt to poke invalid memory at "PREG"!\n", SCIkdebug(SCIkERROR, "Attempt to poke invalid memory at "PREG"!\n",
PRINT_REG(argv[1])); PRINT_REG(argv[1]));
return s->r_acc; return s->r_acc;
} }
if (s->seg_manager.heap[argv[1].segment]->type == MEM_OBJ_LOCALS) if (s->seg_manager.heap[argv[1].segment]->type == MEM_OBJ_LOCALS)
return *((reg_t *) ref); else return *((reg_t *) ref);
else
return make_reg(0, getInt16(ref)); return make_reg(0, getInt16(ref));
} }
break; break;
case K_MEMORY_POKE : { case K_MEMORY_POKE : {
byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2); byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2);
if (!ref) { if (!ref) {
SCIkdebug(SCIkERROR, "Attempt to poke invalid memory at "PREG"!\n", SCIkdebug(SCIkERROR, "Attempt to poke invalid memory at "PREG"!\n",
PRINT_REG(argv[1])); PRINT_REG(argv[1]));
return s->r_acc; return s->r_acc;
} }
if (s->seg_manager.heap[argv[1].segment]->type == MEM_OBJ_LOCALS) if (s->seg_manager.heap[argv[1].segment]->type == MEM_OBJ_LOCALS)
*((reg_t *) ref) = argv[2]; else *((reg_t *) ref) = argv[2];
{ else {
if (argv[2].segment) { if (argv[2].segment) {
SCIkdebug(SCIkERROR, "Attempt to poke memory reference "PREG" to "PREG"!\n", SCIkdebug(SCIkERROR, "Attempt to poke memory reference "PREG" to "PREG"!\n",
PRINT_REG(argv[2]), PRINT_REG(argv[1])); PRINT_REG(argv[2]), PRINT_REG(argv[1]));
return s->r_acc; return s->r_acc;
putInt16(ref, argv[2].offset); putInt16(ref, argv[2].offset);
}
} }
}
return s->r_acc; return s->r_acc;
break; break;
@ -713,16 +697,15 @@ kMemory(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t reg_t
kstub(state_t *s, int funct_nr, int argc, reg_t *argv) kstub(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int i; int i;
SCIkwarn(SCIkWARNING, "Unimplemented syscall: %s[%x](", SCIkwarn(SCIkWARNING, "Unimplemented syscall: %s[%x](",
s->kernel_names[funct_nr], funct_nr); s->kernel_names[funct_nr], funct_nr);
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
sciprintf(PREG, PRINT_REG(argv[i])); sciprintf(PREG, PRINT_REG(argv[i]));
if (i+1 < argc) sciprintf(", "); if (i + 1 < argc) sciprintf(", ");
} }
sciprintf(")\n"); sciprintf(")\n");
return NULL_REG; return NULL_REG;
@ -730,18 +713,16 @@ kstub(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kNOP(state_t *s, int funct_nr, int argc, reg_t *argv) kNOP(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
const char *problem = (const char*)(s->kfunct_table[funct_nr].orig_name ? const char *problem = (const char*)(s->kfunct_table[funct_nr].orig_name ?
"unmapped" : "NOP"); "unmapped" : "NOP");
SCIkwarn(SCIkWARNING, "Warning: Kernel function 0x%02x invoked: %s", funct_nr, problem); SCIkwarn(SCIkWARNING, "Warning: Kernel function 0x%02x invoked: %s", funct_nr, problem);
if (s->kfunct_table[funct_nr].orig_name && if (s->kfunct_table[funct_nr].orig_name &&
strcmp(s->kfunct_table[funct_nr].orig_name, SCRIPT_UNKNOWN_FUNCTION_STRING)) strcmp(s->kfunct_table[funct_nr].orig_name, SCRIPT_UNKNOWN_FUNCTION_STRING)) {
{ sciprintf(" (but its name is known to be %s)", s->kfunct_table[funct_nr].orig_name);
sciprintf(" (but its name is known to be %s)", s->kfunct_table[funct_nr].orig_name); }
}
sciprintf("\n"); sciprintf("\n");
return NULL_REG; return NULL_REG;
@ -750,8 +731,7 @@ kNOP(state_t *s, int funct_nr, int argc, reg_t *argv)
void void
kernel_compile_signature(const char **s) kernel_compile_signature(const char **s) {
{
const char *src = *s; const char *src = *s;
char *result; char *result;
int ellipsis = 0; int ellipsis = 0;
@ -769,8 +749,8 @@ kernel_compile_signature(const char **s)
if (ellipsis) { if (ellipsis) {
sciprintf("INTERNAL ERROR when compiling kernel" sciprintf("INTERNAL ERROR when compiling kernel"
" function signature '%s': non-terminal ellipsis\n", *s, " function signature '%s': non-terminal ellipsis\n", *s,
*src); *src);
exit(1); exit(1);
} }
@ -813,7 +793,7 @@ kernel_compile_signature(const char **s)
case KSIG_SPEC_ALLOW_INV: case KSIG_SPEC_ALLOW_INV:
v |= KSIG_ALLOW_INV; v |= KSIG_ALLOW_INV;
break; break;
case KSIG_SPEC_ELLIPSIS: case KSIG_SPEC_ELLIPSIS:
v |= KSIG_ELLIPSIS; v |= KSIG_ELLIPSIS;
ellipsis = 1; ellipsis = 1;
@ -821,16 +801,16 @@ kernel_compile_signature(const char **s)
default: { default: {
sciprintf("INTERNAL ERROR when compiling kernel" sciprintf("INTERNAL ERROR when compiling kernel"
" function signature '%s': (%02x) not understood (aka" " function signature '%s': (%02x) not understood (aka"
" '%c')\n", " '%c')\n",
*s, c, c); *s, c, c);
exit(1); exit(1);
} }
} }
} while (*src && (*src == KSIG_SPEC_ALLOW_INV || } while (*src && (*src == KSIG_SPEC_ALLOW_INV ||
*src == KSIG_SPEC_ELLIPSIS || *src == KSIG_SPEC_ELLIPSIS ||
(c < 'a' && c != KSIG_SPEC_ANY))); (c < 'a' && c != KSIG_SPEC_ANY)));
/* To handle sum types */ /* To handle sum types */
result[index++] = v; result[index++] = v;
@ -841,22 +821,21 @@ kernel_compile_signature(const char **s)
} }
int int
script_map_kernel(state_t *s) script_map_kernel(state_t *s) {
{
int functnr; int functnr;
int mapped = 0; int mapped = 0;
int ignored = 0; int ignored = 0;
int functions_nr = s->kernel_names_nr; int functions_nr = s->kernel_names_nr;
int max_functions_nr int max_functions_nr
= sci_max_allowed_unknown_kernel_functions[s->resmgr = sci_max_allowed_unknown_kernel_functions[s->resmgr
->sci_version]; ->sci_version];
if (functions_nr < max_functions_nr) { if (functions_nr < max_functions_nr) {
sciprintf("Warning: SCI version believed to have %d kernel" sciprintf("Warning: SCI version believed to have %d kernel"
" functions, but only %d reported-- filling up" " functions, but only %d reported-- filling up"
" remaining %d\n", " remaining %d\n",
max_functions_nr, functions_nr, max_functions_nr, functions_nr,
max_functions_nr - functions_nr); max_functions_nr - functions_nr);
functions_nr = max_functions_nr; functions_nr = max_functions_nr;
} }
@ -875,21 +854,19 @@ script_map_kernel(state_t *s)
if (sought_name) if (sought_name)
for (seeker = 0; (found == -1) for (seeker = 0; (found == -1)
&& kfunct_mappers[seeker].type != KF_TERMINATOR; seeker++) && kfunct_mappers[seeker].type != KF_TERMINATOR; seeker++)
if (kfunct_mappers[seeker].name if (kfunct_mappers[seeker].name
&& strcmp(kfunct_mappers[seeker].name, sought_name) == 0) && strcmp(kfunct_mappers[seeker].name, sought_name) == 0)
found = seeker; /* Found a kernel function with the same name! */ found = seeker; /* Found a kernel function with the same name! */
if (found == -1) { if (found == -1) {
if (sought_name) if (sought_name) {
{
sciprintf("Warning: Kernel function %s[%x] unmapped\n", sciprintf("Warning: Kernel function %s[%x] unmapped\n",
s->kernel_names[functnr], functnr); s->kernel_names[functnr], functnr);
s->kfunct_table[functnr].fun = kNOP; s->kfunct_table[functnr].fun = kNOP;
} else } else {
{
sciprintf("Warning: Flagging kernel function %x as unknown\n", sciprintf("Warning: Flagging kernel function %x as unknown\n",
functnr); functnr);
s->kfunct_table[functnr].fun = k_Unknown; s->kfunct_table[functnr].fun = k_Unknown;
} }
@ -897,26 +874,26 @@ script_map_kernel(state_t *s)
s->kfunct_table[functnr].orig_name = sought_name; s->kfunct_table[functnr].orig_name = sought_name;
} else switch (kfunct_mappers[found].type) { } else switch (kfunct_mappers[found].type) {
case KF_OLD: case KF_OLD:
sciprintf("Emulated kernel function found.\nThis shouldn't happen anymore."); sciprintf("Emulated kernel function found.\nThis shouldn't happen anymore.");
return 1; return 1;
case KF_NONE: case KF_NONE:
s->kfunct_table[functnr].signature = NULL; s->kfunct_table[functnr].signature = NULL;
++ignored; ++ignored;
break; break;
case KF_NEW: case KF_NEW:
s->kfunct_table[functnr] = kfunct_mappers[found].sig_pair; s->kfunct_table[functnr] = kfunct_mappers[found].sig_pair;
kernel_compile_signature(&(s->kfunct_table[functnr].signature)); kernel_compile_signature(&(s->kfunct_table[functnr].signature));
++mapped; ++mapped;
break; break;
} }
} /* for all functions requesting to be mapped */ } /* for all functions requesting to be mapped */
sciprintf("Handled %d/%d kernel functions, mapping %d", sciprintf("Handled %d/%d kernel functions, mapping %d",
mapped+ignored, s->kernel_names_nr, mapped); mapped + ignored, s->kernel_names_nr, mapped);
if (ignored) if (ignored)
sciprintf(" and ignoring %d", ignored); sciprintf(" and ignoring %d", ignored);
sciprintf(".\n"); sciprintf(".\n");
@ -924,15 +901,13 @@ script_map_kernel(state_t *s)
} }
void void
free_kfunct_tables(state_t *s) free_kfunct_tables(state_t *s) {
{
sci_free(s->kfunct_table); sci_free(s->kfunct_table);
s->kfunct_table = NULL; s->kfunct_table = NULL;
} }
int int
determine_reg_type(state_t *s, reg_t reg, int allow_invalid) determine_reg_type(state_t *s, reg_t reg, int allow_invalid) {
{
mem_obj_t *mobj; mem_obj_t *mobj;
if (!reg.segment) { if (!reg.segment) {
@ -942,7 +917,7 @@ determine_reg_type(state_t *s, reg_t reg, int allow_invalid)
} }
if ((reg.segment >= s->seg_manager.heap_size) if ((reg.segment >= s->seg_manager.heap_size)
|| !s->seg_manager.heap[reg.segment]) || !s->seg_manager.heap[reg.segment])
return 0; /* Invalid */ return 0; /* Invalid */
mobj = s->seg_manager.heap[reg.segment]; mobj = s->seg_manager.heap[reg.segment];
@ -951,8 +926,8 @@ determine_reg_type(state_t *s, reg_t reg, int allow_invalid)
case MEM_OBJ_SCRIPT: case MEM_OBJ_SCRIPT:
if (reg.offset <= mobj->data.script.buf_size if (reg.offset <= mobj->data.script.buf_size
&& reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
&& RAW_IS_OBJECT(mobj->data.script.buf + reg.offset)) { && RAW_IS_OBJECT(mobj->data.script.buf + reg.offset)) {
int idx = RAW_GET_CLASS_INDEX(&(mobj->data.script), reg); int idx = RAW_GET_CLASS_INDEX(&(mobj->data.script), reg);
if (idx >= 0 && idx < mobj->data.script.objects_nr) if (idx >= 0 && idx < mobj->data.script.objects_nr)
return KSIG_OBJECT; return KSIG_OBJECT;
@ -981,7 +956,7 @@ determine_reg_type(state_t *s, reg_t reg, int allow_invalid)
case MEM_OBJ_SYS_STRINGS: case MEM_OBJ_SYS_STRINGS:
if (allow_invalid || (reg.offset < SYS_STRINGS_MAX if (allow_invalid || (reg.offset < SYS_STRINGS_MAX
&& mobj->data.sys_strings.strings[reg.offset].name)) && mobj->data.sys_strings.strings[reg.offset].name))
return KSIG_REF; return KSIG_REF;
else else
return KSIG_REF | KSIG_INVALID; return KSIG_REF | KSIG_INVALID;
@ -1011,16 +986,14 @@ determine_reg_type(state_t *s, reg_t reg, int allow_invalid)
} }
const char * const char *
kernel_argtype_description(int type) kernel_argtype_description(int type) {
{ type &= ~KSIG_INVALID;
type &= ~KSIG_INVALID;
return argtype_description[sci_ffs(type)];
return argtype_description[sci_ffs(type)];
} }
int int
kernel_matches_signature(state_t *s, const char *sig, int argc, reg_t *argv) kernel_matches_signature(state_t *s, const char *sig, int argc, reg_t *argv) {
{
if (!sig) if (!sig)
return 1; return 1;
@ -1030,15 +1003,15 @@ kernel_matches_signature(state_t *s, const char *sig, int argc, reg_t *argv)
if (!type) { if (!type) {
sciprintf("[KERN] Could not determine type of ref "PREG";" sciprintf("[KERN] Could not determine type of ref "PREG";"
" failing signature check\n", " failing signature check\n",
PRINT_REG(*argv)); PRINT_REG(*argv));
return 0; return 0;
} }
if (type & KSIG_INVALID) { if (type & KSIG_INVALID) {
sciprintf("[KERN] ref "PREG" was determined to be a %s, " sciprintf("[KERN] ref "PREG" was determined to be a %s, "
"but the reference itself is invalid\n", "but the reference itself is invalid\n",
PRINT_REG(*argv), kernel_argtype_description(type)); PRINT_REG(*argv), kernel_argtype_description(type));
return 0; return 0;
} }
@ -1059,35 +1032,32 @@ kernel_matches_signature(state_t *s, const char *sig, int argc, reg_t *argv)
} }
static inline void * static inline void *
_kernel_dereference_pointer(struct _state *s, reg_t pointer, int entries, int align) _kernel_dereference_pointer(struct _state *s, reg_t pointer, int entries, int align) {
{
int maxsize; int maxsize;
void *retval = sm_dereference(&s->seg_manager, pointer, &maxsize); void *retval = sm_dereference(&s->seg_manager, pointer, &maxsize);
if (pointer.offset & (align-1)) { if (pointer.offset & (align - 1)) {
SCIkdebug(SCIkERROR, "Unaligned pointer read: "PREG" expected with %d alignment!\n", SCIkdebug(SCIkERROR, "Unaligned pointer read: "PREG" expected with %d alignment!\n",
PRINT_REG(pointer), align); PRINT_REG(pointer), align);
return NULL; return NULL;
} }
if (entries > maxsize) { if (entries > maxsize) {
SCIkdebug(SCIkERROR, "Trying to dereference pointer "PREG" beyond end of segment!\n", SCIkdebug(SCIkERROR, "Trying to dereference pointer "PREG" beyond end of segment!\n",
PRINT_REG(pointer)); PRINT_REG(pointer));
return NULL; return NULL;
} }
return retval; return retval;
} }
byte * byte *
kernel_dereference_bulk_pointer(struct _state *s, reg_t pointer, int entries) kernel_dereference_bulk_pointer(struct _state *s, reg_t pointer, int entries) {
{
return (byte*)_kernel_dereference_pointer(s, pointer, entries, 1); return (byte*)_kernel_dereference_pointer(s, pointer, entries, 1);
} }
reg_t * reg_t *
kernel_dereference_reg_pointer(struct _state *s, reg_t pointer, int entries) kernel_dereference_reg_pointer(struct _state *s, reg_t pointer, int entries) {
{
return (reg_t*)_kernel_dereference_pointer(s, pointer, entries, sizeof(reg_t)); return (reg_t*)_kernel_dereference_pointer(s, pointer, entries, sizeof(reg_t));
} }

View file

@ -55,21 +55,19 @@ if ((address) & 1) \
/* Sets a heap value if allowed */ /* Sets a heap value if allowed */
static inline int static inline int
getHeapInt16(unsigned char *base, int address) getHeapInt16(unsigned char *base, int address) {
{ if (address & 1)
if (address & 1) sciprintf("Warning: Unaligned read from %04x\n", (address) & 0xffff);
sciprintf("Warning: Unaligned read from %04x\n", (address) & 0xffff);
return getInt16(base + address); return getInt16(base + address);
} }
static inline unsigned int static inline unsigned int
getHeapUInt16(unsigned char *base, int address) getHeapUInt16(unsigned char *base, int address) {
{ if (address & 1)
if (address & 1) sciprintf("Warning: Unaligned unsigned read from %04x\n", (address) & 0xffff);
sciprintf("Warning: Unaligned unsigned read from %04x\n", (address) & 0xffff);
return getUInt16(base + address); return getUInt16(base + address);
} }

View file

@ -81,7 +81,7 @@ determine_reg_type(state_t *s, reg_t reg, int allow_invalid);
** Parameters: (state_t *) s: The state to operate on ** Parameters: (state_t *) s: The state to operate on
** (reg_t) reg: The register to check ** (reg_t) reg: The register to check
** (int) allow_invalid: Allow invalid pointer values ** (int) allow_invalid: Allow invalid pointer values
** Returns : one of KSIG_* below KSIG_NULL. ** Returns : one of KSIG_* below KSIG_NULL.
** KSIG_INVALID set if the type of reg can be determined, but is invalid. ** KSIG_INVALID set if the type of reg can be determined, but is invalid.
** 0 on error. ** 0 on error.
*/ */

View file

@ -32,14 +32,13 @@ int stop_on_event;
#define SCI_VARIABLE_GAME_SPEED 3 #define SCI_VARIABLE_GAME_SPEED 3
reg_t reg_t
kGetEvent(state_t *s, int funct_nr, int argc, reg_t *argv) kGetEvent(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int mask = UKPV(0); int mask = UKPV(0);
reg_t obj = argv[1]; reg_t obj = argv[1];
sci_event_t e; sci_event_t e;
int oldx, oldy; int oldx, oldy;
int modifier_mask = SCI_VERSION_MAJOR(s->version)==0 ? SCI_EVM_ALL int modifier_mask = SCI_VERSION_MAJOR(s->version) == 0 ? SCI_EVM_ALL
: SCI_EVM_NO_FOOLOCK; : SCI_EVM_NO_FOOLOCK;
if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) { if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) {
/* Penalty time- too many requests to this function without /* Penalty time- too many requests to this function without
@ -48,7 +47,7 @@ kGetEvent(state_t *s, int funct_nr, int argc, reg_t *argv)
gfxop_usleep(s->gfx_state, (1000000 * delay) / 60); gfxop_usleep(s->gfx_state, (1000000 * delay) / 60);
} }
/*If there's a simkey pending, and the game wants a keyboard event, use the /*If there's a simkey pending, and the game wants a keyboard event, use the
*simkey instead of a normal event*/ *simkey instead of a normal event*/
if (_kdebug_cheap_event_hack && (mask & SCI_EVT_KEYBOARD)) { if (_kdebug_cheap_event_hack && (mask & SCI_EVT_KEYBOARD)) {
@ -60,7 +59,7 @@ kGetEvent(state_t *s, int funct_nr, int argc, reg_t *argv)
_kdebug_cheap_event_hack = 0; _kdebug_cheap_event_hack = 0;
return make_reg(0, 1); return make_reg(0, 1);
} }
oldx = s->gfx_state->pointer_pos.x; oldx = s->gfx_state->pointer_pos.x;
oldy = s->gfx_state->pointer_pos.y; oldy = s->gfx_state->pointer_pos.y;
e = gfxop_get_event(s->gfx_state, mask); e = gfxop_get_event(s->gfx_state, mask);
@ -75,7 +74,7 @@ kGetEvent(state_t *s, int funct_nr, int argc, reg_t *argv)
if (e.type) if (e.type)
s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT
| KERNEL_OPT_FLAG_GOT_2NDEVENT); | KERNEL_OPT_FLAG_GOT_2NDEVENT);
else { else {
if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_EVENT) if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_EVENT)
s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_2NDEVENT; s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_2NDEVENT;
@ -83,95 +82,118 @@ kGetEvent(state_t *s, int funct_nr, int argc, reg_t *argv)
s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_EVENT; s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_EVENT;
} }
switch(e.type) switch (e.type) {
{ case SCI_EVT_QUIT:
case SCI_EVT_QUIT: quit_vm();
quit_vm(); break;
break;
case SCI_EVT_KEYBOARD: { case SCI_EVT_KEYBOARD: {
if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT)
&& (e.data == '-')) { && (e.data == '-')) {
sciprintf("Debug mode activated\n"); sciprintf("Debug mode activated\n");
script_debug_flag = 1; /* Enter debug mode */ script_debug_flag = 1; /* Enter debug mode */
_debug_seeking = _debug_step_running = 0; _debug_seeking = _debug_step_running = 0;
s->onscreen_console = 0; s->onscreen_console = 0;
} else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) { } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) {
script_debug_flag = 1; /* Enter debug mode */ script_debug_flag = 1; /* Enter debug mode */
_debug_seeking = _debug_step_running = 0; _debug_seeking = _debug_step_running = 0;
s->onscreen_console = 1; s->onscreen_console = 1;
} else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '1')) { } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '1')) {
if (s->visual) if (s->visual)
s->visual->print(GFXW(s->visual), 0); s->visual->print(GFXW(s->visual), 0);
} else { } else {
PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); /*Keyboard event*/ PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); /*Keyboard event*/
s->r_acc=make_reg(0, 1); s->r_acc = make_reg(0, 1);
PUT_SEL32V(obj, message, e.character); PUT_SEL32V(obj, message, e.character);
/* We only care about the translated /* We only care about the translated
** character */ ** character */
PUT_SEL32V(obj, modifiers, e.buckybits&modifier_mask); PUT_SEL32V(obj, modifiers, e.buckybits&modifier_mask);
}
} break;
case SCI_EVT_MOUSE_RELEASE:
case SCI_EVT_MOUSE_PRESS: {
int extra_bits=0;
if(mask & e.type) {
switch(e.data) {
case 2: extra_bits=SCI_EVM_LSHIFT|SCI_EVM_RSHIFT; break;
case 3: extra_bits=SCI_EVM_CTRL;
default:break;
}
PUT_SEL32V(obj, type, e.type);
PUT_SEL32V(obj, message, 1);
PUT_SEL32V(obj, modifiers, (e.buckybits|extra_bits)&modifier_mask);
s->r_acc = make_reg(0, 1);
}
} break;
default: {
s->r_acc = NULL_REG; /* Unknown or no event */
} }
}
break;
case SCI_EVT_MOUSE_RELEASE:
case SCI_EVT_MOUSE_PRESS: {
int extra_bits = 0;
if (mask & e.type) {
switch (e.data) {
case 2:
extra_bits = SCI_EVM_LSHIFT | SCI_EVM_RSHIFT;
break;
case 3:
extra_bits = SCI_EVM_CTRL;
default:
break;
}
PUT_SEL32V(obj, type, e.type);
PUT_SEL32V(obj, message, 1);
PUT_SEL32V(obj, modifiers, (e.buckybits | extra_bits)&modifier_mask);
s->r_acc = make_reg(0, 1);
} }
}
break;
default: {
s->r_acc = NULL_REG; /* Unknown or no event */
}
}
if ((s->r_acc.offset) && (stop_on_event)) { if ((s->r_acc.offset) && (stop_on_event)) {
stop_on_event = 0; stop_on_event = 0;
script_debug_flag = 1; script_debug_flag = 1;
} }
return s->r_acc; return s->r_acc;
} }
reg_t reg_t
kMapKeyToDir(state_t *s, int funct_nr, int argc, reg_t *argv) kMapKeyToDir(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t obj = argv[0]; reg_t obj = argv[0];
if (GET_SEL32V(obj, type) == SCI_EVT_KEYBOARD) { /* Keyboard */ if (GET_SEL32V(obj, type) == SCI_EVT_KEYBOARD) { /* Keyboard */
int mover = -1; int mover = -1;
switch (GET_SEL32V(obj, message)) { switch (GET_SEL32V(obj, message)) {
case SCI_K_HOME: mover = 8; break; case SCI_K_HOME:
case SCI_K_UP: mover = 1; break; mover = 8;
case SCI_K_PGUP: mover = 2; break; break;
case SCI_K_LEFT: mover = 7; break; case SCI_K_UP:
mover = 1;
break;
case SCI_K_PGUP:
mover = 2;
break;
case SCI_K_LEFT:
mover = 7;
break;
case SCI_K_CENTER: case SCI_K_CENTER:
case 76: mover = 0; break; case 76:
case SCI_K_RIGHT: mover = 3; break; mover = 0;
case SCI_K_END: mover = 6; break; break;
case SCI_K_DOWN: mover = 5; break; case SCI_K_RIGHT:
case SCI_K_PGDOWN: mover = 4; break; mover = 3;
default: break; break;
case SCI_K_END:
mover = 6;
break;
case SCI_K_DOWN:
mover = 5;
break;
case SCI_K_PGDOWN:
mover = 4;
break;
default:
break;
} }
if (mover >= 0) { if (mover >= 0) {
@ -186,8 +208,7 @@ kMapKeyToDir(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kGlobalToLocal(state_t *s, int funct_nr, int argc, reg_t *argv) kGlobalToLocal(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t obj = argc ? argv[0] : NULL_REG; /* Can this really happen? Lars */ reg_t obj = argc ? argv[0] : NULL_REG; /* Can this really happen? Lars */
if (obj.segment) { if (obj.segment) {
@ -204,8 +225,7 @@ kGlobalToLocal(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kLocalToGlobal(state_t *s, int funct_nr, int argc, reg_t *argv) kLocalToGlobal(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t obj = argc ? argv[0] : NULL_REG; /* Can this really happen? Lars */ reg_t obj = argc ? argv[0] : NULL_REG; /* Can this really happen? Lars */
if (obj.segment) { if (obj.segment) {
@ -220,8 +240,7 @@ kLocalToGlobal(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t /* Not implemented */ reg_t /* Not implemented */
kJoystick(state_t *s, int funct_nr, int argc, reg_t *argv) kJoystick(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
SCIkdebug(SCIkSTUB, "Unimplemented syscall 'Joystick()'\n", funct_nr); SCIkdebug(SCIkSTUB, "Unimplemented syscall 'Joystick()'\n", funct_nr);
return NULL_REG; return NULL_REG;
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -33,8 +33,7 @@
#endif #endif
inline node_t * inline node_t *
inline_lookup_node(state_t *s, reg_t addr, const char *file, int line) inline_lookup_node(state_t *s, reg_t addr, const char *file, int line) {
{
mem_obj_t *mobj; mem_obj_t *mobj;
node_table_t *nt; node_table_t *nt;
@ -44,7 +43,7 @@ inline_lookup_node(state_t *s, reg_t addr, const char *file, int line)
mobj = GET_SEGMENT(s->seg_manager, addr.segment, MEM_OBJ_NODES); mobj = GET_SEGMENT(s->seg_manager, addr.segment, MEM_OBJ_NODES);
if (!mobj) { if (!mobj) {
sciprintf("%s, L%d: Attempt to use non-node "PREG" as list node\n", sciprintf("%s, L%d: Attempt to use non-node "PREG" as list node\n",
__FILE__, __LINE__, PRINT_REG(addr)); __FILE__, __LINE__, PRINT_REG(addr));
script_debug_flag = script_error_flag = 1; script_debug_flag = script_error_flag = 1;
return NULL; return NULL;
} }
@ -53,7 +52,7 @@ inline_lookup_node(state_t *s, reg_t addr, const char *file, int line)
if (!ENTRY_IS_VALID(nt, addr.offset)) { if (!ENTRY_IS_VALID(nt, addr.offset)) {
sciprintf("%s, L%d: Attempt to use non-node "PREG" as list node\n", sciprintf("%s, L%d: Attempt to use non-node "PREG" as list node\n",
__FILE__, __LINE__, PRINT_REG(addr)); __FILE__, __LINE__, PRINT_REG(addr));
script_debug_flag = script_error_flag = 1; script_debug_flag = script_error_flag = 1;
return NULL; return NULL;
} }
@ -62,8 +61,7 @@ inline_lookup_node(state_t *s, reg_t addr, const char *file, int line)
} }
node_t * node_t *
lookup_node(state_t *s, reg_t addr, const char *file, int line) lookup_node(state_t *s, reg_t addr, const char *file, int line) {
{
return inline_lookup_node(s, addr, file, line); return inline_lookup_node(s, addr, file, line);
} }
@ -71,8 +69,7 @@ lookup_node(state_t *s, reg_t addr, const char *file, int line)
inline list_t * inline list_t *
_lookup_list(state_t *s, reg_t addr, const char *file, int line, int may_be_null) _lookup_list(state_t *s, reg_t addr, const char *file, int line, int may_be_null) {
{
mem_obj_t *mobj; mem_obj_t *mobj;
list_table_t *lt; list_table_t *lt;
@ -83,7 +80,7 @@ _lookup_list(state_t *s, reg_t addr, const char *file, int line, int may_be_null
if (!mobj) { if (!mobj) {
sciprintf("%s, L%d: Attempt to use non-list "PREG" as list\n", sciprintf("%s, L%d: Attempt to use non-list "PREG" as list\n",
__FILE__, __LINE__, PRINT_REG(addr)); __FILE__, __LINE__, PRINT_REG(addr));
script_debug_flag = script_error_flag = 1; script_debug_flag = script_error_flag = 1;
return NULL; return NULL;
} }
@ -92,7 +89,7 @@ _lookup_list(state_t *s, reg_t addr, const char *file, int line, int may_be_null
if (!ENTRY_IS_VALID(lt, addr.offset)) { if (!ENTRY_IS_VALID(lt, addr.offset)) {
sciprintf("%s, L%d: Attempt to use non-list "PREG" as list\n", sciprintf("%s, L%d: Attempt to use non-list "PREG" as list\n",
__FILE__, __LINE__, PRINT_REG(addr)); __FILE__, __LINE__, PRINT_REG(addr));
script_debug_flag = script_error_flag = 1; script_debug_flag = script_error_flag = 1;
return NULL; return NULL;
} }
@ -101,16 +98,14 @@ _lookup_list(state_t *s, reg_t addr, const char *file, int line, int may_be_null
} }
list_t * list_t *
lookup_list(state_t *s, reg_t addr, const char *file, int line) lookup_list(state_t *s, reg_t addr, const char *file, int line) {
{
return _lookup_list(s, addr, file, line, 0); return _lookup_list(s, addr, file, line, 0);
} }
int int
listp(state_t *s, reg_t addr) listp(state_t *s, reg_t addr) {
{
return (s->seg_manager.heap[addr.segment]->type == MEM_OBJ_LISTS return (s->seg_manager.heap[addr.segment]->type == MEM_OBJ_LISTS
&& ENTRY_IS_VALID(&(s->seg_manager.heap[addr.segment]->data.lists), addr.offset)); && ENTRY_IS_VALID(&(s->seg_manager.heap[addr.segment]->data.lists), addr.offset));
} }
#ifdef DISABLE_VALIDATIONS #ifdef DISABLE_VALIDATIONS
@ -121,8 +116,7 @@ listp(state_t *s, reg_t addr)
#else #else
static inline int static inline int
sane_nodep(state_t *s, reg_t addr) sane_nodep(state_t *s, reg_t addr) {
{
int have_prev = 0; int have_prev = 0;
reg_t prev = addr; reg_t prev = addr;
@ -133,7 +127,7 @@ sane_nodep(state_t *s, reg_t addr)
return 0; return 0;
if ((have_prev) if ((have_prev)
&& !REG_EQ(node->pred, prev)) && !REG_EQ(node->pred, prev))
return 0; return 0;
prev = addr; prev = addr;
@ -147,8 +141,7 @@ sane_nodep(state_t *s, reg_t addr)
int int
sane_listp(state_t *s, reg_t addr) sane_listp(state_t *s, reg_t addr) {
{
list_t *l = LOOKUP_LIST(addr); list_t *l = LOOKUP_LIST(addr);
int empties = 0; int empties = 0;
@ -185,8 +178,7 @@ sane_listp(state_t *s, reg_t addr)
reg_t reg_t
kNewList(state_t *s, int funct_nr, int argc, reg_t *argv) kNewList(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t listbase; reg_t listbase;
list_t *l; list_t *l;
l = sm_alloc_list(&s->seg_manager, &listbase); l = sm_alloc_list(&s->seg_manager, &listbase);
@ -197,39 +189,37 @@ kNewList(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t reg_t
kDisposeList(state_t *s, int funct_nr, int argc, reg_t *argv) kDisposeList(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
list_t *l = LOOKUP_LIST(argv[0]); list_t *l = LOOKUP_LIST(argv[0]);
if (!l) { if (!l) {
SCIkwarn(SCIkERROR, "Attempt to dispose non-list at "PREG"!\n", SCIkwarn(SCIkERROR, "Attempt to dispose non-list at "PREG"!\n",
PRINT_REG(argv[0])); PRINT_REG(argv[0]));
return NULL_REG; return NULL_REG;
} }
if (!sane_listp(s, argv[0])) if (!sane_listp(s, argv[0]))
SCIkwarn(SCIkERROR,"List at "PREG" is not sane anymore!\n", PRINT_REG(argv[0])); SCIkwarn(SCIkERROR, "List at "PREG" is not sane anymore!\n", PRINT_REG(argv[0]));
/* if (!IS_NULL_REG(l->first)) { /* if (!IS_NULL_REG(l->first)) {
reg_t n_addr = l->first; reg_t n_addr = l->first;
while (!IS_NULL_REG(n_addr)) { /-* Free all nodes *-/ while (!IS_NULL_REG(n_addr)) { /-* Free all nodes *-/
node_t *n = LOOKUP_NODE(n_addr); node_t *n = LOOKUP_NODE(n_addr);
sm_free_node(&s->seg_manager, n_addr); sm_free_node(&s->seg_manager, n_addr);
n_addr = n->succ; n_addr = n->succ;
} }
} }
sm_free_list(&s->seg_manager, argv[0]); sm_free_list(&s->seg_manager, argv[0]);
*/ */
return s->r_acc; return s->r_acc;
} }
inline reg_t inline reg_t
_k_new_node(state_t *s, reg_t value, reg_t key) _k_new_node(state_t *s, reg_t value, reg_t key) {
{
reg_t nodebase; reg_t nodebase;
node_t *n = sm_alloc_node(&s->seg_manager, &nodebase); node_t *n = sm_alloc_node(&s->seg_manager, &nodebase);
@ -246,8 +236,7 @@ _k_new_node(state_t *s, reg_t value, reg_t key)
} }
reg_t reg_t
kNewNode(state_t *s, int funct_nr, int argc, reg_t *argv) kNewNode(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
s->r_acc = _k_new_node(s, argv[0], argv[1]); s->r_acc = _k_new_node(s, argv[0], argv[1]);
SCIkdebug(SCIkNODES, "New nodebase at "PREG"\n", PRINT_REG(s->r_acc)); SCIkdebug(SCIkNODES, "New nodebase at "PREG"\n", PRINT_REG(s->r_acc));
@ -258,13 +247,12 @@ kNewNode(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kFirstNode(state_t *s, int funct_nr, int argc, reg_t *argv) kFirstNode(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
list_t *l = LOOKUP_NULL_LIST(argv[0]); list_t *l = LOOKUP_NULL_LIST(argv[0]);
if (l && !sane_listp(s, argv[0])) if (l && !sane_listp(s, argv[0]))
SCIkwarn(SCIkERROR,"List at "PREG" is not sane anymore!\n", SCIkwarn(SCIkERROR, "List at "PREG" is not sane anymore!\n",
PRINT_REG(argv[0])); PRINT_REG(argv[0]));
if (l) if (l)
return l->first; return l->first;
@ -274,13 +262,12 @@ kFirstNode(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kLastNode(state_t *s, int funct_nr, int argc, reg_t *argv) kLastNode(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
list_t *l = LOOKUP_LIST(argv[0]); list_t *l = LOOKUP_LIST(argv[0]);
if (l&&!sane_listp(s, argv[0])) if (l && !sane_listp(s, argv[0]))
SCIkwarn(SCIkERROR,"List at "PREG" is not sane anymore!\n", SCIkwarn(SCIkERROR, "List at "PREG" is not sane anymore!\n",
PRINT_REG(argv[0])); PRINT_REG(argv[0]));
if (l) if (l)
return l->last; return l->last;
@ -290,31 +277,29 @@ kLastNode(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kEmptyList(state_t *s, int funct_nr, int argc, reg_t *argv) kEmptyList(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
list_t *l = LOOKUP_LIST(argv[0]); list_t *l = LOOKUP_LIST(argv[0]);
if (!l || !sane_listp(s, argv[0])) if (!l || !sane_listp(s, argv[0]))
SCIkwarn(SCIkERROR,"List at "PREG" is invalid or not sane anymore!\n", SCIkwarn(SCIkERROR, "List at "PREG" is invalid or not sane anymore!\n",
PRINT_REG(argv[0])); PRINT_REG(argv[0]));
return make_reg(0, ((l)? IS_NULL_REG(l->first) : 0)); return make_reg(0, ((l) ? IS_NULL_REG(l->first) : 0));
} }
inline void inline void
_k_add_to_front(state_t *s, reg_t listbase, reg_t nodebase) _k_add_to_front(state_t *s, reg_t listbase, reg_t nodebase) {
{
list_t *l = LOOKUP_LIST(listbase); list_t *l = LOOKUP_LIST(listbase);
node_t *new_n = LOOKUP_NODE(nodebase); node_t *new_n = LOOKUP_NODE(nodebase);
SCIkdebug(SCIkNODES, "Adding node "PREG" to end of list "PREG"\n", SCIkdebug(SCIkNODES, "Adding node "PREG" to end of list "PREG"\n",
PRINT_REG(nodebase), PRINT_REG(listbase)); PRINT_REG(nodebase), PRINT_REG(listbase));
if (!new_n) if (!new_n)
SCIkwarn(SCIkERROR, "Attempt to add non-node ("PREG") to list at "PREG"\n", SCIkwarn(SCIkERROR, "Attempt to add non-node ("PREG") to list at "PREG"\n",
PRINT_REG(nodebase), PRINT_REG(listbase)); PRINT_REG(nodebase), PRINT_REG(listbase));
if (!l || !sane_listp(s, listbase)) if (!l || !sane_listp(s, listbase))
SCIkwarn(SCIkERROR,"List at "PREG" is not sane anymore!\n", PRINT_REG(listbase)); SCIkwarn(SCIkERROR, "List at "PREG" is not sane anymore!\n", PRINT_REG(listbase));
new_n->succ = l->first; new_n->succ = l->first;
new_n->pred = NULL_REG; new_n->pred = NULL_REG;
@ -329,19 +314,18 @@ _k_add_to_front(state_t *s, reg_t listbase, reg_t nodebase)
} }
inline void inline void
_k_add_to_end(state_t *s, reg_t listbase, reg_t nodebase) _k_add_to_end(state_t *s, reg_t listbase, reg_t nodebase) {
{
list_t *l = LOOKUP_LIST(listbase); list_t *l = LOOKUP_LIST(listbase);
node_t *new_n = LOOKUP_NODE(nodebase); node_t *new_n = LOOKUP_NODE(nodebase);
SCIkdebug(SCIkNODES, "Adding node "PREG" to end of list "PREG"\n", SCIkdebug(SCIkNODES, "Adding node "PREG" to end of list "PREG"\n",
PRINT_REG(nodebase), PRINT_REG(listbase)); PRINT_REG(nodebase), PRINT_REG(listbase));
if (!new_n) if (!new_n)
SCIkwarn(SCIkERROR, "Attempt to add non-node ("PREG") to list at "PREG"\n", SCIkwarn(SCIkERROR, "Attempt to add non-node ("PREG") to list at "PREG"\n",
PRINT_REG(nodebase), PRINT_REG(listbase)); PRINT_REG(nodebase), PRINT_REG(listbase));
if (!l || !sane_listp(s, listbase)) if (!l || !sane_listp(s, listbase))
SCIkwarn(SCIkERROR,"List at "PREG" is not sane anymore!\n", PRINT_REG(listbase)); SCIkwarn(SCIkERROR, "List at "PREG" is not sane anymore!\n", PRINT_REG(listbase));
new_n->succ = NULL_REG; new_n->succ = NULL_REG;
new_n->pred = l->last; new_n->pred = l->last;
@ -357,13 +341,11 @@ _k_add_to_end(state_t *s, reg_t listbase, reg_t nodebase)
reg_t reg_t
kNextNode(state_t *s, int funct_nr, int argc, reg_t *argv) kNextNode(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
node_t *n = LOOKUP_NODE(argv[0]); node_t *n = LOOKUP_NODE(argv[0]);
if (!sane_nodep(s, argv[0])) if (!sane_nodep(s, argv[0])) {
{ SCIkwarn(SCIkERROR, "List node at "PREG" is not sane anymore!\n",
SCIkwarn(SCIkERROR,"List node at "PREG" is not sane anymore!\n", PRINT_REG(argv[0]));
PRINT_REG(argv[0]));
script_error_flag = script_debug_flag = 0; script_error_flag = script_debug_flag = 0;
return NULL_REG; return NULL_REG;
} }
@ -372,25 +354,22 @@ kNextNode(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t reg_t
kPrevNode(state_t *s, int funct_nr, int argc, reg_t *argv) kPrevNode(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
node_t *n = LOOKUP_NODE(argv[0]); node_t *n = LOOKUP_NODE(argv[0]);
if (!sane_nodep(s, argv[0])) if (!sane_nodep(s, argv[0]))
SCIkwarn(SCIkERROR,"List node at "PREG" is not sane anymore!\n", SCIkwarn(SCIkERROR, "List node at "PREG" is not sane anymore!\n",
PRINT_REG(argv[0])); PRINT_REG(argv[0]));
return n->pred; return n->pred;
} }
reg_t reg_t
kNodeValue(state_t *s, int funct_nr, int argc, reg_t *argv) kNodeValue(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
node_t *n = LOOKUP_NODE(argv[0]); node_t *n = LOOKUP_NODE(argv[0]);
if (!sane_nodep(s, argv[0])) if (!sane_nodep(s, argv[0])) {
{ SCIkwarn(SCIkERROR, "List node at "PREG" is not sane!\n",
SCIkwarn(SCIkERROR,"List node at "PREG" is not sane!\n", PRINT_REG(argv[0]));
PRINT_REG(argv[0]));
script_debug_flag = script_error_flag = 0; script_debug_flag = script_error_flag = 0;
return NULL_REG; return NULL_REG;
} }
@ -400,26 +379,24 @@ kNodeValue(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kAddToFront(state_t *s, int funct_nr, int argc, reg_t *argv) kAddToFront(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
_k_add_to_front(s, argv[0], argv[1]); _k_add_to_front(s, argv[0], argv[1]);
return s->r_acc; return s->r_acc;
} }
reg_t reg_t
kAddAfter(state_t *s, int funct_nr, int argc, reg_t *argv) kAddAfter(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
list_t *l = LOOKUP_LIST(argv[0]); list_t *l = LOOKUP_LIST(argv[0]);
node_t *firstnode = IS_NULL_REG(argv[1])? NULL : LOOKUP_NODE(argv[1]); node_t *firstnode = IS_NULL_REG(argv[1]) ? NULL : LOOKUP_NODE(argv[1]);
node_t *newnode = LOOKUP_NODE(argv[2]); node_t *newnode = LOOKUP_NODE(argv[2]);
if (!l || !sane_listp(s, argv[0])) if (!l || !sane_listp(s, argv[0]))
SCIkwarn(SCIkERROR,"List at "PREG" is not sane anymore!\n", SCIkwarn(SCIkERROR, "List at "PREG" is not sane anymore!\n",
PRINT_REG(argv[0])); PRINT_REG(argv[0]));
if (!newnode) { if (!newnode) {
SCIkwarn(SCIkERROR,"New 'node' "PREG" is not a node!\n", SCIkwarn(SCIkERROR, "New 'node' "PREG" is not a node!\n",
argv[1], argv[2]); argv[1], argv[2]);
return NULL_REG; return NULL_REG;
} }
@ -452,26 +429,24 @@ kAddAfter(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kAddToEnd(state_t *s, int funct_nr, int argc, reg_t *argv) kAddToEnd(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
_k_add_to_end(s, argv[0], argv[1]); _k_add_to_end(s, argv[0], argv[1]);
return s->r_acc; return s->r_acc;
} }
reg_t reg_t
kFindKey(state_t *s, int funct_nr, int argc, reg_t *argv) kFindKey(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t node_pos; reg_t node_pos;
reg_t key = argv[1]; reg_t key = argv[1];
reg_t list_pos = argv[0]; reg_t list_pos = argv[0];
SCIkdebug(SCIkNODES, "Looking for key "PREG" in list "PREG"\n", SCIkdebug(SCIkNODES, "Looking for key "PREG" in list "PREG"\n",
PRINT_REG(key), PRINT_REG(list_pos)); PRINT_REG(key), PRINT_REG(list_pos));
if (!sane_listp(s, list_pos)) if (!sane_listp(s, list_pos))
SCIkwarn(SCIkERROR,"List at "PREG" is not sane anymore!\n", SCIkwarn(SCIkERROR, "List at "PREG" is not sane anymore!\n",
PRINT_REG(list_pos)); PRINT_REG(list_pos));
node_pos = LOOKUP_LIST(list_pos)->first; node_pos = LOOKUP_LIST(list_pos)->first;
@ -494,8 +469,7 @@ kFindKey(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kDeleteKey(state_t *s, int funct_nr, int argc, reg_t *argv) kDeleteKey(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t node_pos = kFindKey(s, funct_nr, 2, argv); reg_t node_pos = kFindKey(s, funct_nr, 2, argv);
node_t *n; node_t *n;
list_t *l = LOOKUP_LIST(argv[0]); list_t *l = LOOKUP_LIST(argv[0]);
@ -514,7 +488,7 @@ kDeleteKey(state_t *s, int funct_nr, int argc, reg_t *argv)
if (!IS_NULL_REG(n->succ)) if (!IS_NULL_REG(n->succ))
LOOKUP_NODE(n->succ)->pred = n->pred; LOOKUP_NODE(n->succ)->pred = n->pred;
/* sm_free_node(&s->seg_manager, node_pos);*/ /* sm_free_node(&s->seg_manager, node_pos);*/
return make_reg(0, 1); /* Signal success */ return make_reg(0, 1); /* Signal success */
} }
@ -522,34 +496,31 @@ kDeleteKey(state_t *s, int funct_nr, int argc, reg_t *argv)
typedef struct typedef struct {
{
reg_t key, value; reg_t key, value;
reg_t order; reg_t order;
} sort_temp_t; } sort_temp_t;
int int
sort_temp_cmp(const void *p1, const void *p2) sort_temp_cmp(const void *p1, const void *p2) {
{
sort_temp_t *st1 = (sort_temp_t *) p1; sort_temp_t *st1 = (sort_temp_t *) p1;
sort_temp_t *st2 = (sort_temp_t *) p2; sort_temp_t *st2 = (sort_temp_t *) p2;
if (st1->order.segment < st1->order.segment || if (st1->order.segment < st1->order.segment ||
(st1->order.segment == st1->order.segment && (st1->order.segment == st1->order.segment &&
st1->order.offset < st2->order.offset)) st1->order.offset < st2->order.offset))
return -1; return -1;
if (st1->order.segment > st2->order.segment || if (st1->order.segment > st2->order.segment ||
(st1->order.segment == st2->order.segment && (st1->order.segment == st2->order.segment &&
st1->order.offset > st2->order.offset)) st1->order.offset > st2->order.offset))
return 1; return 1;
return 0; return 0;
} }
reg_t reg_t
kSort(state_t *s, int funct_nr, int argc, reg_t *argv) kSort(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t source = argv[0]; reg_t source = argv[0];
reg_t dest = argv[1]; reg_t dest = argv[1];
reg_t order_func = argv[2]; reg_t order_func = argv[2];
@ -558,8 +529,8 @@ kSort(state_t *s, int funct_nr, int argc, reg_t *argv)
int i; int i;
sort_temp_t *temp_array = (sort_temp_t *) sort_temp_t *temp_array = (sort_temp_t *)
malloc(sizeof(sort_temp_t)*input_size); malloc(sizeof(sort_temp_t) * input_size);
reg_t input_data = GET_SEL32(source, elements); reg_t input_data = GET_SEL32(source, elements);
reg_t output_data = GET_SEL32(dest, elements); reg_t output_data = GET_SEL32(dest, elements);
@ -570,8 +541,7 @@ kSort(state_t *s, int funct_nr, int argc, reg_t *argv)
if (!input_size) if (!input_size)
return s->r_acc; return s->r_acc;
if (IS_NULL_REG(output_data)) if (IS_NULL_REG(output_data)) {
{
list = sm_alloc_list(&s->seg_manager, &output_data); list = sm_alloc_list(&s->seg_manager, &output_data);
list->first = list->last = NULL_REG; list->first = list->last = NULL_REG;
PUT_SEL32(dest, elements, output_data); PUT_SEL32(dest, elements, output_data);
@ -583,8 +553,7 @@ kSort(state_t *s, int funct_nr, int argc, reg_t *argv)
node = LOOKUP_NODE(list->first); node = LOOKUP_NODE(list->first);
i = 0; i = 0;
while (node) while (node) {
{
invoke_selector(INV_SEL(order_func, doit, 0), 1, node->value); invoke_selector(INV_SEL(order_func, doit, 0), 1, node->value);
temp_array[i].key = node->key; temp_array[i].key = node->key;
temp_array[i].value = node->value; temp_array[i].value = node->value;
@ -595,10 +564,9 @@ kSort(state_t *s, int funct_nr, int argc, reg_t *argv)
qsort(temp_array, input_size, sizeof(sort_temp_t), sort_temp_cmp); qsort(temp_array, input_size, sizeof(sort_temp_t), sort_temp_cmp);
for (i=0;i<input_size;i++) for (i = 0;i < input_size;i++) {
{
reg_t lNode = _k_new_node(s, temp_array[i].key, reg_t lNode = _k_new_node(s, temp_array[i].key,
temp_array[i].value); temp_array[i].value);
_k_add_to_end(s, output_data, lNode); _k_add_to_end(s, output_data, lNode);
} }

View file

@ -29,16 +29,14 @@
reg_t reg_t
kRandom(state_t *s, int funct_nr, int argc, reg_t *argv) kRandom(state_t *s, int funct_nr, int argc, reg_t *argv) {
{ return make_reg(0,
return make_reg(0, SKPV(0) + (int)((SKPV(1) + 1.0 - SKPV(0)) * (rand() / (RAND_MAX + 1.0))));
SKPV(0) + (int) ((SKPV(1) + 1.0 - SKPV(0)) * (rand() / (RAND_MAX + 1.0))));
} }
reg_t reg_t
kAbs(state_t *s, int funct_nr, int argc, reg_t *argv) kAbs(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
/* This is a hack, but so is the code in Hoyle1 that needs it. */ /* This is a hack, but so is the code in Hoyle1 that needs it. */
if (argv[0].segment) if (argv[0].segment)
return make_reg(0, 0x3e8); /* Yes people, this is an object */ return make_reg(0, 0x3e8); /* Yes people, this is an object */
@ -47,19 +45,17 @@ kAbs(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kSqrt(state_t *s, int funct_nr, int argc, reg_t *argv) kSqrt(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
return make_reg(0, (gint16) sqrt((float) abs(SKPV(0)))); return make_reg(0, (gint16) sqrt((float) abs(SKPV(0))));
} }
int int
get_angle(int xrel, int yrel) get_angle(int xrel, int yrel) {
{
if ((xrel == 0) && (yrel == 0)) if ((xrel == 0) && (yrel == 0))
return 0; return 0;
else { else {
int val = (int) (180.0/PI * atan2((double)xrel, (double)-yrel)); int val = (int)(180.0 / PI * atan2((double)xrel, (double) - yrel));
if (val < 0) if (val < 0)
val += 360; val += 360;
@ -67,7 +63,7 @@ get_angle(int xrel, int yrel)
FSCI. SCI games sometimes check for equality with FSCI. SCI games sometimes check for equality with
"round" angles */ "round" angles */
if (val % 45 == 44) if (val % 45 == 44)
val++; val++;
else if (val % 45 == 1) else if (val % 45 == 1)
val--; val--;
@ -76,8 +72,7 @@ get_angle(int xrel, int yrel)
} }
reg_t reg_t
kGetAngle(state_t *s, int funct_nr, int argc, reg_t *argv) kGetAngle(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
/* Based on behavior observed with a test program created with /* Based on behavior observed with a test program created with
** SCI Studio. ** SCI Studio.
*/ */
@ -89,7 +84,7 @@ kGetAngle(state_t *s, int funct_nr, int argc, reg_t *argv)
int yrel = y1 - y2; /* y-axis is mirrored. */ int yrel = y1 - y2; /* y-axis is mirrored. */
int angle; int angle;
/* Move (xrel, yrel) to first quadrant. */ /* Move (xrel, yrel) to first quadrant. */
if (y1 < y2) if (y1 < y2)
yrel = -yrel; yrel = -yrel;
if (x2 < x1) if (x2 < x1)
@ -118,64 +113,58 @@ kGetAngle(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kGetDistance(state_t *s, int funct_nr, int argc, reg_t *argv) kGetDistance(state_t *s, int funct_nr, int argc, reg_t *argv) {
{ int xrel = (int)(((float) SKPV(1) - SKPV_OR_ALT(3, 0)) / cos(SKPV_OR_ALT(5, 0) * PI / 180.0)); /* This works because cos(0)==1 */
int xrel = (int) (((float) SKPV(1) - SKPV_OR_ALT(3, 0))/cos(SKPV_OR_ALT(5, 0)* PI / 180.0)); /* This works because cos(0)==1 */ int yrel = SKPV(0) - SKPV_OR_ALT(2, 0);
int yrel = SKPV(0) - SKPV_OR_ALT(2, 0);
return make_reg(0, (gint16)sqrt((float) xrel*xrel + yrel*yrel)); return make_reg(0, (gint16)sqrt((float) xrel*xrel + yrel*yrel));
} }
reg_t reg_t
kTimesSin(state_t *s, int funct_nr, int argc, reg_t *argv) kTimesSin(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int angle = SKPV(0); int angle = SKPV(0);
int factor = SKPV(1); int factor = SKPV(1);
return make_reg(0, (int) (factor * 1.0 * sin(angle * PI / 180.0))); return make_reg(0, (int)(factor * 1.0 * sin(angle * PI / 180.0)));
} }
reg_t reg_t
kTimesCos(state_t *s, int funct_nr, int argc, reg_t *argv) kTimesCos(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int angle = SKPV(0); int angle = SKPV(0);
int factor = SKPV(1); int factor = SKPV(1);
return make_reg(0, (int) (factor * 1.0 * cos(angle * PI / 180.0))); return make_reg(0, (int)(factor * 1.0 * cos(angle * PI / 180.0)));
} }
reg_t reg_t
kCosDiv(state_t *s, int funct_nr, int argc, reg_t *argv) kCosDiv(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int angle = SKPV(0); int angle = SKPV(0);
int value = SKPV(1); int value = SKPV(1);
double cosval = cos(angle * PI / 180.0); double cosval = cos(angle * PI / 180.0);
if ((cosval < 0.0001) && (cosval > 0.0001)) { if ((cosval < 0.0001) && (cosval > 0.0001)) {
SCIkwarn(SCIkWARNING,"Attepted division by zero\n"); SCIkwarn(SCIkWARNING, "Attepted division by zero\n");
return make_reg(0, (gint16)0x8000); return make_reg(0, (gint16)0x8000);
} else } else
return make_reg(0, (gint16) (value/cosval)); return make_reg(0, (gint16)(value / cosval));
} }
reg_t reg_t
kSinDiv(state_t *s, int funct_nr, int argc, reg_t *argv) kSinDiv(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int angle = SKPV(0); int angle = SKPV(0);
int value = SKPV(1); int value = SKPV(1);
double sinval = sin(angle * PI / 180.0); double sinval = sin(angle * PI / 180.0);
if ((sinval < 0.0001) && (sinval > 0.0001)) { if ((sinval < 0.0001) && (sinval > 0.0001)) {
SCIkwarn(SCIkWARNING,"Attepted division by zero\n"); SCIkwarn(SCIkWARNING, "Attepted division by zero\n");
return make_reg(0, (gint16)0x8000); return make_reg(0, (gint16)0x8000);
} else } else
return make_reg(0, (gint16) (value/sinval)); return make_reg(0, (gint16)(value / sinval));
} }
reg_t reg_t
kTimesTan(state_t *s, int funct_nr, int argc, reg_t *argv) kTimesTan(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int param = SKPV(0); int param = SKPV(0);
int scale = SKPV_OR_ALT(1, 1); int scale = SKPV_OR_ALT(1, 1);
@ -184,12 +173,11 @@ kTimesTan(state_t *s, int funct_nr, int argc, reg_t *argv)
SCIkwarn(SCIkWARNING, "Attempted tan(pi/2)"); SCIkwarn(SCIkWARNING, "Attempted tan(pi/2)");
return make_reg(0, (gint16)0x8000); return make_reg(0, (gint16)0x8000);
} else } else
return make_reg(0, (gint16) -(tan(param * PI / 180.0) * scale)); return make_reg(0, (gint16) - (tan(param * PI / 180.0) * scale));
} }
reg_t reg_t
kTimesCot(state_t *s, int funct_nr, int argc, reg_t *argv) kTimesCot(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int param = SKPV(0); int param = SKPV(0);
int scale = SKPV_OR_ALT(1, 1); int scale = SKPV_OR_ALT(1, 1);
@ -197,5 +185,5 @@ kTimesCot(state_t *s, int funct_nr, int argc, reg_t *argv)
SCIkwarn(SCIkWARNING, "Attempted tan(pi/2)"); SCIkwarn(SCIkWARNING, "Attempted tan(pi/2)");
return make_reg(0, (gint16)0x8000); return make_reg(0, (gint16)0x8000);
} else } else
return make_reg(0, (gint16) (tan(param * PI / 180.0) * scale)); return make_reg(0, (gint16)(tan(param * PI / 180.0) * scale));
} }

View file

@ -31,13 +31,12 @@
reg_t reg_t
kAddMenu(state_t *s, int funct_nr, int argc, reg_t *argv) kAddMenu(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
char *name = kernel_dereference_char_pointer(s, argv[0], 0); char *name = kernel_dereference_char_pointer(s, argv[0], 0);
char *contents = kernel_dereference_char_pointer(s, argv[1], 0); char *contents = kernel_dereference_char_pointer(s, argv[1], 0);
menubar_add_menu(s->gfx_state, s->menubar, name, menubar_add_menu(s->gfx_state, s->menubar, name,
contents, s->titlebar_port->font_nr, argv[1]); contents, s->titlebar_port->font_nr, argv[1]);
return s->r_acc; return s->r_acc;
@ -45,8 +44,7 @@ kAddMenu(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kSetMenu(state_t *s, int funct_nr, int argc, reg_t *argv) kSetMenu(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int index = UKPV(0); int index = UKPV(0);
int i = 2; int i = 2;
@ -59,8 +57,7 @@ kSetMenu(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t reg_t
kGetMenu(state_t *s, int funct_nr, int argc, reg_t *argv) kGetMenu(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int index = UKPV(0); int index = UKPV(0);
return menubar_get_attribute(s, (index >> 8) - 1, (index & 0xff) - 1, UKPV(1)); return menubar_get_attribute(s, (index >> 8) - 1, (index & 0xff) - 1, UKPV(1));
@ -68,8 +65,7 @@ kGetMenu(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kDrawStatus(state_t *s, int funct_nr, int argc, reg_t *argv) kDrawStatus(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t text = argv[0]; reg_t text = argv[0];
int fgcolor = SKPV_OR_ALT(1, s->status_bar_foreground); int fgcolor = SKPV_OR_ALT(1, s->status_bar_foreground);
int bgcolor = SKPV_OR_ALT(2, s->status_bar_background); int bgcolor = SKPV_OR_ALT(2, s->status_bar_background);
@ -79,8 +75,8 @@ kDrawStatus(state_t *s, int funct_nr, int argc, reg_t *argv)
s->titlebar_port->bgcolor.visual = *(get_pic_color(s, bgcolor)); s->titlebar_port->bgcolor.visual = *(get_pic_color(s, bgcolor));
s->titlebar_port->bgcolor.mask = GFX_MASK_VISUAL; s->titlebar_port->bgcolor.mask = GFX_MASK_VISUAL;
s->status_bar_foreground=fgcolor; s->status_bar_foreground = fgcolor;
s->status_bar_background=bgcolor; s->status_bar_background = bgcolor;
if (NULL != s->status_bar_text) { if (NULL != s->status_bar_text) {
sci_free(s->status_bar_text); sci_free(s->status_bar_text);
@ -99,8 +95,7 @@ kDrawStatus(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kDrawMenuBar(state_t *s, int funct_nr, int argc, reg_t *argv) kDrawMenuBar(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
if (SKPV(0)) if (SKPV(0))
sciw_set_menubar(s, s->titlebar_port, s->menubar, -1); sciw_set_menubar(s, s->titlebar_port, s->menubar, -1);
@ -122,20 +117,20 @@ static struct {
int fgcolor, bgcolor; int fgcolor, bgcolor;
} _about_freesci_pages[ABOUT_FREESCI_PAGES_NR] = { } _about_freesci_pages[ABOUT_FREESCI_PAGES_NR] = {
{"FreeSCI hackers and contributors", {"FreeSCI hackers and contributors",
"Alexander R. Angas\nDirectX 8 driver, Event sound server, Generic memory functions" "Alexander R. Angas\nDirectX 8 driver, Event sound server, Generic memory functions"
"\n\n" "\n\n"
"Anders Baden Nielsen\nPPC testing" "Anders Baden Nielsen\nPPC testing"
"\n\n" "\n\n"
"Bas Zoetekouw\nMan pages, debian package management, CVS maintenance" "Bas Zoetekouw\nMan pages, debian package management, CVS maintenance"
"\n\n" "\n\n"
"Carl Muckenhoupt\nSources to the SCI resource viewer tools that started it all" "Carl Muckenhoupt\nSources to the SCI resource viewer tools that started it all"
"\n\n" "\n\n"
"Chris Kehler\nMakefile enhancements" "Chris Kehler\nMakefile enhancements"
"\n\n" "\n\n"
"Christoph Reichenbach\nUN*X code, VM/Graphics/Sound/other infrastructure" "Christoph Reichenbach\nUN*X code, VM/Graphics/Sound/other infrastructure"
"\n\n" "\n\n"
"Christopher T. Lansdown\nOriginal CVS maintainer, Alpha compatibility fixes" "Christopher T. Lansdown\nOriginal CVS maintainer, Alpha compatibility fixes"
,0, 15}, , 0, 15},
{"More FreeSCI hackers and contributors", {"More FreeSCI hackers and contributors",
"Claudio Matsuoka\nCVS snapshots, daily builds, BeOS and cygwin ports" "Claudio Matsuoka\nCVS snapshots, daily builds, BeOS and cygwin ports"
"\n\n" "\n\n"
@ -150,7 +145,7 @@ static struct {
"George Reid\nFreeBSD package management" "George Reid\nFreeBSD package management"
"\n\n" "\n\n"
"Hubert Maier\nAmigaOS 4 port" "Hubert Maier\nAmigaOS 4 port"
,0, 15}, , 0, 15},
{"Even more FreeSCI hackers & contributors", {"Even more FreeSCI hackers & contributors",
"Hugues Valois\nGame selection menu" "Hugues Valois\nGame selection menu"
"\n\n" "\n\n"
@ -165,7 +160,7 @@ static struct {
"Matt Hargett\nClean-ups, bugfixes, Hardcore QA, Win32" "Matt Hargett\nClean-ups, bugfixes, Hardcore QA, Win32"
"\n\n" "\n\n"
"Max Horn\nSetJump implementation" "Max Horn\nSetJump implementation"
,0, 15}, , 0, 15},
{"Still more of them", {"Still more of them",
"Paul David Doherty\nGame version information" "Paul David Doherty\nGame version information"
"\n\n" "\n\n"
@ -180,7 +175,7 @@ static struct {
"Ruediger Hanke\nPort to the MorphOS platform" "Ruediger Hanke\nPort to the MorphOS platform"
"\n\n" "\n\n"
"Rune Orsval\nConfiguration file editor" "Rune Orsval\nConfiguration file editor"
,0, 15}, , 0, 15},
{"Is there no end to these contributors?", {"Is there no end to these contributors?",
"Rickard Lind\nMT32->GM MIDI mapping magic, sound research" "Rickard Lind\nMT32->GM MIDI mapping magic, sound research"
"\n\n" "\n\n"
@ -199,18 +194,17 @@ static struct {
{"The CSCI5573 Team at CU Boulder", {"The CSCI5573 Team at CU Boulder",
"Xiaojun Chen\nSean Terrell\nChristoph Reichenbach\n\n" "Xiaojun Chen\nSean Terrell\nChristoph Reichenbach\n\n"
"Special thanks to Prof. Dr. Gary Nutt\n\nfor allowing the FreeSCI VM extension as a\ncourse project in his Advanced OS course" "Special thanks to Prof. Dr. Gary Nutt\n\nfor allowing the FreeSCI VM extension as a\ncourse project in his Advanced OS course"
,0, 15}, , 0, 15},
{"Special Thanks", {"Special Thanks",
"Special Thanks as well\n\n\nto the linuxgames.com and telefragged.com crew\nfor hosting us\n\n" "Special Thanks as well\n\n\nto the linuxgames.com and telefragged.com crew\nfor hosting us\n\n"
"To the savannah.gnu.org staff\nfor hosting our mailing list\n\n" "To the savannah.gnu.org staff\nfor hosting our mailing list\n\n"
"To Bob Heitman and Corey Cole for their support" "To Bob Heitman and Corey Cole for their support"
,0, 15} , 0, 15}
}; };
void void
about_freesci(state_t *s) about_freesci(state_t *s) {
{
int page; int page;
gfxw_port_t *port; gfxw_port_t *port;
int bodyfont, titlefont; int bodyfont, titlefont;
@ -228,7 +222,7 @@ about_freesci(state_t *s)
return; return;
} }
bodyfont = i+1; bodyfont = i + 1;
for (page = 0; page < ABOUT_FREESCI_PAGES_NR; ++page) { for (page = 0; page < ABOUT_FREESCI_PAGES_NR; ++page) {
sci_event_t event; sci_event_t event;
int cont = 2; int cont = 2;
@ -238,9 +232,9 @@ about_freesci(state_t *s)
_about_freesci_pages[page].bgcolor = 15; _about_freesci_pages[page].bgcolor = 15;
gfxop_get_text_params(s->gfx_state, bodyfont, _about_freesci_pages[page].body, 300, &width, &height, 0, gfxop_get_text_params(s->gfx_state, bodyfont, _about_freesci_pages[page].body, 300, &width, &height, 0,
NULL, NULL, NULL); NULL, NULL, NULL);
gfxop_get_text_params(s->gfx_state, titlefont, _about_freesci_pages[page].title, 300, &width2, &foo, 0, gfxop_get_text_params(s->gfx_state, titlefont, _about_freesci_pages[page].title, 300, &width2, &foo, 0,
NULL, NULL, NULL); NULL, NULL, NULL);
width += 4; width += 4;
width2 += 4; width2 += 4;
@ -250,21 +244,21 @@ about_freesci(state_t *s)
width = width2; width = width2;
port = sciw_new_window(s, gfx_rect(156 - (width >> 1), 100 - (height >> 1), width, height), port = sciw_new_window(s, gfx_rect(156 - (width >> 1), 100 - (height >> 1), width, height),
bodyfont, s->ega_colors[_about_freesci_pages[page].fgcolor], bodyfont, s->ega_colors[_about_freesci_pages[page].fgcolor],
s->ega_colors[_about_freesci_pages[page].bgcolor], s->ega_colors[_about_freesci_pages[page].bgcolor],
titlefont, s->ega_colors[15], s->ega_colors[0], titlefont, s->ega_colors[15], s->ega_colors[0],
_about_freesci_pages[page].title, WINDOW_FLAG_TITLE); _about_freesci_pages[page].title, WINDOW_FLAG_TITLE);
port->add(GFXWC(port), GFXW(gfxw_new_text(s->gfx_state, gfx_rect(0,0,width,height), bodyfont, port->add(GFXWC(port), GFXW(gfxw_new_text(s->gfx_state, gfx_rect(0, 0, width, height), bodyfont,
_about_freesci_pages[page].body, _about_freesci_pages[page].body,
ALIGN_CENTER, ALIGN_CENTER, port->color, port->color, ALIGN_CENTER, ALIGN_CENTER, port->color, port->color,
port->bgcolor, 0) port->bgcolor, 0)
)); ));
s->visual->add(GFXWC(s->visual), GFXW(port)); s->visual->add(GFXWC(s->visual), GFXW(port));
port->add_dirty_abs(GFXWC(port), gfx_rect_fullscreen, 1); port->add_dirty_abs(GFXWC(port), gfx_rect_fullscreen, 1);
s->visual->draw(GFXW(s->visual), gfx_point(0,0)); s->visual->draw(GFXW(s->visual), gfx_point(0, 0));
gfxop_update(s->gfx_state); gfxop_update(s->gfx_state);
while (cont) { while (cont) {
@ -286,7 +280,7 @@ about_freesci(state_t *s)
port->widfree(GFXW(port)); port->widfree(GFXW(port));
s->visual->draw(GFXW(s->visual), gfx_point(0,0)); s->visual->draw(GFXW(s->visual), gfx_point(0, 0));
gfxop_update(s->gfx_state); gfxop_update(s->gfx_state);
} }
@ -294,8 +288,7 @@ about_freesci(state_t *s)
static inline int static inline int
_menu_go_down(state_t *s, int menu_nr, int item_nr) _menu_go_down(state_t *s, int menu_nr, int item_nr) {
{
int seeker, max = s->menubar->menus[menu_nr].items_nr; int seeker, max = s->menubar->menus[menu_nr].items_nr;
seeker = item_nr + 1; seeker = item_nr + 1;
@ -313,8 +306,7 @@ _menu_go_down(state_t *s, int menu_nr, int item_nr)
reg_t reg_t
kMenuSelect(state_t *s, int funct_nr, int argc, reg_t *argv) kMenuSelect(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t event = argv[0]; reg_t event = argv[0];
/*int pause_sound = UKPV_OR_ALT(1, 1);*/ /* FIXME: Do this eventually */ /*int pause_sound = UKPV_OR_ALT(1, 1);*/ /* FIXME: Do this eventually */
int claimed = 0; int claimed = 0;
@ -333,33 +325,33 @@ kMenuSelect(state_t *s, int funct_nr, int argc, reg_t *argv)
int menuc, itemc; int menuc, itemc;
if ((type == SCI_EVT_KEYBOARD) if ((type == SCI_EVT_KEYBOARD)
&& (message == SCI_K_ESC)) && (message == SCI_K_ESC))
menu_mode = 1; menu_mode = 1;
else if ((type == SCI_EVT_SAID) || message) { /* Don't claim 0 keyboard event */ else if ((type == SCI_EVT_SAID) || message) { /* Don't claim 0 keyboard event */
SCIkdebug(SCIkMENU,"Menu: Got %s event: %04x/%04x\n", SCIkdebug(SCIkMENU, "Menu: Got %s event: %04x/%04x\n",
((type == SCI_EVT_SAID)? "SAID":"KBD"), message, modifiers); ((type == SCI_EVT_SAID) ? "SAID" : "KBD"), message, modifiers);
for (menuc = 0; menuc < s->menubar->menus_nr; menuc++) for (menuc = 0; menuc < s->menubar->menus_nr; menuc++)
for (itemc = 0; itemc < s->menubar->menus[menuc].items_nr; itemc++) { for (itemc = 0; itemc < s->menubar->menus[menuc].items_nr; itemc++) {
item = s->menubar->menus[menuc].items + itemc; item = s->menubar->menus[menuc].items + itemc;
SCIkdebug(SCIkMENU,"Menu: Checking against %s: %04x/%04x (type %d, %s)\n", SCIkdebug(SCIkMENU, "Menu: Checking against %s: %04x/%04x (type %d, %s)\n",
item->text? item->text : "--bar--", item->key, item->modifiers, item->text ? item->text : "--bar--", item->key, item->modifiers,
item->type, item->enabled? "enabled":"disabled"); item->type, item->enabled ? "enabled" : "disabled");
if (((item->type == MENU_TYPE_NORMAL) if (((item->type == MENU_TYPE_NORMAL)
&& (item->enabled)) && (item->enabled))
&& (((type == SCI_EVT_KEYBOARD) /* keyboard event */ && (((type == SCI_EVT_KEYBOARD) /* keyboard event */
&& menubar_match_key(item, message, modifiers)) && menubar_match_key(item, message, modifiers))
|| ((type == SCI_EVT_SAID) /* Said event */ || ((type == SCI_EVT_SAID) /* Said event */
&& (item->flags & MENU_ATTRIBUTE_FLAGS_SAID) && (item->flags & MENU_ATTRIBUTE_FLAGS_SAID)
&& (said(s, item->said, (s->debug_mode & (1 << SCIkPARSER_NR))) != SAID_NO_MATCH) && (said(s, item->said, (s->debug_mode & (1 << SCIkPARSER_NR))) != SAID_NO_MATCH)
) )
) )
) { ) {
/* Claim the event */ /* Claim the event */
SCIkdebug(SCIkMENU,"Menu: Event CLAIMED for %d/%d\n", menuc, itemc); SCIkdebug(SCIkMENU, "Menu: Event CLAIMED for %d/%d\n", menuc, itemc);
claimed = 1; claimed = 1;
menu_nr = menuc; menu_nr = menuc;
item_nr = itemc; item_nr = itemc;
@ -526,8 +518,7 @@ kMenuSelect(state_t *s, int funct_nr, int argc, reg_t *argv)
s->r_acc = NULL_REG; s->r_acc = NULL_REG;
SCIkdebug(SCIkMENU, "Menu: Claim -> %04x\n", s->r_acc.offset); SCIkdebug(SCIkMENU, "Menu: Claim -> %04x\n", s->r_acc.offset);
} } else s->r_acc = NULL_REG; /* Not claimed */
else s->r_acc = NULL_REG; /* Not claimed */
return s->r_acc; return s->r_acc;
} }

View file

@ -29,17 +29,17 @@
#include "sci/include/engine.h" #include "sci/include/engine.h"
/* /*
Compute "velocity" vector (xStep,yStep)=(vx,vy) for a jump from (0,0) to (dx,dy), with gravity gy. Compute "velocity" vector (xStep,yStep)=(vx,vy) for a jump from (0,0) to (dx,dy), with gravity gy.
The gravity is assumed to be non-negative. The gravity is assumed to be non-negative.
If this was ordinary continuous physics, we would compute the desired (floating point!) If this was ordinary continuous physics, we would compute the desired (floating point!)
velocity vector (vx,vy) as follows, under the assumption that vx and vy are linearly correlated velocity vector (vx,vy) as follows, under the assumption that vx and vy are linearly correlated
by some constant factor c, i.e. vy = c * vx: by some constant factor c, i.e. vy = c * vx:
dx = t * vx dx = t * vx
dy = t * vy + gy * t^2 / 2 dy = t * vy + gy * t^2 / 2
=> dy = c * dx + gy * (dx/vx)^2 / 2 => dy = c * dx + gy * (dx/vx)^2 / 2
=> |vx| = sqrt( gy * dx^2 / (2 * (dy - c * dx)) ) => |vx| = sqrt( gy * dx^2 / (2 * (dy - c * dx)) )
Here, the sign of vx must be chosen equal to the sign of dx, obviously. Here, the sign of vx must be chosen equal to the sign of dx, obviously.
Clearly, this square root only makes sense in our context if the denominator is positive, Clearly, this square root only makes sense in our context if the denominator is positive,
or equivalently, (dy - c * dx) must be positive. For simplicity and by symmetry or equivalently, (dy - c * dx) must be positive. For simplicity and by symmetry
@ -65,8 +65,7 @@ Still, what we compute in the end is of course not a real velocity anymore, but
used in an iterative stepping algorithm used in an iterative stepping algorithm
*/ */
reg_t reg_t
kSetJump(state_t *s, int funct_nr, int argc, reg_t *argv) kSetJump(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
// Input data // Input data
reg_t object = argv[0]; reg_t object = argv[0];
int dx = SKPV(1); int dx = SKPV(1);
@ -98,18 +97,18 @@ kSetJump(state_t *s, int funct_nr, int argc, reg_t *argv)
// we ensure vx will be less than sqrt(gy * dx)). // we ensure vx will be less than sqrt(gy * dx)).
if (dx + dy < 0) { if (dx + dy < 0) {
// dy is negative and |dy| > |dx| // dy is negative and |dy| > |dx|
c = (2*abs(dy)) / dx; c = (2 * abs(dy)) / dx;
//tmp = abs(dy); // ALMOST the resulting value, except for obvious rounding issues //tmp = abs(dy); // ALMOST the resulting value, except for obvious rounding issues
} else { } else {
// dy is either positive, or |dy| <= |dx| // dy is either positive, or |dy| <= |dx|
c = (dx*3/2 - dy) / dx; c = (dx * 3 / 2 - dy) / dx;
// We force c to be strictly positive // We force c to be strictly positive
if (c < 1) if (c < 1)
c = 1; c = 1;
//tmp = dx*3/2; // ALMOST the resulting value, except for obvious rounding issues //tmp = dx*3/2; // ALMOST the resulting value, except for obvious rounding issues
// FIXME: Where is the 3 coming from? Maybe they hard/coded, by "accident", that usually gy=3 ? // FIXME: Where is the 3 coming from? Maybe they hard/coded, by "accident", that usually gy=3 ?
// Then this choice of will make t equal to roughly sqrt(dx) // Then this choice of will make t equal to roughly sqrt(dx)
} }
@ -121,7 +120,7 @@ kSetJump(state_t *s, int funct_nr, int argc, reg_t *argv)
SCIkdebug(SCIkBRESEN, "c: %d, tmp: %d\n", c, tmp); SCIkdebug(SCIkBRESEN, "c: %d, tmp: %d\n", c, tmp);
// Compute x step // Compute x step
if (tmp != 0) if (tmp != 0)
vx = (int)(dx * sqrt(gy / (2.0 * tmp))); vx = (int)(dx * sqrt(gy / (2.0 * tmp)));
@ -131,7 +130,7 @@ kSetJump(state_t *s, int funct_nr, int argc, reg_t *argv)
// Restore the left/right direction: dx and vx should have the same sign. // Restore the left/right direction: dx and vx should have the same sign.
if (dxWasNegative) if (dxWasNegative)
vx = -vx; vx = -vx;
if ((dy < 0) && (vx == 0)) { if ((dy < 0) && (vx == 0)) {
// Special case: If this was a jump (almost) straight upward, i.e. dy < 0 (upward), // Special case: If this was a jump (almost) straight upward, i.e. dy < 0 (upward),
// and vx == 0 (i.e. no horizontal movement, at least not after rounding), then we // and vx == 0 (i.e. no horizontal movement, at least not after rounding), then we
@ -154,10 +153,10 @@ kSetJump(state_t *s, int funct_nr, int argc, reg_t *argv)
SCIkdebug(SCIkBRESEN, "SetJump for object at "PREG"\n", PRINT_REG(object)); SCIkdebug(SCIkBRESEN, "SetJump for object at "PREG"\n", PRINT_REG(object));
SCIkdebug(SCIkBRESEN, "xStep: %d, yStep: %d\n", vx, vy); SCIkdebug(SCIkBRESEN, "xStep: %d, yStep: %d\n", vx, vy);
PUT_SEL32V(object, xStep, vx); PUT_SEL32V(object, xStep, vx);
PUT_SEL32V(object, yStep, vy); PUT_SEL32V(object, yStep, vy);
return s->r_acc; return s->r_acc;
} }
@ -166,13 +165,12 @@ kSetJump(state_t *s, int funct_nr, int argc, reg_t *argv)
void void
initialize_bresen(state_t *s, int funct_nr, int argc, reg_t *argv, reg_t mover, int step_factor, initialize_bresen(state_t *s, int funct_nr, int argc, reg_t *argv, reg_t mover, int step_factor,
int deltax, int deltay) int deltax, int deltay) {
{
reg_t client = GET_SEL32(mover, client); reg_t client = GET_SEL32(mover, client);
int stepx = GET_SEL32SV(client, xStep) * step_factor; int stepx = GET_SEL32SV(client, xStep) * step_factor;
int stepy = GET_SEL32SV(client, yStep) * step_factor; int stepy = GET_SEL32SV(client, yStep) * step_factor;
int numsteps_x = stepx? (abs(deltax) + stepx-1) / stepx : 0; int numsteps_x = stepx ? (abs(deltax) + stepx - 1) / stepx : 0;
int numsteps_y = stepy? (abs(deltay) + stepy-1) / stepy : 0; int numsteps_y = stepy ? (abs(deltay) + stepy - 1) / stepy : 0;
int bdi, i1; int bdi, i1;
int numsteps; int numsteps;
int deltax_step; int deltax_step;
@ -180,35 +178,35 @@ initialize_bresen(state_t *s, int funct_nr, int argc, reg_t *argv, reg_t mover,
if (numsteps_x > numsteps_y) { if (numsteps_x > numsteps_y) {
numsteps = numsteps_x; numsteps = numsteps_x;
deltax_step = (deltax < 0)? -stepx : stepx; deltax_step = (deltax < 0) ? -stepx : stepx;
deltay_step = numsteps? deltay / numsteps : deltay; deltay_step = numsteps ? deltay / numsteps : deltay;
} else { /* numsteps_x <= numsteps_y */ } else { /* numsteps_x <= numsteps_y */
numsteps = numsteps_y; numsteps = numsteps_y;
deltay_step = (deltay < 0)? -stepy : stepy; deltay_step = (deltay < 0) ? -stepy : stepy;
deltax_step = numsteps? deltax / numsteps : deltax; deltax_step = numsteps ? deltax / numsteps : deltax;
} }
/* if (abs(deltax) > abs(deltay)) {*/ /* Bresenham on y */ /* if (abs(deltax) > abs(deltay)) {*/ /* Bresenham on y */
if (numsteps_y < numsteps_x) { if (numsteps_y < numsteps_x) {
PUT_SEL32V(mover, b_xAxis, _K_BRESEN_AXIS_Y); PUT_SEL32V(mover, b_xAxis, _K_BRESEN_AXIS_Y);
PUT_SEL32V(mover, b_incr, (deltay < 0)? -1 : 1); PUT_SEL32V(mover, b_incr, (deltay < 0) ? -1 : 1);
/* /*
i1 = 2 * (abs(deltay) - abs(deltay_step * numsteps)) * abs(deltax_step); i1 = 2 * (abs(deltay) - abs(deltay_step * numsteps)) * abs(deltax_step);
bdi = -abs(deltax); bdi = -abs(deltax);
*/ */
i1 = 2*(abs(deltay) - abs(deltay_step * (numsteps - 1))) * abs(deltax_step); i1 = 2 * (abs(deltay) - abs(deltay_step * (numsteps - 1))) * abs(deltax_step);
bdi = -abs(deltax); bdi = -abs(deltax);
} else { /* Bresenham on x */ } else { /* Bresenham on x */
PUT_SEL32V(mover, b_xAxis, _K_BRESEN_AXIS_X); PUT_SEL32V(mover, b_xAxis, _K_BRESEN_AXIS_X);
PUT_SEL32V(mover, b_incr, (deltax < 0)? -1 : 1); PUT_SEL32V(mover, b_incr, (deltax < 0) ? -1 : 1);
/* /*
i1= 2 * (abs(deltax) - abs(deltax_step * numsteps)) * abs(deltay_step); i1= 2 * (abs(deltax) - abs(deltax_step * numsteps)) * abs(deltay_step);
bdi = -abs(deltay); bdi = -abs(deltay);
*/ */
i1 = 2*(abs(deltax) - abs(deltax_step * (numsteps - 1))) * abs(deltay_step); i1 = 2 * (abs(deltax) - abs(deltax_step * (numsteps - 1))) * abs(deltay_step);
bdi = -abs(deltay); bdi = -abs(deltay);
} }
@ -218,9 +216,9 @@ initialize_bresen(state_t *s, int funct_nr, int argc, reg_t *argv, reg_t mover,
SCIkdebug(SCIkBRESEN, "Init bresen for mover "PREG": d=(%d,%d)\n", PRINT_REG(mover), deltax, deltay); SCIkdebug(SCIkBRESEN, "Init bresen for mover "PREG": d=(%d,%d)\n", PRINT_REG(mover), deltax, deltay);
SCIkdebug(SCIkBRESEN, " steps=%d, mv=(%d, %d), i1= %d, i2=%d\n", SCIkdebug(SCIkBRESEN, " steps=%d, mv=(%d, %d), i1= %d, i2=%d\n",
numsteps, deltax_step, deltay_step, i1, bdi*2); numsteps, deltax_step, deltay_step, i1, bdi*2);
/* PUT_SEL32V(mover, b_movCnt, numsteps); *//* Needed for HQ1/Ogre? */ /* PUT_SEL32V(mover, b_movCnt, numsteps); *//* Needed for HQ1/Ogre? */
PUT_SEL32V(mover, b_di, bdi); PUT_SEL32V(mover, b_di, bdi);
PUT_SEL32V(mover, b_i1, i1); PUT_SEL32V(mover, b_i1, i1);
PUT_SEL32V(mover, b_i2, bdi * 2); PUT_SEL32V(mover, b_i2, bdi * 2);
@ -228,8 +226,7 @@ initialize_bresen(state_t *s, int funct_nr, int argc, reg_t *argv, reg_t mover,
} }
reg_t reg_t
kInitBresen(state_t *s, int funct_nr, int argc, reg_t *argv) kInitBresen(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t mover = argv[0]; reg_t mover = argv[0];
reg_t client = GET_SEL32(mover, client); reg_t client = GET_SEL32(mover, client);
@ -250,17 +247,15 @@ static enum {
INCREMENT_MOVECNT, INCREMENT_MOVECNT,
UNINITIALIZED UNINITIALIZED
} handle_movecnt = UNINITIALIZED; } handle_movecnt = UNINITIALIZED;
int parse_reg_t(state_t *s, const char *str, reg_t *dest); /* In scriptconsole.c */ int parse_reg_t(state_t *s, const char *str, reg_t *dest); /* In scriptconsole.c */
static int static int
checksum_bytes(byte *data, int size) checksum_bytes(byte *data, int size) {
{
int result = 0; int result = 0;
int i; int i;
for (i = 0; i < size; i++) for (i = 0; i < size; i++) {
{
result += *data; result += *data;
data++; data++;
} }
@ -269,45 +264,39 @@ checksum_bytes(byte *data, int size)
} }
static void static void
bresenham_autodetect(state_t *s) bresenham_autodetect(state_t *s) {
{
reg_t motion_class; reg_t motion_class;
if (!parse_reg_t(s, "?Motion", &motion_class)) if (!parse_reg_t(s, "?Motion", &motion_class)) {
{
object_t *obj = obj_get(s, motion_class); object_t *obj = obj_get(s, motion_class);
reg_t fptr; reg_t fptr;
byte *buf; byte *buf;
if (obj == NULL) if (obj == NULL) {
{ SCIkwarn(SCIkWARNING, "bresenham_autodetect failed!");
SCIkwarn(SCIkWARNING,"bresenham_autodetect failed!");
handle_movecnt = INCREMENT_MOVECNT; /* Most games do this, so best guess */ handle_movecnt = INCREMENT_MOVECNT; /* Most games do this, so best guess */
return; return;
} }
if (lookup_selector(s, motion_class, s->selector_map.doit, NULL, &fptr) != SELECTOR_METHOD) if (lookup_selector(s, motion_class, s->selector_map.doit, NULL, &fptr) != SELECTOR_METHOD) {
{ SCIkwarn(SCIkWARNING, "bresenham_autodetect failed!");
SCIkwarn(SCIkWARNING,"bresenham_autodetect failed!");
handle_movecnt = INCREMENT_MOVECNT; /* Most games do this, so best guess */ handle_movecnt = INCREMENT_MOVECNT; /* Most games do this, so best guess */
return; return;
} }
buf = s->seg_manager.heap[fptr.segment]->data.script.buf + fptr.offset; buf = s->seg_manager.heap[fptr.segment]->data.script.buf + fptr.offset;
handle_movecnt = (SCI_VERSION_MAJOR(s->version) == 0 || handle_movecnt = (SCI_VERSION_MAJOR(s->version) == 0 ||
checksum_bytes(buf, 8) == 0x216) ? INCREMENT_MOVECNT : IGNORE_MOVECNT; checksum_bytes(buf, 8) == 0x216) ? INCREMENT_MOVECNT : IGNORE_MOVECNT;
sciprintf("b-moveCnt action based on checksum: %s\n", handle_movecnt == IGNORE_MOVECNT ? sciprintf("b-moveCnt action based on checksum: %s\n", handle_movecnt == IGNORE_MOVECNT ?
"ignore" : "increment"); "ignore" : "increment");
} else } else {
{ SCIkwarn(SCIkWARNING, "bresenham_autodetect failed!");
SCIkwarn(SCIkWARNING,"bresenham_autodetect failed!");
handle_movecnt = INCREMENT_MOVECNT; /* Most games do this, so best guess */ handle_movecnt = INCREMENT_MOVECNT; /* Most games do this, so best guess */
} }
} }
reg_t reg_t
kDoBresen(state_t *s, int funct_nr, int argc, reg_t *argv) kDoBresen(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t mover = argv[0]; reg_t mover = argv[0];
reg_t client = GET_SEL32(mover, client); reg_t client = GET_SEL32(mover, client);
@ -318,8 +307,8 @@ kDoBresen(state_t *s, int funct_nr, int argc, reg_t *argv)
int completed = 0; int completed = 0;
int max_movcnt = GET_SEL32V(client, moveSpeed); int max_movcnt = GET_SEL32V(client, moveSpeed);
if (SCI_VERSION_MAJOR(s->version)>0) if (SCI_VERSION_MAJOR(s->version) > 0)
signal&=~_K_VIEW_SIG_FLAG_HIT_OBSTACLE; signal &= ~_K_VIEW_SIG_FLAG_HIT_OBSTACLE;
if (handle_movecnt == UNINITIALIZED) if (handle_movecnt == UNINITIALIZED)
bresenham_autodetect(s); bresenham_autodetect(s);
@ -340,16 +329,12 @@ kDoBresen(state_t *s, int funct_nr, int argc, reg_t *argv)
// sciprintf("movecnt %d, move speed %d\n", movcnt, max_movcnt); // sciprintf("movecnt %d, move speed %d\n", movcnt, max_movcnt);
if (handle_movecnt) if (handle_movecnt) {
{ if (max_movcnt > movcnt) {
if (max_movcnt > movcnt)
{
++movcnt; ++movcnt;
PUT_SEL32V(mover, b_movCnt, movcnt); /* Needed for HQ1/Ogre? */ PUT_SEL32V(mover, b_movCnt, movcnt); /* Needed for HQ1/Ogre? */
return NULL_REG; return NULL_REG;
} } else {
else
{
movcnt = 0; movcnt = 0;
PUT_SEL32V(mover, b_movCnt, movcnt); /* Needed for HQ1/Ogre? */ PUT_SEL32V(mover, b_movCnt, movcnt); /* Needed for HQ1/Ogre? */
} }
@ -369,33 +354,33 @@ kDoBresen(state_t *s, int funct_nr, int argc, reg_t *argv)
x += dx; x += dx;
y += dy; y += dy;
if ((MOVING_ON_X if ((MOVING_ON_X
&& (((x < destx) && (oldx >= destx)) /* Moving left, exceeded? */ && (((x < destx) && (oldx >= destx)) /* Moving left, exceeded? */
|| ||
((x > destx) && (oldx <= destx)) /* Moving right, exceeded? */ ((x > destx) && (oldx <= destx)) /* Moving right, exceeded? */
|| ||
((x == destx) && (abs(dx) > abs(dy))) /* Moving fast, reached? */ ((x == destx) && (abs(dx) > abs(dy))) /* Moving fast, reached? */
/* Treat this last case specially- when doing sub-pixel movements /* Treat this last case specially- when doing sub-pixel movements
** on the other axis, we could still be far away from the destination */ ** on the other axis, we could still be far away from the destination */
) )
)
|| (MOVING_ON_Y
&& (((y < desty) && (oldy >= desty)) /* Moving upwards, exceeded? */
||
((y > desty) && (oldy <= desty)) /* Moving downwards, exceeded? */
||
((y == desty) && (abs(dy) >= abs(dx))) /* Moving fast, reached? */
)
)
) )
|| (MOVING_ON_Y
&& (((y < desty) && (oldy >= desty)) /* Moving upwards, exceeded? */
||
((y > desty) && (oldy <= desty)) /* Moving downwards, exceeded? */
||
((y == desty) && (abs(dy) >= abs(dx))) /* Moving fast, reached? */
)
)
)
/* Whew... in short: If we have reached or passed our target position */ /* Whew... in short: If we have reached or passed our target position */
{ {
x = destx; x = destx;
y = desty; y = desty;
completed = 1; completed = 1;
SCIkdebug(SCIkBRESEN, "Finished mover "PREG"\n", PRINT_REG(mover)); SCIkdebug(SCIkBRESEN, "Finished mover "PREG"\n", PRINT_REG(mover));
} }
PUT_SEL32V(client, x, x); PUT_SEL32V(client, x, x);
@ -404,8 +389,9 @@ kDoBresen(state_t *s, int funct_nr, int argc, reg_t *argv)
SCIkdebug(SCIkBRESEN, "New data: (x,y)=(%d,%d), di=%d\n", x, y, bdi); SCIkdebug(SCIkBRESEN, "New data: (x,y)=(%d,%d), di=%d\n", x, y, bdi);
if (s->version >= SCI_VERSION_FTU_INVERSE_CANBEHERE) if (s->version >= SCI_VERSION_FTU_INVERSE_CANBEHERE)
invoke_selector(INV_SEL(client, cantBeHere, 0), 0); else invoke_selector(INV_SEL(client, cantBeHere, 0), 0);
invoke_selector(INV_SEL(client, canBeHere, 0), 0); else
invoke_selector(INV_SEL(client, canBeHere, 0), 0);
s->r_acc = not_register(s, s->r_acc); s->r_acc = not_register(s, s->r_acc);
@ -422,7 +408,7 @@ kDoBresen(state_t *s, int funct_nr, int argc, reg_t *argv)
completed = 1; completed = 1;
} }
if (SCI_VERSION_MAJOR(s->version)>0) if (SCI_VERSION_MAJOR(s->version) > 0)
if (completed) if (completed)
invoke_selector(INV_SEL(mover, moveDone, 0), 0); invoke_selector(INV_SEL(mover, moveDone, 0), 0);
@ -430,8 +416,8 @@ kDoBresen(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
extern void extern void
_k_dirloop(reg_t obj, word angle, state_t *s, int funct_nr, _k_dirloop(reg_t obj, word angle, state_t *s, int funct_nr,
int argc, reg_t *argv); int argc, reg_t *argv);
/* From kgraphics.c, used as alternative looper */ /* From kgraphics.c, used as alternative looper */
int int
@ -439,13 +425,12 @@ is_heap_object(state_t *s, reg_t pos);
/* From kscripts.c */ /* From kscripts.c */
extern int extern int
get_angle(int xrel, int yrel); get_angle(int xrel, int yrel);
/* from kmath.c, used for calculating angles */ /* from kmath.c, used for calculating angles */
reg_t reg_t
kDoAvoider(state_t *s, int funct_nr, int argc, reg_t *argv) kDoAvoider(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t avoider = argv[0]; reg_t avoider = argv[0];
reg_t client, looper, mover; reg_t client, looper, mover;
int angle; int angle;
@ -485,8 +470,8 @@ kDoAvoider(state_t *s, int funct_nr, int argc, reg_t *argv)
if (invoke_selector(INV_SEL(mover, doit, 1) , 0)) { if (invoke_selector(INV_SEL(mover, doit, 1) , 0)) {
SCIkwarn(SCIkERROR, "Mover "PREG" of avoider "PREG SCIkwarn(SCIkERROR, "Mover "PREG" of avoider "PREG
" doesn't have a doit() funcselector\n", " doesn't have a doit() funcselector\n",
PRINT_REG(mover), PRINT_REG(avoider)); PRINT_REG(mover), PRINT_REG(avoider));
return NULL_REG; return NULL_REG;
} }
@ -496,7 +481,7 @@ kDoAvoider(state_t *s, int funct_nr, int argc, reg_t *argv)
if (invoke_selector(INV_SEL(client, isBlocked, 1) , 0)) { if (invoke_selector(INV_SEL(client, isBlocked, 1) , 0)) {
SCIkwarn(SCIkERROR, "Client "PREG" of avoider "PREG" doesn't" SCIkwarn(SCIkERROR, "Client "PREG" of avoider "PREG" doesn't"
" have an isBlocked() funcselector\n", PRINT_REG(client), PRINT_REG(avoider)); " have an isBlocked() funcselector\n", PRINT_REG(client), PRINT_REG(avoider));
return NULL_REG; return NULL_REG;
} }
@ -505,10 +490,10 @@ kDoAvoider(state_t *s, int funct_nr, int argc, reg_t *argv)
angle = get_angle(dx, dy); angle = get_angle(dx, dy);
SCIkdebug(SCIkBRESEN, "Movement (%d,%d), angle %d is %sblocked\n", SCIkdebug(SCIkBRESEN, "Movement (%d,%d), angle %d is %sblocked\n",
dx, dy, angle, (s->r_acc.offset)? " ": "not "); dx, dy, angle, (s->r_acc.offset) ? " " : "not ");
if (s->r_acc.offset) { /* isBlocked() returned non-zero */ if (s->r_acc.offset) { /* isBlocked() returned non-zero */
int rotation = (rand() & 1)? 45 : (360-45); /* Clockwise/counterclockwise */ int rotation = (rand() & 1) ? 45 : (360 - 45); /* Clockwise/counterclockwise */
int oldx = GET_SEL32V(client, x); int oldx = GET_SEL32V(client, x);
int oldy = GET_SEL32V(client, y); int oldy = GET_SEL32V(client, y);
int xstep = GET_SEL32V(client, xStep); int xstep = GET_SEL32V(client, xStep);
@ -518,19 +503,19 @@ kDoAvoider(state_t *s, int funct_nr, int argc, reg_t *argv)
SCIkdebug(SCIkBRESEN, " avoider "PREG"\n", PRINT_REG(avoider)); SCIkdebug(SCIkBRESEN, " avoider "PREG"\n", PRINT_REG(avoider));
for (moves = 0; moves < 8; moves++) { for (moves = 0; moves < 8; moves++) {
int move_x = (int) (sin(angle * PI / 180.0) * (xstep)); int move_x = (int)(sin(angle * PI / 180.0) * (xstep));
int move_y = (int) (-cos(angle * PI / 180.0) * (ystep)); int move_y = (int)(-cos(angle * PI / 180.0) * (ystep));
PUT_SEL32V(client, x, oldx + move_x); PUT_SEL32V(client, x, oldx + move_x);
PUT_SEL32V(client, y, oldy + move_y); PUT_SEL32V(client, y, oldy + move_y);
SCIkdebug(SCIkBRESEN, "Pos (%d,%d): Trying angle %d; delta=(%d,%d)\n", SCIkdebug(SCIkBRESEN, "Pos (%d,%d): Trying angle %d; delta=(%d,%d)\n",
oldx, oldy, angle, move_x, move_y); oldx, oldy, angle, move_x, move_y);
if (invoke_selector(INV_SEL(client, canBeHere, 1) , 0)) { if (invoke_selector(INV_SEL(client, canBeHere, 1) , 0)) {
SCIkwarn(SCIkERROR, "Client "PREG" of avoider "PREG" doesn't" SCIkwarn(SCIkERROR, "Client "PREG" of avoider "PREG" doesn't"
" have a canBeHere() funcselector\n", " have a canBeHere() funcselector\n",
PRINT_REG(client), PRINT_REG(avoider)); PRINT_REG(client), PRINT_REG(avoider));
return NULL_REG; return NULL_REG;
} }
@ -551,7 +536,7 @@ kDoAvoider(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
SCIkwarn(SCIkWARNING, "DoAvoider failed for avoider "PREG"\n", SCIkwarn(SCIkWARNING, "DoAvoider failed for avoider "PREG"\n",
PRINT_REG(avoider)); PRINT_REG(avoider));
} else { } else {
int heading = GET_SEL32V(client, heading); int heading = GET_SEL32V(client, heading);
@ -566,13 +551,13 @@ kDoAvoider(state_t *s, int funct_nr, int argc, reg_t *argv)
if (looper.segment) { if (looper.segment) {
if (invoke_selector(INV_SEL(looper, doit, 1), 2, angle, client)) { if (invoke_selector(INV_SEL(looper, doit, 1), 2, angle, client)) {
SCIkwarn(SCIkERROR, "Looper "PREG" of avoider "PREG" doesn't" SCIkwarn(SCIkERROR, "Looper "PREG" of avoider "PREG" doesn't"
" have a doit() funcselector\n", " have a doit() funcselector\n",
PRINT_REG(looper), PRINT_REG(avoider)); PRINT_REG(looper), PRINT_REG(avoider));
} else return s->r_acc; } else return s->r_acc;
} else } else
/* No looper? Fall back to DirLoop */ /* No looper? Fall back to DirLoop */
_k_dirloop(client, (word)angle, s, funct_nr, argc, argv); _k_dirloop(client, (word)angle, s, funct_nr, argc, argv);
} }
return s->r_acc; return s->r_acc;

View file

@ -78,8 +78,7 @@
#define PF_FATAL -2 #define PF_FATAL -2
/* Floating point struct */ /* Floating point struct */
typedef struct pointf typedef struct pointf {
{
pointf() : x(0), y(0) {} pointf() : x(0), y(0) {}
pointf(float x_, float y_) : x(x_), y(y_) {} pointf(float x_, float y_) : x(x_), y(y_) {}
@ -87,13 +86,11 @@ typedef struct pointf
} pointf_t; } pointf_t;
pointf_t pointf_t
to_pointf(point_t p) to_pointf(point_t p) {
{
return pointf(p.x, p.y); return pointf(p.x, p.y);
} }
typedef struct vertex typedef struct vertex {
{
/* Location */ /* Location */
point_t v; point_t v;
@ -115,8 +112,7 @@ typedef struct vertex
typedef CLIST_HEAD(vertices_head, vertex) vertices_head_t; typedef CLIST_HEAD(vertices_head, vertex) vertices_head_t;
typedef struct polygon typedef struct polygon {
{
/* Circular list of vertices */ /* Circular list of vertices */
vertices_head_t vertices; vertices_head_t vertices;
@ -128,8 +124,7 @@ typedef struct polygon
} polygon_t; } polygon_t;
/* Pathfinding state */ /* Pathfinding state */
typedef struct pf_state typedef struct pf_state {
{
/* List of all polygons */ /* List of all polygons */
LIST_HEAD(polygons_head, polygon) polygons; LIST_HEAD(polygons_head, polygon) polygons;
@ -156,8 +151,7 @@ static vertex_t *vertex_cur;
/* Temporary hack to deal with points in reg_ts */ /* Temporary hack to deal with points in reg_ts */
static int static int
polygon_is_reg_t(unsigned char *list, int size) polygon_is_reg_t(unsigned char *list, int size) {
{
int i; int i;
/* Check the first three reg_ts */ /* Check the first three reg_ts */
@ -171,8 +165,7 @@ polygon_is_reg_t(unsigned char *list, int size)
} }
static point_t static point_t
read_point(unsigned char *list, int is_reg_t, int offset) read_point(unsigned char *list, int is_reg_t, int offset) {
{
point_t point; point_t point;
if (!is_reg_t) { if (!is_reg_t) {
@ -185,11 +178,10 @@ read_point(unsigned char *list, int is_reg_t, int offset)
} }
/*** Debug functions ***/ /*** Debug functions ***/
static void static void
draw_line(state_t *s, point_t p1, point_t p2, int type) draw_line(state_t *s, point_t p1, point_t p2, int type) {
{
/* Colors for polygon debugging. /* Colors for polygon debugging.
** Green: Total access ** Green: Total access
** Red : Barred access ** Red : Barred access
@ -218,8 +210,7 @@ draw_line(state_t *s, point_t p1, point_t p2, int type)
} }
static void static void
draw_point(state_t *s, point_t p, int start) draw_point(state_t *s, point_t p, int start) {
{
/* Colors for starting and end point /* Colors for starting and end point
** Green: End point ** Green: End point
** Blue: Starting point ** Blue: Starting point
@ -243,8 +234,7 @@ draw_point(state_t *s, point_t p, int start)
} }
static void static void
draw_polygon(state_t *s, reg_t polygon) draw_polygon(state_t *s, reg_t polygon) {
{
reg_t points = GET_SEL32(polygon, points); reg_t points = GET_SEL32(polygon, points);
int size = KP_UINT(GET_SEL32(polygon, size)); int size = KP_UINT(GET_SEL32(polygon, size));
int type = KP_UINT(GET_SEL32(polygon, type)); int type = KP_UINT(GET_SEL32(polygon, type));
@ -265,8 +255,7 @@ draw_polygon(state_t *s, reg_t polygon)
} }
static void static void
draw_input(state_t *s, reg_t poly_list, point_t start, point_t end, int opt) draw_input(state_t *s, reg_t poly_list, point_t start, point_t end, int opt) {
{
list_t *list; list_t *list;
node_t *node; node_t *node;
@ -292,8 +281,7 @@ draw_input(state_t *s, reg_t poly_list, point_t start, point_t end, int opt)
} }
static void static void
print_polygon(state_t *s, reg_t polygon) print_polygon(state_t *s, reg_t polygon) {
{
reg_t points = GET_SEL32(polygon, points); reg_t points = GET_SEL32(polygon, points);
int size = KP_UINT(GET_SEL32(polygon, size)); int size = KP_UINT(GET_SEL32(polygon, size));
int type = KP_UINT(GET_SEL32(polygon, type)); int type = KP_UINT(GET_SEL32(polygon, type));
@ -314,8 +302,7 @@ print_polygon(state_t *s, reg_t polygon)
} }
static void static void
print_input(state_t *s, reg_t poly_list, point_t start, point_t end, int opt) print_input(state_t *s, reg_t poly_list, point_t start, point_t end, int opt) {
{
list_t *list; list_t *list;
node_t *node; node_t *node;
@ -343,7 +330,7 @@ print_input(state_t *s, reg_t poly_list, point_t start, point_t end, int opt)
} }
/*** Basic geometry functions ***/ /*** Basic geometry functions ***/
static int static int
area(point_t a, point_t b, point_t c) area(point_t a, point_t b, point_t c)
@ -416,9 +403,9 @@ intersect_proper(point_t a, point_t b, point_t c, point_t d)
*/ */
{ {
int ab = (left(a, b, c) && left(b, a, d)) int ab = (left(a, b, c) && left(b, a, d))
|| (left(a, b, d) && left(b, a, c)); || (left(a, b, d) && left(b, a, c));
int cd = (left(c, d, a) && left(d, c, b)) int cd = (left(c, d, a) && left(d, c, b))
|| (left(c, d, b) && left(d, c, a)); || (left(c, d, b) && left(d, c, a));
return ab && cd; return ab && cd;
} }
@ -435,11 +422,11 @@ intersect(point_t a, point_t b, point_t c, point_t d)
return 1; return 1;
return between(a, b, c) || between(a, b, d) return between(a, b, c) || between(a, b, d)
|| between (c, d, a) || between(c, d, b); || between(c, d, a) || between(c, d, b);
} }
/*** Pathfinding ***/ /*** Pathfinding ***/
static vertex_t * static vertex_t *
vertex_new(point_t p) vertex_new(point_t p)
@ -585,7 +572,7 @@ fix_vertex_order(polygon_t *polygon)
** clockwise ** clockwise
*/ */
if (((area > 0) && (polygon->type == POLY_CONTAINED_ACCESS)) if (((area > 0) && (polygon->type == POLY_CONTAINED_ACCESS))
|| ((area < 0) && (polygon->type != POLY_CONTAINED_ACCESS))) { || ((area < 0) && (polygon->type != POLY_CONTAINED_ACCESS))) {
vertices_head_t vertices; vertices_head_t vertices;
/* Create a new circular list */ /* Create a new circular list */
@ -788,7 +775,7 @@ visible(vertex_t *vertex, vertex_t *vertex_prev, int visible, aatree_t *tree)
** if vertex_prev is invisible ** if vertex_prev is invisible
*/ */
if (vertex_prev && !visible && between(p, w, vertex_prev->v)) if (vertex_prev && !visible && between(p, w, vertex_prev->v))
return 0; return 0;
/* Find leftmost node of tree */ /* Find leftmost node of tree */
while ((tree_n = aatree_walk(tree_n, AATREE_WALK_LEFT))) while ((tree_n = aatree_walk(tree_n, AATREE_WALK_LEFT)))
@ -836,14 +823,14 @@ visible_vertices(pf_state_t *s, vertex_t *vert)
/* Check that there is more than one vertex. */ /* Check that there is more than one vertex. */
if (VERTEX_HAS_EDGES(vertex)) if (VERTEX_HAS_EDGES(vertex))
CLIST_FOREACH(vertex, &polygon->vertices, entries) { CLIST_FOREACH(vertex, &polygon->vertices, entries) {
point_t high, low; point_t high, low;
/* Add edges that intersect the initial position of the sweeping line */ /* Add edges that intersect the initial position of the sweeping line */
clockwise(vertex, &high, &low); clockwise(vertex, &high, &low);
if ((high.y < p.y) && (low.y >= p.y) && !POINT_EQUAL(low, p)) if ((high.y < p.y) && (low.y >= p.y) && !POINT_EQUAL(low, p))
aatree_insert(vertex, &tree, edge_compare); aatree_insert(vertex, &tree, edge_compare);
} }
} }
is_visible = 1; is_visible = 1;
@ -926,9 +913,9 @@ edge_on_screen_border(point_t p, point_t q)
{ {
/* FIXME get dimensions from somewhere? */ /* FIXME get dimensions from somewhere? */
return ((p.x == 0 && q.x == 0) return ((p.x == 0 && q.x == 0)
|| (p.x == 319 && q.x == 319) || (p.x == 319 && q.x == 319)
|| (p.y == 0 && q.y == 0) || (p.y == 0 && q.y == 0)
|| (p.y == 189 && q.y == 189)); || (p.y == 189 && q.y == 189));
} }
static int static int
@ -944,7 +931,7 @@ find_free_point(pointf_t f, polygon_t *polygon, point_t *ret)
/* Try nearest point first */ /* Try nearest point first */
p = gfx_point((int) floor(f.x + 0.5), p = gfx_point((int) floor(f.x + 0.5),
(int) floor(f.y + 0.5)); (int) floor(f.y + 0.5));
if (contained(p, polygon) != CONT_INSIDE) { if (contained(p, polygon) != CONT_INSIDE) {
*ret = p; *ret = p;
@ -952,7 +939,7 @@ find_free_point(pointf_t f, polygon_t *polygon, point_t *ret)
} }
p = gfx_point((int) floor(f.x), p = gfx_point((int) floor(f.x),
(int) floor(f.y)); (int) floor(f.y));
/* Try (x, y), (x + 1, y), (x , y + 1) and (x + 1, y + 1) */ /* Try (x, y), (x + 1, y), (x , y + 1) and (x + 1, y + 1) */
if (contained(p, polygon) == CONT_INSIDE) { if (contained(p, polygon) == CONT_INSIDE) {
@ -1039,24 +1026,24 @@ intersection(point_t a, point_t b, vertex_t *vertex, pointf_t *ret)
point_t c = vertex->v; point_t c = vertex->v;
point_t d = CLIST_NEXT(vertex, entries)->v; point_t d = CLIST_NEXT(vertex, entries)->v;
denom = a.x * (float) (d.y - c.y) + denom = a.x * (float)(d.y - c.y) +
b.x * (float) (c.y - d.y) + b.x * (float)(c.y - d.y) +
d.x * (float) (b.y - a.y) + d.x * (float)(b.y - a.y) +
c.x * (float) (a.y - b.y); c.x * (float)(a.y - b.y);
if (denom == 0.0) if (denom == 0.0)
/* Segments are parallel, no intersection */ /* Segments are parallel, no intersection */
return PF_ERROR; return PF_ERROR;
num = a.x * (float) (d.y - c.y) + num = a.x * (float)(d.y - c.y) +
c.x * (float) (a.y - d.y) + c.x * (float)(a.y - d.y) +
d.x * (float) (c.y - a.y); d.x * (float)(c.y - a.y);
s = num / denom; s = num / denom;
num = -(a.x * (float) (c.y - b.y) + num = -(a.x * (float)(c.y - b.y) +
b.x * (float) (a.y - c.y) + b.x * (float)(a.y - c.y) +
c.x * (float) (b.y - a.y)); c.x * (float)(b.y - a.y));
t = num / denom; t = num / denom;
@ -1204,25 +1191,25 @@ merge_point(pf_state_t *s, point_t v)
/* Check for already existing vertex */ /* Check for already existing vertex */
LIST_FOREACH(polygon, &s->polygons, entries) { LIST_FOREACH(polygon, &s->polygons, entries) {
CLIST_FOREACH(vertex, &polygon->vertices, entries) CLIST_FOREACH(vertex, &polygon->vertices, entries)
if (POINT_EQUAL(vertex->v, v)) if (POINT_EQUAL(vertex->v, v))
return vertex; return vertex;
} }
v_new = vertex_new(v); v_new = vertex_new(v);
/* Check for point being on an edge */ /* Check for point being on an edge */
LIST_FOREACH(polygon, &s->polygons, entries) LIST_FOREACH(polygon, &s->polygons, entries)
/* Skip single-vertex polygons */ /* Skip single-vertex polygons */
if (VERTEX_HAS_EDGES(CLIST_FIRST(&polygon->vertices))) if (VERTEX_HAS_EDGES(CLIST_FIRST(&polygon->vertices)))
CLIST_FOREACH(vertex, &polygon->vertices, entries) { CLIST_FOREACH(vertex, &polygon->vertices, entries) {
vertex_t *next = CLIST_NEXT(vertex, entries); vertex_t *next = CLIST_NEXT(vertex, entries);
if (between(vertex->v, next->v, v)) { if (between(vertex->v, next->v, v)) {
/* Split edge by adding vertex */ /* Split edge by adding vertex */
CLIST_INSERT_AFTER(vertex, v_new, entries); CLIST_INSERT_AFTER(vertex, v_new, entries);
return v_new; return v_new;
} }
} }
/* Add point as single-vertex polygon */ /* Add point as single-vertex polygon */
polygon = polygon_new(POLY_BARRED_ACCESS); polygon = polygon_new(POLY_BARRED_ACCESS);
@ -1368,8 +1355,7 @@ convert_polygon_set(state_t *s, reg_t poly_list, point_t start, point_t end, int
sciprintf("[avoidpath] Error: fatal error finding nearest intersecton\n"); sciprintf("[avoidpath] Error: fatal error finding nearest intersecton\n");
free_pf_state(pf_s); free_pf_state(pf_s);
return NULL; return NULL;
} } else if (err == PF_OK)
else if (err == PF_OK)
/* Keep original start position if intersection /* Keep original start position if intersection
** was found ** was found
*/ */
@ -1379,8 +1365,7 @@ convert_polygon_set(state_t *s, reg_t poly_list, point_t start, point_t end, int
sciprintf("[avoidpath] Error: couldn't fix start position for pathfinding\n"); sciprintf("[avoidpath] Error: couldn't fix start position for pathfinding\n");
free_pf_state(pf_s); free_pf_state(pf_s);
return NULL; return NULL;
} } else if (polygon) {
else if (polygon) {
/* Start position has moved */ /* Start position has moved */
pf_s->keep_start = 1; pf_s->keep_start = 1;
if ((polygon->type != POLY_NEAREST_ACCESS)) if ((polygon->type != POLY_NEAREST_ACCESS))
@ -1392,8 +1377,7 @@ convert_polygon_set(state_t *s, reg_t poly_list, point_t start, point_t end, int
sciprintf("[avoidpath] Error: couldn't fix end position for pathfinding\n"); sciprintf("[avoidpath] Error: couldn't fix end position for pathfinding\n");
free_pf_state(pf_s); free_pf_state(pf_s);
return NULL; return NULL;
} } else {
else {
/* Keep original end position if it is contained in a /* Keep original end position if it is contained in a
** near-point accessible polygon ** near-point accessible polygon
*/ */
@ -1440,7 +1424,7 @@ visibility_graph(pf_state_t *s)
vertex_t *vertex; vertex_t *vertex;
CLIST_FOREACH(vertex, &polygon->vertices, entries) CLIST_FOREACH(vertex, &polygon->vertices, entries)
visible_vertices(s, vertex); visible_vertices(s, vertex);
} }
} }
@ -1464,11 +1448,11 @@ intersecting_polygons(pf_state_t *s)
/* Skip neighbouring edges */ /* Skip neighbouring edges */
if ((CLIST_NEXT(v1, entries) == v2) if ((CLIST_NEXT(v1, entries) == v2)
|| CLIST_PREV(v1, entries) == v2) || CLIST_PREV(v1, entries) == v2)
continue; continue;
if (intersect(v1->v, CLIST_NEXT(v1, entries)->v, if (intersect(v1->v, CLIST_NEXT(v1, entries)->v,
v2->v, CLIST_NEXT(v2, entries)->v)) v2->v, CLIST_NEXT(v2, entries)->v))
return 1; return 1;
} }
} }
@ -1500,7 +1484,7 @@ dijkstra(pf_state_t *s)
vertex_t *vertex; vertex_t *vertex;
CLIST_FOREACH(vertex, &polygon->vertices, entries) CLIST_FOREACH(vertex, &polygon->vertices, entries)
LIST_INSERT_HEAD(&remain, vertex, dijkstra); LIST_INSERT_HEAD(&remain, vertex, dijkstra);
} }
s->vertex_start->dist = 0.0f; s->vertex_start->dist = 0.0f;
@ -1542,7 +1526,7 @@ dijkstra(pf_state_t *s)
continue; continue;
new_dist = vertex_min->dist + distance(to_pointf(vertex_min->v), new_dist = vertex_min->dist + distance(to_pointf(vertex_min->v),
to_pointf(s->vertex_index[i]->v)); to_pointf(s->vertex_index[i]->v));
if (new_dist < s->vertex_index[i]->dist) { if (new_dist < s->vertex_index[i]->dist) {
s->vertex_index[i]->dist = new_dist; s->vertex_index[i]->dist = new_dist;
s->vertex_index[i]->path_prev = vertex_min; s->vertex_index[i]->path_prev = vertex_min;
@ -1570,7 +1554,7 @@ output_path(pf_state_t *p, state_t *s)
if (unreachable) { if (unreachable) {
/* If pathfinding failed we only return the path up to vertex_start */ /* If pathfinding failed we only return the path up to vertex_start */
oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE * 3, oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE * 3,
AVOIDPATH_DYNMEM_STRING, &output); AVOIDPATH_DYNMEM_STRING, &output);
if (p->keep_start) if (p->keep_start)
POLY_SET_POINT(oref, 0, p->start.x, p->start.y); POLY_SET_POINT(oref, 0, p->start.x, p->start.y);
@ -1589,7 +1573,7 @@ output_path(pf_state_t *p, state_t *s)
} }
oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE * (path_len + 1 + p->keep_start + p->keep_end), oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE * (path_len + 1 + p->keep_start + p->keep_end),
AVOIDPATH_DYNMEM_STRING, &output); AVOIDPATH_DYNMEM_STRING, &output);
/* Sentinel */ /* Sentinel */
POLY_SET_POINT(oref, path_len + p->keep_start + p->keep_end, POLY_LAST_POINT, POLY_LAST_POINT); POLY_SET_POINT(oref, path_len + p->keep_start + p->keep_end, POLY_LAST_POINT, POLY_LAST_POINT);
@ -1630,12 +1614,11 @@ output_path(pf_state_t *p, state_t *s)
} }
reg_t reg_t
kAvoidPath(state_t *s, int funct_nr, int argc, reg_t *argv) kAvoidPath(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
point_t start = gfx_point(SKPV(0), SKPV(1)); point_t start = gfx_point(SKPV(0), SKPV(1));
if (s->debug_mode & (1 << SCIkAVOIDPATH_NR)) { if (s->debug_mode & (1 << SCIkAVOIDPATH_NR)) {
gfxw_port_t *port= s->picture_port; gfxw_port_t *port = s->picture_port;
if (!port->decorations) { if (!port->decorations) {
port->decorations = gfxw_new_list(gfx_rect(0, 0, 320, 200), 0); port->decorations = gfxw_new_list(gfx_rect(0, 0, 320, 200), 0);
@ -1647,8 +1630,7 @@ kAvoidPath(state_t *s, int funct_nr, int argc, reg_t *argv)
switch (argc) { switch (argc) {
case 3 : case 3 : {
{
reg_t retval; reg_t retval;
polygon_t *polygon = convert_polygon(s, argv[2]); polygon_t *polygon = convert_polygon(s, argv[2]);
@ -1664,8 +1646,7 @@ kAvoidPath(state_t *s, int funct_nr, int argc, reg_t *argv)
return retval; return retval;
} }
case 6 : case 6 :
case 7 : case 7 : {
{
point_t end = gfx_point(SKPV(2), SKPV(3)); point_t end = gfx_point(SKPV(2), SKPV(3));
reg_t poly_list = argv[4]; reg_t poly_list = argv[4];
/* int poly_list_size = UKPV(5); */ /* int poly_list_size = UKPV(5); */
@ -1697,8 +1678,8 @@ kAvoidPath(state_t *s, int funct_nr, int argc, reg_t *argv)
sciprintf("[avoidpath] Error: pathfinding failed for following input:\n"); sciprintf("[avoidpath] Error: pathfinding failed for following input:\n");
print_input(s, poly_list, start, end, opt); print_input(s, poly_list, start, end, opt);
sciprintf("[avoidpath] Returning direct path from start point to end point\n"); sciprintf("[avoidpath] Returning direct path from start point to end point\n");
oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE*3, oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE * 3,
AVOIDPATH_DYNMEM_STRING, &output); AVOIDPATH_DYNMEM_STRING, &output);
POLY_SET_POINT(oref, 0, start.x, start.y); POLY_SET_POINT(oref, 0, start.x, start.y);
POLY_SET_POINT(oref, 1, end.x, end.y); POLY_SET_POINT(oref, 1, end.x, end.y);
@ -1719,7 +1700,7 @@ kAvoidPath(state_t *s, int funct_nr, int argc, reg_t *argv)
default: default:
SCIkwarn(SCIkWARNING, "Unknown AvoidPath subfunction %d\n", SCIkwarn(SCIkWARNING, "Unknown AvoidPath subfunction %d\n",
argc); argc);
return NULL_REG; return NULL_REG;
break; break;
} }

View file

@ -30,8 +30,7 @@
#include "sci/engine/kernel_types.h" #include "sci/engine/kernel_types.h"
reg_t reg_t
read_selector(state_t *s, reg_t object, selector_t selector_id, const char *file, int line) read_selector(state_t *s, reg_t object, selector_t selector_id, const char *file, int line) {
{
reg_t *address; reg_t *address;
if (lookup_selector(s, object, selector_id, &address, NULL) != SELECTOR_VARIABLE) if (lookup_selector(s, object, selector_id, &address, NULL) != SELECTOR_VARIABLE)
@ -43,21 +42,20 @@ read_selector(state_t *s, reg_t object, selector_t selector_id, const char *file
void void
write_selector(state_t *s, reg_t object, selector_t selector_id, reg_t value, write_selector(state_t *s, reg_t object, selector_t selector_id, reg_t value,
const char *fname, int line) const char *fname, int line) {
{
reg_t *address; reg_t *address;
if ((selector_id < 0) || (selector_id > s->selector_names_nr)) { if ((selector_id < 0) || (selector_id > s->selector_names_nr)) {
SCIkwarn(SCIkWARNING, "Attempt to write to invalid selector %d of" SCIkwarn(SCIkWARNING, "Attempt to write to invalid selector %d of"
" object at "PREG" (%s L%d).\n", selector_id, " object at "PREG" (%s L%d).\n", selector_id,
PRINT_REG(object), fname, line); PRINT_REG(object), fname, line);
return; return;
} }
if (lookup_selector(s, object, selector_id, &address, NULL) != SELECTOR_VARIABLE) if (lookup_selector(s, object, selector_id, &address, NULL) != SELECTOR_VARIABLE)
SCIkwarn(SCIkWARNING, "Selector '%s' of object at %04x could not be" SCIkwarn(SCIkWARNING, "Selector '%s' of object at %04x could not be"
" written to (%s L%d)\n", " written to (%s L%d)\n",
s->selector_names[selector_id], object, fname, line); s->selector_names[selector_id], object, fname, line);
else else
*address = value; *address = value;
@ -65,9 +63,8 @@ write_selector(state_t *s, reg_t object, selector_t selector_id, reg_t value,
int int
invoke_selector(state_t *s, reg_t object, int selector_id, int noinvalid, int kfunct, invoke_selector(state_t *s, reg_t object, int selector_id, int noinvalid, int kfunct,
stack_ptr_t k_argp, int k_argc, /* Kernel function argp/argc */ stack_ptr_t k_argp, int k_argc, /* Kernel function argp/argc */
const char *fname, int line, int argc, ...) const char *fname, int line, int argc, ...) {
{
va_list argp; va_list argp;
int i; int i;
int framesize = 2 + 1 * argc; int framesize = 2 + 1 * argc;
@ -84,7 +81,7 @@ invoke_selector(state_t *s, reg_t object, int selector_id, int noinvalid, int kf
if (slc_type == SELECTOR_NONE) { if (slc_type == SELECTOR_NONE) {
SCIkwarn(SCIkERROR, "Selector '%s' of object at "PREG" could not be invoked (%s L%d)\n", SCIkwarn(SCIkERROR, "Selector '%s' of object at "PREG" could not be invoked (%s L%d)\n",
s->selector_names[selector_id], PRINT_REG(object), fname, line); s->selector_names[selector_id], PRINT_REG(object), fname, line);
if (noinvalid == 0) if (noinvalid == 0)
KERNEL_OOPS("Not recoverable: VM was halted\n"); KERNEL_OOPS("Not recoverable: VM was halted\n");
return 1; return 1;
@ -101,17 +98,17 @@ invoke_selector(state_t *s, reg_t object, int selector_id, int noinvalid, int kf
/* Write "kernel" call to the stack, for debugging: */ /* Write "kernel" call to the stack, for debugging: */
xstack = add_exec_stack_entry(s, NULL_REG, NULL, NULL_REG, xstack = add_exec_stack_entry(s, NULL_REG, NULL, NULL_REG,
k_argc, k_argp - 1, 0, NULL_REG, k_argc, k_argp - 1, 0, NULL_REG,
s->execution_stack_pos, SCI_XS_CALLEE_LOCALS); s->execution_stack_pos, SCI_XS_CALLEE_LOCALS);
xstack->selector = -42 - kfunct; /* Evil debugging hack to identify kernel function */ xstack->selector = -42 - kfunct; /* Evil debugging hack to identify kernel function */
xstack->type = EXEC_STACK_TYPE_KERNEL; xstack->type = EXEC_STACK_TYPE_KERNEL;
/* Now commit the actual function: */ /* Now commit the actual function: */
xstack = send_selector(s, object, object, xstack = send_selector(s, object, object,
stackframe, framesize, stackframe); stackframe, framesize, stackframe);
xstack->sp += argc+2; xstack->sp += argc + 2;
xstack->fp += argc+2; xstack->fp += argc + 2;
run_vm(s, 0); /* Start a new vm */ run_vm(s, 0); /* Start a new vm */
@ -122,8 +119,7 @@ invoke_selector(state_t *s, reg_t object, int selector_id, int noinvalid, int kf
int int
is_object(state_t *s, reg_t object) is_object(state_t *s, reg_t object) {
{
return obj_get(s, object) != NULL; return obj_get(s, object) != NULL;
} }
@ -133,28 +129,25 @@ is_object(state_t *s, reg_t object)
** This implementation ignores all resource numbers except the first one. ** This implementation ignores all resource numbers except the first one.
*/ */
reg_t reg_t
kLoad(state_t *s, int funct_nr, int argc, reg_t *argv) kLoad(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int restype = KP_UINT(argv[0]); int restype = KP_UINT(argv[0]);
int resnr = KP_UINT(argv[1]); int resnr = KP_UINT(argv[1]);
if (restype == sci_memory)/* Request to dynamically allocate hunk memory for later use */ if (restype == sci_memory)/* Request to dynamically allocate hunk memory for later use */
return kalloc(s, "kLoad()", resnr); return kalloc(s, "kLoad()", resnr);
return make_reg(0, ((restype << 11) | resnr)); /* Return the resource identifier as handle */ return make_reg(0, ((restype << 11) | resnr)); /* Return the resource identifier as handle */
} }
reg_t reg_t
kLock(state_t *s, int funct_nr, int argc, reg_t *argv) kLock(state_t *s, int funct_nr, int argc, reg_t *argv) {
{ int restype = UKPV(0) & 0x7f;
int restype = UKPV(0)&0x7f;
int resnr = UKPV(1); int resnr = UKPV(1);
int state = argc > 2 ? UKPV(2) : 1; int state = argc > 2 ? UKPV(2) : 1;
resource_t *which; resource_t *which;
switch (state) switch (state) {
{
case 1 : case 1 :
scir_find_resource(s->resmgr, restype, resnr, 1); scir_find_resource(s->resmgr, restype, resnr, 1);
break; break;
@ -170,8 +163,7 @@ kLock(state_t *s, int funct_nr, int argc, reg_t *argv)
** Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr' ** Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr'
*/ */
reg_t reg_t
kUnLoad(state_t *s, int funct_nr, int argc, reg_t *argv) kUnLoad(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int restype = KP_UINT(argv[0]); int restype = KP_UINT(argv[0]);
reg_t resnr = argv[1]; reg_t resnr = argv[1];
@ -183,8 +175,7 @@ kUnLoad(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kClone(state_t *s, int funct_nr, int argc, reg_t *argv) kClone(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t parent_addr = argv[0]; reg_t parent_addr = argv[0];
object_t *parent_obj = obj_get(s, parent_addr); object_t *parent_obj = obj_get(s, parent_addr);
reg_t clone_addr; reg_t clone_addr;
@ -225,18 +216,17 @@ kClone(state_t *s, int funct_nr, int argc, reg_t *argv)
extern void extern void
_k_view_list_mark_free(state_t *s, reg_t off); /* kgraphics.c */ _k_view_list_mark_free(state_t *s, reg_t off); /* kgraphics.c */
reg_t reg_t
kDisposeClone(state_t *s, int funct_nr, int argc, reg_t *argv) kDisposeClone(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t victim_addr = argv[0]; reg_t victim_addr = argv[0];
clone_t *victim_obj = obj_get(s, victim_addr); clone_t *victim_obj = obj_get(s, victim_addr);
word underBits; word underBits;
if (!victim_obj) { if (!victim_obj) {
SCIkwarn(SCIkERROR, "Attempt to dispose non-class/object at "PREG"\n", SCIkwarn(SCIkERROR, "Attempt to dispose non-class/object at "PREG"\n",
PRINT_REG(victim_addr)); PRINT_REG(victim_addr));
return s->r_acc; return s->r_acc;
} }
@ -248,7 +238,7 @@ kDisposeClone(state_t *s, int funct_nr, int argc, reg_t *argv)
underBits = GET_SEL32V(victim_addr, underBits); underBits = GET_SEL32V(victim_addr, underBits);
if (underBits) { if (underBits) {
SCIkwarn(SCIkWARNING,"Clone "PREG" was cleared with underBits set\n", PRINT_REG(victim_addr)); SCIkwarn(SCIkWARNING, "Clone "PREG" was cleared with underBits set\n", PRINT_REG(victim_addr));
} }
#if 0 #if 0
if (s->dyn_views) { /* Free any widget associated with the clone */ if (s->dyn_views) { /* Free any widget associated with the clone */
@ -261,7 +251,7 @@ kDisposeClone(state_t *s, int funct_nr, int argc, reg_t *argv)
victim_obj->flags |= OBJECT_FLAG_FREED; victim_obj->flags |= OBJECT_FLAG_FREED;
_k_view_list_mark_free(s, victim_addr); /* Free on view list, if neccessary */ _k_view_list_mark_free(s, victim_addr); /* Free on view list, if neccessary */
return s->r_acc; return s->r_acc;
} }
@ -271,8 +261,7 @@ kDisposeClone(state_t *s, int funct_nr, int argc, reg_t *argv)
** Returns script dispatch address index in the supplied script ** Returns script dispatch address index in the supplied script
*/ */
reg_t reg_t
kScriptID(state_t *s, int funct_nr, int argc, reg_t *argv) kScriptID(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int script = KP_UINT(argv[0]); int script = KP_UINT(argv[0]);
int index = KP_UINT(KP_ALT(1, NULL_REG)); int index = KP_UINT(KP_ALT(1, NULL_REG));
@ -294,7 +283,7 @@ kScriptID(state_t *s, int funct_nr, int argc, reg_t *argv)
if (index > scr->exports_nr) { if (index > scr->exports_nr) {
SCIkwarn(SCIkERROR, "Dispatch index too big: %d > %d\n", SCIkwarn(SCIkERROR, "Dispatch index too big: %d > %d\n",
index, scr->exports_nr); index, scr->exports_nr);
return NULL_REG; return NULL_REG;
} }
@ -303,19 +292,17 @@ kScriptID(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kDisposeScript(state_t *s, int funct_nr, int argc, reg_t *argv) kDisposeScript(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int script = argv[0].offset; int script = argv[0].offset;
/* Work around QfG1 graveyard bug */ /* Work around QfG1 graveyard bug */
if (argv[0].segment) return s->r_acc; if (argv[0].segment) return s->r_acc;
if (sm_script_is_loaded(&(s->seg_manager), script, SCRIPT_ID)) if (sm_script_is_loaded(&(s->seg_manager), script, SCRIPT_ID)) {
{ int id = sm_seg_get(&(s->seg_manager), script);
int id = sm_seg_get(&(s->seg_manager), script);
if (s->execution_stack[s->execution_stack_pos].addr.pc.segment != id)
if (s->execution_stack[s->execution_stack_pos].addr.pc.segment != id) sm_set_lockers(&(s->seg_manager), 1, script, SCRIPT_ID);
sm_set_lockers(&(s->seg_manager), 1, script, SCRIPT_ID);
} }
script_uninstantiate(s, script); script_uninstantiate(s, script);
@ -324,17 +311,15 @@ kDisposeScript(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
int int
is_heap_object(state_t *s, reg_t pos) is_heap_object(state_t *s, reg_t pos) {
{
object_t *obj = obj_get(s, pos); object_t *obj = obj_get(s, pos);
return (obj != NULL return (obj != NULL
&& (!(obj->flags & OBJECT_FLAG_FREED)) && (!(obj->flags & OBJECT_FLAG_FREED))
&& (!sm_script_is_marked_as_deleted(&s->seg_manager, pos.segment))); && (!sm_script_is_marked_as_deleted(&s->seg_manager, pos.segment)));
} }
reg_t reg_t
kIsObject(state_t *s, int funct_nr, int argc, reg_t *argv) kIsObject(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
if (argv[0].offset == 0xffff) /* Treated specially */ if (argv[0].offset == 0xffff) /* Treated specially */
return NULL_REG; return NULL_REG;
else else
@ -342,12 +327,11 @@ kIsObject(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t reg_t
kRespondsTo(state_t *s, int funct_nr, int argc, reg_t *argv) kRespondsTo(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t obj = argv[0]; reg_t obj = argv[0];
int selector = KP_UINT(argv[1]); int selector = KP_UINT(argv[1]);
return make_reg(0, is_heap_object(s, obj) return make_reg(0, is_heap_object(s, obj)
&& lookup_selector(s, obj, selector, NULL, NULL) != SELECTOR_NONE); && lookup_selector(s, obj, selector, NULL, NULL) != SELECTOR_NONE);
} }

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,7 @@
char * char *
kernel_lookup_text(state_t *s, reg_t address, int index) kernel_lookup_text(state_t *s, reg_t address, int index)
/* Returns the string the script intended to address */ /* Returns the string the script intended to address */
{ {
char *seeker; char *seeker;
resource_t *textres; resource_t *textres;
@ -78,45 +78,43 @@ kernel_lookup_text(state_t *s, reg_t address, int index)
#ifdef SCI_SIMPLE_SAID_CODE #ifdef SCI_SIMPLE_SAID_CODE
int int
vocab_match_simple(state_t *s, heap_ptr addr) vocab_match_simple(state_t *s, heap_ptr addr) {
{ int nextitem;
int nextitem; int listpos = 0;
int listpos = 0;
if (!s->parser_valid) if (!s->parser_valid)
return SAID_NO_MATCH; return SAID_NO_MATCH;
if (s->parser_valid == 2) { /* debug mode: sim_said */ if (s->parser_valid == 2) { /* debug mode: sim_said */
do { do {
sciprintf("DEBUGMATCH: "); sciprintf("DEBUGMATCH: ");
nextitem = s->heap[addr++]; nextitem = s->heap[addr++];
if (nextitem < 0xf0) { if (nextitem < 0xf0) {
nextitem = nextitem << 8 | s->heap[addr++]; nextitem = nextitem << 8 | s->heap[addr++];
if (s->parser_nodes[listpos].type if (s->parser_nodes[listpos].type
|| nextitem != s->parser_nodes[listpos++].content.value) || nextitem != s->parser_nodes[listpos++].content.value)
return SAID_NO_MATCH; return SAID_NO_MATCH;
} else { } else {
if (nextitem == 0xff) if (nextitem == 0xff)
return (s->parser_nodes[listpos++].type == -1)? SAID_FULL_MATCH : SAID_NO_MATCH; /* Finished? */ return (s->parser_nodes[listpos++].type == -1) ? SAID_FULL_MATCH : SAID_NO_MATCH; /* Finished? */
if (s->parser_nodes[listpos].type != 1 if (s->parser_nodes[listpos].type != 1
|| nextitem != s->parser_nodes[listpos++].content.value) || nextitem != s->parser_nodes[listpos++].content.value)
return SAID_NO_MATCH; return SAID_NO_MATCH;
} }
} while (42); } while (42);
} else { /* normal simple match mode */ } else { /* normal simple match mode */
return vocab_simple_said_test(s, addr); return vocab_simple_said_test(s, addr);
} }
} }
#endif /* SCI_SIMPLE_SAID_CODE */ #endif /* SCI_SIMPLE_SAID_CODE */
reg_t reg_t
kSaid(state_t *s, int funct_nr, int argc, reg_t *argv) kSaid(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t heap_said_block = argv[0]; reg_t heap_said_block = argv[0];
byte *said_block; byte *said_block;
int new_lastmatch; int new_lastmatch;
@ -142,27 +140,27 @@ kSaid(state_t *s, int funct_nr, int argc, reg_t *argv)
#ifdef SCI_SIMPLE_SAID_CODE #ifdef SCI_SIMPLE_SAID_CODE
s->acc = 0; s->acc = 0;
if (s->parser_lastmatch_word == SAID_FULL_MATCH) if (s->parser_lastmatch_word == SAID_FULL_MATCH)
return; /* Matched before; we're not doing any more matching work today. */ return; /* Matched before; we're not doing any more matching work today. */
if ((new_lastmatch = vocab_match_simple(s, said_block)) != SAID_NO_MATCH) { if ((new_lastmatch = vocab_match_simple(s, said_block)) != SAID_NO_MATCH) {
if (s->debug_mode & (1 << SCIkPARSER_NR)) if (s->debug_mode & (1 << SCIkPARSER_NR))
sciprintf("Match (simple).\n"); sciprintf("Match (simple).\n");
s->acc = 1; s->acc = 1;
if (new_lastmatch == SAID_FULL_MATCH) /* Finished matching? */ if (new_lastmatch == SAID_FULL_MATCH) /* Finished matching? */
PUT_SELECTOR(s->parser_event, claimed, 1); /* claim event */ PUT_SELECTOR(s->parser_event, claimed, 1); /* claim event */
/* otherwise, we have a partial match: Set new lastmatch word in all cases. */ /* otherwise, we have a partial match: Set new lastmatch word in all cases. */
s->parser_lastmatch_word = new_lastmatch; s->parser_lastmatch_word = new_lastmatch;
} }
#else /* !SCI_SIMPLE_SAID_CODE */ #else /* !SCI_SIMPLE_SAID_CODE */
if ((new_lastmatch = said(s, said_block, (s->debug_mode & (1 << SCIkPARSER_NR)))) if ((new_lastmatch = said(s, said_block, (s->debug_mode & (1 << SCIkPARSER_NR))))
!= SAID_NO_MATCH) { /* Build and possibly display a parse tree */ != SAID_NO_MATCH) { /* Build and possibly display a parse tree */
if (s->debug_mode & (1 << SCIkPARSER_NR)) if (s->debug_mode & (1 << SCIkPARSER_NR))
sciprintf("Match.\n"); sciprintf("Match.\n");
@ -184,8 +182,7 @@ kSaid(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kSetSynonyms(state_t *s, int funct_nr, int argc, reg_t *argv) kSetSynonyms(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t object = argv[0]; reg_t object = argv[0];
list_t *list; list_t *list;
node_t *node; node_t *node;
@ -197,7 +194,7 @@ kSetSynonyms(state_t *s, int funct_nr, int argc, reg_t *argv)
s->synonyms_nr = 0; s->synonyms_nr = 0;
list = LOOKUP_LIST(GET_SEL32(object, elements)); list = LOOKUP_LIST(GET_SEL32(object, elements));
node = LOOKUP_NODE(list->first); node = LOOKUP_NODE(list->first);
while (node) { while (node) {
@ -218,18 +215,18 @@ kSetSynonyms(state_t *s, int funct_nr, int argc, reg_t *argv)
int i; int i;
if (s->synonyms_nr) if (s->synonyms_nr)
s->synonyms = (synonym_t*)sci_realloc(s->synonyms, s->synonyms = (synonym_t*)sci_realloc(s->synonyms,
sizeof(synonym_t) * (s->synonyms_nr + synonyms_nr)); sizeof(synonym_t) * (s->synonyms_nr + synonyms_nr));
else else
s->synonyms = (synonym_t*)sci_malloc(sizeof(synonym_t) * synonyms_nr); s->synonyms = (synonym_t*)sci_malloc(sizeof(synonym_t) * synonyms_nr);
s->synonyms_nr += synonyms_nr; s->synonyms_nr += synonyms_nr;
SCIkdebug(SCIkPARSER, "Setting %d synonyms for script.%d\n", SCIkdebug(SCIkPARSER, "Setting %d synonyms for script.%d\n",
synonyms_nr, script); synonyms_nr, script);
if (synonyms_nr > 16384) { if (synonyms_nr > 16384) {
SCIkwarn(SCIkERROR, "Segtable corruption: script.%03d has %d synonyms!\n", SCIkwarn(SCIkERROR, "Segtable corruption: script.%03d has %d synonyms!\n",
script, synonyms_nr); script, synonyms_nr);
/* We used to reset the corrupted value here. I really don't think it's appropriate. /* We used to reset the corrupted value here. I really don't think it's appropriate.
* Lars */ * Lars */
} else } else
@ -241,7 +238,7 @@ kSetSynonyms(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
} else SCIkwarn(SCIkWARNING, "Synonyms of script.%03d were requested, but script is not available\n"); } else SCIkwarn(SCIkWARNING, "Synonyms of script.%03d were requested, but script is not available\n");
} }
node = LOOKUP_NODE(node->succ); node = LOOKUP_NODE(node->succ);
} }
@ -256,8 +253,7 @@ kSetSynonyms(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kParse(state_t *s, int funct_nr, int argc, reg_t *argv) kParse(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t stringpos = argv[0]; reg_t stringpos = argv[0];
char *string = kernel_dereference_char_pointer(s, stringpos, 0); char *string = kernel_dereference_char_pointer(s, stringpos, 0);
int words_nr; int words_nr;
@ -275,9 +271,9 @@ kParse(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
words = vocab_tokenize_string(string, &words_nr, words = vocab_tokenize_string(string, &words_nr,
s->parser_words, s->parser_words_nr, s->parser_words, s->parser_words_nr,
s->parser_suffices, s->parser_suffices_nr, s->parser_suffices, s->parser_suffices_nr,
&error); &error);
s->parser_valid = 0; /* not valid */ s->parser_valid = 0; /* not valid */
if (words) { if (words) {
@ -298,7 +294,7 @@ kParse(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
if (vocab_build_parse_tree(&(s->parser_nodes[0]), words, words_nr, s->parser_branches, if (vocab_build_parse_tree(&(s->parser_nodes[0]), words, words_nr, s->parser_branches,
s->parser_rules)) s->parser_rules))
syntax_fail = 1; /* Building a tree failed */ syntax_fail = 1; /* Building a tree failed */
#ifdef SCI_SIMPLE_SAID_CODE #ifdef SCI_SIMPLE_SAID_CODE
@ -333,7 +329,7 @@ kParse(state_t *s, int funct_nr, int argc, reg_t *argv)
if (error) { if (error) {
char *pbase_str = kernel_dereference_char_pointer(s, s->parser_base, 0); char *pbase_str = kernel_dereference_char_pointer(s, s->parser_base, 0);
strcpy(pbase_str, error); strcpy(pbase_str, error);
SCIkdebug(SCIkPARSER,"Word unknown: %s\n", error); SCIkdebug(SCIkPARSER, "Word unknown: %s\n", error);
/* Issue warning: */ /* Issue warning: */
invoke_selector(INV_SEL(s->game_obj, wordFail, 0), 2, s->parser_base, stringpos); invoke_selector(INV_SEL(s->game_obj, wordFail, 0), 2, s->parser_base, stringpos);
@ -347,8 +343,7 @@ kParse(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kStrEnd(state_t *s, int funct_nr, int argc, reg_t *argv) kStrEnd(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
reg_t address = argv[0]; reg_t address = argv[0];
char *seeker = kernel_dereference_char_pointer(s, address, 0); char *seeker = kernel_dereference_char_pointer(s, address, 0);
@ -359,8 +354,7 @@ kStrEnd(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t reg_t
kStrCat(state_t *s, int funct_nr, int argc, reg_t *argv) kStrCat(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
char *s1 = kernel_dereference_char_pointer(s, argv[0], 0); char *s1 = kernel_dereference_char_pointer(s, argv[0], 0);
char *s2 = kernel_dereference_char_pointer(s, argv[1], 0); char *s2 = kernel_dereference_char_pointer(s, argv[1], 0);
@ -369,8 +363,7 @@ kStrCat(state_t *s, int funct_nr, int argc, reg_t *argv)
} }
reg_t reg_t
kStrCmp(state_t *s, int funct_nr, int argc, reg_t *argv) kStrCmp(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
char *s1 = kernel_dereference_char_pointer(s, argv[0], 0); char *s1 = kernel_dereference_char_pointer(s, argv[0], 0);
char *s2 = kernel_dereference_char_pointer(s, argv[1], 0); char *s2 = kernel_dereference_char_pointer(s, argv[1], 0);
@ -382,32 +375,30 @@ kStrCmp(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kStrCpy(state_t *s, int funct_nr, int argc, reg_t *argv) kStrCpy(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
char *dest = (char *) kernel_dereference_bulk_pointer(s, argv[0], 0); char *dest = (char *) kernel_dereference_bulk_pointer(s, argv[0], 0);
char *src = (char *) kernel_dereference_bulk_pointer(s, argv[1], 0); char *src = (char *) kernel_dereference_bulk_pointer(s, argv[1], 0);
if (!dest) { if (!dest) {
SCIkdebug(SCIkWARNING, "Attempt to strcpy TO invalid pointer "PREG"!\n", SCIkdebug(SCIkWARNING, "Attempt to strcpy TO invalid pointer "PREG"!\n",
PRINT_REG(argv[0])); PRINT_REG(argv[0]));
return NULL_REG; return NULL_REG;
} }
if (!src) { if (!src) {
SCIkdebug(SCIkWARNING, "Attempt to strcpy FROM invalid pointer "PREG"!\n", SCIkdebug(SCIkWARNING, "Attempt to strcpy FROM invalid pointer "PREG"!\n",
PRINT_REG(argv[1])); PRINT_REG(argv[1]));
return NULL_REG; return NULL_REG;
} }
if (argc > 2) if (argc > 2) {
{
int length = SKPV(2); int length = SKPV(2);
if (length>=0) if (length >= 0)
strncpy(dest, src, length); strncpy(dest, src, length);
else { else {
if (s->seg_manager.heap[argv[0].segment]->type == MEM_OBJ_DYNMEM) { if (s->seg_manager.heap[argv[0].segment]->type == MEM_OBJ_DYNMEM) {
reg_t *srcp = (reg_t *) src; reg_t *srcp = (reg_t *) src;
int i; int i;
SCIkdebug(SCIkWARNING, "Performing reg_t to raw conversion for AvoidPath\n"); SCIkdebug(SCIkWARNING, "Performing reg_t to raw conversion for AvoidPath\n");
for (i = 0; i < -length / 2; i++) { for (i = 0; i < -length / 2; i++) {
@ -418,8 +409,7 @@ kStrCpy(state_t *s, int funct_nr, int argc, reg_t *argv)
} else } else
memcpy(dest, src, -length); memcpy(dest, src, -length);
} }
} } else
else
strcpy(dest, src); strcpy(dest, src);
return argv[0]; return argv[0];
@ -427,31 +417,30 @@ kStrCpy(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kStrAt(state_t *s, int funct_nr, int argc, reg_t *argv) kStrAt(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
unsigned char *dest = (unsigned char *) kernel_dereference_bulk_pointer(s, argv[0], 0); unsigned char *dest = (unsigned char *) kernel_dereference_bulk_pointer(s, argv[0], 0);
reg_t *dest2; reg_t *dest2;
if (!dest) { if (!dest) {
SCIkdebug(SCIkWARNING, "Attempt to StrAt at invalid pointer "PREG"!\n", SCIkdebug(SCIkWARNING, "Attempt to StrAt at invalid pointer "PREG"!\n",
PRINT_REG(argv[0])); PRINT_REG(argv[0]));
return NULL_REG; return NULL_REG;
} }
if ((argc == 2) && if ((argc == 2) &&
/* Our pathfinder already works around the issue we're trying to fix */ /* Our pathfinder already works around the issue we're trying to fix */
(strcmp(sm_get_description(&(s->seg_manager), argv[0]), (strcmp(sm_get_description(&(s->seg_manager), argv[0]),
AVOIDPATH_DYNMEM_STRING) != 0) && AVOIDPATH_DYNMEM_STRING) != 0) &&
((strlen((const char*)dest) < 2) || (!is_print_str((char*)dest)))) ((strlen((const char*)dest) < 2) || (!is_print_str((char*)dest))))
/* SQ4 array handling detected */ /* SQ4 array handling detected */
{ {
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
int odd = KP_UINT(argv[1]) & 1; int odd = KP_UINT(argv[1]) & 1;
#else #else
int odd = !(KP_UINT(argv[1]) & 1); int odd = !(KP_UINT(argv[1]) & 1);
#endif #endif
dest2 = ((reg_t *) dest)+(KP_UINT(argv[1])/2); dest2 = ((reg_t *) dest) + (KP_UINT(argv[1]) / 2);
dest = ((unsigned char *) (&dest2->offset))+odd; dest = ((unsigned char *)(&dest2->offset)) + odd;
} else dest += KP_UINT(argv[1]); } else dest += KP_UINT(argv[1]);
s->r_acc = make_reg(0, *dest); s->r_acc = make_reg(0, *dest);
@ -464,8 +453,7 @@ kStrAt(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kReadNumber(state_t *s, int funct_nr, int argc, reg_t *argv) kReadNumber(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
char *source = kernel_dereference_char_pointer(s, argv[0], 0); char *source = kernel_dereference_char_pointer(s, argv[0], 0);
while (isspace(*source)) while (isspace(*source))
@ -490,8 +478,7 @@ kReadNumber(state_t *s, int funct_nr, int argc, reg_t *argv)
** the supplied parameters and writes it to the targ_address. ** the supplied parameters and writes it to the targ_address.
*/ */
reg_t reg_t
kFormat(state_t *s, int funct_nr, int argc, reg_t *argv) kFormat(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
int *arguments; int *arguments;
reg_t dest = argv[0]; reg_t dest = argv[0];
char *target = (char *) kernel_dereference_bulk_pointer(s, dest, 0); char *target = (char *) kernel_dereference_bulk_pointer(s, dest, 0);
@ -549,15 +536,16 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
char *destp; char *destp;
if (xfer == '0') if (xfer == '0')
fillchar = '0'; else fillchar = '0';
else
if (xfer == '=') { if (xfer == '=') {
align = ALIGN_CENTRE; align = ALIGN_CENTRE;
source++; source++;
} else } else
if (isdigit(xfer)) if (isdigit(xfer))
source--; /* Stepped over length argument */ source--; /* Stepped over length argument */
str_leng = strtol(source, &destp, 10); str_leng = strtol(source, &destp, 10);
@ -580,7 +568,7 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
case 's': { /* Copy string */ case 's': { /* Copy string */
reg_t reg = argv[startarg + paramindex]; reg_t reg = argv[startarg + paramindex];
char *tempsource = kernel_lookup_text(s, reg, char *tempsource = kernel_lookup_text(s, reg,
arguments[paramindex + 1]); arguments[paramindex + 1]);
int slen = strlen(tempsource); int slen = strlen(tempsource);
int extralen = str_leng - slen; int extralen = str_leng - slen;
CHECK_OVERFLOW1(target, extralen, NULL_REG); CHECK_OVERFLOW1(target, extralen, NULL_REG);
@ -604,9 +592,11 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
int half_extralen = extralen >> 1; int half_extralen = extralen >> 1;
while (half_extralen-- > 0) while (half_extralen-- > 0)
*target++ = ' '; /* Format into the text */ *target++ = ' '; /* Format into the text */
break;} break;
}
default: break; default:
break;
} }
@ -621,15 +611,17 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
half_extralen = extralen - (extralen >> 1); half_extralen = extralen - (extralen >> 1);
while (half_extralen-- > 0) while (half_extralen-- > 0)
*target++ = ' '; /* Format into the text */ *target++ = ' '; /* Format into the text */
break;} break;
}
default: break; default:
break;
} }
mode = 0; mode = 0;
} }
break; break;
case 'c': { /* insert character */ case 'c': { /* insert character */
CHECK_OVERFLOW1(target, 2, NULL_REG); CHECK_OVERFLOW1(target, 2, NULL_REG);
@ -640,10 +632,11 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
*target++ = arguments[paramindex++]; *target++ = arguments[paramindex++];
mode = 0; mode = 0;
} }
break; break;
case 'x': case 'x':
case 'u': unsigned_var = 1; case 'u':
unsigned_var = 1;
case 'd': { /* Copy decimal */ case 'd': { /* Copy decimal */
/* int templen; -- unused atm */ /* int templen; -- unused atm */
const char *format_string = "%d"; const char *format_string = "%d";
@ -663,7 +656,7 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
mode = 0; mode = 0;
} }
break; break;
default: default:
*target = '%'; *target = '%';
target++; target++;
@ -679,7 +672,7 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
if (padding > 0) { if (padding > 0) {
if (align > 0) { if (align > 0) {
memmove(writestart + padding, memmove(writestart + padding,
writestart, written); writestart, written);
memset(writestart, fillchar, padding); memset(writestart, fillchar, padding);
} else { } else {
memset(target, ' ', padding); memset(target, ' ', padding);
@ -687,7 +680,7 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
target += padding; target += padding;
} }
} }
}else { /* mode != 1 */ } else { /* mode != 1 */
*target = xfer; *target = xfer;
target++; target++;
} }
@ -701,8 +694,7 @@ kFormat(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kStrLen(state_t *s, int funct_nr, int argc, reg_t *argv) kStrLen(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
char *str = kernel_dereference_char_pointer(s, argv[0], 0); char *str = kernel_dereference_char_pointer(s, argv[0], 0);
return make_reg(0, strlen(str)); return make_reg(0, strlen(str));
@ -710,8 +702,7 @@ kStrLen(state_t *s, int funct_nr, int argc, reg_t *argv)
reg_t reg_t
kGetFarText(state_t *s, int funct_nr, int argc, reg_t *argv) kGetFarText(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
resource_t *textres = scir_find_resource(s->resmgr, sci_text, UKPV(0), 0); resource_t *textres = scir_find_resource(s->resmgr, sci_text, UKPV(0), 0);
char *seeker; char *seeker;
int counter = UKPV(1); int counter = UKPV(1);
@ -739,15 +730,12 @@ kGetFarText(state_t *s, int funct_nr, int argc, reg_t *argv)
static message_state_t state; static message_state_t state;
reg_t reg_t
kMessage(state_t *s, int funct_nr, int argc, reg_t *argv) kMessage(state_t *s, int funct_nr, int argc, reg_t *argv) {
{
if (!state.initialized) if (!state.initialized)
message_state_initialize(s->resmgr, &state); message_state_initialize(s->resmgr, &state);
switch (UKPV(0)) switch (UKPV(0)) {
{ case 0 : {
case 0 :
{
char *buffer = argc == 7 ? kernel_dereference_char_pointer(s, argv[6], 0) : NULL; char *buffer = argc == 7 ? kernel_dereference_char_pointer(s, argv[6], 0) : NULL;
message_tuple_t tuple; message_tuple_t tuple;
int module = UKPV(1); int module = UKPV(1);
@ -757,34 +745,28 @@ kMessage(state_t *s, int funct_nr, int argc, reg_t *argv)
tuple.cond = UKPV(4); tuple.cond = UKPV(4);
tuple.seq = UKPV(5); tuple.seq = UKPV(5);
if (message_state_load_res(&state, module) && message_get_specific(&state, &tuple)) if (message_state_load_res(&state, module) && message_get_specific(&state, &tuple)) {
{ if (buffer)
if (buffer)
message_get_text(&state, buffer, 100); message_get_text(&state, buffer, 100);
return make_reg(0, message_get_talker(&state)); /* Talker id */ return make_reg(0, message_get_talker(&state)); /* Talker id */
} else } else {
{
if (buffer) strcpy(buffer, DUMMY_MESSAGE); if (buffer) strcpy(buffer, DUMMY_MESSAGE);
return NULL_REG; return NULL_REG;
} }
} }
case 1 : case 1 : {
{
char *buffer = argc == 7 ? kernel_dereference_char_pointer(s, argv[6], 0) : NULL; char *buffer = argc == 7 ? kernel_dereference_char_pointer(s, argv[6], 0) : NULL;
if (message_get_next(&state)) if (message_get_next(&state)) {
{ if (buffer)
if (buffer)
message_get_text(&state, buffer, 100); message_get_text(&state, buffer, 100);
return make_reg(0, message_get_talker(&state)); /* Talker id */ return make_reg(0, message_get_talker(&state)); /* Talker id */
} else } else {
{
if (buffer) strcpy(buffer, DUMMY_MESSAGE); if (buffer) strcpy(buffer, DUMMY_MESSAGE);
return NULL_REG; return NULL_REG;
} }
} }
case 2 : case 2 : {
{
message_tuple_t tuple; message_tuple_t tuple;
int module = UKPV(1); int module = UKPV(1);
tuple.noun = UKPV(2); tuple.noun = UKPV(2);
@ -793,7 +775,7 @@ kMessage(state_t *s, int funct_nr, int argc, reg_t *argv)
tuple.seq = UKPV(5); tuple.seq = UKPV(5);
if (message_state_load_res(&state, module) && message_get_specific(&state, &tuple)) if (message_state_load_res(&state, module) && message_get_specific(&state, &tuple))
return make_reg(0, message_get_length(&state)+1); return make_reg(0, message_get_length(&state) + 1);
else return NULL_REG; else return NULL_REG;
} }
} }

View file

@ -30,8 +30,7 @@
#if 0 #if 0
// Unreferenced - removed // Unreferenced - removed
static static
int get_talker_trivial(index_record_cursor_t *cursor) int get_talker_trivial(index_record_cursor_t *cursor) {
{
return -1; return -1;
} }
#endif #endif
@ -41,8 +40,7 @@ int get_talker_trivial(index_record_cursor_t *cursor)
#if 0 #if 0
// Unreferenced - removed // Unreferenced - removed
static static
void index_record_parse_2101(index_record_cursor_t *cursor, message_tuple_t *t) void index_record_parse_2101(index_record_cursor_t *cursor, message_tuple_t *t) {
{
int noun = *(cursor->index_record + 0); int noun = *(cursor->index_record + 0);
int verb = *(cursor->index_record + 1); int verb = *(cursor->index_record + 1);
@ -55,11 +53,10 @@ void index_record_parse_2101(index_record_cursor_t *cursor, message_tuple_t *t)
#if 0 #if 0
// Unreferenced - removed // Unreferenced - removed
static static
void index_record_get_text_2101(index_record_cursor_t *cursor, char *buffer, int buffer_size) void index_record_get_text_2101(index_record_cursor_t *cursor, char *buffer, int buffer_size) {
{
int offset = getUInt16(cursor->index_record + 2); int offset = getUInt16(cursor->index_record + 2);
char *stringptr = (char *)cursor->resource_beginning + offset; char *stringptr = (char *)cursor->resource_beginning + offset;
strncpy(buffer, stringptr, buffer_size); strncpy(buffer, stringptr, buffer_size);
} }
#endif #endif
@ -67,8 +64,7 @@ void index_record_get_text_2101(index_record_cursor_t *cursor, char *buffer, int
#if 0 #if 0
// Unreferenced - removed // Unreferenced - removed
static static
int header_get_index_record_count_2101(byte *header) int header_get_index_record_count_2101(byte *header) {
{
return getUInt16(header + 4); return getUInt16(header + 4);
} }
#endif #endif
@ -76,8 +72,7 @@ int header_get_index_record_count_2101(byte *header)
/* Version 3.411 and later code ahead */ /* Version 3.411 and later code ahead */
static static
void index_record_parse_3411(index_record_cursor_t *cursor, message_tuple_t *t) void index_record_parse_3411(index_record_cursor_t *cursor, message_tuple_t *t) {
{
int noun = *(cursor->index_record + 0); int noun = *(cursor->index_record + 0);
int verb = *(cursor->index_record + 1); int verb = *(cursor->index_record + 1);
int cond = *(cursor->index_record + 2); int cond = *(cursor->index_record + 2);
@ -90,49 +85,43 @@ void index_record_parse_3411(index_record_cursor_t *cursor, message_tuple_t *t)
} }
static static
int index_record_get_talker_3411(index_record_cursor_t *cursor) int index_record_get_talker_3411(index_record_cursor_t *cursor) {
{
return *(cursor->index_record + 4); return *(cursor->index_record + 4);
} }
static static
void index_record_get_text_3411(index_record_cursor_t *cursor, char *buffer, int buffer_size) void index_record_get_text_3411(index_record_cursor_t *cursor, char *buffer, int buffer_size) {
{
int offset = getUInt16(cursor->index_record + 5); int offset = getUInt16(cursor->index_record + 5);
char *stringptr = (char *)cursor->resource_beginning + offset; char *stringptr = (char *)cursor->resource_beginning + offset;
strncpy(buffer, stringptr, buffer_size); strncpy(buffer, stringptr, buffer_size);
} }
static static
int header_get_index_record_count_3411(byte *header) int header_get_index_record_count_3411(byte *header) {
{
return getUInt16(header + 8); return getUInt16(header + 8);
} }
/* Generic code from here on */ /* Generic code from here on */
static static
int four_tuple_match(message_tuple_t *t1, message_tuple_t *t2) int four_tuple_match(message_tuple_t *t1, message_tuple_t *t2) {
{ return
return t1->noun == t2->noun &&
t1->noun == t2->noun && t1->verb == t2->verb &&
t1->verb == t2->verb && t1->cond == t2->cond &&
t1->cond == t2->cond && t1->seq == t2->seq;
t1->seq == t2->seq;
} }
static static
void index_record_cursor_initialize(message_state_t *state, index_record_cursor_t *cursor) void index_record_cursor_initialize(message_state_t *state, index_record_cursor_t *cursor) {
{
cursor->resource_beginning = state->current_res->data; cursor->resource_beginning = state->current_res->data;
cursor->index_record = state->index_records; cursor->index_record = state->index_records;
cursor->index = 1; cursor->index = 1;
} }
static static
int index_record_next(message_state_t *state, index_record_cursor_t *cursor) int index_record_next(message_state_t *state, index_record_cursor_t *cursor) {
{
if (cursor->index == state->record_count) if (cursor->index == state->record_count)
return 0; return 0;
cursor->index_record += state->handler->index_record_size; cursor->index_record += state->handler->index_record_size;
@ -141,15 +130,13 @@ int index_record_next(message_state_t *state, index_record_cursor_t *cursor)
} }
static static
int index_record_find(message_state_t *state, message_tuple_t *t, index_record_cursor_t *cursor) int index_record_find(message_state_t *state, message_tuple_t *t, index_record_cursor_t *cursor) {
{
message_tuple_t looking_at; message_tuple_t looking_at;
int found = 0; int found = 0;
index_record_cursor_initialize(state, cursor); index_record_cursor_initialize(state, cursor);
do do {
{
state->handler->parse(cursor, &looking_at); state->handler->parse(cursor, &looking_at);
if (four_tuple_match(t, &looking_at)) if (four_tuple_match(t, &looking_at))
found = 1; found = 1;
@ -160,46 +147,39 @@ int index_record_find(message_state_t *state, message_tuple_t *t, index_record_c
return found; return found;
} }
int message_get_specific(message_state_t *state, message_tuple_t *t) int message_get_specific(message_state_t *state, message_tuple_t *t) {
{
return index_record_find(state, t, &state->engine_cursor); return index_record_find(state, t, &state->engine_cursor);
} }
int message_get_next(message_state_t *state) int message_get_next(message_state_t *state) {
{
return index_record_next(state, &state->engine_cursor); return index_record_next(state, &state->engine_cursor);
} }
int message_get_talker(message_state_t *state) int message_get_talker(message_state_t *state) {
{
return state->handler->get_talker(&state->engine_cursor); return state->handler->get_talker(&state->engine_cursor);
} }
int message_get_text(message_state_t *state, char *buffer, int length) int message_get_text(message_state_t *state, char *buffer, int length) {
{
state->handler->get_text(&state->engine_cursor, buffer, length); state->handler->get_text(&state->engine_cursor, buffer, length);
return strlen(buffer); return strlen(buffer);
} }
int message_get_length(message_state_t *state) int message_get_length(message_state_t *state) {
{
char buffer[500]; char buffer[500];
state->handler->get_text(&state->engine_cursor, buffer, sizeof(buffer)); state->handler->get_text(&state->engine_cursor, buffer, sizeof(buffer));
return strlen(buffer); return strlen(buffer);
} }
int message_state_load_res(message_state_t *state, int module) int message_state_load_res(message_state_t *state, int module) {
{ if (state->module == module)
if (state->module == module)
return 1; return 1;
state->module = module; state->module = module;
state->current_res = scir_find_resource(state->resmgr, sci_message, module, 0); state->current_res = scir_find_resource(state->resmgr, sci_message, module, 0);
if (state->current_res == NULL || if (state->current_res == NULL ||
state->current_res->data == NULL) state->current_res->data == NULL) {
{
sciprintf("Message subsystem: Failed to load %d.MSG\n", module); sciprintf("Message subsystem: Failed to load %d.MSG\n", module);
return 0; return 0;
} }
@ -211,17 +191,17 @@ int message_state_load_res(message_state_t *state, int module)
return 1; return 1;
} }
static message_handler_t fixed_handler = {3411, static message_handler_t fixed_handler = {3411,
index_record_parse_3411, index_record_parse_3411,
index_record_get_talker_3411, index_record_get_talker_3411,
index_record_get_text_3411, index_record_get_text_3411,
header_get_index_record_count_3411, header_get_index_record_count_3411,
10, 10,
11}; 11
};
void message_state_initialize(resource_mgr_t *resmgr, message_state_t *state) void message_state_initialize(resource_mgr_t *resmgr, message_state_t *state) {
{
// resource_t *tester = scir_find_resource(resmgr, sci_message, 0, 0); // resource_t *tester = scir_find_resource(resmgr, sci_message, 0, 0);
//int version; //int version;

View file

@ -27,16 +27,14 @@
#include "sci/include/sciresource.h" #include "sci/include/sciresource.h"
typedef struct typedef struct {
{
int noun; int noun;
int verb; int verb;
int cond; int cond;
int seq; int seq;
} message_tuple_t; } message_tuple_t;
typedef struct typedef struct {
{
byte *index_record; byte *index_record;
int index; int index;
byte *resource_beginning; byte *resource_beginning;
@ -48,20 +46,18 @@ typedef int get_talker_t(index_record_cursor_t *cursor);
typedef void get_text_t(index_record_cursor_t *cursor, char *buffer, int buffer_size); typedef void get_text_t(index_record_cursor_t *cursor, char *buffer, int buffer_size);
typedef int index_record_count_t(byte *header); typedef int index_record_count_t(byte *header);
typedef struct typedef struct {
{
int version_id; int version_id;
parse_index_record_t *parse; parse_index_record_t *parse;
get_talker_t *get_talker; get_talker_t *get_talker;
get_text_t *get_text; get_text_t *get_text;
index_record_count_t *index_record_count; index_record_count_t *index_record_count;
int header_size; int header_size;
int index_record_size; int index_record_size;
} message_handler_t; } message_handler_t;
typedef struct typedef struct {
{
int initialized; int initialized;
message_handler_t *handler; message_handler_t *handler;
resource_mgr_t *resmgr; resource_mgr_t *resmgr;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -30,22 +30,21 @@
#include "sci/include/sci_memory.h" #include "sci/include/sci_memory.h"
void void
sys_string_acquire(sys_strings_t *strings, int index, const char *name, int max_len) sys_string_acquire(sys_strings_t *strings, int index, const char *name, int max_len) {
{
sys_string_t *str = strings->strings + index; sys_string_t *str = strings->strings + index;
if (index < 0 || index >= SYS_STRINGS_MAX) { if (index < 0 || index >= SYS_STRINGS_MAX) {
fprintf(stderr, "[SYSSTR] Error: Attempt to acquire string #%d\n", fprintf(stderr, "[SYSSTR] Error: Attempt to acquire string #%d\n",
index); index);
BREAKPOINT(); BREAKPOINT();
} }
if (str->name if (str->name
&& (strcmp(name, str->name) && (strcmp(name, str->name)
|| (str->max_size != max_len))) { || (str->max_size != max_len))) {
fprintf(stderr, "[SYSSTR] Error: Attempt to re-acquire existing string #%d;" fprintf(stderr, "[SYSSTR] Error: Attempt to re-acquire existing string #%d;"
"was '%s', tried to claim as '%s'\n", "was '%s', tried to claim as '%s'\n",
index, str->name, name); index, str->name, name);
BREAKPOINT(); BREAKPOINT();
} }
@ -56,13 +55,12 @@ sys_string_acquire(sys_strings_t *strings, int index, const char *name, int max_
} }
int int
sys_string_set(sys_strings_t *strings, int index, const char *value) sys_string_set(sys_strings_t *strings, int index, const char *value) {
{
sys_string_t *str = strings->strings + index; sys_string_t *str = strings->strings + index;
if (index < 0 || index >= SYS_STRINGS_MAX || !str->name) { if (index < 0 || index >= SYS_STRINGS_MAX || !str->name) {
fprintf(stderr, "[SYSSTR] Error: Attempt to write to invalid/unused string #%d\n", fprintf(stderr, "[SYSSTR] Error: Attempt to write to invalid/unused string #%d\n",
index); index);
BREAKPOINT(); BREAKPOINT();
return 1; return 1;
} }
@ -73,26 +71,23 @@ sys_string_set(sys_strings_t *strings, int index, const char *value)
} }
void void
sys_string_free(sys_strings_t *strings, int index) sys_string_free(sys_strings_t *strings, int index) {
{
sys_string_t *str = strings->strings + index; sys_string_t *str = strings->strings + index;
free(str->name); free(str->name);
str->name = NULL; str->name = NULL;
free(str->value); free(str->value);
str->value = NULL; str->value = NULL;
str->max_size = 0; str->max_size = 0;
} }
void void
sys_string_free_all(sys_strings_t *strings) sys_string_free_all(sys_strings_t *strings) {
{
int i; int i;
for (i=0;i<SYS_STRINGS_MAX;i++) for (i = 0;i < SYS_STRINGS_MAX;i++) {
{
if (strings->strings[i].name) if (strings->strings[i].name)
sys_string_free(strings, i); sys_string_free(strings, i);
} }
@ -100,8 +95,7 @@ sys_string_free_all(sys_strings_t *strings)
} }
void void
sys_strings_restore(sys_strings_t *new_strings, sys_strings_t *old_strings) sys_strings_restore(sys_strings_t *new_strings, sys_strings_t *old_strings) {
{
int i; int i;
/* First, pad memory */ /* First, pad memory */

File diff suppressed because it is too large Load diff