update_hud()1 void update_hud () {
2 if (game_mode == GAME_A) {
3 if (score [0] > hi_score) hi_score = score [0];
4 SMS_setTileatXY (6, 0, 0x1000 + 35);
5 SMS_setTile (0x1000 + 37);
6 SMS_setTile (0x1000 + 34);
7 write_big_num (9, 0, score [0]);
8 SMS_setTileatXY (15, 0, 0x1000 + 27);
9 SMS_setTile (0x1010 + plives [0]);
10 SMS_setTileatXY (18, 0, 0x1000 + 32);
11 SMS_setTile (0x1000 + 33);
12 SMS_setTile (0x1000 + 34);
13 write_big_num (21, 0, hi_score);
14 } else {
15 if (score [0] > hi_score) hi_score = score [0];
16 if (score [1] > hi_score) hi_score = score [1];
17 SMS_setTileatXY (0, 0, 0x1000 + 35);
18 SMS_setTile (0x1000 + 37);
19 SMS_setTile (0x1000 + 34);
20 write_big_num (3, 0, score [0]);
21 SMS_setTileatXY (9, 0, 0x1000 + 27);
22 SMS_setTile (0x1010 + plives [0]);
23 SMS_setTileatXY (12, 0, 0x1000 + 32);
24 SMS_setTile (0x1000 + 33);
25 SMS_setTile (0x1000 + 34);
26 write_big_num (15, 0, hi_score);
27 SMS_setTileatXY (21, 0, 0x1000 + 36);
28 SMS_setTile (0x1000 + 37);
29 SMS_setTile (0x1000 + 34);
30 write_big_num (24, 0, score [1]);
31 SMS_setTileatXY (30, 0, 0x1000 + 27);
32 SMS_setTile (0x1010 + plives [1]);
33 }
34 }
35
one_life_less(unsigned char p)36 void one_life_less (unsigned char p) {
37 if (plives [p]) plives [p] --;
38 }
39
init_rano()40 void init_rano () {
41 rx = rand () & 63;
42 ry = rand () & 63;
43 rmx = 1;
44 rmy = 1;
45 rframeam = 0;
46 }
47
move_rano()48 void move_rano () {
49 rx += rmx;
50 ry += rmy;
51 if (rx == 0 || rx == 240) rmx = -rmx;
52 if (ry == 0 || ry == 176) rmy = -rmy;
53
54 if (ppx [0] + 7 >= rx && ppx [0] < rx + 15 && ppy [0] + 7 >= ry && ppy [0] < ry + 15 && pactive [0]) {
55 pvx [0] = -pvx [0]; pvy [0] = -pvy [0];
56 rmx = -rmx; rmy = -rmy;
57 PSGSFXPlay (s_psg3 [tv_system], SFX_CHANNEL2);
58 one_life_less (0);
59 update_hud ();
60 }
61 if (game_mode == GAME_B) {
62 if (ppx [1] + 7 >= rx && ppx [1] < rx + 15 && ppy [1] + 7 >= ry && ppy [1] < ry + 15 && pactive [1]) {
63 pvx [1] = -pvx [1]; pvy [1] = -pvy [1];
64 rmx = -rmx; rmy = -rmy;
65 PSGSFXPlay (s_psg3 [tv_system], SFX_CHANNEL2);
66 one_life_less (1);
67 update_hud ();
68 }
69 }
70
71 if ((rand () & 7) == 3) rframeam = 1 - rframeam;
72
73 rframe = RBASE + (rframeam << 2);
74 }
75
draw_terrain()76 void draw_terrain () {
77 gpp = field;
78 SMS_setTileatXY (0, 0, (unsigned int) (*gpp ++));
79 gpint = 767; while (gpint --) SMS_setTile (*gpp ++);
80 }
81
attr(unsigned char x,unsigned char y)82 unsigned char attr (unsigned char x, unsigned char y) {
83 return field [x + (y << 5)];
84 }
85
init_moggys()86 void init_moggys () {
87 if (game_mode == GAME_A) {
88 ppx [0] = 124;
89 ppy [0] = 92;
90 px [0] = ppx [0] << 6;
91 py [0] = ppy [0] << 6;
92 pvx [0] = 0;
93 pvy [0] = 0;
94 pframe [0] = 0;
95 } else {
96 ppx [0] = 116;
97 ppy [0] = ppy [1] = 92;
98 ppx [1] = 132;
99
100 for (gpit = 0; gpit < 2; gpit ++) {
101 px [gpit] = ppx [gpit] << 6;
102 py [gpit] = ppy [gpit] << 6;
103 pvx [gpit] = 0;
104 pvy [gpit] = 0;
105 if (pactive [gpit]) pframe [gpit] = 0; else pframe [gpit] = 6;
106 }
107 }
108 }
109
eat(unsigned char p,unsigned char x,unsigned char y)110 void eat (unsigned char p, unsigned char x, unsigned char y) {
111 field [x + (y << 5)] = 7;
112 SMS_setTileatXY (x, y, 7);
113 friends [p] ++;
114 score [p] = score [p] + 1 + rano + level;
115 pframe [p] = 0;
116 update_hud ();
117 PSGSFXPlay (s_psg1 [tv_system], SFX_CHANNEL2);
118 }
119
die(unsigned char p,unsigned char x,unsigned char y)120 void die (unsigned char p, unsigned char x, unsigned char y) {
121 field [x + (y << 5)] = 7;
122 SMS_setTileatXY (x, y, 7);
123 one_life_less (p);
124 pframe [p] = 5;
125 update_hud ();
126 PSGSFXPlay (s_psg2 [tv_system], SFX_CHANNEL2);
127 }
128
collide_moggies(void)129 void collide_moggies (void) {
130 if (ppx [0] + 7 >= ppx [1] && ppx [0] <= ppx [1] + 7 &&
131 ppy [0] + 7 >= ppy [1] && ppy [0] <= ppy [1] + 7) {
132
133 // Momentum conservation law for equal masses
134 // Velocities just... swap! Rocket!!
135 aux = pvx [0]; pvx [0] = pvx [1]; pvx [1] = aux;
136 aux = pvy [0]; pvy [0] = pvy [1]; pvy [1] = aux;
137
138 // After collision, make sure they don't overlap
139 // In the most cheesy manner possible.
140 px [0] = pcx [0]; ppx [0] = px [0] >> 6;
141 py [0] = pcy [0]; ppy [0] = py [0] >> 6;
142 px [1] = pcx [1]; ppx [1] = px [1] >> 6;
143 py [1] = pcy [1]; ppy [1] = py [1] >> 6;
144 }
145 }
146
move_moggy(unsigned char p)147 void move_moggy (unsigned char p) {
148 pcx [p] = px [p];
149 pcy [p] = py [p];
150
151 if (!pactive [p]) {
152 pframe [p] = 6;
153 return;
154 }
155
156 gpint = SMS_getKeysStatus ();
157 phit = 0;
158
159 // =========================================================================
160 // H Axis
161 // =========================================================================
162
163 px [p] += pvx [p];
164 if (px [p] < 0) { px [p] = 0; pvx [p] = 0; }
165 if (px [p] > 15872) { px [p] = 15872; pvx [p] = 0; }
166
167 // Collision
168
169 ppx [p] = px [p] >> 6;
170 ppy [p] = py [p] >> 6;
171 ptx1 = (ppx [p] + 1) >> 3;
172 ptx2 = (ppx [p] + 6) >> 3;
173 pty1 = (ppy [p] + 1) >> 3;
174 pty2 = (ppy [p] + 6) >> 3;
175
176 if (pvx [p] < 0) {
177 // Collide left
178 pstop = 0;
179 switch (gpit = attr (ptx1, pty1)) {
180 case 5:
181 eat (p, ptx1, pty1);
182 break;
183 case 6:
184 die (p, ptx1, pty1);
185 break;
186 }
187 pstop = (gpit > 7);
188 switch (gpit = attr (ptx1, pty2)) {
189 case 5:
190 eat (p, ptx1, pty2);
191 break;
192 case 6:
193 die (p, ptx1, pty2);
194 break;
195 }
196 if (gpit > 7 || pstop) {
197 // Stop
198 ppx [p] = ((ptx1 + 1) << 3) - 1;
199 px [p] = ppx [p] << 6;
200 }
201 } else if (pvx [p] > 0) {
202 // Collide right
203 pstop = 0;
204 switch (gpit = attr (ptx2, pty1)) {
205 case 5:
206 eat (p, ptx2, pty1);
207 break;
208 case 6:
209 die (p, ptx2, pty1);
210 break;
211 }
212 pstop = (gpit > 7);
213 switch (gpit = attr (ptx2, pty2)) {
214 case 5:
215 eat (p, ptx2, pty2);
216 break;
217 case 6:
218 die (p, ptx2, pty2);
219 break;
220 }
221 if (gpit > 7 || pstop) {
222 // Stop
223 ppx [p] = ((ptx2 - 1) << 3) + 1;
224 px [p] = ppx [p] << 6;
225 }
226 }
227
228 // Read controller
229
230 if (gpint & player_controller_KEY_LEFT [p]) {
231 pframe [p] = 3;
232 if (pvx [p] > -PLAYER_MAX_V) pvx [p] -= PLAYER_A;
233 } else if (gpint & player_controller_KEY_RIGHT [p]) {
234 pframe [p] = 1;
235 if (pvx [p] < PLAYER_MAX_V) pvx [p] += PLAYER_A;
236 }
237
238 // =========================================================================
239 // V Axis
240 // =========================================================================
241
242 py [p] += pvy [p];
243 if (py [p] < 0) { py [p] = 0; pvy [p] = 0; }
244 if (py [p] > 11776) { py [p] = 11776; pvy [p] = 0; }
245
246 // Collision
247
248 ppx [p] = px [p] >> 6;
249 ppy [p] = py [p] >> 6;
250 ptx1 = (ppx [p] + 1) >> 3;
251 ptx2 = (ppx [p] + 6) >> 3;
252 pty1 = (ppy [p] + 1) >> 3;
253 pty2 = (ppy [p] + 6) >> 3;
254
255 if (pvy [p] < 0) {
256 // Collide up
257 pstop = 0;
258 switch (gpit = attr (ptx1, pty1)) {
259 case 5:
260 eat (p, ptx1, pty1);
261 break;
262 case 6:
263 die (p, ptx1, pty1);
264 break;
265 }
266 pstop = (gpit > 7);
267 switch (gpit = attr (ptx2, pty1)) {
268 case 5:
269 eat (p, ptx2, pty1);
270 break;
271 case 6:
272 die (p, ptx2, pty1);
273 break;
274 }
275 if (gpit > 7 || pstop) {
276 // Stop
277 ppy [p] = ((pty1 + 1) << 3) - 1;
278 py [p] = ppy [p] << 6;
279 }
280 } else if (pvy [p] > 0) {
281 // Collide down
282 pstop = 0;
283 switch (gpit = attr (ptx1, pty2)) {
284 case 5:
285 eat (p, ptx1, pty2);
286 break;
287 case 6:
288 die (p, ptx1, pty2);
289 break;
290 }
291 pstop = (gpit > 7);
292 switch (gpit = attr (ptx2, pty2)) {
293 case 5:
294 eat (p, ptx2, pty2);
295 break;
296 case 6:
297 die (p, ptx2, pty2);
298 break;
299 }
300 if (gpit > 7 || pstop) {
301 // Stop
302 ppy [p] = ((pty2 - 1) << 3) + 1;
303 py [p] = ppy [p] << 6;
304 }
305 }
306
307 // Read controller
308
309 if (gpint & player_controller_KEY_UP [p]) {
310 pframe [p] = 4;
311 if (pvy [p] > -PLAYER_MAX_V) pvy [p] -= PLAYER_A;
312 } else if (gpint & player_controller_KEY_DOWN [p]) {
313 pframe [p] = 2;
314 if (pvy [p] < PLAYER_MAX_V) pvy [p] += PLAYER_A;
315 }
316
317 }
318