diff --git a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.rgds b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.rgds index 236e09659c..dc74b4d149 100644 --- a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.rgds +++ b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/config/RK3566/drastic.cfg.rgds @@ -60,7 +60,7 @@ controls_a[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 controls_a[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 controls_a[CONTROL_INDEX_LOAD_GAME] = 65535 controls_a[CONTROL_INDEX_QUIT] = 65535 -controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_a[CONTROL_INDEX_FAKE_MICROPHONE] = 327 controls_a[CONTROL_INDEX_UI_UP] = 1217 controls_a[CONTROL_INDEX_UI_DOWN] = 1153 controls_a[CONTROL_INDEX_UI_LEFT] = 1216 @@ -98,7 +98,7 @@ controls_b[CONTROL_INDEX_SWAP_ORIENTATION_A] = 65535 controls_b[CONTROL_INDEX_SWAP_ORIENTATION_B] = 65535 controls_b[CONTROL_INDEX_LOAD_GAME] = 65535 controls_b[CONTROL_INDEX_QUIT] = 65535 -controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 65535 +controls_b[CONTROL_INDEX_FAKE_MICROPHONE] = 327 controls_b[CONTROL_INDEX_UI_UP] = 1037 controls_b[CONTROL_INDEX_UI_DOWN] = 1038 controls_b[CONTROL_INDEX_UI_LEFT] = 1039 diff --git a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/package.mk b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/package.mk index 6ef4987000..8811d16e7b 100644 --- a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/package.mk +++ b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/package.mk @@ -31,6 +31,9 @@ makeinstall_target() { cp -rf ${PKG_BUILD}/drastic_aarch64/* ${INSTALL}/usr/config/drastic/ cp -rf ${PKG_DIR}/config/${DEVICE}/* ${INSTALL}/usr/config/drastic/config/ cp -rf ${PKG_DIR}/config/drastic.gptk ${INSTALL}/usr/config/drastic/ + + mkdir -p ${INSTALL}/usr/config/drastic/microphone + cp -f ${PKG_DIR}/sources/microphone.wav ${INSTALL}/usr/config/drastic/microphone/ } post_install() { diff --git a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh index 8dcc55df7e..b687ffb8f2 100644 --- a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh +++ b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh @@ -16,6 +16,7 @@ PLATFORM="nds" HIRES3D=$(get_setting hires_3d "${PLATFORM}" "${GAME}") THREADED3D=$(get_setting threaded_3d "${PLATFORM}" "${GAME}") FOLLOW3D=$(get_setting follow_3d_renderer "${PLATFORM}" "${GAME}") +MICTHRESH=$(get_setting microphone_sensitivity "${PLATFORM}" "${GAME}") #load gptokeyb support files control-gen_init.sh @@ -92,12 +93,9 @@ if [ "${HW_DEVICE}" = "S922X" ]; then fi $GPTOKEYB "drastic" -c "drastic.gptk" & -# Fix actual touch inputs by replacing touch->mouse translation +# Fix actual touch inputs by replacing touch->mouse translation and add hw mic support export LD_PRELOAD="/usr/lib/libdrastouch.so" export SDL_TOUCH_MOUSE_EVENTS="0" +export DSHOOK_MIC_THRESH="${MICTHRESH}" ./drastic "$1" kill -9 $(pidof gptokeyb) - -if echo "${UI_SERVICE}" | grep "sway"; then - kill -9 $(pidof drastic_sense.sh) -fi diff --git a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/sources/libdrastouch.c b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/sources/libdrastouch.c index 4f8814d50f..790923bca9 100644 --- a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/sources/libdrastouch.c +++ b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/sources/libdrastouch.c @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include static int ds_screen_width = 256; static int ds_screen_height = 192; @@ -14,6 +17,14 @@ static int logical_width = -1; static int logical_height = -1; static int actual_touch = 0; +// Microphone monitoring +static SDL_AudioDeviceID mic_device = 0; +static int mic_key_held = 0; +static float mic_threshold = 0.0f; +static int mic_enabled = 0; +static float mic_baseline = 0.0f; +static int mic_baseline_samples = 0; + static SDL_Texture* screens[4]; static SDL_Texture* stylus_tex[2]; static SDL_Rect touch_rect_storage = {0}; @@ -26,6 +37,14 @@ static int (*real_SDL_RenderSetLogicalSize)(SDL_Renderer*, int, int) = NULL; static SDL_Texture* (*real_SDL_CreateTexture)(SDL_Renderer*, Uint32, int, int, int) = NULL; static int (*real_SDL_RenderCopy)(SDL_Renderer*, SDL_Texture*, const SDL_Rect*, const SDL_Rect*) = NULL; static int (*real_SDL_PollEvent)(SDL_Event*) = NULL; +static int (*real_SDL_PushEvent)(SDL_Event*) = NULL; +static Uint32 (*real_SDL_WasInit)(Uint32) = NULL; +static int (*real_SDL_InitSubSystem)(Uint32) = NULL; +static SDL_AudioDeviceID (*real_SDL_OpenAudioDevice)(const char*, int, const SDL_AudioSpec*, SDL_AudioSpec*, int) = NULL; +static void (*real_SDL_PauseAudioDevice)(SDL_AudioDeviceID, int) = NULL; +static void (*real_SDL_CloseAudioDevice)(SDL_AudioDeviceID) = NULL; +static int (*real_SDL_GetNumAudioDevices)(int) = NULL; +static const char* (*real_SDL_GetAudioDeviceName)(int, int) = NULL; SDL_Window* SDL_CreateWindow(const char* title, int x, int y, int w, int h, Uint32 flags) { int num_displays = SDL_GetNumVideoDisplays(); @@ -156,6 +175,53 @@ int SDL_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect return real_SDL_RenderCopy(renderer, texture, srcrect, dstrect); } +void mic_audio_callback(void* userdata, Uint8* stream, int len) { + if (!mic_enabled) return; + + Sint16* samples = (Sint16*)stream; + int sample_count = len / 2; + + // Calculate RMS amplitude + float sum = 0.0f; + for (int i = 0; i < sample_count; i++) { + float sample = samples[i] / 32768.0f; // Normalize to [-1.0..1.0] + sum += sample * sample; + } + float rms = sqrtf(sum / sample_count); + + // Build ambient baseline over first ~3 seconds + if (mic_baseline_samples < 60) { + mic_baseline = (mic_baseline * mic_baseline_samples + rms) / (mic_baseline_samples + 1); + mic_baseline_samples++; + return; // Don't trigger during calibration + } + + mic_baseline = mic_baseline * 0.999f + rms * 0.001f; + + // Trigger only if significantly above baseline + float trigger_level = mic_baseline + mic_threshold; + int should_hold = (rms > trigger_level); + if (should_hold && !mic_key_held) { + // Noise detected, press Scroll Lock + SDL_Event key_event = {0}; + key_event.type = SDL_KEYDOWN; + key_event.key.state = SDL_PRESSED; + key_event.key.keysym.scancode = SDL_SCANCODE_SCROLLLOCK; + key_event.key.keysym.sym = SDLK_SCROLLLOCK; + real_SDL_PushEvent(&key_event); + mic_key_held = 1; + } else if (!should_hold && mic_key_held) { + // Noise dropped below threshold, release Scroll Lock + SDL_Event key_event = {0}; + key_event.type = SDL_KEYUP; + key_event.key.state = SDL_RELEASED; + key_event.key.keysym.scancode = SDL_SCANCODE_SCROLLLOCK; + key_event.key.keysym.sym = SDLK_SCROLLLOCK; + real_SDL_PushEvent(&key_event); + mic_key_held = 0; + } +} + int SDL_PollEvent(SDL_Event* event) { // Loop required to filter events we don't want to pass along while (1) { @@ -188,7 +254,7 @@ int SDL_PollEvent(SDL_Event* event) { event->button.state = SDL_PRESSED; event->button.x = x; event->button.y = y; - SDL_PushEvent(event); + real_SDL_PushEvent(event); // Jump to new position event->type = SDL_MOUSEMOTION; @@ -253,6 +319,60 @@ static void init(void) { real_SDL_CreateTexture = dlsym(RTLD_NEXT, "SDL_CreateTexture"); real_SDL_RenderCopy = dlsym(RTLD_NEXT, "SDL_RenderCopy"); real_SDL_PollEvent = dlsym(RTLD_NEXT, "SDL_PollEvent"); + real_SDL_PushEvent = dlsym(RTLD_NEXT, "SDL_PushEvent"); + real_SDL_WasInit = dlsym(RTLD_NEXT, "SDL_WasInit"); + real_SDL_InitSubSystem = dlsym(RTLD_NEXT, "SDL_InitSubSystem"); + real_SDL_OpenAudioDevice = dlsym(RTLD_NEXT, "SDL_OpenAudioDevice"); + real_SDL_PauseAudioDevice = dlsym(RTLD_NEXT, "SDL_PauseAudioDevice"); + real_SDL_CloseAudioDevice = dlsym(RTLD_NEXT, "SDL_CloseAudioDevice"); + real_SDL_GetNumAudioDevices = dlsym(RTLD_NEXT, "SDL_GetNumAudioDevices"); + real_SDL_GetAudioDeviceName = dlsym(RTLD_NEXT, "SDL_GetAudioDeviceName"); + + const char* threshold_str = getenv("DSHOOK_MIC_THRESH"); + if (threshold_str) { + mic_threshold = atof(threshold_str); + if (mic_threshold > 0.0f) { + mic_enabled = 1; + + // Make sure SDL audio is ready, just in case + if (real_SDL_WasInit(SDL_INIT_AUDIO) == 0) + real_SDL_InitSubSystem(SDL_INIT_AUDIO); + + int num_devices = real_SDL_GetNumAudioDevices(1); + const char* device_name = NULL; + for (int i = 0; i < num_devices; i++) { + const char* name = real_SDL_GetAudioDeviceName(i, 1); + // Use first available device (or look for Built-in) + if (name && (i == 0 || strstr(name, "Built-in"))) { + device_name = name; + break; + } + } + + // Configure audio capture + SDL_AudioSpec desired_spec = {0}; + desired_spec.freq = 44100; + desired_spec.format = AUDIO_S16SYS; + desired_spec.channels = 1; + desired_spec.samples = 2048; + desired_spec.callback = mic_audio_callback; + + SDL_AudioSpec obtained_spec; + mic_device = real_SDL_OpenAudioDevice(device_name, 1, &desired_spec, &obtained_spec, 0); + + if (mic_device > 0) // Opened, start capture + real_SDL_PauseAudioDevice(mic_device, 0); + else // Couldn't open, fallback to disable + mic_enabled = 0; + } + } +} + +__attribute__((destructor)) +static void cleanup(void) { + if (mic_device > 0 && real_SDL_CloseAudioDevice) { + real_SDL_CloseAudioDevice(mic_device); + } } // Major thanks/credit to Shaun Inman for providing the basis of this hook library! \ No newline at end of file diff --git a/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/sources/microphone.wav b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/sources/microphone.wav new file mode 100644 index 0000000000..7d58159181 Binary files /dev/null and b/projects/ROCKNIX/packages/emulators/standalone/drastic-sa/sources/microphone.wav differ diff --git a/projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh b/projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh index 2d79e103f6..fc38f45635 100644 --- a/projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh +++ b/projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh @@ -68,12 +68,12 @@ fi if [ "$PLATFORM" = "ndsiware" ]; then sed -i '/^DirectBoot=/c\DirectBoot=0' /storage/.config/melonDS/melonDS.ini else - if [ "$DBOOT" = "1" ]; then - sed -i '/^DirectBoot=/c\DirectBoot=1' /storage/.config/melonDS/melonDS.ini - sed -i '/^ExternalBIOSEnable=/c\ExternalBIOSEnable=0' /storage/.config/melonDS/melonDS.ini - else + if [ "$DBOOT" = "0" ]; then sed -i '/^DirectBoot=/c\DirectBoot=0' /storage/.config/melonDS/melonDS.ini sed -i '/^ExternalBIOSEnable=/c\ExternalBIOSEnable=1' /storage/.config/melonDS/melonDS.ini + else + sed -i '/^DirectBoot=/c\DirectBoot=1' /storage/.config/melonDS/melonDS.ini + sed -i '/^ExternalBIOSEnable=/c\ExternalBIOSEnable=0' /storage/.config/melonDS/melonDS.ini fi fi diff --git a/projects/ROCKNIX/packages/hardware/quirks/devices/Anbernic RG DS/050-game_configs b/projects/ROCKNIX/packages/hardware/quirks/devices/Anbernic RG DS/050-game_configs index 8cdd238d2e..d001c06f6f 100755 --- a/projects/ROCKNIX/packages/hardware/quirks/devices/Anbernic RG DS/050-game_configs +++ b/projects/ROCKNIX/packages/hardware/quirks/devices/Anbernic RG DS/050-game_configs @@ -7,6 +7,10 @@ if [ ! -d "/storage/.config/drastic" ]; then mkdir -p "/storage/.config/drastic" cp -r "/usr/config/drastic" "/storage/.config/" fi -if [ -f "/storage/.config/drastic/config/drastic.cfg.rgds" ]; then - cp /storage/.config/drastic/config/drastic.cfg.rgds /storage/.config/drastic/config/drastic.cfg +if [ -f "/storage/.config/drastic/config/drastic.cfg.rgds" ] && [ -f "/storage/.config/drastic/config/drastic.cfg" ]; then + sed -i '/^controls_b/d' /storage/.config/drastic/config/drastic.cfg + grep '^controls_b' /storage/.config/drastic/config/drastic.cfg.rgds >> /storage/.config/drastic/config/drastic.cfg +elif [ -f "/storage/.config/drastic/config/drastic.cfg.rgds" ]; then + # Fall back to full copy if user drastic.cfg doesn't exist for some reason + cp /storage/.config/drastic/config/drastic.cfg.rgds /storage/.config/drastic/config/drastic.cfg fi diff --git a/projects/ROCKNIX/packages/ui/emulationstation/config/common/es_features.cfg b/projects/ROCKNIX/packages/ui/emulationstation/config/common/es_features.cfg index e6c01c6579..b7b7d34103 100644 --- a/projects/ROCKNIX/packages/ui/emulationstation/config/common/es_features.cfg +++ b/projects/ROCKNIX/packages/ui/emulationstation/config/common/es_features.cfg @@ -1624,6 +1624,12 @@ + + + + + +