pwnagotchi.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #include "../include/pwnagotchi.h"
  2. /*
  3. Icons from RogueMaster at:
  4. https://github.com/RogueMaster/flipperzero-firmware-wPlugins/commit/8c45f8e9a921f61cda78ecdb2e58a244041d3e05
  5. */
  6. #include "flipagotchi_icons.h"
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <math.h>
  10. #include <furi.h>
  11. Pwnagotchi* pwnagotchi_alloc() {
  12. Pwnagotchi* pwn = malloc(sizeof(Pwnagotchi));
  13. pwn->face = Cool;
  14. pwn->friendFace = NoFace;
  15. strncpy(pwn->channel, "*", 2);
  16. strncpy(pwn->apStat, "0 (0)", 6);
  17. strncpy(pwn->hostname, "pwn", 4);
  18. strncpy(pwn->handshakes, "0 (0)", 6);
  19. strncpy(pwn->uptime, "00:00:00", 9);
  20. strncpy(pwn->message, "Hack the planet!", 17);
  21. pwn->mode = PwnMode_Manual;
  22. return pwn;
  23. }
  24. void pwnagotchi_draw_face(Pwnagotchi* pwn, Canvas* canvas) {
  25. const Icon* currentFace;
  26. bool draw = true;
  27. switch(pwn->face) {
  28. case NoFace:
  29. // Draw nothing
  30. draw = false;
  31. break;
  32. case DefaultFace:
  33. currentFace = &I_awake_flipagotchi;
  34. break;
  35. case Look_r:
  36. currentFace = &I_look_r_flipagotchi;
  37. break;
  38. case Look_l:
  39. currentFace = &I_look_l_flipagotchi;
  40. break;
  41. case Look_r_happy:
  42. currentFace = &I_look_r_happy_flipagotchi;
  43. break;
  44. case Look_l_happy:
  45. currentFace = &I_look_l_happy_flipagotchi;
  46. break;
  47. case Sleep:
  48. currentFace = &I_sleep_flipagotchi;
  49. break;
  50. case Sleep2:
  51. currentFace = &I_sleep2_flipagotchi;
  52. break;
  53. case Awake:
  54. currentFace = &I_awake_flipagotchi;
  55. break;
  56. case Bored:
  57. currentFace = &I_bored_flipagotchi;
  58. break;
  59. case Intense:
  60. currentFace = &I_intense_flipagotchi;
  61. break;
  62. case Cool:
  63. currentFace = &I_cool_flipagotchi;
  64. break;
  65. case Happy:
  66. currentFace = &I_happy_flipagotchi;
  67. break;
  68. case Grateful:
  69. currentFace = &I_grateful_flipagotchi;
  70. break;
  71. case Excited:
  72. currentFace = &I_excited_flipagotchi;
  73. break;
  74. case Motivated:
  75. currentFace = &I_motivated_flipagotchi;
  76. break;
  77. case Demotivated:
  78. currentFace = &I_demotivated_flipagotchi;
  79. break;
  80. case Smart:
  81. currentFace = &I_smart_flipagotchi;
  82. break;
  83. case Lonely:
  84. currentFace = &I_lonely_flipagotchi;
  85. break;
  86. case Sad:
  87. currentFace = &I_sad_flipagotchi;
  88. break;
  89. case Angry:
  90. currentFace = &I_angry_flipagotchi;
  91. break;
  92. case Friend:
  93. currentFace = &I_friend_flipagotchi;
  94. break;
  95. case Broken:
  96. currentFace = &I_broken_flipagotchi;
  97. break;
  98. case Debug:
  99. currentFace = &I_debug_flipagotchi;
  100. break;
  101. case Upload:
  102. currentFace = &I_upload_flipagotchi;
  103. break;
  104. case Upload1:
  105. currentFace = &I_upload1_flipagotchi;
  106. break;
  107. case Upload2:
  108. currentFace = &I_upload2_flipagotchi;
  109. break;
  110. default:
  111. draw = false;
  112. }
  113. if(draw) {
  114. canvas_draw_icon(canvas, PWNAGOTCHI_FACE_J, PWNAGOTCHI_FACE_I, currentFace);
  115. }
  116. }
  117. void pwnagotchi_draw_name(Pwnagotchi* pwn, Canvas* canvas) {
  118. char* formatName = malloc(sizeof(char) * (PWNAGOTCHI_MAX_HOSTNAME_LEN + 2));
  119. strncpy(formatName, pwn->hostname, PWNAGOTCHI_MAX_HOSTNAME_LEN);
  120. strncat(formatName, ">", 2);
  121. canvas_set_font(canvas, PWNAGOTCHI_FONT);
  122. canvas_draw_str(canvas, PWNAGOTCHI_NAME_J, PWNAGOTCHI_NAME_I, formatName);
  123. free(formatName);
  124. }
  125. void pwnagotchi_draw_channel(Pwnagotchi* pwn, Canvas* canvas) {
  126. char* formatChannel = malloc(sizeof(char) * (PWNAGOTCHI_MAX_CHANNEL_LEN + 4));
  127. strncpy(formatChannel, "CH", 3);
  128. strcat(formatChannel, pwn->channel);
  129. canvas_set_font(canvas, PWNAGOTCHI_FONT);
  130. canvas_draw_str(canvas, PWNAGOTCHI_CHANNEL_J, PWNAGOTCHI_CHANNEL_I, formatChannel);
  131. free(formatChannel);
  132. }
  133. void pwnagotchi_draw_aps(Pwnagotchi* pwn, Canvas* canvas) {
  134. char* formatAP = malloc(sizeof(char) * (PWNAGOTCHI_MAX_APS_LEN + 5));
  135. strncpy(formatAP, "APS", 4);
  136. strcat(formatAP, pwn->apStat);
  137. canvas_set_font(canvas, PWNAGOTCHI_FONT);
  138. canvas_draw_str(canvas, PWNAGOTCHI_APS_J, PWNAGOTCHI_APS_I, formatAP);
  139. free(formatAP);
  140. }
  141. void pwnagotchi_draw_uptime(Pwnagotchi* pwn, Canvas* canvas) {
  142. char* formatUp = malloc(sizeof(char) * (PWNAGOTCHI_MAX_UPTIME_LEN + 4));
  143. strncpy(formatUp, "UP", 3);
  144. strcat(formatUp, pwn->uptime);
  145. canvas_set_font(canvas, PWNAGOTCHI_FONT);
  146. canvas_draw_str(canvas, PWNAGOTCHI_UPTIME_J, PWNAGOTCHI_UPTIME_I, formatUp);
  147. free(formatUp);
  148. }
  149. void pwnagotchi_draw_lines(Pwnagotchi* pwn, Canvas* canvas) {
  150. UNUSED(pwn);
  151. // Line 1
  152. canvas_draw_line(
  153. canvas,
  154. PWNAGOTCHI_LINE1_START_J,
  155. PWNAGOTCHI_LINE1_START_I,
  156. PWNAGOTCHI_LINE1_END_J,
  157. PWNAGOTCHI_LINE1_END_I);
  158. // Line 2
  159. canvas_draw_line(
  160. canvas,
  161. PWNAGOTCHI_LINE2_START_J,
  162. PWNAGOTCHI_LINE2_START_I,
  163. PWNAGOTCHI_LINE2_END_J,
  164. PWNAGOTCHI_LINE2_END_I);
  165. }
  166. void pwnagotchi_draw_handshakes(Pwnagotchi* pwn, Canvas* canvas) {
  167. char* formatShakes = malloc(sizeof(char) * (PWNAGOTCHI_MAX_HANDSHAKES_LEN + 5));
  168. strncpy(formatShakes, "PWND ", 6);
  169. strcat(formatShakes, pwn->handshakes);
  170. canvas_set_font(canvas, PWNAGOTCHI_FONT);
  171. canvas_draw_str(canvas, PWNAGOTCHI_HANDSHAKES_J, PWNAGOTCHI_HANDSHAKES_I, formatShakes);
  172. free(formatShakes);
  173. }
  174. void pwnagotchi_draw_friend(Pwnagotchi* pwn, Canvas* canvas) {
  175. UNUSED(pwn);
  176. UNUSED(canvas);
  177. }
  178. void pwnagotchi_draw_mode(Pwnagotchi* pwn, Canvas* canvas) {
  179. canvas_set_font(canvas, PWNAGOTCHI_FONT);
  180. switch(pwn->mode) {
  181. case PwnMode_Manual:
  182. canvas_draw_str(canvas, PWNAGOTCHI_MODE_MANU_J, PWNAGOTCHI_MODE_MANU_I, "MANU");
  183. break;
  184. case PwnMode_Auto:
  185. canvas_draw_str(canvas, PWNAGOTCHI_MODE_AUTO_J, PWNAGOTCHI_MODE_AUTO_I, "AUTO");
  186. break;
  187. case PwnMode_Ai:
  188. canvas_draw_str(canvas, PWNAGOTCHI_MODE_AI_J, PWNAGOTCHI_MODE_AI_I, "AI");
  189. break;
  190. }
  191. }
  192. void pwnagotchi_draw_message(Pwnagotchi* pwn, Canvas* canvas) {
  193. canvas_set_font(canvas, FontSecondary);
  194. int fontHeight = canvas_current_font_height(canvas);
  195. // Apparently W is the widest character (USING a for a more average approach)
  196. size_t charLength = canvas_string_width(canvas, "a");
  197. size_t horizSpace = FLIPPER_SCREEN_WIDTH - PWNAGOTCHI_MESSAGE_J;
  198. size_t charSpaces = floor(((double)horizSpace) / charLength);
  199. size_t messagePixLen = canvas_string_width(canvas, pwn->message);
  200. size_t maxLines =
  201. floor((PWNAGOTCHI_MESSAGE_I - PWNAGOTCHI_LINE2_END_I) / ((double)fontHeight));
  202. size_t requiredLines = ceil(((double)messagePixLen) / horizSpace);
  203. size_t charIndex = 0;
  204. for(size_t i = 0; i < requiredLines && i < maxLines - 1; i++) {
  205. // Allocate the line with room for two more characters (a space and then another char)
  206. size_t allocSize = charSpaces + 2;
  207. char* line = malloc(sizeof(char) * allocSize);
  208. // Copy the allotted characters into line
  209. memcpy(line, (pwn->message + charIndex), allocSize);
  210. // Now loop backwards and cut it off at a space if we end with a letter
  211. size_t backspaceCount = 0;
  212. if(line[allocSize - 1] != ' ' && line[allocSize - 1] != '\0') {
  213. for(int j = allocSize - 1; j >= 0; j--) {
  214. if(line[j] == ' ') {
  215. line[j] = '\0';
  216. break;
  217. }
  218. backspaceCount++;
  219. }
  220. }
  221. // Lets make sure if backspaceCount is too large that we cut the word instead of drawing off the screen
  222. if(backspaceCount >= charSpaces) {
  223. backspaceCount = 0;
  224. }
  225. canvas_draw_str(
  226. canvas, PWNAGOTCHI_MESSAGE_J, PWNAGOTCHI_MESSAGE_I + (i * fontHeight), line);
  227. charIndex += (charSpaces - backspaceCount + 1);
  228. free(line);
  229. }
  230. }
  231. void pwnagotchi_draw_all(Pwnagotchi* pwn, Canvas* canvas) {
  232. pwnagotchi_draw_face(pwn, canvas);
  233. pwnagotchi_draw_name(pwn, canvas);
  234. pwnagotchi_draw_channel(pwn, canvas);
  235. pwnagotchi_draw_aps(pwn, canvas);
  236. pwnagotchi_draw_uptime(pwn, canvas);
  237. pwnagotchi_draw_lines(pwn, canvas);
  238. pwnagotchi_draw_friend(pwn, canvas);
  239. pwnagotchi_draw_mode(pwn, canvas);
  240. pwnagotchi_draw_handshakes(pwn, canvas);
  241. pwnagotchi_draw_message(pwn, canvas);
  242. }
  243. void pwnagotchi_free(Pwnagotchi* pwn) {
  244. free(pwn);
  245. pwn = NULL;
  246. }
  247. void pwnagotchi_screen_clear(Pwnagotchi* pwn) {
  248. UNUSED(pwn);
  249. }