1 #include <stdlib.h>
2 #include <sms.h>
3
4 unsigned char pal1[] = {0x00, 0x01, 0x02, 0x03, 0x10, 0x20, 0x30, 0x2B,
5 0x14, 0x24, 0x39, 0x0F, 0x00, 0x15, 0x2A, 0x3F};
6
7 unsigned char pal2[] = {0x00, 0x01, 0x02, 0x03, 0x10, 0x20, 0x30, 0x2B,
8 0x15, 0x35, 0x1D, 0x3D, 0x00, 0x15, 0x2A, 0x3F};
9
10 unsigned int bkg_bottom[] = {0x000F, 0x000F, 0x000F, 0x0010, 0x000F, 0x000F, 0x000F, 0x0010,
11 0x000F, 0x000F, 0x0010, 0x000F, 0x000F, 0x000F, 0x0010, 0x000F,
12 0x000F, 0x0010, 0x000F, 0x000F, 0x000F, 0x0010, 0x000F, 0x000F,
13 0x0010, 0x000F, 0x000F, 0x000F, 0x0010, 0x000F, 0x000F, 0x000F,};
14
15 unsigned int bkg_top1[] = {0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
16 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
17 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
18 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0015,};
19
20 unsigned int bkg_top2[] = {0x0011, 0x0013, 0x0013, 0x0012, 0x0013, 0x0013, 0x0013, 0x0012,
21 0x0013, 0x0013, 0x0012, 0x0013, 0x0013, 0x0013, 0x0012, 0x0013,
22 0x0013, 0x0012, 0x0013, 0x0013, 0x0013, 0x0012, 0x0013, 0x0013,
23 0x0012, 0x0013, 0x0013, 0x0013, 0x0012, 0x0013, 0x0013, 0x0011,};
24
25 unsigned int lplayer_icons[] = {0x017, 0x019};
26 unsigned int rplayer_icons[] = {0x018, 0x01A, 0x01B, 0x01C};
27 unsigned int paddle_icons[] = {0x01D, 0x01E, 0x01F};
28 unsigned int spin_icons[] = {0x021, 0x020};
29
30 extern unsigned char pong_graphics[];
31
32 typedef struct {
33 int x;
34 int y;
35 int size;
36 int height;
37 int controlled_by;
38 int base_spr;
39 int base_tile;
40 int spd_x;
41 int spd_y;
42 int top_spd;
43 int accel;
44 int friction;
45 } paddle_rec;
46
47 typedef struct {
48 int x;
49 int y;
50 int base_spr;
51 int base_tile;
52 int spd_x;
53 int spd_y;
54 int base_spd;
55 int top_spd;
56 int spin;
57 int spin_friction;
58 } ball_rec;
59
60 typedef struct {
61 int top;
62 int bottom;
63 int left;
64 int right;
65 int score0;
66 int score1;
67 int left_player;
68 int right_player;
69 int paddle_mode;
70 int actual_paddle_count;
71 int spin_on;
72 } playfield_rec;
73
sig_shr(int number,int shift)74 int sig_shr(int number, int shift) {
75 if (number < 0) {
76 return -((-number) >> shift);
77 } else {
78 return number >> shift;
79 }
80 }
81
wait_joy1_release()82 int wait_joy1_release() {
83 while (read_joypad1()) {
84 wait_vblank_noint();
85 }
86 }
87
draw_score_digits(int x,int y,int n)88 void draw_score_digits(int x, int y, int n) {
89 unsigned int buffer[2];
90 buffer[0] = (n / 10) + 1;
91 buffer[1] = (n % 10) + 1;
92 set_bkg_map(buffer, x, y, 2, 1);
93 }
94
draw_option_panel(int x,int y,playfield_rec * playfield)95 void draw_option_panel(int x, int y, playfield_rec *playfield) {
96 unsigned int buffer[4];
97 unsigned int *p;
98 p = buffer;
99 *p = lplayer_icons[playfield->left_player];
100 p++;
101 *p = rplayer_icons[playfield->right_player];
102 p++;
103 *p = paddle_icons[playfield->paddle_mode];
104 p++;
105 *p = spin_icons[playfield->spin_on];
106 set_bkg_map(buffer, x, y, 4, 1);
107 }
108
draw_score(playfield_rec * playfield)109 void draw_score(playfield_rec *playfield) {
110 draw_score_digits(4, 0, playfield->score0);
111 draw_score_digits(26, 0, playfield->score1);
112 draw_option_panel(14, 0, playfield);
113 }
114
draw_bkg()115 void draw_bkg() {
116 set_bkg_map(bkg_top1, 0, 0, 32, 1);
117 set_bkg_map(bkg_top2, 0, 1, 32, 1);
118 set_bkg_map(bkg_bottom, 0, 23, 32, 1);
119 }
120
draw_paddle(paddle_rec * paddle)121 void draw_paddle(paddle_rec *paddle) {
122 int x = (paddle->x >> 4);
123 int y = (paddle->y >> 4);
124 int spr = paddle->base_spr;
125 int tile = paddle->base_tile;
126 int i;
127
128 set_sprite(spr, x, y, tile);
129 y += 8; spr++; tile++;
130 for (i = paddle->size; i; i--, y += 8, spr++) {
131 set_sprite(spr, x, y, tile);
132 }
133 tile++;
134 set_sprite(spr, x, y, tile);
135 }
136
draw_paddles(paddle_rec * paddles,int count)137 void draw_paddles(paddle_rec *paddles, int count) {
138 for (; count; count--, paddles++) {
139 draw_paddle(paddles);
140 }
141 }
142
handle_paddle_joypad(int joy,paddle_rec * paddle)143 void handle_paddle_joypad(int joy, paddle_rec *paddle) {
144 if (joy & JOY_UP) {
145 paddle->spd_y -= paddle->accel;
146 }
147 if (joy & JOY_DOWN) {
148 paddle->spd_y += paddle->accel;
149 }
150 }
151
handle_paddle_joypad_lr(int joy,paddle_rec * paddle)152 void handle_paddle_joypad_lr(int joy, paddle_rec *paddle) {
153 if (joy & JOY_LEFT) {
154 paddle->spd_y -= paddle->accel;
155 }
156 if (joy & JOY_RIGHT) {
157 paddle->spd_y += paddle->accel;
158 }
159 }
160
handle_paddle_ai(paddle_rec * paddle,ball_rec * ball)161 void handle_paddle_ai(paddle_rec *paddle, ball_rec *ball) {
162 int h = paddle->height >> 1;
163 int y = paddle->y + h;
164
165 if (ball->spd_x < 0) {
166 return;
167 }
168
169 if (y > ball->y) {
170 paddle->spd_y -= paddle->accel;
171 } else if (y < ball->y) {
172 paddle->spd_y += paddle->accel;
173 }
174 }
175
handle_paddle_physics(paddle_rec * paddle,playfield_rec * playfield)176 void handle_paddle_physics(paddle_rec *paddle, playfield_rec *playfield) {
177 paddle->x += paddle->spd_x;
178 paddle->y += paddle->spd_y;
179
180 if (paddle->spd_y < -paddle->top_spd) {
181 paddle->spd_y = -paddle->top_spd;
182 } else if (paddle->spd_y > paddle->top_spd) {
183 paddle->spd_y = paddle->top_spd;
184 }
185
186 /* if (paddle->x < playfield->left) {
187 paddle->x = playfield->left;
188 paddle->spd_x = -paddle->spd_x;
189 }
190 if (paddle->x > playfield->right-8) {
191 paddle->x = playfield->right-8;
192 paddle->spd_x = -paddle->spd_x;
193 } */
194
195 if (paddle->y < playfield->top) {
196 paddle->y = playfield->top;
197 paddle->spd_y = -paddle->spd_y;
198 }
199 if (paddle->y > playfield->bottom-paddle->height) {
200 paddle->y = playfield->bottom-paddle->height;
201 paddle->spd_y = -paddle->spd_y;
202 }
203
204 /* if (paddle->spd_x > 0) {
205 if (paddle->spd_x > paddle->friction) {
206 paddle->spd_x -= paddle->friction;
207 } else {
208 paddle->spd_x = 0;
209 }
210 } else {
211 if (paddle->spd_x < -paddle->friction) {
212 paddle->spd_x += paddle->friction;
213 } else {
214 paddle->spd_x = 0;
215 }
216 }*/
217
218 if (paddle->spd_y > 0) {
219 if (paddle->spd_y > paddle->friction) {
220 paddle->spd_y -= paddle->friction;
221 } else {
222 paddle->spd_y = 0;
223 }
224 } else {
225 if (paddle->spd_y < -paddle->friction) {
226 paddle->spd_y += paddle->friction;
227 } else {
228 paddle->spd_y = 0;
229 }
230 }
231 }
232
draw_ball(ball_rec * ball)233 void draw_ball(ball_rec *ball) {
234 int x = (ball->x >> 4);
235 int y = (ball->y >> 4);
236 int spr = ball->base_spr;
237 int tile = ball->base_tile;
238
239 set_sprite(spr, x, y, tile);
240 }
241
deploy_ball(ball_rec * ball)242 void deploy_ball(ball_rec *ball) {
243 ball->x = 128 << 4;
244 ball->y = 32 << 4;
245 ball->base_spr = 12;
246 ball->base_tile = 14;
247 if (rand() & 0x01) {
248 ball->spd_x = 0x18;
249 } else {
250 ball->spd_x = -0x18;
251 }
252 ball->spd_y = (rand() & 0x3F) - 0x20;
253 ball->base_spd = 0x20;
254 ball->top_spd = 0x60;
255 ball->spin = 0;
256 ball->spin_friction = 0x01;
257 }
258
handle_ball_physics(ball_rec * ball,playfield_rec * playfield,paddle_rec paddles[],int paddle_count)259 void handle_ball_physics(ball_rec *ball, playfield_rec *playfield, paddle_rec paddles[], int paddle_count) {
260 int i;
261 int collided;
262 paddle_rec *paddle;
263
264 ball->x += ball->spd_x;
265 ball->y += ball->spd_y;
266
267 ball->spd_y -= sig_shr(ball->spin, 3);
268 if (ball->spin > 0) {
269 if (ball->spin > ball->spin_friction) {
270 ball->spin -= ball->spin_friction;
271 } else {
272 ball->spin = 0;
273 }
274 } else {
275 if (ball->spin < -ball->spin_friction) {
276 ball->spin += ball->spin_friction;
277 } else {
278 ball->spin = 0;
279 }
280 }
281
282 if (ball->spd_x < 0) {
283 if (ball->spd_x < -ball->top_spd) {
284 ball->spd_x = -ball->top_spd;
285 }
286 } else {
287 if (ball->spd_x > ball->top_spd) {
288 ball->spd_x = ball->top_spd;
289 }
290 }
291
292 if (ball->x < playfield->left) {
293 ball->x = playfield->left;
294 ball->spd_x = -ball->spd_x;
295 playfield->score0++;
296 deploy_ball(ball);
297 draw_score(playfield);
298 }
299 if (ball->x > playfield->right-8) {
300 ball->x = playfield->right-8;
301 ball->spd_x = -ball->spd_x;
302 playfield->score1++;
303 deploy_ball(ball);
304 draw_score(playfield);
305 }
306
307 if (ball->spd_y < 0) {
308 if (ball->spd_y < -ball->top_spd) {
309 ball->spd_y = -ball->top_spd;
310 }
311 } else {
312 if (ball->spd_y > ball->top_spd) {
313 ball->spd_y = ball->top_spd;
314 }
315 }
316
317 if (ball->y < playfield->top) {
318 ball->y = playfield->top;
319 ball->spd_y = -ball->spd_y;
320 }
321 if (ball->y > playfield->bottom-0x80) {
322 ball->y = playfield->bottom-0x80;
323 ball->spd_y = -ball->spd_y;
324 }
325
326 for (i = paddle_count, paddle = paddles; i; i--, paddle++) {
327 if ((ball->y > paddle->y - 0x80) && (ball->y < paddle->y + paddle->height)) {
328 collided = 0;
329 if (ball->spd_x < 0) {
330 if ((ball->x < paddle->x + 0x80) && (ball->x > paddle->x)) {
331 ball->x = paddle->x + 0x80;
332 ball->spd_x = -ball->spd_x;
333 ball->spd_x += 0x02;
334 ball->spin = paddle->spd_y/* + sig_shr(paddle->spd_y, 1)*/;
335 collided = 1;
336 }
337 } else {
338 if ((ball->x < paddle->x) && (ball->x > paddle->x - 0x80)) {
339 ball->x = paddle->x - 0x80;
340 ball->spd_x = -ball->spd_x;
341 ball->spd_x -= 0x02;
342 ball->spin = paddle->spd_y/* + sig_shr(paddle->spd_y, 1)*/;
343 collided = 1;
344 }
345 }
346 if (collided) {
347 if (ball->y < paddle->y) {
348 ball->spd_y -= 0x60;
349 } else if (ball->y > paddle->y + paddle->height - 0x80) {
350 ball->spd_y += 0x60;
351 }
352
353 if (!playfield->spin_on) {
354 ball->spin = 0;
355 }
356 }
357 }
358 }
359 }
360
setup_paddles(paddle_rec * paddles,playfield_rec * playfield)361 void setup_paddles(paddle_rec *paddles, playfield_rec *playfield) {
362 paddle_rec *paddle;
363 int x, xinc;
364 int i;
365 int half_paddle_count;
366 int base_spr = 0;
367 int base_tile = 11;
368 int paddle_size = 2;
369 int max_speed = 0x60;
370 int controlled_by = 0;
371
372 playfield->actual_paddle_count = 2;
373 if (playfield->paddle_mode == 1) {
374 playfield->actual_paddle_count = 4;
375 }
376 if (playfield->left_player == 1) {
377 playfield->actual_paddle_count <<= 1;
378 }
379 half_paddle_count = playfield->actual_paddle_count >> 1;
380
381 if (playfield->paddle_mode == 2) {
382 paddle_size = 3;
383 }
384
385 for (i = 0, paddle = paddles; i != playfield->actual_paddle_count; i++, paddle++) {
386 paddle->y = 80 << 4;
387 paddle->size = paddle_size;
388 paddle->height = (paddle->size + 2) << 7;
389 paddle->base_spr = base_spr;
390 paddle->base_tile = base_tile;
391 paddle->spd_x = 0;
392 paddle->spd_y = 0;
393 paddle->top_spd = max_speed;
394 paddle->accel = 0x0E;
395 paddle->friction = 0x06;
396
397 base_spr += paddle_size+2;
398 }
399
400 xinc = 32;
401 if (half_paddle_count > 2) {
402 xinc = 16;
403 }
404 xinc <<= 4;
405
406 x = 8 << 4;
407 controlled_by = 0;
408 for (i = 0, paddle = paddles; i != half_paddle_count; i++, paddle++) {
409 paddle->x = x;
410 paddle->controlled_by = controlled_by;
411
412 x += xinc;
413 if (playfield->left_player == 1) {
414 controlled_by++;
415 } else {
416 controlled_by = (controlled_by + 2) & 0x03;
417 }
418 }
419
420 controlled_by = 4;
421 switch (playfield->right_player) {
422 case 0:
423 controlled_by = 1;
424 break;
425
426 case 1:
427 max_speed = 0x40;
428 break;
429
430 case 2:
431 max_speed = 0x80;
432 break;
433 }
434
435 x = 240 << 4;
436 for (i = 0; i != half_paddle_count; i++, paddle++) {
437 paddle->x = x;
438 paddle->controlled_by = controlled_by;
439 paddle->top_spd = max_speed;
440
441 x -= xinc;
442 if (playfield->left_player == 0) {
443 controlled_by = (controlled_by + 2) & 0x03;
444 }
445 }
446 }
447
select_options(paddle_rec * paddles,playfield_rec * playfield)448 void select_options(paddle_rec *paddles, playfield_rec *playfield) {
449 int done;
450 int joy1;
451 int incr, lim;
452 int col = 0;
453 int blink = 0;
454
455 done = 0;
456 while(!done) {
457 joy1 = read_joypad1();
458 incr = 0;
459 if (joy1 & (JOY_FIREA | JOY_FIREB)) {
460 done = 1;
461 } else if (joy1 & JOY_LEFT) {
462 col--;
463 } else if (joy1 & JOY_RIGHT) {
464 col++;
465 } else if (joy1 & JOY_UP) {
466 incr = 1;
467 } else if (joy1 & JOY_DOWN) {
468 incr = -1;
469 }
470
471 if (incr != 0) {
472 switch (col) {
473 case 0:
474 playfield->left_player += incr;
475 playfield->left_player &= 0x01;
476 break;
477
478 case 1:
479 playfield->right_player += incr;
480 playfield->right_player &= 0x03;
481 break;
482
483 case 2:
484 playfield->paddle_mode += incr;
485 if (playfield->paddle_mode < 0) {
486 playfield->paddle_mode = 2;
487 } else if (playfield->paddle_mode > 2) {
488 playfield->paddle_mode = 0;
489 }
490 break;
491
492 case 3:
493 playfield->spin_on += incr;
494 playfield->spin_on &= 0x01;
495 break;
496 }
497 draw_score(playfield);
498 setup_paddles(paddles, playfield);
499 draw_paddles(paddles, playfield->actual_paddle_count);
500 }
501
502 col &= 0x03;
503
504 wait_vblank_noint();
505 if (blink & 0x10) {
506 set_sprite(63, 0, -16, 1);
507 } else {
508 set_sprite(63, (col + 14) << 3, 0, 0x16);
509 }
510
511 if (joy1) {
512 wait_joy1_release();
513 }
514
515 blink++;
516 }
517 set_sprite(63, 0, -16, 1);
518 }
519
main()520 void main() {
521 int joy1, joy2;
522 int i;
523 playfield_rec playfield;
524 paddle_rec paddles[8], *paddle;
525 ball_rec ball;
526
527 playfield.top = 16 << 4;
528 playfield.bottom = 184 << 4;
529 playfield.left = 0 << 4;
530 playfield.right = 255 << 4;
531 playfield.score0 = 0;
532 playfield.score1 = 0;
533 playfield.left_player = 0;
534 playfield.right_player = 2;
535 playfield.paddle_mode = 0;
536 playfield.actual_paddle_count = 1;
537 playfield.spin_on = 1;
538
539 setup_paddles(paddles, &playfield);
540
541 clear_vram();
542 load_tiles(pong_graphics, 1, 64, 4);
543 load_palette(pal1, 0, 16);
544 load_palette(pal2, 16, 16);
545
546 for (i = 0; i != 64; i++) {
547 set_sprite(i, 0, -16, 0);
548 }
549
550 set_vdp_reg(VDP_REG_FLAGS1, VDP_REG_FLAGS1_BIT7 | VDP_REG_FLAGS1_SCREEN);
551 while (1) {
552 draw_bkg();
553 draw_score(&playfield);
554 draw_paddles(paddles, playfield.actual_paddle_count);
555
556 select_options(paddles, &playfield);
557
558 deploy_ball(&ball);
559 for (;;) {
560 /* joy1 = read_joypad1();
561 handle_paddle_joypad(joy1, paddle);
562 handle_paddle_physics(paddle, &playfield);
563
564 paddle++;
565 joy2 = read_joypad2();
566 // handle_paddle_joypad(joy2, paddle);
567 handle_paddle_ai(paddle, &ball);
568 handle_paddle_physics(paddle, &playfield);*/
569 joy1 = read_joypad1();
570 joy2 = read_joypad2();
571
572 for (i = 0, paddle = paddles; i != playfield.actual_paddle_count; i++, paddle++) {
573 switch (paddle->controlled_by) {
574 case 0:
575 handle_paddle_joypad(joy1, paddle);
576 break;
577
578 case 1:
579 handle_paddle_joypad(joy2, paddle);
580 break;
581
582 case 2:
583 handle_paddle_joypad_lr(joy1, paddle);
584 break;
585
586 case 3:
587 handle_paddle_joypad_lr(joy2, paddle);
588 break;
589
590 default:
591 handle_paddle_ai(paddle, &ball);
592 }
593 }
594
595 handle_ball_physics(&ball, &playfield, paddles, playfield.actual_paddle_count);
596
597 for (i = 0, paddle = paddles; i != playfield.actual_paddle_count; i++, paddle++) {
598 handle_paddle_physics(paddle, &playfield);
599 }
600
601 wait_vblank_noint();
602 draw_paddles(paddles, playfield.actual_paddle_count);
603 /* for (i = 0, paddle = paddles; i != playfield.actual_paddle_count; i++, paddle++) {
604 draw_paddle(paddle);
605 }*/
606 draw_ball(&ball);
607 }
608 }
609 }
610