dolphin_state.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include "dolphin_state.h"
  2. #include <furi.h>
  3. #include <api-hal.h>
  4. #include <math.h>
  5. typedef struct {
  6. uint8_t magic;
  7. uint8_t version;
  8. uint8_t checksum;
  9. uint8_t flags;
  10. uint32_t timestamp;
  11. } DolphinDataHeader;
  12. #define DOLPHIN_DATA_PAGE 0xC0
  13. #define DOLPHIN_DATA_HEADER_ADDRESS 0x080C0000U
  14. #define DOLPHIN_DATA_DATA_ADDRESS (DOLPHIN_DATA_HEADER_ADDRESS + sizeof(DolphinDataHeader))
  15. #define DOLPHIN_DATA_HEADER_MAGIC 0xD0
  16. #define DOLPHIN_DATA_HEADER_VERSION 0x01
  17. #define DOLPHIN_LVL_THRESHOLD 20.0f
  18. typedef struct {
  19. uint32_t limit_ibutton;
  20. uint32_t limit_nfc;
  21. uint32_t limit_ir;
  22. uint32_t limit_rfid;
  23. uint32_t flags;
  24. uint32_t icounter;
  25. uint32_t butthurt;
  26. } DolphinData;
  27. struct DolphinState {
  28. DolphinData data;
  29. };
  30. DolphinState* dolphin_state_alloc() {
  31. DolphinState* dolphin_state = furi_alloc(sizeof(DolphinState));
  32. return dolphin_state;
  33. }
  34. void dolphin_state_free(DolphinState* dolphin_state) {
  35. free(dolphin_state);
  36. }
  37. bool dolphin_state_save(DolphinState* dolphin_state) {
  38. if(!api_hal_flash_erase(DOLPHIN_DATA_PAGE, 1)) {
  39. return false;
  40. }
  41. uint8_t* source = (uint8_t*)&dolphin_state->data;
  42. uint8_t checksum = 0;
  43. for(size_t i = 0; i < sizeof(DolphinData); i++) {
  44. checksum += source[i];
  45. }
  46. DolphinDataHeader header;
  47. header.magic = DOLPHIN_DATA_HEADER_MAGIC;
  48. header.version = DOLPHIN_DATA_HEADER_VERSION;
  49. header.checksum = checksum;
  50. header.flags = 0;
  51. header.timestamp = 0;
  52. if(!api_hal_flash_write_dword(DOLPHIN_DATA_HEADER_ADDRESS, *(uint64_t*)&header)) {
  53. return false;
  54. }
  55. uint8_t destination[sizeof(uint64_t)];
  56. size_t block_count = sizeof(DolphinData) / sizeof(uint64_t) + 1;
  57. size_t offset = 0;
  58. for(size_t i = 0; i < block_count; i++) {
  59. for(size_t n = 0; n < sizeof(uint64_t); n++) {
  60. if(offset < sizeof(DolphinData)) {
  61. destination[n] = source[offset];
  62. } else {
  63. destination[n] = 0;
  64. }
  65. offset++;
  66. }
  67. if(!api_hal_flash_write_dword(
  68. DOLPHIN_DATA_DATA_ADDRESS + i * sizeof(uint64_t), *(uint64_t*)destination)) {
  69. return false;
  70. }
  71. }
  72. return true;
  73. }
  74. bool dolphin_state_load(DolphinState* dolphin_state) {
  75. const DolphinDataHeader* header = (const DolphinDataHeader*)DOLPHIN_DATA_HEADER_ADDRESS;
  76. if(header->magic == DOLPHIN_DATA_HEADER_MAGIC &&
  77. header->version == DOLPHIN_DATA_HEADER_VERSION) {
  78. uint8_t checksum = 0;
  79. const uint8_t* source = (const uint8_t*)DOLPHIN_DATA_DATA_ADDRESS;
  80. for(size_t i = 0; i < sizeof(DolphinData); i++) {
  81. checksum += source[i];
  82. }
  83. if(header->checksum == checksum) {
  84. memcpy(
  85. &dolphin_state->data, (const void*)DOLPHIN_DATA_DATA_ADDRESS, sizeof(DolphinData));
  86. return true;
  87. }
  88. }
  89. return false;
  90. }
  91. void dolphin_state_clear(DolphinState* dolphin_state) {
  92. memset(&dolphin_state->data, 0, sizeof(DolphinData));
  93. }
  94. void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) {
  95. const DolphinDeedWeight* deed_weight = dolphin_deed_weight(deed);
  96. int32_t icounter = dolphin_state->data.icounter + deed_weight->icounter;
  97. if(icounter >= 0) {
  98. dolphin_state->data.icounter = icounter;
  99. }
  100. }
  101. uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state) {
  102. return dolphin_state->data.icounter;
  103. }
  104. uint32_t dolphin_state_get_butthurt(DolphinState* dolphin_state) {
  105. return dolphin_state->data.butthurt;
  106. }
  107. uint32_t dolphin_state_get_level(DolphinState* dolphin_state) {
  108. return 0.5f +
  109. sqrtf(1.0f + 8.0f * ((float)dolphin_state->data.icounter / DOLPHIN_LVL_THRESHOLD)) /
  110. 2.0f;
  111. }
  112. uint32_t dolphin_state_xp_to_levelup(DolphinState* dolphin_state, uint32_t level, bool remaining) {
  113. return (DOLPHIN_LVL_THRESHOLD * level * (level + 1) / 2) -
  114. (remaining ? dolphin_state->data.icounter : 0);
  115. }