diff options
Diffstat (limited to 'sword2/interpreter.cpp')
-rw-r--r-- | sword2/interpreter.cpp | 791 |
1 files changed, 791 insertions, 0 deletions
diff --git a/sword2/interpreter.cpp b/sword2/interpreter.cpp new file mode 100644 index 0000000000..91bf84f3ad --- /dev/null +++ b/sword2/interpreter.cpp @@ -0,0 +1,791 @@ +/* Copyright (C) 1994-2003 Revolution Software Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#ifndef INSIDE_LINC // Are we running in linc? +#include "console.h" +#endif + +#include "driver/driver96.h" +#include "interpreter.h" + + + +// This file serves two purposes. It is compiled as part of the test functions +// of Linc, and also as part of the game + + +// The machine code table + +int32 FN_test_function(int32 *params); +int32 FN_test_flags(int32 *params); +int32 FN_register_start_point(int32 *params); +int32 FN_init_background(int32 *params); +int32 FN_set_session(int32 *params); +int32 FN_back_sprite(int32 *params); +int32 FN_sort_sprite(int32 *params); +int32 FN_fore_sprite(int32 *params); +int32 FN_register_mouse(int32 *params); +int32 FN_anim(int32 *); +int32 FN_random(int32 *); +int32 FN_preload(int32 *); +int32 FN_add_subject(int32 *); +int32 FN_interact(int32 *); +int32 FN_choose(int32 *); +int32 FN_walk(int32 *); +int32 FN_walk_to_anim(int32 *); // walk to start position of anim +int32 FN_turn(int32 *); // turn to (dir) +int32 FN_stand_at(int32 *); // stand at (x,y,dir) +int32 FN_stand(int32 *); // stand facing (dir) +int32 FN_stand_after_anim(int32 *); // stand at end position of anim +int32 FN_pause(int32 *); +int32 FN_mega_table_anim(int32 *); +int32 FN_add_menu_object(int32 *); +int32 FN_start_conversation(int32 *); +int32 FN_end_conversation(int32 *); +int32 FN_set_frame(int32 *); +int32 FN_random_pause(int32 *); +int32 FN_register_frame(int32 *); +int32 FN_no_sprite(int32 *); +int32 FN_send_sync(int32 *); +int32 FN_update_player_stats(int32 *); +int32 FN_pass_graph(int32 *); +int32 FN_init_floor_mouse(int32 *); +int32 FN_pass_mega(int32 *); +int32 FN_face_xy(int32 *); +int32 FN_end_session(int32 *); +int32 FN_no_human(int32 *); +int32 FN_add_human(int32 *); +int32 FN_we_wait(int32 *); +int32 FN_they_do_we_wait(int32 *); +int32 FN_they_do(int32 *); +int32 FN_walk_to_talk_to_mega(int32 *); +int32 FN_fade_down(int32 *); +int32 FN_i_speak(int32 *); +int32 FN_total_restart(int32 *); +int32 FN_set_walkgrid(int32 *); +int32 FN_speech_process(int32 *); +int32 FN_set_scaling(int32 *); +int32 FN_start_event(int32 *); +int32 FN_check_event_waiting(int32 *); +int32 FN_request_speech(int32 *); +int32 FN_gosub(int32 *); +int32 FN_timed_wait(int32 *); +int32 FN_play_fx(int32 *); +int32 FN_stop_fx(int32 *); +int32 FN_play_music(int32 *); +int32 FN_stop_music(int32 *); +int32 FN_set_value(int32 *); +int32 FN_new_script(int32 *); +int32 FN_get_sync(int32 *); +int32 FN_wait_sync(int32 *); +int32 FN_register_walkgrid(int32 *); +int32 FN_reverse_mega_table_anim(int32 *); +int32 FN_reverse_anim(int32 *); +int32 FN_add_to_kill_list(int32 *); +int32 FN_set_standby_coords(int32 *); +int32 FN_back_par0_sprite(int32 *params); +int32 FN_back_par1_sprite(int32 *params); +int32 FN_fore_par0_sprite(int32 *params); +int32 FN_fore_par1_sprite(int32 *params); +int32 FN_fore_par1_sprite(int32 *params); +int32 FN_set_player_action_event(int32 *params); +int32 FN_set_scroll_coordinate(int32 *params); +int32 FN_stand_at_anim(int32 *params); +int32 FN_set_scroll_left_mouse(int32 *params); +int32 FN_set_scroll_right_mouse(int32 *params); +int32 FN_colour(int32 *params); +int32 FN_flash(int32 *params); +int32 FN_prefetch(int32 *params); +int32 FN_get_player_savedata(int32 *params); +int32 FN_pass_player_savedata(int32 *params); +int32 FN_send_event(int32 *params); +int32 FN_add_walkgrid(int32 *params); +int32 FN_remove_walkgrid(int32 *params); +int32 FN_check_for_event(int32 *params); +int32 FN_pause_for_event(int32 *params); +int32 FN_clear_event(int32 *params); +int32 FN_face_mega(int32 *params); +int32 FN_play_sequence(int32 *params); +int32 FN_shaded_sprite(int32 *params); +int32 FN_unshaded_sprite(int32 *params); +int32 FN_fade_up(int32 *params); +int32 FN_display_msg(int32 *params); +int32 FN_set_object_held(int32 *params); +int32 FN_add_sequence_text(int32 *params); +int32 FN_reset_globals(int32 *params); +int32 FN_set_palette(int32 *params); +int32 FN_register_pointer_text(int32 *params); +int32 FN_fetch_wait(int32 *params); +int32 FN_release(int32 *params); +int32 FN_sound_fetch(int32 *params); +int32 FN_prepare_music(int32 *params); +int32 FN_smacker_lead_in(int32 *params); +int32 FN_smacker_lead_out(int32 *params); +int32 FN_stop_all_fx(int32 *params); +int32 FN_check_player_activity(int32 *params); +int32 FN_reset_player_activity_delay(int32 *params); +int32 FN_check_music_playing(int32 *params); +int32 FN_play_credits(int32 *params); +int32 FN_set_scroll_speed_normal(int32 *params); +int32 FN_set_scroll_speed_slow(int32 *params); +int32 FN_remove_chooser(int32 *params); +int32 FN_set_fx_vol_and_pan(int32 *params); +int32 FN_set_fx_vol(int32 *params); +int32 FN_restore_game(int32 *params); +int32 FN_refresh_inventory(int32 *params); +int32 FN_change_shadows(int32 *params); + +#define MAX_FN_NUMBER 117 + +extern int32 (*McodeTable[])(int32 *); + +#ifndef INSIDE_LINC +int32 * globalInterpreterVariables2 = NULL; // Point to the global varibale data +int g_debugFlag = 0; // Set this to turn debugging on +#endif + + +int32 (*McodeTable[MAX_FN_NUMBER+1])(int32 *) = +{ FN_test_function, + FN_test_flags, + FN_register_start_point, + FN_init_background, + FN_set_session, + FN_back_sprite, + FN_sort_sprite, + FN_fore_sprite, + FN_register_mouse, + FN_anim, + FN_random, + FN_preload, + FN_add_subject, + FN_interact, + FN_choose, + FN_walk, + FN_walk_to_anim, + FN_turn, + FN_stand_at, + FN_stand, + FN_stand_after_anim, + FN_pause, + FN_mega_table_anim, + FN_add_menu_object, + FN_start_conversation, + FN_end_conversation, + FN_set_frame, + FN_random_pause, + FN_register_frame, + FN_no_sprite, + FN_send_sync, + FN_update_player_stats, + FN_pass_graph, + FN_init_floor_mouse, + FN_pass_mega, + FN_face_xy, + FN_end_session, + FN_no_human, + FN_add_human, + FN_we_wait, + FN_they_do_we_wait, + FN_they_do, + FN_walk_to_talk_to_mega, + FN_fade_down, + FN_i_speak, + FN_total_restart, + FN_set_walkgrid, + FN_speech_process, + FN_set_scaling, + FN_start_event, + FN_check_event_waiting, + FN_request_speech, + FN_gosub, + FN_timed_wait, + FN_play_fx, + FN_stop_fx, + FN_play_music, + FN_stop_music, + FN_set_value, + FN_new_script, + FN_get_sync, + FN_wait_sync, + FN_register_walkgrid, + FN_reverse_mega_table_anim, + FN_reverse_anim, + FN_add_to_kill_list, + FN_set_standby_coords, + FN_back_par0_sprite, + FN_back_par1_sprite, + FN_fore_par0_sprite, + FN_fore_par1_sprite, + FN_set_player_action_event, + FN_set_scroll_coordinate, + FN_stand_at_anim, + FN_set_scroll_left_mouse, + FN_set_scroll_right_mouse, + FN_colour, + FN_flash, + FN_prefetch, + FN_get_player_savedata, + FN_pass_player_savedata, + FN_send_event, + FN_add_walkgrid, + FN_remove_walkgrid, + FN_check_for_event, + FN_pause_for_event, + FN_clear_event, + FN_face_mega, + FN_play_sequence, + FN_shaded_sprite, + FN_unshaded_sprite, + FN_fade_up, + FN_display_msg, + FN_set_object_held, + FN_add_sequence_text, + FN_reset_globals, + FN_set_palette, + FN_register_pointer_text, + FN_fetch_wait, + FN_release, + FN_prepare_music, + FN_sound_fetch, + FN_prepare_music, + FN_smacker_lead_in, + FN_smacker_lead_out, + FN_stop_all_fx, + FN_check_player_activity, + FN_reset_player_activity_delay, + FN_check_music_playing, + FN_play_credits, + FN_set_scroll_speed_normal, + FN_set_scroll_speed_slow, + FN_remove_chooser, + FN_set_fx_vol_and_pan, + FN_set_fx_vol, + FN_restore_game, + FN_refresh_inventory, + FN_change_shadows, +}; + +#define CHECKSTACKPOINTER2 ASSERT((stackPointer2>=0)&&(stackPointer2<STACK_SIZE)); +#define PUSHONSTACK(x) {stack2[stackPointer2] = (x);stackPointer2++;CHECKSTACKPOINTER2;} +#define POPOFFSTACK(x) {x=stack2[stackPointer2-1];stackPointer2--;CHECKSTACKPOINTER2;} +#define DOOPERATION(x) {stack2[stackPointer2-2] = (x);stackPointer2--;CHECKSTACKPOINTER2;} + +#ifndef INSIDE_LINC +void SetGlobalInterpreterVariables(int32 *vars) +{ + globalInterpreterVariables2 = vars; +} +#endif + +#ifdef INSIDE_LINC // Are we running in linc? +int RunScript ( MCBOVirtualSword &engine , const char * scriptData , char * objectData , uint32 *offset ) +#else +int RunScript ( const char * scriptData , char * objectData , uint32 *offset ) +#endif +{ + #define STACK_SIZE 10 + + _standardHeader *header = (_standardHeader *)scriptData; + scriptData += sizeof(_standardHeader) + sizeof(_object_hub); + + // The script data format: + + + // int32_TYPE 1 Size of variable space in bytes + // ... The variable space + // int32_TYPE 1 numberOfScripts + // int32_TYPE numberOfScripts The offsets for each script + + + // Initialise some stuff + + int ip = 0; // Code pointer + int curCommand,parameter,value; // Command and parameter variables + int32 stack2[STACK_SIZE]; // The current stack + int32 stackPointer2 = 0; // Position within stack + int parameterReturnedFromMcodeFunction=0; // Allow scripts to return things + int savedStartOfMcode; // For saving start of mcode commands + + // Get the start of variables and start of code + DEBUG3("Enter interpreter data %x, object %x, offset %d",scriptData,objectData,*offset); + const char *variables = scriptData + sizeof(int); + const char *code = scriptData + *((int *)scriptData) + sizeof(int); + uint32 noScripts = *((int32 *)code); + if ( (*offset) < noScripts) + { ip = ((int *)code)[(*offset)+1]; + DEBUG2("Start script %d with offset %d",*offset,ip); + } + else + { ip = (*offset); + DEBUG1("Start script with offset %d",ip); + } + + code += noScripts * sizeof(int) + sizeof(int); + +/************************************************************************************************/ +#ifdef DONTPROCESSSCRIPTCHECKSUM + + code += sizeof(int) * 3; + +#else + + // Code should nopw be pointing at an identifier and a checksum + int *checksumBlock = (int *)code; + code += sizeof(int) * 3; + + if (checksumBlock[0] != 12345678) + { +#ifdef INSIDE_LINC + AfxMessageBox(CVString("Invalid script in object %s",header->name)); +#else + Con_fatal_error("Invalid script in object %s",header->name); +#endif + return(0); + } + int codeLen = checksumBlock[1]; + int checksum = 0; + for (int count = 0 ; count < codeLen ; count++) + checksum += (unsigned char)code[count]; + if ( checksum != checksumBlock[2] ) + { +#ifdef INSIDE_LINC + AfxMessageBox(CVString("Checksum error in script %s",header->name)); +#else + Con_fatal_error("Checksum error in object %s",header->name); +#endif + return(0); + } + +#endif //DONTPROCESSSCRIPTCHECKSUM + +/************************************************************************************************/ + + int runningScript = 1; + while ( runningScript ) + { curCommand = code[ip++]; + switch(curCommand) + { case CP_END_SCRIPT: // 0 End the script + DEBUG1("End script",0); + runningScript = 0; +#ifdef INSIDE_LINC + engine.AddTextLine( "End script" , VS_COL_GREY ); + engine.AddTextLine( "" , VS_COL_GREY ); +#endif + break; + + case CP_PUSH_LOCAL_VAR32: // 1 Push the contents of a local variable + Read16ip(parameter) + DEBUG2("Push local var %d (%d)",parameter,*((int *)(variables+parameter))); + PUSHONSTACK ( *((int *)(variables+parameter)) ); + break; + + + case CP_PUSH_GLOBAL_VAR32: // 2 Push a global variable + Read16ip(parameter) +#ifdef INSIDE_LINC + DEBUG2("Push global var %d (%d)",parameter,g_GlobalVariables.GetLocalByIndex(parameter).GetValue()); + PUSHONSTACK ( g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ); +#else + DEBUG2("Push global var %d (%d)",parameter,globalInterpreterVariables2[parameter]); + ASSERT(globalInterpreterVariables2); + PUSHONSTACK ( globalInterpreterVariables2[parameter] ); +#endif + break; + + case CP_POP_LOCAL_VAR32: // 3 Pop a value into a local word variable + Read16ip(parameter) + POPOFFSTACK ( value ); + DEBUG2("Pop %d into var %d",value,parameter); + *((int *)(variables+parameter)) = value; + break; + + case CP_CALL_MCODE: // 4 Call an mcode routine + { + Read16ip(parameter) + ASSERT(parameter <= MAX_FN_NUMBER); + value = *((int8 *)(code+ip)); // amount to adjust stack by (no of parameters) + ip ++; + DEBUG2("Call mcode %d with stack = %x",parameter,stack2+(stackPointer2-value)); +#ifdef INSIDE_LINC + int retVal = engine.McodeTable(parameter , stack2+(stackPointer2-value)); +#else + int retVal = McodeTable[parameter](stack2+(stackPointer2-value)); +#endif + stackPointer2 -= value; + CHECKSTACKPOINTER2 + switch ( retVal & 7 ) + { case IR_STOP: // 0: Quit out for a cycle + *offset = ip; + return(0); + + case IR_CONT: // 1: // Continue as normal + break; + + case IR_TERMINATE: // 2: + // Return without updating the offset + return(2); + + case IR_REPEAT: // 3: + // Return setting offset to start of this function call + *offset = savedStartOfMcode; + return(0); + + case IR_GOSUB: // 4: //that's really neat + *offset = ip; + return(2); + + default: + ASSERT(FALSE); + } + parameterReturnedFromMcodeFunction = retVal >> 3; + } + break; + + case CP_PUSH_LOCAL_ADDR: // 5 push the address of a local variable + Read16ip(parameter) + DEBUG2("Push address of local variable %d (%x)",parameter,(int32)(variables + parameter)); + PUSHONSTACK ( (int32)(variables + parameter) ); + break; + + case CP_PUSH_INT32: // 6 Push a long word value on to the stack + Read32ip(parameter) + DEBUG2("Push int32 %d (%x)",parameter,parameter); + PUSHONSTACK ( parameter ); + break; + + + case CP_SKIPONFALSE: // 7 Skip if the value on the stack is false + Read32ipLeaveip(parameter) + POPOFFSTACK ( value ); + DEBUG2("Skip %d if %d is false",parameter,value); + if (value) + ip += sizeof(int32); + else + ip += parameter; + break; + + case CP_SKIPALLWAYS: // 8 skip a block + Read32ipLeaveip(parameter) + DEBUG1("Skip %d",parameter); + ip += parameter; + break; + + case CP_SWITCH: // 9 switch + { POPOFFSTACK ( value ); + int caseCount; + Read32ip(caseCount) + // Search the cases + int foundCase = 0; + for (int count = 0 ; (count < caseCount) && (!foundCase) ; count++) + { + if (value == *((int32 *)(code+ip))) + { // We have found the case, so lets jump to it + foundCase = 1; + ip += *((int32 *)(code+ip+sizeof(int32))); + } + else + ip += sizeof(int32) * 2; + } + // If we found no matching case then use the default + if (!foundCase) + { + ip += *((int32 *)(code+ip)); + } + } + break; + + case CP_ADDNPOP_LOCAL_VAR32: // 10 + Read16ip(parameter) + POPOFFSTACK ( value ); + *((int *)(variables+parameter)) += value; + DEBUG3("+= %d into var %d->%d",value,parameter,*((int *)(variables+parameter))); + break; + + case CP_SUBNPOP_LOCAL_VAR32: // 11 + Read16ip(parameter) + POPOFFSTACK ( value ); + *((int *)(variables+parameter)) -= value; + DEBUG3("-= %d into var %d->%d",value,parameter,*((int *)(variables+parameter))); + break; + + case CP_SKIPONTRUE: // 12 Skip if the value on the stack is TRUE + Read32ipLeaveip(parameter) + POPOFFSTACK ( value ); + DEBUG2("Skip %d if %d is false",parameter,value); + if (!value) + ip += sizeof(int32); + else + ip += parameter; + break; + + case CP_POP_GLOBAL_VAR32: // 13 // Pop a global variable + Read16ip(parameter) + POPOFFSTACK ( value ); + DEBUG2("Pop %d into global var %d",value,parameter); +#ifdef INSIDE_LINC + g_GlobalVariables.lclSet(parameter,value); + engine.AddTextLine(CVString( "Set variable %s to %d", + g_GlobalVariables.GetLocalByIndex(parameter).GetName(), + g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ), + VS_COL_GREY); +#else //INSIDE_LINC + +#ifdef TRACEGLOBALVARIABLESET + TRACEGLOBALVARIABLESET(parameter,value); +#endif + + globalInterpreterVariables2[parameter] = value; + +#endif + break; + + case CP_ADDNPOP_GLOBAL_VAR32: // 14 Add and pop a global variable + { Read16ip(parameter) +// parameter = *((int16_TYPE *)(code+ip)); +// ip += 2; + POPOFFSTACK ( value ); +#ifdef INSIDE_LINC + int newVal = g_GlobalVariables.GetLocalByIndex(parameter).GetValue() + value ; + g_GlobalVariables.lclSet(parameter, newVal ); + engine.AddTextLine( CVString( "Set variable %s to %d", + g_GlobalVariables.GetLocalByIndex(parameter).GetName(), + g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ), + VS_COL_GREY); +#else + globalInterpreterVariables2[parameter] += value; + DEBUG3("+= %d into global var %d->%d",value,parameter,*((int *)(variables+parameter))); +#endif + break; + } + + case CP_SUBNPOP_GLOBAL_VAR32: // 15 Sub and pop a global variable + { Read16ip(parameter) +// parameter = *((int16_TYPE *)(code+ip)); +// ip += 2; + POPOFFSTACK ( value ); +#ifdef INSIDE_LINC + int newVal = g_GlobalVariables.GetLocalByIndex(parameter).GetValue() - value ; + g_GlobalVariables.lclSet(parameter, newVal ); + engine.AddTextLine( CVString( "Set variable %s to %d", + g_GlobalVariables.GetLocalByIndex(parameter).GetName(), + g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ), + VS_COL_GREY); +#else + globalInterpreterVariables2[parameter] -= value; + DEBUG3("-= %d into global var %d->%d",value,parameter,*((int *)(variables+parameter))); +#endif + break; + } + + case CP_DEBUGON: + // Turn debugging on + g_debugFlag = 1; + break; + + case CP_DEBUGOFF: + // Turn debugging on + g_debugFlag = 0; + break; + + case CP_QUIT: +#ifdef INSIDE_LINC + break; +#else + // Quit out for a cycle + *offset = ip; + return(0); +#endif + + case CP_TERMINATE: + // Quit out immediately without affecting the offset pointer + return(3); + +/****************************************************************************************************************** +******************************************************************************************************************/ + + // Operators + + case OP_ISEQUAL: // 20 // '==' + DEBUG3("%d == %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] == stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] == stack2[stackPointer2-1]) ); + break; + + case OP_PLUS: // 21 // '+' + DEBUG3("%d + %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] + stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] + stack2[stackPointer2-1]) ); + break; + + case OP_MINUS: // 22 // '+' + DEBUG3("%d - %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] - stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] - stack2[stackPointer2-1]) ); + break; + + case OP_TIMES: // 23 // '+' + DEBUG3("%d * %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] * stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] * stack2[stackPointer2-1]) ); + break; + + case OP_DEVIDE: // 24 // '+' + DEBUG3("%d / %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] / stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] / stack2[stackPointer2-1]) ); + break; + + case OP_NOTEQUAL: // 25 // '!=' + DEBUG3("%d != %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] != stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] != stack2[stackPointer2-1]) ); + break; + + case OP_ANDAND: // 26 + DEBUG3("%d != %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] && stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] && stack2[stackPointer2-1]) ); + break; + + case OP_GTTHAN: // 27 > + DEBUG3("%d > %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] > stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] > stack2[stackPointer2-1]) ); + break; + + case OP_LSTHAN: // 28 < + DEBUG3("%d < %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] < stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] < stack2[stackPointer2-1]) ); + break; + + case CP_JUMP_ON_RETURNED: // 29 + { // Jump to a part of the script depending on the return value from an mcode routine + parameter = *((int8 *)(code+ip)); // Get the maximum value + ip++; +#ifdef INSIDE_LINC + TRACE("ip %d: Parameter %d skip %d\r\n", ip, + parameterReturnedFromMcodeFunction, + ((int32*)(code+ip))[parameterReturnedFromMcodeFunction] ); +#endif + + ip += ((int32 *)(code+ip))[parameterReturnedFromMcodeFunction]; + } + break; + + case CP_TEMP_TEXT_PROCESS: // 30 + // Process a text line + Read32ip(parameter) +// parameter = *((int32_TYPE *)(code+ip)); +// ip += sizeof(int32_TYPE);; + DEBUG1("Process text id %d",parameter); +#ifdef INSIDE_LINC + // Linc only for the moment + engine.ProcessTextLine(parameter); +#endif //INSIDE_LINC + break; + + case CP_SAVE_MCODE_START: // 31 + // Save the start position on an mcode instruction in case we need to restart it again + savedStartOfMcode = ip-1; + break; + + case CP_RESTART_SCRIPT: // 32 + { // Start the script again + // Do a ip search to find the script we are running + const char *tempScrPtr = scriptData + *((int *)scriptData) + sizeof(int); + int scriptNumber = 0; + int foundScript = 0; + uint32 count = 0; + for (count = 1 ; (count < noScripts) && (!foundScript) ; count++) + { if (ip < ((int *)tempScrPtr)[count+1]) + { scriptNumber = count - 1 ; + foundScript = 1; + } + } + if (!foundScript) + scriptNumber = count - 1 ; + // So we know what script we are running, lets restart it + ip = ((int *)tempScrPtr)[scriptNumber+1]; + break; + } + + case CP_PUSH_STRING: // 33 + { // Push the address of a string on to the stack + parameter = *((int8 *)(code+ip)); // Get the string size + ip += 1; + // ip points to the string + PUSHONSTACK( (int)(code+ip) ); + ip += (parameter+1); + break; + } + + case CP_PUSH_DEREFERENCED_STRUCTURE: // 34 + { // Push the address of a dereferenced structure + Read32ip(parameter) + DEBUG1("Push address of far variable (%x)",(int32)(variables + parameter)); + PUSHONSTACK( (int)(objectData + sizeof(int) + sizeof(_standardHeader) + sizeof(_object_hub) + parameter)); + break; + } + + case OP_GTTHANE: // 35 >= + DEBUG3("%d > %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] >= stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] >= stack2[stackPointer2-1]) ); + break; + + case OP_LSTHANE: // 36 <= + DEBUG3("%d < %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] <= stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] <= stack2[stackPointer2-1]) ); + break; + + case OP_OROR: // 37 + DEBUG3("%d || %d -> %d", stack2[stackPointer2-2], + stack2[stackPointer2-1], + stack2[stackPointer2-2] || stack2[stackPointer2-1]); + DOOPERATION ( (stack2[stackPointer2-2] || stack2[stackPointer2-1]) ); + break; + + + default: +#ifdef INSIDE_LINC + AfxMessageBox(CVString("Invalid interpreter token %d",curCommand)); +#else + Con_fatal_error("Interpreter error: Invalid token %d", curCommand); +#endif + return(3); + } + + } + + return(1); +} |