void opcode_restore_undo(void) { int result; size_t dynamic_memory_size; struct undo_frame *frame_to_restore; TRACE_LOG("Opcode: RESTORE_UNDO.\n"); if (undo_index > 0) { undo_index--; frame_to_restore = undo_frames[undo_index]; dynamic_memory_size = (size_t)( active_z_story->dynamic_memory_end - z_mem + 1 ); ensure_z_stack_size(frame_to_restore->z_stack_size); pc = frame_to_restore->pc; //current_z_stack_size = frame_to_restore->z_stack_size; //behind_z_stack = z_stack + current_z_stack_size; z_stack_index = z_stack + frame_to_restore->z_stack_size; stack_words_from_active_routine = frame_to_restore->stack_words_from_active_routine; number_of_locals_active = frame_to_restore->number_of_locals_active; number_of_locals_from_function_call = frame_to_restore->number_of_locals_from_function_call; local_variable_storage_index = z_stack_index - stack_words_from_active_routine - number_of_locals_active; memcpy( z_stack, // non-null when size > 0 frame_to_restore->stack, frame_to_restore->z_stack_size * sizeof(uint16_t)); //current_z_stack_size * sizeof(uint16_t)); memcpy( z_mem, frame_to_restore->dynamic_memory, dynamic_memory_size); delete_undo_frame(frame_to_restore); write_interpreter_info_into_header(); result = 2; } else { result = 0; } read_z_result_variable(); set_variable(z_res_var, (uint16_t)result, false); }
void opcode_load(void) { TRACE_LOG("Opcode: LOAD.\n"); read_z_result_variable(); TRACE_LOG("Loading variable with code %d to variable with code %d.\n", op[0], z_res_var); set_variable(z_res_var, get_variable(op[0], true), false); }
void opcode_pull(void) { uint16_t value = 0; uint16_t spare_slots; uint8_t *user_stack; TRACE_LOG("Opcode: PULL.\n"); if (ver == 6) (void)read_z_result_variable(); if ( (ver != 6) || (number_of_operands < 1) ) { if ( (stack_words_from_active_routine == 0) && (bool_equal(skip_active_routines_stack_check_warning, false)) ) { i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_NOT_ENOUGH_STACK_WORDS_FROM_LOCAL_ROUTINE_ON_STACK, -1); } else { TRACE_LOG("Pulling to variable %x.\n", op[0]); value = z_stack_pull_word(); stack_words_from_active_routine--; } } else { user_stack = z_mem + (uint16_t)op[0]; spare_slots = load_word(user_stack); spare_slots++; value = load_word(user_stack + spare_slots); store_word(user_stack, spare_slots); } if (ver == 6) set_variable(z_res_var, value, true); else set_variable(op[0], value, true); }
void opcode_loadw(void) { uint16_t value; uint8_t *address = z_mem + (uint16_t)(op[0] + ((int16_t)op[1])*2); TRACE_LOG("Opcode: LOADW.\n"); read_z_result_variable(); if (address > active_z_story->static_memory_end) { TRACE_LOG("ERROR: Trying to loadw from %x which is above static memory.\n", address); set_variable(z_res_var, 0, false); } else { value = load_word(address); TRACE_LOG("Loading %x from %x var %x.\n", value, address, z_res_var); set_variable(z_res_var, value, false); } }
void opcode_push_user_stack(void) { uint16_t spare_slots; uint8_t *user_stack; TRACE_LOG("Opcode: PUSH_USER_STACK.\n"); (void)read_z_result_variable(); user_stack = z_mem + (uint16_t)op[1]; if ((spare_slots = load_word(user_stack)) > 0) { store_word(user_stack + spare_slots, (uint16_t)op[0]); spare_slots--; store_word(user_stack, spare_slots); evaluate_branch((uint8_t)1); } else { evaluate_branch((uint8_t)0); } }
void opcode_loadb(void) { uint8_t *address = z_mem + (uint16_t)(op[0] + (int16_t)op[1]); TRACE_LOG("Opcode: LOADB.\n"); read_z_result_variable(); if (address > active_z_story->static_memory_end) { TRACE_LOG("Static memory end: %x.\n", active_z_story->static_memory_end); TRACE_LOG("Trying to loadb from %x which is above static memory.\n", address); set_variable(z_res_var, 0, false); } else { TRACE_LOG("Loading from %x to var %x.\n", *address, z_res_var); set_variable(z_res_var, *address, false); } }
void opcode_save_undo(void) { size_t dynamic_memory_size; struct undo_frame *new_undo_frame; int result; size_t nof_stack_bytes_in_use; TRACE_LOG("Opcode: SAVE_UNDO.\n"); if (max_undo_steps <= 0) { result = 0; } else { if ( (undo_frames == NULL) && (set_max_undo_steps(max_undo_steps) != 0) ) { result = 0; } else { if ((new_undo_frame = create_new_undo_frame()) == NULL) { result = 0; } else { dynamic_memory_size = (size_t)( active_z_story->dynamic_memory_end - z_mem + 1 ); if ( (new_undo_frame->dynamic_memory = malloc(dynamic_memory_size)) == NULL) { delete_undo_frame(new_undo_frame); result = 0; } else { nof_stack_bytes_in_use = (z_stack_index - z_stack) * sizeof(uint16_t); if ((new_undo_frame->stack = (uint16_t*)malloc(nof_stack_bytes_in_use)) == NULL) { delete_undo_frame(new_undo_frame); result = 0; } else { if (undo_index == max_undo_steps) { delete_undo_frame(undo_frames[0]); memmove( undo_frames, undo_frames + 1, sizeof(struct undo_frame*) * (max_undo_steps - 1)); undo_index--; } memcpy( new_undo_frame->stack, z_stack, // non-null when size > 0 nof_stack_bytes_in_use); memcpy( new_undo_frame->dynamic_memory, z_mem, dynamic_memory_size); // new_undo_frame->pc is not allocated, no free required. new_undo_frame->pc = pc; new_undo_frame->z_stack_size = z_stack_index - z_stack; new_undo_frame->stack_words_from_active_routine = stack_words_from_active_routine; new_undo_frame->number_of_locals_active = number_of_locals_active; new_undo_frame->number_of_locals_from_function_call = number_of_locals_from_function_call; undo_frames[undo_index++] = new_undo_frame; result = 1; } } } } } read_z_result_variable(); set_variable(z_res_var, (uint16_t)result, false); }
void opcode_set_font(void) { z_font new_z_font; // If the requested font is available, then it is chosen for the // current window, and the store value is the font ID of the previous // font (which is always positive). If the font is unavailable, // nothing will happen and the store value is 0. // Please note: I consider the "normal" -- code 1 -- and the courier, // fixed font -- code 4 -- to be always available. For simple interfaces, // these are probably the same. The availability of the character graphics // and picture font are read from interface definition. TRACE_LOG("Opcode: SET_FONT\n"); read_z_result_variable(); new_z_font = (int16_t)op[0]; // REVISIT: Implement warning. if ( ( (new_z_font < 0) || (new_z_font > 4) ) || ( (new_z_font == Z_FONT_PICTURE) && (active_interface->is_picture_font_availiable() != true) ) || ( (new_z_font == Z_FONT_CHARACTER_GRAPHICS) && (active_interface->is_character_graphics_font_availiable() != true) ) ) { set_variable(z_res_var, 0, false); return; } /* // REVISIT: Is it correct to not double-set fonts? if (new_z_font != current_font) { if (active_window_number == 0) { #ifndef DISABLE_OUTPUT_HISTORY store_metadata_in_history( outputhistory[0], HISTORY_METADATA_TYPE_FONT, new_z_font); #endif // DISABLE_OUTPUT_HISTORY } else if (active_window_number == 1) { #ifndef DISABLE_BLOCKBUFFER if (ver >= 5) { set_blockbuf_font(upper_window_buffer, new_z_font); } #endif // DISABLE_BLOCKBUFFER } active_interface->set_font(new_z_font); set_variable(z_res_var, (uint16_t)current_font, false); current_font = new_z_font; TRACE_LOG("New font is: %d\n", current_font); } else { set_variable(z_res_var, (uint16_t)current_font, false); } */ current_font = new_z_font; set_variable(z_res_var, (uint16_t)current_font, false); }