watterott.ino 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include <SPI.h>
  2. #include <GD.h>
  3. // ----------------------------------------------------------------------
  4. // qrand: quick random numbers
  5. // ----------------------------------------------------------------------
  6. static uint16_t lfsr = 1;
  7. static void qrandSeed(int seed)
  8. {
  9. if (seed) {
  10. lfsr = seed;
  11. } else {
  12. lfsr = 0x947;
  13. }
  14. }
  15. static byte qrand1() // a random bit
  16. {
  17. lfsr = (lfsr >> 1) ^ (-(lfsr & 1) & 0xb400);
  18. return lfsr & 1;
  19. }
  20. static byte qrand(byte n) // n random bits
  21. {
  22. byte r = 0;
  23. while (n--)
  24. r = (r << 1) | qrand1();
  25. return r;
  26. }
  27. // ----------------------------------------------------------------------
  28. #include "watterott_logo.h"
  29. #include "bgstripes.h"
  30. int focusx, focusy;
  31. // JCB-PARTICLE-A
  32. #define NSPR 200
  33. struct spr {
  34. int x, y;
  35. signed char vx, vy;
  36. } sprites[NSPR];
  37. static void born(byte i)
  38. {
  39. sprites[i].x = focusx + qrand(4);
  40. sprites[i].y = focusy -16 + qrand(5);
  41. sprites[i].vx = -8 + qrand(4);
  42. sprites[i].vy = -qrand(4) - 1;
  43. }
  44. static void kill(byte i)
  45. {
  46. sprites[i].y = 309;
  47. sprites[i].vx = 0;
  48. sprites[i].vy = 0;
  49. }
  50. // JCB-PARTICLE-B
  51. int atxy(int x, int y)
  52. {
  53. return (y << 6) + x;
  54. }
  55. static byte sprcnt = 0;
  56. void setup()
  57. {
  58. GD.begin();
  59. Serial.begin(1000000); // JCB
  60. // Black-to-gray transition starting at line 150
  61. GD.microcode(bgstripes_code, sizeof(bgstripes_code));
  62. GD.wr16(COMM+0, 112);
  63. GD.uncompress(RAM_CHR, logobg_chr_compressed);
  64. GD.copy(PALETTE4A, spark_palette, sizeof(spark_palette));
  65. GD.uncompress(RAM_SPRIMG, wlogo_compressed);
  66. }
  67. void bgfade(byte t)
  68. {
  69. for (byte i = 0; i < 64; i++) {
  70. byte l = ((t == 31) ? 8 : 0) + ((i * t) >> 4);
  71. GD.wr16(0x3e80 + 2 * i, RGB(l, l, l));
  72. }
  73. }
  74. static void fade(uint16_t addr)
  75. {
  76. uint16_t col = GD.rd16(addr);
  77. if (col & (31 << 10)) col -= (1 << 10);
  78. if (col & (31 << 5)) col -= (1 << 5);
  79. if (col & 31) col -= 1;
  80. GD.wr16(addr, col);
  81. }
  82. // Fade 16 palette entries starting at addr
  83. static void fade16(uint16_t addr)
  84. {
  85. uint16_t cols[16];
  86. GD.__start(addr);
  87. for (byte i = 0; i < 16; i++) {
  88. byte lo = SPI.transfer(0);
  89. byte hi = SPI.transfer(0);
  90. uint16_t col = (hi << 8) | lo;
  91. if (col & (31 << 10)) col -= (1 << 10);
  92. if (col & (31 << 5)) col -= (1 << 5);
  93. if (col & 31) col -= 1;
  94. cols[i] = col;
  95. }
  96. GD.__end();
  97. GD.__wstart(addr);
  98. for (byte i = 0; i < 16; i++) {
  99. uint16_t col = cols[i];
  100. SPI.transfer(lowByte(col));
  101. SPI.transfer(highByte(col));
  102. }
  103. GD.__end();
  104. }
  105. #define FINALX 305
  106. void loop()
  107. {
  108. focusy = 138;
  109. sprcnt = 0;
  110. for (byte i = 0; i < NSPR; i++) {
  111. kill(i);
  112. }
  113. GD.__wstartspr(0);
  114. for (int i = 0; i < 512; i++)
  115. GD.xhide();
  116. GD.__end();
  117. GD.copy(PALETTE16A, wlogo_palette, sizeof(wlogo_palette));
  118. GD.uncompress(RAM_PAL, logobg_pal_compressed);
  119. byte jitter = 0;
  120. for (int t = 0; t < 8 * 72; t++) {
  121. byte frame = (t & 1);
  122. if (t < 32)
  123. bgfade(t);
  124. if (((8 * 72) - 32) < t) {
  125. bgfade(8 * 72 - t);
  126. for (uint16_t a = RAM_PAL; a < RAM_PAL + (256 * 4 * 2); a += 32)
  127. fade16(a);
  128. fade16(PALETTE16A);
  129. }
  130. byte sparking = (72 <= t) && (t <= (72 + FINALX));
  131. if (sparking) {
  132. focusx = t - 72;
  133. if (16 <= focusx && ((focusx & 15) == 0)) {
  134. GD.__wstartspr(sprcnt);
  135. draw_wlogo(focusx, 109, (focusx - 16) >> 4, 0);
  136. GD.__end();
  137. GD.__wstartspr(256 | sprcnt);
  138. draw_wlogo(focusx, 109, (focusx - 16) >> 4, 0);
  139. GD.__end();
  140. sprcnt += GD.spr;
  141. }
  142. }
  143. #if 1
  144. GD.__wstartspr((frame ? 256 : 0) + 56);
  145. byte i;
  146. // JCB-SPARK-A
  147. struct spr *ps;
  148. for (i = 0, ps = &sprites[i]; i < NSPR; i++, ps++) {
  149. draw_spark(ps->x, ps->y, 0, (i & 7));
  150. ps->x += ps->vx;
  151. ps->y += ps->vy;
  152. ps->vy++;
  153. if ((ps->x < 0) || (ps->x > 400) || (ps->y > 310)) {
  154. if (sparking)
  155. born(i);
  156. else
  157. kill(i);
  158. }
  159. }
  160. // JCB-SPARK-B
  161. GD.__end();
  162. #endif
  163. GD.waitvblank();
  164. GD.wr(SPR_PAGE, frame);
  165. // JCB-JITTER-A
  166. GD.wr16(SCROLL_X, random(-1, 2));
  167. GD.wr16(SCROLL_Y, random(-1, 2));
  168. flash_uint8_t *src = logobg_pic + (12 * 25 * jitter);
  169. for (byte y = 0; y < 12; y++) {
  170. GD.copy(atxy(24, 12 + y), src, 25);
  171. src += 25;
  172. }
  173. // JCB-JITTER-B
  174. jitter = (jitter == 4) ? 0 : (jitter + 1);
  175. // static int ss; GD.screenshot(ss++); // JCB
  176. }
  177. delay(700);
  178. }