home *** CD-ROM | disk | FTP | other *** search
- /* ScummC
- * Copyright (C) 2006 Alban Bedel
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
- /**
- * @file scvm_op.c
- * @ingroup scvm
- * @brief SCVM op-code implementation
- */
-
- #include "config.h"
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <inttypes.h>
- #include <errno.h>
- #include <stdarg.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <math.h>
-
- #include "scc_fd.h"
- #include "scc_util.h"
- #include "scc_cost.h"
- #include "scc_box.h"
- #include "scvm_res.h"
- #include "scvm_thread.h"
- #include "scvm.h"
-
- // Basic stack ops
-
- int scvm_push(scvm_t* vm,int val) {
- if(vm->stack_ptr + 1 >= vm->stack_size) {
- scc_log(LOG_ERR,"Stack overflow!\n");
- return SCVM_ERR_STACK_OVERFLOW;
- }
- scc_log(LOG_MSG,"Push %d\n",val);
- vm->stack[vm->stack_ptr] = val;
- vm->stack_ptr++;
- return 0;
- }
-
- int scvm_pop(scvm_t* vm,int* val) {
- if(vm->stack_ptr < 1) {
- scc_log(LOG_ERR,"Stack underflow!\n");
- return SCVM_ERR_STACK_UNDERFLOW;
- }
- vm->stack_ptr--;
- scc_log(LOG_MSG,"Pop %d\n",vm->stack[vm->stack_ptr]);
- if(val) *val = vm->stack[vm->stack_ptr];
- return 0;
- }
-
- int scvm_vpop(scvm_t* vm, ...) {
- va_list ap;
- int* val,r;
- va_start(ap,vm);
- while((val = va_arg(ap,int*)))
- if((r = scvm_pop(vm,val))) return r;
- va_end(ap);
- return 0;
- }
-
- int scvm_peek(scvm_t* vm,int* val) {
- if(vm->stack_ptr < 1) {
- scc_log(LOG_ERR,"Stack underflow!\n");
- return SCVM_ERR_STACK_UNDERFLOW;
- }
- if(val) *val = vm->stack[vm->stack_ptr-1];
- return 0;
- }
-
- int scvm_thread_read_var(scvm_t* vm, scvm_thread_t* thread,
- uint16_t addr, int* val) {
- // decode the address
- if(addr & 0x8000) { // bit variable
- addr &= 0x7FFF;
- if(addr >= vm->num_bitvar) return SCVM_ERR_BAD_ADDR;
- *val = (vm->bitvar[addr>>3]>>(addr&7))&1;
- scc_log(LOG_MSG,"Read bit var %d: %d\n",addr,*val);
- } else if(addr & 0x4000) { // thread local variable
- addr &= 0x3FFF;
- if(!thread || addr >= thread->num_var) return SCVM_ERR_BAD_ADDR;
- *val = thread->var[addr];
- scc_log(LOG_MSG,"Read local var %d: %d\n",addr,*val);
- } else { // global variable
- addr &= 0x3FFF;
- if(addr >= vm->num_var) return SCVM_ERR_BAD_ADDR;
- if(addr < 0x100 && vm->get_var[addr])
- *val = vm->get_var[addr](vm,addr);
- else
- *val = vm->var_mem[addr];
- scc_log(LOG_MSG,"Read global var %d: %d\n",addr,*val);
- }
- return 0;
- }
-
- int scvm_thread_write_var(scvm_t* vm, scvm_thread_t* thread,
- uint16_t addr, int val) {
- // decode the address
- if(addr & 0x8000) { // bit variable
- addr &= 0x7FFF;
- if(addr >= vm->num_bitvar) return SCVM_ERR_BAD_ADDR;
- vm->bitvar[addr>>3] &= ~(1<<(addr&7));
- vm->bitvar[addr>>3] |= (val&1)<<(addr&7);
- scc_log(LOG_MSG,"Write bit var %d: %d\n",addr,val);
- } else if(addr & 0x4000) { // thread local variable
- addr &= 0x3FFF;
- if(!thread || addr >= thread->num_var) return SCVM_ERR_BAD_ADDR;
- thread->var[addr] = val;
- scc_log(LOG_MSG,"Write local var %d: %d\n",addr,val);
- } else { // global variable
- addr &= 0x3FFF;
- if(addr >= vm->num_var) return SCVM_ERR_BAD_ADDR;
- if(addr < 0x100 && vm->set_var[addr])
- vm->set_var[addr](vm,addr,val);
- else
- vm->var_mem[addr] = val;
- scc_log(LOG_MSG,"Write global var %d: %d\n",addr,val);
- }
- return 0;
- }
-
-
- int scvm_read_array(scvm_t* vm, unsigned addr, unsigned x, unsigned y, int* val) {
- unsigned idx;
- if(addr >= vm->num_array) return SCVM_ERR_BAD_ADDR;
- idx = x+y*vm->array[addr].line_size;
- if(idx >= vm->array[addr].size)
- return SCVM_ERR_ARRAY_BOUND;
- switch(vm->array[addr].type) {
- case SCVM_ARRAY_WORD:
- *val = vm->array[addr].data.word[idx];
- break;
- case SCVM_ARRAY_BYTE:
- //case SCVM_ARRAY_CHAR:
- *val = vm->array[addr].data.byte[idx];
- break;
- case SCVM_ARRAY_NIBBLE:
- *val = (vm->array[addr].data.byte[idx>>2]>>((idx&1)<<2))&0xF;
- break;
- case SCVM_ARRAY_BIT:
- *val = (vm->array[addr].data.byte[idx>>3]>>(idx&7))&1;
- break;
- default:
- return SCVM_ERR_ARRAY_TYPE;
- }
- scc_log(LOG_MSG,"Read array %d[%d][%d]: %d\n",addr,x,y,*val);
- return 0;
- }
-
- int scvm_write_array(scvm_t* vm, unsigned addr, unsigned x, unsigned y, int val) {
- unsigned idx;
- scc_log(LOG_MSG,"Write array %d[%d][%d]: %d\n",addr,x,y,val);
- if(addr >= vm->num_array) return SCVM_ERR_BAD_ADDR;
- idx = x+y*vm->array[addr].line_size;
- if(idx >= vm->array[addr].size)
- return SCVM_ERR_ARRAY_BOUND;
- switch(vm->array[addr].type) {
- case SCVM_ARRAY_WORD:
- vm->array[addr].data.word[idx] = val;
- break;
- case SCVM_ARRAY_BYTE:
- //case SCVM_ARRAY_CHAR:
- val = vm->array[addr].data.byte[idx] = val;
- break;
- case SCVM_ARRAY_NIBBLE:
- vm->array[addr].data.byte[idx>>2] &= 0xF<<((idx&1)<<2);
- vm->array[addr].data.byte[idx>>2] |= (val&0xF)<<((idx&1)<<2);
- break;
- case SCVM_ARRAY_BIT:
- vm->array[addr].data.byte[idx>>3] &= ~(1<<(idx&7));
- vm->array[addr].data.byte[idx>>3] |= (val&1)<<(idx&7);
- break;
- default:
- return SCVM_ERR_ARRAY_TYPE;
- }
- return 0;
- }
-
-
- int scvm_alloc_array(scvm_t* vm, unsigned type, unsigned x, unsigned y) {
- scvm_array_t* array;
- int addr;
-
- switch(type) {
- case SCVM_ARRAY_WORD:
- case SCVM_ARRAY_BYTE:
- break;
- case SCVM_ARRAY_NIBBLE:
- x = (x+1)&~1;
- break;
- case SCVM_ARRAY_BIT:
- x = (x+7)&~7;
- break;
- default:
- return SCVM_ERR_ARRAY_TYPE;
- }
-
- for(addr = 1 ; addr < vm->num_array ; addr++)
- if(vm->array[addr].size == 0) break;
- if(addr >= vm->num_array) return SCVM_ERR_OUT_OF_ARRAY;
- array = &vm->array[addr];
- array->type = type;
-
- if(y) {
- array->line_size = x;
- array->size = x*y;
- } else {
- array->line_size = 0;
- array->size = x;
- }
- switch(type) {
- case SCVM_ARRAY_WORD:
- array->data.word = calloc(2,array->size);
- break;
- case SCVM_ARRAY_BYTE:
- array->data.byte = calloc(1,array->size);
- break;
- case SCVM_ARRAY_NIBBLE:
- array->data.byte = calloc(1,array->size>>1);
- break;
- case SCVM_ARRAY_BIT:
- array->data.byte = calloc(1,array->size>>3);
- break;
- }
- return addr;
- }
-
- static int scvm_nuke_array(scvm_t* vm, unsigned addr) {
- if(!addr || addr >= vm->num_array) return SCVM_ERR_BAD_ADDR;
- if(vm->array[addr].data.byte) free(vm->array[addr].data.byte);
- vm->array[addr].size = vm->array[addr].line_size = 0;
- return 0;
- }
-
- // SCUMM ops
-
- // 0x00
- static int scvm_op_push_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- uint8_t byte;
- if((r=scvm_thread_r8(thread,&byte))) return r;
- return scvm_push(vm,byte);
- }
-
- // 0x01
- static int scvm_op_push_word(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- int16_t word;
- if((r=scvm_thread_r16(thread,&word))) return r;
- return scvm_push(vm,word);
- }
-
- // 0x02
- static int scvm_op_var_read_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- uint8_t addr;
- if((r=scvm_thread_r8(thread,&addr)) ||
- (r=scvm_thread_read_var(vm,thread,addr,&val))) return r;
- return scvm_push(vm,val);
- }
-
- // 0x03
- static int scvm_op_var_read_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- uint16_t addr;
- if((r=scvm_thread_r16(thread,&addr)) ||
- (r=scvm_thread_read_var(vm,thread,addr,&val))) return r;
- return scvm_push(vm,val);
- }
-
- // 0x06
- static int scvm_op_array_read_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x;
- uint8_t vaddr;
- if((r=scvm_thread_r8(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_pop(vm,&x)) ||
- (r=scvm_read_array(vm,addr,x,0,&val)))
- return r;
- return scvm_push(vm,val);
- }
-
- // 0x07
- static int scvm_op_array_read_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x;
- uint16_t vaddr;
- if((r=scvm_thread_r16(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_pop(vm,&x)) ||
- (r=scvm_read_array(vm,addr,x,0,&val)))
- return r;
- return scvm_push(vm,val);
- }
-
- // 0x0A
- static int scvm_op_array2_read_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x,y;
- uint8_t vaddr;
- if((r=scvm_thread_r8(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_vpop(vm,&x,&y,NULL)) ||
- (r=scvm_read_array(vm,addr,x,y,&val)))
- return r;
- return scvm_push(vm,val);
- }
-
- // 0x0B
- static int scvm_op_array2_read_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x,y;
- uint16_t vaddr;
- if((r=scvm_thread_r16(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_vpop(vm,&x,&y,NULL)) ||
- (r=scvm_read_array(vm,addr,x,y,&val)))
- return r;
- return scvm_push(vm,val);
- }
-
- // 0x0C
- static int scvm_op_dup(scvm_t* vm, scvm_thread_t* thread) {
- int r,a;
- if((r=scvm_peek(vm,&a))) return r;
- return scvm_push(vm,a);
- }
-
- // 0x0D
- static int scvm_op_not(scvm_t* vm, scvm_thread_t* thread) {
- int r,a;
- if((r=scvm_pop(vm,&a))) return r;
- return scvm_push(vm,!a);
- }
-
- #define SCVM_BIN_OP(name,op) \
- static int scvm_op_ ##name (scvm_t* vm, scvm_thread_t* thread) { \
- int r,a,b; \
- if((r=scvm_vpop(vm,&b,&a,NULL))) \
- return r; \
- return scvm_push(vm,(a op b)); \
- }
-
- // 0x0E ... 0x19
- SCVM_BIN_OP(eq,==)
- SCVM_BIN_OP(neq,!=)
- SCVM_BIN_OP(gt,>)
- SCVM_BIN_OP(lt,<)
- SCVM_BIN_OP(ge,>=)
- SCVM_BIN_OP(le,<=)
- SCVM_BIN_OP(add,+)
- SCVM_BIN_OP(sub,-)
- SCVM_BIN_OP(mul,*)
- SCVM_BIN_OP(div,/)
- SCVM_BIN_OP(land,&&)
- SCVM_BIN_OP(lor,||)
- // 0xD6 0xD7
- SCVM_BIN_OP(band,&)
- SCVM_BIN_OP(bor,|)
-
- // 0x1A
- static int scvm_op_pop(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,NULL);
- }
-
- // 0x42
- static int scvm_op_var_write_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- uint8_t addr;
- if((r=scvm_thread_r8(thread,&addr)) ||
- (r=scvm_pop(vm,&val))) return r;
- return scvm_thread_write_var(vm,thread,addr,val);
- }
-
- // 0x43
- static int scvm_op_var_write_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- uint16_t addr;
- if((r=scvm_thread_r16(thread,&addr)) ||
- (r=scvm_pop(vm,&val))) return r;
- return scvm_thread_write_var(vm,thread,addr,val);
- }
-
- // 0x46
- static int scvm_op_array_write_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x;
- uint8_t vaddr;
- if((r=scvm_thread_r8(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_vpop(vm,&val,&x,NULL)))
- return r;
- return scvm_write_array(vm,addr,x,0,val);
- }
-
- // 0x47
- static int scvm_op_array_write_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x;
- uint16_t vaddr;
- if((r=scvm_thread_r16(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_vpop(vm,&val,&x,NULL)))
- return r;
- return scvm_write_array(vm,addr,x,0,val);
- }
-
- // 0x4A
- static int scvm_op_array2_write_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x,y;
- uint8_t vaddr;
- if((r=scvm_thread_r8(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_vpop(vm,&val,&x,&y,NULL)))
- return r;
- return scvm_write_array(vm,addr,x,0,val);
- }
-
- // 0x4B
- static int scvm_op_array2_write_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x,y;
- uint16_t vaddr;
- if((r=scvm_thread_r16(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_vpop(vm,&val,&x,&y,NULL)))
- return r;
- return scvm_write_array(vm,addr,x,0,val);
- }
-
- // 0x4E
- static int scvm_op_var_inc_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- uint8_t addr;
- if((r=scvm_thread_r8(thread,&addr)) ||
- (r=scvm_thread_read_var(vm,thread,addr,&val))) return r;
- val++;
- return scvm_thread_write_var(vm,thread,addr,val);
- }
-
- // 0x4F
- static int scvm_op_var_inc_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- uint16_t addr;
- if((r=scvm_thread_r16(thread,&addr)) ||
- (r=scvm_thread_read_var(vm,thread,addr,&val))) return r;
- val++;
- return scvm_thread_write_var(vm,thread,addr,val);
- }
-
- // 0x52
- static int scvm_op_array_inc_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x;
- uint8_t vaddr;
- if((r=scvm_thread_r8(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_pop(vm,&x)) ||
- (r=scvm_read_array(vm,addr,x,0,&val)))
- return r;
- val++;
- return scvm_write_array(vm,addr,x,0,val);
- }
-
- // 0x53
- static int scvm_op_array_inc_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x;
- uint16_t vaddr;
- if((r=scvm_thread_r16(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_pop(vm,&x)) ||
- (r=scvm_read_array(vm,addr,x,0,&val)))
- return r;
- val++;
- return scvm_write_array(vm,addr,x,0,val);
- }
-
- // 0x56
- static int scvm_op_var_dec_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- uint8_t addr;
- if((r=scvm_thread_r8(thread,&addr)) ||
- (r=scvm_thread_read_var(vm,thread,addr,&val))) return r;
- val--;
- return scvm_thread_write_var(vm,thread,addr,val);
- }
-
- // 0x57
- static int scvm_op_var_dec_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- uint16_t addr;
- if((r=scvm_thread_r16(thread,&addr)) ||
- (r=scvm_thread_read_var(vm,thread,addr,&val))) return r;
- val--;
- return scvm_thread_write_var(vm,thread,addr,val);
- }
-
- // 0x5A
- static int scvm_op_array_dec_byte(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x;
- uint8_t vaddr;
- if((r=scvm_thread_r8(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_pop(vm,&x)) ||
- (r=scvm_read_array(vm,addr,x,0,&val)))
- return r;
- val--;
- return scvm_write_array(vm,addr,x,0,val);
- }
-
- // 0x5B
- static int scvm_op_array_dec_word(scvm_t* vm, scvm_thread_t* thread) {
- int r,val;
- unsigned addr,x;
- uint16_t vaddr;
- if((r=scvm_thread_r16(thread,&vaddr)) ||
- (r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_pop(vm,&x)) ||
- (r=scvm_read_array(vm,addr,x,0,&val)))
- return r;
- val--;
- return scvm_write_array(vm,addr,x,0,val);
- }
-
- // 0x5C
- static int scvm_op_jmp_not_zero(scvm_t* vm, scvm_thread_t* thread) {
- int r,ptr,val;
- int16_t off;
- if((r=scvm_thread_r16(thread,&off)) ||
- (r=scvm_pop(vm,&val))) return r;
- ptr = thread->code_ptr+off;
- if(ptr < 0 || ptr >= thread->script->size)
- return SCVM_ERR_JUMP_BOUND;
- if(val) thread->code_ptr = ptr;
- return 0;
- }
-
- // 0x5D
- static int scvm_op_jmp_zero(scvm_t* vm, scvm_thread_t* thread) {
- int r,ptr,val;
- int16_t off;
- if((r=scvm_thread_r16(thread,&off)) ||
- (r=scvm_pop(vm,&val))) return r;
- ptr = thread->code_ptr+off;
- if(ptr < 0 || ptr >= thread->script->size)
- return SCVM_ERR_JUMP_BOUND;
- if(!val) thread->code_ptr = ptr;
- return 0;
- }
-
- // 0x5E
- static int scvm_op_start_script(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned num_args,script,flags;
- if((r=scvm_pop(vm,&num_args))) return r;
- else {
- int args[num_args+1];
- args[0] = num_args;
- while(num_args > 0) {
- if((r=scvm_pop(vm,&args[num_args]))) return r;
- num_args--;
- }
- if((r=scvm_vpop(vm,&script,&flags,NULL)) ||
- (r=scvm_start_script(vm,flags,script,args)) < 0)
- return r;
- vm->next_thread = &vm->thread[r];
- return SCVM_START_SCRIPT;
- }
- }
-
- // 0x5F
- static int scvm_op_start_script0(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned num_args,script;
- if((r=scvm_pop(vm,&num_args))) return r;
- else {
- int args[num_args+1];
- args[0] = num_args;
- while(num_args > 0) {
- if((r=scvm_pop(vm,&args[num_args]))) return r;
- num_args--;
- }
- if((r=scvm_pop(vm,&script)) ||
- (r=scvm_start_script(vm,0,script,args)) < 0)
- return r;
- vm->next_thread = &vm->thread[r];
- return SCVM_START_SCRIPT;
- }
- }
-
- // 0xBF
- static int scvm_op_start_script_recursive(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned num_args,script;
- if((r=scvm_pop(vm,&num_args))) return r;
- else {
- int args[num_args+1];
- args[0] = num_args;
- while(num_args > 0) {
- if((r=scvm_pop(vm,&args[num_args]))) return r;
- num_args--;
- }
- if((r=scvm_pop(vm,&script)) ||
- (r=scvm_start_script(vm,SCVM_THREAD_RECURSIVE,script,args)) < 0)
- return r;
- vm->next_thread = &vm->thread[r];
- return SCVM_START_SCRIPT;
- }
- }
-
- // 0x61
- static int scvm_op_draw_object(scvm_t* vm, scvm_thread_t* thread) {
- int r,obj_id,state;
- if((r = scvm_vpop(vm,&state,&obj_id,NULL)))
- return r;
- if(!vm->room) return SCVM_ERR_NO_ROOM;
- // the lower address are actors
- if(obj_id < 0x10 || obj_id >= vm->num_object)
- return SCVM_ERR_BAD_OBJECT;
- vm->object_pdata[obj_id].state = state > 0 ? state : 1;
- return 0;
- }
-
- // 0x65, 0x66
- static int scvm_op_stop_thread(scvm_t* vm, scvm_thread_t* thread) {
- scvm_stop_thread(vm,thread);
- return 0;
- }
-
- // 0x6C
- static int scvm_op_break_script(scvm_t* vm, scvm_thread_t* thread) {
- thread->cycle = vm->cycle+1;
- return 0;
- }
-
- // 0x73
- static int scvm_op_jmp(scvm_t* vm, scvm_thread_t* thread) {
- int r,ptr;
- int16_t off;
- if((r=scvm_thread_r16(thread,&off))) return r;
- ptr = thread->code_ptr+off;
- if(ptr < 0 || ptr >= thread->script->size)
- return SCVM_ERR_JUMP_BOUND;
- thread->code_ptr = ptr;
- return 0;
- }
-
- // 0x78
- static int scvm_op_pan_camera_to(scvm_t* vm, scvm_thread_t* thread) {
- int r,x;
- if((r=scvm_pop(vm,&x))) return r;
- scvm_pan_camera_to(vm,x);
- return 0;
- }
-
- // 0x79
- static int scvm_op_camera_follow_actor(scvm_t* vm, scvm_thread_t* thread) {
- unsigned a;
- int r;
- if((r=scvm_pop(vm,&a))) return r;
- if(a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- vm->view->follow = a;
- return SCVM_CAMERA_FOLLOW_ACTOR;
- }
-
- // 0x7A
- static int scvm_op_set_camera_at(scvm_t* vm, scvm_thread_t* thread) {
- int r,x;
- if((r=scvm_pop(vm,&x)) ||
- (r=scvm_set_camera_at(vm,x)) < 0) return r;
-
- // Stop following actors and panning
- vm->view->follow = 0;
- vm->view->flags &= ~ SCVM_VIEW_PAN;
-
- if(r > 0) {
- vm->next_thread = &vm->thread[r-1];
- return SCVM_START_SCRIPT;
- }
- return 0;
- }
-
- // 0x7B
- static int scvm_op_start_room(scvm_t* vm, scvm_thread_t* thread) {
- int r;
-
- if((r=scvm_pop(vm,&vm->next_room))) return r;
- return SCVM_OPEN_ROOM;
- }
-
- // 0x7C
- static int scvm_op_stop_script(scvm_t* vm, scvm_thread_t* thread) {
- int r,id;
- if((r=scvm_pop(vm,&id))) return r;
- scvm_stop_script(vm,id);
- return 0;
- }
-
- // 0x7E
- static int scvm_op_walk_actor_to(scvm_t* vm, scvm_thread_t* thread) {
- int r,a,x,y;
-
- if((r=scvm_vpop(vm,&y,&x,&a,NULL)))
- return r;
-
- if(a < 0 || a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- scvm_actor_walk_to(&vm->actor[a],x,y);
- return 0;
- }
-
-
- // 0x7F
- static int scvm_op_put_actor_at(scvm_t* vm, scvm_thread_t* thread) {
- int r,a,x,y,room;
-
- if((r=scvm_vpop(vm,&room,&y,&x,&a,NULL)))
- return r;
- return scvm_put_actor_at(vm,a,x,y,room);
- }
-
- // 0x82
- static int scvm_op_actor_animate(scvm_t* vm, scvm_thread_t* thread) {
- int r,a,f;
- if((r = scvm_vpop(vm,&f,&a,NULL)))
- return r;
- if(a < 0 || a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- scvm_actor_animate(&vm->actor[a],f);
- return 0;
- }
-
- // 0x87
- static int scvm_op_get_random_number(scvm_t* vm, scvm_thread_t* thread) {
- int r,max;
- if((r=scvm_pop(vm,&max))) return r;
- vm->var->random_num = scvm_random(vm,0,max);
- return scvm_push(vm,vm->var->random_num);
- }
-
- // 0x88
- static int scvm_op_get_random_number_range(scvm_t* vm, scvm_thread_t* thread) {
- int r,min,max;
- if((r=scvm_vpop(vm,&max,&min,NULL)))
- return r;
- vm->var->random_num = scvm_random(vm,min,max);
- return scvm_push(vm,vm->var->random_num);
- }
-
- // 0x8B
- static int scvm_op_is_script_running(scvm_t* vm, scvm_thread_t* thread) {
- int r,id;
- if((r=scvm_pop(vm,&id))) return r;
- r = scvm_is_script_running(vm,id);
- return scvm_push(vm,r);
- }
-
- // 0x8C
- static int scvm_op_get_actor_room(scvm_t* vm, scvm_thread_t* thread) {
- int r,a;
- if((r=scvm_pop(vm,&a))) return r;
- if(a < 0 || a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- return scvm_push(vm,vm->actor[a].room);
- }
-
- // 0x8D
- static int scvm_op_get_object_x(scvm_t* vm, scvm_thread_t* thread) {
- int r,o,x;
- if((r=scvm_pop(vm,&o)) ||
- (r=scvm_get_object_position(vm,o,&x,NULL)) < 0) return r;
- return scvm_push(vm,x);
- }
-
- // 0x8E
- static int scvm_op_get_object_y(scvm_t* vm, scvm_thread_t* thread) {
- int r,o,y;
- if((r=scvm_pop(vm,&o)) ||
- (r=scvm_get_object_position(vm,o,NULL,&y)) < 0) return r;
- return scvm_push(vm,y);
- }
-
- // 0x8F
- static int scvm_op_get_object_direction(scvm_t* vm, scvm_thread_t* thread) {
- int r,a;
- if((r=scvm_pop(vm,&a))) return r;
- if(a < 0 || a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- return scvm_push(vm,vm->actor[a].direction);
- }
-
- // 0x90
- static int scvm_op_get_actor_walk_box(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned a;
- if((r=scvm_pop(vm,&a))) return r;
- if(a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- return scvm_push(vm,vm->actor[a].box);
- }
-
- // 0x95
- static int scvm_op_begin_override(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- // there should be a jump there
- if(thread->code_ptr + 3 >= thread->script->size)
- return SCVM_ERR_SCRIPT_BOUND;
- if((r=scvm_thread_begin_override(vm,thread)))
- return r;
- // skip the jump
- thread->code_ptr += 3;
- return 0;
- }
-
- // 0x96
- static int scvm_op_end_override(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_thread_end_override(vm,thread);
- }
-
- // 0x9B
- static int scvm_op_resource(scvm_t* vm, scvm_thread_t* thread) {
- int r,res;
- uint8_t op;
-
- if((r=scvm_thread_r8(thread,&op)) ||
- (r=scvm_pop(vm,&res))) return r;
-
- if(op == 0x65) return 0; // ignore sounds for now
-
- if(op >= 0x64 && op <= 0x67) {
- if(!scvm_load_res(vm,op-0x64,res))
- return SCVM_ERR_BAD_RESOURCE;
- return 0;
- } else if(op >= 0x6C && op <= 0x6F) {
- if(!scvm_lock_res(vm,op-0x6C,res))
- return SCVM_ERR_BAD_RESOURCE;
- return 0;
- } else if(op >= 0x70 && op <= 0x73) {
- if(!scvm_unlock_res(vm,op-0x70,res))
- return SCVM_ERR_BAD_RESOURCE;
- return 0;
- }
-
- switch(op) {
- case 0x75: // load charset
- if(!scvm_load_res(vm,SCVM_RES_CHARSET,res))
- return SCVM_ERR_BAD_RESOURCE;
- return 0;
- case 0x77: // load fl object
- return scvm_pop(vm,NULL);
- }
- return SCVM_ERR_NO_OP;
- }
-
- // 0x9CAC
- static int scvm_op_set_scrolling(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- if((r=scvm_vpop(vm,&vm->view->scroll_right,
- &vm->view->scroll_left,NULL)))
- return r;
- return 0;
- }
-
- // 0x9CAE
- static int scvm_op_set_screen(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- if((r=scvm_vpop(vm,&vm->view->room_end,
- &vm->view->room_start,NULL)))
- return r;
- return 0;
- }
-
- // 0x9CAF
- static int scvm_op_set_room_color(scvm_t* vm, scvm_thread_t* thread) {
- int r,red,green,blue,color;
- if((r=scvm_vpop(vm,&color,&blue,&green,&red,NULL)))
- return r;
- if(color < 0 || color > 0xFF) return 0;
- vm->view->palette[color].r = red;
- vm->view->palette[color].g = green;
- vm->view->palette[color].b = blue;
- vm->view->flags |= SCVM_VIEW_PALETTE_CHANGED;
- return 0;
- }
-
- // 0x9CB0
- static int scvm_op_shake_on(scvm_t* vm, scvm_thread_t* thread) {
- vm->view->flags |= SCVM_VIEW_SHAKE;
- return 0;
- }
-
- // 0x9CB1
- static int scvm_op_shake_off(scvm_t* vm, scvm_thread_t* thread) {
- vm->view->flags &= ~SCVM_VIEW_SHAKE;
- return 0;
- }
-
- // 0x9CB3
- static int scvm_op_set_room_intensity(scvm_t* vm, scvm_thread_t* thread) {
- int r,scale,start,end;
- if((r=scvm_vpop(vm,&end,&start,&scale,NULL)))
- return r;
- if(!vm->room) return SCVM_ERR_NO_ROOM;
- scvm_view_scale_palette(vm->view,vm->room->current_palette,
- scale,scale,scale,start,end);
- return 0;
- }
-
- // 0x9CB5
- static int scvm_op_set_transition_effect(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->view->effect);
- }
-
- // 0x9CB6
- static int scvm_op_set_rgb_intensity(scvm_t* vm, scvm_thread_t* thread) {
- int r,red,green,blue,start,end;
- if((r=scvm_vpop(vm,&end,&start,&blue,&green,&red,NULL)))
- return r;
- if(!vm->room) return SCVM_ERR_NO_ROOM;
- scvm_view_scale_palette(vm->view,vm->room->current_palette,
- red,green,blue,start,end);
- return 0;
- }
-
- // 0x9CD5
- static int scvm_op_set_palette(scvm_t* vm, scvm_thread_t* thread) {
- int r,p;
- if((r=scvm_pop(vm,&p))) return r;
- if(!vm->room) return SCVM_ERR_NO_ROOM;
- if(p < 0 || p >= vm->room->num_palette)
- return SCVM_ERR_BAD_PALETTE;
- vm->room->current_palette = vm->room->palette[p];
- memcpy(vm->view->palette,vm->room->current_palette,
- sizeof(scvm_palette_t));
- vm->view->flags |= SCVM_VIEW_PALETTE_CHANGED;
- return 0;
- }
-
-
- // 0x9DC5
- static int scvm_op_set_current_actor(scvm_t* vm, scvm_thread_t* thread) {
- int r,a;
- if((r=scvm_pop(vm,&a))) return r;
- if(r >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- vm->current_actor = &vm->actor[a];
- return 0;
- }
-
- // 0x9D4C
- static int scvm_op_set_actor_costume(scvm_t* vm, scvm_thread_t* thread) {
- int r,a;
- scc_cost_t* cost = NULL;
- if((r=scvm_pop(vm,&a))) return r;
- if(a && !(cost = scvm_load_res(vm,SCVM_RES_COSTUME,a)))
- return SCVM_ERR_BAD_COSTUME;
- if(vm->current_actor)
- scvm_actor_set_costume(vm->current_actor,cost);
- return 0;
- }
-
- // 0x9D4D
- static int scvm_op_set_actor_walk_speed(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_vpop(vm,&vm->current_actor->walk_speed_y,
- &vm->current_actor->walk_speed_x,NULL);
- }
-
- // 0x9D4F
- static int scvm_op_set_actor_walk_frame(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->walk_frame);
- }
-
- // 0x9D50
- static int scvm_op_set_actor_talk_frame(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_vpop(vm,&vm->current_actor->talk_end_frame,
- &vm->current_actor->talk_start_frame,NULL);
- }
-
- // 0x9D51
- static int scvm_op_set_actor_stand_frame(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->stand_frame);
- }
-
- // 0x9D53
- static int scvm_op_actor_init(scvm_t* vm, scvm_thread_t* thread) {
- if(vm->current_actor)
- scvm_actor_init(vm->current_actor);
- return 0;
- }
-
- // 0x9D54
- static int scvm_op_set_actor_elevation(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->elevation);
- }
-
- // 0x9D54
- static int scvm_op_set_actor_default_frames(scvm_t* vm,
- scvm_thread_t* thread) {
- if(vm->current_actor)
- scvm_actor_set_default_frames(vm->current_actor);
- return 0;
- }
-
-
- // 0x9D57
- static int scvm_op_set_actor_talk_color(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->talk_color);
- }
-
- // 0x9D58
- static int scvm_op_set_actor_name(scvm_t* vm, scvm_thread_t* thread) {
- int r,len;
- if((r = scvm_thread_strlen(thread,&len))) return r;
- if(vm->current_actor->name)
- free(vm->current_actor->name);
- vm->current_actor->name = malloc(len+1);
- if(len > 0)
- memcpy(vm->current_actor->name,
- &thread->script->code[thread->code_ptr],len);
- thread->code_ptr += len+1;
- vm->current_actor->name[len] = 0;
- return 0;
- }
-
- // 0x9D59
- static int scvm_op_set_actor_init_frame(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->init_frame);
- }
-
- // 0x9D5B
- static int scvm_op_set_actor_width(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->width);
- }
-
- // 0x9D5C
- static int scvm_op_set_actor_scale(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- if((r=scvm_pop(vm,&vm->current_actor->scale_x))) return r;
- vm->current_actor->scale_y = vm->current_actor->scale_x;
- return 0;
- }
-
- // 0x9D5F
- static int scvm_op_set_actor_ignore_boxes(scvm_t* vm, scvm_thread_t* thread) {
- if(!vm->current_actor) return 0;
- vm->current_actor->flags |= SCVM_ACTOR_IGNORE_BOXES;
- vm->current_actor->box = 0;
- return 0;
- }
-
- // 0x9D60
- static int scvm_op_set_actor_follow_boxes(scvm_t* vm, scvm_thread_t* thread) {
- if(!vm->current_actor) return 0;
- vm->current_actor->flags &= ~SCVM_ACTOR_IGNORE_BOXES;
- if(vm->current_actor->room == vm->room->id)
- scvm_put_actor_at(vm,vm->current_actor->id,
- vm->current_actor->x,
- vm->current_actor->y,
- vm->current_actor->room);
- return 0;
- }
-
- // 0x9D61
- static int scvm_op_set_actor_anim_speed(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->anim_speed);
- }
-
- // 0x9D63
- static int scvm_op_set_actor_talk_pos(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_vpop(vm,&vm->current_actor->talk_y,
- &vm->current_actor->talk_x,NULL);
- }
-
-
- // 0x9DE3
- static int scvm_op_set_actor_layer(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->layer);
- }
-
- // 0x9DE4
- static int scvm_op_set_actor_walk_script(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->walk_script);
- }
-
- // 0x9DE6
- static int scvm_op_set_actor_direction(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->direction);
- }
-
- // 0x9DEB
- static int scvm_op_set_actor_talk_script(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,&vm->current_actor->talk_script);
- }
-
-
- // 0xA4CD
- static int scvm_op_array_write_string(scvm_t* vm, scvm_thread_t* thread) {
- int r,addr;
- uint16_t vaddr;
- unsigned len,x;
-
- if((r=scvm_pop(vm,&x)) ||
- (r=scvm_thread_r16(thread,&vaddr)) ||
- (r = scvm_thread_strlen(thread,&len))) return r;
- if((addr = scvm_alloc_array(vm,SCVM_ARRAY_BYTE,
- x+len+1,0)) < 0)
- return addr;
- if(len > 0)
- memcpy(vm->array[addr].data.byte+x,
- thread->script->code+thread->code_ptr,len);
- thread->code_ptr += len+1;
- vm->array[addr].data.byte[len] = 0;
- return scvm_thread_write_var(vm,thread,vaddr,addr);
- }
-
- // 0xA4D0
- static int scvm_op_array_write_list(scvm_t* vm, scvm_thread_t* thread) {
- int r,val,addr;
- uint16_t vaddr;
- unsigned len,x;
-
- if((r=scvm_pop(vm,&x)) ||
- (r=scvm_thread_r16(thread,&vaddr)) ||
- (r = scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r = scvm_pop(vm,&len))) return r;
- if(addr <= 0) {
- if((addr = scvm_alloc_array(vm,SCVM_ARRAY_WORD, x+len,0)) <= 0)
- return addr;
- scvm_thread_write_var(vm,thread,vaddr,addr);
- }
- while(len > 0) {
- if((r = scvm_pop(vm,&val)) ||
- (r=scvm_write_array(vm,addr,x,0,val))) return r;
- len--, x++;
- }
- return 0;
- }
-
- // 0xA4D4
- static int scvm_op_array_write_list2(scvm_t* vm, scvm_thread_t* thread) {
- int r,addr;
- uint16_t vaddr;
- unsigned len,x,y;
-
- if((r=scvm_pop(vm,&x)) ||
- (r=scvm_thread_r16(thread,&vaddr)) ||
- (r = scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r = scvm_pop(vm,&len))) return r;
- if(!addr || addr >= vm->num_array) return SCVM_ERR_BAD_ADDR;
- else {
- int i,list[len];
- for(i = 0 ; i < len ; i++)
- if((r = scvm_pop(vm,list+i))) return r;
- if((r = scvm_pop(vm,&y))) return r;
- for(i = 0 ; i < len ; i++)
- if((r = scvm_write_array(vm,addr,x+i,y,list[i]))) return r;
- }
- return 0;
- }
-
- // 0xA9A8
- static int scvm_op_wait_for_actor(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned a;
- int16_t off;
- if((r=scvm_pop(vm,&a)) ||
- (r=scvm_thread_r16(thread,&off))) return r;
- if(a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- if(vm->actor[a].walking) {
- thread->code_ptr += off;
- return scvm_op_break_script(vm,thread);
- }
- return 0;
- }
-
- // 0xA9A8 A9E2 A9E8
- static int scvm_op_wait_for(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned x;
- uint16_t off;
- if((r=scvm_pop(vm,&x)) ||
- (r=scvm_thread_r16(thread,&off))) return r;
- return scvm_op_break_script(vm,thread);
- }
-
- // 0xA9A9 A9AA A9AB
- static int scvm_op_wait(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_op_break_script(vm,thread);
- }
-
- // 0xAA
- static int scvm_op_get_actor_x_scale(scvm_t* vm, scvm_thread_t* thread) {
- int r,a;
- if((r=scvm_pop(vm,&a))) return a;
- if(a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- return scvm_push(vm,vm->actor[a].scale_x);
- }
-
- // 0xAB
- static int scvm_op_get_actor_anim_counter(scvm_t* vm, scvm_thread_t* thread) {
- int r,a;
- if((r=scvm_pop(vm,&a))) return r;
- if(a < 0 || a >= vm->num_actor) return SCVM_ERR_BAD_ACTOR;
- return scvm_push(vm,vm->actor[a].costdec.anim_counter);
- }
-
-
- // 0xAC
- static int scvm_op_sound_kludge(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned num;
- // drop the list for now
- r=scvm_pop(vm,&num);
- while(!r && num > 0) {
- r=scvm_pop(vm,NULL);
- num--;
- }
- return r;
- }
-
- // 0xAD
- static int scvm_op_is_any_of(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned len;
- if((r=scvm_pop(vm,&len))) return r;
- else {
- int i,val,list[len];
- for(i = len-1 ; i >= 0 ; i--)
- if((r=scvm_pop(vm,list+i))) return r;
- if((r=scvm_pop(vm,&val))) return r;
- for(i = 0 ; i < len ; i++)
- if(val == list[i])
- return scvm_push(vm,1);
- }
- return scvm_push(vm,0);
- }
-
- // 0xB0
- static int scvm_op_delay(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned d;
- if((r=scvm_pop(vm,&d))) return r;
- thread->delay = d*16;
- thread->state = SCVM_THREAD_DELAYED;
- return 0;
- }
-
- // 0xB1
- static int scvm_op_delay_seconds(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned d;
- if((r=scvm_pop(vm,&d))) return r;
- thread->delay = d*1000;
- thread->state = SCVM_THREAD_DELAYED;
- return 0;
- }
-
- // 0xB2
- static int scvm_op_delay_minutes(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned d;
- if((r=scvm_pop(vm,&d))) return r;
- thread->delay = d*60000;
- thread->state = SCVM_THREAD_DELAYED;
- return 0;
- }
-
- // 0xBA
- static int scvm_op_actor_say(scvm_t* vm, scvm_thread_t* thread) {
- int r,len;
- int actor;
- if((r = scvm_pop(vm,&actor))) return r;
-
- if((r = scvm_thread_strlen(thread,&len))) return r;
- thread->code_ptr += len+1;
-
- return 0;
- }
-
- // 0xBB
- static int scvm_op_ego_say(scvm_t* vm, scvm_thread_t* thread) {
- scvm_push(vm, vm->var->ego);
- return scvm_op_actor_say(vm, thread);
- }
-
- // 0xBC
- static int scvm_op_dim(scvm_t* vm, scvm_thread_t* thread) {
- int r,addr;
- unsigned size;
- uint8_t op;
- uint16_t vaddr;
-
- if((r=scvm_thread_r8(thread,&op)) ||
- (r=scvm_thread_r16(thread,&vaddr))) return r;
-
- if(op == 0xCC) { // UNDIM
- if((r=scvm_thread_read_var(vm,thread,vaddr,&addr)) ||
- (r=scvm_nuke_array(vm,addr)))
- return r;
- return scvm_thread_write_var(vm,thread,vaddr,0);
- }
-
- if(op < 0xC7 || op > 0xCB) return SCVM_ERR_NO_OP;
- if((r=scvm_pop(vm,&size))) return r;
-
- switch(op) {
- case 0xC7:
- addr = scvm_alloc_array(vm,SCVM_ARRAY_WORD,size,0);
- break;
- case 0xC8:
- addr = scvm_alloc_array(vm,SCVM_ARRAY_BIT,size,0);
- break;
- case 0xC9:
- addr = scvm_alloc_array(vm,SCVM_ARRAY_NIBBLE,size,0);
- break;
- case 0xCA: // byte
- case 0xCB: // char
- addr = scvm_alloc_array(vm,SCVM_ARRAY_BYTE,size,0);
- break;
- }
- if(addr < 0) return addr;
- return scvm_thread_write_var(vm,thread,vaddr,addr);
- }
-
- // 0xC5
- static int scvm_op_get_distance_obj_obj(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned objA, objB;
- int ax,ay, bx,by;
-
- if((r = scvm_vpop(vm,&objB,&objA,NULL)) ||
- (r = scvm_get_object_position(vm,objA,&ax,&ay)) < 0 ||
- (r = scvm_get_object_position(vm,objB,&bx,&by)) < 0) return r;
- return scvm_push(vm,hypot(bx-ax,by-ay));
- }
-
- // 0xCA
- static int scvm_op_break_script_n_times(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- unsigned n;
- if((r=scvm_pop(vm,&n))) return r;
- thread->cycle = vm->cycle+n;
- return 0;
- }
-
- static int scvm_op_dummy(scvm_t* vm, scvm_thread_t* thread) {
- return 0;
- }
-
- static int scvm_op_dummy_v(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_pop(vm,NULL);
- }
-
- static int scvm_op_dummy_vv(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- if((r=scvm_pop(vm,NULL))) return r;
- return scvm_pop(vm,NULL);
- }
-
- static int scvm_op_dummy_vvv(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- if((r=scvm_pop(vm,NULL)) ||
- (r=scvm_pop(vm,NULL))) return r;
- return scvm_pop(vm,NULL);
- }
-
- static int scvm_op_dummy_vvvv(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- if((r=scvm_pop(vm,NULL)) ||
- (r=scvm_pop(vm,NULL)) ||
- (r=scvm_pop(vm,NULL))) return r;
- return scvm_pop(vm,NULL);
- }
-
- static int scvm_op_dummy_vvvvv(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- if((r=scvm_pop(vm,NULL)) ||
- (r=scvm_pop(vm,NULL)) ||
- (r=scvm_pop(vm,NULL)) ||
- (r=scvm_pop(vm,NULL))) return r;
- return scvm_pop(vm,NULL);
- }
-
- static int scvm_op_dummy_l(scvm_t* vm, scvm_thread_t* thread) {
- int r,len;
- if((r=scvm_pop(vm,&len))) return r;
- while(len > 0) {
- if((r=scvm_pop(vm,NULL))) return r;
- len--;
- }
- return 0;
- }
-
- static int scvm_op_dummy_s(scvm_t* vm, scvm_thread_t* thread) {
- int r,len;
- if((r = scvm_thread_strlen(thread,&len))) return r;
- thread->code_ptr += len+1;
- return 0;
- }
-
- static int scvm_op_dummy_print(scvm_t* vm, scvm_thread_t* thread) {
- int r;
- uint8_t op;
- if((r = scvm_thread_r8(thread,&op))) return r;
- switch(op) {
- case 0x41: // at
- return scvm_op_dummy_vv(vm,thread);
- case 0x42: // color
- case 0x43: // clipped
- return scvm_op_dummy_v(vm,thread);
- case 0x45: // center
- case 0x47: // left
- case 0x48: // overhead
- case 0x4A: // mumble
- case 0xFE: // begin
- case 0xFF: // end
- return 0;
- case 0x4B:
- return scvm_op_dummy_s(vm,thread);
- }
- return SCVM_ERR_NO_OP;
- }
-
- static int scvm_op_dummy_get_at(scvm_t* vm, scvm_thread_t* thread) {
- int r,x,y;
- if((r = scvm_vpop(vm,&y,&x,NULL))) return r;
- return scvm_push(vm,0);
- }
-
-
- static int scvm_op_subop(scvm_t* vm, scvm_thread_t* thread) {
- return scvm_thread_do_op(vm,thread,vm->suboptable);
- }
-
- scvm_op_t scvm_optable[0x100] = {
- // 00
- { scvm_op_push_byte, "push" },
- { scvm_op_push_word, "push" },
- { scvm_op_var_read_byte, "read var" },
- { scvm_op_var_read_word, "read var" },
- // 04
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_array_read_byte, "read array" },
- { scvm_op_array_read_word, "read array" },
- // 08
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_array2_read_byte, "read array2" },
- { scvm_op_array2_read_word, "read array2" },
- // 0C
- { scvm_op_dup, "dup" },
- { scvm_op_not, "not" },
- { scvm_op_eq, "eq" },
- { scvm_op_neq, "neq" },
- // 10
- { scvm_op_gt, "gt" },
- { scvm_op_lt, "lt" },
- { scvm_op_le, "le" },
- { scvm_op_ge, "ge" },
- // 14
- { scvm_op_add, "add" },
- { scvm_op_sub, "sub" },
- { scvm_op_mul, "mul" },
- { scvm_op_div, "div" },
- // 18
- { scvm_op_land, "land" },
- { scvm_op_lor, "lor" },
- { scvm_op_pop, "pop" },
- { NULL, NULL },
- // 1C
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 20
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 24
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 28
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 2C
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 30
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 34
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 38
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 3C
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 40
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_var_write_byte, "write var" },
- { scvm_op_var_write_word, "write var" },
- // 44
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_array_write_byte, "write array" },
- { scvm_op_array_write_word, "write array" },
- // 48
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_array2_write_byte, "write array2" },
- { scvm_op_array2_write_word, "write array2" },
- // 4C
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_var_inc_byte, "inc var" },
- { scvm_op_var_inc_word, "inc var" },
- // 50
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_array_inc_byte, "inc array" },
- { scvm_op_array_inc_word, "inc array" },
- // 54
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_var_dec_byte, "dec var" },
- { scvm_op_var_dec_word, "dec var" },
- // 58
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_array_dec_byte, "dec array" },
- { scvm_op_array_dec_word, "dec array" },
- // 5C
- { scvm_op_jmp_not_zero, "jump if not zero" },
- { scvm_op_jmp_zero, "jump if zero" },
- { scvm_op_start_script, "start script" },
- { scvm_op_start_script0, "start script0" },
- // 60
- { NULL, NULL },
- { scvm_op_draw_object, "draw object" },
- { NULL, NULL },
- { NULL, NULL },
- // 64
- { NULL, NULL },
- { scvm_op_stop_thread, "stop thread" },
- { scvm_op_stop_thread, "stop thread" },
- { NULL, NULL },
- // 68
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_subop, "interface op" },
- // 6C
- { scvm_op_break_script, "break script" },
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_dummy_v, "set object state" },
- // 70
- { scvm_op_dummy_vv, "set object state" },
- { scvm_op_dummy_vv, "set object owner" },
- { scvm_op_dummy_v, "get object owner" },
- { scvm_op_jmp, "jump" },
- // 74
- { scvm_op_dummy_v, "start sound" },
- { scvm_op_dummy_v, "stop sound" },
- { scvm_op_dummy_v, "start music" },
- { NULL, NULL },
- // 78
- { scvm_op_pan_camera_to, "pan camera to" },
- { scvm_op_camera_follow_actor, "camera follow actor" },
- { scvm_op_set_camera_at, "set camera at" },
- { scvm_op_start_room, "start room" },
- // 7C
- { scvm_op_stop_script, "stop script" },
- { scvm_op_dummy_vvv, "walk actor to object" },
- { scvm_op_walk_actor_to, "walk actor to" },
- { scvm_op_put_actor_at, "put actor at" },
- // 80
- { scvm_op_dummy_vvv, "put actor at object" },
- { scvm_op_dummy_vv, "actor face" },
- { scvm_op_actor_animate, "actor animate" },
- { scvm_op_dummy_vvvv, "do sentence" },
- // 84
- { scvm_op_dummy_vv, "pickup object" },
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_get_random_number, "get random number" },
- // 88
- { scvm_op_get_random_number_range, "get random number range" },
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_is_script_running, "is script running" },
- // 8C
- { scvm_op_get_actor_room, "get actor room" },
- { scvm_op_get_object_x, "get object x" },
- { scvm_op_get_object_y, "get object y" },
- { scvm_op_get_object_direction, "get object direction" },
- // 90
- { scvm_op_get_actor_walk_box, "get actor walk box" },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 94
- { scvm_op_dummy_get_at, "get verb at" },
- { scvm_op_begin_override, "begin override" },
- { scvm_op_end_override, "end override" },
- { NULL, NULL },
- // 98
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_resource, "resource op" },
- // 9C
- { scvm_op_subop, "view op" },
- { scvm_op_subop, "actor op" },
- { scvm_op_subop, "verb op" },
- { scvm_op_dummy_get_at, "get actor at" },
- // A0
- { scvm_op_dummy_get_at, "get object at" },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // A4
- { scvm_op_subop, "array write" },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // A8
- { NULL, NULL },
- { scvm_op_subop, "wait" },
- { scvm_op_get_actor_x_scale, "get actor x scale" },
- { scvm_op_get_actor_anim_counter, "get actor anim counter" },
- // AC
- { scvm_op_sound_kludge, "sound kludge" },
- { scvm_op_is_any_of, "is any of" },
- { NULL, NULL },
- { NULL, NULL },
- // B0
- { scvm_op_delay, "delay" },
- { scvm_op_delay_seconds, "delay seconds" },
- { scvm_op_delay_minutes, "delay minutes" },
- { scvm_op_dummy, "stop sentence" },
- // B4
- { scvm_op_dummy_print, "print" },
- { scvm_op_dummy_print, "cursor print" },
- { scvm_op_dummy_print, "debug print" },
- { scvm_op_dummy_print, "sys print" },
- // B8
- { scvm_op_dummy_print, "actor print" },
- { scvm_op_dummy_print, "ego print" },
- { scvm_op_actor_say, "actor say" },
- { scvm_op_ego_say, "ego say" },
- // BC
- { scvm_op_dim, "dim" },
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_start_script_recursive, "start script recursive" },
- // C0
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // C4
- { NULL, NULL },
- { scvm_op_get_distance_obj_obj, "get dist obj obj" },
- { NULL, NULL },
- { NULL, NULL },
- // C8
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_break_script_n_times, "break script n times" },
- { NULL, NULL },
- // CC
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // D0
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // D4
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_band, "bit and" },
- { scvm_op_bor, "bit or" },
- // D8
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // DC
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // E0
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // E4
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // E8
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // EC
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // F0
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // F4
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // F8
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // FC
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL }
- };
-
- scvm_op_t scvm_suboptable[0x100] = {
- // 00
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 04
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 08
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 0C
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 10
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 14
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 18
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 1C
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 20
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 24
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 28
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 2C
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 30
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 34
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 38
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 3C
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 40
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 44
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 48
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 4C
- { scvm_op_set_actor_costume, "set costume" },
- { scvm_op_set_actor_walk_speed, "set walk speed" },
- { scvm_op_dummy_l, "set sounds" },
- { scvm_op_set_actor_walk_frame, "set walk frame" },
- // 50
- { scvm_op_set_actor_talk_frame, "set talk frame" },
- { scvm_op_set_actor_stand_frame, "set stand frame" },
- { NULL, NULL },
- { scvm_op_actor_init, "init" },
- // 54
- { scvm_op_set_actor_elevation, "set elevation" },
- { scvm_op_set_actor_default_frames, "default frames" },
- { NULL, NULL },
- { scvm_op_set_actor_talk_color, "set talk color" },
- // 58
- { scvm_op_set_actor_name, "set name" },
- { scvm_op_set_actor_init_frame, "set init frame" },
- { NULL, NULL },
- { scvm_op_set_actor_width, "set width" },
- // 5C
- { scvm_op_set_actor_scale, "set scale" },
- { scvm_op_dummy, "never z clip" },
- { NULL, NULL },
- { scvm_op_set_actor_ignore_boxes, "ignore boxes" },
- // 60
- { scvm_op_set_actor_follow_boxes, "follow boxes" },
- { scvm_op_set_actor_anim_speed, "set anim speed" },
- { scvm_op_dummy_v, "set shadow mode" },
- { scvm_op_set_actor_talk_pos, "set talk pos" },
- // 64
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 68
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 6C
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 70
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 74
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 78
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 7C
- { scvm_op_dummy_v, "set image" },
- { scvm_op_dummy_s, "set name" },
- { scvm_op_dummy_v, "set color" },
- { scvm_op_dummy_v, "set hi-color" },
- // 80
- { scvm_op_dummy_vv, "set XY" },
- { scvm_op_dummy, "set on" },
- { scvm_op_dummy, "set off" },
- { scvm_op_dummy, "kill" },
- // 84
- { scvm_op_dummy, "init" },
- { scvm_op_dummy_v, "set dim-color" },
- { scvm_op_dummy, "dim" },
- { scvm_op_dummy_v, "set key" },
- // 88
- { scvm_op_dummy, "set center" },
- { scvm_op_dummy_v, "set name string" },
- { NULL, NULL },
- { scvm_op_dummy_vv, "set object" },
- // 8C
- { scvm_op_dummy_v, "set back color" },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // 90
- { scvm_op_dummy, "cursor on" },
- { scvm_op_dummy, "cursor off" },
- { scvm_op_dummy, "user put on" },
- { scvm_op_dummy, "user put off" },
- // 94
- { scvm_op_dummy, "soft cursor on" },
- { scvm_op_dummy, "soft curosr off" },
- { scvm_op_dummy, "soft user put on" },
- { scvm_op_dummy, "soft user put off" },
- // 98
- { NULL, NULL },
- { scvm_op_dummy_vv, "set cursor image" },
- { scvm_op_dummy_vv, "set cursor hotspot" },
- { NULL, NULL },
- // 9C
- { scvm_op_dummy_v, "init charset" },
- { scvm_op_dummy_l, "set charset colors" },
- { NULL, NULL },
- { NULL, NULL },
- // A0
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // A4
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // A8
- { scvm_op_wait_for_actor, "wait actor" },
- { scvm_op_wait, "wait msg" },
- { scvm_op_wait, "wait camera" },
- { scvm_op_wait, "wait sentence" },
- // AC
- { scvm_op_set_scrolling, "set scrolling" },
- { NULL, NULL },
- { scvm_op_set_screen, "set screen" },
- { scvm_op_set_room_color, "room color" },
- // B0
- { scvm_op_shake_on, "shake on" },
- { scvm_op_shake_off, "shake off" },
- { NULL, NULL },
- { scvm_op_set_room_intensity, "room intensity" },
- // B4
- { scvm_op_dummy_vv, "save/load thing" },
- { scvm_op_set_transition_effect, "transition effect" },
- { scvm_op_set_rgb_intensity, "rgb intensitiy" },
- { scvm_op_dummy_vvvvv, "room shadow" },
- // B8
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_dummy_vvvv, "pal manip" },
- { scvm_op_dummy_vv, "cycle delay" },
- // BC
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // C0
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // C4
- { scvm_op_dummy_v, "set current verb" },
- { scvm_op_set_current_actor, "set current actor" },
- { scvm_op_dummy_vv, "set anim var" },
- { NULL, NULL },
- // C8
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // CC
- { NULL, NULL },
- { scvm_op_array_write_string, "array write string" },
- { NULL, NULL },
- { NULL, NULL },
- // D0
- { scvm_op_array_write_list, "array write list" },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // D4
- { scvm_op_array_write_list2, "array write list2" },
- { scvm_op_set_palette, "set palette" },
- { NULL, NULL },
- { scvm_op_dummy_v, "set cursor transparency" },
- // D8
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // DC
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // E0
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_wait_for, "wait anim" },
- { scvm_op_set_actor_layer, "set layer" },
- // E4
- { scvm_op_set_actor_walk_script, "set walk script" },
- { scvm_op_dummy, "set standing" },
- { scvm_op_set_actor_direction, "set direction" },
- { scvm_op_dummy_v, "turn to direction" },
- // E8
- { scvm_op_wait_for, "wait turn" },
- { scvm_op_dummy, "freeze" },
- { scvm_op_dummy, "unfreeze" },
- { scvm_op_set_actor_talk_script, "set talk script" },
- // EC
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // F0
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // F4
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // F8
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- // FC
- { NULL, NULL },
- { NULL, NULL },
- { NULL, NULL },
- { scvm_op_dummy, "redraw" }
- };
-