diff --git a/apps/SOURCES b/apps/SOURCES index 0bf42a6999..6fc8a276c8 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -305,6 +305,4 @@ keymaps/keymap-echor1.c keymaps/keymap-surfansf28.c #elif CONFIG_KEYPAD == RG_NANO_PAD keymaps/keymap-rgnano.c -#elif CONFIG_KEYPAD == CTRU_PAD -keymaps/keymap-ctru.c #endif diff --git a/apps/keymaps/keymap-ctru.c b/apps/keymaps/keymap-ctru.c deleted file mode 100644 index 0461d03192..0000000000 --- a/apps/keymaps/keymap-ctru.c +++ /dev/null @@ -1,302 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: keymap-ctru.c 28704 2025-07-09 11:28:53Z gama $ - * - * Copyright (C) 2025 Mauricio Garrido - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Button Code Definitions for Civic Type R (ctru) target */ - -#include -#include -#include - -#include "config.h" -#include "action.h" -#include "button.h" -#include "settings.h" - -/* - * The format of the list is as follows - * { Action Code, Button code, Prereq button code } - * if there's no need to check the previous button's value, use BUTTON_NONE - * Insert LAST_ITEM_IN_LIST at the end of each mapping - */ - -static const struct button_mapping button_context_standard[] = { - { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_BACK|BUTTON_REL, BUTTON_BACK }, - - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - { ACTION_STD_OK, BUTTON_RIGHT, BUTTON_NONE }, - - { ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, - { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - { ACTION_STD_CONTEXT, BUTTON_MENU|BUTTON_REL, BUTTON_NONE }, - - { ACTION_STD_KEYLOCK, BUTTON_USER|BUTTON_POWER, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_standard */ - - -static const struct button_mapping button_context_mainmenu[] = { - { ACTION_TREE_WPS, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_TREE), -}; /* button_context_mainmenu */ - -static const struct button_mapping button_context_wps[] = { - { ACTION_WPS_PLAY, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - { ACTION_WPS_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_WPS_BROWSE, BUTTON_BACK|BUTTON_REL, BUTTON_BACK }, - { ACTION_WPS_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - - - { ACTION_WPS_HOTKEY, BUTTON_USER|BUTTON_REL, BUTTON_USER }, - { ACTION_WPS_PITCHSCREEN, BUTTON_USER|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_STD_KEYLOCK, BUTTON_USER|BUTTON_POWER, BUTTON_NONE }, - - - { ACTION_WPS_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, - { ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT }, - - { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, - - { ACTION_WPS_VOLUP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_DOWN, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_wps */ - -static const struct button_mapping button_context_list[] = { - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_list */ - -static const struct button_mapping button_context_tree[] = { - { ACTION_TREE_WPS, BUTTON_USER|BUTTON_REPEAT, BUTTON_USER }, - { ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_TREE_HOTKEY, BUTTON_USER|BUTTON_REL, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST) -}; /* button_context_tree */ - -static const struct button_mapping button_context_settings[] = { - { ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_TREE) -}; /* button_context_settings */ - -static const struct button_mapping button_context_settings_right_is_inc[] = { - { ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings_right_is_inc */ - -static const struct button_mapping button_context_yesno[] = { - { ACTION_YESNO_ACCEPT, BUTTON_SELECT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings_yesno */ - -static const struct button_mapping button_context_colorchooser[] = { //check - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - { ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_colorchooser */ - -static const struct button_mapping button_context_eq[] = { - { ACTION_STD_CANCEL, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - { ACTION_SETTINGS_INC, BUTTON_RIGHT , BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_LEFT , BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT , BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_eq */ - -/** Bookmark Screen **/ -static const struct button_mapping button_context_bmark[] = { - { ACTION_BMS_DELETE, BUTTON_POWER, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST), -}; /* button_context_bmark */ - -static const struct button_mapping button_context_time[] = { - { ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD), -}; /* button_context_time */ - -static const struct button_mapping button_context_quickscreen[] = { - { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE }, - { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_quickscreen */ - -static const struct button_mapping button_context_pitchscreen[] = { - { ACTION_PS_INC_SMALL, BUTTON_UP, BUTTON_NONE }, - { ACTION_PS_INC_BIG, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_DEC_SMALL, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_PS_DEC_BIG, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_PS_NUDGE_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, - - { ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE }, - { ACTION_PS_TOGGLE_MODE, BUTTON_USER, BUTTON_NONE }, - { ACTION_PS_EXIT, BUTTON_MENU|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_EXIT, BUTTON_BACK|BUTTON_REL, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_pitchcreen */ - -static const struct button_mapping button_context_keyboard[] = { - { ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, - { ACTION_KBD_ABORT, BUTTON_BACK|BUTTON_REL, BUTTON_BACK }, - { ACTION_KBD_DONE, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - { ACTION_KBD_BACKSPACE, BUTTON_USER, BUTTON_NONE }, - { ACTION_KBD_PAGE_FLIP, BUTTON_POWER, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_keyboard */ - -static const struct button_mapping button_context_radio[] = { - { ACTION_FM_MENU, BUTTON_SELECT | BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_FM_PRESET, BUTTON_MENU | BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_FM_STOP, BUTTON_POWER | BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_FM_MODE, BUTTON_MENU | BUTTON_REL, BUTTON_MENU }, - { ACTION_FM_EXIT, BUTTON_BACK | BUTTON_REL, BUTTON_BACK }, - { ACTION_FM_PLAY, BUTTON_SELECT | BUTTON_REL, BUTTON_SELECT }, - { ACTION_FM_NEXT_PRESET, BUTTON_USER | BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_FM_PREV_PRESET, BUTTON_USER | BUTTON_LEFT, BUTTON_NONE }, - - /* Volume */ - { ACTION_SETTINGS_INC, BUTTON_UP | BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_UP, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_DOWN | BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN, BUTTON_NONE }, - /* Tuning */ - { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_LEFT | BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT | BUTTON_REPEAT, BUTTON_NONE }, -}; /* button_context_radio */ - -const struct button_mapping* target_get_context_mapping(int context) -{ - switch (context & ~CONTEXT_LOCKED) - { - case CONTEXT_STD: - return button_context_standard; - case CONTEXT_WPS: - return button_context_wps; - - case CONTEXT_LIST: - return button_context_list; - case CONTEXT_MAINMENU: - return button_context_mainmenu; - - case CONTEXT_TREE: - return button_context_tree; - - case CONTEXT_SETTINGS: - return button_context_settings; - - case CONTEXT_CUSTOM|CONTEXT_SETTINGS: - case CONTEXT_SETTINGS_RECTRIGGER: - return button_context_settings_right_is_inc; - - case CONTEXT_SETTINGS_COLOURCHOOSER: - return button_context_colorchooser; - case CONTEXT_SETTINGS_EQ: - return button_context_eq; - - case CONTEXT_SETTINGS_TIME: - return button_context_time; - - case CONTEXT_YESNOSCREEN: - return button_context_yesno; - case CONTEXT_FM: - return button_context_radio; - case CONTEXT_BOOKMARKSCREEN: - return button_context_bmark; - case CONTEXT_QUICKSCREEN: - return button_context_quickscreen; - case CONTEXT_PITCHSCREEN: - return button_context_pitchscreen; - case CONTEXT_KEYBOARD: - return button_context_keyboard; - } - return button_context_standard; -} diff --git a/apps/tree.c b/apps/tree.c index 5df204bbf2..86b841988c 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -565,11 +565,7 @@ void resume_directory(const char *dir) /* Returns the current working directory and also writes cwd to buf if non-NULL. In case of error, returns NULL. */ -#ifdef CTRU -char *__wrap_getcwd(char *buf, getcwd_size_t size) -#else char *getcwd(char *buf, getcwd_size_t size) -#endif { if (!buf) return tc.currdir; diff --git a/apps/tree.h b/apps/tree.h index 4c7c2e8fe7..70d013e945 100644 --- a/apps/tree.h +++ b/apps/tree.h @@ -128,12 +128,7 @@ void tree_unlock_cache(struct tree_context *t); #else #define getcwd_size_t size_t #endif -#ifdef CTRU -/* devkitarm already defines getcwd */ -char *__wrap_getcwd(char *buf, getcwd_size_t size); -#else char *getcwd(char *buf, getcwd_size_t size); -#endif void reload_directory(void); bool check_rockboxdir(void); struct tree_context* tree_get_context(void); diff --git a/firmware/SOURCES b/firmware/SOURCES index c8d8212927..19d7fa1bba 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -25,7 +25,7 @@ target/hosted/rtc.c #if (CONFIG_PLATFORM & PLATFORM_ANDROID) == 0 && \ !defined(DX50) && !defined(DX90) && \ - (defined(DEBUG) || defined(SIMULATOR) || defined(CTRU)) /* sim should define DEBUG instead */ + (defined(DEBUG) || defined(SIMULATOR)) /* sim should define DEBUG instead */ target/hosted/debug-hosted.c #endif @@ -94,14 +94,12 @@ target/hosted/sdl/app/button-application.c #ifdef WIN32 target/hosted/filesystem-win32.c #else /* !WIN32 */ -#ifndef CTRU target/hosted/filesystem-unix.c -#endif /* CTRU */ #endif /* WIN32 */ #endif /* APPLICATION */ #endif /* HAVE_SDL */ -#if defined(APPLICATION) && !defined(CTRU) +#ifdef APPLICATION target/hosted/filesystem-app.c #endif /* APPLICATION */ @@ -583,8 +581,6 @@ target/hosted/maemo/pcm-gstreamer.c target/hosted/sdl/pcm-sdl.c #endif /* (CONFIG_PLATFORM & PLATFORM_MAEMO) */ -#elif defined(CTRU) -drivers/audio/ctru.c #endif #endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) */ @@ -2075,28 +2071,6 @@ target/hosted/ibasso/dx90/button-dx90.c #endif #endif -#if (CONFIG_PLATFORM & PLATFORM_CTRU) -asm/arm/lcd-as-memframe.S -target/hosted/ctru/backlight-ctru.c -target/hosted/ctru/button-ctru.c -target/hosted/ctru/kernel-ctru.c -target/hosted/ctru/thread-ctru.c -target/hosted/ctru/lcd-bitmap.c -target/hosted/ctru/luminance-ctru.c -target/hosted/ctru/system-ctru.c -target/hosted/ctru/filesystem-ctru.c -target/hosted/ctru/lc-ctru.c -target/hosted/ctru/lc-program-resolver.c -target/hosted/ctru/powermgmt-ctru.c -target/hosted/ctru/timer-ctru.c -target/hosted/ctru/pcm-ctru.c -target/hosted/ctru/lib/sys_file.c -target/hosted/ctru/lib/sys_dir.c -target/hosted/ctru/lib/sys_thread.c -target/hosted/ctru/lib/sys_timer.c -target/hosted/ctru/lib/bfile/bfile.c -#endif - #else /* defined(SIMULATOR) */ #ifdef WIN32 @@ -2145,9 +2119,9 @@ kernel/queue.c #ifdef HAVE_SEMAPHORE_OBJECTS kernel/semaphore.c #endif -#ifdef HAVE_SDL_THREADS +#if defined(HAVE_SDL_THREADS) target/hosted/sdl/thread-sdl.c -#elif !defined(CTRU) +#else kernel/thread.c #endif kernel/thread-common.c diff --git a/firmware/drivers/audio/ctru.c b/firmware/drivers/audio/ctru.c deleted file mode 100644 index 70a4170557..0000000000 --- a/firmware/drivers/audio/ctru.c +++ /dev/null @@ -1,92 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright © 2010 Thomas Martitz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "sound.h" -#include "pcm_sampr.h" -#ifdef HAVE_SW_VOLUME_CONTROL -#include "pcm_sw_volume.h" -#include "fixedpoint.h" -#endif - -/** - * Audio Hardware api. Make some of them do nothing as we cannot properly - * simulate with SDL. if we used DSP we would run code that doesn't actually - * run on the target - **/ - -void audiohw_set_volume(int vol_l, int vol_r) -{ - (void)vol_l; (void)vol_r; -} - -#if defined(AUDIOHW_HAVE_BALANCE) -void audiohw_set_balance(int value) { (void)value; } -#endif -#ifndef HAVE_SW_TONE_CONTROLS -#if defined(AUDIOHW_HAVE_BASS) -void audiohw_set_bass(int value) { (void)value; } -#endif -#if defined(AUDIOHW_HAVE_TREBLE) -void audiohw_set_treble(int value) { (void)value; } -#endif -#endif /* HAVE_SW_TONE_CONTROLS */ -#if defined(AUDIOHW_HAVE_BASS_CUTOFF) -void audiohw_set_bass_cutoff(int value) { (void)value; } -#endif -#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF) -void audiohw_set_treble_cutoff(int value){ (void)value; } -#endif -/* EQ-based tone controls */ -#if defined(AUDIOHW_HAVE_EQ) -void audiohw_set_eq_band_gain(unsigned int band, int value) - { (void)band; (void)value; } -#endif -#if defined(AUDIOHW_HAVE_EQ_FREQUENCY) -void audiohw_set_eq_band_frequency(unsigned int band, int value) - { (void)band; (void)value; } -#endif -#if defined(AUDIOHW_HAVE_EQ_WIDTH) -void audiohw_set_eq_band_width(unsigned int band, int value) - { (void)band; (void)value; } -#endif -#if defined(AUDIOHW_HAVE_DEPTH_3D) -void audiohw_set_depth_3d(int value) - { (void)value; } -#endif -#if defined(AUDIOHW_HAVE_LINEOUT) -void audiohw_set_lineout_volume(int vol_l, int vol_r) - { (void)vol_l; (void)vol_r; } -#endif -#if defined(AUDIOHW_HAVE_FILTER_ROLL_OFF) -void audiohw_set_filter_roll_off(int value) - { (void)value; } -#endif -#if defined(AUDIOHW_HAVE_POWER_MODE) -void audiohw_set_power_mode(int value) - { (void)value; } -#endif - -#ifdef CONFIG_SAMPR_TYPES -unsigned int pcm_sampr_to_hw_sampr(unsigned int samplerate, - unsigned int type) - { return samplerate; (void)type; } -#endif /* CONFIG_SAMPR_TYPES */ diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 98f0857daf..7fc6d39468 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -224,7 +224,7 @@ struct sound_settings_info #elif defined(HAVE_ES9218) #include "es9218.h" #elif ((CONFIG_PLATFORM & (PLATFORM_ANDROID | PLATFORM_MAEMO \ - | PLATFORM_PANDORA | PLATFORM_SDL | PLATFORM_CTRU)) | defined(RG_NANO)) + | PLATFORM_PANDORA | PLATFORM_SDL )) | defined(RG_NANO)) #include "hosted_codec.h" #elif defined(DX50) #include "codec-dx50.h" diff --git a/firmware/export/config.h b/firmware/export/config.h index 9ddc563d9b..fe66f06644 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -85,7 +85,6 @@ #define RK27XX 2700 #define X1000 1000 #define STM32H743 32743 -#define N10480H 10480 /* platforms * bit fields to allow PLATFORM_HOSTED to be OR'ed e.g. with a @@ -99,7 +98,6 @@ #define PLATFORM_MAEMO5 (1<<5) #define PLATFORM_MAEMO (PLATFORM_MAEMO4|PLATFORM_MAEMO5) #define PLATFORM_PANDORA (1<<6) -#define PLATFORM_CTRU (1<<7) /* CONFIG_KEYPAD */ #define IRIVER_H100_PAD 4 @@ -169,7 +167,6 @@ #define ECHO_R1_PAD 75 #define SURFANS_F28_PAD 76 #define RG_NANO_PAD 77 -#define CTRU_PAD 78 /* CONFIG_REMOTE_KEYPAD */ #define H100_REMOTE 1 @@ -626,8 +623,6 @@ Lyre prototype 1 */ #include "config/surfansf28.h" #elif defined(RG_NANO) #include "config/rgnano.h" -#elif defined(CTRU) -#include "config/ctru.h" #else #error "unknown hardware platform!" #endif @@ -655,7 +650,7 @@ Lyre prototype 1 */ # define CONFIG_BUFLIB_BACKEND BUFLIB_BACKEND_MEMPOOL #endif -#if defined(APPLICATION) +#ifdef APPLICATION #ifndef CONFIG_CPU #define CONFIG_CPU 0 #endif @@ -1038,8 +1033,7 @@ Lyre prototype 1 */ #if defined(ASSEMBLER_THREADS) \ || defined(HAVE_WIN32_FIBER_THREADS) \ - || defined(HAVE_SIGALTSTACK_THREADS) \ - || defined(CTRU) + || defined(HAVE_SIGALTSTACK_THREADS) #define HAVE_PRIORITY_SCHEDULING #endif @@ -1110,7 +1104,7 @@ Lyre prototype 1 */ * Older versions of GCC emit assembly in divided syntax with no option * to enable unified syntax. */ -#if (__GNUC__ < 8) && defined(CPU_ARM_CLASSIC) || defined(CTRU) +#if (__GNUC__ < 8) && defined(CPU_ARM_CLASSIC) #define BEGIN_ARM_ASM_SYNTAX_UNIFIED ".syntax unified\n" #define END_ARM_ASM_SYNTAX_UNIFIED ".syntax divided\n" #else diff --git a/firmware/export/config/ctru.h b/firmware/export/config/ctru.h deleted file mode 100644 index 0edaf145a5..0000000000 --- a/firmware/export/config/ctru.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This config file is for the N3DS hosted application - */ - -/* We don't run on hardware directly */ -#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_CTRU) -#define HAVE_FPU - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 100s -#define MODEL_NAME "CTRU" - -#define USB_NONE - -#define CONFIG_CPU N10480H - -#define CPU_FREQ 268000000 - -/* Define this if you have adjustable CPU frequency */ -/* #define HAVE_ADJUSTABLE_CPU_FREQ */ - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you want album art for this target */ -#define HAVE_ALBUMART - -/* define this to enable bitmap scaling */ -#define HAVE_BMP_SCALING - -/* define this to enable JPEG decoding */ -#define HAVE_JPEG - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* LCD dimensions */ -#define LCD_WIDTH 320 -#define LCD_HEIGHT 240 - -#define LCD_DEPTH 16 -#define LCD_PIXELFORMAT RGB565 - -#define LCD_OPTIMIZED_UPDATE -#define LCD_OPTIMIZED_UPDATE_RECT -#define LCD_OPTIMIZED_BLIT_YUV - -/* define this to indicate your device's keypad */ -#define HAVE_TOUCHSCREEN -#define HAVE_BUTTON_DATA - -/* define this if you have a real-time clock */ -#define CONFIG_RTC APPLICATION - -/* Power management */ -#define CONFIG_BATTERY_MEASURE PERCENTAGE_MEASURE -#define CONFIG_CHARGING CHARGING_MONITOR -#define HAVE_SW_POWEROFF - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x80000 - -#define AB_REPEAT_ENABLE - - -/* #define HAVE_SCROLLWHEEL */ -#define CONFIG_KEYPAD CTRU_PAD - -#define HAVE_CTRU_AUDIO -#define HAVE_HEADPHONE_DETECTION -/* #define HAVE_SW_VOLUME_CONTROL */ -/* #define PCM_SW_VOLUME_UNBUFFERED */ -/* #define PCM_SW_VOLUME_FRACBITS (16) */ - -/* Define this for LCD backlight available */ -#define HAVE_BACKLIGHT -#define HAVE_BACKLIGHT_BRIGHTNESS - -/* Main LCD backlight brightness range and defaults */ -#define MIN_BRIGHTNESS_SETTING 16 -#define MAX_BRIGHTNESS_SETTING 142 -#define BRIGHTNESS_STEP 5 -#define DEFAULT_BRIGHTNESS_SETTING 28 -#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING - -#define CONFIG_LCD LCD_COWOND2 - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY - -#define BOOTDIR "/" - -/* No special storage */ -#define CONFIG_STORAGE STORAGE_HOSTFS -#define HAVE_STORAGE_FLUSH - diff --git a/firmware/export/debug.h b/firmware/export/debug.h index 623b9e4827..3a4a774f42 100644 --- a/firmware/export/debug.h +++ b/firmware/export/debug.h @@ -35,10 +35,6 @@ extern void ldebugf(const char* file, int line, const char *fmt, ...) || (defined(APPLICATION) && defined(DEBUG)) #define DEBUGF debugf #define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__) -#elif (CONFIG_PLATFORM & PLATFORM_CTRU) -/* let's use second display for debug output */ -#define DEBUGF debugf -#define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__) #elif defined(DEBUG) /* DEBUG on native targets */ #ifdef HAVE_GDB_API diff --git a/firmware/export/hosted_codec.h b/firmware/export/hosted_codec.h index 1a689c534b..5391ca8ee9 100644 --- a/firmware/export/hosted_codec.h +++ b/firmware/export/hosted_codec.h @@ -21,9 +21,8 @@ #ifndef HOSTED_CODEC_H #define HOSTED_CODEC_H -#if (defined(HAVE_SDL_AUDIO) \ - && !(CONFIG_PLATFORM & PLATFORM_MAEMO5)) \ - || (CONFIG_PLATFORM & PLATFORM_CTRU) +#if defined(HAVE_SDL_AUDIO) \ + && !(CONFIG_PLATFORM & PLATFORM_MAEMO5) AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -80, 0, 0) #else #define AUDIOHW_CAPS (MONO_VOL_CAP) diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h index 322f47bbe0..72715906b9 100644 --- a/firmware/export/rbpaths.h +++ b/firmware/export/rbpaths.h @@ -41,7 +41,7 @@ /* NOTE: target-specific hosted HOME_DIR resides in filesystem-app.c */ #if !defined(APPLICATION) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || \ defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX) || \ - defined(HIBY_LINUX) || defined(FIIO_M3K_LINUX) || defined(CTRU) + defined(HIBY_LINUX) || defined(FIIO_M3K_LINUX) #define HOME_DIR "/" @@ -87,7 +87,7 @@ #if defined(APPLICATION) && \ !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || \ - defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX) || defined(FIIO_M3K_LINUX) || defined(CTRU)) + defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX) || defined(FIIO_M3K_LINUX)) #define PLUGIN_DATA_DIR ROCKBOX_DIR "/rocks.data" #define PLUGIN_GAMES_DATA_DIR PLUGIN_DATA_DIR diff --git a/firmware/include/_ansi.h b/firmware/include/_ansi.h index d5b19172e7..5f0ce211ed 100644 --- a/firmware/include/_ansi.h +++ b/firmware/include/_ansi.h @@ -9,8 +9,8 @@ "comment out" the non-ANSI parts of the ANSI header files (non-ANSI header files aren't affected). */ -#ifndef __ANSIDECL_H__ -#define __ANSIDECL_H__ +#ifndef _ANSIDECL_H_ +#define _ANSIDECL_H_ /* First try to figure out whether we really are in an ANSI C environment. */ /* FIXME: This probably needs some work. Perhaps sys/config.h can be @@ -64,4 +64,4 @@ #endif #endif -#endif /* __ANSIDECL_H__ */ +#endif /* _ANSIDECL_H_ */ diff --git a/firmware/include/dir.h b/firmware/include/dir.h index 516b407bf1..6336cee81d 100644 --- a/firmware/include/dir.h +++ b/firmware/include/dir.h @@ -28,9 +28,7 @@ #include "fs_attr.h" #include "fs_defines.h" -#if defined(CTRU) && !defined(SIMULATOR) -#include "filesystem-ctru.h" -#elif defined (APPLICATION) || defined(CHECKWPS) +#if defined (APPLICATION) || defined(CHECKWPS) #include "filesystem-app.h" #elif defined(SIMULATOR) || defined(DBTOOL) #include "../../uisimulator/common/filesystem-sim.h" diff --git a/firmware/include/file.h b/firmware/include/file.h index 324a657848..20b2224db6 100644 --- a/firmware/include/file.h +++ b/firmware/include/file.h @@ -40,9 +40,7 @@ enum relate_result RELATE_PREFIX, /* the path2 contains path1 as a prefix */ }; -#if defined(CTRU) && !defined(SIMULATOR) -#include "filesystem-ctru.h" -#elif defined(APPLICATION) || defined(CHECKWPS) +#if defined(APPLICATION) || defined(CHECKWPS) #include "filesystem-app.h" #elif defined(SIMULATOR) || defined(DBTOOL) #include "../../uisimulator/common/filesystem-sim.h" diff --git a/firmware/include/rbendian.h b/firmware/include/rbendian.h index 690c9a115a..16888335fe 100644 --- a/firmware/include/rbendian.h +++ b/firmware/include/rbendian.h @@ -28,7 +28,7 @@ #endif #ifndef __MINGW32__ -#if defined(__APPLE__) || defined(CTRU) +#ifdef __APPLE__ #include #else #include diff --git a/firmware/kernel/include/thread.h b/firmware/kernel/include/thread.h index a80080b979..5cf7c71b78 100644 --- a/firmware/kernel/include/thread.h +++ b/firmware/kernel/include/thread.h @@ -89,7 +89,7 @@ struct thread_entry; * * simulator (possibly) doesn't simulate stack usage anyway but well ... */ -#if defined(HAVE_SDL_THREADS) || defined(__PCTOOL__) || defined(CTRU) +#if defined(HAVE_SDL_THREADS) || defined(__PCTOOL__) #define DEFAULT_STACK_SIZE 0x100 /* tiny, ignored anyway */ #else #include "asm/thread.h" diff --git a/firmware/kernel/mutex.c b/firmware/kernel/mutex.c index eb09b9d68c..b1ae3e9e54 100644 --- a/firmware/kernel/mutex.c +++ b/firmware/kernel/mutex.c @@ -75,15 +75,11 @@ void mutex_lock(struct mutex *m) /* Release ownership of a mutex object - only owning thread must call this */ void mutex_unlock(struct mutex *m) { -#ifndef CTRU - /* FIXME: synchronization primitives does not behave - correctly between different cores */ /* unlocker not being the owner is an unlocking violation */ KERNEL_ASSERT(m->blocker.thread == __running_self_entry(), "mutex_unlock->wrong thread (%s != %s)\n", m->blocker.thread->name, __running_self_entry()->name); -#endif if(m->recursion > 0) { diff --git a/firmware/kernel/thread-common.c b/firmware/kernel/thread-common.c index 074af1b7e1..76424e9e9c 100644 --- a/firmware/kernel/thread-common.c +++ b/firmware/kernel/thread-common.c @@ -304,7 +304,7 @@ int thread_get_debug_info(unsigned int thread_id, #ifdef HAVE_SCHEDULER_BOOSTCTRL cpu_boost = thread->cpu_boost; #endif -#if !defined(HAVE_SDL_THREADS) && !defined(CTRU) +#ifndef HAVE_SDL_THREADS infop->stack_usage = stack_usage(thread->stack, thread->stack_size); size_t stack_used_current = diff --git a/firmware/kernel/thread-internal.h b/firmware/kernel/thread-internal.h index f7e3d82117..2d2eb161bd 100644 --- a/firmware/kernel/thread-internal.h +++ b/firmware/kernel/thread-internal.h @@ -32,7 +32,7 @@ * * simulator (possibly) doesn't simulate stack usage anyway but well ... */ -#if defined(HAVE_SDL_THREADS) || defined(__PCTOOL__) || defined(CTRU) +#if defined(HAVE_SDL_THREADS) || defined(__PCTOOL__) struct regs { void *t; /* OS thread */ diff --git a/firmware/target/hosted/ctru/app/adc-target.h b/firmware/target/hosted/ctru/app/adc-target.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/firmware/target/hosted/ctru/app/backlight-target.h b/firmware/target/hosted/ctru/app/backlight-target.h deleted file mode 100644 index b29005f7e1..0000000000 --- a/firmware/target/hosted/ctru/app/backlight-target.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************** - * __________ __ ___ - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * Copyright (C) 2017 Marcin Bukat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _BACKLIGHT_TARGET_H_ -#define _BACKLIGHT_TARGET_H_ - -#include - -/* See backlight.c */ -bool backlight_hw_init(void); -void backlight_hw_on(void); -void backlight_hw_off(void); -void backlight_hw_brightness(int brightness); - -#endif diff --git a/firmware/target/hosted/ctru/app/button-target.h b/firmware/target/hosted/ctru/app/button-target.h deleted file mode 100644 index 36fed8b59d..0000000000 --- a/firmware/target/hosted/ctru/app/button-target.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Rob Purchase - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -/* Logical buttons key codes */ -#define BUTTON_UP 0x00000001 -#define BUTTON_DOWN 0x00000002 -#define BUTTON_LEFT 0x00000004 -#define BUTTON_RIGHT 0x00000008 -#define BUTTON_USER 0x00000010 -#define BUTTON_MENU 0x00000020 -#define BUTTON_BACK 0x00000040 -#define BUTTON_POWER 0x00000080 -#define BUTTON_SELECT 0x00000100 - -/* Touch Screen Area Buttons */ -#define BUTTON_TOPLEFT 0x00001000 -#define BUTTON_TOPMIDDLE 0x00002000 -#define BUTTON_TOPRIGHT 0x00004000 -#define BUTTON_MIDLEFT 0x00008000 -#define BUTTON_CENTER 0x00010000 -#define BUTTON_MIDRIGHT 0x00020000 -#define BUTTON_BOTTOMLEFT 0x00040000 -#define BUTTON_BOTTOMMIDDLE 0x00080000 -#define BUTTON_BOTTOMRIGHT 0x00100000 - -#define BUTTON_MAIN 0x1FFF - -/* Software power-off */ -#define POWEROFF_BUTTON BUTTON_POWER -/* About 3 seconds */ -#define POWEROFF_COUNT 10 - -#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/hosted/ctru/backlight-ctru.c b/firmware/target/hosted/ctru/backlight-ctru.c deleted file mode 100644 index 917db29405..0000000000 --- a/firmware/target/hosted/ctru/backlight-ctru.c +++ /dev/null @@ -1,114 +0,0 @@ -/*************************************************************************** - * __________ __ ___ - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include "config.h" -#include "backlight-target.h" -#include "sysfs.h" -#include "panic.h" -#include "lcd.h" -#include "debug.h" - -#include <3ds/services/gsplcd.h> -#include <3ds/result.h> -#include "luminance-ctru.h" - -/* TODO: To use calibrated values in rockbox, - MIN_BRIGHTNESS_SETTING (etc) would need to be - declared as constants in settings-list.c */ - -u32 ctru_min_lum = 16; -u32 ctru_max_lum = 142; -u32 ctru_luminance = 28; - -/* FIXME: After calling gspLcdInit() the home menu will no longer be - accesible, to fix this we have to call gspLcdInit/gspLcdExit as - a mutex lock/unlock when using gsplcd.h functions. */ -void lcd_mutex_lock(void) -{ - Result res = gspLcdInit(); - if (R_FAILED(res)) { - DEBUGF("backlight_hw_init: gspLcdInit failed.\n"); - } -} - -void lcd_mutex_unlock(void) -{ - gspLcdExit(); -} - -bool backlight_hw_init(void) -{ - /* read calibrated values */ - ctru_luminance = getCurrentLuminance(false); - ctru_min_lum = getMinLuminancePreset(); - ctru_max_lum = getMaxLuminancePreset(); - - backlight_hw_on(); - backlight_hw_brightness(DEFAULT_BRIGHTNESS_SETTING); - return true; -} - -static int last_bl = -1; - -void backlight_hw_on(void) -{ - lcd_mutex_lock(); - if (last_bl != 1) { -#ifdef HAVE_LCD_ENABLE - lcd_enable(true); -#endif - GSPLCD_PowerOnAllBacklights(); - last_bl = 1; - } - lcd_mutex_unlock(); -} - -void backlight_hw_off(void) -{ - lcd_mutex_lock(); - if (last_bl != 0) { - /* only power off rockbox ui screen */ - GSPLCD_PowerOffBacklight(GSPLCD_SCREEN_BOTTOM); -#ifdef HAVE_LCD_ENABLE - lcd_enable(false); -#endif - last_bl = 0; - } - lcd_mutex_unlock(); -} - -void backlight_hw_brightness(int brightness) -{ - /* cap range, just in case */ - if (brightness > MAX_BRIGHTNESS_SETTING) - brightness = MAX_BRIGHTNESS_SETTING; - if (brightness < MIN_BRIGHTNESS_SETTING) - brightness = MIN_BRIGHTNESS_SETTING; - - /* normalize level on both screens */ - lcd_mutex_lock(); - GSPLCD_SetBrightnessRaw(GSPLCD_SCREEN_TOP | GSPLCD_SCREEN_BOTTOM, (u32) brightness); - lcd_mutex_unlock(); -} diff --git a/firmware/target/hosted/ctru/button-ctru.c b/firmware/target/hosted/ctru/button-ctru.c deleted file mode 100644 index c28d7e56ae..0000000000 --- a/firmware/target/hosted/ctru/button-ctru.c +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Felix Arends - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include /* EXIT_SUCCESS */ -#include -#include "config.h" -#include "button.h" -#include "kernel.h" -#include "backlight.h" -#include "system.h" -#include "button-ctru.h" -#include "buttonmap.h" -#include "debug.h" -#include "powermgmt.h" -#include "storage.h" -#include "settings.h" -#include "sound.h" -#include "misc.h" - -#include "touchscreen.h" - -#include <3ds/types.h> -#include <3ds/services/apt.h> -#include <3ds/services/hid.h> -#include <3ds/services/mcuhwc.h> -#include <3ds/services/dsp.h> - -static u8 old_slider_level = 0; -static int last_y, last_x; - -static enum { - STATE_UNKNOWN = -1, - STATE_UP = 0, - STATE_DOWN = 1, -} last_touch_state = STATE_UNKNOWN; - -static double map_values(double n, double source_start, double source_end, double dest_start, double dest_end, int decimal_precision ) { - double delta_start = source_end - source_start; - double delta_end = dest_end - dest_start; - if(delta_start == 0.0 || delta_end == 0.0) { - return 1.0; - } - double scale = delta_end / delta_start; - double neg_start = -1.0 * source_start; - double offset = (neg_start * scale) + dest_start; - double final_number = (n * scale) + offset; - int calc_scale = (int) pow(10.0, decimal_precision); - return (double) round(final_number * calc_scale) / calc_scale; -} - -void update_sound_slider_level(void) -{ - /* update global volume based on sound slider level */ - u8 level; - MCUHWC_GetSoundSliderLevel(&level); - - if (level != old_slider_level) { - int volume = (int) map_values((double) level, - 0.0, /* min slider voslume */ - (double) 0x3f, /* max slider value */ - (double) sound_min(SOUND_VOLUME), - (double) sound_max(SOUND_VOLUME), - 0); - global_status.volume = volume; - setvol(); - old_slider_level = level; - } -} - -int button_read_device(int* data) -{ - int key = BUTTON_NONE; - - /* TODO: implement Home Menu button support */ - /* if (!aptMainLoop()) { - return true; - } */ - - hidScanInput(); - u32 kDown = hidKeysDown(); - - if (kDown & KEY_SELECT) { - touchscreen_set_mode(touchscreen_get_mode() == TOUCHSCREEN_POINT ? TOUCHSCREEN_BUTTON : TOUCHSCREEN_POINT); - printf("Touchscreen mode: %s\n", touchscreen_get_mode() == TOUCHSCREEN_POINT ? "TOUCHSCREEN_POINT" : "TOUCHSCREEN_BUTTON"); - } - - u32 kHeld = hidKeysHeld(); - - /* rockbox will handle button repeats */ - kDown |= kHeld; - - /* Check for all the keys */ - if (kDown & KEY_A) { - key |= BUTTON_SELECT; - } - if (kDown & KEY_B) { - key |= BUTTON_BACK; - } - if (kDown & KEY_X) { - key |= BUTTON_MENU; - } - if (kDown & KEY_Y) { - key |= BUTTON_USER; - } - if (kDown & KEY_START) { - key |= BUTTON_POWER; - } - if (kDown & KEY_DRIGHT) { - key |= BUTTON_RIGHT; - } - if (kDown & KEY_DLEFT) { - key |= BUTTON_LEFT; - } - if (kDown & KEY_DUP) { - key |= BUTTON_UP; - } - if (kDown & KEY_DDOWN) { - key |= BUTTON_DOWN; - } - if (kDown & KEY_START) { - key |= BUTTON_POWER; - } - - touchPosition touch; - hidTouchRead(&touch); - - /* Generate UP and DOWN events */ - if (kDown & KEY_TOUCH) { - last_touch_state = STATE_DOWN; - } - else { - last_touch_state = STATE_UP; - } - - last_x = touch.px; - last_y = touch.py; - - int tkey = touchscreen_to_pixels(last_x, last_y, data); - if (last_touch_state == STATE_DOWN) { - key |= tkey; - } - - update_sound_slider_level(); - - return key; -} - -void button_init_device(void) -{ - hidInit(); -} - -#ifndef HAS_BUTTON_HOLD -void touchscreen_enable_device(bool en) -{ - (void)en; -} -#endif - -bool headphones_inserted(void) -{ - bool is_inserted; - DSP_GetHeadphoneStatus(&is_inserted); - return is_inserted; -} diff --git a/firmware/target/hosted/ctru/button-ctru.h b/firmware/target/hosted/ctru/button-ctru.h deleted file mode 100644 index 637fcbf077..0000000000 --- a/firmware/target/hosted/ctru/button-ctru.h +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Thomas Martitz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - - -#ifndef __BUTTON_CTRU_H__ -#define __BUTTON_CTRU_H__ - -#include -#include "config.h" - -bool button_hold(void); -#undef button_init_device -void button_init_device(void); -int button_read_device(int *data); - -#endif /* __BUTTON_CTRU_H__ */ diff --git a/firmware/target/hosted/ctru/buttonmap.h b/firmware/target/hosted/ctru/buttonmap.h deleted file mode 100644 index b6fcaa2efc..0000000000 --- a/firmware/target/hosted/ctru/buttonmap.h +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 by Fred Bauer - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __BUTTONMAP_H__ -#define __BUTTONMAP_H__ -/* Button maps: simulated key, x, y, radius, name */ -/* Run sim with --mapping to get coordinates */ -/* or --debugbuttons to check */ -/* The First matching button is returned */ -struct button_map { - int button, x, y, radius; - char *description; -}; - -extern struct button_map bm[]; - -int xy2button( int x, int y); - -#ifdef HAVE_TOUCHSCREEN -int key_to_touch(int keyboard_button, unsigned int mouse_coords); -#endif - -#endif /* __BUTTONMAP_H__ */ diff --git a/firmware/target/hosted/ctru/filesystem-ctru.c b/firmware/target/hosted/ctru/filesystem-ctru.c deleted file mode 100644 index 607a2e2ed6..0000000000 --- a/firmware/target/hosted/ctru/filesystem-ctru.c +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 by Thomas Martitz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#define RB_FILESYSTEM_OS -#include -#include -#include -#include -#include -#include "config.h" -#include "system.h" -#include "file.h" -#include "dir.h" -#include "mv.h" -#include "debug.h" -#include "pathfuncs.h" -#include "string-extra.h" - -#include <3ds/archive.h> - -void paths_init(void) -{ - /* is this needed in 3DS? */ -#if 0 - char config_dir[MAX_PATH]; - - const char *home = "/3ds"; - mkdir("/3ds/.rockbox" __MKDIR_MODE_ARG); - - snprintf(config_dir, sizeof(config_dir), "%s/.config", home); - mkdir(config_dir __MKDIR_MODE_ARG); - snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org", home); - mkdir(config_dir __MKDIR_MODE_ARG); - /* Plugin data directory */ - snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org/rocks.data", home); - mkdir(config_dir __MKDIR_MODE_ARG); -#endif -} - -/* only sdcard volume is accesible to the user */ -void volume_size(IF_MV(int volume,) sector_t *sizep, sector_t *freep) -{ - sector_t size = 0, free = 0; - - FS_ArchiveResource sdmcRSRC; - FSUSER_GetSdmcArchiveResource(&sdmcRSRC); - - size = (sdmcRSRC.totalClusters * sdmcRSRC.clusterSize) / sdmcRSRC.sectorSize; - free = (sdmcRSRC.freeClusters * sdmcRSRC.clusterSize) / sdmcRSRC.sectorSize; - - if (sizep) - *sizep = size; - - if (freep) - *freep = free; -} diff --git a/firmware/target/hosted/ctru/filesystem-ctru.h b/firmware/target/hosted/ctru/filesystem-ctru.h deleted file mode 100644 index a67c7b58a0..0000000000 --- a/firmware/target/hosted/ctru/filesystem-ctru.h +++ /dev/null @@ -1,116 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 by Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _FILESYSTEM_CTRU_H_ -#define _FILESYSTEM_CTRU_H_ - -#if defined(PLUGIN) || defined(CODEC) -#define FILEFUNCTIONS_DECLARED -#define FILEFUNCTIONS_DEFINED -#define DIRFUNCTIONS_DECLARED -#define DIRFUNCTIONS_DEFINED -#define OSFUNCTIONS_DECLARED -#endif /* PLUGIN || CODEC */ - -#ifndef OSFUNCTIONS_DECLARED -#define FS_PREFIX(_x_) ctru_ ## _x_ - -void paths_init(void); -#endif /* !OSFUNCTIONS_DECLARED */ -#endif /* _FILESYSTEM_CTRU_H_ */ - -#ifdef _FILE_H_ -#include - -#ifndef _FILESYSTEM_CTRU__FILE_H_ -#define _FILESYSTEM_CTRU__FILE_H_ - -#ifdef RB_FILESYSTEM_OS -#define FILEFUNCTIONS_DEFINED -#endif - -#ifndef FILEFUNCTIONS_DECLARED -#define __OPEN_MODE_ARG -#define __CREAT_MODE_ARG \ - , mode - -#include - -int ctru_open(const char *name, int oflag, ...); -int ctru_creat(const char *name, mode_t mode); -int ctru_close(int fildes); -int ctru_ftruncate(int fildes, off_t length); -int ctru_fsync(int fildes); -off_t ctru_lseek(int fildes, off_t offset, int whence); -ssize_t ctru_read(int fildes, void *buf, size_t nbyte); -ssize_t ctru_write(int fildes, const void *buf, size_t nbyte); -int ctru_remove(const char *path); -int ctru_rename(const char *old, const char *new); -int ctru_modtime(const char *path, time_t modtime); -off_t ctru_filesize(int fildes); -int ctru_fsamefile(int fildes1, int fildes2); -int ctru_relate(const char *path1, const char *path2); -bool ctru_file_exists(const char *path); -ssize_t ctru_readlink(const char *path, char *buf, size_t bufsiz); - -#endif /* !FILEFUNCTIONS_DECLARED */ - -#endif /* _FILESYSTEM_CTRU__FILE_H_ */ -#endif /* _FILE_H_ */ - -#ifdef _DIR_H_ -#ifndef _FILESYSTEM_CTRU__DIR_H_ -#define _FILESYSTEM_CTRU__DIR_H_ - -#define DIRENT dirent -struct dirent; - -struct dirinfo_native -{ - unsigned int attr; - off_t size; - uint16_t wrtdate; - uint16_t wrttime; -}; - -typedef struct {} DIR; - -#ifndef DIRFUNCTIONS_DECLARED -#define __MKDIR_MODE_ARG \ - , 0777 - -#ifdef RB_FILESYSTEM_OS -#define DIRFUNCTIONS_DEFINED -#endif - -DIR * ctru_opendir(const char *dirname); -struct dirent * ctru_readdir(DIR *dirp); -int ctru_readdir_r(DIR *dirp, struct dirent *entry, - struct dirent **result); -void ctru_rewinddir(DIR *dirp); -int ctru_closedir(DIR *dirp); -int ctru_mkdir(const char *path); -int ctru_rmdir(const char *path); -int ctru_samedir(DIR *dirp1, DIR *dirp2); -bool ctru_dir_exists(const char *dirname); -#endif /* !DIRFUNCTIONS_DECLARED */ - -#endif /* _FILESYSTEM_CTRU__DIR_H_ */ -#endif /* _DIR_H_ */ diff --git a/firmware/target/hosted/ctru/kernel-ctru.c b/firmware/target/hosted/ctru/kernel-ctru.c deleted file mode 100644 index e035af282d..0000000000 --- a/firmware/target/hosted/ctru/kernel-ctru.c +++ /dev/null @@ -1,166 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include "system-ctru.h" -#include "thread-ctru.h" -#include "kernel.h" -#include "thread.h" -#include "panic.h" -#include "debug.h" - -static int tick_timer_id; -long start_tick; - -/* Condition to signal that "interrupts" may proceed */ -static sysCond *sim_thread_cond; -/* Mutex to serialize changing levels and exclude other threads while - * inside a handler */ -static RecursiveLock sim_irq_mtx; -/* Level: 0 = enabled, not 0 = disabled */ -static int volatile interrupt_level = HIGHEST_IRQ_LEVEL; -/* How many handers waiting? Not strictly needed because CondSignal is a - * noop if no threads were waiting but it filters-out calls to functions - * with higher overhead and provides info when debugging. */ -static int handlers_pending = 0; -/* 1 = executing a handler; prevents CondSignal calls in set_irq_level - * while in a handler */ -static int status_reg = 0; - -/* Nescessary logic: - * 1) All threads must pass unblocked - * 2) Current handler must always pass unblocked - * 3) Threads must be excluded when irq routine is running - * 4) No more than one handler routine should execute at a time - */ -int set_irq_level(int level) -{ - RecursiveLock_Lock(&sim_irq_mtx); - - int oldlevel = interrupt_level; - - if (status_reg == 0 && level == 0 && oldlevel != 0) - { - /* Not in a handler and "interrupts" are going from disabled to - * enabled; signal any pending handlers still waiting */ - if (handlers_pending > 0) - sys_cond_broadcast(sim_thread_cond); - } - - interrupt_level = level; /* save new level */ - - RecursiveLock_Unlock(&sim_irq_mtx); - return oldlevel; -} - -void sim_enter_irq_handler(void) -{ - RecursiveLock_Lock(&sim_irq_mtx); - handlers_pending++; - - /* Check each time before proceeding: disabled->enabled->...->disabled - * is possible on an app thread before a handler thread is ever granted - * the mutex; a handler can also leave "interrupts" disabled during - * its execution */ - while (interrupt_level != 0) - sys_cond_wait(sim_thread_cond, &sim_irq_mtx); - - status_reg = 1; -} - -void sim_exit_irq_handler(void) -{ - /* If any others are waiting, give the signal */ - if (--handlers_pending > 0) - sys_cond_signal(sim_thread_cond); - - status_reg = 0; - RecursiveLock_Unlock(&sim_irq_mtx); -} - -static bool sim_kernel_init(void) -{ - RecursiveLock_Init(&sim_irq_mtx); - sim_thread_cond = sys_cond_create(); - if (sim_thread_cond == NULL) - { - panicf("Cannot create sim_thread_cond\n"); - return false; - } - return true; -} - -void sim_kernel_shutdown(void) -{ - sys_remove_timer(tick_timer_id); - enable_irq(); - while(handlers_pending > 0) - sys_delay(10); - - sys_cond_destroy(sim_thread_cond); -} - -u32 tick_timer(u32 interval, void *param) -{ - long new_tick; - - (void) interval; - (void) param; - - new_tick = (sys_get_ticks() - start_tick) / (1000/HZ); - - while(new_tick != current_tick) - { - sim_enter_irq_handler(); - - /* Run through the list of tick tasks - increments tick - * on each iteration. */ - call_tick_tasks(); - - sim_exit_irq_handler(); - } - - return interval; -} - -void tick_start(unsigned int interval_in_ms) -{ - if (!sim_kernel_init()) - { - panicf("Could not initialize kernel!"); - exit(-1); - } - - if (tick_timer_id != 0) - { - sys_remove_timer(tick_timer_id); - tick_timer_id = 0; - } - else - { - start_tick = sys_get_ticks(); - } - - tick_timer_id = sys_add_timer(interval_in_ms, tick_timer, NULL); -} - diff --git a/firmware/target/hosted/ctru/lc-ctru.c b/firmware/target/hosted/ctru/lc-ctru.c deleted file mode 100644 index e65adbbf5a..0000000000 --- a/firmware/target/hosted/ctru/lc-ctru.c +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#define RB_FILESYSTEM_OS -#include -#include -#include -#include "system.h" -#include "load_code.h" -#include "filesystem-ctru.h" -#include "debug.h" - -void* programResolver(const char* sym, void *userData); -void * lc_open(const char *filename, unsigned char *buf, size_t buf_size) -{ - DEBUGF("dlopen(path=\"%s\")\n", filename); - - /* note: the 3ds dlopen implementation needs a custom resolver - for the unresolved symbols in shared objects */ - /* void *handle = dlopen(filename, RTLD_NOW | RTLD_LOCAL); */ - void *handle = ctrdlOpen(filename, - RTLD_NOW | RTLD_LOCAL, - programResolver, - NULL); - if (handle == NULL) - { - DEBUGF("%s(\"%s\") failed\n", __func__, filename); - DEBUGF(" lc_open error '%s'\n", dlerror()); - } - DEBUGF("handle = %p\n", handle); - - return handle; - (void) buf; (void) buf_size; -} - -void * lc_get_header(void *handle) -{ - void *symbol = dlsym(handle, "__header"); - if (!symbol) { - symbol = dlsym(handle, "___header"); - } - - return symbol; -} - -void lc_close(void *handle) -{ - if (handle) { - dlclose(handle); - } -} diff --git a/firmware/target/hosted/ctru/lc-program-resolver.c b/firmware/target/hosted/ctru/lc-program-resolver.c deleted file mode 100644 index 5c504b1069..0000000000 --- a/firmware/target/hosted/ctru/lc-program-resolver.c +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include "debug.h" - -#define RESOLVER_ENTRY(name) \ - if (!strcmp(symName, #name)) \ - return (void *)name; - -/* void* ctrdlProgramResolver(const char* symName) */ -void* programResolver(const char* symName, void *userData) -{ - DEBUGF("programResolver(name=\"%s\")\n", symName); - - /* codecs, etc */ - RESOLVER_ENTRY(abs); - RESOLVER_ENTRY(labs); - RESOLVER_ENTRY(llabs); - RESOLVER_ENTRY(printf); - - /* plugins */ - RESOLVER_ENTRY(_ctype_); - RESOLVER_ENTRY(__errno); - RESOLVER_ENTRY(longjmp); - RESOLVER_ENTRY(setjmp); - - return NULL; - (void) userData; -} diff --git a/firmware/target/hosted/ctru/lcd-bitmap.c b/firmware/target/hosted/ctru/lcd-bitmap.c deleted file mode 100644 index 571857b9f3..0000000000 --- a/firmware/target/hosted/ctru/lcd-bitmap.c +++ /dev/null @@ -1,245 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 Dan Everton - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include "debug.h" -#include "system.h" -#include "button-ctru.h" -#include "screendump.h" -#include "lcd-target.h" - -#include <3ds/gfx.h> -#include <3ds/allocator/linear.h> -#include <3ds/console.h> -#include <3ds/services/cfgu.h> - -/*#define LOGF_ENABLE*/ -#include "logf.h" - -fb_data *dev_fb = 0; - -static u8 system_model = CFG_MODEL_3DS; - -typedef struct -{ - int width, height; -} dimensions_t; - -int get_dest_offset(int x, int y, int dest_width) -{ - return dest_width - y - 1 + dest_width * x; -} - -int get_source_offset(int x, int y, int source_width) -{ - return x + y * source_width; -} - -void copy_framebuffer_16(u16 *dest, const dimensions_t dest_dim, const u16 *source, const dimensions_t source_dim) -{ - int rows = MIN(dest_dim.width, source_dim.height); - int cols = MIN(dest_dim.height, source_dim.width); - for (int y = 0; y < rows; ++y) { - for (int x = 0; x < cols; ++x) { - const u16 *s = source + get_source_offset(x, y, source_dim.width); - u16 *d = dest + get_dest_offset(x, y, dest_dim.width); - *d = *s; - } - } -} - -void copy_framebuffer_24(u8 *dest, const dimensions_t dest_dim, const u8 *source, const dimensions_t source_dim) -{ - int rows = MIN(dest_dim.width, source_dim.height); - int cols = MIN(dest_dim.height, source_dim.width); - for (int y = 0; y < rows; ++y) { - for (int x = 0; x < cols; ++x) { - const u8 *s = source + get_source_offset(x, y, source_dim.width) * 3; - u8 *d = dest + get_dest_offset(x, y, dest_dim.width) * 3; - d[0] = s[0]; - d[1] = s[1]; - d[2] = s[2]; - } - } -} - -void copy_framebuffer_32(u32 *dest, const dimensions_t dest_dim, const u32 *source, const dimensions_t source_dim) -{ - int rows = MIN(dest_dim.width, source_dim.height); - int cols = MIN(dest_dim.height, source_dim.width); - for (int y = 0; y < rows; ++y) { - for (int x = 0; x < cols; ++x) { - const u32 *s = source + get_source_offset(x, y, source_dim.width); - u32 *d = dest + get_dest_offset(x, y, dest_dim.width); - *d = *s; - } - } -} - -void update_framebuffer(void) -{ - u16 fb_width, fb_height; - u32 bufsize; - u8* fb = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, &fb_width, &fb_height); - bufsize = fb_width * fb_height * 2; - - /* lock_window_mutex() */ - - if (FB_DATA_SZ == 2) { - copy_framebuffer_16((void *)fb, (dimensions_t){ fb_width, fb_height }, - (u16 *)dev_fb, (dimensions_t){ LCD_WIDTH, LCD_HEIGHT }); - } - else if (FB_DATA_SZ == 3) { - copy_framebuffer_24((void *)fb, (dimensions_t){ fb_width, fb_height }, - (u8 *)dev_fb, (dimensions_t){ LCD_WIDTH, LCD_HEIGHT }); - } - else { - copy_framebuffer_32((void *)fb, (dimensions_t){ fb_width, fb_height }, - (u32 *)dev_fb, (dimensions_t){ LCD_WIDTH, LCD_HEIGHT }); - } - - // Flush and swap framebuffers - /* gfxFlushBuffers(); */ - GSPGPU_FlushDataCache(fb, bufsize); - gfxSwapBuffers(); - gspWaitForVBlank(); - - /* unlock_window_mutex() */ -} - -/* lcd-as-memframe.c */ -extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, - int width, int height); - -void lcd_update_rect(int x, int y, int width, int height) -{ - fb_data *dst, *src; - - if (x + width > LCD_WIDTH) - width = LCD_WIDTH - x; /* Clip right */ - if (x < 0) - width += x, x = 0; /* Clip left */ - if (width <= 0) - return; /* nothing left to do */ - - if (y + height > LCD_HEIGHT) - height = LCD_HEIGHT - y; /* Clip bottom */ - if (y < 0) - height += y, y = 0; /* Clip top */ - if (height <= 0) - return; /* nothing left to do */ - - dst = LCD_FRAMEBUF_ADDR(x, y); - src = FBADDR(x,y); - - /* Copy part of the Rockbox framebuffer to the second framebuffer */ - if (width < LCD_WIDTH) - { - /* Not full width - do line-by-line */ - lcd_copy_buffer_rect(dst, src, width, height); - } - else - { - /* Full width - copy as one line */ - lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); - } - - update_framebuffer(); -} - -void lcd_update(void) -{ - /* update a full screen rect */ - lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); -} - -void sys_console_init(void) -{ - gfxInit(GSP_BGR8_OES, GSP_RGB565_OES, false); - consoleInit(GFX_TOP, NULL); -} - -void lcd_init_device(void) -{ - gfxSetDoubleBuffering(GFX_BOTTOM, true); - - /* hidInit(); */ - - u16 fb_width, fb_height; - u8* fb = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, &fb_width, &fb_height); - u32 bufsize = fb_width * fb_height * 2; - - dev_fb = (fb_data *) linearAlloc(bufsize); - if (dev_fb == NULL) { - logf("could not allocate dev_fb size %d bytes\n", - bufsize); - exit(EXIT_FAILURE); - } - - memset(dev_fb, 0x00, bufsize); - - /* Set dpi value from system model */ - CFGU_GetSystemModel(&system_model); -} - -void lcd_shutdown(void) -{ - if (dev_fb) { - linearFree(dev_fb); - dev_fb = 0; - } - - /* hidExit(); */ - gfxExit(); -} - -int lcd_get_dpi(void) -{ - /* link: https://www.reddit.com/r/nintendo/comments/2uzk5y/informative_post_about_dpi_on_the_new_3ds/ */ - /* all values for bottom lcd */ - float dpi = 96.0f; - switch(system_model) { - case CFG_MODEL_3DS: - dpi = 132.45f; - break; - case CFG_MODEL_3DSXL: - dpi = 95.69f; - break; - case CFG_MODEL_N3DS: - dpi = 120.1f; - break; - case CFG_MODEL_2DS: - dpi = 132.45f; - break; - case CFG_MODEL_N3DSXL: - dpi = 95.69f; - break; - case CFG_MODEL_N2DSXL: - dpi = 95.69f; - break; - default: - break; - }; - return (int) roundf(dpi); -} - diff --git a/firmware/target/hosted/ctru/lcd-bitmap.h b/firmware/target/hosted/ctru/lcd-bitmap.h deleted file mode 100644 index ba3bcfcc70..0000000000 --- a/firmware/target/hosted/ctru/lcd-bitmap.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __LCDBITMAP_H__ -#define __LCDBITMAP_H__ - -#include "lcd.h" - -void sim_lcd_init(void); -void sys_console_init(void); - -#endif /* #ifndef __LCDBITMAP_H__ */ - diff --git a/firmware/target/hosted/ctru/lcd-target.h b/firmware/target/hosted/ctru/lcd-target.h deleted file mode 100644 index 4b1c1a4315..0000000000 --- a/firmware/target/hosted/ctru/lcd-target.h +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef LCD_TARGET_H -#define LCD_TARGET_H - -#include "lcd.h" - -/* - Framebuffer device and framebuffer access. - See lcd-memframe.c -*/ -extern fb_data *dev_fb; -#define LCD_FRAMEBUF_ADDR(col, row) (dev_fb + row * LCD_WIDTH + col) - -#endif /* LCD_TARGET_H */ - diff --git a/firmware/target/hosted/ctru/lib/bfile/bfile-internal.h b/firmware/target/hosted/ctru/lib/bfile/bfile-internal.h deleted file mode 100644 index e274daf5f5..0000000000 --- a/firmware/target/hosted/ctru/lib/bfile/bfile-internal.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef _BFILE_INTERNAL_H_ -#define _BFILE_INTERNAL_H_ - -#include -#include -#include -#include -#include -#include - -#include <3ds/gfx.h> -#include <3ds/svc.h> -#include <3ds/types.h> -#include <3ds/thread.h> -#include <3ds/result.h> -#include <3ds/services/fs.h> -#include <3ds/synchronization.h> - -/* #define MALLOC_DEBUG -#include "rmalloc/rmalloc.h" */ - -#include "cslice.h" -#include "cmap.h" - -#define nil NULL - -/* in go functions can return two values */ -#define two_type_value(type1, type2, name1, name2, type_name) \ -typedef struct { \ - type1 name1; \ - type2 name2; \ -} type_name##_t; - -/* single mutex implementation */ -#define sync_Mutex LightLock -static inline void sync_MutexInit(sync_Mutex* m) { - LightLock_Init(m); -} - -/* mutex unlock */ -static inline void sync_MutexLock(sync_Mutex* m) { - LightLock_Lock(m); -} - -/* mutex lock */ -static inline void sync_MutexUnlock(sync_Mutex* m) { - LightLock_Unlock(m); -} - -/* read_write mutex implementation */ -typedef struct { - sync_Mutex shared; - CondVar reader_q; - CondVar writer_q; - int active_readers; - int active_writers; - int waiting_writers; -} sync_RWMutex; - -void sync_RWMutexInit(sync_RWMutex *m); -void sync_RWMutexRLock(sync_RWMutex *m); -void sync_RWMutexRUnlock(sync_RWMutex *m); -void sync_RWMutexLock(sync_RWMutex *m); -void sync_RWMutexUnlock(sync_RWMutex *m); - -/* declare a two type value with name 'n_err_t' */ -two_type_value(int, const char*, n, err, int_error); -two_type_value(struct stat, const char*, fi, err, stat_error); -typedef const char* file_error_t; - -typedef struct page { - s64 num; - struct page* prev; - struct page* next; - u8* data; -} page; - -/* the two map types used by this library */ -cmap_declare(page, s64, struct page*); -cmap_declare(bool, s64, bool); - -typedef struct shard { - sync_Mutex mu; - cmap(page) pages; - cmap(bool) dirty; - struct page* head; - struct page* tail; -} shard; - -typedef struct Pager { - Handle file; - s64 pgsize; - s64 pgmax; - /* sync_RWMutex mu; */ - s64 size; - cslice(shard) shards; -} Pager; - -#endif /* _BFILE_INTERNAL_H_ */ diff --git a/firmware/target/hosted/ctru/lib/bfile/bfile.c b/firmware/target/hosted/ctru/lib/bfile/bfile.c deleted file mode 100644 index 8542cf3ae0..0000000000 --- a/firmware/target/hosted/ctru/lib/bfile/bfile.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * This code is based on bfile.go by Josh Baker. - * Converted to C code by Mauricio G. - * Released under the MIT License. - */ - -/* IMPORTANT: this code only works for O_RDONLY and O_RDWR files. */ - -#include "bfile.h" - -/* note: for ease of reading and ease of comparing go code - with c implementation, function names are similar to the - go version */ - -/* note2: sync_RWMutex calls have been moved to rockbox sys_file - implementation. To use as standalone code please uncomment those calls. */ - -void sync_RWMutexInit(sync_RWMutex *m) { - LightLock_Init(&m->shared); - CondVar_Init(&m->reader_q); - CondVar_Init(&m->writer_q); - m->active_readers = 0; - m->active_writers = 0; - m->waiting_writers = 0; -} - -static inline LightLock *unique_lock(LightLock *lk) { - LightLock_Lock(lk); - return lk; -} - -void sync_RWMutexRLock(sync_RWMutex *m) { - LightLock *lk = unique_lock(&m->shared); - while (m->waiting_writers != 0) { - CondVar_Wait(&m->reader_q, lk); - } - ++m->active_readers; - LightLock_Unlock(lk); -} - -void sync_RWMutexRUnlock(sync_RWMutex *m) { - LightLock *lk = unique_lock(&m->shared); - --m->active_readers; - LightLock_Unlock(lk); - CondVar_Signal(&m->writer_q); -} - -void sync_RWMutexLock(sync_RWMutex *m) { - LightLock *lk = unique_lock(&m->shared); - ++m->waiting_writers; - while ((m->active_readers != 0) || (m->active_writers != 0)) { - CondVar_Wait(&m->writer_q, lk); - } - ++m->active_writers; - LightLock_Unlock(lk); -} - -void sync_RWMutexUnlock(sync_RWMutex *m) { - LightLock *lk = unique_lock(&m->shared); - --m->waiting_writers; - --m->active_writers; - if (m->waiting_writers > 0) { - CondVar_Signal(&m->writer_q); - } else { - CondVar_Broadcast(&m->reader_q); - } - LightLock_Unlock(lk); -} - -void s_init(shard* s); - -void s_push(shard* s, page* p) { - s->head->next->prev = p; - p->next = s->head->next; - p->prev = s->head; - s->head->next = p; -} - -void s_pop(shard* s, page* p) { - p->prev->next = p->next; - p->next->prev = p->prev; -} - -void s_bump(shard* s, page* p) { - s_pop(s, p); - s_push(s, p); -} - -/* page_pair_t destructor */ -/* page_pair_t type is defined by cmap_declare(page, s64, struct page*) */ -/* struct { - s64 key; - struct page* value; - } page_pair_t; -*/ -void page_pair_free(void* pair_ptr) { - if (pair_ptr) { - page_pair_t *pair = (page_pair_t*) pair_ptr; - struct page *p = pair->value; - if (p != nil) { - if (p->data != nil) { - free(p->data); - } - free(p); - } - } -} - -/* shard destructor */ -void s_free(void* s_ptr) { - if (s_ptr) { - shard *s = (shard*) s_ptr; - if (s->pages != nil) { - cmap_set_elem_destructor(s->pages, page_pair_free); - cmap_clear(page, s->pages); - cmap_clear(bool, s->dirty); - free(s->head); - free(s->tail); - } - } -} - -Pager* NewPager(Handle file) { - return NewPagerSize(file, 0, 0); -} - -Pager* NewPagerSize(Handle file, int pageSize, int bufferSize) { - if (pageSize <= 0) { - pageSize = defaultPageSize; - } else if ((pageSize & 4095) != 0) { - // must be a power of two - int x = 1; - while (x < pageSize) { - x *= 2; - } - pageSize = x; - } - - if (bufferSize <= 0) { - bufferSize = defaultBufferSize; - } else if (bufferSize < pageSize) { - bufferSize = pageSize; - } - - Pager* f = (Pager*) malloc(sizeof(Pager)); - f->file = file; - f->size = -1; - f->pgsize = (s64) pageSize; - - /* sync_RWMutexInit(&f->mu); */ - - // calculate the max number of pages across all shards - s64 pgmax = (s64) bufferSize / f->pgsize; - if (pgmax < minPages) { - pgmax = minPages; - } - - // calculate how many shards are needed, power of 2 - s64 nshards = (s64) ceil((double) pgmax / (double) pagesPerShard); - if (nshards > maxShards) { - nshards = maxShards; - } - s64 x = 1; - while (x < nshards) { - x *= 2; - } - nshards = x; - - // calculate the max number of pages per shard - f->pgmax = (s64) floor((double) pgmax / (double) nshards); - cslice_make(f->shards, nshards, (shard) { 0 }); - - // initialize sync mutex - size_t i; - for (i = 0; i < cslice_len(f->shards); i++) { - sync_MutexInit(&f->shards[i].mu); - } - return f; -} - -static int_error_t read_at(Handle file, u8 *data, size_t data_len, off_t off) -{ - u32 read_bytes = 0; - if (R_FAILED(FSFILE_Read(file, &read_bytes, (u64) off, data, (u32) data_len))) { - return (int_error_t) { -1, "I/O error" }; - } - - /* io.EOF */ - if (read_bytes == 0) { - return (int_error_t) { 0, "io.EOF" }; - } - - return (int_error_t) { (int) read_bytes, nil }; -} - -static int_error_t write_at(Handle file, u8 *data, size_t data_len, off_t off) -{ - u32 written = 0; - if (R_FAILED(FSFILE_Write(file, &written, (u64) off, data, (u32) data_len, FS_WRITE_FLUSH))) { - return (int_error_t) { -1, "I/O error" }; - } - - /* I/O error */ - if ((written == 0) || (written < (u32) data_len)) { - return (int_error_t) { -1, "I/O error" }; - } - - return (int_error_t) { (int) written, nil }; -} - -static stat_error_t file_stat(Handle file) -{ - u64 size = 0; - struct stat fi = { 0 }; - if (R_FAILED(FSFILE_GetSize(file, &size))) { - fi.st_size = 0; - return (stat_error_t) { fi, "I/O error" }; - } - - fi.st_size = (off_t) size; - return (stat_error_t) { fi, nil }; -} - -void s_init(shard* s) -{ - if (s->pages == nil) { - s->pages = cmap_make(/*s64*/page); - s->dirty = cmap_make(/*s64*/bool); - s->head = (page*) malloc(sizeof(page)); - s->tail = (page*) malloc(sizeof(page)); - s->head->next = s->tail; - s->tail->prev = s->head; - } -} - -file_error_t f_write(Pager* f, page* p) { - s64 off = p->num * f->pgsize; - s64 end = f->pgsize; - if ((off + end) > f->size) { - end = f->size - off; - } - int_error_t __err = write_at(f->file, p->data, end, off); - if (__err.err != nil) { - return __err.err; - } - return nil; -} - -file_error_t f_read(Pager* f, page* p) { - int_error_t __err = read_at(f->file, p->data, f->pgsize, p->num * f->pgsize); - if ((__err.err != nil) && strcmp(__err.err, "io.EOF")) { - return "I/O error"; - } - - return nil; -} - -const char* f_incrSize(Pager* f, s64 end, bool write) -{ -#define defer(m) \ - sync_RWMutexUnlock(&f->mu); \ - sync_RWMutexRLock(&f->mu); - - /* sync_RWMutexRUnlock(&f->mu); - sync_RWMutexLock(&f->mu); */ - - if (f->size == -1) { - stat_error_t fi_err = file_stat(f->file); - if (fi_err.err != nil) { - /* defer(&f->mu); */ - return nil; - } - f->size = fi_err.fi.st_size; - } - if (write && (end > f->size)) { - f->size = end; - } - - /* defer(&f->mu); */ - return nil; -} - -int_error_t f_pio(Pager *f, u8 *b, size_t len_b, s64 pnum, s64 pstart, s64 pend, bool write); -int_error_t f_io(Pager *f, u8 *b, size_t len_b, s64 off, bool write) { - if (f == nil) { - return (int_error_t) { 0, "invalid argument" }; - } - bool eof = false; - s64 start = off, end = off + len_b; - if (start < 0) { - return (int_error_t) { 0, "negative offset" }; - } - - // Check the upper bounds of the input to the known file size. - // Increase the file size if needed. - /* sync_RWMutexRLock(&f->mu); */ - if (end > f->size) { - file_error_t err = f_incrSize(f, end, write); - if (err != nil) { - /* sync_RWMutexRUnlock(&f->mu); */ - return (int_error_t) { 0, err }; - } - if (!write && (end > f->size)) { - end = f->size; - if ((end - start) < 0) { - end = start; - } - eof = true; - len_b = end-start; /* b = b[:end-start] */ - } - } - /* sync_RWMutexRUnlock(&f->mu); */ - - // Perform the page I/O. - int total = 0; - while (len_b > 0) { - s64 pnum = off / f->pgsize; - s64 pstart = off & (f->pgsize - 1); - s64 pend = pstart + (s64) len_b; - if (pend > f->pgsize) { - pend = f->pgsize; - } - - int_error_t result = f_pio(f, b, pend - pstart, pnum, pstart, pend, write); - if (result.err != nil) { - return (int_error_t) { total, result.err }; - } - - off += (s64) result.n; - total += result.n; - b = &b[result.n]; len_b -= result.n; /* b = b[n:] */ - } - if (eof) { - return (int_error_t) { total, "io.EOF" }; - } - - return (int_error_t) { total, nil }; -} - -int_error_t f_pio(Pager *f, u8 *b, size_t len_b, s64 pnum, s64 pstart, s64 pend, bool write) { - /* printf("pio(%p, %d, %lld, %lld, %lld, %s)\n", b, len_b, pnum, pstart, pend, write == true ? "true" : "false"); */ - shard *s = &f->shards[pnum & (s64) (cslice_len(f->shards) - 1)]; - sync_MutexLock(&s->mu); - s_init(s); - page *p = cmap_get_ptr(page, s->pages, pnum); - if (p == nil) { - // Page does not exist in memory. - // Acquire a new one. - if (cmap_len(s->pages) == f->pgmax) { - // The buffer is at capacity. - // Evict lru page and hang on to it. - p = s->tail->prev; - s_pop(s, p); - cmap_delete(page, s->pages, p->num); - if (cmap_get(bool, s->dirty, p->num)) { - // dirty page. flush it now - file_error_t err = f_write(f, p); - if (err != nil) { - sync_MutexUnlock(&s->mu); - return (int_error_t) { 0, err }; - } - cmap_delete(bool, s->dirty, p->num); - } - // Clear the previous page memory for partial page writes for - // pages that are being partially written to. - if (write && ((pend - pstart) < f->pgsize)) { - memset(p->data, 0, f->pgsize); - } - } else { - // Allocate an entirely new page. - p = (page *) malloc(sizeof(page)); - p->data = (u8 *) malloc(f->pgsize); - } - p->num = pnum; - // Read contents of page from file for all read operations, and - // partial write operations. Ignore for full page writes. - if (!write || ((pend-pstart) < f->pgsize)) { - file_error_t err = f_read(f, p); - if (err != nil) { - sync_MutexUnlock(&s->mu); - return (int_error_t) { 0, err }; - } - } - // Add the newly acquired page to the list. - cmap_set(page, s->pages, p->num, p); - s_push(s, p); - } else { - // Bump the page to the front of the list. - s_bump(s, p); - } - if (write) { - memcpy(p->data + pstart, b, pend - pstart); - cmap_set(bool, s->dirty, pnum, true); - } else { - memcpy(b, p->data + pstart, pend - pstart); - } - sync_MutexUnlock(&s->mu); - return (int_error_t) { len_b, nil }; -} - -// Flush writes any unwritten buffered data to the underlying file. -file_error_t PagerFlush(Pager *f) { - if (f == nil) { - return "invalid argument"; - } - - /* sync_RWMutexLock(&f->mu); */ - for (size_t i = 0; i < cslice_len(f->shards); i++) { - cmap_iterator(bool) pnum; - if (f->shards[i].dirty != nil) { - for (pnum = cmap_begin(f->shards[i].dirty); - pnum != cmap_end(f->shards[i].dirty); pnum++) { - if (pnum->value == true) { - page *p = cmap_get_ptr(page, f->shards[i].pages, pnum->key); - if (p != nil) { - file_error_t err = f_write(f, p); - if (err != nil) { - /* sync_RWMutexUnlock(&f->mu); */ - return err; - } - } - cmap_set(bool, f->shards[i].dirty, pnum->key, false); - } - } - } - } - /* sync_RWMutexUnlock(&f->mu); */ - return nil; -} - -// ReadAt reads len(b) bytes from the File starting at byte offset off. -int_error_t PagerReadAt(Pager *f, u8 *b, size_t len_b, off_t off) { - return f_io(f, b, len_b, off, false); -} - -// WriteAt writes len(b) bytes to the File starting at byte offset off. -int_error_t PagerWriteAt(Pager *f, u8 *b, size_t len_b, off_t off) { - return f_io(f, b, len_b, off, true); -} - -file_error_t PagerTruncate(Pager *f, off_t length) { - if (f == nil) { - return "invalid argument"; - } - - /* flush unwritten changes to disk */ - PagerFlush(f); - - /* sync_RWMutexRLock(&f->mu); */ - /* set new file size */ - Handle handle = f->file; - Result res = FSFILE_SetSize(handle, (u64) length); - if (R_FAILED(res)) { - return "I/O error"; - } - /* sync_RWMutexRUnlock(&f->mu); */ - - /* FIXME: truncate only required pages. Remove all for now */ - PagerClear(f); - f = NewPager(handle); - return nil; -} - -void PagerClear(Pager *f) { - if (f) { - cslice_set_elem_destructor(f->shards, s_free); - cslice_clear(f->shards); - free(f); - } -} - diff --git a/firmware/target/hosted/ctru/lib/bfile/bfile.h b/firmware/target/hosted/ctru/lib/bfile/bfile.h deleted file mode 100644 index 870a9248d0..0000000000 --- a/firmware/target/hosted/ctru/lib/bfile/bfile.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _BFILE_H_ -#define _BFILE_H_ - -#include "bfile-internal.h" - -static const int defaultPageSize = 4096; // all pages are this size -static const int defaultBufferSize = 0x800000; // default buffer size, 8 MB -static const int minPages = 4; // minimum total pages per file -static const int pagesPerShard = 32; // ideal number of pages per shard -static const int maxShards = 128; // maximum number of shards per file - -// NewPager returns a new Pager that is backed by the provided file. -Pager* NewPager(Handle file); - -// NewPagerSize returns a new Pager with a custom page size and buffer size. -// The bufferSize is the maximum amount of memory dedicated to individual -// pages. Setting pageSize and bufferSize to zero will use their defaults, -// which are 4096 and 8 MB respectively. Custom values are rounded up to the -// nearest power of 2. -Pager* NewPagerSize(Handle file, int pageSize, int bufferSize); - -// ReadAt reads len(b) bytes from the File starting at byte offset off. -int_error_t PagerReadAt(Pager *f, u8 *b, size_t len_b, off_t off); - -// WriteAt writes len(b) bytes to the File starting at byte offset off. -int_error_t PagerWriteAt(Pager *f, u8 *b, size_t len_b, off_t off); - -// Flush writes any unwritten buffered data to the underlying file. -file_error_t PagerFlush(Pager *f); - -// Truncates pager to specified length -file_error_t PagerTruncate(Pager *f, off_t length); - -// Free all memory associated to a Pager file -void PagerClear(Pager *f); - -#endif /* _B_FILE_H_ */ diff --git a/firmware/target/hosted/ctru/lib/cmap.h b/firmware/target/hosted/ctru/lib/cmap.h deleted file mode 100644 index faa1eff9f3..0000000000 --- a/firmware/target/hosted/ctru/lib/cmap.h +++ /dev/null @@ -1,209 +0,0 @@ -#ifndef CMAP_H_ -#define CMAP_H_ - -#define CVECTOR_LINEAR_GROWTH -#include "cvector.h" - -/* note: for ease of porting go code to c, many functions (macros) names - remain similar to the ones used by go */ - -/* note2: this is a very basic map implementation. It does not do any sorting, and only works for basic types (and pointers) that can be compared with the equality operator */ - -#define nil NULL - -#define cmap_elem_destructor_t cvector_elem_destructor_t - -/** - * @brief cmap_declare - The map type used in this library - * @param name - The name associated to a map type. - * @param key_type - The map pair key type. - * @param val_type - The map pair value type. - * @param compare_func - The function used to compare for key_type. Should return value < 0 when a < b, 0 when a == b and value > 0 when a > b. - */ -#define cmap_declare(name, key_type, val_type) \ -typedef struct { \ - key_type key; \ - val_type value; \ -} name##_pair_t; \ -\ -typedef struct { \ - cvector(name##_pair_t) tree; \ - cmap_elem_destructor_t elem_destructor; \ -} name##_map_t; \ -\ -static inline val_type name##_get_( \ - name##_map_t *this, const key_type key) \ -{ \ - if (this) { \ - size_t i; \ - for (i = 0; i < cvector_size(this->tree); i++) { \ - if (key == this->tree[i].key) { \ - return this->tree[i].value; \ - } \ - } \ - } \ - return 0; \ -} \ -\ -static inline val_type name##_get_ptr_( \ - name##_map_t *this, const key_type key) \ -{ \ - if (this) { \ - size_t i; \ - for (i = 0; i < cvector_size(this->tree); i++) { \ - if (key == this->tree[i].key) { \ - return this->tree[i].value; \ - } \ - } \ - } \ - return nil; \ -} \ -\ -static inline void name##_set_( \ - name##_map_t *this, const key_type key, val_type value) \ -{ \ - if (this) { \ - size_t i; \ - for (i = 0; i < cvector_size(this->tree); i++) { \ - if (key == this->tree[i].key) { \ - this->tree[i].value = value; \ - return; \ - } \ - } \ - name##_pair_t new_pair = (name##_pair_t) { key, value }; \ - cvector_push_back(this->tree, new_pair); \ - } \ -} \ -\ -static inline void name##_delete_( \ - name##_map_t *this, const key_type key) \ -{ \ - if (this) { \ - size_t i; \ - for (i = 0; i < cvector_size(this->tree); i++) { \ - if (key == this->tree[i].key) { \ - cvector_erase(this->tree, i); \ - return; \ - } \ - } \ - } \ -} \ -\ -static inline name##_map_t* name##_map_make_(void) \ -{ \ - name##_map_t *map = (name##_map_t*) malloc(sizeof(name##_map_t)); \ - if (map) { \ - map->tree = nil; \ - cvector_init(map->tree, 0, nil); \ - return map; \ - } \ - return nil; \ -} \ -\ -static inline void name##_clear_(name##_map_t *this) \ -{ \ - if (this) { \ - cvector_free(this->tree); \ - free(this); \ - } \ -} \ -\ - - -/** - * @brief cmap - The map type used in this library - * @param name - The name associated to a map type. - */ -#define cmap(name) name##_map_t * - -/** - * @brief cmap_make - creates a new map. Automatically initializes the map. - * @param name - the name asociated to the map type - * @return a pointer to a new map. - */ -#define cmap_make(name) name##_map_make_() - -/** - * @brief cmap_size - gets the current size of the map - * @param map_ptr - the map pointer - * @return the size as a size_t - */ -#define cmap_len(map_ptr) cvector_size(map_ptr->tree) - -/** - * @brief cmap_get - gets value associated to a key. - * @param name - the name asociated to the map type - * @param map_ptr - the map pointer - * @param key - the key to search for - * @return the value associated to a key - */ -#define cmap_get(name, map_ptr, key) name##_get_(map_ptr, key) - -/** - * @brief cmap_get-ptr - gets ptr_value associated to a key. Use it to avoid assigning a ptr to 0. - * @param name - the name asociated to the map type - * @param map_ptr - the map pointer - * @param key - the key to search for - * @return the value associated to a key - */ -#define cmap_get_ptr(name, map_ptr, key) name##_get_ptr_(map_ptr, key) - - -/** - * @brief cmap_set - sets value associated to a key. - * @param name - the name asociated to the map type - * @param map_ptr - the map pointer - * @param key - the key to search for - * @param value - the new value - * @return void - */ -#define cmap_set(name, map_ptr, key, val) name##_set_(map_ptr, key, val) - -/** - * @brief cmap_delete - deletes map entry associated to a key. - * @param name - the name asociated to the map type - * @param map_ptr - the map pointer - * @param key - the key to search for - * @return void - */ -#define cmap_delete(name, map_ptr, key) name##_delete_(map_ptr, key) - -/** - * @brief cmap_set_elem_destructor - set the element destructor function - * used to clean up removed elements. The map must NOT be NULL for this to do anything. - * @param map_ptr - the map pointer - * @param elem_destructor_fn - function pointer of type cvector_elem_destructor_t used to destroy elements - * @return void - */ -#define cmap_set_elem_destructor(map_ptr, elem_destructor_fn) \ - cvector_set_elem_destructor(map_ptr->tree, elem_destructor_fn) - -/** - * @brief cmap_clear - deletes all map entries. And frees memory is an element destructor was set previously. - * @param name - the name asociated to the map type - * @param map_ptr - the map pointer - * @return void - */ -#define cmap_clear(name, map_ptr) name##_clear_(map_ptr) - -/** - * @brief cmap_iterator - The iterator type used for cmap - * @param type The type of iterator to act on. - */ -#define cmap_iterator(name) cvector_iterator(name##_pair_t) - -/** - * @brief cmap_begin - returns an iterator to first element of the vector - * @param map_ptr - the map pointer - * @return a pointer to the first element (or NULL) - */ -#define cmap_begin(map_ptr) ((map_ptr) ? cvector_begin(map_ptr->tree) : nil) - -/** - * @brief cmap_end - returns an iterator to one past the last element of the vector - * @param map_ptrs - the map pointer - * @return a pointer to one past the last element (or NULL) - */ -#define cmap_end(map_ptr) ((map_ptr) ? cvector_end(map_ptr->tree) : nil) - -#endif /* CMAP_H_ */ diff --git a/firmware/target/hosted/ctru/lib/cslice.h b/firmware/target/hosted/ctru/lib/cslice.h deleted file mode 100644 index 36ec6d6faa..0000000000 --- a/firmware/target/hosted/ctru/lib/cslice.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef CSLICE_H_ -#define CSLICE_H_ - -#define CVECTOR_LINEAR_GROWTH -#include "cvector.h" - -/* note: for ease of porting go code to c, many functions (macros) names - remain similar to the ones used by go */ - -#define nil NULL - -/** - * @brief cslice - The slice type used in this library - * @param type The type of slice to act on. - */ -#define cslice(type) cvector(type) - -/** - * @brief cslice_make - creates a new slice. Automatically initializes the slice. - * @param slice - the slice - * @param count - new size of the slice - * @param value - the value to initialize new elements with - * @return void - */ -#define cslice_make(slice, capacity, value) \ - do { \ - slice = nil; \ - cvector_init(slice, capacity, nil); \ - cvector_resize(slice, capacity, value); \ - } while(0) - -/** - * @brief cslice_size - gets the current size of the slice - * @param slice - the slice - * @return the size as a size_t - */ -#define cslice_len(slice) cvector_size(slice) - -/** - * @brief cslice_capacity - gets the current capacity of the slice - * @param slice - the slice - * @return the capacity as a size_t - */ -#define cslice_cap(slice) cvector_capacity(slice) - -/** - * @brief cslice_set_elem_destructor - set the element destructor function - * used to clean up removed elements. The vector must NOT be NULL for this to do anything. - * @param slice - the slice - * @param elem_destructor_fn - function pointer of type cslice_elem_destructor_t used to destroy elements - * @return void - */ -#define cslice_set_elem_destructor(slice, elem_destructor_fn) \ - cvector_set_elem_destructor(slice, elem_destructor_fn) - -/** - * @brief cslice_free - frees all memory associated with the slice - * @param slice - the slice - * @return void - */ -#define cslice_clear(slice) cvector_free(slice) - -#endif /* CSLICE_H_ */ diff --git a/firmware/target/hosted/ctru/lib/cvector.h b/firmware/target/hosted/ctru/lib/cvector.h deleted file mode 100644 index 5045025c73..0000000000 --- a/firmware/target/hosted/ctru/lib/cvector.h +++ /dev/null @@ -1,549 +0,0 @@ -#ifndef CVECTOR_H_ -#define CVECTOR_H_ -/** - * @copyright Copyright (c) 2015 Evan Teran, - * License: The MIT License (MIT) - * @brief cvector heap implemented using C library malloc() - * @file cvector.h - */ - -/* in case C library malloc() needs extra protection, - * allow these defines to be overridden. - */ -/* functions for allocation and deallocation need to correspond to each other, fall back to C library functions if not all are overridden */ -#if !defined(cvector_clib_free) || !defined(cvector_clib_malloc) || !defined(cvector_clib_calloc) || !defined(cvector_clib_realloc) -#ifdef cvector_clib_free -#undef cvector_clib_free -#endif -#ifdef cvector_clib_malloc -#undef cvector_clib_malloc -#endif -#ifdef cvector_clib_calloc -#undef cvector_clib_calloc -#endif -#ifdef cvector_clib_realloc -#undef cvector_clib_realloc -#endif -#include -#define cvector_clib_free free -#define cvector_clib_malloc malloc -#define cvector_clib_calloc calloc -#define cvector_clib_realloc realloc -#endif -/* functions independent of memory allocation */ -#ifndef cvector_clib_assert -#include /* for assert */ -#define cvector_clib_assert assert -#endif -#ifndef cvector_clib_memcpy -#include /* for memcpy */ -#define cvector_clib_memcpy memcpy -#endif -#ifndef cvector_clib_memmove -#include /* for memmove */ -#define cvector_clib_memmove memmove -#endif - -/* NOTE: Similar to C's qsort and bsearch, you will receive a T* - * for a vector of Ts. This means that you cannot use `free` directly - * as a destructor. Instead if you have for example a cvector_vector_type(int *) - * you will need to supply a function which casts `elem_ptr` to an `int**` - * and then does a free on what that pointer points to: - * - * ex: - * - * void free_int(void *p) { free(*(int **)p); } - */ -typedef void (*cvector_elem_destructor_t)(void *elem_ptr); - -typedef struct cvector_metadata_t { - size_t size; - size_t capacity; - cvector_elem_destructor_t elem_destructor; -} cvector_metadata_t; - -/** - * @brief cvector_vector_type - The vector type used in this library - * @param type The type of vector to act on. - */ -#define cvector_vector_type(type) type * - -/** - * @brief cvector - Syntactic sugar to retrieve a vector type - * @param type The type of vector to act on. - */ -#define cvector(type) cvector_vector_type(type) - -/** - * @brief cvector_iterator - The iterator type used for cvector - * @param type The type of iterator to act on. - */ -#define cvector_iterator(type) cvector_vector_type(type) - -/** - * @note you can also safely pass a pointer to a cvector iterator to a function - * but you have to update the pointer at the end to update the original - * iterator. - * example: - * void function( cvector_vector_type( type ) * p_it ) - * { - * cvector_vector_type( type ) it = *p_it; - * it ++; - * - * ... - * - * *p_it = it; - * } - */ - -/** - * @brief cvector_vector_type_ptr - helper to make code more "readable" - * @param type - the vector type pointer - */ -#define cvector_ptr_type(type) \ - cvector_vector_type(type) * - -/** - * @brief cvector_vector_ptr_get_iterator/set - helpers to make code more "readable" - * @param it - the vector iterator - * @param ptr - the vector pointer - */ -#define cvector_ptr_get_iterator(ptr) \ - *(ptr) - -#define cvector_ptr_set(ptr, it) \ - *(ptr) = it - -/** - * @brief cvector_vector_container_declare - defined a vector container type - */ -#define cvector_vector_container_declare(name, type) \ -struct cvector_vector_container_##name { \ - cvector_vector_type(type) vector; \ -} - -/** - * @brief cvector_vector_container - used to pass a cvector wrapped inside a container as a function parameter - */ -#define cvector_vector_container(name) \ - struct cvector_vector_container_##name - - -/** - * @brief cvector_vec_to_base - For internal use, converts a vector pointer to a metadata pointer - * @param vec - the vector - * @return the metadata pointer of the vector - * @internal - */ -#define cvector_vec_to_base(vec) \ - (&((cvector_metadata_t *)(void *)(vec))[-1]) - -/** - * @brief cvector_base_to_vec - For internal use, converts a metadata pointer to a vector pointer - * @param ptr - pointer to the metadata - * @return the vector - * @internal - */ -#define cvector_base_to_vec(ptr) \ - ((void *)&((cvector_metadata_t *)(ptr))[1]) - -/** - * @brief cvector_capacity - gets the current capacity of the vector - * @param vec - the vector - * @return the capacity as a size_t - */ -#define cvector_capacity(vec) \ - ((vec) ? cvector_vec_to_base(vec)->capacity : (size_t)0) - -/** - * @brief cvector_size - gets the current size of the vector - * @param vec - the vector - * @return the size as a size_t - */ -#define cvector_size(vec) \ - ((vec) ? cvector_vec_to_base(vec)->size : (size_t)0) - -/** - * @brief cvector_elem_destructor - get the element destructor function used - * to clean up elements - * @param vec - the vector - * @return the function pointer as cvector_elem_destructor_t - */ -#define cvector_elem_destructor(vec) \ - ((vec) ? cvector_vec_to_base(vec)->elem_destructor : NULL) - -/** - * @brief cvector_empty - returns non-zero if the vector is empty - * @param vec - the vector - * @return non-zero if empty, zero if non-empty - */ -#define cvector_empty(vec) \ - (cvector_size(vec) == 0) - -/** - * @brief cvector_reserve - Requests that the vector capacity be at least enough - * to contain n elements. If n is greater than the current vector capacity, the - * function causes the container to reallocate its storage increasing its - * capacity to n (or greater). - * @param vec - the vector - * @param n - Minimum capacity for the vector. - * @return void - */ -#define cvector_reserve(vec, n) \ - do { \ - size_t cv_reserve_cap__ = cvector_capacity(vec); \ - if (cv_reserve_cap__ < (n)) { \ - cvector_grow((vec), (n)); \ - } \ - } while (0) - -/** - * @brief cvector_init - Initialize a vector. The vector must be NULL for this to do anything. - * @param vec - the vector - * @param capacity - vector capacity to reserve - * @param elem_destructor_fn - element destructor function - * @return void - */ -#define cvector_init(vec, capacity, elem_destructor_fn) \ - do { \ - if (!(vec)) { \ - cvector_reserve((vec), capacity); \ - cvector_set_elem_destructor((vec), (elem_destructor_fn)); \ - } \ - } while (0) - -/** - * @brief cvector_init_default - Initialize a vector with default value. The vector must be NULL for this to do anything. Does NOT work for struct types. - * @param vec - the vector - * @param capacity - vector capacity to reserve - * @param elem_destructor_fn - element destructor function - * @return void - */ -#define cvector_init_default(vec, capacity, default) \ - do { \ - if (!(vec)) { \ - cvector_reserve((vec), capacity); \ - cvector_set_elem_destructor((vec), (elem_destructor_fn)); \ - } \ - } while (0) - -/** - * @brief cvector_erase - removes the element at index i from the vector - * @param vec - the vector - * @param i - index of element to remove - * @return void - */ -#define cvector_erase(vec, i) \ - do { \ - if (vec) { \ - const size_t cv_erase_sz__ = cvector_size(vec); \ - if ((i) < cv_erase_sz__) { \ - cvector_elem_destructor_t cv_erase_elem_dtor__ = cvector_elem_destructor(vec); \ - if (cv_erase_elem_dtor__) { \ - cv_erase_elem_dtor__(&(vec)[i]); \ - } \ - cvector_set_size((vec), cv_erase_sz__ - 1); \ - cvector_clib_memmove( \ - (vec) + (i), \ - (vec) + (i) + 1, \ - sizeof(*(vec)) * (cv_erase_sz__ - 1 - (i))); \ - } \ - } \ - } while (0) - -/** - * @brief cvector_clear - erase all of the elements in the vector - * @param vec - the vector - * @return void - */ -#define cvector_clear(vec) \ - do { \ - if (vec) { \ - cvector_elem_destructor_t cv_clear_elem_dtor__ = cvector_elem_destructor(vec); \ - if (cv_clear_elem_dtor__) { \ - size_t cv_clear_i__; \ - for (cv_clear_i__ = 0; cv_clear_i__ < cvector_size(vec); ++cv_clear_i__) { \ - cv_clear_elem_dtor__(&(vec)[cv_clear_i__]); \ - } \ - } \ - cvector_set_size(vec, 0); \ - } \ - } while (0) - -/** - * @brief cvector_free - frees all memory associated with the vector - * @param vec - the vector - * @return void - */ -#define cvector_free(vec) \ - do { \ - if (vec) { \ - void *cv_free_p__ = cvector_vec_to_base(vec); \ - cvector_elem_destructor_t cv_free_elem_dtor__ = cvector_elem_destructor(vec); \ - if (cv_free_elem_dtor__) { \ - size_t cv_free_i__; \ - for (cv_free_i__ = 0; cv_free_i__ < cvector_size(vec); ++cv_free_i__) { \ - cv_free_elem_dtor__(&(vec)[cv_free_i__]); \ - } \ - } \ - cvector_clib_free(cv_free_p__); \ - } \ - } while (0) - -/** - * @brief cvector_begin - returns an iterator to first element of the vector - * @param vec - the vector - * @return a pointer to the first element (or NULL) - */ -#define cvector_begin(vec) \ - (vec) - -/** - * @brief cvector_end - returns an iterator to one past the last element of the vector - * @param vec - the vector - * @return a pointer to one past the last element (or NULL) - */ -#define cvector_end(vec) \ - ((vec) ? &((vec)[cvector_size(vec)]) : NULL) - -/* user request to use linear growth algorithm */ -#ifdef CVECTOR_LINEAR_GROWTH - -/** - * @brief cvector_compute_next_grow - returns an the computed size in next vector grow - * size is increased by 1 - * @param size - current size - * @return size after next vector grow - */ -#define cvector_compute_next_grow(size) \ - ((size) + 1) - -#else - -/** - * @brief cvector_compute_next_grow - returns an the computed size in next vector grow - * size is increased by multiplication of 2 - * @param size - current size - * @return size after next vector grow - */ -#define cvector_compute_next_grow(size) \ - ((size) ? ((size) << 1) : 1) - -#endif /* CVECTOR_LINEAR_GROWTH */ - -/** - * @brief cvector_push_back - adds an element to the end of the vector - * @param vec - the vector - * @param value - the value to add - * @return void - */ -#define cvector_push_back(vec, value) \ - do { \ - size_t cv_push_back_cap__ = cvector_capacity(vec); \ - if (cv_push_back_cap__ <= cvector_size(vec)) { \ - cvector_grow((vec), cvector_compute_next_grow(cv_push_back_cap__)); \ - } \ - (vec)[cvector_size(vec)] = (value); \ - cvector_set_size((vec), cvector_size(vec) + 1); \ - } while (0) - -/** - * @brief cvector_insert - insert element at position pos to the vector - * @param vec - the vector - * @param pos - position in the vector where the new elements are inserted. - * @param val - value to be copied (or moved) to the inserted elements. - * @return void - */ -#define cvector_insert(vec, pos, val) \ - do { \ - size_t cv_insert_cap__ = cvector_capacity(vec); \ - if (cv_insert_cap__ <= cvector_size(vec)) { \ - cvector_grow((vec), cvector_compute_next_grow(cv_insert_cap__)); \ - } \ - if ((pos) < cvector_size(vec)) { \ - cvector_clib_memmove( \ - (vec) + (pos) + 1, \ - (vec) + (pos), \ - sizeof(*(vec)) * ((cvector_size(vec)) - (pos))); \ - } \ - (vec)[(pos)] = (val); \ - cvector_set_size((vec), cvector_size(vec) + 1); \ - } while (0) - -/** - * @brief cvector_pop_back - removes the last element from the vector - * @param vec - the vector - * @return void - */ -#define cvector_pop_back(vec) \ - do { \ - cvector_elem_destructor_t cv_pop_back_elem_dtor__ = cvector_elem_destructor(vec); \ - if (cv_pop_back_elem_dtor__) { \ - cv_pop_back_elem_dtor__(&(vec)[cvector_size(vec) - 1]); \ - } \ - cvector_set_size((vec), cvector_size(vec) - 1); \ - } while (0) - -/** - * @brief cvector_copy - copy a vector - * @param from - the original vector - * @param to - destination to which the function copy to - * @return void - */ -#define cvector_copy(from, to) \ - do { \ - if ((from)) { \ - cvector_grow(to, cvector_size(from)); \ - cvector_set_size(to, cvector_size(from)); \ - cvector_clib_memcpy((to), (from), cvector_size(from) * sizeof(*(from))); \ - } \ - } while (0) - -/** - * @brief cvector_swap - exchanges the content of the vector by the content of another vector of the same type - * @param vec - the original vector - * @param other - the other vector to swap content with - * @param type - the type of both vectors - * @return void - */ -#define cvector_swap(vec, other, type) \ - do { \ - if (vec && other) { \ - cvector_vector_type(type) cv_swap__ = vec; \ - vec = other; \ - other = cv_swap__; \ - } \ - } while (0) - -/** - * @brief cvector_set_capacity - For internal use, sets the capacity variable of the vector - * @param vec - the vector - * @param size - the new capacity to set - * @return void - * @internal - */ -#define cvector_set_capacity(vec, size) \ - do { \ - if (vec) { \ - cvector_vec_to_base(vec)->capacity = (size); \ - } \ - } while (0) - -/** - * @brief cvector_set_size - For internal use, sets the size variable of the vector - * @param vec - the vector - * @param _size - the new capacity to set - * @return void - * @internal - */ -#define cvector_set_size(vec, _size) \ - do { \ - if (vec) { \ - cvector_vec_to_base(vec)->size = (_size); \ - } \ - } while (0) - -/** - * @brief cvector_set_elem_destructor - set the element destructor function - * used to clean up removed elements. The vector must NOT be NULL for this to do anything. - * @param vec - the vector - * @param elem_destructor_fn - function pointer of type cvector_elem_destructor_t used to destroy elements - * @return void - */ -#define cvector_set_elem_destructor(vec, elem_destructor_fn) \ - do { \ - if (vec) { \ - cvector_vec_to_base(vec)->elem_destructor = (elem_destructor_fn); \ - } \ - } while (0) - -/** - * @brief cvector_grow - For internal use, ensures that the vector is at least `count` elements big - * @param vec - the vector - * @param count - the new capacity to set - * @return void - * @internal - */ -#define cvector_grow(vec, count) \ - do { \ - const size_t cv_grow_sz__ = (count) * sizeof(*(vec)) + sizeof(cvector_metadata_t); \ - if (vec) { \ - void *cv_grow_p1__ = cvector_vec_to_base(vec); \ - void *cv_grow_p2__ = cvector_clib_realloc(cv_grow_p1__, cv_grow_sz__); \ - cvector_clib_assert(cv_grow_p2__); \ - (vec) = cvector_base_to_vec(cv_grow_p2__); \ - } else { \ - void *cv_grow_p__ = cvector_clib_malloc(cv_grow_sz__); \ - cvector_clib_assert(cv_grow_p__); \ - (vec) = cvector_base_to_vec(cv_grow_p__); \ - cvector_set_size((vec), 0); \ - cvector_set_elem_destructor((vec), NULL); \ - } \ - cvector_set_capacity((vec), (count)); \ - } while (0) - -/** - * @brief cvector_shrink_to_fit - requests the container to reduce its capacity to fit its size - * @param vec - the vector - * @return void - */ -#define cvector_shrink_to_fit(vec) \ - do { \ - if (vec) { \ - const size_t cv_shrink_to_fit_sz__ = cvector_size(vec); \ - cvector_grow(vec, cv_shrink_to_fit_sz__); \ - } \ - } while (0) - -/** - * @brief cvector_at - returns a reference to the element at position n in the vector. - * @param vec - the vector - * @param n - position of an element in the vector. - * @return the element at the specified position in the vector. - */ -#define cvector_at(vec, n) \ - ((vec) ? (((int)(n) < 0 || (size_t)(n) >= cvector_size(vec)) ? NULL : &(vec)[n]) : NULL) - -/** - * @brief cvector_front - returns a reference to the first element in the vector. Unlike member cvector_begin, which returns an iterator to this same element, this function returns a direct reference. - * @param vec - the vector - * @return a reference to the first element in the vector container. - */ -#define cvector_front(vec) \ - ((vec) ? ((cvector_size(vec) > 0) ? cvector_at(vec, 0) : NULL) : NULL) - -/** - * @brief cvector_back - returns a reference to the last element in the vector.Unlike member cvector_end, which returns an iterator just past this element, this function returns a direct reference. - * @param vec - the vector - * @return a reference to the last element in the vector. - */ -#define cvector_back(vec) \ - ((vec) ? ((cvector_size(vec) > 0) ? cvector_at(vec, cvector_size(vec) - 1) : NULL) : NULL) - -/** - * @brief cvector_resize - resizes the container to contain count elements. - * @param vec - the vector - * @param count - new size of the vector - * @param value - the value to initialize new elements with - * @return void - */ -#define cvector_resize(vec, count, value) \ - do { \ - if (vec) { \ - size_t cv_resize_count__ = (size_t)(count); \ - size_t cv_resize_sz__ = cvector_vec_to_base(vec)->size; \ - if (cv_resize_count__ > cv_resize_sz__) { \ - cvector_reserve((vec), cv_resize_count__); \ - cvector_set_size((vec), cv_resize_count__); \ - do { \ - (vec)[cv_resize_sz__++] = (value); \ - } while (cv_resize_sz__ < cv_resize_count__); \ - } else { \ - while (cv_resize_count__ < cv_resize_sz__--) { \ - cvector_pop_back(vec); \ - } \ - } \ - } \ - } while (0) - -#endif /* CVECTOR_H_ */ diff --git a/firmware/target/hosted/ctru/lib/sys_dir.c b/firmware/target/hosted/ctru/lib/sys_dir.c deleted file mode 100644 index 0b9a0300fb..0000000000 --- a/firmware/target/hosted/ctru/lib/sys_dir.c +++ /dev/null @@ -1,403 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#define DIRFUNCTIONS_DEFINED -#include "config.h" -#include -#include -#include "debug.h" -#include "dir.h" -#include "pathfuncs.h" -#include "timefuncs.h" -#include "system.h" -#include "fs_defines.h" -#include "sys_file.h" - -#include <3ds/archive.h> -#include <3ds/util/utf.h> - -/* This file is based on firmware/common/dir.c */ - -/* Define LOGF_ENABLE to enable logf output in this file */ -// #define LOGF_ENABLE -#include "logf.h" - -/* structure used for open directory streams */ -static struct dirstr_desc -{ - struct filestr_base stream; /* basic stream info (first!) */ - struct dirent entry; /* current parsed entry information */ -} open_streams[MAX_OPEN_DIRS] = -{ - [0 ... MAX_OPEN_FILES-1] = { .stream = { .handle = 0 } } -}; - -extern FS_Archive sdmcArchive; - -/* check and return a struct dirstr_desc* from a DIR* */ -static struct dirstr_desc * get_dirstr(DIR *dirp) -{ - struct dirstr_desc *dir = (struct dirstr_desc *)dirp; - - if (!PTR_IN_ARRAY(open_streams, dir, MAX_OPEN_DIRS)) - dir = NULL; - else if (dir->stream.handle != 0) - return dir; - - int errnum; - - if (!dir) - { - errnum = EFAULT; - } - else - { - logf("dir #%d: dir not open\n", (int)(dir - open_streams)); - errnum = EBADF; - } - - errno = errnum; - return NULL; -} - -#define GET_DIRSTR(type, dirp) \ - ({ \ - file_internal_lock_##type(); \ - struct dirstr_desc *_dir = get_dirstr(dirp); \ - if (_dir) \ - FILESTR_LOCK(type, &_dir->stream); \ - else { \ - file_internal_unlock_##type(); \ -} \ - _dir; \ - }) - -/* release the lock on the dirstr_desc* */ -#define RELEASE_DIRSTR(type, dir) \ - ({ \ - FILESTR_UNLOCK(type, &(dir)->stream); \ - file_internal_unlock_##type(); \ - }) - - -/* find a free dir stream descriptor */ -static struct dirstr_desc * alloc_dirstr(void) -{ - for (unsigned int dd = 0; dd < MAX_OPEN_DIRS; dd++) - { - struct dirstr_desc *dir = &open_streams[dd]; - if (dir->stream.handle == 0) - return dir; - } - - logf("Too many dirs open\n"); - return NULL; -} - -u32 fs_error(void) { - u32 err; - FSUSER_GetSdmcFatfsError(&err); - return err; -} - -/* Initialize the base descriptor */ -static void filestr_base_init(struct filestr_base *stream) -{ - stream->cache = nil; - stream->handle = 0; - stream->size = 0; - LightLock_Init(&stream->mtx); -} - -/** POSIX interface **/ - -/* open a directory */ -DIR * ctru_opendir(const char *dirname) -{ - logf("opendir(dirname=\"%s\")\n", dirname); - - DIR *dirp = NULL; - file_internal_lock_WRITER(); - - int rc; - - struct dirstr_desc * const dir = alloc_dirstr(); - if (!dir) - FILE_ERROR(EMFILE, _RC); - - filestr_base_init(&dir->stream); - Result res = FSUSER_OpenDirectory(&dir->stream.handle, - sdmcArchive, - fsMakePath(PATH_ASCII, dirname)); - if (R_FAILED(res)) { - logf("Open failed: %lld\n", fs_error()); - FILE_ERROR(EMFILE, -1); - } - - dir->stream.size = 0; - dir->stream.flags = 0; - - /* we will use file path to implement ctru_samedir function */ - strcpy(dir->stream.path, dirname); - - dirp = (DIR *)dir; -file_error: - file_internal_unlock_WRITER(); - return dirp; -} - -/* close a directory stream */ -int ctru_closedir(DIR *dirp) -{ - int rc; - - file_internal_lock_WRITER(); - - /* needs to work even if marked "nonexistant" */ - struct dirstr_desc * const dir = (struct dirstr_desc *)dirp; - if (!PTR_IN_ARRAY(open_streams, dir, MAX_OPEN_DIRS)) - FILE_ERROR(EFAULT, -1); - - logf("closedir(dirname=\"%s\")\n", dir->stream.path); - - if (dir->stream.handle == 0) - { - logf("dir #%d: dir not open\n", (int)(dir - open_streams)); - FILE_ERROR(EBADF, -2); - } - - Result res = FSDIR_Close(dir->stream.handle); - if (R_FAILED(res)) - FILE_ERROR(ERRNO, -3); - - dir->stream.handle = 0; - dir->stream.path[0] = '\0'; - - rc = 0; -file_error: - file_internal_unlock_WRITER(); - return rc; -} - -void dirstr_entry_init(FS_DirectoryEntry *dirEntry, struct dirent *entry) -{ - /* clear */ - memset(entry, 0, sizeof(struct dirent)); - - /* attributes */ - if (dirEntry->attributes & FS_ATTRIBUTE_DIRECTORY) - entry->info.attr |= ATTR_DIRECTORY; - if (dirEntry->attributes & FS_ATTRIBUTE_HIDDEN) - entry->info.attr |= ATTR_HIDDEN; - if (dirEntry->attributes & FS_ATTRIBUTE_ARCHIVE) - entry->info.attr |= ATTR_ARCHIVE; - if (dirEntry->attributes & FS_ATTRIBUTE_READ_ONLY) - entry->info.attr |= ATTR_READ_ONLY; - - /* size */ - entry->info.size = dirEntry->fileSize; - - /* name */ - uint8_t d_name[0xA0 + 1]; - memset(d_name, '\0', 0xA0); - utf16_to_utf8(d_name, (uint16_t *) &dirEntry->name, 0xA0); - memcpy(entry->d_name, d_name, 0xA0); -} - -/* read a directory */ -struct dirent * ctru_readdir(DIR *dirp) -{ - struct dirstr_desc * const dir = GET_DIRSTR(READER, dirp); - if (!dir) - FILE_ERROR_RETURN(ERRNO, NULL); - - int rc; - struct dirent *res = NULL; - - logf("readdir(dirname=\"%s\")\n", dir->stream.path); - - u32 dataRead = 0; - FS_DirectoryEntry dirEntry; - Result result = FSDIR_Read(dir->stream.handle, - &dataRead, - 1, - &dirEntry); - if (R_FAILED(result)) - FILE_ERROR(EIO, _RC); - - if (dataRead == 0) { - /* directory end. return NULL value, no errno */ - res = NULL; - goto file_error; - } - - res = &dir->entry; - dirstr_entry_init(&dirEntry, res); - - /* time */ - char full_path[MAX_PATH+1]; - - if (!strcmp(PATH_ROOTSTR, dir->stream.path)) - snprintf(full_path, MAX_PATH, "%s%s", dir->stream.path, res->d_name); - else - snprintf(full_path, MAX_PATH, "%s/%s", dir->stream.path, res->d_name); - - u64 mtime; - archive_getmtime(full_path, &mtime); - - /* DEBUGF("archive_getmtime(%s): %lld\n", full_path, mtime); */ - - uint16_t dosdate, dostime; - dostime_localtime(mtime, &dosdate, &dostime); - res->info.wrtdate = dosdate; - res->info.wrttime = dostime; - -file_error: - RELEASE_DIRSTR(READER, dir); - return res; -} - -/* make a directory */ -int ctru_mkdir(const char *path) -{ - logf("mkdir(path=\"%s\")\n", path); - - int rc; - - file_internal_lock_WRITER(); - - Result res = FSUSER_CreateDirectory(sdmcArchive, - fsMakePath(PATH_ASCII, path), - 0); - if (R_FAILED(res)) - FILE_ERROR(ERRNO, -1); - - rc = 0; -file_error: - file_internal_unlock_WRITER(); - return rc; -} - -/* remove a directory */ -int ctru_rmdir(const char *name) -{ - logf("rmdir(name=\"%s\")\n", name); - - int rc; - - if (name) - { - /* path may not end with "." */ - const char *basename; - size_t len = path_basename(name, &basename); - if (basename[0] == '.' && len == 1) - { - logf("Invalid path; last component is \".\"\n"); - FILE_ERROR_RETURN(EINVAL, -9); - } - } - - file_internal_lock_WRITER(); - Result res = FSUSER_DeleteDirectory(sdmcArchive, - fsMakePath(PATH_ASCII, name)); - if (R_FAILED(res)) - FILE_ERROR(ERRNO, -1); - - rc = 0; -file_error: - file_internal_unlock_WRITER(); - return rc; -} - - -/** Extended interface **/ - -/* return if two directory streams refer to the same directory */ -int ctru_samedir(DIR *dirp1, DIR *dirp2) -{ - struct dirstr_desc * const dir1 = GET_DIRSTR(WRITER, dirp1); - if (!dir1) - FILE_ERROR_RETURN(ERRNO, -1); - - int rc = -2; - - struct dirstr_desc * const dir2 = get_dirstr(dirp2); - if (dir2) { - rc = strcmp(dir1->stream.path, dir2->stream.path) == 0 ? 1 : 0; - } - - RELEASE_DIRSTR(WRITER, dir1); - return rc; -} - -/* test directory existence (returns 'false' if a file) */ -bool ctru_dir_exists(const char *dirname) -{ - file_internal_lock_WRITER(); - - int rc; - - Handle handle; - Result res = FSUSER_OpenDirectory(&handle, - sdmcArchive, - fsMakePath(PATH_ASCII, dirname)); - if (R_FAILED(res)) { - logf("Directory not found: %ld\n", fs_error()); - FILE_ERROR(EMFILE, -1); - } - - rc = 0; -file_error: - if (rc == 0) { - FSDIR_Close(handle); - } - file_internal_unlock_WRITER(); - return rc == 0 ? true : false; -} - -/* get the portable info from the native entry */ -struct dirinfo dir_get_info(DIR *dirp, struct dirent *entry) -{ - int rc; - if (!dirp || !entry) - FILE_ERROR(EFAULT, _RC); - - if (entry->d_name[0] == '\0') - FILE_ERROR(ENOENT, _RC); - - if ((file_size_t)entry->info.size > FILE_SIZE_MAX) - FILE_ERROR(EOVERFLOW, _RC); - - return (struct dirinfo) - { - .attribute = entry->info.attr, - .size = entry->info.size, - .mtime = dostime_mktime(entry->info.wrtdate, entry->info.wrttime), - }; - -file_error: - return (struct dirinfo){ .attribute = 0 }; -} - -const char* ctru_root_realpath(void) -{ - /* Native only, for APP and SIM see respective filesystem-.c files */ - return PATH_ROOTSTR; /* rb_namespace.c */ -} diff --git a/firmware/target/hosted/ctru/lib/sys_file.c b/firmware/target/hosted/ctru/lib/sys_file.c deleted file mode 100644 index 1df88282d6..0000000000 --- a/firmware/target/hosted/ctru/lib/sys_file.c +++ /dev/null @@ -1,777 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#define RB_FILESYSTEM_OS -#include "config.h" -#include "system.h" -#include -#include -#include -#include -#include -#include "file.h" -#include "debug.h" -#include "string-extra.h" -#include "fs_defines.h" -#include "sys_file.h" - -/* This file is based on firmware/common/file.c */ - -/* Define LOGF_ENABLE to enable logf output in this file */ -// #define LOGF_ENABLE -#include "logf.h" - -/** - * These functions provide a roughly POSIX-compatible file I/O API. - * Important: the bufferio I/O library (bfile) used in the 3ds does not work - * with write-only files due to an internal limitation. - * So all files will be opened with the read flag by default. - */ - -/* structure used for open file descriptors */ -static struct filestr_desc -{ - struct filestr_base stream; /* basic stream info (first!) */ - file_size_t offset; /* current offset for stream */ - u64 *sizep; /* shortcut to file size in fileobj */ -} open_streams[MAX_OPEN_FILES] = -{ - [0 ... MAX_OPEN_FILES-1] = { .stream = { .cache = nil, .flags = 0 } } -}; - -extern FS_Archive sdmcArchive; - -/* check and return a struct filestr_desc* from a file descriptor number */ -static struct filestr_desc * get_filestr(int fildes) -{ - struct filestr_desc *file = &open_streams[fildes]; - - if ((unsigned int)fildes >= MAX_OPEN_FILES) - file = NULL; - else if (file->stream.cache != nil) - return file; - - logf("fildes %d: bad file number\n", fildes); - errno = (file && (file->stream.cache == nil)) ? ENXIO : EBADF; - return NULL; -} - -#define GET_FILESTR(type, fildes) \ - ({ \ - file_internal_lock_##type(); \ - struct filestr_desc * _file = get_filestr(fildes); \ - if (_file) \ - FILESTR_LOCK(type, &_file->stream); \ - else { \ - file_internal_unlock_##type(); \ - }\ - _file; \ - }) - -/* release the lock on the filestr_desc* */ -#define RELEASE_FILESTR(type, file) \ - ({ \ - FILESTR_UNLOCK(type, &(file)->stream); \ - file_internal_unlock_##type(); \ - }) - -/* find a free file descriptor */ -static int alloc_filestr(struct filestr_desc **filep) -{ - for (int fildes = 0; fildes < MAX_OPEN_FILES; fildes++) - { - struct filestr_desc *file = &open_streams[fildes]; - if (file->stream.cache == nil) - { - *filep = file; - return fildes; - } - } - - logf("Too many files open\n"); - return -1; -} - -/* check for file existence */ -int test_stream_exists_internal(const char *path) -{ - int rc; - bool is_dir = false; - - Handle handle; - Result res = FSUSER_OpenFile(&handle, - sdmcArchive, - fsMakePath(PATH_ASCII, path), - FS_OPEN_READ, - 0); - if (R_FAILED(res)) { - /* not a file, try to open a directory */ - res = FSUSER_OpenDirectory(&handle, - sdmcArchive, - fsMakePath(PATH_ASCII, path)); - if (R_FAILED(res)) { - logf("File does not exist\n"); - FILE_ERROR(ERRNO, -1); - } - - is_dir = true; - } - - rc = 1; -file_error: - if (handle > 0) { - if (is_dir) - FSDIR_Close(handle); - else - FSFILE_Close(handle); - } - - return rc; -} - -/* set the file pointer */ -static off_t lseek_internal(struct filestr_desc *file, off_t offset, - int whence) -{ - off_t rc; - off_t pos; - - off_t size = MIN(*file->sizep, FILE_SIZE_MAX); - off_t file_offset = AtomicLoad(&file->offset); - - switch (whence) - { - case SEEK_SET: - if (offset < 0 || (off_t)offset > size) - FILE_ERROR(EINVAL, -1); - - pos = offset; - break; - - case SEEK_CUR: - if ((offset < 0 && (off_t)-offset > file_offset) || - (offset > 0 && (off_t)offset > size - file_offset)) - FILE_ERROR(EINVAL, -1); - - pos = file_offset + offset; - break; - - case SEEK_END: - if (offset > 0 || (off_t)-offset > size) - FILE_ERROR(EINVAL, -1); - - pos = size + offset; - break; - - default: - FILE_ERROR(EINVAL, -1); - } - - AtomicSwap(&file->offset, pos); - - return pos; -file_error: - return rc; -} - -/* read from or write to the file; back end to read() and write() */ -static ssize_t readwrite(struct filestr_desc *file, void *buf, size_t nbyte, - bool write) -{ -#ifndef LOGF_ENABLE /* wipes out log before you can save it */ - /* DEBUGF("readwrite(%p,%lx,%lu,%s)\n", - file, (long)buf, (unsigned long)nbyte, write ? "write" : "read"); */ -#endif - - const file_size_t size = *file->sizep; - size_t filerem; - - if (write) - { - /* if opened in append mode, move pointer to end */ - if (file->stream.flags & O_APPEND) - AtomicSwap(&file->offset, MIN(size, FILE_SIZE_MAX)); - - filerem = FILE_SIZE_MAX - AtomicLoad(&file->offset); - } - else - { - /* limit to maximum possible offset (EOF or FILE_SIZE_MAX) */ - filerem = MIN(size, FILE_SIZE_MAX) - AtomicLoad(&file->offset); - } - - if (nbyte > filerem) - { - nbyte = filerem; - if (nbyte > 0) - {} - else if (write) - FILE_ERROR_RETURN(EFBIG, -1); /* would get too large */ - else if (AtomicLoad(&file->offset) >= FILE_SIZE_MAX) - FILE_ERROR_RETURN(EOVERFLOW, -2); /* can't read here */ - } - - if (nbyte == 0) - return 0; - - int rc = 0; - int_error_t n_err; - - if (write) - n_err = PagerWriteAt(file->stream.cache, (u8 *) buf, nbyte, AtomicLoad(&file->offset)); - else - n_err = PagerReadAt(file->stream.cache, (u8 *) buf, nbyte, AtomicLoad(&file->offset)); - - if ((n_err.err != nil) && strcmp(n_err.err, "io.EOF")) { - FILE_ERROR(ERRNO, -3); - } - -file_error:; -#ifdef DEBUG - if (errno == ENOSPC) - logf("No space left on device\n"); -#endif - - size_t done = n_err.n; - if (done) - { - /* error or not, update the file offset and size if anything was - transferred */ - AtomicAdd(&file->offset, done); -#ifndef LOGF_ENABLE /* wipes out log before you can save it */ - /* DEBUGF("file offset: %lld\n", file->offset); */ -#endif - /* adjust file size to length written */ - if (write && AtomicLoad(&file->offset) > size) - *file->sizep = AtomicLoad(&file->offset); - - return done; - } - - return rc; -} - -/* initialize the base descriptor */ -static void filestr_base_init(struct filestr_base *stream) -{ - stream->cache = nil; - stream->handle = 0; - stream->size = 0; - LightLock_Init(&stream->mtx); -} - -int open_internal_inner2(Handle *handle, const char *path, u32 openFlags, u32 attributes) -{ - int rc; - Result res = FSUSER_OpenFile(handle, - sdmcArchive, - fsMakePath(PATH_ASCII, path), - openFlags, - attributes); - if (R_FAILED(res)) { - FILE_ERROR(ERRNO, -1); - } - - rc = 1; -file_error: - return rc; -} - -static int open_internal_inner1(const char *path, int oflag) -{ - int rc; - struct filestr_desc *file; - int fildes = alloc_filestr(&file); - if (fildes < 0) - FILE_ERROR_RETURN(EMFILE, -1); - - u32 openFlags = 0, attributes = 0; - - /* open for reading by default */ - openFlags = FS_OPEN_READ; - - if (oflag & O_ACCMODE) - { - if ((oflag & O_ACCMODE) == O_RDONLY) { - attributes |= FS_ATTRIBUTE_READ_ONLY; - } - if ((oflag & O_ACCMODE) == O_WRONLY) { - openFlags |= FS_OPEN_WRITE; - } - if ((oflag & O_ACCMODE) == O_RDWR) { - openFlags |= FS_OPEN_WRITE; - } - } - else if (oflag & O_TRUNC) - { - /* O_TRUNC requires write mode */ - logf("No write mode but have O_TRUNC\n"); - FILE_ERROR(EINVAL, -2); - } - - /* O_CREAT and O_APPEND are fine without write mode - * for the former, an empty file is created but no data may be written - * for the latter, no append will be allowed anyway */ - if (!(oflag & O_CREAT)) - oflag &= ~O_EXCL; /* result is undefined: we choose "ignore" */ - - filestr_base_init(&file->stream); - rc = open_internal_inner2(&file->stream.handle, path, openFlags, attributes); - - if (rc > 0) { - if (oflag & O_EXCL) - { - logf("File exists\n"); - FILE_ERROR(EEXIST, -4); - } - } - else if (oflag & O_CREAT) - { - /* not found; try to create it */ - openFlags |= FS_OPEN_CREATE; - rc = open_internal_inner2(&file->stream.handle, path, openFlags, attributes); - if (rc < 0) - FILE_ERROR(ERRNO, rc * 10 - 6); - } - else - { - logf("File not found\n"); - FILE_ERROR(ENOENT, -5); - } - - /* truncate file if requested */ - if (oflag & O_TRUNC) { - Result res = FSFILE_SetSize(file->stream.handle, 0); - if (R_FAILED(res)) { - FILE_ERROR(ERRNO, -6); - } - } - - /* we need to set file size here, or else lseek - will fail if no read or write has been done */ - u64 size = 0; - Result res = FSFILE_GetSize(file->stream.handle, &size); - if (R_FAILED(res)) { - FILE_ERROR(ERRNO, -8); - } - - int pageSize = 4096; /* 4096 bytes */ - int bufferSize = 512 * 1024; /* 512 kB */ - - /* streamed file formats like flac and mp3 need very large page - sizes to avoid stuttering */ - if (((oflag & O_ACCMODE) == O_RDONLY) && (size > 0x200000)) { - /* printf("open(%s)_BIG_pageSize\n", path); */ - pageSize = 32 * 1024; - bufferSize = MIN(size, defaultBufferSize); - } - - file->stream.cache = NewPagerSize(file->stream.handle, - pageSize, - bufferSize); - if (file->stream.cache == nil) { - FILE_ERROR(ERRNO, -7); - } - - file->stream.flags = oflag; - file->stream.size = size; - file->sizep = &file->stream.size; - AtomicSwap(&file->offset, 0); - - /* we will use file path to implement ctru_fsamefile function */ - strcpy(file->stream.path, path); - - return fildes; - -file_error: - if (fildes >= 0) { - if (file->stream.cache != nil) { - PagerFlush(file->stream.cache); - PagerClear(file->stream.cache); - file->stream.cache = nil; - } - - FSFILE_Close(file->stream.handle); - file->stream.handle = 0; - } - - return rc; -} - -static int open_internal_locked(const char *path, int oflag) -{ - file_internal_lock_WRITER(); - int rc = open_internal_inner1(path, oflag); - file_internal_unlock_WRITER(); - return rc; -} - -int ctru_open(const char *path, int oflag, ...) -{ - logf("open(path=\"%s\",oflag=%X)\n", path, (unsigned)oflag); - return open_internal_locked(path, oflag); -} - -int ctru_creat(const char *path, mode_t mode) -{ - logf("creat(path=\"%s\")\n", path); - return ctru_open(path, O_WRONLY|O_CREAT|O_TRUNC, mode); -} - -int ctru_close(int fildes) -{ - logf("close(fd=%d)\n", fildes); - - int rc; - - file_internal_lock_WRITER(); - - /* needs to work even if marked "nonexistant" */ - struct filestr_desc *file = &open_streams[fildes]; - if ((unsigned int)fildes >= MAX_OPEN_FILES || (file->stream.cache == nil)) - { - logf("filedes %d not open\n", fildes); - FILE_ERROR(EBADF, -2); - } - - if (file->stream.cache != nil) { - PagerFlush(file->stream.cache); - PagerClear(file->stream.cache); - file->stream.cache = nil; - } - - FSFILE_Close(file->stream.handle); - file->stream.handle = 0; - file->stream.path[0] = '\0'; - - rc = 0; -file_error: - file_internal_unlock_WRITER(); - return rc; -} - -/* truncate a file to a specified length */ -int ctru_ftruncate(int fildes, off_t length) -{ - logf("ftruncate(fd=%d,len=%ld)\n", fildes, (long)length); - - struct filestr_desc * const file = GET_FILESTR(READER, fildes); - if (!file) - FILE_ERROR_RETURN(ERRNO, -1); - - int rc; - - if (file->stream.flags & O_RDONLY) - { - logf("Descriptor is read-only mode\n"); - FILE_ERROR(EBADF, -2); - } - - if (length < 0) - { - logf("Length %ld is invalid\n", (long)length); - FILE_ERROR(EINVAL, -3); - } - - file_error_t err = PagerTruncate(file->stream.cache, length); - if (err) { - FILE_ERROR(ERRNO, -11); - } - - *file->sizep = length; - - rc = 0; -file_error: - RELEASE_FILESTR(READER, file); - return rc; -} - -/* synchronize changes to a file */ -int ctru_fsync(int fildes) -{ - logf("fsync(fd=%d)\n", fildes); - - struct filestr_desc * const file = GET_FILESTR(WRITER, fildes); - if (!file) - FILE_ERROR_RETURN(ERRNO, -1); - - int rc; - - if (file->stream.flags & O_RDONLY) - { - logf("Descriptor is read-only mode\n"); - FILE_ERROR(EINVAL, -2); - } - - /* flush all pending changes to disk */ - file_error_t err = PagerFlush(file->stream.cache); - if (err != nil) { - FILE_ERROR(ERRNO, -3); - } - - rc = 0; -file_error: - RELEASE_FILESTR(WRITER, file); - return rc; -} - -/* move the read/write file offset */ -off_t ctru_lseek(int fildes, off_t offset, int whence) -{ -#ifndef LOGF_ENABLE /* wipes out log before you can save it */ - /* DEBUGF("lseek(fd=%d,ofs=%ld,wh=%d)\n", fildes, (long)offset, whence); */ -#endif - struct filestr_desc * const file = GET_FILESTR(READER, fildes); - if (!file) - FILE_ERROR_RETURN(ERRNO, -1); - - off_t rc = lseek_internal(file, offset, whence); - if (rc < 0) - FILE_ERROR(ERRNO, rc * 10 - 2); - -file_error: - RELEASE_FILESTR(READER, file); - return rc; -} - -/* read from a file */ -ssize_t ctru_read(int fildes, void *buf, size_t nbyte) -{ - struct filestr_desc * const file = GET_FILESTR(READER, fildes); - if (!file) - FILE_ERROR_RETURN(ERRNO, -1); - - ssize_t rc; - - if (file->stream.flags & O_WRONLY) - { - logf("read(fd=%d,buf=%p,nb=%lu) - " - "descriptor is write-only mode\n", - fildes, buf, (unsigned long)nbyte); - FILE_ERROR(EBADF, -2); - } - - rc = readwrite(file, buf, nbyte, false); - if (rc < 0) - FILE_ERROR(ERRNO, rc * 10 - 3); - -file_error: - RELEASE_FILESTR(READER, file); - return rc; -} - -/* write on a file */ -ssize_t ctru_write(int fildes, const void *buf, size_t nbyte) -{ - struct filestr_desc * const file = GET_FILESTR(READER, fildes); - if (!file) - FILE_ERROR_RETURN(ERRNO, -1); - - ssize_t rc; - - if (file->stream.flags & O_RDONLY) - { - logf("write(fd=%d,buf=%p,nb=%lu) - " - "descriptor is read-only mode\n", - fildes, buf, (unsigned long)nbyte); - FILE_ERROR(EBADF, -2); - } - - rc = readwrite(file, (void *)buf, nbyte, true); - if (rc < 0) - FILE_ERROR(ERRNO, rc * 10 - 3); - -file_error: - RELEASE_FILESTR(READER, file); - return rc; -} - -/* remove a file */ -int ctru_remove(const char *path) -{ - logf("remove(path=\"%s\")\n", path); - - int rc; - - file_internal_lock_WRITER(); - Result res = FSUSER_DeleteFile(sdmcArchive, - fsMakePath(PATH_ASCII, path)); - if (R_FAILED(res)) - FILE_ERROR(ERRNO, -1); - - rc = 0; -file_error: - file_internal_unlock_WRITER(); - return rc; -} - -/* rename a file */ -int ctru_rename(const char *old, const char *new) -{ - /* note: move by rename does not work in devkitARM toolchain */ - logf("rename(old=\"%s\",new=\"%s\")\n", old, new); - - int rc; - - /* if 'old' is a directory then 'new' is also required to be one if 'new' - is to be overwritten */ - bool are_dirs = false; - - file_internal_lock_WRITER(); - - if (!strcmp(new, old)) /* case-only is ok */ - { - logf("No name change (success)\n"); - rc = 0; - FILE_ERROR(ERRNO, _RC); - } - - /* open 'old'; it must exist */ - Handle open1rc; - Result res = FSUSER_OpenFile(&open1rc, - sdmcArchive, - fsMakePath(PATH_ASCII, old), - FS_OPEN_READ, - 0); - if (R_FAILED(res)) { - /* not a file, try to open a directory */ - res = FSUSER_OpenDirectory(&open1rc, - sdmcArchive, - fsMakePath(PATH_ASCII, old)); - if (R_FAILED(res)) { - logf("Failed opening old\n"); - FILE_ERROR(ERRNO, -1); - } - - are_dirs = true; - } - - if (are_dirs) { - /* rename directory */ - FSUSER_RenameDirectory(sdmcArchive, - fsMakePath(PATH_ASCII, old), - sdmcArchive, - fsMakePath(PATH_ASCII, new)); - } - else { - /* rename file */ - FSUSER_RenameFile(sdmcArchive, - fsMakePath(PATH_ASCII, old), - sdmcArchive, - fsMakePath(PATH_ASCII, new)); - } - - if (R_FAILED(res)) { - logf("Rename failed\n"); - FILE_ERROR(ERRNO, -2); - } - - rc = 0; -file_error: - /* for now, there is nothing to fail upon closing the old stream */ - if (open1rc > 0) { - if (are_dirs) - FSDIR_Close(open1rc); - else - FSFILE_Close(open1rc); - } - - file_internal_unlock_WRITER(); - return rc; -} - -/** Extensions **/ - -/* todo: utime does not work in devkitARM toolchain */ -int ctru_modtime(const char *path, time_t modtime) -{ - struct utimbuf times = - { - .actime = modtime, - .modtime = modtime, - }; - - return utime(path, ×); -} - -/* get the binary size of a file (in bytes) */ -off_t ctru_filesize(int fildes) -{ - struct filestr_desc * const file = GET_FILESTR(READER, fildes); - if (!file) - FILE_ERROR_RETURN(ERRNO, -1); - - off_t rc; - file_size_t size = *file->sizep; - - if (size > FILE_SIZE_MAX) - FILE_ERROR(EOVERFLOW, -2); - - rc = (off_t)size; -file_error: - RELEASE_FILESTR(READER, file); - return rc; -} - -/* test if two file descriptors refer to the same file */ -int ctru_fsamefile(int fildes1, int fildes2) -{ - struct filestr_desc * const file1 = GET_FILESTR(WRITER, fildes1); - if (!file1) - FILE_ERROR_RETURN(ERRNO, -1); - - int rc = -2; - - struct filestr_desc * const file2 = get_filestr(fildes2); - if (file2) - rc = strcmp(file1->stream.path, file2->stream.path) == 0 ? 1 : 0; - - RELEASE_FILESTR(WRITER, file1); - return rc; -} - -/* tell the relationship of path1 to path2 */ -int ctru_relate(const char *path1, const char *path2) -{ - /* FAT32 file system does not support symbolic links, - therefore, comparing the two full paths should be enough - to tell relationship */ - logf("relate(path1=\"%s\",path2=\"%s\")\n", path1, path2); - int rc = RELATE_DIFFERENT; - if (strcmp(path1, path2) == 0) - rc = RELATE_SAME; - return rc; -} - -/* test file or directory existence */ -bool ctru_file_exists(const char *path) -{ - file_internal_lock_WRITER(); - bool rc = test_stream_exists_internal(path) > 0; - file_internal_unlock_WRITER(); - return rc; -} - -/* note: no symbolic links support in devkitARM */ -ssize_t ctru_readlink(const char *path, char *buf, size_t bufsiz) -{ - return readlink(path, buf, bufsiz); -} - diff --git a/firmware/target/hosted/ctru/lib/sys_file.h b/firmware/target/hosted/ctru/lib/sys_file.h deleted file mode 100644 index cfed6017fc..0000000000 --- a/firmware/target/hosted/ctru/lib/sys_file.h +++ /dev/null @@ -1,129 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 by Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _SYS_FILE_H -#define _SYS_FILE_H - -#include "bfile.h" - -/* Include for file.h and dir.h because mkdir and friends may be here */ -#include - -#define strlcpy_from_os strlcpy - -#define AtomicLoad(ptr) __atomic_load_n((u32*)(ptr), __ATOMIC_SEQ_CST) -#define AtomicAdd(ptr, value) __atomic_add_fetch((u32*)(ptr), value, __ATOMIC_SEQ_CST) - -struct filestr_base { - Pager* cache; /* buffer IO implementation (cache) */ - Handle handle; /* file handle */ - u64 size; /* file size */ - int flags; /* stream flags */ - char path[MAX_PATH+1]; - - LightLock mtx; /* serialization for this stream */ -}; - -static inline void filestr_lock(struct filestr_base *stream) -{ - LightLock_Lock(&stream->mtx); -} - -static inline void filestr_unlock(struct filestr_base *stream) -{ - LightLock_Unlock(&stream->mtx); -} - -/* stream lock doesn't have to be used if getting RW lock writer access */ -#define FILESTR_WRITER 0 -#define FILESTR_READER 1 - -#define FILESTR_LOCK(type, stream) \ - ({ if (FILESTR_##type) filestr_lock(stream); }) - -#define FILESTR_UNLOCK(type, stream) \ - ({ if (FILESTR_##type) filestr_unlock(stream); }) - -/** Synchronization used throughout **/ - -/* acquire the filesystem lock as READER */ -static inline void file_internal_lock_READER(void) -{ - extern sync_RWMutex file_internal_mrsw; - sync_RWMutexRLock(&file_internal_mrsw); -} - -/* release the filesystem lock as READER */ -static inline void file_internal_unlock_READER(void) -{ - extern sync_RWMutex file_internal_mrsw; - sync_RWMutexRUnlock(&file_internal_mrsw); -} - -/* acquire the filesystem lock as WRITER */ -static inline void file_internal_lock_WRITER(void) -{ - extern sync_RWMutex file_internal_mrsw; - sync_RWMutexLock(&file_internal_mrsw); -} - -/* release the filesystem lock as WRITER */ -static inline void file_internal_unlock_WRITER(void) -{ - extern sync_RWMutex file_internal_mrsw; - sync_RWMutexUnlock(&file_internal_mrsw); -} - -#define ERRNO 0 /* maintain errno value */ -#define _RC 0 /* maintain rc value */ - -/* NOTES: if _errno is a non-constant expression, it must set an error - * number and not return the ERRNO constant which will merely set - * errno to zero, not preserve the current value; if you must set - * errno to zero, set it explicitly, not in the macro - * - * if _rc is constant-expression evaluation to 'RC', then rc will - * NOT be altered; i.e. if you must set rc to zero, set it explicitly, - * not in the macro - */ - -#define FILE_SET_CODE(_name, _keepcode, _value) \ - ({ __builtin_constant_p(_value) ? \ - ({ if ((_value) != (_keepcode)) _name = (_value); }) : \ - ({ _name = (_value); }); }) - -/* set errno and rc and proceed to the "file_error:" label */ -#define FILE_ERROR(_errno, _rc) \ - ({ FILE_SET_CODE(errno, ERRNO, (_errno)); \ - FILE_SET_CODE(rc, _RC, (_rc)); \ - goto file_error; }) - -/* set errno and return a value at the point of invocation */ -#define FILE_ERROR_RETURN(_errno, _rc...) \ - ({ FILE_SET_CODE(errno, ERRNO, _errno); \ - return _rc; }) - -/* set errno and return code, no branching */ -#define FILE_ERROR_SET(_errno, _rc) \ - ({ FILE_SET_CODE(errno, ERRNO, (_errno)); \ - FILE_SET_CODE(rc, _RC, (_rc)); }) - -#endif /* _SYS_FILE_H */ - diff --git a/firmware/target/hosted/ctru/lib/sys_thread.c b/firmware/target/hosted/ctru/lib/sys_thread.c deleted file mode 100644 index 4d6ba2ff99..0000000000 --- a/firmware/target/hosted/ctru/lib/sys_thread.c +++ /dev/null @@ -1,403 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio Ga. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include "sys_thread.h" -#include "sys_timer.h" -#include "debug.h" -#include "logf.h" - -bool _AtomicCAS(u32 *ptr, int oldval, int newval) -{ - int expected = oldval; - int desired = newval; - return __atomic_compare_exchange(ptr, &expected, &desired, false, - __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); -} - -bool _AtomicTryLock(int *lock) -{ - int result; - asm volatile( - "ldrex %0, [%2] \n" - "teq %0, #0 \n" - "strexeq %0, %1, [%2] \n" - : "=&r"(result) - : "r"(1), "r"(lock) - : "cc", "memory" - ); - return result == 0; -} - -#define CPUPauseInstruction() asm volatile("yield" ::: "memory") -void AtomicLock(int *lock) -{ - int iterations = 0; - while (!_AtomicTryLock(lock)) { - if (iterations < 32) { - iterations++; - CPUPauseInstruction(); - } else { - sys_delay(0); - } - } -} - -void AtomicUnlock(int *lock) -{ - *lock = 0; -} - -/* Convert rockbox priority value to libctru value */ -int get_ctru_thread_priority(int priority) -{ - if ((priority == PRIORITY_REALTIME_1) || (priority == PRIORITY_REALTIME_2) || - (priority == PRIORITY_REALTIME_3) || (priority == PRIORITY_REALTIME_4) || - (priority == PRIORITY_REALTIME)) - return 0x18; - else if (priority == PRIORITY_BUFFERING) - return 0x18; /* Highest */ - else if ((priority == PRIORITY_USER_INTERFACE) || (priority == PRIORITY_RECORDING) || - (priority == PRIORITY_PLAYBACK)) - return 0x30; - else if (priority == PRIORITY_PLAYBACK_MAX) - return 0x2F; - else if (priority == PRIORITY_SYSTEM) - return 0x30; - else if (priority == PRIORITY_BACKGROUND) - return 0x3F; /* Lowest */ - else - return 0x30; -} - -static size_t get_thread_stack_size(size_t requested_size) -{ - if (requested_size == 0) { - return (80 * 1024); /* 80 kB */ - } - - return requested_size; -} - -static void thread_entry(void *arg) -{ - sys_run_thread((sysThread *)arg); - threadExit(0); -} - -int wait_on_semaphore_for(LightSemaphore *sem, u32 timeout) -{ - u64 stop_time = sys_get_ticks64() + timeout; - u64 current_time = sys_get_ticks64(); - while (current_time < stop_time) { - if (LightSemaphore_TryAcquire(sem, 1) == 0) { - return 0; - } - /* 100 microseconds seems to be the sweet spot */ - svcSleepThread(100000LL); - current_time = sys_get_ticks64(); - } - - /* If we failed, yield to avoid starvation on busy waits */ - svcSleepThread(1); - return 1; -} - -int sys_sem_try_wait(LightSemaphore *sem) -{ - if (LightSemaphore_TryAcquire(sem, 1) != 0) { - /* If we failed, yield to avoid starvation on busy waits */ - svcSleepThread(1); - return 1; - } - - return 0; -} - -int sys_sem_wait_timeout(LightSemaphore *sem, u32 timeout) -{ - if (timeout == (~(u32)0)) { - LightSemaphore_Acquire(sem, 1); - return 0; - } - - if (LightSemaphore_TryAcquire(sem, 1) != 0) { - return wait_on_semaphore_for(sem, timeout); - } - - return 0; -} - -int sys_sem_wait(LightSemaphore *sem) -{ - return sys_sem_wait_timeout(sem, (~(u32)0)); -} - -u32 sys_sem_value(LightSemaphore *sem) -{ - return sem->current_count; -} - -int sys_thread_id(void) -{ - u32 thread_ID = 0; - svcGetThreadId(&thread_ID, CUR_THREAD_HANDLE); - return (int)thread_ID; -} - -void sys_run_thread(sysThread *thread) -{ - void *userdata = thread->userdata; - int(* userfunc)(void *) = thread->userfunc; - - int *statusloc = &thread->status; - - /* Get the thread id */ - thread->threadid = sys_thread_id(); - - /* Run the function */ - *statusloc = userfunc(userdata); - - /* Mark us as ready to be joined (or detached) */ - if (!AtomicCAS(&thread->state, THREAD_STATE_ALIVE, THREAD_STATE_ZOMBIE)) { - /* Clean up if something already detached us. */ - if (AtomicCAS(&thread->state, THREAD_STATE_DETACHED, THREAD_STATE_CLEANED)) { - free(thread); - } - } -} - -sysThread *sys_create_thread(int(*fn)(void *), const char *name, const size_t stacksize, - void *data IF_PRIO(, int priority) IF_COP(, unsigned int core)) -{ - sys_ticks_init(); - - /* Allocate memory for the thread info structure */ - sysThread *thread = (sysThread *) calloc(1, sizeof(sysThread)); - if (thread == NULL) { - DEBUGF("sys_create_thread: could not allocate memory\n"); - return NULL; - } - thread->status = -1; - AtomicSet(&thread->state, THREAD_STATE_ALIVE); - - /* Set up the arguments for the thread */ - thread->userfunc = fn; - thread->userdata = data; - thread->stacksize = stacksize; - - int cpu = -1; - if (name && (strncmp(name, "tagcache", 8) == 0) && R_SUCCEEDED(APT_SetAppCpuTimeLimit(30))) { - cpu = 1; - printf("thread: %s, running in cpu 1\n", name); - } - - thread->handle = threadCreate(thread_entry, - thread, - get_thread_stack_size(stacksize), - get_ctru_thread_priority(priority), - cpu, - false); - - if (!thread->handle) { - DEBUGF("sys_create_thread: threadCreate failed\n"); - free(thread); - thread = NULL; - } - - /* Everything is running now */ - return thread; -} - -void sys_wait_thread(sysThread *thread, int *status) -{ - if (thread) { - Result res = threadJoin(thread->handle, U64_MAX); - - /* - Detached threads can be waited on, but should NOT be cleaned manually - as it would result in a fatal error. - */ - if (R_SUCCEEDED(res) && AtomicGet(&thread->state) != THREAD_STATE_DETACHED) { - threadFree(thread->handle); - } - if (status) { - *status = thread->status; - } - free(thread); - } -} - -void sys_detach_thread(sysThread *thread) -{ - if (!thread) { - return; - } - - /* Grab dibs if the state is alive+joinable. */ - if (AtomicCAS(&thread->state, THREAD_STATE_ALIVE, THREAD_STATE_DETACHED)) { - threadDetach(thread->handle); - } else { - /* all other states are pretty final, see where we landed. */ - const int thread_state = AtomicGet(&thread->state); - if ((thread_state == THREAD_STATE_DETACHED) || (thread_state == THREAD_STATE_CLEANED)) { - return; /* already detached (you shouldn't call this twice!) */ - } else if (thread_state == THREAD_STATE_ZOMBIE) { - sys_wait_thread(thread, NULL); /* already done, clean it up. */ - } else { - assert(0 && "Unexpected thread state"); - } - } -} - -int sys_set_thread_priority(sysThread *thread, int priority) -{ - Handle h = threadGetHandle(thread->handle); - int old_priority = priority; - Result res = svcSetThreadPriority(h, get_ctru_thread_priority(priority)); - if (R_SUCCEEDED(res)) { - return priority; - } - - return old_priority; -} - -/* sysCond */ -sysCond *sys_cond_create(void) -{ - sysCond *cond; - - cond = (sysCond *)malloc(sizeof(sysCond)); - if (cond) { - RecursiveLock_Init(&cond->lock); - LightSemaphore_Init(&cond->wait_sem, 0, ((s16)0x7FFF)); - LightSemaphore_Init(&cond->wait_done, 0, ((s16)0x7FFF)); - cond->waiting = cond->signals = 0; - } else { - DEBUGF("sys_cond_create: out of memory.\n");; - } - return cond; -} - -/* Destroy a condition variable */ -void sys_cond_destroy(sysCond *cond) -{ - if (cond) { - free(cond); - } -} - -/* Restart one of the threads that are waiting on the condition variable */ -int sys_cond_signal(sysCond *cond) -{ - if (!cond) { - DEBUGF("sys_cond_signal: Invalid param 'cond'\n"); - return -1; - } - - /* If there are waiting threads not already signalled, then - signal the condition and wait for the thread to respond. - */ - RecursiveLock_Lock(&cond->lock); - if (cond->waiting > cond->signals) { - ++cond->signals; - LightSemaphore_Release(&cond->wait_sem, 1); - RecursiveLock_Unlock(&cond->lock); - LightSemaphore_Acquire(&cond->wait_done, 1); - } else { - RecursiveLock_Unlock(&cond->lock); - } - - return 0; -} - -/* Restart all threads that are waiting on the condition variable */ -int sys_cond_broadcast(sysCond *cond) -{ - if (!cond) { - DEBUGF("sys_cond_signal: Invalid param 'cond'\n"); - return -1; - } - - /* If there are waiting threads not already signalled, then - signal the condition and wait for the thread to respond. - */ - RecursiveLock_Lock(&cond->lock); - if (cond->waiting > cond->signals) { - int i, num_waiting; - - num_waiting = (cond->waiting - cond->signals); - cond->signals = cond->waiting; - for (i = 0; i < num_waiting; ++i) { - LightSemaphore_Release(&cond->wait_sem, 1); - } - /* Now all released threads are blocked here, waiting for us. - Collect them all (and win fabulous prizes!) :-) - */ - RecursiveLock_Unlock(&cond->lock); - for (i = 0; i < num_waiting; ++i) { - LightSemaphore_Acquire(&cond->wait_done, 1); - } - } else { - RecursiveLock_Unlock(&cond->lock); - } - - return 0; -} - -int sys_cond_wait(sysCond *cond, RecursiveLock *mutex) -{ - if (!cond) { - DEBUGF("sys_cond_signal: Invalid param 'cond'\n"); - return -1; - } - - RecursiveLock_Lock(&cond->lock); - ++cond->waiting; - RecursiveLock_Unlock(&cond->lock); - - /* Unlock the mutex, as is required by condition variable semantics */ - RecursiveLock_Unlock(mutex); - - /* Wait for a signal */ - LightSemaphore_Acquire(&cond->wait_sem, 1); - - RecursiveLock_Lock(&cond->lock); - if (cond->signals > 0) { - /* We always notify the signal thread that we are done */ - LightSemaphore_Release(&cond->wait_done, 1); - - /* Signal handshake complete */ - --cond->signals; - } - --cond->waiting; - RecursiveLock_Unlock(&cond->lock); - - /* Lock the mutex, as is required by condition variable semantics */ - RecursiveLock_Lock(mutex); - - return 0; -} - diff --git a/firmware/target/hosted/ctru/lib/sys_thread.h b/firmware/target/hosted/ctru/lib/sys_thread.h deleted file mode 100644 index c951668993..0000000000 --- a/firmware/target/hosted/ctru/lib/sys_thread.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __SYSTHREAD_H__ -#define __SYSTHREAD_H__ - -#include "thread.h" - -#include <3ds/synchronization.h> -#include <3ds/thread.h> -#include <3ds/services/apt.h> - -/* Complementary atomic operations */ -bool _AtomicCAS(u32 *ptr, int oldval, int newval); -#define AtomicGet(ptr) __atomic_load_n((u32*)(ptr), __ATOMIC_SEQ_CST) -#define AtomicSet(ptr, value) AtomicSwap(ptr, value) -#define AtomicCAS(ptr, oldvalue, newvalue) _AtomicCAS((u32 *)(ptr), oldvalue, newvalue) -void AtomicLock(int *lock); -void AtomicUnlock(int *lock); - -/* This code was taken from SDL2 thread implementation */ - -enum thread_state_t -{ - THREAD_STATE_ALIVE, - THREAD_STATE_DETACHED, - THREAD_STATE_ZOMBIE, - THREAD_STATE_CLEANED, -}; - -typedef struct _thread -{ - int threadid; - Thread handle; - int status; - int state; - size_t stacksize; - int(* userfunc)(void *); - void *userdata; - void *data; -} sysThread; - -typedef struct _cond -{ - RecursiveLock lock; - int waiting; - int signals; - LightSemaphore wait_sem; - LightSemaphore wait_done; -} sysCond; - -int sys_sem_wait(LightSemaphore *sem); -int sys_sem_wait_timeout(LightSemaphore *sem, u32 timeout); -int sys_sem_try_wait(LightSemaphore *sem); -u32 sys_sem_value(LightSemaphore *sem); - -sysThread *sys_create_thread(int(*fn)(void *), const char *name, const size_t stacksize, - void *data IF_PRIO(, int priority) IF_COP(, unsigned int core)); -void sys_run_thread(sysThread *thread); -void sys_wait_thread(sysThread *thread, int *status); -int sys_thread_id(void); -int sys_set_thread_priority(sysThread *thread, int priority); - -sysCond *sys_cond_create(void); -void sys_cond_destroy(sysCond *cond); -int sys_cond_signal(sysCond *cond); -int sys_cond_broadcast(sysCond *cond); -int sys_cond_wait(sysCond *cond, RecursiveLock *mutex); -#endif /* #ifndef __SYSTHREAD_H__ */ - diff --git a/firmware/target/hosted/ctru/lib/sys_timer.c b/firmware/target/hosted/ctru/lib/sys_timer.c deleted file mode 100644 index a38d7ca032..0000000000 --- a/firmware/target/hosted/ctru/lib/sys_timer.c +++ /dev/null @@ -1,402 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 Dan Everton - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include "debug.h" -#include "logf.h" - -#include <3ds/os.h> -#include "sys_thread.h" -#include "sys_timer.h" - -#define CACHELINE_SIZE 128 - -static bool ticks_started = false; -static u64 start_tick; - -#define NSEC_PER_MSEC 1000000ULL - -void sys_ticks_init(void) -{ - if (ticks_started) { - return; - } - ticks_started = true; - - start_tick = svcGetSystemTick(); -} - -void sys_ticks_quit(void) -{ - ticks_started = false; -} - -u64 sys_get_ticks64(void) -{ - u64 elapsed; - if (!ticks_started) { - sys_ticks_init(); - } - - elapsed = svcGetSystemTick() - start_tick; - return elapsed / CPU_TICKS_PER_MSEC; -} - -u32 sys_get_ticks(void) -{ - return (u32)(sys_get_ticks64() & 0xFFFFFFFF); -} - -void sys_delay(u32 ms) -{ - svcSleepThread(ms * NSEC_PER_MSEC); -} - -typedef struct _timer -{ - int timerID; - timer_callback_ptr callback; - void *param; - u32 interval; - u32 scheduled; - int canceled; - struct _timer *next; -} sysTimer; - -typedef struct _timer_map -{ - int timerID; - sysTimer *timer; - struct _timer_map *next; -} timerMap; - -/* The timers are kept in a sorted list */ -typedef struct -{ - /* Data used by the main thread */ - Thread thread; - int nextID; - timerMap *timermap; - RecursiveLock timermap_lock; - - /* Padding to separate cache lines between threads */ - char cache_pad[CACHELINE_SIZE]; - - /* Data used to communicate with the timer thread */ - int lock; - LightSemaphore sem; - sysTimer *pending; - sysTimer *freelist; - int active; - - /* List of timers - this is only touched by the timer thread */ - sysTimer *timers; -} timerData; - -static timerData timer_data = { .active = 0 }; - -/* The idea here is that any thread might add a timer, but a single - * thread manages the active timer queue, sorted by scheduling time. - * - * Timers are removed by simply setting a canceled flag - */ - -static void add_timer_interval(timerData *data, sysTimer *timer) -{ - sysTimer *prev, *curr; - - prev = NULL; - for (curr = data->timers; curr; prev = curr, curr = curr->next) { - if ((s32)(timer->scheduled - curr->scheduled) < 0) { - break; - } - } - - /* Insert the timer here! */ - if (prev) { - prev->next = timer; - } else { - data->timers = timer; - } - timer->next = curr; -} - -static void timer_thread(void *_data) -{ - timerData *data = (timerData *)_data; - sysTimer *pending; - sysTimer *current; - sysTimer *freelist_head = NULL; - sysTimer *freelist_tail = NULL; - u32 tick, now, interval, delay; - - /* Threaded timer loop: - * 1. Queue timers added by other threads - * 2. Handle any timers that should dispatch this cycle - * 3. Wait until next dispatch time or new timer arrives - */ - for (;;) { - /* Pending and freelist maintenance */ - AtomicLock(&data->lock); - { - /* Get any timers ready to be queued */ - pending = data->pending; - data->pending = NULL; - - /* Make any unused timer structures available */ - if (freelist_head) { - freelist_tail->next = data->freelist; - data->freelist = freelist_head; - } - } - AtomicUnlock(&data->lock); - - /* Sort the pending timers into our list */ - while (pending) { - current = pending; - pending = pending->next; - add_timer_interval(data, current); - } - freelist_head = NULL; - freelist_tail = NULL; - - /* Check to see if we're still running, after maintenance */ - if (!AtomicGet(&data->active)) { - break; - } - - /* Initial delay if there are no timers */ - delay = (~(u32)0); - - tick = sys_get_ticks(); - - /* Process all the pending timers for this tick */ - while (data->timers) { - current = data->timers; - - if ((s32)(tick - current->scheduled) < 0) { - /* Scheduled for the future, wait a bit */ - delay = (current->scheduled - tick); - break; - } - - /* We're going to do something with this timer */ - data->timers = current->next; - - if (AtomicGet(¤t->canceled)) { - interval = 0; - } else { - interval = current->callback(current->interval, current->param); - } - - if (interval > 0) { - /* Reschedule this timer */ - current->interval = interval; - current->scheduled = tick + interval; - add_timer_interval(data, current); - } else { - if (!freelist_head) { - freelist_head = current; - } - if (freelist_tail) { - freelist_tail->next = current; - } - freelist_tail = current; - - AtomicSet(¤t->canceled, 1); - } - } - - /* Adjust the delay based on processing time */ - now = sys_get_ticks(); - interval = (now - tick); - if (interval > delay) { - delay = 0; - } else { - delay -= interval; - } - - /* Note that each time a timer is added, this will return - immediately, but we process the timers added all at once. - That's okay, it just means we run through the loop a few - extra times. - */ - sys_sem_wait_timeout(&data->sem, delay); - } -} - -int sys_timer_init(void) -{ - timerData *data = &timer_data; - - if (!AtomicGet(&data->active)) { - RecursiveLock_Init(&data->timermap_lock); - LightSemaphore_Init(&data->sem, 0, ((s16)0x7FFF)); - AtomicSet(&data->active, 1); - - /* Timer threads use a callback into the app, so we can't set a limited stack size here. */ - data->thread = threadCreate(timer_thread, - data, - 32 * 1024, - 0x28, - -1, - false); - if (!data->thread) { - sys_timer_quit(); - return -1; - } - - AtomicSet(&data->nextID, 1); - } - return 0; -} - -void sys_timer_quit(void) -{ - timerData *data = &timer_data; - sysTimer *timer; - timerMap *entry; - - if (AtomicCAS(&data->active, 1, 0)) { /* active? Move to inactive. */ - /* Shutdown the timer thread */ - if (data->thread) { - LightSemaphore_Release(&data->sem, 1); - Result res = threadJoin(data->thread, U64_MAX); - threadFree(data->thread); - data->thread = NULL; - } - - /* Clean up the timer entries */ - while (data->timers) { - timer = data->timers; - data->timers = timer->next; - free(timer); - } - while (data->freelist) { - timer = data->freelist; - data->freelist = timer->next; - free(timer); - } - while (data->timermap) { - entry = data->timermap; - data->timermap = entry->next; - free(entry); - } - } -} - -int sys_add_timer(u32 interval, timer_callback_ptr callback, void *param) -{ - timerData *data = &timer_data; - sysTimer *timer; - timerMap *entry; - - AtomicLock(&data->lock); - if (!AtomicGet(&data->active)) { - if (sys_timer_init() < 0) { - AtomicUnlock(&data->lock); - return 0; - } - } - - timer = data->freelist; - if (timer) { - data->freelist = timer->next; - } - AtomicUnlock(&data->lock); - - if (timer) { - sys_remove_timer(timer->timerID); - } else { - timer = (sysTimer *) malloc(sizeof(*timer)); - if (!timer) { - DEBUGF("sys_add_timer: out of memory\n"); - return 0; - } - } - timer->timerID = AtomicIncrement(&data->nextID); - timer->callback = callback; - timer->param = param; - timer->interval = interval; - timer->scheduled = sys_get_ticks() + interval; - AtomicSet(&timer->canceled, 0); - - entry = (timerMap *) malloc(sizeof(*entry)); - if (!entry) { - free(timer); - DEBUGF("sys_add_timer: out of memory\n"); - return 0; - } - entry->timer = timer; - entry->timerID = timer->timerID; - - RecursiveLock_Lock(&data->timermap_lock); - entry->next = data->timermap; - data->timermap = entry; - RecursiveLock_Unlock(&data->timermap_lock); - - /* Add the timer to the pending list for the timer thread */ - AtomicLock(&data->lock); - timer->next = data->pending; - data->pending = timer; - AtomicUnlock(&data->lock); - - /* Wake up the timer thread if necessary */ - LightSemaphore_Release(&data->sem, 1); - - return entry->timerID; -} - -bool sys_remove_timer(int id) -{ - timerData *data = &timer_data; - timerMap *prev, *entry; - bool canceled = false; - - /* Find the timer */ - RecursiveLock_Lock(&data->timermap_lock); - prev = NULL; - for (entry = data->timermap; entry; prev = entry, entry = entry->next) { - if (entry->timerID == id) { - if (prev) { - prev->next = entry->next; - } else { - data->timermap = entry->next; - } - break; - } - } - RecursiveLock_Unlock(&data->timermap_lock); - - if (entry) { - if (!AtomicGet(&entry->timer->canceled)) { - AtomicSet(&entry->timer->canceled, 1); - canceled = true; - } - free(entry); - } - return canceled; -} - diff --git a/firmware/target/hosted/ctru/lib/sys_timer.h b/firmware/target/hosted/ctru/lib/sys_timer.h deleted file mode 100644 index cccaab4fce..0000000000 --- a/firmware/target/hosted/ctru/lib/sys_timer.h +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __SYSTIMER_H__ -#define __SYSTIMER_H__ - -#include <3ds/svc.h> -#include "sys_thread.h" - -typedef u32 (* timer_callback_ptr) (u32 interval, void *param); - -void sys_ticks_init(void); -void sys_ticks_quit(void); -u32 sys_get_ticks(void); -u64 sys_get_ticks64(void); -void sys_delay(u32 ms); - -int sys_timer_init(void); -void sys_timer_quit(void); -int sys_add_timer(u32 interval, timer_callback_ptr callback, void *param); -bool sys_remove_timer(int id); - -#endif /* #ifndef __SYSTIMER_H__ */ - diff --git a/firmware/target/hosted/ctru/luminance-ctru.c b/firmware/target/hosted/ctru/luminance-ctru.c deleted file mode 100644 index 7d1d0a3310..0000000000 --- a/firmware/target/hosted/ctru/luminance-ctru.c +++ /dev/null @@ -1,133 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2016-2020 Aurora Wright, TuxSH -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Additional Terms 7.b and 7.c of GPLv3 apply to this file: -* * Requiring preservation of specified reasonable legal notices or -* author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -* * Prohibiting misrepresentation of the origin of that material, -* or requiring that modified versions of such material be marked in -* reasonable ways as different from the original version. -*/ - -/* This file is taken from Luma3DS project */ - -#include <3ds.h> -#include -#include "luminance-ctru.h" - -// For accessing physmem uncached (and directly) -#define PA_PTR(addr) (void *)((u32)(addr) | 1 << 31) - -#ifndef PA_FROM_VA_PTR -#define PA_FROM_VA_PTR(addr) PA_PTR(svcConvertVAToPA((const void *)(addr), false)) -#endif - -#define REG32(addr) (*(vu32 *)(PA_PTR(addr))) - - -extern bool is_n3ds; - -typedef struct BlPwmData -{ - float coeffs[3][3]; - u8 numLevels; - u8 unk; - u16 luminanceLevels[7]; - u16 brightnessMax; - u16 brightnessMin; -} BlPwmData; - -// Calibration, with (dubious) default values as fallback -static BlPwmData s_blPwmData = { - .coeffs = { - { 0.00111639f, 1.41412f, 0.07178809f }, - { 0.000418169f, 0.66567f, 0.06098654f }, - { 0.00208543f, 1.55639f, 0.0385939f } - }, - .numLevels = 5, - .unk = 0, - .luminanceLevels = { 20, 43, 73, 95, 117, 172, 172 }, - .brightnessMax = 512, - .brightnessMin = 13, -}; - -static inline float getPwmRatio(u32 brightnessMax, u32 pwmCnt) -{ - u32 val = (pwmCnt & 0x10000) ? pwmCnt & 0x3FF : 511; // check pwm enabled flag - return (float)brightnessMax / (val + 1); -} - -// nn's asm has rounding errors (originally at 10^-3) -static inline u32 luminanceToBrightness(u32 luminance, const float coeffs[3], u32 minLuminance, float pwmRatio) -{ - float x = (float)luminance; - float y = coeffs[0]*x*x + coeffs[1]*x + coeffs[2]; - y = (y <= minLuminance ? (float)minLuminance : y) / pwmRatio; - - return (u32)(y + 0.5f); -} - -static inline u32 brightnessToLuminance(u32 brightness, const float coeffs[3], float pwmRatio) -{ - // Find polynomial root of ax^2 + bx + c = y - - float y = (float)brightness * pwmRatio; - float a = coeffs[0]; - float b = coeffs[1]; - float c = coeffs[2] - y; - - float x0 = (-b + sqrtf(b*b - 4.0f*a*c)) / (a + a); - - return (u32)(x0 + 0.5f); -} - -static void readCalibration(void) -{ - static bool calibRead = false; - - if (!calibRead) { - cfguInit(); - calibRead = R_SUCCEEDED(CFG_GetConfigInfoBlk8(sizeof(BlPwmData), 0x50002, &s_blPwmData)); - cfguExit(); - } -} - -u32 getMinLuminancePreset(void) -{ - readCalibration(); - return s_blPwmData.luminanceLevels[0]; -} - -u32 getMaxLuminancePreset(void) -{ - readCalibration(); - return s_blPwmData.luminanceLevels[s_blPwmData.numLevels - 1]; -} - -u32 getCurrentLuminance(bool top) -{ - u32 regbase = top ? 0x10202200 : 0x10202A00; - - readCalibration(); - - const float *coeffs = s_blPwmData.coeffs[top ? (is_n3ds ? 2 : 1) : 0]; - u32 brightness = REG32(regbase + 0x40); - float ratio = getPwmRatio(s_blPwmData.brightnessMax, REG32(regbase + 0x44)); - - return brightnessToLuminance(brightness, coeffs, ratio); -} diff --git a/firmware/target/hosted/ctru/luminance-ctru.h b/firmware/target/hosted/ctru/luminance-ctru.h deleted file mode 100644 index 148935b790..0000000000 --- a/firmware/target/hosted/ctru/luminance-ctru.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2016-2020 Aurora Wright, TuxSH -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Additional Terms 7.b and 7.c of GPLv3 apply to this file: -* * Requiring preservation of specified reasonable legal notices or -* author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -* * Prohibiting misrepresentation of the origin of that material, -* or requiring that modified versions of such material be marked in -* reasonable ways as different from the original version. -*/ - -#ifndef _LUMINANCE_CTRU_H_ -#define _LUMINANCE_CTRU_H_ - -#include <3ds/types.h> - -extern u32 ctru_min_lum; -extern u32 ctru_max_lum; -extern u32 ctru_luminance; - -u32 getMinLuminancePreset(void); -u32 getMaxLuminancePreset(void); -u32 getCurrentLuminance(bool top); - -#endif /* _LUMINANCE_CTRU_H_ */ diff --git a/firmware/target/hosted/ctru/pcm-ctru.c b/firmware/target/hosted/ctru/pcm-ctru.c deleted file mode 100644 index d7c9d36458..0000000000 --- a/firmware/target/hosted/ctru/pcm-ctru.c +++ /dev/null @@ -1,359 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2005 by Nick Lanham - * Copyright (C) 2010 by Thomas Martitz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -#include "autoconf.h" - -#include -#include -#include -#include "config.h" -#include "debug.h" -#include "sound.h" -#include "audiohw.h" -#include "system.h" -#include "panic.h" - -#ifdef HAVE_RECORDING -#include "audiohw.h" -#ifdef HAVE_SPDIF_IN -#include "spdif.h" -#endif -#endif - -#include "pcm.h" -#include "pcm-internal.h" -#include "pcm_sampr.h" -#include "pcm_mixer.h" - -#include <3ds/ndsp/ndsp.h> -#include <3ds/ndsp/channel.h> -#include <3ds/services/dsp.h> -#include <3ds/synchronization.h> -#include <3ds/allocator/linear.h> - -/*#define LOGF_ENABLE*/ -#include "logf.h" - -#ifdef DEBUG -extern bool debug_audio; -#endif - -extern const char *audiodev; - -/* Bytes left in the Rockbox PCM frame buffer. */ -static size_t _pcm_buffer_size = 0; - - -/* Rockbox PCM frame buffer. */ -static const void *_pcm_buffer = NULL; - -/* - 1: PCM thread suspended. - 0: PCM thread running. - These are used by pcm_play_[lock|unlock] or pcm_play_dma_[start|stop|pause]. These need to be - separated because of nested calls for suspending and stopping. -*/ -static volatile int _dsp_enabled = 1; -static volatile int _pcm_shutdown = 0; - - -/* Mutex for PCM thread suspend/unsuspend. */ -static RecursiveLock _pcm_lock_mtx; /* audio device mutex */ -static LightEvent _dsp_callback_event; /* dsp callback synchronization flag */ - -static Thread _pcm_thread; -static int _pcm_thread_id = -1; - -/* DSP wave buffers */ -static ndspWaveBuf _dsp_wave_bufs[3]; -static s16 *_dsp_audio_buffer = NULL; - -static inline bool is_in_audio_thread(int audio_thread_id) -{ - /* The device thread locks the same mutex, but not through the public API. - This check is in case the application, in the audio callback, - tries to lock the thread that we've already locked from the - device thread...just in case we only have non-recursive mutexes. */ - if ( (sys_thread_id() == audio_thread_id)) { - return true; - } - - return false; -} - -void pcm_play_lock(void) -{ - if (!is_in_audio_thread(_pcm_thread_id)) { - RecursiveLock_Lock(&_pcm_lock_mtx); - } -} - -void pcm_play_unlock(void) -{ - if (!is_in_audio_thread(_pcm_thread_id)) { - RecursiveLock_Unlock(&_pcm_lock_mtx); - } -} - -static void pcm_write_to_soundcard(const void *pcm_buffer, size_t pcm_buffer_size, ndspWaveBuf *dsp_buffer) -{ - s16 *buffer = dsp_buffer->data_pcm16; - memcpy(buffer, pcm_buffer, pcm_buffer_size); - - dsp_buffer->nsamples = pcm_buffer_size / 2 / sizeof(s16); - ndspChnWaveBufAdd(0, dsp_buffer); - DSP_FlushDataCache(buffer, pcm_buffer_size); -} - -bool fill_buffer(ndspWaveBuf *dsp_buffer) -{ - if(_pcm_buffer_size == 0) - { - /* Retrive a new PCM buffer from Rockbox. */ - if(!pcm_play_dma_complete_callback(PCM_DMAST_OK, &_pcm_buffer, &_pcm_buffer_size)) - { - /* DEBUGF("DEBUG %s: No new buffer.\n", __func__); */ - svcSleepThread(10000); - return false; - } - } - pcm_play_dma_status_callback(PCM_DMAST_STARTED); - - /* This relies on Rockbox PCM frame buffer size == ALSA PCM frame buffer size. */ - pcm_write_to_soundcard(_pcm_buffer, _pcm_buffer_size, dsp_buffer); - _pcm_buffer_size = 0; - - return true; -} - -void pcm_thread_run(void* nothing) -{ - (void) nothing; - - DEBUGF("DEBUG %s: Thread start.\n", __func__); - - _pcm_thread_id = sys_thread_id(); - - while(!AtomicGet(&_pcm_shutdown)) - { - RecursiveLock_Lock(&_pcm_lock_mtx); - for(size_t i = 0; i < ARRAY_SIZE(_dsp_wave_bufs); ++i) { - if(_dsp_wave_bufs[i].status != NDSP_WBUF_DONE) { - continue; - } - - if(!fill_buffer(&_dsp_wave_bufs[i])) { - continue; - } - } - RecursiveLock_Unlock(&_pcm_lock_mtx); - - // Wait for a signal that we're needed again before continuing, - // so that we can yield to other things that want to run - // (Note that the 3DS uses cooperative threading) - LightEvent_Wait(&_dsp_callback_event); - } - - DEBUGF("DEBUG %s: Thread end.\n", __func__); -} - -void dsp_callback(void *const nul_) { - (void)nul_; - - if(AtomicGet(&_pcm_shutdown)) { - return; - } - - LightEvent_Signal(&_dsp_callback_event); -} - -static void pcm_dma_apply_settings_nolock(void) -{ - ndspChnReset(0); - - ndspSetOutputMode(NDSP_OUTPUT_STEREO); - - ndspChnSetRate(0, pcm_sampr); - ndspChnSetFormat(0, NDSP_FORMAT_STEREO_PCM16); - /* ndspChnSetInterp(0, NDSP_INTERP_POLYPHASE); */ - /* ndspChnSetInterp(0, NDSP_INTERP_NONE); */ - ndspChnSetInterp(0, NDSP_INTERP_LINEAR); - - float mix[12]; - memset(mix, 0, sizeof(mix)); - mix[0] = 1.0; - mix[1] = 1.0; - ndspChnSetMix(0, mix); - - memset(_dsp_wave_bufs, 0, sizeof(_dsp_wave_bufs) * ARRAY_SIZE(_dsp_wave_bufs)); - - const size_t wave_buffer_size = MIX_FRAME_SAMPLES * 2 * sizeof(s16); - size_t buffer_size = wave_buffer_size * ARRAY_SIZE(_dsp_wave_bufs); - - _dsp_audio_buffer = (s16 *)linearAlloc(buffer_size); - - s16 *buffer = _dsp_audio_buffer; - for (unsigned i = 0; i < ARRAY_SIZE(_dsp_wave_bufs); i++) { - _dsp_wave_bufs[i].data_vaddr = buffer; - _dsp_wave_bufs[i].status = NDSP_WBUF_DONE; - - buffer += wave_buffer_size / sizeof(buffer[0]); - } - - ndspChnSetPaused(0, true); - ndspSetCallback(dsp_callback, NULL); - - AtomicSet(&_pcm_shutdown, 0); - AtomicSet(&_dsp_enabled, 1); - - // Start the thread, passing our opusFile as an argument. - _pcm_thread = threadCreate(pcm_thread_run, - NULL, - 32 * 1024, /* 32kB stack size */ - 0x18, /* high priority */ - -1, /* run on any core */ false); -} - -void pcm_play_dma_start(const void *addr, size_t size) -{ - _pcm_buffer = addr; - _pcm_buffer_size = size; - - RecursiveLock_Lock(&_pcm_lock_mtx); - ndspChnSetPaused(0, false); - RecursiveLock_Unlock(&_pcm_lock_mtx); -} - -void pcm_play_dma_stop(void) -{ - RecursiveLock_Lock(&_pcm_lock_mtx); - ndspChnSetPaused(0, true); - RecursiveLock_Unlock(&_pcm_lock_mtx); -} - -/* TODO: implement recording */ -#ifdef HAVE_RECORDING -void pcm_rec_lock(void) -{ -} - -void pcm_rec_unlock(void) -{ -} - -void pcm_rec_dma_init(void) -{ -} - -void pcm_rec_dma_close(void) -{ -} - -void pcm_rec_dma_start(void *start, size_t size) -{ - (void)start; - (void)size; - - -} - -void pcm_rec_dma_stop(void) -{ -} - -const void * pcm_rec_dma_get_peak_buffer(void) -{ - return NULL; -} - -void audiohw_set_recvol(int left, int right, int type) -{ - (void)left; - (void)right; - (void)type; -} - -#ifdef HAVE_SPDIF_IN -unsigned long spdif_measure_frequency(void) -{ - return 0; -} -#endif - -#endif /* HAVE_RECORDING */ - -void pcm_play_dma_init(void) -{ - Result ndsp_init_res = ndspInit(); - if (R_FAILED(ndsp_init_res)) { - if ((R_SUMMARY(ndsp_init_res) == RS_NOTFOUND) && (R_MODULE(ndsp_init_res) == RM_DSP)) { - logf("DSP init failed: dspfirm.cdc missing!"); - } else { - logf("DSP init failed. Error code: 0x%lX", ndsp_init_res); - } - return; - } - - RecursiveLock_Init(&_pcm_lock_mtx); - LightEvent_Init(&_dsp_callback_event, RESET_ONESHOT); -} - -void pcm_play_dma_postinit(void) -{ -} - -void pcm_dma_apply_settings(void) -{ - pcm_play_lock(); - pcm_dma_apply_settings_nolock(); - pcm_play_unlock(); -} - -void pcm_close_device(void) -{ - RecursiveLock_Lock(&_pcm_lock_mtx); - AtomicSet(&_pcm_shutdown, 1); - LightEvent_Signal(&_dsp_callback_event); - - threadJoin(_pcm_thread, UINT64_MAX); - threadFree(_pcm_thread); - _pcm_thread_id = -1; - RecursiveLock_Unlock(&_pcm_lock_mtx); - - ndspSetCallback(NULL, NULL); - - ndspChnReset(0); - if (_dsp_audio_buffer != NULL) { - linearFree(_dsp_audio_buffer); - _dsp_audio_buffer = NULL; - } - - ndspExit(); -} - -/* moved from drivers/audio/ctru.c */ -void audiohw_close(void) -{ - pcm_close_device(); -} diff --git a/firmware/target/hosted/ctru/powermgmt-ctru.c b/firmware/target/hosted/ctru/powermgmt-ctru.c deleted file mode 100644 index 063abf7a7b..0000000000 --- a/firmware/target/hosted/ctru/powermgmt-ctru.c +++ /dev/null @@ -1,107 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include - -#include "config.h" -#include "kernel.h" -#include "powermgmt.h" -#include "power.h" -#include "adc.h" -#include "system.h" -#include "debug.h" - -#include <3ds/types.h> -#include <3ds/result.h> -#include <3ds/services/mcuhwc.h> -#include <3ds/services/ptmu.h> - -void mcuhwc_init(void) -{ - Result result = mcuHwcInit(); - if (R_FAILED(result)) { - DEBUGF("mcuhwc_init: warning, mcuHwcInit failed\n"); - } - - result = ptmuInit(); - if (R_FAILED(result)) { - DEBUGF("mcuhwc_init: warning, ptmuInit failed\n"); - } -} - -void mcuhwc_close(void) -{ - mcuHwcExit(); - ptmuExit(); -} - -/* FIXME: what level should disksafe be?*/ -unsigned short battery_level_disksafe = 0; - -unsigned short battery_level_shutoff = 0; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -unsigned short percent_to_volt_discharge[11] = -{ -}; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ -unsigned short percent_to_volt_charge[11] = -{ - 3450, 3670, 3721, 3751, 3782, 3821, 3876, 3941, 4034, 4125, 4200 -}; - -enum -{ - BATT_NOT_CHARGING = 0, - BATT_CHARGING, -}; - -static u8 charging_status = BATT_NOT_CHARGING; - -unsigned int power_input_status(void) -{ - unsigned status = POWER_INPUT_NONE; - PTMU_GetBatteryChargeState(&charging_status); - if (charging_status == BATT_CHARGING) - status = POWER_INPUT_MAIN_CHARGER; - return status; -} - -/* Returns battery voltage from MAX17040 VCELL ADC [millivolts steps], - * adc returns voltage in 1.25mV steps */ -/* - * TODO this would be interesting to be mixed with battery percentage, for information - * and completition purpouses - */ -int _battery_level(void) -{ - u8 level = 100; - MCUHWC_GetBatteryLevel(&level); - return level; -} - -bool charging_state(void) -{ - return (charging_status == BATT_CHARGING); -} - diff --git a/firmware/target/hosted/ctru/system-ctru.c b/firmware/target/hosted/ctru/system-ctru.c deleted file mode 100644 index a091e889c6..0000000000 --- a/firmware/target/hosted/ctru/system-ctru.c +++ /dev/null @@ -1,145 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Daniel Everton - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include "system.h" -#include "kernel.h" -#include "thread-ctru.h" -#include "system-ctru.h" -#include "button-ctru.h" -#include "lcd-bitmap.h" -#include "panic.h" -#include "debug.h" - -#include <3ds/types.h> -#include <3ds/allocator/linear.h> -#include <3ds/services/cfgu.h> -#include "bfile.h" - -const char *audiodev = NULL; - -#ifdef DEBUG -bool debug_audio = false; -#endif - -/* default main thread priority, low */ -s32 main_thread_priority = 0x30; -bool is_n3ds = false; - -/* filesystem */ -sync_RWMutex file_internal_mrsw; -FS_Archive sdmcArchive; - -void ctru_sys_quit(void) -{ - sys_poweroff(); -} - -void power_off(void) -{ - /* since sim_thread_shutdown() grabs the mutex we need to let it free, - * otherwise sys_wait_thread will deadlock */ - struct thread_entry* t = sim_thread_unlock(); - sim_thread_shutdown(); - - /* lock again before entering the scheduler */ - sim_thread_lock(t); - /* sim_thread_shutdown() will cause sim_do_exit() to be called via longjmp, - * but only if we let the sdl thread scheduler exit the other threads */ - while(1) yield(); -} - -void sim_do_exit() -{ - sim_kernel_shutdown(); - sys_timer_quit(); - /* TODO: quit_everything() */ - exit(EXIT_SUCCESS); -} - -uintptr_t *stackbegin; -uintptr_t *stackend; -void system_init(void) -{ - /* fake stack, OS manages size (and growth) */ - volatile uintptr_t stack = 0; - stackbegin = stackend = (uintptr_t*) &stack; - - /* disable sleep mode when lid is closed */ - aptSetSleepAllowed(false); - - sys_console_init(); - sys_timer_init(); - - svcGetThreadPriority(&main_thread_priority, CUR_THREAD_HANDLE); - if (main_thread_priority != 0x30) { - DEBUGF("warning, main_thread_priority = 0x%x\n", main_thread_priority); - } - - /* check for New 3DS model */ - s64 dummyInfo; - is_n3ds = svcGetSystemInfo(&dummyInfo, 0x10001, 0) == 0; - - /* filesystem */ - sync_RWMutexInit(&file_internal_mrsw); - Result res = FSUSER_OpenArchive(&sdmcArchive, - ARCHIVE_SDMC, - fsMakePath(PATH_ASCII, "")); - if (R_FAILED(res)) { - DEBUGF("FSUSER_OpenArchive failed\n"); - exit(-1); - } - - mcuhwc_init(); - cfguInit(); -} - - -void system_reboot(void) -{ - sim_thread_exception_wait(); -} - -void system_exception_wait(void) -{ - system_reboot(); -} - -int hostfs_init(void) -{ - /* stub */ - /* romfsInit(); */ - return 0; -} - -#ifdef HAVE_STORAGE_FLUSH -int hostfs_flush(void) -{ -#ifdef __unix__ - sync(); -#endif - return 0; -} -#endif /* HAVE_STORAGE_FLUSH */ - diff --git a/firmware/target/hosted/ctru/system-ctru.h b/firmware/target/hosted/ctru/system-ctru.h deleted file mode 100644 index 23c63a3c0c..0000000000 --- a/firmware/target/hosted/ctru/system-ctru.h +++ /dev/null @@ -1,70 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 by Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _SYSTEM_SDL_H_ -#define _SYSTEM_SDL_H_ - -#include -#include -#include "config.h" -#include "gcc_extensions.h" - -#include <3ds/types.h> -#include <3ds/svc.h> -#include "sys_timer.h" - -#define HIGHEST_IRQ_LEVEL 1 - -int set_irq_level(int level); - -#define disable_irq() \ - ((void)set_irq_level(HIGHEST_IRQ_LEVEL)) - -#define enable_irq() \ - ((void)set_irq_level(0)) - -#define disable_irq_save() \ - set_irq_level(HIGHEST_IRQ_LEVEL) - -#define restore_irq(level) \ - ((void)set_irq_level(level)) - -#define wait_for_interrupt() - -#include "system-hosted.h" - -void sim_enter_irq_handler(void); -void sim_exit_irq_handler(void); -void sim_kernel_shutdown(void); -void sys_poweroff(void); -void sys_handle_argv(int argc, char *argv[]); -void gui_message_loop(void); -void sim_do_exit(void) NORETURN_ATTR; -void sdl_sys_quit(void); - -void mcuhwc_init(void); -void mcuhwc_close(void); - -extern bool background; /* True if the background image is enabled */ -extern bool showremote; -extern double display_zoom; -extern long start_tick; - -#endif /* _SYSTEM_SDL_H_ */ diff --git a/firmware/target/hosted/ctru/system-target.h b/firmware/target/hosted/ctru/system-target.h deleted file mode 100644 index 79df842405..0000000000 --- a/firmware/target/hosted/ctru/system-target.h +++ /dev/null @@ -1,4 +0,0 @@ -#include "system-ctru.h" - -#define NEED_GENERIC_BYTESWAPS - diff --git a/firmware/target/hosted/ctru/thread-ctru.c b/firmware/target/hosted/ctru/thread-ctru.c deleted file mode 100644 index 675cb314be..0000000000 --- a/firmware/target/hosted/ctru/thread-ctru.c +++ /dev/null @@ -1,503 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 Dan Everton - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "autoconf.h" - -#include -#include -#include -#include /* memset() */ -#include -#include "system-ctru.h" -#include "thread-ctru.h" -#include "sys_thread.h" -#include "../kernel-internal.h" -#include "core_alloc.h" - -/* Define this as 1 to show informational messages that are not errors. */ -#define THREAD_DEBUGF_ENABLED 0 - -#if THREAD_DEBUGF_ENABLED -#define THREAD_DEBUGF(...) DEBUGF(__VA_ARGS__) -static char __name[sizeof (((struct thread_debug_info *)0)->name)]; -#define THREAD_GET_NAME(thread) \ - ({ format_thread_name(__name, sizeof (__name), thread); __name; }) -#else -#define THREAD_DEBUGF(...) -#define THREAD_GET_NAME(thread) -#endif - -#define THREAD_PANICF(str...) \ - ({ fprintf(stderr, str); exit(-1); }) - -/* Jump buffers for graceful exit - kernel threads don't stay neatly - * in their start routines responding to messages so this is the only - * way to get them back in there so they may exit */ -static jmp_buf thread_jmpbufs[MAXTHREADS]; -/* this mutex locks out other Rockbox threads while one runs, - * that enables us to simulate a cooperative environment even if - * the host is preemptive */ -static RecursiveLock m; -#define THREADS_RUN 0 -#define THREADS_EXIT 1 -#define THREADS_EXIT_COMMAND_DONE 2 -static volatile int threads_status = THREADS_RUN; - -extern long start_tick; - -void sim_thread_shutdown(void) -{ - int i; - - /* This *has* to be a push operation from a thread not in the pool - so that they may be dislodged from their blocking calls. */ - - /* Tell all threads jump back to their start routines, unlock and exit - gracefully - we'll check each one in turn for it's status. Threads - _could_ terminate via thread_exit or multiple threads could exit - on each unlock but that is safe. */ - - /* Do this before trying to acquire lock */ - threads_status = THREADS_EXIT; - - /* Take control */ - RecursiveLock_Lock(&m); - - /* Signal all threads on delay or block */ - for (i = 0; i < MAXTHREADS; i++) - { - struct thread_entry *thread = __thread_slot_entry(i); - if (thread->context.s == NULL) - continue; - LightSemaphore_Release(thread->context.s, 1); - } - - /* Wait for all threads to finish and cleanup old ones. */ - for (i = 0; i < MAXTHREADS; i++) - { - struct thread_entry *thread = __thread_slot_entry(i); - sysThread *t = thread->context.t; - - if (t != NULL) - { - RecursiveLock_Unlock(&m); - /* Wait for it to finish */ - sys_wait_thread(t, NULL); - /* Relock for next thread signal */ - RecursiveLock_Lock(&m); - /* Already waited and exiting thread would have waited .told, - * replacing it with t. */ - thread->context.told = NULL; - } - else - { - /* Wait on any previous thread in this location-- could be one not - * quite finished exiting but has just unlocked the mutex. If it's - * NULL, the call returns immediately. - * - * See thread_exit below for more information. */ - sys_wait_thread(thread->context.told, NULL); - } - } - - RecursiveLock_Unlock(&m); - - /* Signal completion of operation */ - threads_status = THREADS_EXIT_COMMAND_DONE; -} - -void sim_thread_exception_wait(void) -{ - while (1) - { - sys_delay(HZ/10); - if (threads_status != THREADS_RUN) - thread_exit(); - } -} - -/* A way to yield and leave the threading system for extended periods */ -void sim_thread_lock(void *me) -{ - RecursiveLock_Lock(&m); - __running_self_entry() = (struct thread_entry *)me; - - if (threads_status != THREADS_RUN) - thread_exit(); -} - -void * sim_thread_unlock(void) -{ - struct thread_entry *current = __running_self_entry(); - RecursiveLock_Unlock(&m); - return current; -} - -void switch_thread(void) -{ - struct thread_entry *current = __running_self_entry(); - - enable_irq(); - - switch (current->state) - { - case STATE_RUNNING: - { - RecursiveLock_Unlock(&m); - /* Any other thread waiting already will get it first */ - RecursiveLock_Lock(&m); - break; - } /* STATE_RUNNING: */ - - case STATE_BLOCKED: - { - int oldlevel; - - RecursiveLock_Unlock(&m); - sys_sem_wait(current->context.s); - RecursiveLock_Lock(&m); - - oldlevel = disable_irq_save(); - current->state = STATE_RUNNING; - restore_irq(oldlevel); - break; - } /* STATE_BLOCKED: */ - - case STATE_BLOCKED_W_TMO: - { - int result, oldlevel; - - RecursiveLock_Unlock(&m); - result = sys_sem_wait_timeout(current->context.s, current->tmo_tick); - RecursiveLock_Lock(&m); - - oldlevel = disable_irq_save(); - - current->state = STATE_RUNNING; - - if (result == 1) - { - /* Other signals from an explicit wake could have been made before - * arriving here if we timed out waiting for the semaphore. Make - * sure the count is reset. */ - while (sys_sem_value(current->context.s) > 0) - sys_sem_try_wait(current->context.s); - } - - restore_irq(oldlevel); - break; - } /* STATE_BLOCKED_W_TMO: */ - - case STATE_SLEEPING: - { - RecursiveLock_Unlock(&m); - sys_sem_wait_timeout(current->context.s, current->tmo_tick); - RecursiveLock_Lock(&m); - current->state = STATE_RUNNING; - break; - } /* STATE_SLEEPING: */ - } - -#ifdef BUFLIB_DEBUG_CHECK_VALID - core_check_valid(); -#endif - __running_self_entry() = current; - - if (threads_status != THREADS_RUN) - thread_exit(); -} - -void sleep_thread(int ticks) -{ - struct thread_entry *current = __running_self_entry(); - int rem; - - current->state = STATE_SLEEPING; - - rem = (sys_get_ticks() - start_tick) % (1000/HZ); - if (rem < 0) - rem = 0; - - current->tmo_tick = (1000/HZ) * ticks + ((1000/HZ)-1) - rem; -} - -void block_thread_(struct thread_entry *current, int ticks) -{ - if (ticks < 0) - current->state = STATE_BLOCKED; - else - { - current->state = STATE_BLOCKED_W_TMO; - current->tmo_tick = (1000/HZ)*ticks; - } - - wait_queue_register(current); -} - -unsigned int wakeup_thread_(struct thread_entry *thread - IF_PRIO(, enum wakeup_thread_protocol proto)) -{ - switch (thread->state) - { - case STATE_BLOCKED: - case STATE_BLOCKED_W_TMO: - wait_queue_remove(thread); - thread->state = STATE_RUNNING; - LightSemaphore_Release(thread->context.s, 1); - return THREAD_OK; - } - - return THREAD_NONE; - (void) proto; -} - -void thread_thaw(unsigned int thread_id) -{ - struct thread_entry *thread = __thread_id_entry(thread_id); - - if (thread->id == thread_id && thread->state == STATE_FROZEN) - { - thread->state = STATE_RUNNING; - LightSemaphore_Release(thread->context.s, 1); - } -} - -int runthread(void *data) -{ - /* Cannot access thread variables before locking the mutex as the - data structures may not be filled-in yet. */ - RecursiveLock_Lock(&m); - - struct thread_entry *current = (struct thread_entry *)data; - __running_self_entry() = current; - - jmp_buf *current_jmpbuf = &thread_jmpbufs[THREAD_ID_SLOT(current->id)]; - - /* Setup jump for exit */ - if (setjmp(*current_jmpbuf) == 0) - { - /* Run the thread routine */ - if (current->state == STATE_FROZEN) - { - RecursiveLock_Unlock(&m); - sys_sem_wait(current->context.s); - RecursiveLock_Lock(&m); - __running_self_entry() = current; - } - - if (threads_status == THREADS_RUN) - { - current->context.start(); - THREAD_DEBUGF("Thread Done: %d (%s)\n", - THREAD_ID_SLOT(current->id), - THREAD_GET_NAME(current)); - /* Thread routine returned - suicide */ - } - - thread_exit(); - } - else - { - /* Unlock and exit */ - RecursiveLock_Unlock(&m); - } - - return 0; -} - -unsigned int create_thread(void (*function)(void), - void* stack, size_t stack_size, - unsigned flags, const char *name - IF_PRIO(, int priority) - IF_COP(, unsigned int core)) -{ - THREAD_DEBUGF("Creating thread: (%s)\n", name ? name : ""); - - struct thread_entry *thread = thread_alloc(); - if (thread == NULL) - { - DEBUGF("Failed to find thread slot\n"); - return 0; - } - - LightSemaphore *s = (LightSemaphore *) malloc(sizeof(LightSemaphore)); - if (s == NULL) - { - DEBUGF("Failed to create semaphore\n"); - return 0; - } - - LightSemaphore_Init(s, 0, 255); - - sysThread *t = sys_create_thread(runthread, - name, - stack_size, - thread - IF_PRIO(, priority) - IF_COP(, core)); - if (t == NULL) - { - DEBUGF("Failed to create thread\n"); - free(s); - return 0; - } - - thread->name = name; - thread->state = (flags & CREATE_THREAD_FROZEN) ? - STATE_FROZEN : STATE_RUNNING; - thread->context.start = function; - thread->context.t = t; - thread->context.s = s; - thread->priority = priority; - - THREAD_DEBUGF("New Thread: %lu (%s)\n", - (unsigned long)thread->id, - THREAD_GET_NAME(thread)); - - return thread->id; - (void)stack; -} - -void thread_exit(void) -{ - struct thread_entry *current = __running_self_entry(); - - int oldlevel = disable_irq_save(); - - sysThread *t = current->context.t; - LightSemaphore *s = current->context.s; - - /* Wait the last thread here and keep this one or ctru will leak it since - * it doesn't free its own library allocations unless a wait is performed. - * Such behavior guards against the memory being invalid by the time - * sys_wait_thread is reached and also against two different threads having - * the same pointer. It also makes sys_wait_thread a non-concurrent function. - * - * However, see more below about sys_kill_thread. - */ - sys_wait_thread(current->context.told, NULL); - - current->context.t = NULL; - current->context.s = NULL; - current->context.told = t; - - unsigned int id = current->id; - new_thread_id(current); - current->state = STATE_KILLED; - wait_queue_wake(¤t->queue); - - free(s); - - /* Do a graceful exit - perform the longjmp back into the thread - function to return */ - restore_irq(oldlevel); - - thread_free(current); - - longjmp(thread_jmpbufs[THREAD_ID_SLOT(id)], 1); - - /* This should never and must never be reached - if it is, the - * state is corrupted */ - THREAD_PANICF("thread_exit->K:*R (ID: %d)", id); - while (1); -} - -void thread_wait(unsigned int thread_id) -{ - struct thread_entry *current = __running_self_entry(); - struct thread_entry *thread = __thread_id_entry(thread_id); - - if (thread->id == thread_id && thread->state != STATE_KILLED) - { - block_thread(current, TIMEOUT_BLOCK, &thread->queue, NULL); - switch_thread(); - } -} - -int thread_set_priority(unsigned int thread_id, int priority) -{ - struct thread_entry *thread = __thread_id_entry(thread_id); - sysThread *t = thread->context.t; - thread->priority = sys_set_thread_priority(t, priority); - return thread->priority; -} - -int thread_get_priority(unsigned int thread_id) -{ - struct thread_entry *thread = __thread_id_entry(thread_id); - return thread->priority; -} - -/* Initialize threading */ -void init_threads(void) -{ - RecursiveLock_Init(&m); - RecursiveLock_Lock(&m); - - thread_alloc_init(); - - struct thread_entry *thread = thread_alloc(); - if (thread == NULL) - { - fprintf(stderr, "Main thread alloc failed\n"); - return; - } - - /* Slot 0 is reserved for the main thread - initialize it here and - then create the thread - it is possible to have a quick, early - shutdown try to access the structure. */ - thread->name = __main_thread_name; - thread->state = STATE_RUNNING; - thread->context.s = (LightSemaphore *) malloc(sizeof(LightSemaphore)); - LightSemaphore_Init(thread->context.s, 0, 255); - thread->context.t = NULL; /* NULL for the implicit main thread */ - __running_self_entry() = thread; - - if (thread->context.s == NULL) - { - fprintf(stderr, "Failed to create main semaphore\n"); - return; - } - - /* Tell all threads jump back to their start routines, unlock and exit - gracefully - we'll check each one in turn for it's status. Threads - _could_ terminate via thread_exit or multiple threads could exit - on each unlock but that is safe. */ - - /* Setup jump for exit */ - if (setjmp(thread_jmpbufs[THREAD_ID_SLOT(thread->id)]) == 0) - { - THREAD_DEBUGF("Main Thread: %lu (%s)\n", - (unsigned long)thread->id, - THREAD_GET_NAME(thread)); - return; - } - - RecursiveLock_Unlock(&m); - - /* Set to 'COMMAND_DONE' when other rockbox threads have exited. */ - while (threads_status < THREADS_EXIT_COMMAND_DONE) - sys_delay(10); - - /* We're the main thead - perform exit - doesn't return. */ - sim_do_exit(); -} - diff --git a/firmware/target/hosted/ctru/thread-ctru.h b/firmware/target/hosted/ctru/thread-ctru.h deleted file mode 100644 index 89e2d121cb..0000000000 --- a/firmware/target/hosted/ctru/thread-ctru.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2025 Mauricio G. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __THREAD_CTRU_H__ -#define __THREAD_CTRU_H__ - -/* extra thread functions that only apply when running on hosting platforms */ -void sim_thread_lock(void *me); -void * sim_thread_unlock(void); -void sim_thread_exception_wait(void); -void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */ - -#endif /* #ifndef __THREAD_CTRU_H__ */ - diff --git a/firmware/target/hosted/ctru/timer-ctru.c b/firmware/target/hosted/ctru/timer-ctru.c deleted file mode 100644 index 4c608b667b..0000000000 --- a/firmware/target/hosted/ctru/timer-ctru.c +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Copyright (C) 2025 Mauricio G. -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#include "sys_timer.h" -#include "timer.h" - -static int timer_prio = -1; -void (*global_timer_callback)(void); -int timerId; - -u32 _timer_callback(u32 interval, void *param){ - (void)param; - global_timer_callback(); - return(interval); -} - -#define cycles_to_miliseconds(cycles) \ - ((int)((1000*cycles)/TIMER_FREQ)) - -bool timer_register(int reg_prio, void (*unregister_callback)(void), - long cycles, void (*timer_callback)(void)) -{ - (void)unregister_callback; - if (reg_prio <= timer_prio || cycles == 0) - return false; - timer_prio=reg_prio; - global_timer_callback=timer_callback; - timerId=sys_add_timer(cycles_to_miliseconds(cycles), _timer_callback, 0); - return true; -} - -bool timer_set_period(long cycles) -{ - sys_remove_timer(timerId); - timerId=sys_add_timer(cycles_to_miliseconds(cycles), _timer_callback, 0); - return true; -} - -void timer_unregister(void) -{ - sys_remove_timer(timerId); - timer_prio = -1; -} diff --git a/firmware/target/hosted/ctru/timer-ctru_sys.c b/firmware/target/hosted/ctru/timer-ctru_sys.c deleted file mode 100644 index 4c608b667b..0000000000 --- a/firmware/target/hosted/ctru/timer-ctru_sys.c +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Copyright (C) 2025 Mauricio G. -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#include "sys_timer.h" -#include "timer.h" - -static int timer_prio = -1; -void (*global_timer_callback)(void); -int timerId; - -u32 _timer_callback(u32 interval, void *param){ - (void)param; - global_timer_callback(); - return(interval); -} - -#define cycles_to_miliseconds(cycles) \ - ((int)((1000*cycles)/TIMER_FREQ)) - -bool timer_register(int reg_prio, void (*unregister_callback)(void), - long cycles, void (*timer_callback)(void)) -{ - (void)unregister_callback; - if (reg_prio <= timer_prio || cycles == 0) - return false; - timer_prio=reg_prio; - global_timer_callback=timer_callback; - timerId=sys_add_timer(cycles_to_miliseconds(cycles), _timer_callback, 0); - return true; -} - -bool timer_set_period(long cycles) -{ - sys_remove_timer(timerId); - timerId=sys_add_timer(cycles_to_miliseconds(cycles), _timer_callback, 0); - return true; -} - -void timer_unregister(void) -{ - sys_remove_timer(timerId); - timer_prio = -1; -} diff --git a/firmware/target/hosted/filesystem-app.h b/firmware/target/hosted/filesystem-app.h index 6233524bb4..2d907b98fa 100644 --- a/firmware/target/hosted/filesystem-app.h +++ b/firmware/target/hosted/filesystem-app.h @@ -58,11 +58,7 @@ const char * handle_special_dirs(const char *dir, unsigned flags, #ifdef WIN32 #include "filesystem-win32.h" #else /* !WIN32 */ -#if defined(CTRU) && !defined(SIMULATOR) -#include "filesystem-ctru.h" -#else #include "filesystem-unix.h" -#endif #endif /* WIN32 */ #include "filesystem-hosted.h" diff --git a/firmware/target/hosted/rtc.c b/firmware/target/hosted/rtc.c index 82266d8e40..b41862f977 100644 --- a/firmware/target/hosted/rtc.c +++ b/firmware/target/hosted/rtc.c @@ -24,7 +24,7 @@ #include #if !defined(WIN32) #include -#if !defined(__APPLE__) && !defined(CTRU) +#if !defined(__APPLE__) #include #endif #include @@ -49,7 +49,7 @@ int rtc_read_datetime(struct tm *tm) int rtc_write_datetime(const struct tm *tm) { -#if !defined(WIN32) && !defined(__APPLE__) && !defined(CTRU) +#if !defined(WIN32) && !defined(__APPLE__) struct timeval tv; struct tm *tm_time; diff --git a/lib/rbcodec/codecs/codec_crt0.c b/lib/rbcodec/codecs/codec_crt0.c index 4a4dd8ee82..0f9749ddb8 100644 --- a/lib/rbcodec/codecs/codec_crt0.c +++ b/lib/rbcodec/codecs/codec_crt0.c @@ -31,12 +31,6 @@ extern unsigned char plugin_end_addr[]; * avoid warning with certain compilers */ int _start(void) {return 0;} -#ifdef CTRU -/* dummy undefined symbols */ -void __aeabi_unwind_cpp_pr0(void) {} -struct _reent * _EXFUN(__getreent, (void)) {} -#endif - enum codec_status codec_start(enum codec_entry_call_reason reason) { #if (CONFIG_PLATFORM & PLATFORM_NATIVE) diff --git a/lib/rbcodec/codecs/codecs.make b/lib/rbcodec/codecs/codecs.make index 6d790f5d9a..598bee091c 100644 --- a/lib/rbcodec/codecs/codecs.make +++ b/lib/rbcodec/codecs/codecs.make @@ -137,10 +137,6 @@ ifeq ($(ARCH),arch_arm) $(SGCLIB) : CODECFLAGS += -O1 $(VGMLIB) : CODECFLAGS += -O1 $(WAVPACKLIB) : CODECFLAGS += -O3 - ifneq (,$(findstring ctru, $(MODELNAME))) - # segfault with -O1 - $(SPCLIB) : CODECFLAGS += -O2 - endif else ifeq ($(ARCH),arch_m68k) $(CODECLIB) : CODECFLAGS += -O2 $(A52LIB) : CODECFLAGS += -O2 diff --git a/packaging/ctru/ctru.make b/packaging/ctru/ctru.make deleted file mode 100644 index 288b4ac3bd..0000000000 --- a/packaging/ctru/ctru.make +++ /dev/null @@ -1,101 +0,0 @@ -# __________ __ ___. -# Open \______ \ ____ ____ | | _\_ |__ _______ ___ -# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -# \/ \/ \/ \/ \/ -# $Id$ -# - -# 3ds_rules -export DEVKITARM ?= /opt/devkitpro/devkitARM -export DEVKITPRO ?= /opt/devkitpro - -PORTLIBS := $(DEVKITPRO)/portlibs/3ds - -CTRULIB ?= $(DEVKITPRO)/libctru - -export PATH := $(DEVKITPRO)/portlibs/3ds/bin:$(PATH) - -# base_rules -export SHELL := /usr/bin/env bash - -DEVKITPATH=$(shell echo "$(DEVKITPRO)" | sed -e 's/^\([a-zA-Z]\):/\/\1/') - -export PATH := $(DEVKITPATH)/tools/bin:$(DEVKITPATH)/devkitARM/bin:$(PATH) - -# 3DSX -VERSION_MAJOR := 1 -VERSION_MINOR := 0 -VERSION_MICRO := 0 - -APP_TITLE := rockbox -APP_DESCRIPTION := Open Source Jukebox Firmware -APP_AUTHOR := rockbox.org -APP_ICON := $(ROOTDIR)/packaging/ctru/res/icon.png - -# CIA -BANNER_AUDIO := $(ROOTDIR)/packaging/ctru/res/banner.wav -BANNER_IMAGE := $(ROOTDIR)/packaging/ctru/res/banner.cgfx -RSF_PATH := $(ROOTDIR)/packaging/ctru/res/app.rsf -#LOGO := $(ROOTDIR)/packaging/ctru/logo.lz11 -UNIQUE_ID := 0xCB001 -PRODUCT_CODE := CTR-ROCKBOX -ICON_FLAGS := nosavebackups,visible - -# CIA Configuration -USE_ON_SD := true -APP_ENCRYPTED := false -CATEGORY := Application -USE_ON_SD := true -MEMORY_TYPE := Application -SYSTEM_MODE := 64MB -SYSTEM_MODE_EXT := Legacy -CPU_SPEED := 268MHz -ENABLE_L2_CACHE := false - -.SECONDEXPANSION: # $$(OBJ) is not populated until after this - -MAKEROM ?= makerom -MAKEROM_ARGS := -elf "$(BINARY).elf" -rsf "$(RSF_PATH)" -banner "$(BUILDDIR)/banner.bnr" -icon "$(BUILDDIR)/icon.icn" -DAPP_TITLE="$(APP_TITLE)" -DAPP_PRODUCT_CODE="$(PRODUCT_CODE)" -DAPP_UNIQUE_ID="$(UNIQUE_ID)" -DAPP_ENCRYPTED="$(APP_ENCRYPTED)" -DAPP_SYSTEM_MODE="$(SYSTEM_MODE)" -DAPP_SYSTEM_MODE_EXT="$(SYSTEM_MODE_EXT)" -DAPP_CATEGORY="$(CATEGORY)" -DAPP_USE_ON_SD="$(USE_ON_SD)" -DAPP_MEMORY_TYPE="$(MEMORY_TYPE)" -DAPP_CPU_SPEED="$(CPU_SPEED)" -DAPP_ENABLE_L2_CACHE="$(ENABLE_L2_CACHE)" -MAKEROM_ARGS += -major $(VERSION_MAJOR) -minor $(VERSION_MINOR) -micro $(VERSION_MICRO) - -ifneq ($(strip $(LOGO)),) - MAKEROM_ARGS += -logo "$(LOGO)" -endif -ifneq ($(strip $(ROMFS)),) - MAKEROM_ARGS += -DAPP_ROMFS="$(ROMFS)" -endif - -BANNERTOOL ?= bannertool - -ifeq ($(suffix $(BANNER_IMAGE)),.cgfx) - BANNER_IMAGE_ARG := -ci -else - BANNER_IMAGE_ARG := -i -endif - -ifeq ($(suffix $(BANNER_AUDIO)),.cwav) - BANNER_AUDIO_ARG := -ca -else - BANNER_AUDIO_ARG := -a -endif - -# main binary -$(BUILDDIR)/$(BINARY): $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS) -ifeq ($(UNAME), Darwin) - $(call PRINTS,LD $(BINARY))$(CC) -o $@ $^ $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,$(LDMAP_OPT),$(BUILDDIR)/rockbox.map -else - $(call PRINTS,LD $(BINARY))$(CC) -o $@ -Wl,--start-group $^ -Wl,--end-group $(LDOPTS) $(GLOBAL_LDOPTS) \ - -Wl,$(LDMAP_OPT),$(BUILDDIR)/rockbox-.map - @mv $(BINARY) $(BINARY).elf - smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) "rockbox.smdh" - 3dsxtool $(BINARY).elf $(BINARY).3dsx --smdh="rockbox.smdh" - $(BANNERTOOL) makebanner $(BANNER_IMAGE_ARG) "$(BANNER_IMAGE)" $(BANNER_AUDIO_ARG) "$(BANNER_AUDIO)" -o "$(BUILDDIR)/banner.bnr" - $(BANNERTOOL) makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i "$(APP_ICON)" -f "$(ICON_FLAGS)" -o "$(BUILDDIR)/icon.icn" - $(MAKEROM) -f cia -o "$(BINARY).cia" -target t -exefslogo $(MAKEROM_ARGS) -ifndef DEBUG - $(SILENT)rm $(BINARY).elf -endif -endif - diff --git a/packaging/ctru/res/app.rsf b/packaging/ctru/res/app.rsf deleted file mode 100644 index e89849df48..0000000000 --- a/packaging/ctru/res/app.rsf +++ /dev/null @@ -1,286 +0,0 @@ -BasicInfo: - Title : $(APP_TITLE) - ProductCode : $(APP_PRODUCT_CODE) - Logo : Homebrew - -RomFs: - RootPath: $(APP_ROMFS) - -TitleInfo: - Category : $(APP_CATEGORY) - UniqueId : $(APP_UNIQUE_ID) - -Option: - UseOnSD : $(APP_USE_ON_SD) # true if App is to be installed to SD - FreeProductCode : true # Removes limitations on ProductCode - MediaFootPadding : false # If true CCI files are created with padding - EnableCrypt : $(APP_ENCRYPTED) # Enables encryption for NCCH and CIA - EnableCompress : true # Compresses where applicable (currently only exefs:/.code) - -AccessControlInfo: - CoreVersion : 2 - - # Exheader Format Version - DescVersion : 2 - - # Minimum Required Kernel Version (below is for 4.5.0) - ReleaseKernelMajor : "02" - ReleaseKernelMinor : "33" - - # ExtData - UseExtSaveData : false # enables ExtData - #ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId - - # FS:USER Archive Access Permissions - # Uncomment as required - FileSystemAccess: - - CategorySystemApplication - - CategoryHardwareCheck - - CategoryFileSystemTool - - Debug - - TwlCardBackup - - TwlNandData - - Boss - - DirectSdmc - - Core - - CtrNandRo - - CtrNandRw - - CtrNandRoWrite - - CategorySystemSettings - - CardBoard - - ExportImportIvs - - DirectSdmcWrite - - SwitchCleanup - - SaveDataMove - - Shop - - Shell - - CategoryHomeMenu - - SeedDB - IoAccessControl: - - FsMountNand - - FsMountNandRoWrite - - FsMountTwln - - FsMountWnand - - FsMountCardSpi - - UseSdif3 - - CreateSeed - - UseCardSpi - - # Process Settings - MemoryType : $(APP_MEMORY_TYPE) # Application/System/Base - SystemMode : $(APP_SYSTEM_MODE) # 64MB(Default)/96MB/80MB/72MB/32MB - IdealProcessor : 0 - AffinityMask : 1 - Priority : 16 - MaxCpu : 0x9E # Default - HandleTableSize : 0x200 - DisableDebug : false - EnableForceDebug : false - CanWriteSharedPage : true - CanUsePrivilegedPriority : false - CanUseNonAlphabetAndNumber : true - PermitMainFunctionArgument : true - CanShareDeviceMemory : true - RunnableOnSleep : false - SpecialMemoryArrange : true - - # New3DS Exclusive Process Settings - SystemModeExt : $(APP_SYSTEM_MODE_EXT) # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode - CpuSpeed : $(APP_CPU_SPEED) # 268MHz(Default)/804MHz - EnableL2Cache : $(APP_ENABLE_L2_CACHE) # false(default)/true - CanAccessCore2 : true - - # Virtual Address Mappings - IORegisterMapping: - - 1ff00000-1ff7ffff # DSP memory - MemoryMapping: - - 1f000000-1f5fffff:r # VRAM - - # Accessible SVCs, : - SystemCallAccess: - ControlMemory: 1 - QueryMemory: 2 - ExitProcess: 3 - GetProcessAffinityMask: 4 - SetProcessAffinityMask: 5 - GetProcessIdealProcessor: 6 - SetProcessIdealProcessor: 7 - CreateThread: 8 - ExitThread: 9 - SleepThread: 10 - GetThreadPriority: 11 - SetThreadPriority: 12 - GetThreadAffinityMask: 13 - SetThreadAffinityMask: 14 - GetThreadIdealProcessor: 15 - SetThreadIdealProcessor: 16 - GetCurrentProcessorNumber: 17 - Run: 18 - CreateMutex: 19 - ReleaseMutex: 20 - CreateSemaphore: 21 - ReleaseSemaphore: 22 - CreateEvent: 23 - SignalEvent: 24 - ClearEvent: 25 - CreateTimer: 26 - SetTimer: 27 - CancelTimer: 28 - ClearTimer: 29 - CreateMemoryBlock: 30 - MapMemoryBlock: 31 - UnmapMemoryBlock: 32 - CreateAddressArbiter: 33 - ArbitrateAddress: 34 - CloseHandle: 35 - WaitSynchronization1: 36 - WaitSynchronizationN: 37 - SignalAndWait: 38 - DuplicateHandle: 39 - GetSystemTick: 40 - GetHandleInfo: 41 - GetSystemInfo: 42 - GetProcessInfo: 43 - GetThreadInfo: 44 - ConnectToPort: 45 - SendSyncRequest1: 46 - SendSyncRequest2: 47 - SendSyncRequest3: 48 - SendSyncRequest4: 49 - SendSyncRequest: 50 - OpenProcess: 51 - OpenThread: 52 - GetProcessId: 53 - GetProcessIdOfThread: 54 - GetThreadId: 55 - GetResourceLimit: 56 - GetResourceLimitLimitValues: 57 - GetResourceLimitCurrentValues: 58 - GetThreadContext: 59 - Break: 60 - OutputDebugString: 61 - ControlPerformanceCounter: 62 - CreatePort: 71 - CreateSessionToPort: 72 - CreateSession: 73 - AcceptSession: 74 - ReplyAndReceive1: 75 - ReplyAndReceive2: 76 - ReplyAndReceive3: 77 - ReplyAndReceive4: 78 - ReplyAndReceive: 79 - BindInterrupt: 80 - UnbindInterrupt: 81 - InvalidateProcessDataCache: 82 - StoreProcessDataCache: 83 - FlushProcessDataCache: 84 - StartInterProcessDma: 85 - StopDma: 86 - GetDmaState: 87 - RestartDma: 88 - DebugActiveProcess: 96 - BreakDebugProcess: 97 - TerminateDebugProcess: 98 - GetProcessDebugEvent: 99 - ContinueDebugEvent: 100 - GetProcessList: 101 - GetThreadList: 102 - GetDebugThreadContext: 103 - SetDebugThreadContext: 104 - QueryDebugProcessMemory: 105 - ReadProcessMemory: 106 - WriteProcessMemory: 107 - SetHardwareBreakPoint: 108 - GetDebugThreadParam: 109 - ControlProcessMemory: 112 - MapProcessMemory: 113 - UnmapProcessMemory: 114 - CreateCodeSet: 115 - CreateProcess: 117 - TerminateProcess: 118 - SetProcessResourceLimits: 119 - CreateResourceLimit: 120 - SetResourceLimitValues: 121 - AddCodeSegment: 122 - Backdoor: 123 - KernelSetState: 124 - QueryProcessMemory: 125 - - # Service List - # Maximum 34 services (32 if firmware is prior to 9.6.0) - ServiceAccessControl: - - APT:U - - ac:u - - am:net - - boss:U - - cam:u - - cecd:u - - cfg:nor - - cfg:u - - csnd:SND - - dsp::DSP - - frd:u - - fs:USER - - gsp::Gpu - - gsp::Lcd - - hid:USER - - http:C - - ir:rst - - ir:u - - ir:USER - - mic:u - - mcu::HWC - - ndm:u - - news:s - - nwm::EXT - - nwm::UDS - - ptm:sysm - - ptm:u - - pxi:dev - - soc:U - - ssl:C - - y2r:u - - -SystemControlInfo: - SaveDataSize: 0KB # Change if the app uses savedata - RemasterVersion: $(APP_VERSION_MAJOR) - StackSize: 0x40000 - - # Modules that run services listed above should be included below - # Maximum 48 dependencies - # : - Dependency: - ac: 0x0004013000002402 - #act: 0x0004013000003802 - am: 0x0004013000001502 - boss: 0x0004013000003402 - camera: 0x0004013000001602 - cecd: 0x0004013000002602 - cfg: 0x0004013000001702 - codec: 0x0004013000001802 - csnd: 0x0004013000002702 - dlp: 0x0004013000002802 - dsp: 0x0004013000001a02 - friends: 0x0004013000003202 - gpio: 0x0004013000001b02 - gsp: 0x0004013000001c02 - hid: 0x0004013000001d02 - http: 0x0004013000002902 - i2c: 0x0004013000001e02 - ir: 0x0004013000003302 - mcu: 0x0004013000001f02 - mic: 0x0004013000002002 - ndm: 0x0004013000002b02 - news: 0x0004013000003502 - #nfc: 0x0004013000004002 - nim: 0x0004013000002c02 - nwm: 0x0004013000002d02 - pdn: 0x0004013000002102 - ps: 0x0004013000003102 - ptm: 0x0004013000002202 - #qtm: 0x0004013020004202 - ro: 0x0004013000003702 - socket: 0x0004013000002e02 - spi: 0x0004013000002302 - ssl: 0x0004013000002f02 diff --git a/packaging/ctru/res/banner.cgfx b/packaging/ctru/res/banner.cgfx deleted file mode 100644 index e806a310bb..0000000000 Binary files a/packaging/ctru/res/banner.cgfx and /dev/null differ diff --git a/packaging/ctru/res/banner.png b/packaging/ctru/res/banner.png deleted file mode 100644 index 87c0ae0f66..0000000000 Binary files a/packaging/ctru/res/banner.png and /dev/null differ diff --git a/packaging/ctru/res/banner.wav b/packaging/ctru/res/banner.wav deleted file mode 100644 index 90d7b2c9ca..0000000000 Binary files a/packaging/ctru/res/banner.wav and /dev/null differ diff --git a/packaging/ctru/res/banner_.cgfx b/packaging/ctru/res/banner_.cgfx deleted file mode 100644 index 028c466d3f..0000000000 Binary files a/packaging/ctru/res/banner_.cgfx and /dev/null differ diff --git a/packaging/ctru/res/icon.png b/packaging/ctru/res/icon.png deleted file mode 100644 index d788de7205..0000000000 Binary files a/packaging/ctru/res/icon.png and /dev/null differ diff --git a/packaging/ctru/res/icon_yellow.png b/packaging/ctru/res/icon_yellow.png deleted file mode 100644 index 76c2f42b7f..0000000000 Binary files a/packaging/ctru/res/icon_yellow.png and /dev/null differ diff --git a/packaging/ctru/rockbox.xml b/packaging/ctru/rockbox.xml deleted file mode 100644 index 0e01ecc6e7..0000000000 --- a/packaging/ctru/rockbox.xml +++ /dev/null @@ -1,7 +0,0 @@ - - /3ds/.rockbox/rockbox.3dsx - .rockbox/icon.icn - rockbox - Open Source Jukebox Firmware - rockbox.org - \ No newline at end of file diff --git a/tools/buildzip.pl b/tools/buildzip.pl index c72f70072a..50611e6183 100755 --- a/tools/buildzip.pl +++ b/tools/buildzip.pl @@ -424,11 +424,6 @@ sub buildzip { glob_mkdir("$temp_dir/libertas"); glob_copy("$ROOT/firmware/drivers/libertas/firmware/*", "$temp_dir/libertas/"); } - # add hbmenu shortcut's icon and 3dsx executable - if ($modelname =~ /ctru/) { - glob_copy("icon.icn", "$temp_dir/"); - glob_copy("rockbox.3dsx", "$temp_dir/"); - } glob_mkdir("$temp_dir/langs"); glob_mkdir("$temp_dir/rocks"); @@ -745,18 +740,6 @@ sub runone { move(".rockbox", $rbdir); print "mv .rockbox $rbdir\n" if $verbose; } - - # add hbmenu shortcut and cia file to zip file - if ($modelname =~ /ctru/) { - move("rockbox.cia", "3ds"); - copy("$ROOT/packaging/ctru/rockbox.xml", "3ds"); - - system("$ziptool -u $output 3ds/rockbox.xml $target >/dev/null"); - print "$ziptool $output $ROOT/packaging/ctru/rockbox.xml $target >/dev/null\n" if $verbose; - system("$ziptool -u $output 3ds/rockbox.cia $target >/dev/null"); - print "$ziptool $output rockbox.cia $target >/dev/null\n" if $verbose; - } - system("$ziptool $output $rbdir $target >/dev/null"); print "$ziptool $output $rbdir $target >/dev/null\n" if $verbose; rmtree("$rbdir"); diff --git a/tools/configure b/tools/configure index 24d509ce8e..2fbb27a334 100755 --- a/tools/configure +++ b/tools/configure @@ -1009,90 +1009,6 @@ rgnanocc () { rbdir="/FunKey/.rockbox" } -devkitarmcc () { - if [ -z "$DEVKITPRO" ]; then - echo "ERROR: You need a devkitPro toolchain and libraries installed" - echo "and have the DEVKITPRO environment variable point to the root" - echo "of the devkitPro installation." - echo "More info at https://devkitpro.org/wiki/Getting_Started" - exit - fi - - if [ -z "$DEVKITARM" ]; then - echo "ERROR: You need devkitARM toolchain installed and have the DEVKITARM" - echo "environment variable point to the root directory of the sdk." - exit - fi - - # check for additional dependencies - if [ ! -e "$DEVKITPRO/portlibs/3ds/lib/libCTRL.a" ]; then - echo "ERROR: You need to install libCTRL utility library." - echo "https://github.com/kynex7510/CTRL" - exit - fi - - if [ ! -e "$DEVKITPRO/portlibs/3ds/lib/libdl.a" ]; then - echo "ERROR: You need to install libdl implementation for 3ds (CTRDL)" - echo "https://github.com/kynex7510/CTRDL" - exit - fi - - if [ ! -n "`findtool makerom`" ]; then - echo "ERROR: makerom not found, please install and run configure again." - echo "https://github.com/3DSGuy/Project_CTR" - exit - fi - - if [ ! -n "`findtool bannertool`" ]; then - echo "ERROR: bannertool not found, please install and run configure again." - echo "https://github.com/carstene1ns/3ds-bannertool" - exit - fi - - arch="arm" - arch_version="6" - arch_profile="classic" - - CC=$DEVKITARM/bin/arm-none-eabi-gcc - CPP=$DEVKITARM/bin/arm-none-eabi-cpp - LD=$DEVKITARM/bin/arm-none-eabi-ld - AR=$DEVKITARM/bin/arm-none-eabi-gcc-ar - AS=$DEVKITARM/bin/arm-none-eabi-as - OC=$DEVKITARM/bin/arm-none-eabi-objcopy - WINDRES=windres - DLLTOOL=dlltool - DLLWRAP=dllwrap - RANLIB=$DEVKITARM/bin/arm-none-eabi-gcc-ranlib - - if [ "yes" = "$use_debug" ]; then - GCCOPTS=`echo $GCCOPTS | sed -e s/\ -Os/\ -Og/` - fi - - GCCOPTS="$GCCOPTS -fno-builtin -g -Wno-unused-result" - GCCOPTS="$GCCOPTS -I$DEVKITPRO/libctru/include -I$DEVKITPRO/portlibs/3ds/include" - GCCOPTS="$GCCOPTS -mword-relocations -ffunction-sections -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft" - GCCOPTS="$GCCOPTS -D_GNU_SOURCE=1 -D_REENTRANT -masm-syntax-unified" - - SHARED_LDFLAGS="-shared" - SHARED_CFLAGS="-fPIC -fvisibility=hidden" - - LDOPTS="-specs=3dsx.specs -L$DEVKITPRO/libctru/lib -L$DEVKITPRO/portlibs/3ds/lib -ldl -lCTRL -lctru -lm" - GLOBAL_LDOPTS="$GLOBAL_LDOPTS -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft" - - # let's allow building shared libraries even if unresolved symbols are found, - # CTRDL (libdl) implementation will use a custom resolver for resolve symbols at runtime. - # TODO: use ResGen command to automatically detect unresolved symbols. - GLOBAL_LDOPTS=`echo $GLOBAL_LDOPTS | sed -e s/\-Wl,-z,defs//` - - # devkitarm already defines getcwd - GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-wrap,getcwd" - - ARG_PREFIX="romfs" - - extradefines="-D__3DS__" - rbdir="/3ds/.rockbox" -} - do_bootloader() { appsdir='$(ROOTDIR)/bootloader' @@ -1863,9 +1779,6 @@ cat <