main_espboy.ino 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /**
  2. @file main_espboy.ino
  3. This is ESPboy implementation of the game front end, using Arduino
  4. libraries.
  5. by Miloslav Ciz (drummyfish), 2021
  6. Sadly compiling can't be done with any other optimization flag than -Os.
  7. Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
  8. plus a waiver of all other intellectual property. The goal of this work is to
  9. be and remain completely in the public domain forever, available for any use
  10. whatsoever.
  11. */
  12. #define SFG_CAN_SAVE 1 // for version without saving, set this to 0
  13. #define SFG_FOV_HORIZONTAL 240
  14. #define SFG_SCREEN_RESOLUTION_X 128
  15. #define SFG_SCREEN_RESOLUTION_Y 128
  16. #define SFG_FPS 22
  17. #define SFG_RAYCASTING_MAX_STEPS 20
  18. #define SFG_RAYCASTING_SUBSAMPLE 2
  19. #define SFG_DIMINISH_SPRITES 1
  20. #define SFG_CAN_EXIT 0
  21. #define SFG_DITHERED_SHADOW 1
  22. #define SFG_AVR 1
  23. #include <Arduino.h>
  24. #include <Adafruit_MCP23017.h>
  25. #include <Adafruit_MCP4725.h>
  26. #include <TFT_eSPI.h>
  27. #if SFG_CAN_SAVE
  28. #include <ESP_EEPROM.h>
  29. #define SAVE_VALID_VALUE 173
  30. EEPROMClass eeprom;
  31. #endif
  32. #define MCP23017address 0
  33. #define MCP4725address 0x60
  34. Adafruit_MCP23017 mcp;
  35. Adafruit_MCP4725 dac;
  36. TFT_eSPI tft;
  37. #include "game.h"
  38. #define SAVE_VALID_VALUE 73
  39. uint8_t gamescreen[SFG_SCREEN_RESOLUTION_X * SFG_SCREEN_RESOLUTION_Y];
  40. uint8_t keys;
  41. void SFG_setPixel(uint16_t x, uint16_t y, uint8_t colorIndex)
  42. {
  43. gamescreen[y * SFG_SCREEN_RESOLUTION_X + x] = colorIndex;
  44. }
  45. void SFG_sleepMs(uint16_t timeMs)
  46. {
  47. }
  48. uint32_t SFG_getTimeMs()
  49. {
  50. return millis();
  51. }
  52. int8_t SFG_keyPressed(uint8_t key)
  53. {
  54. switch (key)
  55. {
  56. case SFG_KEY_UP: return keys & 0x02; break;
  57. case SFG_KEY_DOWN: return keys & 0x04; break;
  58. case SFG_KEY_RIGHT: return keys & 0x08; break;
  59. case SFG_KEY_LEFT: return keys & 0x01; break;
  60. case SFG_KEY_A: return keys & 0x10; break;
  61. case SFG_KEY_B: return keys & 0x20; break;
  62. case SFG_KEY_C: return keys & 0x80; break;
  63. case SFG_KEY_MAP: return keys & 0x40; break;
  64. default: return 0; break;
  65. }
  66. }
  67. void SFG_getMouseOffset(int16_t *x, int16_t *y)
  68. {
  69. }
  70. void SFG_setMusic(uint8_t value)
  71. {
  72. }
  73. void SFG_save(uint8_t data[SFG_SAVE_SIZE])
  74. {
  75. #if SFG_CAN_SAVE
  76. eeprom.write(0,SAVE_VALID_VALUE);
  77. for (uint8_t i = 0; i < SFG_SAVE_SIZE; ++i)
  78. eeprom.write(i + 1,data[i]);
  79. eeprom.commit();
  80. #endif
  81. }
  82. void SFG_processEvent(uint8_t event, uint8_t data)
  83. {
  84. }
  85. uint8_t SFG_load(uint8_t data[SFG_SAVE_SIZE])
  86. {
  87. #if SFG_CAN_SAVE
  88. if (eeprom.read(0) == SAVE_VALID_VALUE)
  89. for (uint8_t i = 0; i < SFG_SAVE_SIZE; ++i)
  90. data[i] = eeprom.read(i + 1);
  91. return 1;
  92. #else
  93. return 0;
  94. #endif
  95. }
  96. void SFG_playSound(uint8_t soundIndex, uint8_t volume)
  97. {
  98. int freq = 400;
  99. int dur = 75;
  100. switch (soundIndex)
  101. {
  102. case 0: freq = 120; dur = 250; break; // shot
  103. case 1: freq = 200; dur = 260; break; // door
  104. case 2: freq = 80; dur = 200; break; // explosion
  105. case 3: freq = 220; dur = 50; break; // click
  106. case 4: freq = 180; dur = 200; break; // plasma
  107. case 5: freq = 300; dur = 100; break; // monster
  108. default: break;
  109. }
  110. tone(D3,freq,dur);
  111. }
  112. void setup()
  113. {
  114. dac.begin(MCP4725address);
  115. delay (100);
  116. dac.setVoltage(0,false);
  117. mcp.begin(MCP23017address);
  118. delay(100);
  119. // buttons
  120. for (uint8_t i = 0; i < 8; i++)
  121. {
  122. mcp.pinMode(i,INPUT);
  123. mcp.pullUp(i,HIGH);
  124. }
  125. mcp.pinMode(8,OUTPUT);
  126. mcp.digitalWrite(8,LOW);
  127. tft.begin();
  128. delay(100);
  129. tft.setRotation(0);
  130. tft.setAddrWindow(0,128,0,128);
  131. tft.fillScreen(TFT_BLACK);
  132. dac.setVoltage(4095,true); // backlight
  133. pinMode(D3,OUTPUT); // sound
  134. #if SFG_CAN_SAVE
  135. eeprom.begin(SFG_SAVE_SIZE + 1);
  136. #endif
  137. SFG_init();
  138. }
  139. void loop()
  140. {
  141. keys = ~mcp.readGPIOAB() & 255;
  142. SFG_mainLoopBody();
  143. uint8_t *pixel = gamescreen;
  144. for (int i = 0; i < SFG_SCREEN_RESOLUTION_X * SFG_SCREEN_RESOLUTION_Y; ++i)
  145. {
  146. tft.pushColor(pgm_read_word(paletteRGB565 + *pixel));
  147. pixel++;
  148. }
  149. }