1 /*
2 * Ported to the Ti82/83/83+ (rest will follow) by Henk Poley
3 * Extended with different sprite sizes and sound by Stefano Bodrato
4 *
5 * * * * * * *
6 *
7 * dstar.c
8 *
9 * DStar Z88 - C Demo
10 * Original TI game By A Von Dollen
11 * Converted to Z88 By D Morris
12 * Keys: Q,A,O,P,SPACE,H,G
13 *
14 * * * * * * *
15 *
16 * dstarz88 is a conversion of a TI86 game I found with
17 * source on www.ticalc.org.
18 *
19 * The original program was written by Andrew Von Dollen who
20 * in turn based it on a HP game by Joe W.
21 *
22 * The aim of the game is to collect all the clear bubbles by
23 * running over them. You control either the dark bubble or
24 * the solid box. The dark bubble is used to collect the clear
25 * bubbles, and the solid box is used as a sort of movable wall.
26 *
27 * Both objects carry on moving until they hit something else
28 * (except for the dark bubble in the case of clear bubbles).
29 *
30 * * * * * * *
31 *
32 * The keys are defined in #define statements, and default thus:
33 *
34 * Up: Q
35 * Down: A
36 * Left: O
37 * Right: P
38 * Quit: G
39 * Retry: H
40 * Switch: [SPACE]
41 *
42 * Switch changes between the dark bubble and the solid box.
43 *
44 *
45 * On the TI Calculators the keyboard mapping is:
46 *
47 * up,down,left,right - move ball/box
48 * [Enter] - toggle ball/box
49 * 7 - Quit
50 * 9 - Restart level
51 * +,- - CHEAT....
52 *
53 * * * * * * *
54 *
55 * This is the first game ever produced with the Small C compiler -
56 * it was written as a statement saying that it is possible to
57 * write something easily, quickly and efficiently using the
58 * compiler. Hopefully it will be an encouragement for others to
59 * do likewise!
60 *
61 * * * * * * *
62 *
63 * Compile examples :
64 *
65 * To get a TI82 version of the game (optionally you could add sound):
66 * zcc +ti82 -create-app dstar.c
67 *
68 * To get a TI85 version of the game (optionally you could add sound):
69 * zcc +ti85 -Dspritesize=7 -create-app dstar.c
70 *
71 * To get a Spectrum 16K version of the game:
72 * zcc +zx -Dspritesize=16 -DSOUND -create-app -zorg=24300 dstar.c
73 *
74 * To get a TS2068 HRG version of the game:
75 * zcc +ts2068 -startup=2 -Dspritesize=21 -DSOUND -create-app dstar.c
76 *
77 * To get a VZ200 version:
78 * zcc +vz -Dspritesize=7 -DSOUND -odztar.vz dstar.c
79 *
80 * TIKI1-100
81 * zcc +cpm -subtype=tiki100 -o dstar.com -Dspritesize=28 dstar.c
82 *
83 * MSXDOS:
84 * zcc +msx -Dspritesize=16 -DSOUND -startup=2 dstar.c
85 *
86 * MSX:
87 * zcc +msx -Dspritesize=16 -DSOUND -create-app dstar.c
88 *
89 * MULTI 8:
90 * zcc +multi8 -Dspritesize=21 -create-app dstar.c
91 *
92 * NEC PC-8801:
93 * zcc +pc88 -lgfxpc88 -create-app -DSOUND -Dspritesize=10 dstar.c
94 * zcc +pc88 -lgfxpc88hr200 -create-app -lm -Dspritemem=102 -DSOUND dstar.c
95 *
96 * Robotron KC:
97 * zcc +z9001 -Dspritesize=20 -DSOUND -lgfx9001krt -create-app dstar.c
98 * zcc +kc -Dspritesize=20 -create-app dstar.c
99 *
100 * Sharp PC-G850:
101 * zcc +g800 -clib=g850 -Dspritesize=5 -create-app -DSOUND dstar.c
102 *
103 * SPC-1000:
104 * zcc +spc1000 -Dspritesize=16 -create-app dstar.c
105 *
106 * Commodore 128:
107 * zcc +c128 -lgfx128hr -create-app -lm -Dspritesize=21 dstar.c
108 *
109 * ZX81, various HRG flavours (see also the specific target version):
110 * zcc +zx81 -O3 -clib=mt -create-app -Dspritesize=15 dstar.c
111 * zcc +zx81 -O3 -clib=g007 -create-app -Dspritesize=16 dstar.c
112 * zcc +zx81 -O3 -clib=arx -subtype=arx -create-app -Dspritesize=16 dstar.c
113 * zcc +zx81 -O3 -clib=wrx -subtype=wrx -create-app -Dspritesize=16 dstar.c
114 *
115 * To get an 80 pixel graphics version of the game (Mattel Aquarius, TRS80, etc):
116 * zcc +aquarius -Dspritesize=5 -create-app dstar.c
117 *
118 * Even smaller version of the game:
119 * zcc +gal -Dspritesize=4 -create-app dstar.c
120 *
121 * (in the above examples the sprite size can be set to 4,5,6,7,8 or 16
122 * and sound can optionally be added with some target)
123 *
124 * * * * * * *
125 *
126 * Enough twaddle, enjoy the game and study the source!
127 *
128 * d. <djm@jb.man.ac.uk> 1/12/98
129 *
130 * * * * * * *
131 */
132
133 #include <stdio.h>
134 #include <games.h>
135 #include <stdlib.h>
136 #include <graphics.h>
137
138 #ifdef SOUND
139 #include <sound.h>
140 #endif
141 #ifdef SOUNDB
142 #include <sound.h>
143 #endif
144
145
146 /* #define spritesize 4 --> minimalistic, 64x36 pixels */
147 /* #define spritesize 5 --> very low resolutions, 80x45 pixels */
148 /* #define spritesize 6 --> TI mode, 96x54 */
149 /* #define spritesize 7 --> TI85/86, VZ200 */
150 /* #define spritesize 8 --> 128x72 pixels */
151 /* #define spritesize 10 --> 160x90 pixels */
152 /* #define spritesize 14 --> Medium screen mode 224x126 */
153 /* #define spritesize 16 --> Big screen mode 256x144 */
154 /* #define spritesize 20 --> Wide screen mode 320x160 */
155 /* #define spritesize 21 --> Wide screen mode 512x192 */
156 /* #define spritemem 102 --> 640x200 */
157 /* #define spritesize 28 --> Extra wide screen mode 1024x256 */
158
159
160 /* Single sprite memory usage, including bytes for its size */
161 #if (spritesize == 10)
162 #define spritemem 22
163 #endif
164 #if (spritesize == 14)
165 #define spritemem 30
166 #endif
167 #if (spritesize == 15)|(spritesize == 16)
168 #define spritemem 34
169 #endif
170 #if (spritesize == 20)
171 #define spritemem 62
172 #define xsize 20
173 #endif
174 #if (spritemem == 102) // 640x200
175 #define spritesize 20
176 #define xsize 40
177 #endif
178 #if (spritesize == 21)
179 #define spritemem 90
180 #define xsize 32
181 #endif
182 #if (spritesize == 28)
183 #define spritemem 226
184 #define xsize 64
185 #endif
186
187 #ifndef spritemem
188 #define spritemem (spritesize+2)
189 #endif
190
191 #ifndef spritesize
192 #define spritesize 6
193 #endif
194
195
196 #include "dstar.h"
197
198
199 #ifdef __TIKI100__
200 #include "tiki100.h"
201 #endif
202
203
main()204 void main()
205 {
206 Level = (STARTLEV-1);
207 SetupLevel(); /* Display the first level */
208
209 /* Loop keyhandler till you finished the game */
210 while (CheckNotFinished())
211 Gamekeys();
212 }
213
214
Gamekeys(void)215 void Gamekeys(void)
216 {
217 char *charptr;
218
219 /* Set up a pointer to the variable we want to change
220 * (either the box or the ball) */
221 charptr = PieceIsBall ? &BoxOffset : &BallOffset;
222
223 switch(getk())
224 {
225 case K_DOWN:
226 MovePiece(charptr,0,+1);
227 break;
228 case K_UP:
229 MovePiece(charptr,0,-1);
230 break;
231 case K_RIGHT:
232 MovePiece(charptr,+1,0);
233 break;
234 case K_LEFT:
235 MovePiece(charptr,-1,0);
236 break;
237 case K_SWITCH:
238 PieceIsBall^=1; /* Toggle ball/box */
239 #ifdef SOUND
240 bit_fx4 (5);
241 #endif
242 #ifdef SOUNDB
243 bit_fx6 (6);
244 #endif
245 while (getk() == K_SWITCH) {}
246 break;
247 case K_EXIT:
248 #ifdef SOUNDB
249 bit_fx6 (4);
250 #endif
251 exit(0);
252 case K_NEXTLEV: /* Okay this IS cheating... */
253 if(++Level==MAXLEVEL)
254 { --Level; break; }
255 SetupLevel();
256 break;
257 case K_PREVLEV:
258 if(--Level==-1)
259 { ++Level; break; }
260 /* fall thrue */
261 case K_CLEAR:
262 #ifdef SOUND
263 bit_fx4 (3);
264 #endif
265 #ifdef SOUNDB
266 bit_fx6 (1);
267 #endif
268 SetupLevel();
269 }
270 }
271
272
273 /* The level is stored 'compressed', taking up 38 bytes a time.
274 * byte 0 - position of ball
275 * byte 1 - position of box
276 * 2-37 - Level data
277 *
278 * Level data is stored as two bits per block, so we have to shift our
279 * picked up byte round to get it.
280 */
SetupLevel(void)281 void SetupLevel(void)
282 {
283 int x;
284 char *ptr,*ptr2;
285
286 /* Fresh level, so start with the ball */
287 PieceIsBall = FALSE;
288
289 ptr2 = Board; /* We copy to the Board */
290 ptr = levels + (Level * 38); /* from the Level data */
291
292 /* First two bytes are the ball and the box position */
293 BallOffset = *ptr++;
294 BoxOffset = *ptr++;
295
296 /* Decompress Level into the Board */
297 for (x=0; x!=36; x++)
298 {
299 *ptr2++=((*ptr)>>6)&3;
300 *ptr2++=((*ptr)>>4)&3;
301 *ptr2++=((*ptr)>>2)&3;
302 *ptr2++=( *ptr) &3;
303 ptr++;
304 }
305
306 /* Put the ball and box into their Board position */
307 *(Board+BallOffset) = BALL;
308 *(Board+BoxOffset) = BOX;
309
310 DrawBoard(); /* Display the clean Board */
311
312 #ifdef SOUND
313 bit_fx4 (1);
314 #endif
315 #ifdef SOUNDB
316 bit_fx6 (0);
317 #endif
318 }
319
320
DrawBoard(void)321 void DrawBoard(void)
322 {
323 int x,y;
324 char *ptr;
325
326 ptr = Board;
327
328 #ifdef __TIKI100__
329 gr_defmod(1);
330 #endif
331
332 clg(); /* clear the screen */
333
334 for (y=0 ; y!=9 ; y++)
335 {
336 for (x=0 ; x!=16 ; x++)
337 {
338 #ifdef xsize
339 putsprite(spr_or,(x*xsize),(y*spritesize),sprites + (spritemem * (*ptr++)));
340 #else
341 putsprite(spr_or,(x*spritesize),(y*spritesize),sprites + (spritemem * (*ptr++)));
342 #endif
343 }
344 }
345 }
346
347
348
349 /* Check if a Level is (not) finished:
350 * There are 144 squares in each Level
351 *
352 * Note the use of != instead of < or <=
353 * - this is faster to execute on the Z80!
354 */
CheckNotFinished(void)355 char CheckNotFinished(void)
356 {
357 char *ptr;
358 int i;
359
360 ptr = Board;
361 for(i=1 ; i!=144 ; i++)
362 {
363 if(*ptr++ == BUBB) return(TRUE); /* Are there any bubbles? */
364 }
365 if(++Level == MAXLEVEL) return(FALSE); /* All levels done? */
366
367 SetupLevel(); /* If not => Next Level! */
368 return(TRUE); /* And keep scanning keys */
369 }
370
371
372 /* Check to see if we're running into anything:
373 * - The box stops for everything (exept empty space [= 0])
374 * - The ball stops for everything exept a bubble
375 */
TestNextPosIsStop(char nextpos)376 char TestNextPosIsStop(char nextpos)
377 {
378 if(!PieceIsBall)
379 if (nextpos==BUBB) return(FALSE);
380 return(nextpos);
381 }
382
383
MovePiece(char * ptr,char plusx,char plusy)384 void MovePiece(char *ptr, char plusx, char plusy)
385 {
386 char *locn;
387 char temp,temp2;
388 int x,y;
389
390 temp = PieceIsBall + 3;
391 temp2 = (plusx + (plusy * 16));
392
393 while(1) /* loop */
394 {
395
396 locn = *(ptr) + Board;
397 if(TestNextPosIsStop(*(locn+temp2))) return; /* till edge */
398
399 y = (*(ptr) / 16);
400 #ifdef xsize
401 x = (*(ptr) - (y * 16)) * xsize;
402 #else
403 x = (*(ptr) - (y * 16)) * spritesize;
404 #endif
405 y *= spritesize;
406
407 if(*(locn+temp2)==BUBB)
408 {
409 #ifdef xsize
410 putsprite(spr_xor,x+(plusx*xsize),y+(plusy*spritesize),sprites + (spritemem * BUBB));
411 #else
412 putsprite(spr_xor,x+(plusx*spritesize),y+(plusy*spritesize),sprites + (spritemem * BUBB));
413 #endif
414
415 #ifdef SOUND
416 bit_fx2 (5);
417 #endif
418 #ifdef SOUNDB
419 bit_fx6 (3);
420 #endif
421 }
422
423 *(locn+temp2) = *locn;
424 *locn = 0;
425
426 /* remove old */
427 putsprite(spr_xor,x,y,sprites + (spritemem * temp));
428 /* put new */
429 #ifdef xsize
430 putsprite(spr_xor,x+(plusx*xsize),y+(plusy*spritesize),sprites + (spritemem * temp));
431 #else
432 putsprite(spr_xor,x+(plusx*spritesize),y+(plusy*spritesize),sprites + (spritemem * temp));
433 #endif
434
435 #ifdef SOUND
436 bit_fx2 (2);
437 #endif
438 #ifdef SOUNDB
439 bit_fx6 (7);
440 #endif
441
442 (*ptr) += temp2;
443 }
444 }
445