3e5c6e0c0980cfb6e39d133093f1a0a057257f43
[projects/chimara/chimara.git] / interpreters / frotz / variable.c
1 /* variable.c - Variable and stack related opcodes
2  *      Copyright (c) 1995-1997 Stefan Jokisch
3  *
4  * This file is part of Frotz.
5  *
6  * Frotz is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Frotz is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include "frotz.h"
22
23 /*
24  * z_dec, decrement a variable.
25  *
26  *      zargs[0] = variable to decrement
27  *
28  */
29
30 void z_dec (void)
31 {
32     zword value;
33
34     if (zargs[0] == 0)
35         (*sp)--;
36     else if (zargs[0] < 16)
37         (*(fp - zargs[0]))--;
38     else {
39         zword addr = h_globals + 2 * (zargs[0] - 16);
40         LOW_WORD (addr, value)
41         value--;
42         SET_WORD (addr, value)
43     }
44
45 }/* z_dec */
46
47 /*
48  * z_dec_chk, decrement a variable and branch if now less than value.
49  *
50  *      zargs[0] = variable to decrement
51  *      zargs[1] = value to check variable against
52  *
53  */
54
55 void z_dec_chk (void)
56 {
57     zword value;
58
59     if (zargs[0] == 0)
60         value = --(*sp);
61     else if (zargs[0] < 16)
62         value = --(*(fp - zargs[0]));
63     else {
64         zword addr = h_globals + 2 * (zargs[0] - 16);
65         LOW_WORD (addr, value)
66         value--;
67         SET_WORD (addr, value)
68     }
69
70     branch ((short) value < (short) zargs[1]);
71
72 }/* z_dec_chk */
73
74 /*
75  * z_inc, increment a variable.
76  *
77  *      zargs[0] = variable to increment
78  *
79  */
80
81 void z_inc (void)
82 {
83     zword value;
84
85     if (zargs[0] == 0)
86         (*sp)++;
87     else if (zargs[0] < 16)
88         (*(fp - zargs[0]))++;
89     else {
90         zword addr = h_globals + 2 * (zargs[0] - 16);
91         LOW_WORD (addr, value)
92         value++;
93         SET_WORD (addr, value)
94     }
95
96 }/* z_inc */
97
98 /*
99  * z_inc_chk, increment a variable and branch if now greater than value.
100  *
101  *      zargs[0] = variable to increment
102  *      zargs[1] = value to check variable against
103  *
104  */
105
106 void z_inc_chk (void)
107 {
108     zword value;
109
110     if (zargs[0] == 0)
111         value = ++(*sp);
112     else if (zargs[0] < 16)
113         value = ++(*(fp - zargs[0]));
114     else {
115         zword addr = h_globals + 2 * (zargs[0] - 16);
116         LOW_WORD (addr, value)
117         value++;
118         SET_WORD (addr, value)
119     }
120
121     branch ((short) value > (short) zargs[1]);
122
123 }/* z_inc_chk */
124
125 /*
126  * z_load, store the value of a variable.
127  *
128  *      zargs[0] = variable to store
129  *
130  */
131
132 void z_load (void)
133 {
134     zword value;
135
136     if (zargs[0] == 0)
137         value = *sp;
138     else if (zargs[0] < 16)
139         value = *(fp - zargs[0]);
140     else {
141         zword addr = h_globals + 2 * (zargs[0] - 16);
142         LOW_WORD (addr, value)
143     }
144
145     store (value);
146
147 }/* z_load */
148
149 /*
150  * z_pop, pop a value off the game stack and discard it.
151  *
152  *      no zargs used
153  *
154  */
155
156 void z_pop (void)
157 {
158
159     sp++;
160
161 }/* z_pop */
162
163 /*
164  * z_pop_stack, pop n values off the game or user stack and discard them.
165  *
166  *      zargs[0] = number of values to discard
167  *      zargs[1] = address of user stack (optional)
168  *
169  */
170
171 void z_pop_stack (void)
172 {
173
174     if (zargc == 2) {           /* it's a user stack */
175
176         zword size;
177         zword addr = zargs[1];
178
179         LOW_WORD (addr, size)
180
181         size += zargs[0];
182         storew (addr, size);
183
184     } else sp += zargs[0];      /* it's the game stack */
185
186 }/* z_pop_stack */
187
188 /*
189  * z_pull, pop a value off...
190  *
191  * a) ...the game or a user stack and store it (V6)
192  *
193  *      zargs[0] = address of user stack (optional)
194  *
195  * b) ...the game stack and write it to a variable (other than V6)
196  *
197  *      zargs[0] = variable to write value to
198  *
199  */
200
201 void z_pull (void)
202 {
203     zword value;
204
205     if (h_version != V6) {      /* not a V6 game, pop stack and write */
206
207         value = *sp++;
208
209         if (zargs[0] == 0)
210             *sp = value;
211         else if (zargs[0] < 16)
212             *(fp - zargs[0]) = value;
213         else {
214             zword addr = h_globals + 2 * (zargs[0] - 16);
215             SET_WORD (addr, value)
216         }
217
218     } else {                    /* it's V6, but is there a user stack? */
219
220         if (zargc == 1) {       /* it's a user stack */
221
222             zword size;
223             zword addr = zargs[0];
224
225             LOW_WORD (addr, size)
226
227             size++;
228             storew (addr, size);
229
230             addr += 2 * size;
231             LOW_WORD (addr, value)
232
233         } else value = *sp++;   /* it's the game stack */
234
235         store (value);
236
237     }
238
239 }/* z_pull */
240
241 /*
242  * z_push, push a value onto the game stack.
243  *
244  *      zargs[0] = value to push onto the stack
245  *
246  */
247
248 void z_push (void)
249 {
250
251     *--sp = zargs[0];
252
253 }/* z_push */
254
255 /*
256  * z_push_stack, push a value onto a user stack then branch if successful.
257  *
258  *      zargs[0] = value to push onto the stack
259  *      zargs[1] = address of user stack
260  *
261  */
262
263 void z_push_stack (void)
264 {
265     zword size;
266     zword addr = zargs[1];
267
268     LOW_WORD (addr, size)
269
270     if (size != 0) {
271
272         storew ((zword) (addr + 2 * size), zargs[0]);
273
274         size--;
275         storew (addr, size);
276
277     }
278
279     branch (size);
280
281 }/* z_push_stack */
282
283 /*
284  * z_store, write a value to a variable.
285  *
286  *      zargs[0] = variable to be written to
287  *      zargs[1] = value to write
288  *
289  */
290
291 void z_store (void)
292 {
293     zword value = zargs[1];
294
295     if (zargs[0] == 0)
296         *sp = value;
297     else if (zargs[0] < 16)
298         *(fp - zargs[0]) = value;
299     else {
300         zword addr = h_globals + 2 * (zargs[0] - 16);
301         SET_WORD (addr, value)
302     }
303
304 }/* z_store */