chopper.ino 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #include <SPI.h>
  2. #include <GD.h>
  3. #include "chopper.h"
  4. #include "splitscreen.h"
  5. class Controller {
  6. public:
  7. void begin() {
  8. pinMode(3, INPUT);
  9. digitalWrite(3, HIGH);
  10. }
  11. byte read() {
  12. return (!digitalRead(3));
  13. }
  14. };
  15. static Controller Control;
  16. int atxy(int x, int y)
  17. {
  18. return (y << 6) + x;
  19. }
  20. // ----------------------------------------------------------------------
  21. // 7-segment display
  22. // copy a (w,h) rectangle from the source image (x,y) into picture RAM
  23. static void rect(unsigned int dst, byte x, byte y, byte w, byte h)
  24. {
  25. flash_uint8_t *src = desert_pic + (16 * y) + x;
  26. while (h--) {
  27. GD.copy(dst, src, w);
  28. dst += 64;
  29. src += 16;
  30. }
  31. }
  32. static void digit(uint16_t dst, byte d)
  33. {
  34. byte sx = 3 * (d % 5);
  35. byte sy = (d < 5) ? 32 : 36;
  36. rect(dst, sx, sy, 3, 4);
  37. }
  38. // ----------------------------------------------------------------------
  39. static void map(uint16_t dst, uint16_t src)
  40. {
  41. src &= 2047;
  42. int y = pgm_read_byte_near(roof + src);
  43. byte b;
  44. b = 0;
  45. while (y > -16) {
  46. draw_blocks(dst, y, b++, 4);
  47. y -= 16;
  48. }
  49. y = 256 - pgm_read_byte_near(foot + src);
  50. b = 0;
  51. while (y < 256) {
  52. draw_blocks(dst, y, b++, 0);
  53. y += 16;
  54. }
  55. }
  56. static void waitpress()
  57. {
  58. delay(200);
  59. while (!Control.read())
  60. ;
  61. delay(200);
  62. }
  63. void setup()
  64. {
  65. pinMode(6, INPUT);
  66. Control.begin();
  67. GD.begin();
  68. Serial.begin(1000000); // JCB
  69. GD.copy(PALETTE16A, chopper_palette, sizeof(chopper_palette));
  70. GD.copy(PALETTE16B, blocks_palette, sizeof(blocks_palette));
  71. GD.uncompress(RAM_SPRIMG, chopper_compressed);
  72. GD.uncompress(RAM_CHR, desert_chr_compressed);
  73. GD.uncompress(RAM_PAL, desert_pal_compressed);
  74. {
  75. flash_uint8_t *src = desert_pic;
  76. for (byte y = 0; y < 32; y++) {
  77. for (byte x = 0; x < 64; x += 16)
  78. GD.copy(atxy(x, y), src, 16);
  79. src += 16;
  80. }
  81. }
  82. byte blank = pgm_read_byte_near(desert_pic + (16 * 32));
  83. GD.fill(atxy(0,32), blank, 8 * 64);
  84. GD.microcode(splitscreen_code, sizeof(splitscreen_code));
  85. GD.wr16(COMM+0, 0); // far SCROLL_X
  86. GD.wr16(COMM+2, 0);
  87. GD.wr16(COMM+4, 120); // split at line 120
  88. GD.wr16(COMM+6, 0); // near SCROLL_X
  89. GD.wr16(COMM+8, 0);
  90. GD.wr16(COMM+10, 256); // turn sprites off at line 256
  91. GD.wr16(COMM+12, 0);
  92. GD.wr16(COMM+14, 0x8000 | 0);
  93. }
  94. void loop()
  95. {
  96. uint16_t f = 0 << 4;
  97. int y = 100 << 4;
  98. int yv = 0;
  99. byte dying = 0;
  100. char msg[6];
  101. while (dying < (3 * 72) || !Control.read()) {
  102. byte frame = (f & 1);
  103. if (Control.read())
  104. yv -= 3;
  105. yv++; // gravity
  106. if (!dying)
  107. y += yv;
  108. int x;
  109. if (!dying)
  110. x = f;
  111. int yp = y >> 4;
  112. GD.__wstartspr((frame ? 256 : 0));
  113. {
  114. int xm = (x >> 4);
  115. int xb = -(x & 15);
  116. for (int i = 0; i < 26; i++) {
  117. map(xb + (i << 4), xm + i);
  118. }
  119. sprintf(msg, "%04d", xm);
  120. }
  121. while (GD.spr != 248)
  122. GD.xhide();
  123. GD.__end();
  124. GD.__wstartspr((frame ? 256 : 0) + 248);
  125. if (!dying) {
  126. byte bf = min(max(0, yv >> 2), 3);
  127. draw_chopper(100, y >> 4, (2 * bf) + ((f >> 2) & 1), 0);
  128. // if ((yp < 16) || (268 < yp))
  129. // dying = 1;
  130. } else {
  131. draw_dead(100, yp, (~(f >> 2) & 3), 0);
  132. byte ef = dying >> 3;
  133. if (ef < 8)
  134. draw_explode(100, yp, ef, 0);
  135. dying = min((3 * 72), dying + 1);
  136. }
  137. while (GD.spr != 8)
  138. GD.xhide();
  139. GD.__end();
  140. GD.waitvblank();
  141. if (!dying && f > 0) {
  142. GD.__start(COLLISION + 248);
  143. for (byte i = 0; i < 4; i++) {
  144. byte c = SPI.transfer(0); // c is the colliding sprite number
  145. if (c != 0xff) {
  146. dying = 1;
  147. }
  148. }
  149. GD.__end();
  150. }
  151. GD.wr16(COMM+0, x >> 2); // far SCROLL_X
  152. GD.wr16(COMM+6, x >> 1); // near SCROLL_X
  153. GD.wr(SPR_PAGE, frame);
  154. if (dying) {
  155. byte v = max(0, 255 - dying * 6);
  156. GD.voice(0, 0, 220, v, v);
  157. GD.voice(1, 1, 220/8, v/2, v/2);
  158. } else {
  159. GD.voice(0, 0, 6 * 4000, 190, 0);
  160. GD.voice(0, 1, (f & 7) << 4, 0, 190);
  161. }
  162. digit(atxy(19, 32), msg[0] - '0');
  163. digit(atxy(22, 32), msg[1] - '0');
  164. digit(atxy(25, 32), msg[2] - '0');
  165. digit(atxy(28, 32), msg[3] - '0');
  166. f++;
  167. }
  168. }