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