ebedf4f452f7eb432dfb84a51b66c2131eb6774a
[projects/chimara/chimara.git] / interpreters / nitfol / op_call.c
1 /*  Nitfol - z-machine interpreter using Glk for output.
2     Copyright (C) 1999  Evin Robertson
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
17
18     The author can be reached at nitfol@deja.com
19 */
20 #include "nitfol.h"
21
22 void mop_call(zword dest, unsigned num_args, zword *args, int result_var)
23 {
24   unsigned i;
25   offset destPC;
26   unsigned num_local;
27
28   if(dest == 0) {
29     check_set_var(result_var, 0);
30     return;
31   }
32
33   destPC = UNPACKR(dest);
34
35   /*  printf("call %x -> %x\n", oldPC, destPC); */
36   
37 #ifndef FAST
38   if(destPC > game_size) {
39     n_show_error(E_INSTR, "call past end of story", dest);
40     check_set_var(result_var, 0);
41     return;
42   }
43 #endif
44   
45   num_local = HIBYTE(destPC); /* first byte is # of local variables */
46
47 #ifndef FAST
48   if(num_local > 15) {
49     n_show_error(E_INSTR, "call to non-function (initial byte > 15)", dest);
50     check_set_var(result_var, 0);
51     return;
52   }
53 #endif
54
55   destPC++;     /* Go on past the variable count */
56
57   if(zversion < 5) {
58     for(i = num_args; i < num_local; i++)
59       args[i] = HIWORD(destPC + i * ZWORD_SIZE);  /* Load default locals */
60     destPC += num_local * ZWORD_SIZE;
61   } else {
62     for(i = num_args; i < num_local; i++)
63       args[i] = 0;                                /* locals default to zero */
64   }
65
66   add_stack_frame(PC, num_local, args, num_args, result_var);
67
68   PC = destPC;
69
70   /*n_show_debug(E_DEBUG, "function starting", dest);*/
71 }
72
73 void op_call_n(void)
74 {
75   mop_call(operand[0], numoperands - 1, operand + 1, -1);
76 }
77
78 void op_call_s(void)
79 {
80   zbyte ret_var = HIBYTE(PC);
81   PC++;
82   mop_call(operand[0], numoperands - 1, operand + 1, ret_var);
83 }
84
85 void op_ret(void)
86 {
87   mop_func_return(operand[0]);
88 }
89
90 void op_rfalse(void)
91 {
92   mop_func_return(0);
93 }
94
95 void op_rtrue(void)
96 {
97   mop_func_return(1);
98 }