Re-organize the example programs.
Chris Pressey
4 years ago
0 | word score | |
1 | routine main | |
2 | inputs score | |
3 | outputs score | |
4 | trashes a, c, z, v, n | |
5 | { | |
6 | st off, c | |
7 | add score, 1999 | |
8 | } |
0 | vector vec | |
1 | inputs y | |
2 | outputs y | |
3 | trashes z, n | |
4 | ||
5 | routine foo | |
6 | inputs x | |
7 | outputs x | |
8 | trashes z, n | |
9 | { | |
10 | inc x | |
11 | } | |
12 | ||
13 | routine main | |
14 | inputs foo | |
15 | outputs vec | |
16 | trashes a, z, n | |
17 | { | |
18 | copy foo, vec | |
19 | } |
0 | buffer[2048] buf | |
1 | pointer ptr @ 254 | |
2 | byte foo | |
3 | ||
4 | routine main | |
5 | inputs buf | |
6 | outputs buf, y, foo | |
7 | trashes a, z, n, ptr | |
8 | { | |
9 | ld y, 0 | |
10 | copy ^buf, ptr | |
11 | copy 123, [ptr] + y | |
12 | copy [ptr] + y, foo | |
13 | copy foo, [ptr] + y | |
14 | } |
0 | // **************************** | |
1 | // * Demo Game for SixtyPical * | |
2 | // **************************** | |
3 | ||
4 | // ---------------------------------------------------------------- | |
5 | // Type Definitions | |
6 | // ---------------------------------------------------------------- | |
7 | ||
8 | // | |
9 | // Type of routines (and vectors to those routines) which are called on each frame | |
10 | // to implement a certain state of the game (title screen, in play, game over, etc.) | |
11 | // | |
12 | // This type is also used as the type for the interrupt vector, even though | |
13 | // the interrupt routine saves and restores everything before being called and | |
14 | // thus clearly does not actually trash all the registers. It is declared this | |
15 | // way so that the game state routines, which do trash these registers, can be | |
16 | // assigned to it. | |
17 | // | |
18 | // This type is also used as the type for the location the old interrupt vector | |
19 | // is backed up to, because all the game state routines `goto` the old handler | |
20 | // and the end of their own routines, so the type needs to be compatible. | |
21 | // (In a good sense, it is a continuation.) | |
22 | // | |
23 | // Further, | |
24 | // | |
25 | // It's very arguable that screen1/2/3/4 and colormap1/2/3/4 are not REALLY inputs. | |
26 | // They're only there to support the fact that game states sometimes clear the | |
27 | // screen, and sometimes don't. When they don't, they preserve the screen, and | |
28 | // currently the way to say "we preserve the screen" is to have it as both input | |
29 | // and output. There is probably a better way to do this, but it needs thought. | |
30 | // | |
31 | ||
32 | typedef routine | |
33 | inputs joy2, press_fire_msg, dispatch_game_state, | |
34 | actor_pos, actor_delta, actor_logic, | |
35 | screen, screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 | |
36 | outputs dispatch_game_state, | |
37 | actor_pos, actor_delta, actor_logic, | |
38 | screen, screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 | |
39 | trashes a, x, y, c, z, n, v, pos, new_pos, delta, ptr, dispatch_logic | |
40 | game_state_routine | |
41 | ||
42 | // | |
43 | // Routines that are called to get the new state of each actor (player, enemy, etc.) | |
44 | // | |
45 | // Routines that conform to this type also follow this convention: | |
46 | // | |
47 | // Set carry if the player perished. Carry clear otherwise. | |
48 | // | |
49 | ||
50 | typedef routine | |
51 | inputs pos, delta, joy2, screen | |
52 | outputs pos, delta, new_pos, screen, c | |
53 | trashes a, x, y, z, n, v, ptr | |
54 | logic_routine | |
55 | ||
56 | // ---------------------------------------------------------------- | |
57 | // System Locations | |
58 | // ---------------------------------------------------------------- | |
59 | ||
60 | byte vic_border @ 53280 | |
61 | byte vic_bg @ 53281 | |
62 | ||
63 | byte table[256] screen1 @ 1024 | |
64 | byte table[256] screen2 @ 1274 | |
65 | byte table[256] screen3 @ 1524 | |
66 | byte table[256] screen4 @ 1774 | |
67 | ||
68 | byte table[256] colormap1 @ 55296 | |
69 | byte table[256] colormap2 @ 55546 | |
70 | byte table[256] colormap3 @ 55796 | |
71 | byte table[256] colormap4 @ 56046 | |
72 | ||
73 | buffer[2048] screen @ 1024 | |
74 | byte joy2 @ $dc00 | |
75 | ||
76 | // ---------------------------------------------------------------- | |
77 | // Global Variables | |
78 | // ---------------------------------------------------------------- | |
79 | ||
80 | pointer ptr @ 254 | |
81 | ||
82 | word table[256] actor_pos | |
83 | word pos | |
84 | word new_pos | |
85 | ||
86 | word table[256] actor_delta | |
87 | word delta | |
88 | ||
89 | vector logic_routine table[256] actor_logic | |
90 | vector logic_routine dispatch_logic | |
91 | ||
92 | byte table[32] press_fire_msg: "PRESS`FIRE`TO`PLAY" | |
93 | ||
94 | // | |
95 | // Points to the routine that implements the current game state. | |
96 | // | |
97 | ||
98 | vector game_state_routine | |
99 | dispatch_game_state | |
100 | ||
101 | // | |
102 | // Interrupt vector. Has same type as game states (see above.) | |
103 | // | |
104 | ||
105 | vector game_state_routine | |
106 | cinv @ 788 | |
107 | ||
108 | // | |
109 | // Location to which the old interrupt vector is saved before replacement. | |
110 | // | |
111 | ||
112 | vector game_state_routine | |
113 | save_cinv | |
114 | ||
115 | // ---------------------------------------------------------------- | |
116 | // Utility Routines | |
117 | // ---------------------------------------------------------------- | |
118 | ||
119 | routine read_stick | |
120 | inputs joy2 | |
121 | outputs delta | |
122 | trashes a, x, z, n | |
123 | { | |
124 | ld x, joy2 | |
125 | ld a, x | |
126 | and a, 1 // up | |
127 | if z { | |
128 | copy $ffd8, delta // -40 | |
129 | } else { | |
130 | ld a, x | |
131 | and a, 2 // down | |
132 | if z { | |
133 | copy word 40, delta | |
134 | } else { | |
135 | ld a, x | |
136 | and a, 4 // left | |
137 | if z { | |
138 | copy $ffff, delta // -1 | |
139 | } else { | |
140 | ld a, x | |
141 | and a, 8 // right | |
142 | if z { | |
143 | copy word 1, delta | |
144 | } else { | |
145 | copy word 0, delta | |
146 | } | |
147 | } | |
148 | } | |
149 | } | |
150 | } | |
151 | ||
152 | // You can repeatedly (i.e. as part of actor logic or an IRQ handler) | |
153 | // call this routine. | |
154 | // Upon return, if carry is set, the button was pressed then released. | |
155 | ||
156 | define check_button routine | |
157 | inputs joy2 | |
158 | outputs c | |
159 | trashes a, z, n | |
160 | static byte button_down : 0 | |
161 | { | |
162 | ld a, button_down | |
163 | if z { | |
164 | ld a, joy2 | |
165 | and a, $10 | |
166 | if z { | |
167 | ld a, 1 | |
168 | st a, button_down | |
169 | } | |
170 | st off, c | |
171 | } else { | |
172 | ld a, joy2 | |
173 | and a, $10 | |
174 | if not z { | |
175 | ld a, 0 | |
176 | st a, button_down | |
177 | st on, c | |
178 | } else { | |
179 | st off, c | |
180 | } | |
181 | } | |
182 | } | |
183 | ||
184 | routine clear_screen | |
185 | outputs screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 | |
186 | trashes a, y, c, n, z | |
187 | { | |
188 | ld y, 0 | |
189 | repeat { | |
190 | ld a, 1 | |
191 | st a, colormap1 + y | |
192 | st a, colormap2 + y | |
193 | st a, colormap3 + y | |
194 | st a, colormap4 + y | |
195 | ||
196 | ld a, 32 | |
197 | st a, screen1 + y | |
198 | st a, screen2 + y | |
199 | st a, screen3 + y | |
200 | st a, screen4 + y | |
201 | ||
202 | inc y | |
203 | cmp y, 250 | |
204 | } until z | |
205 | } | |
206 | ||
207 | routine calculate_new_position | |
208 | inputs pos, delta | |
209 | outputs new_pos | |
210 | trashes a, c, n, z, v | |
211 | { | |
212 | copy pos, new_pos | |
213 | st off, c | |
214 | add new_pos, delta | |
215 | } | |
216 | ||
217 | define check_new_position_in_bounds routine | |
218 | inputs new_pos | |
219 | outputs c | |
220 | trashes a, z, n, v | |
221 | static word compare_target : 0 | |
222 | { | |
223 | copy 1000, compare_target | |
224 | st on, c | |
225 | sub compare_target, new_pos | |
226 | ||
227 | if not c { | |
228 | copy word 0, compare_target | |
229 | st on, c | |
230 | sub compare_target, new_pos | |
231 | if not c { | |
232 | st off, c | |
233 | } else { | |
234 | st on, c | |
235 | } | |
236 | } else { | |
237 | st on, c | |
238 | } | |
239 | } | |
240 | ||
241 | routine init_game | |
242 | inputs actor_pos, actor_delta, actor_logic | |
243 | outputs actor_pos, actor_delta, actor_logic | |
244 | trashes pos, a, y, z, n, c, v | |
245 | { | |
246 | ld y, 0 | |
247 | copy word 0, pos | |
248 | repeat { | |
249 | copy pos, actor_pos + y | |
250 | copy word 40, actor_delta + y | |
251 | copy enemy_logic, actor_logic + y | |
252 | ||
253 | st off, c | |
254 | add pos, word 7 | |
255 | ||
256 | inc y | |
257 | cmp y, 16 | |
258 | } until z | |
259 | ||
260 | ld y, 0 | |
261 | copy word 0, actor_pos + y | |
262 | copy word 0, actor_delta + y | |
263 | copy player_logic, actor_logic + y | |
264 | } | |
265 | ||
266 | // ---------------------------------------------------------------- | |
267 | // Actor Logics | |
268 | // ---------------------------------------------------------------- | |
269 | ||
270 | define player_logic logic_routine | |
271 | { | |
272 | call read_stick | |
273 | ||
274 | call calculate_new_position | |
275 | call check_new_position_in_bounds | |
276 | ||
277 | if c { | |
278 | copy ^screen, ptr | |
279 | st off, c | |
280 | add ptr, new_pos | |
281 | ld y, 0 | |
282 | ||
283 | // check collision. | |
284 | ld a, [ptr] + y | |
285 | // if "collision" is with your own self, treat it as if it's blank space! | |
286 | cmp a, 81 | |
287 | if z { | |
288 | ld a, 32 | |
289 | } | |
290 | cmp a, 32 | |
291 | if z { | |
292 | copy ^screen, ptr | |
293 | st off, c | |
294 | add ptr, pos | |
295 | copy 32, [ptr] + y | |
296 | ||
297 | copy new_pos, pos | |
298 | ||
299 | copy ^screen, ptr | |
300 | st off, c | |
301 | add ptr, pos | |
302 | copy 81, [ptr] + y | |
303 | ||
304 | st off, c | |
305 | } else { | |
306 | st on, c | |
307 | } | |
308 | ||
309 | // FIXME these trashes, strictly speaking, probably shouldn't be needed, | |
310 | // but currently the compiler cares a little too much about values that are | |
311 | // initialized in one branch of an `if`, but not the other, but are trashed | |
312 | // at the end of the routine anyway. | |
313 | trash ptr | |
314 | trash y | |
315 | trash v | |
316 | } else { | |
317 | st off, c | |
318 | } | |
319 | } | |
320 | ||
321 | define enemy_logic logic_routine | |
322 | static word compare_target : 0 | |
323 | { | |
324 | call calculate_new_position | |
325 | call check_new_position_in_bounds | |
326 | ||
327 | if c { | |
328 | copy ^screen, ptr | |
329 | st off, c | |
330 | add ptr, new_pos | |
331 | ld y, 0 | |
332 | ||
333 | // check collision. | |
334 | ld a, [ptr] + y | |
335 | // if "collision" is with your own self, treat it as if it's blank space! | |
336 | cmp a, 82 | |
337 | if z { | |
338 | ld a, 32 | |
339 | } | |
340 | cmp a, 32 | |
341 | if z { | |
342 | copy ^screen, ptr | |
343 | st off, c | |
344 | add ptr, pos | |
345 | copy 32, [ptr] + y | |
346 | ||
347 | copy new_pos, pos | |
348 | ||
349 | copy ^screen, ptr | |
350 | st off, c | |
351 | add ptr, pos | |
352 | copy 82, [ptr] + y | |
353 | ||
354 | st off, c | |
355 | } else { | |
356 | st on, c | |
357 | } | |
358 | ||
359 | // FIXME these trashes, strictly speaking, probably shouldn't be needed, | |
360 | // but currently the compiler cares too much about values that are | |
361 | // initialized in one branch of an `if`, but not the other, but trashed | |
362 | // at the end of the routine anyway. | |
363 | trash ptr | |
364 | trash y | |
365 | } else { | |
366 | copy delta, compare_target | |
367 | st on, c | |
368 | sub compare_target, word 40 | |
369 | if not z { | |
370 | copy word 40, delta | |
371 | } else { | |
372 | copy $ffd8, delta | |
373 | } | |
374 | } | |
375 | ||
376 | st off, c | |
377 | } | |
378 | ||
379 | // ---------------------------------------------------------------- | |
380 | // Game States | |
381 | // ---------------------------------------------------------------- | |
382 | ||
383 | define game_state_title_screen game_state_routine | |
384 | { | |
385 | ld y, 0 | |
386 | repeat { | |
387 | ld a, press_fire_msg + y | |
388 | ||
389 | st on, c | |
390 | sub a, 64 // yuck. oh well | |
391 | ||
392 | st a, screen1 + y | |
393 | inc y | |
394 | cmp y, 18 | |
395 | } until z | |
396 | ||
397 | st off, c | |
398 | call check_button | |
399 | ||
400 | if c { | |
401 | call clear_screen | |
402 | call init_game | |
403 | copy game_state_play, dispatch_game_state | |
404 | } | |
405 | ||
406 | goto save_cinv | |
407 | } | |
408 | ||
409 | define game_state_play game_state_routine | |
410 | static byte save_x : 0 | |
411 | { | |
412 | ld x, 0 | |
413 | repeat { | |
414 | copy actor_pos + x, pos | |
415 | copy actor_delta + x, delta | |
416 | ||
417 | st x, save_x | |
418 | ||
419 | copy actor_logic + x, dispatch_logic | |
420 | call dispatch_logic | |
421 | ||
422 | if c { | |
423 | // Player died! Want no dead! Break out of the loop (this is a bit awkward.) | |
424 | call clear_screen | |
425 | copy game_state_game_over, dispatch_game_state | |
426 | ld x, 15 | |
427 | } else { | |
428 | ld x, save_x | |
429 | } | |
430 | ||
431 | copy pos, actor_pos + x | |
432 | copy delta, actor_delta + x | |
433 | ||
434 | inc x | |
435 | cmp x, 16 | |
436 | } until z | |
437 | ||
438 | goto save_cinv | |
439 | } | |
440 | ||
441 | define game_state_game_over game_state_routine | |
442 | { | |
443 | st off, c | |
444 | call check_button | |
445 | ||
446 | if c { | |
447 | call clear_screen | |
448 | call init_game | |
449 | copy game_state_title_screen, dispatch_game_state | |
450 | } | |
451 | ||
452 | goto save_cinv | |
453 | } | |
454 | ||
455 | // ************************* | |
456 | // * Main Game Loop Driver * | |
457 | // ************************* | |
458 | ||
459 | define our_cinv game_state_routine | |
460 | { | |
461 | goto dispatch_game_state | |
462 | } | |
463 | ||
464 | routine main | |
465 | inputs cinv | |
466 | outputs cinv, save_cinv, pos, dispatch_game_state, | |
467 | screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 | |
468 | trashes a, y, n, c, z, vic_border, vic_bg | |
469 | { | |
470 | ld a, 5 | |
471 | st a, vic_border | |
472 | ld a, 0 | |
473 | st a, vic_bg | |
474 | ld y, 0 | |
475 | ||
476 | call clear_screen | |
477 | ||
478 | copy game_state_title_screen, dispatch_game_state | |
479 | ||
480 | copy word 0, pos | |
481 | with interrupts off { | |
482 | copy cinv, save_cinv | |
483 | copy our_cinv, cinv | |
484 | } | |
485 | ||
486 | repeat { } forever | |
487 | } |
0 | byte vic_border @ 53280 | |
1 | ||
2 | // | |
3 | // The constraints on these 2 vectors are kind-of sort-of big fibs. | |
4 | // They're only written this way so they can be compatible with our | |
5 | // routine. In fact, CINV is an interrupt routine where it doesn't | |
6 | // really matter what you trash anyway, because all registers were | |
7 | /// saved by the caller (the KERNAL) and will be restored by the end | |
8 | // of the code of the saved origin cinv routine that we goto. | |
9 | // | |
10 | // I wonder if this could be arranged somehow to be less fibby, in | |
11 | // a future version of SixtyPical. | |
12 | // | |
13 | ||
14 | vector cinv | |
15 | inputs vic_border | |
16 | outputs vic_border | |
17 | trashes z, n | |
18 | @ 788 | |
19 | ||
20 | vector save_cinv | |
21 | inputs vic_border | |
22 | outputs vic_border | |
23 | trashes z, n | |
24 | ||
25 | routine our_cinv | |
26 | inputs vic_border | |
27 | outputs vic_border | |
28 | trashes z, n | |
29 | { | |
30 | inc vic_border | |
31 | goto save_cinv | |
32 | } | |
33 | ||
34 | routine main | |
35 | inputs cinv | |
36 | outputs cinv, save_cinv | |
37 | trashes a, n, z | |
38 | { | |
39 | with interrupts off { | |
40 | copy cinv, save_cinv | |
41 | copy our_cinv, cinv | |
42 | } | |
43 | } |
0 | word screen @ 1024 | |
1 | byte joy2 @ $dc00 | |
2 | ||
3 | word delta | |
4 | ||
5 | routine read_stick | |
6 | inputs joy2 | |
7 | outputs delta | |
8 | trashes a, x, z, n | |
9 | { | |
10 | ld x, joy2 | |
11 | ld a, x | |
12 | and a, 1 // up | |
13 | if z { | |
14 | copy $ffd8, delta // -40 | |
15 | } else { | |
16 | ld a, x | |
17 | and a, 2 // down | |
18 | if z { | |
19 | copy word 40, delta | |
20 | } else { | |
21 | ld a, x | |
22 | and a, 4 // left | |
23 | if z { | |
24 | copy $ffff, delta // -1 | |
25 | } else { | |
26 | ld a, x | |
27 | and a, 8 // right | |
28 | if z { | |
29 | copy word 1, delta | |
30 | } else { | |
31 | copy word 0, delta | |
32 | } | |
33 | } | |
34 | } | |
35 | } | |
36 | } | |
37 | ||
38 | routine main | |
39 | inputs joy2 | |
40 | outputs delta | |
41 | trashes a, x, z, n, screen | |
42 | { | |
43 | repeat { | |
44 | call read_stick | |
45 | copy delta, screen | |
46 | ld a, 1 | |
47 | } until z | |
48 | } |
0 | // Displays 256 hearts at the top of the Commodore 64's screen. | |
1 | ||
2 | // Define where the screen starts in memory: | |
3 | byte table[256] screen @ 1024 | |
4 | ||
5 | routine main | |
6 | // These are the values that will be written to by this routine: | |
7 | trashes a, x, z, n, screen | |
8 | { | |
9 | ld x, 0 | |
10 | ld a, 83 // 83 = screen code for heart | |
11 | repeat { | |
12 | st a, screen + x | |
13 | inc x | |
14 | } until z // this flag will be set when x wraps around from 255 to 0 | |
15 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine print | |
6 | trashes a, z, n | |
7 | { | |
8 | ld a, 65 | |
9 | call chrout | |
10 | } | |
11 | ||
12 | routine main | |
13 | trashes a, z, n | |
14 | { | |
15 | call print | |
16 | call print | |
17 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine main | |
6 | trashes a, x, y, z, n, c, v | |
7 | { | |
8 | ld a, 0 | |
9 | if z { | |
10 | ld a, 89 | |
11 | call chrout | |
12 | } else { | |
13 | ld a, 78 | |
14 | call chrout | |
15 | } | |
16 | ||
17 | ld a, 1 | |
18 | if z { | |
19 | ld a, 89 | |
20 | call chrout | |
21 | } else { | |
22 | ld a, 78 | |
23 | call chrout | |
24 | } | |
25 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine main | |
6 | trashes a, x, y, z, n, c, v | |
7 | { | |
8 | ld a, 0 | |
9 | if z { | |
10 | ld a, 89 | |
11 | call chrout | |
12 | ld a, 1 | |
13 | } | |
14 | ||
15 | ld a, 65 | |
16 | call chrout | |
17 | ||
18 | ld a, 1 | |
19 | if z { | |
20 | ld a, 89 | |
21 | call chrout | |
22 | ld a, 1 | |
23 | } | |
24 | } |
0 | byte bar | |
1 | byte baz | |
2 | ||
3 | routine main | |
4 | inputs baz | |
5 | outputs bar | |
6 | trashes a, n, z | |
7 | { | |
8 | copy baz, bar | |
9 | } |
0 | byte lives | |
1 | ||
2 | routine main | |
3 | inputs lives | |
4 | outputs lives | |
5 | trashes a, x | |
6 | { | |
7 | ld a, 0 | |
8 | st a, lives | |
9 | ld x, lives | |
10 | st off, c | |
11 | add x, 1 | |
12 | st x, lives | |
13 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine bar trashes a, z, n { | |
6 | ld a, 66 | |
7 | call chrout | |
8 | } | |
9 | ||
10 | routine main trashes a, z, n { | |
11 | ld a, 65 | |
12 | call chrout | |
13 | goto bar | |
14 | } |
0 | routine foo | |
1 | inputs a | |
2 | outputs a | |
3 | { | |
4 | cmp a, 42 | |
5 | if z { | |
6 | ld a, 7 | |
7 | } else { | |
8 | ld a, 23 | |
9 | } | |
10 | } |
0 | byte vic_border @ 53280 | |
1 | ||
2 | // | |
3 | // The constraints on these 2 vectors are kind-of sort-of big fibs. | |
4 | // They're only written this way so they can be compatible with our | |
5 | // routine. In fact, CINV is an interrupt routine where it doesn't | |
6 | // really matter what you trash anyway, because all registers were | |
7 | /// saved by the caller (the KERNAL) and will be restored by the end | |
8 | // of the code of the saved origin cinv routine that we goto. | |
9 | // | |
10 | // I wonder if this could be arranged somehow to be less fibby, in | |
11 | // a future version of SixtyPical. | |
12 | // | |
13 | ||
14 | vector cinv | |
15 | inputs vic_border | |
16 | outputs vic_border | |
17 | trashes z, n | |
18 | @ 788 | |
19 | ||
20 | vector save_cinv | |
21 | inputs vic_border | |
22 | outputs vic_border | |
23 | trashes z, n | |
24 | ||
25 | routine our_cinv | |
26 | inputs vic_border | |
27 | outputs vic_border | |
28 | trashes z, n | |
29 | { | |
30 | inc vic_border | |
31 | goto save_cinv | |
32 | } | |
33 | ||
34 | routine main | |
35 | inputs cinv | |
36 | outputs cinv, save_cinv | |
37 | trashes a, n, z | |
38 | { | |
39 | with interrupts off { | |
40 | copy cinv, save_cinv | |
41 | copy our_cinv, cinv | |
42 | } | |
43 | } |
0 | word screen @ 1024 | |
1 | byte joy2 @ $dc00 | |
2 | ||
3 | word delta | |
4 | ||
5 | routine read_stick | |
6 | inputs joy2 | |
7 | outputs delta | |
8 | trashes a, x, z, n | |
9 | { | |
10 | ld x, joy2 | |
11 | ld a, x | |
12 | and a, 1 // up | |
13 | if z { | |
14 | copy $ffd8, delta // -40 | |
15 | } else { | |
16 | ld a, x | |
17 | and a, 2 // down | |
18 | if z { | |
19 | copy word 40, delta | |
20 | } else { | |
21 | ld a, x | |
22 | and a, 4 // left | |
23 | if z { | |
24 | copy $ffff, delta // -1 | |
25 | } else { | |
26 | ld a, x | |
27 | and a, 8 // right | |
28 | if z { | |
29 | copy word 1, delta | |
30 | } else { | |
31 | copy word 0, delta | |
32 | } | |
33 | } | |
34 | } | |
35 | } | |
36 | } | |
37 | ||
38 | routine main | |
39 | inputs joy2 | |
40 | outputs delta | |
41 | trashes a, x, z, n, screen | |
42 | { | |
43 | repeat { | |
44 | call read_stick | |
45 | copy delta, screen | |
46 | ld a, 1 | |
47 | } until z | |
48 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine main | |
6 | trashes a, y, z, n, c | |
7 | { | |
8 | ld y, 65 | |
9 | repeat { | |
10 | ld a, y | |
11 | call chrout | |
12 | inc y | |
13 | cmp y, 91 | |
14 | } until z | |
15 | } |
0 | byte foo | |
1 | ||
2 | routine chrout | |
3 | inputs a | |
4 | trashes a | |
5 | @ 65490 | |
6 | ||
7 | routine print | |
8 | inputs foo | |
9 | trashes a, z, n | |
10 | { | |
11 | ld a, foo | |
12 | call chrout | |
13 | } | |
14 | ||
15 | routine main | |
16 | trashes a, y, z, n, foo | |
17 | { | |
18 | ld y, 65 | |
19 | st y, foo | |
20 | call print | |
21 | inc foo | |
22 | call print | |
23 | } |
0 | // SixtyPical 0.11 introduced a new syntax for defining routines | |
1 | // (routine was made into a type, and you can now say: define name type.) | |
2 | ||
3 | typedef routine | |
4 | inputs x | |
5 | outputs x | |
6 | trashes z, n | |
7 | routine_type | |
8 | ||
9 | vector routine_type vec | |
10 | ||
11 | define foo routine_type | |
12 | { | |
13 | inc x | |
14 | } | |
15 | ||
16 | define main routine | |
17 | outputs vec | |
18 | trashes a, z, n | |
19 | { | |
20 | copy foo, vec | |
21 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine main | |
6 | inputs a | |
7 | trashes a, z, n | |
8 | { | |
9 | ld a, 65 | |
10 | call chrout | |
11 | } |
0 | // **************************** | |
1 | // * Demo Game for SixtyPical * | |
2 | // **************************** | |
3 | ||
4 | // ---------------------------------------------------------------- | |
5 | // Type Definitions | |
6 | // ---------------------------------------------------------------- | |
7 | ||
8 | // | |
9 | // Type of routines (and vectors to those routines) which are called on each frame | |
10 | // to implement a certain state of the game (title screen, in play, game over, etc.) | |
11 | // | |
12 | // This type is also used as the type for the interrupt vector, even though | |
13 | // the interrupt routine saves and restores everything before being called and | |
14 | // thus clearly does not actually trash all the registers. It is declared this | |
15 | // way so that the game state routines, which do trash these registers, can be | |
16 | // assigned to it. | |
17 | // | |
18 | // This type is also used as the type for the location the old interrupt vector | |
19 | // is backed up to, because all the game state routines `goto` the old handler | |
20 | // and the end of their own routines, so the type needs to be compatible. | |
21 | // (In a good sense, it is a continuation.) | |
22 | // | |
23 | // Further, | |
24 | // | |
25 | // It's very arguable that screen1/2/3/4 and colormap1/2/3/4 are not REALLY inputs. | |
26 | // They're only there to support the fact that game states sometimes clear the | |
27 | // screen, and sometimes don't. When they don't, they preserve the screen, and | |
28 | // currently the way to say "we preserve the screen" is to have it as both input | |
29 | // and output. There is probably a better way to do this, but it needs thought. | |
30 | // | |
31 | ||
32 | typedef routine | |
33 | inputs joy2, press_fire_msg, dispatch_game_state, | |
34 | actor_pos, actor_delta, actor_logic, | |
35 | screen, screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 | |
36 | outputs dispatch_game_state, | |
37 | actor_pos, actor_delta, actor_logic, | |
38 | screen, screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 | |
39 | trashes a, x, y, c, z, n, v, pos, new_pos, delta, ptr, dispatch_logic | |
40 | game_state_routine | |
41 | ||
42 | // | |
43 | // Routines that are called to get the new state of each actor (player, enemy, etc.) | |
44 | // | |
45 | // Routines that conform to this type also follow this convention: | |
46 | // | |
47 | // Set carry if the player perished. Carry clear otherwise. | |
48 | // | |
49 | ||
50 | typedef routine | |
51 | inputs pos, delta, joy2, screen | |
52 | outputs pos, delta, new_pos, screen, c | |
53 | trashes a, x, y, z, n, v, ptr | |
54 | logic_routine | |
55 | ||
56 | // ---------------------------------------------------------------- | |
57 | // System Locations | |
58 | // ---------------------------------------------------------------- | |
59 | ||
60 | byte vic_border @ 53280 | |
61 | byte vic_bg @ 53281 | |
62 | ||
63 | byte table[256] screen1 @ 1024 | |
64 | byte table[256] screen2 @ 1274 | |
65 | byte table[256] screen3 @ 1524 | |
66 | byte table[256] screen4 @ 1774 | |
67 | ||
68 | byte table[256] colormap1 @ 55296 | |
69 | byte table[256] colormap2 @ 55546 | |
70 | byte table[256] colormap3 @ 55796 | |
71 | byte table[256] colormap4 @ 56046 | |
72 | ||
73 | buffer[2048] screen @ 1024 | |
74 | byte joy2 @ $dc00 | |
75 | ||
76 | // ---------------------------------------------------------------- | |
77 | // Global Variables | |
78 | // ---------------------------------------------------------------- | |
79 | ||
80 | pointer ptr @ 254 | |
81 | ||
82 | word table[256] actor_pos | |
83 | word pos | |
84 | word new_pos | |
85 | ||
86 | word table[256] actor_delta | |
87 | word delta | |
88 | ||
89 | vector logic_routine table[256] actor_logic | |
90 | vector logic_routine dispatch_logic | |
91 | ||
92 | byte table[32] press_fire_msg: "PRESS`FIRE`TO`PLAY" | |
93 | ||
94 | // | |
95 | // Points to the routine that implements the current game state. | |
96 | // | |
97 | ||
98 | vector game_state_routine | |
99 | dispatch_game_state | |
100 | ||
101 | // | |
102 | // Interrupt vector. Has same type as game states (see above.) | |
103 | // | |
104 | ||
105 | vector game_state_routine | |
106 | cinv @ 788 | |
107 | ||
108 | // | |
109 | // Location to which the old interrupt vector is saved before replacement. | |
110 | // | |
111 | ||
112 | vector game_state_routine | |
113 | save_cinv | |
114 | ||
115 | // ---------------------------------------------------------------- | |
116 | // Utility Routines | |
117 | // ---------------------------------------------------------------- | |
118 | ||
119 | routine read_stick | |
120 | inputs joy2 | |
121 | outputs delta | |
122 | trashes a, x, z, n | |
123 | { | |
124 | ld x, joy2 | |
125 | ld a, x | |
126 | and a, 1 // up | |
127 | if z { | |
128 | copy $ffd8, delta // -40 | |
129 | } else { | |
130 | ld a, x | |
131 | and a, 2 // down | |
132 | if z { | |
133 | copy word 40, delta | |
134 | } else { | |
135 | ld a, x | |
136 | and a, 4 // left | |
137 | if z { | |
138 | copy $ffff, delta // -1 | |
139 | } else { | |
140 | ld a, x | |
141 | and a, 8 // right | |
142 | if z { | |
143 | copy word 1, delta | |
144 | } else { | |
145 | copy word 0, delta | |
146 | } | |
147 | } | |
148 | } | |
149 | } | |
150 | } | |
151 | ||
152 | // You can repeatedly (i.e. as part of actor logic or an IRQ handler) | |
153 | // call this routine. | |
154 | // Upon return, if carry is set, the button was pressed then released. | |
155 | ||
156 | define check_button routine | |
157 | inputs joy2 | |
158 | outputs c | |
159 | trashes a, z, n | |
160 | static byte button_down : 0 | |
161 | { | |
162 | ld a, button_down | |
163 | if z { | |
164 | ld a, joy2 | |
165 | and a, $10 | |
166 | if z { | |
167 | ld a, 1 | |
168 | st a, button_down | |
169 | } | |
170 | st off, c | |
171 | } else { | |
172 | ld a, joy2 | |
173 | and a, $10 | |
174 | if not z { | |
175 | ld a, 0 | |
176 | st a, button_down | |
177 | st on, c | |
178 | } else { | |
179 | st off, c | |
180 | } | |
181 | } | |
182 | } | |
183 | ||
184 | routine clear_screen | |
185 | outputs screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 | |
186 | trashes a, y, c, n, z | |
187 | { | |
188 | ld y, 0 | |
189 | repeat { | |
190 | ld a, 1 | |
191 | st a, colormap1 + y | |
192 | st a, colormap2 + y | |
193 | st a, colormap3 + y | |
194 | st a, colormap4 + y | |
195 | ||
196 | ld a, 32 | |
197 | st a, screen1 + y | |
198 | st a, screen2 + y | |
199 | st a, screen3 + y | |
200 | st a, screen4 + y | |
201 | ||
202 | inc y | |
203 | cmp y, 250 | |
204 | } until z | |
205 | } | |
206 | ||
207 | routine calculate_new_position | |
208 | inputs pos, delta | |
209 | outputs new_pos | |
210 | trashes a, c, n, z, v | |
211 | { | |
212 | copy pos, new_pos | |
213 | st off, c | |
214 | add new_pos, delta | |
215 | } | |
216 | ||
217 | define check_new_position_in_bounds routine | |
218 | inputs new_pos | |
219 | outputs c | |
220 | trashes a, z, n, v | |
221 | static word compare_target : 0 | |
222 | { | |
223 | copy 1000, compare_target | |
224 | st on, c | |
225 | sub compare_target, new_pos | |
226 | ||
227 | if not c { | |
228 | copy word 0, compare_target | |
229 | st on, c | |
230 | sub compare_target, new_pos | |
231 | if not c { | |
232 | st off, c | |
233 | } else { | |
234 | st on, c | |
235 | } | |
236 | } else { | |
237 | st on, c | |
238 | } | |
239 | } | |
240 | ||
241 | routine init_game | |
242 | inputs actor_pos, actor_delta, actor_logic | |
243 | outputs actor_pos, actor_delta, actor_logic | |
244 | trashes pos, a, y, z, n, c, v | |
245 | { | |
246 | ld y, 0 | |
247 | copy word 0, pos | |
248 | repeat { | |
249 | copy pos, actor_pos + y | |
250 | copy word 40, actor_delta + y | |
251 | copy enemy_logic, actor_logic + y | |
252 | ||
253 | st off, c | |
254 | add pos, word 7 | |
255 | ||
256 | inc y | |
257 | cmp y, 16 | |
258 | } until z | |
259 | ||
260 | ld y, 0 | |
261 | copy word 0, actor_pos + y | |
262 | copy word 0, actor_delta + y | |
263 | copy player_logic, actor_logic + y | |
264 | } | |
265 | ||
266 | // ---------------------------------------------------------------- | |
267 | // Actor Logics | |
268 | // ---------------------------------------------------------------- | |
269 | ||
270 | define player_logic logic_routine | |
271 | { | |
272 | call read_stick | |
273 | ||
274 | call calculate_new_position | |
275 | call check_new_position_in_bounds | |
276 | ||
277 | if c { | |
278 | copy ^screen, ptr | |
279 | st off, c | |
280 | add ptr, new_pos | |
281 | ld y, 0 | |
282 | ||
283 | // check collision. | |
284 | ld a, [ptr] + y | |
285 | // if "collision" is with your own self, treat it as if it's blank space! | |
286 | cmp a, 81 | |
287 | if z { | |
288 | ld a, 32 | |
289 | } | |
290 | cmp a, 32 | |
291 | if z { | |
292 | copy ^screen, ptr | |
293 | st off, c | |
294 | add ptr, pos | |
295 | copy 32, [ptr] + y | |
296 | ||
297 | copy new_pos, pos | |
298 | ||
299 | copy ^screen, ptr | |
300 | st off, c | |
301 | add ptr, pos | |
302 | copy 81, [ptr] + y | |
303 | ||
304 | st off, c | |
305 | } else { | |
306 | st on, c | |
307 | } | |
308 | ||
309 | // FIXME these trashes, strictly speaking, probably shouldn't be needed, | |
310 | // but currently the compiler cares a little too much about values that are | |
311 | // initialized in one branch of an `if`, but not the other, but are trashed | |
312 | // at the end of the routine anyway. | |
313 | trash ptr | |
314 | trash y | |
315 | trash v | |
316 | } else { | |
317 | st off, c | |
318 | } | |
319 | } | |
320 | ||
321 | define enemy_logic logic_routine | |
322 | static word compare_target : 0 | |
323 | { | |
324 | call calculate_new_position | |
325 | call check_new_position_in_bounds | |
326 | ||
327 | if c { | |
328 | copy ^screen, ptr | |
329 | st off, c | |
330 | add ptr, new_pos | |
331 | ld y, 0 | |
332 | ||
333 | // check collision. | |
334 | ld a, [ptr] + y | |
335 | // if "collision" is with your own self, treat it as if it's blank space! | |
336 | cmp a, 82 | |
337 | if z { | |
338 | ld a, 32 | |
339 | } | |
340 | cmp a, 32 | |
341 | if z { | |
342 | copy ^screen, ptr | |
343 | st off, c | |
344 | add ptr, pos | |
345 | copy 32, [ptr] + y | |
346 | ||
347 | copy new_pos, pos | |
348 | ||
349 | copy ^screen, ptr | |
350 | st off, c | |
351 | add ptr, pos | |
352 | copy 82, [ptr] + y | |
353 | ||
354 | st off, c | |
355 | } else { | |
356 | st on, c | |
357 | } | |
358 | ||
359 | // FIXME these trashes, strictly speaking, probably shouldn't be needed, | |
360 | // but currently the compiler cares too much about values that are | |
361 | // initialized in one branch of an `if`, but not the other, but trashed | |
362 | // at the end of the routine anyway. | |
363 | trash ptr | |
364 | trash y | |
365 | } else { | |
366 | copy delta, compare_target | |
367 | st on, c | |
368 | sub compare_target, word 40 | |
369 | if not z { | |
370 | copy word 40, delta | |
371 | } else { | |
372 | copy $ffd8, delta | |
373 | } | |
374 | } | |
375 | ||
376 | st off, c | |
377 | } | |
378 | ||
379 | // ---------------------------------------------------------------- | |
380 | // Game States | |
381 | // ---------------------------------------------------------------- | |
382 | ||
383 | define game_state_title_screen game_state_routine | |
384 | { | |
385 | ld y, 0 | |
386 | repeat { | |
387 | ld a, press_fire_msg + y | |
388 | ||
389 | st on, c | |
390 | sub a, 64 // yuck. oh well | |
391 | ||
392 | st a, screen1 + y | |
393 | inc y | |
394 | cmp y, 18 | |
395 | } until z | |
396 | ||
397 | st off, c | |
398 | call check_button | |
399 | ||
400 | if c { | |
401 | call clear_screen | |
402 | call init_game | |
403 | copy game_state_play, dispatch_game_state | |
404 | } | |
405 | ||
406 | goto save_cinv | |
407 | } | |
408 | ||
409 | define game_state_play game_state_routine | |
410 | static byte save_x : 0 | |
411 | { | |
412 | ld x, 0 | |
413 | repeat { | |
414 | copy actor_pos + x, pos | |
415 | copy actor_delta + x, delta | |
416 | ||
417 | st x, save_x | |
418 | ||
419 | copy actor_logic + x, dispatch_logic | |
420 | call dispatch_logic | |
421 | ||
422 | if c { | |
423 | // Player died! Want no dead! Break out of the loop (this is a bit awkward.) | |
424 | call clear_screen | |
425 | copy game_state_game_over, dispatch_game_state | |
426 | ld x, 15 | |
427 | } else { | |
428 | ld x, save_x | |
429 | } | |
430 | ||
431 | copy pos, actor_pos + x | |
432 | copy delta, actor_delta + x | |
433 | ||
434 | inc x | |
435 | cmp x, 16 | |
436 | } until z | |
437 | ||
438 | goto save_cinv | |
439 | } | |
440 | ||
441 | define game_state_game_over game_state_routine | |
442 | { | |
443 | st off, c | |
444 | call check_button | |
445 | ||
446 | if c { | |
447 | call clear_screen | |
448 | call init_game | |
449 | copy game_state_title_screen, dispatch_game_state | |
450 | } | |
451 | ||
452 | goto save_cinv | |
453 | } | |
454 | ||
455 | // ************************* | |
456 | // * Main Game Loop Driver * | |
457 | // ************************* | |
458 | ||
459 | define our_cinv game_state_routine | |
460 | { | |
461 | goto dispatch_game_state | |
462 | } | |
463 | ||
464 | routine main | |
465 | inputs cinv | |
466 | outputs cinv, save_cinv, pos, dispatch_game_state, | |
467 | screen1, screen2, screen3, screen4, colormap1, colormap2, colormap3, colormap4 | |
468 | trashes a, y, n, c, z, vic_border, vic_bg | |
469 | { | |
470 | ld a, 5 | |
471 | st a, vic_border | |
472 | ld a, 0 | |
473 | st a, vic_bg | |
474 | ld y, 0 | |
475 | ||
476 | call clear_screen | |
477 | ||
478 | copy game_state_title_screen, dispatch_game_state | |
479 | ||
480 | copy word 0, pos | |
481 | with interrupts off { | |
482 | copy cinv, save_cinv | |
483 | copy our_cinv, cinv | |
484 | } | |
485 | ||
486 | repeat { } forever | |
487 | } |
0 | This directory contains example sources which demonstrate | |
1 | the rudiments of SixtyPical. | |
2 | ||
3 | Some are meant to fail and produce an error message. | |
4 | ||
5 | They are not meant to be specific to any architecture, but | |
6 | many do assume the existence of a routine at 65490 which | |
7 | outputs the value of the accumulator as an ASCII character, | |
8 | simply for the purposes of producing some observable output. |
0 | word score | |
1 | routine main | |
2 | inputs score | |
3 | outputs score | |
4 | trashes a, c, z, v, n | |
5 | { | |
6 | st off, c | |
7 | add score, 1999 | |
8 | } |
0 | vector vec | |
1 | inputs y | |
2 | outputs y | |
3 | trashes z, n | |
4 | ||
5 | routine foo | |
6 | inputs x | |
7 | outputs x | |
8 | trashes z, n | |
9 | { | |
10 | inc x | |
11 | } | |
12 | ||
13 | routine main | |
14 | inputs foo | |
15 | outputs vec | |
16 | trashes a, z, n | |
17 | { | |
18 | copy foo, vec | |
19 | } |
0 | buffer[2048] buf | |
1 | pointer ptr @ 254 | |
2 | byte foo | |
3 | ||
4 | routine main | |
5 | inputs buf | |
6 | outputs buf, y, foo | |
7 | trashes a, z, n, ptr | |
8 | { | |
9 | ld y, 0 | |
10 | copy ^buf, ptr | |
11 | copy 123, [ptr] + y | |
12 | copy [ptr] + y, foo | |
13 | copy foo, [ptr] + y | |
14 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine print | |
6 | trashes a, z, n | |
7 | { | |
8 | ld a, 65 | |
9 | call chrout | |
10 | } | |
11 | ||
12 | routine main | |
13 | trashes a, z, n | |
14 | { | |
15 | call print | |
16 | call print | |
17 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine main | |
6 | trashes a, x, y, z, n, c, v | |
7 | { | |
8 | ld a, 0 | |
9 | if z { | |
10 | ld a, 89 | |
11 | call chrout | |
12 | } else { | |
13 | ld a, 78 | |
14 | call chrout | |
15 | } | |
16 | ||
17 | ld a, 1 | |
18 | if z { | |
19 | ld a, 89 | |
20 | call chrout | |
21 | } else { | |
22 | ld a, 78 | |
23 | call chrout | |
24 | } | |
25 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine main | |
6 | trashes a, x, y, z, n, c, v | |
7 | { | |
8 | ld a, 0 | |
9 | if z { | |
10 | ld a, 89 | |
11 | call chrout | |
12 | ld a, 1 | |
13 | } | |
14 | ||
15 | ld a, 65 | |
16 | call chrout | |
17 | ||
18 | ld a, 1 | |
19 | if z { | |
20 | ld a, 89 | |
21 | call chrout | |
22 | ld a, 1 | |
23 | } | |
24 | } |
0 | byte bar | |
1 | byte baz | |
2 | ||
3 | routine main | |
4 | inputs baz | |
5 | outputs bar | |
6 | trashes a, n, z | |
7 | { | |
8 | copy baz, bar | |
9 | } |
0 | byte lives | |
1 | ||
2 | routine main | |
3 | inputs lives | |
4 | outputs lives | |
5 | trashes a, x | |
6 | { | |
7 | ld a, 0 | |
8 | st a, lives | |
9 | ld x, lives | |
10 | st off, c | |
11 | add x, 1 | |
12 | st x, lives | |
13 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine bar trashes a, z, n { | |
6 | ld a, 66 | |
7 | call chrout | |
8 | } | |
9 | ||
10 | routine main trashes a, z, n { | |
11 | ld a, 65 | |
12 | call chrout | |
13 | goto bar | |
14 | } |
0 | routine foo | |
1 | inputs a | |
2 | outputs a | |
3 | { | |
4 | cmp a, 42 | |
5 | if z { | |
6 | ld a, 7 | |
7 | } else { | |
8 | ld a, 23 | |
9 | } | |
10 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine main | |
6 | trashes a, y, z, n, c | |
7 | { | |
8 | ld y, 65 | |
9 | repeat { | |
10 | ld a, y | |
11 | call chrout | |
12 | inc y | |
13 | cmp y, 91 | |
14 | } until z | |
15 | } |
0 | byte foo | |
1 | ||
2 | routine chrout | |
3 | inputs a | |
4 | trashes a | |
5 | @ 65490 | |
6 | ||
7 | routine print | |
8 | inputs foo | |
9 | trashes a, z, n | |
10 | { | |
11 | ld a, foo | |
12 | call chrout | |
13 | } | |
14 | ||
15 | routine main | |
16 | trashes a, y, z, n, foo | |
17 | { | |
18 | ld y, 65 | |
19 | st y, foo | |
20 | call print | |
21 | inc foo | |
22 | call print | |
23 | } |
0 | // SixtyPical 0.11 introduced a new syntax for defining routines | |
1 | // (routine was made into a type, and you can now say: define name type.) | |
2 | ||
3 | typedef routine | |
4 | inputs x | |
5 | outputs x | |
6 | trashes z, n | |
7 | routine_type | |
8 | ||
9 | vector routine_type vec | |
10 | ||
11 | define foo routine_type | |
12 | { | |
13 | inc x | |
14 | } | |
15 | ||
16 | define main routine | |
17 | outputs vec | |
18 | trashes a, z, n | |
19 | { | |
20 | copy foo, vec | |
21 | } |
0 | routine chrout | |
1 | inputs a | |
2 | trashes a | |
3 | @ 65490 | |
4 | ||
5 | routine main | |
6 | inputs a | |
7 | trashes a, z, n | |
8 | { | |
9 | ld a, 65 | |
10 | call chrout | |
11 | } |
0 | byte table[8] message : "WHAT?" | |
1 | ||
2 | routine main | |
3 | inputs message | |
4 | outputs x, a, z, n | |
5 | { | |
6 | ld x, 9 | |
7 | ld a, message + x | |
8 | } |
0 | // | |
1 | // Demonstrates vector tables. | |
2 | // Prints "AABAB". | |
3 | // | |
4 | ||
5 | vector routine | |
6 | trashes a, z, n | |
7 | ||
8 | ||
9 | vector (routine | |
10 | trashes a, z, n) | |
11 | table[32] vectors | |
12 | ||
13 | routine chrout | |
14 | inputs a | |
15 | trashes a | |
16 | @ 65490 | |
17 | ||
18 | routine printa | |
19 | trashes a, z, n | |
20 | { | |
21 | ld a, 65 | |
22 | call chrout | |
23 | } | |
24 | ||
25 | routine printb | |
26 | trashes a, z, n | |
27 | { | |
28 | ld a, 66 | |
29 | call chrout | |
30 | } | |
31 | ||
32 | routine main | |
33 | inputs vectors | |
34 | outputs vectors | |
35 | trashes print, a, x, z, n, c | |
36 | { | |
37 | ld x, 0 | |
38 | copy printa, vectors + x | |
39 | inc x | |
40 | copy printa, print | |
41 | copy print, vectors + x | |
42 | inc x | |
43 | copy printb, print | |
44 | copy print, vectors + x | |
45 | inc x | |
46 | copy printa, vectors + x | |
47 | inc x | |
48 | copy printb, vectors + x | |
49 | ||
50 | ld x, 0 | |
51 | repeat { | |
52 | copy vectors + x, print | |
53 | call print | |
54 | inc x | |
55 | cmp x, 5 | |
56 | } until z | |
57 | } |
0 | vector routine | |
1 | trashes a, z, n | |
2 | ||
3 | ||
4 | routine chrout | |
5 | inputs a | |
6 | trashes a | |
7 | @ 65490 | |
8 | ||
9 | routine printa | |
10 | trashes a, z, n | |
11 | { | |
12 | ld a, 65 | |
13 | call chrout | |
14 | } | |
15 | ||
16 | routine printb | |
17 | trashes a, z, n | |
18 | { | |
19 | ld a, 66 | |
20 | call chrout | |
21 | } | |
22 | ||
23 | routine main | |
24 | trashes print, a, z, n | |
25 | { | |
26 | copy printa, print | |
27 | call print | |
28 | copy printb, print | |
29 | call print | |
30 | } |
0 | word one | |
1 | word table many | |
2 | ||
3 | routine main | |
4 | inputs one, many | |
5 | outputs one, many | |
6 | trashes a, x, y, n, z | |
7 | { | |
8 | ld x, 0 | |
9 | ld y, 0 | |
10 | copy 777, one | |
11 | copy one, many + x | |
12 | copy one, many + y | |
13 | copy many + x, one | |
14 | copy many + y, one | |
15 | } |
0 | // Displays 256 hearts at the top of the Commodore 64's screen. | |
1 | ||
2 | // Define where the screen starts in memory: | |
3 | byte table screen @ 1024 | |
4 | ||
5 | routine main | |
6 | // These are the values that will be written to by this routine: | |
7 | trashes a, x, z, n, screen | |
8 | { | |
9 | ld x, 0 | |
10 | ld a, 83 // 83 = screen code for heart | |
11 | repeat { | |
12 | st a, screen + x | |
13 | inc x | |
14 | } until z // this flag will be set when x wraps around from 255 to 0 | |
15 | } |
0 | // | |
1 | // Demonstrates vector tables. | |
2 | // Prints "AABAB". | |
3 | // | |
4 | ||
5 | vector routine | |
6 | trashes a, z, n | |
7 | ||
8 | ||
9 | vector (routine | |
10 | trashes a, z, n) | |
11 | table[32] vectors | |
12 | ||
13 | routine chrout | |
14 | inputs a | |
15 | trashes a | |
16 | @ 65490 | |
17 | ||
18 | routine printa | |
19 | trashes a, z, n | |
20 | { | |
21 | ld a, 65 | |
22 | call chrout | |
23 | } | |
24 | ||
25 | routine printb | |
26 | trashes a, z, n | |
27 | { | |
28 | ld a, 66 | |
29 | call chrout | |
30 | } | |
31 | ||
32 | routine main | |
33 | inputs vectors | |
34 | outputs vectors | |
35 | trashes print, a, x, z, n, c | |
36 | { | |
37 | ld x, 0 | |
38 | copy printa, vectors + x | |
39 | inc x | |
40 | copy printa, print | |
41 | copy print, vectors + x | |
42 | inc x | |
43 | copy printb, print | |
44 | copy print, vectors + x | |
45 | inc x | |
46 | copy printa, vectors + x | |
47 | inc x | |
48 | copy printb, vectors + x | |
49 | ||
50 | ld x, 0 | |
51 | repeat { | |
52 | copy vectors + x, print | |
53 | call print | |
54 | inc x | |
55 | cmp x, 5 | |
56 | } until z | |
57 | } |
0 | vector routine | |
1 | trashes a, z, n | |
2 | ||
3 | ||
4 | routine chrout | |
5 | inputs a | |
6 | trashes a | |
7 | @ 65490 | |
8 | ||
9 | routine printa | |
10 | trashes a, z, n | |
11 | { | |
12 | ld a, 65 | |
13 | call chrout | |
14 | } | |
15 | ||
16 | routine printb | |
17 | trashes a, z, n | |
18 | { | |
19 | ld a, 66 | |
20 | call chrout | |
21 | } | |
22 | ||
23 | routine main | |
24 | trashes print, a, z, n | |
25 | { | |
26 | copy printa, print | |
27 | call print | |
28 | copy printb, print | |
29 | call print | |
30 | } |