void op_save_undo(void) { if(saveundo(TRUE)) { mop_store_result(1); } else { mop_store_result(0); } }
void op_save4(void) { if(!savegame()) { mop_store_result(0); } else { mop_store_result(1); } }
void op_pull(void) { if(zversion == 6) { /* v6 uses user stacks */ if(numoperands == 0 || operand[0] == 0) mop_store_result(stack_pop()); else { zword space = LOWORD(operand[0]) + 1; /* One more slot is free */ LOWORDwrite(operand[0], space); mop_store_result(LOWORD(operand[0] + space * ZWORD_SIZE)); } } else { zword val = stack_pop(); set_var(operand[0], val); } }
void op_save5(void) { unsigned i; char filename[256]; unsigned length; strid_t file = NULL; offset end; switch(numoperands) { case 0: op_save4(); return; case 1: n_show_error(E_INSTR, "call save with bad number of operands", numoperands); mop_store_result(0); return; case 2: file = n_file_prompt(fileusage_Data | fileusage_BinaryMode, filemode_Write); break; default: length = LOBYTE(operand[2]); if(length > 13) n_show_port(E_INSTR, "save with filename > 13 characters", length); for(i = 0; i < length; i++) filename[i] = glk_char_to_upper(LOBYTE(operand[2] + 1 + i)); filename[length] = 0; file = n_file_name(fileusage_Data | fileusage_BinaryMode, filemode_Write, filename); break; } if(!file) { mop_store_result(0); return; } end = ((offset) operand[0]) + operand[1]; if(end > 65535 || end > total_size) { n_show_error(E_MEMORY, "attempt to save data out of range", end); mop_store_result(0); return; } w_glk_put_buffer_stream(file, (char *) z_memory + operand[0], operand[1]); glk_stream_close(file, NULL); mop_store_result(1); }
/* Just like restoreundo, but the opposite ;) The idea is to go to the @save_undo location, but return 0 instead of 2 so the game thinks it just successfully saved the game. For games which don't contain @save_undo, jumps to right after the @read instruction. */ BOOL restoreredo(void) { strid_t stack; int i; glui32 wid, hei; stream_result_t poo; move_difference *p = movelist; if(!p || move_index <= 0) return FALSE; move_index--; for(i = 0; i < move_index; i++) { p=p->next; if(!p) return FALSE; } quetzal_undiff(prevstate, dynamic_size, p->delta, p->deltalength, TRUE); n_memcpy(z_memory, prevstate, dynamic_size); stack = glk_stream_open_memory((char *) p->stackchunk, p->stacklength, filemode_Read, 0); quetzal_stack_restore(stack, p->stacklength); glk_stream_close(stack, &poo); if(poo.readcount != p->stacklength) { n_show_error(E_SAVE, "incorrect stack size assessment", poo.readcount); return FALSE; } if(p->PC_in_instruction) { PC = p->PC; mop_store_result(0); false_undo = FALSE; } else { PC = p->PC; false_undo = FALSE; } has_done_save_undo = TRUE; z_find_size(&wid, &hei); set_header(wid, hei); return TRUE; }
BOOL restoreundo(void) { strid_t stack; int i; glui32 wid, hei; move_difference *p = movelist; if(!p || move_index < 0) return FALSE; for(i = 0; i < move_index; i++) { p=p->next; if(!p) return FALSE; } move_index++; n_memcpy(z_memory, prevstate, dynamic_size); quetzal_undiff(prevstate, dynamic_size, p->delta, p->deltalength, TRUE); stack = glk_stream_open_memory((char *) p->stackchunk, p->stacklength, filemode_Read, 0); quetzal_stack_restore(stack, p->stacklength); glk_stream_close(stack, NULL); if(p->PC_in_instruction) { PC = p->PC; mop_store_result(2); false_undo = FALSE; } else { PC = p->oldPC; false_undo = TRUE; } has_done_save_undo = TRUE; z_find_size(&wid, &hei); set_header(wid, hei); return TRUE; }
void op_restore_undo(void) { if(!restoreundo()) mop_store_result(0); }
void op_catch(void) { mop_store_result(frame_count); }