git @ Cat's Eye Technologies SixtyPical / 2fdba72
Re-organize the example programs. Chris Pressey 3 years ago
52 changed file(s) with 987 addition(s) and 969 deletion(s). Raw diff Collapse all Expand all
+0
-6
eg/add-fail.60p less more
0 routine add_four
1 inputs a
2 outputs a
3 {
4 add a, 4
5 }
+0
-8
eg/add-pass.60p less more
0 routine main
1 inputs a
2 outputs a
3 trashes c, z, n, v
4 {
5 st off, c
6 add a, 4
7 }
+0
-9
eg/add-word.60p less more
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
-20
eg/bad-vector.60p less more
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
-15
eg/buffer.60p less more
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 byte screen @ 1024
1
2 routine main
3 trashes a, z, n, screen
4 {
5 ld a, 83
6 st a, screen
7 }
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
-18
eg/call.60p less more
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
-26
eg/conditional.60p less more
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
-25
eg/conditional2.60p less more
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
-10
eg/copy.60p less more
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
-14
eg/example.60p less more
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
-8
eg/forever.60p less more
0 routine main
1 trashes a, y, z, n, c
2 {
3 ld y, 65
4 repeat {
5 inc y
6 } forever
7 }
+0
-15
eg/goto.60p less more
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
-11
eg/if.60p less more
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
-44
eg/intr1.60p less more
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
-49
eg/joystick.60p less more
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
-16
eg/loop.p60 less more
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
-24
eg/memloc.p60 less more
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
-22
eg/new-style-routine.60p less more
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
-12
eg/print.60p less more
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
-488
eg/proto-game.60p less more
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 routine add_four
1 inputs a
2 outputs a
3 {
4 add a, 4
5 }
0 routine main
1 inputs a
2 outputs a
3 trashes c, z, n, v
4 {
5 st off, c
6 add a, 4
7 }
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 main
1 trashes a, y, z, n, c
2 {
3 ld y, 65
4 repeat {
5 inc y
6 } forever
7 }
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 print
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 print
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
-8
eg/screen1.60p less more
0 byte screen @ 1024
1
2 routine main
3 trashes a, z, n, screen
4 {
5 ld a, 83
6 st a, screen
7 }
+0
-16
eg/screen2.60p less more
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
-58
eg/vector-table.60p less more
0 //
1 // Demonstrates vector tables.
2 // Prints "AABAB".
3 //
4
5 vector routine
6 trashes a, z, n
7 print
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
-31
eg/vector.60p less more
0 vector routine
1 trashes a, z, n
2 print
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
-16
eg/word-table.60p less more
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 }