From 2fc3816cb5138fc484c71c856f1ee99c1b4ce47f Mon Sep 17 00:00:00 2001 From: Bryan Head Date: Wed, 7 Aug 2024 17:26:25 -0700 Subject: [PATCH] Replace applet declaration macros with template --- software/res/progname.py | 3 + software/src/APP_HEMISPHERE.h | 50 +++--- software/src/APP_QUADRANTS.h | 20 +-- software/src/HemisphereApplet.h | 24 ++- software/src/hemisphere_config.h | 270 +++++++++++-------------------- 5 files changed, 150 insertions(+), 217 deletions(-) diff --git a/software/res/progname.py b/software/res/progname.py index 5ae9e8ddf..e2a8c9ebd 100644 --- a/software/res/progname.py +++ b/software/res/progname.py @@ -20,3 +20,6 @@ extras += "_flipped" env.Replace(PROGNAME=f"o_C-phazerville-{version}{extras}-{git_rev}") + +# include toolchain paths in compiledb for clangd lsp +env.Replace(COMPILATIONDB_INCLUDE_TOOLCHAIN=True) diff --git a/software/src/APP_HEMISPHERE.h b/software/src/APP_HEMISPHERE.h index c37ff3a61..9777a2a83 100644 --- a/software/src/APP_HEMISPHERE.h +++ b/software/src/APP_HEMISPHERE.h @@ -85,9 +85,9 @@ class HemispherePreset : public SystemExclusiveHandler, return (h == LEFT_HEMISPHERE) ? values_[HEMISPHERE_SELECTED_LEFT_ID] : values_[HEMISPHERE_SELECTED_RIGHT_ID]; } - HemisphereApplet* GetApplet(int h) { + HemisphereApplet& GetApplet(int h) { int idx = HS::get_applet_index_by_id( GetAppletId(h) ); - return HS::available_applets[idx].instance[h]; + return HS::available_applets[idx]->GetInstance(h); } void SetAppletId(int h, int id) { apply_value(h, id); @@ -267,11 +267,11 @@ class HemisphereManager : public HSApplication { for (int h = 0; h < 2; h++) { int index = my_applet[h]; - if (hem_active_preset->GetAppletId(HEM_SIDE(h)) != HS::available_applets[index].id) + if (hem_active_preset->GetAppletId(HEM_SIDE(h)) != HS::available_applets[index]->id) doSave = 1; - hem_active_preset->SetAppletId(HEM_SIDE(h), HS::available_applets[index].id); + hem_active_preset->SetAppletId(HEM_SIDE(h), HS::available_applets[index]->id); - uint64_t data = HS::available_applets[index].instance[h]->OnDataRequest(); + uint64_t data = HS::available_applets[index]->GetInstance(h).OnDataRequest(); if (data != applet_data[h]) doSave = 1; applet_data[h] = data; hem_active_preset->SetData(HEM_SIDE(h), data); @@ -319,7 +319,7 @@ class HemisphereManager : public HSApplication { int index = HS::get_applet_index_by_id( hem_active_preset->GetAppletId(h) ); applet_data[h] = hem_active_preset->GetData(HEM_SIDE(h)); SetApplet(HEM_SIDE(h), index); - HS::available_applets[index].instance[h]->OnDataReceive(applet_data[h]); + HS::available_applets[index]->GetInstance(h).OnDataReceive(applet_data[h]); } @@ -331,13 +331,19 @@ class HemisphereManager : public HSApplication { LoadFromPreset(queued_preset); } + HemisphereApplet& GetApplet(HEM_SIDE hemisphere) { + return HS::available_applets[my_applet[hemisphere]]->GetInstance(hemisphere); + } // does not modify the preset, only the manager void SetApplet(HEM_SIDE hemisphere, int index) { //if (my_applet[hemisphere]) // TODO: special case for first load? - HS::available_applets[my_applet[hemisphere]].instance[hemisphere]->Unload(); + GetApplet(hemisphere).Unload(); next_applet[hemisphere] = my_applet[hemisphere] = index; - HS::available_applets[index].instance[hemisphere]->BaseStart(hemisphere); + HemisphereApplet& selected_applet = HS::available_applets[index]->GetInstance(hemisphere); + selected_applet.BaseStart(hemisphere); + } + void ChangeApplet(HEM_SIDE h, int dir) { int index = HS::get_next_applet_index(next_applet[h], dir); next_applet[h] = index; @@ -423,7 +429,7 @@ class HemisphereManager : public HSApplication { int index = my_applet[h]; // MIDI signals mixed with inputs to applets - if (HS::available_applets[index].id != 150) // not MIDI In + if (HS::available_applets[index]->id != 150) // not MIDI In { ForEachChannel(ch) { int chan = h*2 + ch; @@ -448,7 +454,7 @@ class HemisphereManager : public HSApplication { } } } - HS::available_applets[index].instance[h]->BaseController(); + HS::available_applets[index]->GetInstance(h).BaseController(); } #ifdef ARDUINO_TEENSY41 @@ -514,15 +520,15 @@ class HemisphereManager : public HSApplication { } if (draw_applets) { + // either zoomed or split view + if (help_hemisphere > -1) { - int index = my_applet[help_hemisphere]; - HS::available_applets[index].instance[help_hemisphere]->BaseView(true); - draw_applets = false; + GetApplet(static_cast(help_hemisphere)).BaseView(true); } else { for (int h = 0; h < 2; h++) { int index = my_applet[h]; - HS::available_applets[index].instance[h]->BaseView(); + HS::available_applets[index]->GetInstance(h).BaseView(); } if (select_mode == LEFT_HEMISPHERE) graphics.drawFrame(0, 0, 64, 64); @@ -576,7 +582,7 @@ class HemisphereManager : public HSApplication { } else if (!clock_setup) { // regular applets get button release int index = my_applet[h]; - HS::available_applets[index].instance[h]->OnButtonPress(); + HS::available_applets[index]->GetInstance(h).OnButtonPress(); } } @@ -678,11 +684,11 @@ class HemisphereManager : public HSApplication { // -- button release if (!clock_setup) { const int index = my_applet[hemisphere]; - HemisphereApplet* applet = HS::available_applets[index].instance[hemisphere]; + HemisphereApplet& applet = HS::available_applets[index]->GetInstance(hemisphere); - if (applet->EditMode()) { + if (applet.EditMode()) { // select button becomes aux button while editing a param - applet->AuxButton(); + applet.AuxButton(); } else { // Select Mode if (hemisphere == select_mode) select_mode = -1; // Exit Select Mode if same button is pressed @@ -724,7 +730,7 @@ class HemisphereManager : public HSApplication { ChangeApplet(HEM_SIDE(h), event.value); } else { int index = my_applet[h]; - HS::available_applets[index].instance[h]->OnEncoderMove(event.value); + HS::available_applets[index]->GetInstance(h).OnEncoderMove(event.value); } } @@ -1087,7 +1093,7 @@ class HemisphereManager : public HSApplication { ++current, y += LineH) { gfxIcon(1, y + 1, HS::applet_is_hidden(current) ? CHECK_OFF_ICON : CHECK_ON_ICON); - gfxPrint( 11, y + 2, HS::available_applets[current].instance[0]->applet_name()); + gfxPrint( 11, y + 2, HS::available_applets[current]->GetInstance(0).applet_name()); if (current == showhide_cursor.cursor_pos()) gfxInvert(0, y, 127, LineH - 1); @@ -1163,9 +1169,9 @@ class HemisphereManager : public HSApplication { if (!hem_presets[i].is_valid()) gfxPrint(18, y, "(empty)"); else { - gfxPrint(18, y, hem_presets[i].GetApplet(0)->applet_name()); + gfxPrint(18, y, hem_presets[i].GetApplet(0).applet_name()); gfxPrint(", "); - gfxPrint(hem_presets[i].GetApplet(1)->applet_name()); + gfxPrint(hem_presets[i].GetApplet(1).applet_name()); } y += 10; diff --git a/software/src/APP_QUADRANTS.h b/software/src/APP_QUADRANTS.h index f8ebdd287..a15da3dc9 100644 --- a/software/src/APP_QUADRANTS.h +++ b/software/src/APP_QUADRANTS.h @@ -89,9 +89,9 @@ class QuadrantsPreset : public SystemExclusiveHandler, int GetAppletId(HEM_SIDE h) { return values_[QUADRANTS_SELECTED_LEFT_ID + h]; } - HemisphereApplet* GetApplet(HEM_SIDE h) { + HemisphereApplet& GetApplet(HEM_SIDE h) { int idx = HS::get_applet_index_by_id( GetAppletId(h) ); - return HS::available_applets[idx].instance[h]; + return HS::available_applets[idx]->GetInstance(h); } void SetAppletId(HEM_SIDE h, int id) { apply_value(h, id); @@ -273,11 +273,11 @@ class QuadAppletManager : public HSApplication { for (int h = 0; h < APPLET_SLOTS; h++) { int index = active_applet_index[h]; - if (quad_active_preset->GetAppletId(HEM_SIDE(h)) != HS::available_applets[index].id) + if (quad_active_preset->GetAppletId(HEM_SIDE(h)) != HS::available_applets[index]->id) doSave = 1; - quad_active_preset->SetAppletId(HEM_SIDE(h), HS::available_applets[index].id); + quad_active_preset->SetAppletId(HEM_SIDE(h), HS::available_applets[index]->id); - uint64_t data = HS::available_applets[index].instance[h]->OnDataRequest(); + uint64_t data = HS::available_applets[index]->GetInstance(h).OnDataRequest(); if (data != applet_data[h]) doSave = 1; applet_data[h] = data; quad_active_preset->SetData(HEM_SIDE(h), data); @@ -328,7 +328,7 @@ class QuadAppletManager : public HSApplication { int index = HS::get_applet_index_by_id( quad_active_preset->GetAppletId(HEM_SIDE(h)) ); applet_data[h] = quad_active_preset->GetData(HEM_SIDE(h)); SetApplet(HEM_SIDE(h), index); - HS::available_applets[index].instance[h]->OnDataReceive(applet_data[h]); + HS::available_applets[index]->GetInstance(h).OnDataReceive(applet_data[h]); } } preset_id = id; @@ -352,7 +352,7 @@ class QuadAppletManager : public HSApplication { active_applet[hemisphere]->Unload(); next_applet_index[hemisphere] = active_applet_index[hemisphere] = index; - active_applet[hemisphere] = HS::available_applets[index].instance[hemisphere]; + active_applet[hemisphere] = &HS::available_applets[index]->GetInstance(hemisphere); active_applet[hemisphere]->BaseStart(hemisphere); } void ChangeApplet(HEM_SIDE h, int dir) { @@ -404,7 +404,7 @@ class QuadAppletManager : public HSApplication { } // MIDI signals mixed with inputs to applets - if (HS::available_applets[ active_applet_index[h] ].id != 150) // not MIDI In + if (HS::available_applets[ active_applet_index[h] ]->id != 150) // not MIDI In { ForEachChannel(ch) { int chan = h*2 + ch; @@ -1120,9 +1120,9 @@ class QuadAppletManager : public HSApplication { if (!quad_presets[i].is_valid()) gfxPrint(18, y, "(empty)"); else { - gfxPrint(18, y, quad_presets[i].GetApplet(LEFT_HEMISPHERE)->applet_name()); + gfxPrint(18, y, quad_presets[i].GetApplet(LEFT_HEMISPHERE).applet_name()); gfxPrint(", "); - gfxPrint(quad_presets[i].GetApplet(RIGHT_HEMISPHERE)->applet_name()); + gfxPrint(quad_presets[i].GetApplet(RIGHT_HEMISPHERE).applet_name()); } y += 10; diff --git a/software/src/HemisphereApplet.h b/software/src/HemisphereApplet.h index d51a43bdf..93ba8e5ea 100644 --- a/software/src/HemisphereApplet.h +++ b/software/src/HemisphereApplet.h @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////////////// #pragma once +#include #ifndef _HEM_APPLET_H_ #define _HEM_APPLET_H_ @@ -48,11 +49,24 @@ class HemisphereApplet; namespace HS { -typedef struct Applet { - const int id; - const uint8_t categories; - HemisphereApplet* instance[APPLET_SLOTS]; -} Applet; +class BaseApplet { +public: + BaseApplet(const int id, const uint8_t categories) : id(id), categories(categories) {} + const int id; + const uint8_t categories; + virtual HemisphereApplet & GetInstance(int slot) = 0; +}; + +template +class StaticApplet : public BaseApplet { +public: + StaticApplet() : BaseApplet(Id, Categories) {} + A instance[APPLET_SLOTS]; + + HemisphereApplet & GetInstance(int slot) override { + return instance[slot]; + } +}; extern IOFrame frame; diff --git a/software/src/hemisphere_config.h b/software/src/hemisphere_config.h index e66d52b75..93a336187 100644 --- a/software/src/hemisphere_config.h +++ b/software/src/hemisphere_config.h @@ -13,24 +13,7 @@ // * Category filtering is deprecated at 1.8, but I'm leaving the per-applet categorization // alone to avoid breaking forked codebases by other developers. -#ifdef ARDUINO_TEENSY41 -// Teensy 4.1 can run four applets in Quadrasphere -#define CREATE_APPLET(class_name) \ -class_name class_name ## _instance[4] - -#define DECLARE_APPLET(id, categories, class_name) \ -{ id, categories, { \ - &class_name ## _instance[0], &class_name ## _instance[1], \ - &class_name ## _instance[2], &class_name ## _instance[3] \ - } } - -#else -#define CREATE_APPLET(class_name) \ -class_name class_name ## _instance[2] - -#define DECLARE_APPLET(id, categories, class_name) \ -{ id, categories, { &class_name ## _instance[0], &class_name ## _instance[1] } } -#endif +#include #include "applets/ADSREG.h" #include "applets/ADEG.h" @@ -62,7 +45,7 @@ class_name class_name ## _instance[2] #include "applets/DualTM.h" #include "applets/EbbAndLfo.h" #include "applets/EnigmaJr.h" -//#include "applets/EnsOscKey.h" +// #include "applets/EnsOscKey.h" #include "applets/EnvFollow.h" #include "applets/EuclidX.h" #include "applets/GameOfLife.h" @@ -112,169 +95,96 @@ class_name class_name ## _instance[2] #include "applets/hMIDIIn.h" #include "applets/hMIDIOut.h" - -CREATE_APPLET(Cumulus); -CREATE_APPLET(ADSREG); -CREATE_APPLET(ADEG); -CREATE_APPLET(AttenuateOffset); -CREATE_APPLET(BugCrack); -CREATE_APPLET(DrumMap); -CREATE_APPLET(DualTM); -CREATE_APPLET(EbbAndLfo); -CREATE_APPLET(EuclidX); -CREATE_APPLET(hMIDIIn); -CREATE_APPLET(hMIDIOut); -CREATE_APPLET(Pigeons); -CREATE_APPLET(Stairs); -CREATE_APPLET(TB_3PO); -CREATE_APPLET(Voltage); - -CREATE_APPLET(Calibr8); -CREATE_APPLET(DivSeq); -CREATE_APPLET(PolyDiv); -CREATE_APPLET(Strum); - -CREATE_APPLET(ASR); -CREATE_APPLET(Binary); -CREATE_APPLET(BootsNCat); -CREATE_APPLET(Brancher); -CREATE_APPLET(Burst); -CREATE_APPLET(Button); -CREATE_APPLET(Calculate); -CREATE_APPLET(Carpeggio); -CREATE_APPLET(Chordinator); -CREATE_APPLET(ClockDivider); -CREATE_APPLET(ClockSkip); -CREATE_APPLET(Compare); -CREATE_APPLET(CVRecV2); -CREATE_APPLET(DualQuant); -CREATE_APPLET(EnigmaJr); -//CREATE_APPLET(EnsOscKey); -CREATE_APPLET(EnvFollow); -CREATE_APPLET(GameOfLife); -CREATE_APPLET(GateDelay); -CREATE_APPLET(GatedVCA); -CREATE_APPLET(DrLoFi); -CREATE_APPLET(Logic); -CREATE_APPLET(LowerRenz); -CREATE_APPLET(Metronome); -CREATE_APPLET(MixerBal); -CREATE_APPLET(MultiScale); -CREATE_APPLET(Palimpsest); -CREATE_APPLET(ProbabilityDivider); -CREATE_APPLET(ProbabilityMelody); -CREATE_APPLET(ResetClock); -CREATE_APPLET(RndWalk); -CREATE_APPLET(RunglBook); -CREATE_APPLET(ScaleDuet); -CREATE_APPLET(Schmitt); -CREATE_APPLET(Scope); -CREATE_APPLET(SequenceX); -CREATE_APPLET(Seq32); -CREATE_APPLET(SeqPlay7); -CREATE_APPLET(ShiftGate); -CREATE_APPLET(ShiftReg); -CREATE_APPLET(Shredder); -CREATE_APPLET(Shuffle); -CREATE_APPLET(Slew); -CREATE_APPLET(Squanch); -CREATE_APPLET(Switch); -CREATE_APPLET(SwitchSeq); -CREATE_APPLET(TLNeuron); -CREATE_APPLET(Trending); -CREATE_APPLET(TrigSeq); -CREATE_APPLET(TrigSeq16); -CREATE_APPLET(Tuner); -CREATE_APPLET(VectorEG); -CREATE_APPLET(VectorLFO); -CREATE_APPLET(VectorMod); -CREATE_APPLET(VectorMorph); - -////////////////// id cat class name -#define HEMISPHERE_APPLETS { \ - DECLARE_APPLET( 8, 0x01, ADSREG), \ - DECLARE_APPLET( 34, 0x01, ADEG), \ - DECLARE_APPLET( 47, 0x09, ASR), \ - DECLARE_APPLET( 56, 0x10, AttenuateOffset), \ - DECLARE_APPLET( 41, 0x41, Binary), \ - DECLARE_APPLET( 55, 0x80, BootsNCat), \ - DECLARE_APPLET( 4, 0x14, Brancher), \ - DECLARE_APPLET( 51, 0x80, BugCrack), \ - DECLARE_APPLET( 31, 0x04, Burst), \ - DECLARE_APPLET( 65, 0x10, Button), \ - DECLARE_APPLET( 12, 0x10, Calculate),\ - DECLARE_APPLET( 88, 0x10, Calibr8), \ - DECLARE_APPLET( 32, 0x0a, Carpeggio), \ - DECLARE_APPLET( 64, 0x08, Chordinator), \ - DECLARE_APPLET( 6, 0x04, ClockDivider), \ - DECLARE_APPLET( 28, 0x04, ClockSkip), \ - DECLARE_APPLET( 30, 0x10, Compare), \ - DECLARE_APPLET( 74, 0x40, Cumulus), \ - DECLARE_APPLET( 24, 0x02, CVRecV2), \ - DECLARE_APPLET( 68, 0x06, DivSeq), \ - DECLARE_APPLET( 16, 0x80, DrLoFi), \ - DECLARE_APPLET( 57, 0x02, DrumMap), \ - DECLARE_APPLET( 9, 0x08, DualQuant), \ - DECLARE_APPLET( 18, 0x02, DualTM), \ - DECLARE_APPLET( 7, 0x01, EbbAndLfo), \ - DECLARE_APPLET( 45, 0x02, EnigmaJr), \ - DECLARE_APPLET( 42, 0x11, EnvFollow), \ - DECLARE_APPLET( 15, 0x02, EuclidX), \ - DECLARE_APPLET( 22, 0x01, GameOfLife), \ - DECLARE_APPLET( 29, 0x04, GateDelay), \ - DECLARE_APPLET( 17, 0x50, GatedVCA), \ - DECLARE_APPLET( 10, 0x44, Logic), \ - DECLARE_APPLET( 21, 0x01, LowerRenz), \ - DECLARE_APPLET( 50, 0x04, Metronome), \ - DECLARE_APPLET(150, 0x20, hMIDIIn), \ - DECLARE_APPLET( 27, 0x20, hMIDIOut), \ - DECLARE_APPLET( 33, 0x10, MixerBal), \ - DECLARE_APPLET( 73, 0x08, MultiScale), \ - DECLARE_APPLET( 20, 0x02, Palimpsest), \ - DECLARE_APPLET( 71, 0x02, Pigeons), \ - DECLARE_APPLET( 72, 0x06, PolyDiv), \ - DECLARE_APPLET( 59, 0x04, ProbabilityDivider), \ - DECLARE_APPLET( 62, 0x04, ProbabilityMelody), \ - DECLARE_APPLET( 70, 0x14, ResetClock), \ - DECLARE_APPLET( 69, 0x01, RndWalk), \ - DECLARE_APPLET( 44, 0x01, RunglBook), \ - DECLARE_APPLET( 26, 0x08, ScaleDuet), \ - DECLARE_APPLET( 40, 0x40, Schmitt), \ - DECLARE_APPLET( 23, 0x80, Scope), \ - DECLARE_APPLET( 75, 0x02, Seq32), \ - DECLARE_APPLET( 76, 0x02, SeqPlay7), \ - DECLARE_APPLET( 14, 0x02, SequenceX), \ - DECLARE_APPLET( 48, 0x45, ShiftGate), \ - DECLARE_APPLET( 77, 0x45, ShiftReg), \ - DECLARE_APPLET( 58, 0x01, Shredder), \ - DECLARE_APPLET( 36, 0x04, Shuffle), \ - DECLARE_APPLET( 19, 0x01, Slew), \ - DECLARE_APPLET( 46, 0x08, Squanch), \ - DECLARE_APPLET( 61, 0x01, Stairs), \ - DECLARE_APPLET( 74, 0x08, Strum), \ - DECLARE_APPLET( 3, 0x10, Switch), \ - DECLARE_APPLET( 38, 0x10, SwitchSeq), \ - DECLARE_APPLET( 60, 0x02, TB_3PO), \ - DECLARE_APPLET( 13, 0x40, TLNeuron), \ - DECLARE_APPLET( 37, 0x40, Trending), \ - DECLARE_APPLET( 11, 0x06, TrigSeq), \ - DECLARE_APPLET( 25, 0x06, TrigSeq16), \ - DECLARE_APPLET( 39, 0x80, Tuner), \ - DECLARE_APPLET( 52, 0x01, VectorEG), \ - DECLARE_APPLET( 49, 0x01, VectorLFO), \ - DECLARE_APPLET( 53, 0x01, VectorMod), \ - DECLARE_APPLET( 54, 0x01, VectorMorph), \ - DECLARE_APPLET( 43, 0x10, Voltage), \ +static std::tuple< + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + // StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet, + StaticApplet +> applet_tuple; + +template +std::array::value> tuple_to_array(Tuple &tuple, std::integer_sequence) { + return std::array::value>{ &std::get(tuple)... }; } -/* - DECLARE_APPLET( 35, 0x08, EnsOscKey), \ - DECLARE_APPLET(127, 0x80, DIAGNOSTIC), \ -*/ +template +std::array::value> tuple_to_array(Tuple &tuple) { + return tuple_to_array(tuple, std::make_index_sequence::value>()); +} namespace HS { - static constexpr Applet available_applets[] = HEMISPHERE_APPLETS; - static constexpr int HEMISPHERE_AVAILABLE_APPLETS = ARRAY_SIZE(available_applets); + constexpr static int HEMISPHERE_AVAILABLE_APPLETS = std::tuple_size(); + static auto available_applets = tuple_to_array(applet_tuple); // TODO: figure out where to store this uint64_t hidden_applets[2] = { 0, 0 }; @@ -286,11 +196,11 @@ namespace HS { hidden_applets[seg] = hidden_applets[seg] ^ (uint64_t(1) << (index%64)); } - constexpr int get_applet_index_by_id(const int& id) { + int get_applet_index_by_id(const int& id) { int index = 0; for (int i = 0; i < HEMISPHERE_AVAILABLE_APPLETS; i++) { - if (available_applets[i].id == id) index = i; + if (available_applets[i]->id == id) index = i; } return index; }