├── .gitmodules ├── icon.png ├── .gitattributes ├── romfs └── res │ ├── Roboto-Regular.ttf │ └── drawable │ ├── bg_header.png │ ├── battery_20.png │ ├── battery_30.png │ ├── battery_50.png │ ├── battery_60.png │ ├── battery_80.png │ ├── battery_90.png │ ├── battery_full.png │ ├── battery_low.png │ ├── ic_fso_default.png │ ├── ic_fso_folder.png │ ├── battery_unknown.png │ ├── btn_playback_play.png │ ├── default_artwork.png │ ├── ic_fso_type_audio.png │ ├── ic_fso_type_image.png │ ├── ic_fso_type_text.png │ ├── battery_20_charging.png │ ├── battery_30_charging.png │ ├── battery_50_charging.png │ ├── battery_60_charging.png │ ├── battery_80_charging.png │ ├── battery_90_charging.png │ ├── btn_playback_pause.png │ ├── btn_playback_repeat.png │ ├── btn_playback_rewind.png │ ├── ic_fso_folder_dark.png │ ├── ic_material_dialog.png │ ├── battery_full_charging.png │ ├── btn_playback_forward.png │ ├── btn_playback_shuffle.png │ ├── default_artwork_blur.png │ ├── ic_arrow_back_normal.png │ ├── ic_fso_type_compress.png │ ├── ic_fso_type_document.png │ ├── ic_fso_type_executable.png │ ├── ic_material_dialog_dark.png │ ├── ic_material_light_accept.png │ ├── ic_material_light_remove.png │ ├── ic_material_light_sdcard.png │ ├── ic_material_light_secure.png │ ├── btn_playback_repeat_overlay.png │ ├── ic_material_light_settings.png │ ├── ic_material_options_dialog.png │ ├── btn_playback_shuffle_overlay.png │ ├── ic_material_dialog_fs_locked.png │ ├── ic_material_light_accept_dark.png │ ├── ic_material_light_remove_dark.png │ ├── ic_material_light_sdcard_dark.png │ ├── ic_material_light_secure_dark.png │ ├── ic_material_properties_dialog.png │ ├── ic_material_light_settings_dark.png │ ├── ic_material_options_dialog_dark.png │ ├── btn_material_light_check_on_normal.png │ ├── btn_material_light_radio_on_normal.png │ ├── ic_material_properties_dialog_dark.png │ ├── btn_material_light_check_off_normal.png │ ├── btn_material_light_radio_off_normal.png │ ├── btn_material_light_toggle_off_normal.png │ ├── btn_material_light_toggle_on_normal.png │ ├── ic_material_light_contextual_action.png │ ├── ic_material_light_navigation_drawer.png │ ├── btn_material_light_check_on_normal_dark.png │ ├── btn_material_light_radio_on_normal_dark.png │ ├── btn_material_light_check_off_normal_dark.png │ ├── btn_material_light_radio_off_normal_dark.png │ └── btn_material_light_toggle_on_normal_dark.png ├── include ├── menus │ ├── menu_main.h │ ├── menu_music.h │ ├── menu_settings.h │ ├── menu_gallery.h │ └── menu_options.h ├── status_bar.h ├── minizip │ ├── archive.h │ ├── crypt.h │ ├── ioapi.h │ └── unzip.h ├── progress_bar.h ├── osk.h ├── config.h ├── utils.h ├── fs.h ├── touch_helper.h ├── common.h ├── dirbrowse.h ├── textures.h ├── input_helper.h └── SDL_helper.h ├── .gitignore ├── source ├── common.c ├── config.c ├── progress_bar.c ├── utils.c ├── input_helper.c ├── fs.c ├── touch_helper.c ├── status_bar.c ├── SDL_helper.c ├── main.c ├── minizip │ ├── archive.c │ └── ioapi.c ├── menus │ ├── menu_gallery.c │ ├── menu_main.c │ ├── menu_music.c │ ├── menu_settings.c │ └── menu_options.c ├── textures.c ├── osk.c └── dirbrowse.c ├── README.md └── Makefile /.gitmodules: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/icon.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /romfs/res/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/Roboto-Regular.ttf -------------------------------------------------------------------------------- /romfs/res/drawable/bg_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/bg_header.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_20.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_30.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_50.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_60.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_80.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_90.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_full.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_low.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_low.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_default.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_folder.png -------------------------------------------------------------------------------- /include/menus/menu_main.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_MENU_MAIN_H 2 | #define WIIU_SHELL_MENU_MAIN_H 3 | 4 | void Menu_Main(void); 5 | 6 | #endif -------------------------------------------------------------------------------- /romfs/res/drawable/battery_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_unknown.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_playback_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_playback_play.png -------------------------------------------------------------------------------- /romfs/res/drawable/default_artwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/default_artwork.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_type_audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_type_audio.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_type_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_type_image.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_type_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_type_text.png -------------------------------------------------------------------------------- /include/menus/menu_music.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_MUSIC_H 2 | #define WIIU_SHELL_MUSIC_H 3 | 4 | void Menu_PlayMusic(char *path); 5 | 6 | #endif -------------------------------------------------------------------------------- /romfs/res/drawable/battery_20_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_20_charging.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_30_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_30_charging.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_50_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_50_charging.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_60_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_60_charging.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_80_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_80_charging.png -------------------------------------------------------------------------------- /romfs/res/drawable/battery_90_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_90_charging.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_playback_pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_playback_pause.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_playback_repeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_playback_repeat.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_playback_rewind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_playback_rewind.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_folder_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_folder_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_dialog.png -------------------------------------------------------------------------------- /include/status_bar.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_STATUS_BAR_H 2 | #define WIIU_SHELL_STATUS_BAR_H 3 | 4 | void StatusBar_DisplayTime(void); 5 | 6 | #endif -------------------------------------------------------------------------------- /romfs/res/drawable/battery_full_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/battery_full_charging.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_playback_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_playback_forward.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_playback_shuffle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_playback_shuffle.png -------------------------------------------------------------------------------- /romfs/res/drawable/default_artwork_blur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/default_artwork_blur.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_arrow_back_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_arrow_back_normal.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_type_compress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_type_compress.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_type_document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_type_document.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_fso_type_executable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_fso_type_executable.png -------------------------------------------------------------------------------- /include/menus/menu_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_SETTINGS_H 2 | #define WIIU_SHELL_SETTINGS_H 3 | 4 | void Menu_DisplaySettings(void); 5 | 6 | #endif -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_dialog_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_dialog_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_accept.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_remove.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_sdcard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_sdcard.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_secure.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.exe 3 | *.o 4 | test 5 | tahoma12.c 6 | tahoma24.c 7 | *.zip 8 | build 9 | *.elf 10 | *.nso 11 | *.pfs0 12 | *.nacp 13 | *.nro -------------------------------------------------------------------------------- /romfs/res/drawable/btn_playback_repeat_overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_playback_repeat_overlay.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_settings.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_options_dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_options_dialog.png -------------------------------------------------------------------------------- /include/menus/menu_gallery.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_MENU_GALLERY_H 2 | #define WIIU_SHELL_MENU_GALLERY_H 3 | 4 | void Gallery_DisplayImage(char *path); 5 | 6 | #endif -------------------------------------------------------------------------------- /romfs/res/drawable/btn_playback_shuffle_overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_playback_shuffle_overlay.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_dialog_fs_locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_dialog_fs_locked.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_accept_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_accept_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_remove_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_remove_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_sdcard_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_sdcard_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_secure_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_secure_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_properties_dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_properties_dialog.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_settings_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_settings_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_options_dialog_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_options_dialog_dark.png -------------------------------------------------------------------------------- /include/minizip/archive.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_ARCHIVE_H 2 | #define WIIU_SHELL_ARCHIVE_H 3 | 4 | int Archive_ExtractZip(const char *src, const char *dst); 5 | 6 | #endif -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_check_on_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_check_on_normal.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_radio_on_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_radio_on_normal.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_properties_dialog_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_properties_dialog_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_check_off_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_check_off_normal.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_radio_off_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_radio_off_normal.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_toggle_off_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_toggle_off_normal.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_toggle_on_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_toggle_on_normal.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_contextual_action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_contextual_action.png -------------------------------------------------------------------------------- /romfs/res/drawable/ic_material_light_navigation_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/ic_material_light_navigation_drawer.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_check_on_normal_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_check_on_normal_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_radio_on_normal_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_radio_on_normal_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_check_off_normal_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_check_off_normal_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_radio_off_normal_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_radio_off_normal_dark.png -------------------------------------------------------------------------------- /romfs/res/drawable/btn_material_light_toggle_on_normal_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rw-r-r-0644/WiiU-Shell/HEAD/romfs/res/drawable/btn_material_light_toggle_on_normal_dark.png -------------------------------------------------------------------------------- /include/progress_bar.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_MENU_PROGRESS_BAR_H 2 | #define WIIU_SHELL_MENU_PROGRESS_BAR_H 3 | 4 | void ProgressBar_DisplayProgress(char *msg, char *src, uint32_t offset, uint32_t size); 5 | 6 | #endif -------------------------------------------------------------------------------- /include/osk.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_OSK_H 2 | #define WIIU_SHELL_OSK_H 3 | 4 | #define MAX_Y 4 5 | #define MAX_X 9 6 | 7 | char osk_buffer[256]; 8 | 9 | void OSK_Display(char *title, char *msg); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_CONFIG_H 2 | #define WIIU_SHELL_CONFIG_H 3 | 4 | #include 5 | 6 | extern bool config_dark_theme; 7 | extern int config_sort_by; 8 | 9 | int Config_Save(bool config_dark_theme, int config_sort_by); 10 | int Config_Load(void); 11 | 12 | #endif -------------------------------------------------------------------------------- /source/common.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | jmp_buf exitJmp; 4 | 5 | SDL_Window *WINDOW; 6 | SDL_Surface *WINDOW_SURFACE; 7 | SDL_Renderer *RENDERER; 8 | TTF_Font *Roboto_large, *Roboto, *Roboto_small, *Roboto_OSK; 9 | 10 | int MENU_DEFAULT_STATE; 11 | int BROWSE_STATE; 12 | 13 | char cwd[512]; 14 | -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_UTILS_H 2 | #define WIIU_SHELL_UTILS_H 3 | 4 | char *Utils_Basename(const char *filename); 5 | void Utils_GetSizeString(char *string, uint32_t size); 6 | void Utils_SetMax(int *set, int value, int max); 7 | void Utils_SetMin(int *set, int value, int min); 8 | void Utils_AppendArr(char subject[], const char insert[], int pos); 9 | 10 | #endif -------------------------------------------------------------------------------- /include/fs.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_FS_H 2 | #define WIIU_SHELL_FS_H 3 | 4 | #include 5 | 6 | int FS_MakeDir(const char *path); 7 | int FS_RecursiveMakeDir(const char * dir); 8 | bool FS_FileExists(const char *path); 9 | bool FS_DirExists(const char *path); 10 | const char *FS_GetFileExt(const char *filename); 11 | char *FS_GetFileModifiedTime(const char *filename); 12 | uint32_t FS_GetFileSize(const char *filename); 13 | 14 | #endif -------------------------------------------------------------------------------- /include/menus/menu_options.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_MENU_OPTIONS_H 2 | #define WIIU_SHELL_MENU_OPTIONS_H 3 | 4 | #include "touch_helper.h" 5 | 6 | /* 7 | * Copy Flags 8 | */ 9 | #define COPY_FOLDER_RECURSIVE 2 10 | #define COPY_DELETE_ON_FINISH 1 11 | #define COPY_KEEP_ON_FINISH 0 12 | #define NOTHING_TO_COPY -1 13 | 14 | void FileOptions_ResetClipboard(void); 15 | void Menu_ControlDeleteDialog(uint32_t input, TouchInfo touchInfo); 16 | void Menu_DisplayDeleteDialog(void); 17 | void Menu_ControlProperties(uint32_t input, TouchInfo touchInfo); 18 | void Menu_DisplayProperties(void); 19 | void Menu_ControlOptions(uint32_t input, TouchInfo touchInfo); 20 | void Menu_DisplayOptions(void); 21 | 22 | #endif -------------------------------------------------------------------------------- /include/touch_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_TOUCH_HELPER_H 2 | #define WIIU_SHELL_TOUCH_HELPER_H 3 | 4 | #include "input_helper.h" 5 | #include 6 | 7 | #define tapped_inside(touchInfo, x1, y1, x2, y2) (touchInfo.firstTouch.px >= x1 && touchInfo.firstTouch.px <= x2 && touchInfo.firstTouch.py >= y1 && touchInfo.firstTouch.py <= y2) 8 | #define tapped_outside(touchInfo, x1, y1, x2, y2) (touchInfo.firstTouch.px < x1 || touchInfo.firstTouch.px > x2 || touchInfo.firstTouch.py < y1 || touchInfo.firstTouch.py > y2) 9 | 10 | typedef enum TouchState 11 | { 12 | TouchNone, 13 | TouchStart, 14 | TouchMoving, 15 | TouchEnded 16 | } TouchState; 17 | 18 | typedef enum TapType 19 | { 20 | TapNone, 21 | TapShort, 22 | TapLong 23 | } TapType; 24 | 25 | typedef struct TouchInfo 26 | { 27 | TouchState state; 28 | TouchPosition firstTouch; 29 | TouchPosition prevTouch; 30 | TapType tapType; 31 | time_t touchStart; 32 | } TouchInfo; 33 | 34 | void Touch_Init(TouchInfo * touchInfo); 35 | void Touch_Process(TouchInfo * touchInfo); 36 | 37 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WiiU-Shell 2 | 3 | Work in progress port of NX-Shell by joel16 (Multi purpose file manager) to the Nintendo WiiU. 4 | 5 | # Features: 6 | 7 | - Delete files and folders. 8 | - Copy/Move files and folders. 9 | - Rename files and folders. 10 | - Create folders. 11 | - Displays file size. (files only ATM) 12 | - Image viewer (PNG/JPG/GIF/BMP) 13 | - Extract .ZIP files. 14 | - Sorting options (Sort by name, date, size). 15 | - Dark theme toggle. 16 | - Audio playback. (Following formats are supported: OGG, WAV and MOD) 17 | - Touch screen. 18 | 19 | # Build instructions 20 | 21 | ```bash 22 | git clone --recursive https://github.com/rw-r-r-0644/WiiU-Shell.git 23 | cd WiiU-Shell/ 24 | make 25 | ``` 26 | 27 | # Credits: 28 | - **rw-r-r-0644** for the wiiu porting. 29 | - **joel16** for the original NX-Shell and 3DShell. 30 | - **Preetisketch** for some of the assets used as well as the banner. 31 | - **StevenMattera** for the implementing the foundation of all touch-screen code. 32 | - **rock88** for integrating mupdf, allowing WiiU-Shell to read pdfs and other epubs. 33 | - **FlameKat53** for making the icon.png 34 | -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_COMMON_H 2 | #define WIIU_SHELL_COMMON_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define wait(msec) SDL_Delay(msec) 12 | 13 | extern jmp_buf exitJmp; 14 | 15 | extern SDL_Window *WINDOW; 16 | extern SDL_Surface *WINDOW_SURFACE; 17 | extern SDL_Renderer *RENDERER; 18 | extern TTF_Font *Roboto_large, *Roboto, *Roboto_small, *Roboto_OSK; 19 | 20 | #define ROOT_PATH "/vol/external01/" 21 | #define START_PATH ROOT_PATH 22 | #define MAX_FILES 2048 23 | #define FILES_PER_PAGE 8 24 | 25 | extern int MENU_DEFAULT_STATE; 26 | extern int BROWSE_STATE; 27 | 28 | enum MENU_STATES 29 | { 30 | MENU_STATE_HOME = 0, 31 | MENU_STATE_OPTIONS = 1, 32 | MENU_STATE_MENUBAR = 2, 33 | MENU_STATE_SETTINGS = 3, 34 | MENU_STATE_FTP = 4, 35 | MENU_STATE_SORT = 5, 36 | MENU_STATE_DELETE_DIALOG = 6, 37 | MENU_STATE_PROPERTIES = 7 38 | }; 39 | 40 | enum BROWSE_STATES 41 | { 42 | STATE_SD = 0, 43 | STATE_NAND = 1 44 | }; 45 | 46 | extern char cwd[512]; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /source/config.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "config.h" 6 | #include "fs.h" 7 | 8 | bool config_dark_theme; 9 | int config_sort_by; 10 | 11 | const char *configFile = 12 | "theme = %d\n" 13 | "sortBy = %d\n"; 14 | 15 | int Config_Save(bool config_dark_theme, int config_sort_by) 16 | { 17 | char *buf = (char *)malloc(64); 18 | snprintf(buf, 64, configFile, config_dark_theme, config_sort_by); 19 | 20 | FILE *file = fopen("wiiu/WiiU-Shell/config.cfg", "w"); 21 | fprintf(file, buf); 22 | fclose(file); 23 | 24 | free(buf); 25 | return 0; 26 | } 27 | 28 | int Config_Load(void) 29 | { 30 | if (!FS_FileExists("wiiu/WiiU-Shell/config.cfg")) 31 | { 32 | config_dark_theme = false; 33 | config_sort_by = 0; 34 | return Config_Save(config_dark_theme, config_sort_by); 35 | } 36 | 37 | uint32_t size = FS_GetFileSize("wiiu/WiiU-Shell/config.cfg"); 38 | char *buf = (char *)malloc(size + 1); 39 | 40 | FILE *file = fopen("wiiu/WiiU-Shell/config.cfg", "r"); 41 | fread(buf, size, 1, file); 42 | fclose(file); 43 | 44 | buf[size] = '\0'; 45 | sscanf(buf, configFile, &config_dark_theme, &config_sort_by); 46 | free(buf); 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /include/dirbrowse.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_DIRBROWSE_H 2 | #define WIIU_SHELL_DIRBROWSE_H 3 | 4 | #include 5 | 6 | typedef struct File 7 | { 8 | struct File *next; // Next item 9 | int isDir; // Folder flag 10 | int isReadOnly; // Read-only flag 11 | int isHidden; // Hidden file flag 12 | char name[256]; // File name 13 | char ext[4]; // File extension 14 | uint32_t size; // File size 15 | } File; 16 | 17 | extern File *files; 18 | 19 | extern int initialPosition; 20 | extern int position; 21 | extern int fileCount; 22 | 23 | int multi_select_index; // Multi-select index. 24 | bool multi_select[256]; // Array of indices selected. 25 | int multi_select_indices[256]; // Array to hold the indices. 26 | char multi_select_dir[512]; // Holds the current dir where multi-select happens. 27 | char multi_select_paths[256][512]; // Holds the file paths of those in the clipboard. 28 | 29 | void Dirbrowse_RecursiveFree(File *node); 30 | void Dirbrowse_PopulateFiles(bool clear); 31 | void Dirbrowse_DisplayFiles(void); 32 | File *Dirbrowse_GetFileIndex(int index); 33 | void Dirbrowse_OpenFile(void); 34 | int Dirbrowse_Navigate(bool parent); 35 | 36 | #endif -------------------------------------------------------------------------------- /source/progress_bar.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "config.h" 3 | #include "progress_bar.h" 4 | #include "SDL_helper.h" 5 | #include "textures.h" 6 | 7 | void ProgressBar_DisplayProgress(char *msg, char *src, uint32_t offset, uint32_t size) 8 | { 9 | int text_width = 0; 10 | TTF_SizeText(Roboto, src, &text_width, NULL); 11 | 12 | int width = 0, height = 0; 13 | SDL_QueryTexture(config_dark_theme? dialog_dark : dialog, NULL, NULL, &width, &height); 14 | 15 | SDL_DrawImage(RENDERER, config_dark_theme? dialog_dark : dialog, ((1280 - (width)) / 2), ((720 - (height)) / 2)); 16 | 17 | SDL_DrawText(RENDERER, Roboto, ((1280 - (width)) / 2) + 80, ((720 - (height)) / 2) + 45, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, msg); 18 | 19 | SDL_DrawText(RENDERER, Roboto, ((1280 - (text_width)) / 2), ((720 - (height)) / 2) + 111, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, src); 20 | 21 | SDL_DrawRect(RENDERER, ((1280 - (width)) / 2) + 80, ((720 - (height)) / 2) + 178, 720, 12, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 22 | SDL_DrawRect(RENDERER, ((1280 - (width)) / 2) + 80, ((720 - (height)) / 2) + 178, (double)offset / (double)size * 720.0, 12, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR); 23 | 24 | SDL_RenderPresent(RENDERER); 25 | } -------------------------------------------------------------------------------- /include/textures.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_TEXTURES_H 2 | #define WIIU_SHELL_TEXTURES_H 3 | 4 | 5 | SDL_Texture *icon_app, *icon_archive, *icon_audio, *icon_dir, *icon_file, *icon_image, *icon_text, *icon_dir_dark, \ 6 | *icon_doc, *icon_check, *icon_uncheck, *icon_check_dark, *icon_uncheck_dark, *icon_radio_off, *icon_radio_on, \ 7 | *icon_radio_dark_off, *icon_radio_dark_on, *icon_toggle_on, *icon_toggle_dark_on, *icon_toggle_off, \ 8 | *dialog, *options_dialog, *properties_dialog, *dialog_dark, *options_dialog_dark, *properties_dialog_dark, \ 9 | *bg_header, *icon_settings, *icon_sd, *icon_secure, *icon_settings_dark, *icon_sd_dark, *icon_secure_dark, \ 10 | *default_artwork, *default_artwork_blur, *btn_play, *btn_pause, *btn_rewind, *btn_forward, \ 11 | *btn_repeat, *btn_shuffle, *btn_repeat_overlay, *btn_shuffle_overlay, *icon_lock, \ 12 | *icon_nav_drawer, *icon_actions, *icon_back, \ 13 | *icon_accept, *icon_accept_dark, *icon_remove, *icon_remove_dark, \ 14 | *battery_20, *battery_20_charging, *battery_30, *battery_30_charging, *battery_50, *battery_50_charging, \ 15 | *battery_60, *battery_60_charging, *battery_80, *battery_80_charging, *battery_90, *battery_90_charging, \ 16 | *battery_full, *battery_full_charging, *battery_low, *battery_unknown; 17 | 18 | void Textures_Load(void); 19 | void Textures_Free(void); 20 | 21 | #endif -------------------------------------------------------------------------------- /source/utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "utils.h" 5 | 6 | char *Utils_Basename(const char *filename) 7 | { 8 | char *p = strrchr (filename, '/'); 9 | return p ? p + 1 : (char *) filename; 10 | } 11 | 12 | void Utils_GetSizeString(char *string, uint32_t size) 13 | { 14 | double double_size = (double)size; 15 | 16 | int i = 0; 17 | static char *units[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; 18 | 19 | while (double_size >= 1024.0f) 20 | { 21 | double_size /= 1024.0f; 22 | i++; 23 | } 24 | 25 | sprintf(string, "%.*f %s", (i == 0) ? 0 : 2, double_size, units[i]); 26 | } 27 | 28 | void Utils_SetMax(int *set, int value, int max) 29 | { 30 | if (*set > max) 31 | *set = value; 32 | } 33 | 34 | void Utils_SetMin(int *set, int value, int min) 35 | { 36 | if (*set < min) 37 | *set = value; 38 | } 39 | 40 | void Utils_AppendArr(char subject[], const char insert[], int pos) 41 | { 42 | char buf[100] = {}; // 100 so that it's big enough. fill with 0 43 | // or you could use malloc() to allocate sufficient space 44 | 45 | strncpy(buf, subject, pos); // copy at most first pos characters 46 | int len = strlen(buf); 47 | strcpy(buf+len, insert); // copy all of insert[] at the end 48 | len += strlen(insert); // increase the length by length of insert[] 49 | strcpy(buf+len, subject+pos); // copy the rest 50 | 51 | strcpy(subject, buf); // copy it back to subject 52 | // deallocate buf[] here, if used malloc() 53 | } 54 | -------------------------------------------------------------------------------- /source/input_helper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "input_helper.h" 4 | 5 | #define TOUCH_PRECISION 10 6 | 7 | static uint32_t kHeld = 0, kDown = 0, kUp = 0; 8 | static uint32_t tHeld = 0, tPosX = 0, tPosY = 0; 9 | static uint8_t battStatus = 0; 10 | 11 | void Input_Update() 12 | { 13 | VPADStatus vpad; 14 | VPADReadError vpad_e; 15 | 16 | VPADRead(VPAD_CHAN_0, &vpad, 1, &vpad_e); 17 | if (vpad_e == VPAD_READ_SUCCESS) 18 | { 19 | kHeld = vpad.hold; 20 | kDown = vpad.trigger; 21 | kUp = vpad.release; 22 | battStatus = vpad.battery; 23 | 24 | VPADTouchData tpdata; 25 | VPADGetTPCalibratedPoint(VPAD_CHAN_0, &tpdata, &vpad.tpNormal); 26 | 27 | if (tpdata.touched) 28 | { 29 | tHeld = 1; 30 | if (!(tpdata.validity & VPAD_INVALID_X) && (abs(tPosX - tpdata.x) > TOUCH_PRECISION)) 31 | tPosX = tpdata.x; 32 | if (!(tpdata.validity & VPAD_INVALID_Y) && (abs(tPosY - tpdata.y) > TOUCH_PRECISION)) 33 | tPosY = tpdata.y; 34 | } 35 | else 36 | { 37 | tHeld = 0; 38 | } 39 | } 40 | } 41 | 42 | uint8_t Input_BatteryStatus() 43 | { 44 | return battStatus; 45 | } 46 | 47 | uint32_t Input_KeysHeld() 48 | { 49 | return kHeld; 50 | } 51 | 52 | uint32_t Input_KeysDown() 53 | { 54 | return kDown; 55 | } 56 | 57 | uint32_t Input_KeysUp() 58 | { 59 | return kUp; 60 | } 61 | 62 | uint32_t Input_TouchCount() 63 | { 64 | return tHeld; 65 | } 66 | 67 | void Input_TouchPos(TouchPosition *pos, uint32_t touch) 68 | { 69 | if (touch == 0 && tHeld) 70 | { 71 | pos->px = tPosX; 72 | pos->py = tPosY; 73 | } 74 | else 75 | { 76 | pos->px = 0; 77 | pos->py = 0; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /source/fs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "fs.h" 7 | 8 | int FS_MakeDir(const char *path) 9 | { 10 | if (!path) 11 | return -1; 12 | 13 | return mkdir(path, 0777); 14 | } 15 | 16 | int FS_RecursiveMakeDir(const char * dir) 17 | { 18 | int ret = 0; 19 | char buf[256]; 20 | char *p = NULL; 21 | size_t len; 22 | 23 | snprintf(buf, sizeof(buf), "%s",dir); 24 | len = strlen(buf); 25 | 26 | if (buf[len - 1] == '/') 27 | buf[len - 1] = 0; 28 | 29 | for (p = buf + 1; *p; p++) 30 | { 31 | if (*p == '/') 32 | { 33 | *p = 0; 34 | 35 | ret = FS_MakeDir(buf); 36 | 37 | *p = '/'; 38 | } 39 | 40 | ret = FS_MakeDir(buf); 41 | } 42 | 43 | return ret; 44 | } 45 | 46 | bool FS_FileExists(const char *path) 47 | { 48 | FILE *temp = fopen(path, "r"); 49 | 50 | if (temp == NULL) 51 | return false; 52 | 53 | fclose(temp); 54 | return true; 55 | } 56 | 57 | bool FS_DirExists(const char *path) 58 | { 59 | struct stat info; 60 | 61 | if (stat(path, &info) != 0) 62 | return false; 63 | else if (info.st_mode & S_IFDIR) 64 | return true; 65 | else 66 | return false; 67 | } 68 | 69 | const char *FS_GetFileExt(const char *filename) 70 | { 71 | const char *dot = strrchr(filename, '.'); 72 | 73 | if (!dot || dot == filename) 74 | return ""; 75 | 76 | return dot + 1; 77 | } 78 | 79 | char *FS_GetFileModifiedTime(const char *filename) 80 | { 81 | struct stat attr; 82 | stat(filename, &attr); 83 | 84 | return ctime(&attr.st_mtime); 85 | } 86 | 87 | uint32_t FS_GetFileSize(const char *filename) 88 | { 89 | struct stat st; 90 | stat(filename, &st); 91 | 92 | return st.st_size; 93 | } -------------------------------------------------------------------------------- /source/touch_helper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "input_helper.h" 6 | #include "touch_helper.h" 7 | 8 | #define TAP_MOVEMENT_GAP 20 9 | #define LONG_TAP_PERIOD 2 10 | 11 | 12 | void Touch_Init(TouchInfo * touchInfo) 13 | { 14 | touchInfo->state = TouchNone; 15 | touchInfo->tapType = TapNone; 16 | } 17 | 18 | void Touch_Process(TouchInfo * touchInfo) 19 | { 20 | TouchPosition currentTouch; 21 | uint32_t touches = Input_TouchCount(); 22 | 23 | if (touches >= 1) 24 | Input_TouchPos(¤tTouch, 0); 25 | 26 | time_t current_time = time(NULL); 27 | 28 | // On touch start. 29 | if (touches == 1 && (touchInfo->state == TouchNone || touchInfo->state == TouchEnded)) 30 | { 31 | touchInfo->state = TouchStart; 32 | touchInfo->firstTouch = currentTouch; 33 | touchInfo->prevTouch = currentTouch; 34 | touchInfo->tapType = TapShort; 35 | touchInfo->touchStart = current_time; 36 | } 37 | // On touch moving. 38 | else if (touches >= 1 && touchInfo->state != TouchNone) 39 | { 40 | touchInfo->state = TouchMoving; 41 | touchInfo->prevTouch = currentTouch; 42 | 43 | if (touchInfo->tapType != TapNone && (abs(touchInfo->firstTouch.px - currentTouch.px) > TAP_MOVEMENT_GAP || abs(touchInfo->firstTouch.py - currentTouch.py) > TAP_MOVEMENT_GAP)) 44 | touchInfo->tapType = TapNone; 45 | else if (touchInfo->tapType == TapShort && current_time - touchInfo->touchStart >= LONG_TAP_PERIOD) 46 | touchInfo->tapType = TapLong; 47 | } 48 | // On touch end. 49 | else 50 | touchInfo->state = (touchInfo->state == TouchMoving) ? TouchEnded : TouchNone; 51 | } -------------------------------------------------------------------------------- /include/input_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_INPUT_HELPER_H 2 | #define WIIU_SHELL_INPUT_HELPER_H 3 | 4 | #include 5 | 6 | typedef enum InputKeys 7 | { 8 | KEY_A = VPAD_BUTTON_A, 9 | KEY_B = VPAD_BUTTON_B, 10 | KEY_X = VPAD_BUTTON_X, 11 | KEY_Y = VPAD_BUTTON_Y, 12 | KEY_LSTICK = VPAD_BUTTON_STICK_L, 13 | KEY_RSTICK = VPAD_BUTTON_STICK_R, 14 | KEY_L = VPAD_BUTTON_L, 15 | KEY_R = VPAD_BUTTON_R, 16 | KEY_ZL = VPAD_BUTTON_ZL, 17 | KEY_ZR = VPAD_BUTTON_ZR, 18 | KEY_PLUS = VPAD_BUTTON_PLUS, 19 | KEY_MINUS = VPAD_BUTTON_MINUS, 20 | KEY_DLEFT = VPAD_BUTTON_LEFT, 21 | KEY_DUP = VPAD_BUTTON_UP, 22 | KEY_DRIGHT = VPAD_BUTTON_RIGHT, 23 | KEY_DDOWN = VPAD_BUTTON_DOWN, 24 | KEY_LSTICK_LEFT = VPAD_STICK_L_EMULATION_LEFT, 25 | KEY_LSTICK_UP = VPAD_STICK_L_EMULATION_UP, 26 | KEY_LSTICK_RIGHT = VPAD_STICK_L_EMULATION_RIGHT, 27 | KEY_LSTICK_DOWN = VPAD_STICK_L_EMULATION_DOWN, 28 | KEY_RSTICK_LEFT = VPAD_STICK_R_EMULATION_LEFT, 29 | KEY_RSTICK_UP = VPAD_STICK_R_EMULATION_UP, 30 | KEY_RSTICK_RIGHT = VPAD_STICK_R_EMULATION_RIGHT, 31 | KEY_RSTICK_DOWN = VPAD_STICK_R_EMULATION_DOWN, 32 | KEY_UP = KEY_DUP | KEY_LSTICK_UP | KEY_RSTICK_UP, 33 | KEY_DOWN = KEY_DDOWN | KEY_LSTICK_DOWN | KEY_RSTICK_DOWN, 34 | KEY_LEFT = KEY_DLEFT | KEY_LSTICK_LEFT | KEY_RSTICK_LEFT, 35 | KEY_RIGHT = KEY_DRIGHT | KEY_LSTICK_RIGHT | KEY_RSTICK_RIGHT, 36 | } InputKeys; 37 | 38 | typedef struct TouchPosition 39 | { 40 | uint32_t px; 41 | uint32_t py; 42 | } TouchPosition; 43 | 44 | void Input_Update(); 45 | uint8_t Input_BatteryStatus(); 46 | uint32_t Input_KeysHeld(); 47 | uint32_t Input_KeysDown(); 48 | uint32_t Input_KeysUp(); 49 | uint32_t Input_TouchCount(); 50 | void Input_TouchPos(TouchPosition *pos, uint32_t touch); 51 | 52 | #endif -------------------------------------------------------------------------------- /include/SDL_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef WIIU_SHELL_SDL_HELPER_H 2 | #define WIIU_SHELL_SDL_HELPER_H 3 | 4 | static inline SDL_Color SDL_MakeColour(Uint8 r, Uint8 g, Uint8 b, Uint8 a) 5 | { 6 | SDL_Color colour = {r, g, b, a}; 7 | return colour; 8 | } 9 | 10 | #define WHITE SDL_MakeColour(255, 255, 255, 255) 11 | #define BLACK_BG SDL_MakeColour(48, 48, 48, 255) 12 | #define STATUS_BAR_LIGHT SDL_MakeColour(37, 79, 174, 255) 13 | #define STATUS_BAR_DARK SDL_MakeColour(38, 50, 56, 255) 14 | #define MENU_BAR_LIGHT SDL_MakeColour(51, 103, 214, 255) 15 | #define MENU_BAR_DARK SDL_MakeColour(55, 71, 79, 255) 16 | #define BLACK SDL_MakeColour(0, 0, 0, 255) 17 | #define SELECTOR_COLOUR_LIGHT SDL_MakeColour(241, 241, 241, 255) 18 | #define SELECTOR_COLOUR_DARK SDL_MakeColour(76, 76, 76, 255) 19 | #define TITLE_COLOUR SDL_MakeColour(30, 136, 229, 255) 20 | #define TITLE_COLOUR_DARK SDL_MakeColour(0, 150, 136, 255) 21 | #define TEXT_MIN_COLOUR_LIGHT SDL_MakeColour(32, 32, 32, 255) 22 | #define TEXT_MIN_COLOUR_DARK SDL_MakeColour(185, 185, 185, 255) 23 | #define BAR_COLOUR SDL_MakeColour(200, 200, 200, 255) 24 | 25 | void SDL_ClearScreen(SDL_Renderer *renderer, SDL_Color colour); 26 | void SDL_DrawRect(SDL_Renderer *renderer, int x, int y, int w, int h, SDL_Color colour); 27 | void SDL_DrawCircle(SDL_Renderer *renderer, int x, int y, int r, SDL_Color colour); 28 | void SDL_DrawText(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color colour, const char *text); 29 | void SDL_DrawTextf(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color colour, const char* text, ...); 30 | void SDL_LoadImage(SDL_Renderer *renderer, SDL_Texture **texture, char *path); 31 | void SDL_LoadImageBuf(SDL_Renderer *renderer, SDL_Texture **texture, void *mem, int size); 32 | void SDL_DrawImage(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y); 33 | void SDL_DrawImageScale(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, int w, int h); 34 | 35 | #endif -------------------------------------------------------------------------------- /source/status_bar.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "SDL_helper.h" 7 | #include "status_bar.h" 8 | #include "textures.h" 9 | #include "input_helper.h" 10 | 11 | static char *Clock_GetCurrentTime(void) 12 | { 13 | static char buffer[10]; 14 | 15 | OSCalendarTime calTime; 16 | OSTicksToCalendarTime(OSGetTime(), &calTime); 17 | int hours = (calTime.tm_hour); 18 | int minutes = calTime.tm_min; 19 | 20 | bool amOrPm = false; 21 | 22 | if (hours < 12) 23 | amOrPm = true; 24 | if (hours == 0) 25 | hours = 12; 26 | else if (hours > 12) 27 | hours = hours - 12; 28 | 29 | if ((hours >= 1) && (hours < 10)) 30 | snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM"); 31 | else 32 | snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM"); 33 | 34 | return buffer; 35 | } 36 | 37 | static void StatusBar_GetBatteryStatus(int x, int y) 38 | { 39 | int percent = 50; 40 | int width = 0; 41 | char buf[5]; 42 | 43 | switch(Input_BatteryStatus()) 44 | { 45 | case 0: 46 | SDL_DrawImage(RENDERER, battery_50_charging, x, 3); 47 | percent = -1; 48 | break; 49 | case 1: 50 | SDL_DrawImage(RENDERER, battery_low, x, 3); 51 | percent = 0; 52 | break; 53 | case 2: 54 | SDL_DrawImage(RENDERER, battery_20, x, 3); 55 | percent = 20; 56 | break; 57 | case 3: 58 | SDL_DrawImage(RENDERER, battery_30, x, 3); 59 | percent = 30; 60 | break; 61 | case 4: 62 | SDL_DrawImage(RENDERER, battery_50, x, 3); 63 | percent = 50; 64 | break; 65 | case 5: 66 | SDL_DrawImage(RENDERER, battery_80, x, 3); 67 | percent = 80; 68 | break; 69 | case 6: 70 | SDL_DrawImage(RENDERER, battery_full, x, 3); 71 | percent = 100; 72 | break; 73 | default: 74 | SDL_DrawImage(RENDERER, battery_unknown, x, 3); 75 | percent = -2; 76 | break; 77 | } 78 | 79 | if (percent >= 0) 80 | snprintf(buf, 5, "%d%%", percent); 81 | else if (percent == -1) 82 | snprintf(buf, 5, "CHRG"); 83 | else if (percent == -2) 84 | snprintf(buf, 5, "UNKN"); 85 | 86 | TTF_SizeText(Roboto, buf, &width, NULL); 87 | SDL_DrawText(RENDERER, Roboto, (x - width - 10), y, WHITE, buf); 88 | } 89 | 90 | void StatusBar_DisplayTime(void) 91 | { 92 | int width = 0, height = 0; 93 | TTF_SizeText(Roboto, Clock_GetCurrentTime(), &width, &height); 94 | 95 | StatusBar_GetBatteryStatus(1260 - width - 44, (40 - height) / 2); 96 | SDL_DrawText(RENDERER, Roboto, 1260 - width, (40 - height) / 2, WHITE, Clock_GetCurrentTime()); 97 | } -------------------------------------------------------------------------------- /source/SDL_helper.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "SDL_helper.h" 3 | 4 | void SDL_ClearScreen(SDL_Renderer *renderer, SDL_Color colour) 5 | { 6 | SDL_SetRenderDrawColor(renderer, colour.r, colour.g, colour.b, colour.a); 7 | SDL_RenderClear(renderer); 8 | } 9 | 10 | void SDL_DrawRect(SDL_Renderer *renderer, int x, int y, int w, int h, SDL_Color colour) 11 | { 12 | SDL_Rect rect; 13 | rect.x = x; rect.y = y; rect.w = w; rect.h = h; 14 | SDL_SetRenderDrawColor(RENDERER, colour.r, colour.g, colour.b, colour.a); 15 | SDL_RenderFillRect(RENDERER, &rect); 16 | } 17 | 18 | void SDL_DrawCircle(SDL_Renderer *renderer, int x, int y, int r, SDL_Color colour) 19 | { 20 | filledCircleRGBA(renderer, x, y, r, colour.r, colour.g, colour.b, colour.a); 21 | return; 22 | } 23 | 24 | void SDL_DrawText(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color colour, const char *text) 25 | { 26 | SDL_Surface *surface = TTF_RenderText_Blended_Wrapped(font, text, colour, 1280); 27 | SDL_SetSurfaceAlphaMod(surface, colour.a); 28 | SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); 29 | SDL_FreeSurface(surface); 30 | 31 | SDL_Rect position; 32 | position.x = x; position.y = y; 33 | SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h); 34 | SDL_RenderCopy(renderer, texture, NULL, &position); 35 | SDL_DestroyTexture(texture); 36 | } 37 | 38 | void SDL_DrawTextf(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color colour, const char* text, ...) 39 | { 40 | char buffer[256]; 41 | va_list args; 42 | va_start(args, text); 43 | vsnprintf(buffer, 256, text, args); 44 | SDL_DrawText(renderer, font, x, y, colour, buffer); 45 | va_end(args); 46 | } 47 | 48 | void SDL_LoadImage(SDL_Renderer *renderer, SDL_Texture **texture, char *path) 49 | { 50 | SDL_Surface *loaded_surface = NULL; 51 | loaded_surface = IMG_Load(path); 52 | 53 | if (loaded_surface) 54 | { 55 | Uint32 colorkey = SDL_MapRGB(loaded_surface->format, 0, 0, 0); 56 | SDL_SetColorKey(loaded_surface, SDL_TRUE, colorkey); 57 | *texture = SDL_CreateTextureFromSurface(renderer, loaded_surface); 58 | } 59 | 60 | SDL_FreeSurface(loaded_surface); 61 | } 62 | 63 | void SDL_DrawImage(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y) 64 | { 65 | SDL_Rect position; 66 | position.x = x; position.y = y; 67 | SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h); 68 | SDL_RenderCopy(renderer, texture, NULL, &position); 69 | } 70 | 71 | void SDL_DrawImageScale(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, int w, int h) 72 | { 73 | SDL_Rect position; 74 | position.x = x; position.y = y; position.w = w; position.h = h; 75 | SDL_RenderCopy(renderer, texture, NULL, &position); 76 | } 77 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "common.h" 5 | #include "config.h" 6 | #include "fs.h" 7 | #include "menu_main.h" 8 | #include "textures.h" 9 | 10 | #ifdef DEBUG 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static devoptab_t dotab_stdout; 18 | static ssize_t wiiu_log_write (struct _reent *r, void *fd, const char *ptr, size_t len) { 19 | WHBLogPrintf("%*.*s", len, len, ptr); 20 | return len; 21 | } 22 | 23 | #endif 24 | 25 | 26 | 27 | static void Term_Services(void) 28 | { 29 | Textures_Free(); 30 | 31 | TTF_CloseFont(Roboto_OSK); 32 | TTF_CloseFont(Roboto_small); 33 | TTF_CloseFont(Roboto); 34 | TTF_CloseFont(Roboto_large); 35 | TTF_Quit(); 36 | 37 | Mix_CloseAudio(); 38 | Mix_Quit(); 39 | 40 | IMG_Quit(); 41 | 42 | SDL_DestroyRenderer(RENDERER); 43 | SDL_FreeSurface(WINDOW_SURFACE); 44 | SDL_DestroyWindow(WINDOW); 45 | 46 | #ifdef DEBUG 47 | WHBLogUdpDeinit(); 48 | #endif 49 | 50 | SDL_Quit(); 51 | romfsExit(); 52 | } 53 | 54 | static void Init_Services(void) 55 | { 56 | romfsInit(); 57 | SDL_Init(SDL_INIT_EVERYTHING); 58 | 59 | #ifdef DEBUG 60 | WHBLogUdpInit(); 61 | memset(&dotab_stdout, 0, sizeof(devoptab_t)); 62 | dotab_stdout.name = "stdout_udp"; 63 | dotab_stdout.write_r = &wiiu_log_write; 64 | devoptab_list[STD_OUT] = &dotab_stdout; 65 | devoptab_list[STD_ERR] = &dotab_stdout; 66 | #endif 67 | 68 | SDL_CreateWindowAndRenderer(1280, 720, 0, &WINDOW, &RENDERER); 69 | 70 | WINDOW_SURFACE = SDL_GetWindowSurface(WINDOW); 71 | 72 | SDL_SetRenderDrawBlendMode(RENDERER, SDL_BLENDMODE_BLEND); 73 | 74 | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2"); 75 | 76 | IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG); 77 | 78 | Mix_Init(MIX_INIT_FLAC | MIX_INIT_MOD | MIX_INIT_MP3 | MIX_INIT_OGG | MIX_INIT_MID); 79 | Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096); 80 | 81 | TTF_Init(); 82 | Roboto_large = TTF_OpenFont("romfs:/res/Roboto-Regular.ttf", 30); 83 | Roboto = TTF_OpenFont("romfs:/res/Roboto-Regular.ttf", 25); 84 | Roboto_small = TTF_OpenFont("romfs:/res/Roboto-Regular.ttf", 20); 85 | Roboto_OSK = TTF_OpenFont("romfs:/res/Roboto-Regular.ttf", 50); 86 | if (!Roboto_large || !Roboto || !Roboto_small || !Roboto_OSK) 87 | Term_Services(); 88 | 89 | Textures_Load(); 90 | 91 | FS_RecursiveMakeDir("wiiu/WiiU-Shell/"); 92 | 93 | if (FS_FileExists("wiiu/WiiU-Shell/lastdir.txt")) 94 | { 95 | char *buf = (char *)malloc(256); 96 | 97 | FILE *read = fopen("wiiu/WiiU-Shell/lastdir.txt", "r"); 98 | fscanf(read, "%s", buf); 99 | fclose(read); 100 | 101 | if (FS_DirExists(buf)) // Incase a directory previously visited had been deleted, set start path to sdmc:/ to avoid errors. 102 | strcpy(cwd, buf); 103 | else 104 | strcpy(cwd, START_PATH); 105 | 106 | free(buf); 107 | } 108 | else 109 | { 110 | char *buf = (char *)malloc(256); 111 | strcpy(buf, START_PATH); 112 | 113 | FILE *write = fopen("wiiu/WiiU-Shell/lastdir.txt", "w"); 114 | fprintf(write, "%s", buf); 115 | fclose(write); 116 | 117 | strcpy(cwd, buf); // Set Start Path to "sdmc:/" if lastDir.txt hasn't been created. 118 | 119 | free(buf); 120 | } 121 | 122 | Config_Load(); 123 | } 124 | 125 | int main(int argc, char **argv) 126 | { 127 | Init_Services(); 128 | 129 | if (setjmp(exitJmp)) 130 | { 131 | Term_Services(); 132 | return 0; 133 | } 134 | 135 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 136 | Menu_Main(); 137 | Term_Services(); 138 | } 139 | -------------------------------------------------------------------------------- /source/minizip/archive.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "archive.h" 8 | #include "progress_bar.h" 9 | #include "fs.h" 10 | #include "unzip.h" 11 | #include "utils.h" 12 | 13 | int unzExtractCurrentFile(unzFile *unzHandle, int *path) 14 | { 15 | int res = 0; 16 | char filename[256]; 17 | unsigned int bufsize = (64 * 1024); 18 | 19 | unz_file_info file_info; 20 | if ((res = unzGetCurrentFileInfo(unzHandle, &file_info, filename, sizeof(filename), NULL, 0, NULL, 0)) != 0) 21 | { 22 | unzClose(unzHandle); 23 | return -1; 24 | } 25 | 26 | void *buf = (void *)malloc(bufsize); 27 | if (!buf) 28 | return -2; 29 | 30 | char *filenameWithoutPath = Utils_Basename(filename); 31 | 32 | if ((*filenameWithoutPath) == '\0') 33 | { 34 | if ((*path) == 0) 35 | mkdir(filename, 0777); 36 | } 37 | else 38 | { 39 | const char *write; 40 | 41 | if ((*path) == 0) 42 | write = filename; 43 | else 44 | write = filenameWithoutPath; 45 | 46 | if ((res = unzOpenCurrentFile(unzHandle)) != UNZ_OK) 47 | { 48 | unzClose(unzHandle); 49 | free(buf); 50 | return res; 51 | } 52 | 53 | FILE *out = fopen(write, "wb"); 54 | 55 | if ((out == NULL) && ((*path) == 0) && (filenameWithoutPath != (char *)filename)) 56 | { 57 | char c = *(filenameWithoutPath - 1); 58 | *(filenameWithoutPath - 1) = '\0'; 59 | mkdir(write, 0777); 60 | *(filenameWithoutPath - 1) = c; 61 | out = fopen(write, "wb"); 62 | } 63 | 64 | do 65 | { 66 | res = unzReadCurrentFile(unzHandle, buf, bufsize); 67 | 68 | if (res < 0) 69 | break; 70 | 71 | if (res > 0) 72 | fwrite(buf, 1, res, out); 73 | } 74 | while (res > 0); 75 | 76 | fclose(out); 77 | 78 | res = unzCloseCurrentFile(unzHandle); 79 | } 80 | 81 | if (buf) 82 | free(buf); 83 | 84 | return res; 85 | } 86 | 87 | int unzExtractAll(const char *src, unzFile *unzHandle) 88 | { 89 | int res = 0; 90 | int path = 0; 91 | char *filename = Utils_Basename(src); 92 | 93 | unz_global_info global_info; 94 | memset(&global_info, 0, sizeof(unz_global_info)); 95 | 96 | if ((res = unzGetGlobalInfo(unzHandle, &global_info)) != UNZ_OK) // Get info about the zip file 97 | { 98 | unzClose(unzHandle); 99 | return res; 100 | } 101 | 102 | for (unsigned int i = 0; i < global_info.number_entry; i++) 103 | { 104 | ProgressBar_DisplayProgress("Extracting", filename, i, global_info.number_entry); 105 | 106 | if ((res = unzExtractCurrentFile(unzHandle, &path)) != UNZ_OK) 107 | break; 108 | 109 | if ((i + 1) < global_info.number_entry) 110 | { 111 | if ((res = unzGoToNextFile(unzHandle)) != UNZ_OK) // Could not read next file. 112 | { 113 | unzClose(unzHandle); 114 | return res; 115 | } 116 | } 117 | } 118 | 119 | return res; 120 | } 121 | 122 | int Archive_ExtractZip(const char *src, const char *dst) 123 | { 124 | char tmpFile2[512]; 125 | char tmpPath2[512]; 126 | 127 | FS_MakeDir(dst); 128 | 129 | strncpy(tmpPath2, "sdmc:", sizeof(tmpPath2)); 130 | strncat(tmpPath2, (char *)dst, (512 - strlen(tmpPath2) - 1)); 131 | chdir(tmpPath2); 132 | 133 | strncpy(tmpFile2, "sdmc:", sizeof(tmpFile2)); 134 | strncat(tmpFile2, (char*)src, (512 - strlen(tmpFile2) - 1)); 135 | 136 | unzFile *unzHandle = unzOpen(tmpFile2); // Open zip file 137 | 138 | if (unzHandle == NULL) // not found 139 | return -1; 140 | 141 | int res = unzExtractAll(src, unzHandle); 142 | res = unzClose(unzHandle); 143 | 144 | return res; 145 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BASEDIR := $(dir $(firstword $(MAKEFILE_LIST))) 2 | VPATH := $(BASEDIR) 3 | 4 | PKGCONF := $(DEVKITPRO)/portlibs/ppc/bin/powerpc-eabi-pkg-config 5 | PKGCONF_WIIU := $(DEVKITPRO)/portlibs/wiiu/bin/powerpc-eabi-pkg-config 6 | 7 | #--------------------------------------------------------------------------------- 8 | # TARGET is the name of the output 9 | # SOURCES is a list of directories containing source code 10 | # INCLUDES is a list of directories containing header files 11 | # ROMFS is a folder to generate app's romfs 12 | #--------------------------------------------------------------------------------- 13 | TARGET := WiiU-Shell 14 | SOURCES := source \ 15 | source/audio \ 16 | source/menus \ 17 | source/minizip \ 18 | source/menus/menu_book_reader 19 | INCLUDES := include \ 20 | include/audio \ 21 | include/menus \ 22 | include/minizip 23 | ROMFS := romfs 24 | 25 | VERSION_MAJOR := 1 26 | VERSION_MINOR := 0 27 | VERSION_MICRO := 4 28 | 29 | #--------------------------------------------------------------------------------- 30 | # options for code generation 31 | #--------------------------------------------------------------------------------- 32 | CFLAGS += -O2 -std=c11 -Wall -Wno-format-truncation -U__STRICT_ANSI__ \ 33 | -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO) 34 | CXXFLAGS += -O2 -Wall -Wno-format-truncation -U__STRICT_ANSI__ \ 35 | -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO) 36 | 37 | #--------------------------------------------------------------------------------- 38 | # libraries 39 | #--------------------------------------------------------------------------------- 40 | CFLAGS += `$(PKGCONF_WIIU) --cflags SDL2_gfx SDL2_image SDL2_mixer SDL2_ttf sdl2` 41 | CXXFLAGS += `$(PKGCONF_WIIU) --cflags SDL2_gfx SDL2_image SDL2_mixer SDL2_ttf sdl2` 42 | LDFLAGS += `$(PKGCONF_WIIU) --libs SDL2_gfx SDL2_image SDL2_mixer SDL2_ttf sdl2` \ 43 | `$(PKGCONF) --libs freetype2 zlib libpng libjpeg libmpg123` 44 | 45 | #--------------------------------------------------------------------------------- 46 | # wut libraries 47 | #--------------------------------------------------------------------------------- 48 | LDFLAGS += $(WUT_NEWLIB_LDFLAGS) $(WUT_STDCPP_LDFLAGS) \ 49 | -lcoreinit -lvpad -lsndcore2 -lnsysnet -lsysapp -lproc_ui -lgx2 -lgfd -lwhb 50 | 51 | #--------------------------------------------------------------------------------- 52 | # romfs 53 | #--------------------------------------------------------------------------------- 54 | include $(WUT_ROOT)/share/romfs-wiiu.mk 55 | LDFLAGS += $(ROMFS_LDFLAGS) 56 | OBJECTS += $(ROMFS_TARGET) 57 | 58 | #--------------------------------------------------------------------------------- 59 | # includes 60 | #--------------------------------------------------------------------------------- 61 | CFLAGS += $(foreach dir,$(INCLUDES),-I$(dir)) 62 | CXXFLAGS += $(foreach dir,$(INCLUDES),-I$(dir)) 63 | 64 | #--------------------------------------------------------------------------------- 65 | # generate a list of objects 66 | #--------------------------------------------------------------------------------- 67 | CFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.c)) 68 | CPPFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.cpp)) 69 | SFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.S)) 70 | OBJECTS += $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 71 | 72 | #--------------------------------------------------------------------------------- 73 | # targets 74 | #--------------------------------------------------------------------------------- 75 | $(TARGET).rpx: $(OBJECTS) 76 | 77 | clean: 78 | $(info clean ...) 79 | @rm -rf $(TARGET).rpx $(OBJECTS) $(OBJECTS:.o=.d) 80 | 81 | .PHONY: clean 82 | 83 | #--------------------------------------------------------------------------------- 84 | # wut 85 | #--------------------------------------------------------------------------------- 86 | include $(WUT_ROOT)/share/wut.mk 87 | -------------------------------------------------------------------------------- /source/menus/menu_gallery.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "fs.h" 7 | #include "menu_gallery.h" 8 | #include "SDL_helper.h" 9 | #include "touch_helper.h" 10 | #include "input_helper.h" 11 | #include "utils.h" 12 | 13 | static char album[1024][512]; 14 | static int count = 0, selection = 0; 15 | static SDL_Texture *image = NULL; 16 | static int width = 0, height = 0; 17 | static float scale_factor = 0.0f; 18 | 19 | static void Gallery_GetImageList(void) 20 | { 21 | DIR *dir; 22 | struct dirent *entries; 23 | dir = opendir(cwd); 24 | 25 | if (dir != NULL) 26 | { 27 | while ((entries = readdir (dir)) != NULL) 28 | { 29 | if ((strncasecmp(FS_GetFileExt(entries->d_name), "png", 3) == 0) || (strncasecmp(FS_GetFileExt(entries->d_name), "jpg", 3) == 0) 30 | || (strncasecmp(FS_GetFileExt(entries->d_name), "bmp", 3) == 0) || (strncasecmp(FS_GetFileExt(entries->d_name), "gif", 3) == 0)) 31 | { 32 | strcpy(album[count], cwd); 33 | strcpy(album[count] + strlen(album[count]), entries->d_name); 34 | count++; 35 | } 36 | } 37 | 38 | closedir(dir); 39 | } 40 | } 41 | 42 | static int Gallery_GetCurrentIndex(char *path) 43 | { 44 | for(int i = 0; i < count; ++i) 45 | { 46 | if (!strcmp(album[i], path)) 47 | return i; 48 | } 49 | return 0; 50 | } 51 | 52 | static void Gallery_HandleNext(bool forward) 53 | { 54 | if (forward) 55 | selection++; 56 | else 57 | selection--; 58 | 59 | Utils_SetMax(&selection, 0, (count - 1)); 60 | Utils_SetMin(&selection, (count - 1), 0); 61 | 62 | SDL_DestroyTexture(image); 63 | selection = Gallery_GetCurrentIndex(album[selection]); 64 | 65 | SDL_LoadImage(RENDERER, &image, album[selection]); 66 | SDL_QueryTexture(image, NULL, NULL, &width, &height); 67 | } 68 | 69 | static void Gallery_DrawImage(int x, int y, int w, int h, float zoom_factor) 70 | { 71 | SDL_Rect position; 72 | position.x = x; position.y = y; position.w = w * zoom_factor; position.h = h * zoom_factor; 73 | SDL_RenderCopy(RENDERER, image, NULL, &position); 74 | } 75 | 76 | void Gallery_DisplayImage(char *path) 77 | { 78 | Gallery_GetImageList(); 79 | selection = Gallery_GetCurrentIndex(path); 80 | SDL_LoadImage(RENDERER, &image, path); 81 | SDL_QueryTexture(image, NULL, NULL, &width, &height); 82 | 83 | TouchInfo touchInfo; 84 | Touch_Init(&touchInfo); 85 | 86 | uint64_t current_time = 0, last_time = 0; 87 | float zoom_factor = 1.0f; 88 | 89 | while(WHBProcIsRunning()) 90 | { 91 | SDL_ClearScreen(RENDERER, SDL_MakeColour(33, 39, 43, 255)); 92 | SDL_RenderClear(RENDERER); 93 | 94 | last_time = current_time; 95 | current_time = SDL_GetPerformanceCounter(); 96 | double delta_time = (double)((current_time - last_time) * 1000 / SDL_GetPerformanceFrequency()); 97 | 98 | if (height <= 720) 99 | Gallery_DrawImage((1280 - (width * zoom_factor)) / 2, (720 - (height * zoom_factor)) / 2, 100 | width, height, zoom_factor); 101 | else if (height > 720) 102 | { 103 | scale_factor = (720.0f / (float)height); 104 | width = width * scale_factor; 105 | height = height * scale_factor; 106 | Gallery_DrawImage((float)((1280.0f - (width * zoom_factor)) / 2.0f), 107 | (float)((720.0f - (height * zoom_factor)) / 2.0f), (float)width, (float)height, zoom_factor); 108 | } 109 | 110 | Input_Update(); 111 | Touch_Process(&touchInfo); 112 | uint32_t kDown = Input_KeysDown(); 113 | uint32_t kHeld = Input_KeysHeld(); 114 | 115 | if ((kDown & KEY_DLEFT) || (kDown & KEY_L)) 116 | { 117 | wait(1); 118 | Gallery_HandleNext(false); 119 | } 120 | else if ((kDown & KEY_DRIGHT) || (kDown & KEY_R)) 121 | { 122 | wait(1); 123 | Gallery_HandleNext(true); 124 | } 125 | 126 | if ((kHeld & KEY_DUP) || (kHeld & KEY_LSTICK_UP)) 127 | { 128 | zoom_factor += 0.5f * (delta_time * 0.001); 129 | 130 | if (zoom_factor > 2.0f) 131 | zoom_factor = 2.0f; 132 | } 133 | else if ((kHeld & KEY_DDOWN) || (kHeld & KEY_LSTICK_DOWN)) 134 | { 135 | zoom_factor -= 0.5f * (delta_time * 0.001); 136 | 137 | if (zoom_factor < 0.5f) 138 | zoom_factor = 0.5f; 139 | } 140 | 141 | if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 142 | { 143 | if (tapped_inside(touchInfo, 0, 0, 120, 720)) 144 | { 145 | wait(1); 146 | Gallery_HandleNext(false); 147 | } 148 | else if (tapped_inside(touchInfo, 1160, 0, 1280, 720)) 149 | { 150 | wait(1); 151 | Gallery_HandleNext(true); 152 | } 153 | } 154 | 155 | SDL_RenderPresent(RENDERER); 156 | 157 | if (kDown & KEY_B) 158 | break; 159 | } 160 | 161 | SDL_DestroyTexture(image); 162 | memset(album, 0, sizeof(album[0][0]) * 512 * 512); 163 | count = 0; 164 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 165 | } -------------------------------------------------------------------------------- /include/minizip/crypt.h: -------------------------------------------------------------------------------- 1 | /* crypt.h -- base code for crypt/uncrypt ZIPfile 2 | 3 | 4 | Version 1.01e, February 12th, 2005 5 | 6 | Copyright (C) 1998-2005 Gilles Vollant 7 | 8 | This code is a modified version of crypting code in Infozip distribution 9 | 10 | The encryption/decryption parts of this source code (as opposed to the 11 | non-echoing password parts) were originally written in Europe. The 12 | whole source package can be freely distributed, including from the USA. 13 | (Prior to January 2000, re-export from the US was a violation of US law.) 14 | 15 | This encryption code is a direct transcription of the algorithm from 16 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This 17 | file (appnote.txt) is distributed with the PKZIP program (even in the 18 | version without encryption capabilities). 19 | 20 | If you don't need crypting in your application, just define symbols 21 | NOCRYPT and NOUNCRYPT. 22 | 23 | This code support the "Traditional PKWARE Encryption". 24 | 25 | The new AES encryption added on Zip format by Winzip (see the page 26 | http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong 27 | Encryption is not supported. 28 | */ 29 | 30 | #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) 31 | 32 | /*********************************************************************** 33 | * Return the next byte in the pseudo-random sequence 34 | */ 35 | static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) 36 | { 37 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an 38 | * unpredictable manner on 16-bit systems; not a problem 39 | * with any known compiler so far, though */ 40 | 41 | temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; 42 | return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); 43 | } 44 | 45 | /*********************************************************************** 46 | * Update the encryption keys with the next byte of plain text 47 | */ 48 | static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) 49 | { 50 | (*(pkeys+0)) = CRC32((*(pkeys+0)), c); 51 | (*(pkeys+1)) += (*(pkeys+0)) & 0xff; 52 | (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; 53 | { 54 | register int keyshift = (int)((*(pkeys+1)) >> 24); 55 | (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); 56 | } 57 | return c; 58 | } 59 | 60 | 61 | /*********************************************************************** 62 | * Initialize the encryption keys and the random header according to 63 | * the given password. 64 | */ 65 | static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) 66 | { 67 | *(pkeys+0) = 305419896L; 68 | *(pkeys+1) = 591751049L; 69 | *(pkeys+2) = 878082192L; 70 | while (*passwd != '\0') { 71 | update_keys(pkeys,pcrc_32_tab,(int)*passwd); 72 | passwd++; 73 | } 74 | } 75 | 76 | #define zdecode(pkeys,pcrc_32_tab,c) \ 77 | (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) 78 | 79 | #define zencode(pkeys,pcrc_32_tab,c,t) \ 80 | (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) 81 | 82 | #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED 83 | 84 | #define RAND_HEAD_LEN 12 85 | /* "last resort" source for second part of crypt seed pattern */ 86 | # ifndef ZCR_SEED2 87 | # define ZCR_SEED2 3141592654UL /* use PI as default pattern */ 88 | # endif 89 | 90 | static int crypthead(const char* passwd, /* password string */ 91 | unsigned char* buf, /* where to write header */ 92 | int bufSize, 93 | unsigned long* pkeys, 94 | const z_crc_t* pcrc_32_tab, 95 | unsigned long crcForCrypting) 96 | { 97 | int n; /* index in random header */ 98 | int t; /* temporary */ 99 | int c; /* random byte */ 100 | unsigned char header[RAND_HEAD_LEN-2]; /* random header */ 101 | static unsigned calls = 0; /* ensure different random header each time */ 102 | 103 | if (bufSize> 7) & 0xff; 118 | header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); 119 | } 120 | /* Encrypt random header (last two bytes is high word of crc) */ 121 | init_keys(passwd, pkeys, pcrc_32_tab); 122 | for (n = 0; n < RAND_HEAD_LEN-2; n++) 123 | { 124 | buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); 125 | } 126 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); 127 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); 128 | return n; 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /include/minizip/ioapi.h: -------------------------------------------------------------------------------- 1 | /* ioapi.h -- IO base function header for compress/uncompress .zip 2 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) 3 | 4 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) 5 | 6 | Modifications for Zip64 support 7 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) 8 | 9 | For more info read MiniZip_info.txt 10 | 11 | Changes 12 | 13 | Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) 14 | Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. 15 | More if/def section may be needed to support other platforms 16 | Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. 17 | (but you should use iowin32.c for windows instead) 18 | 19 | */ 20 | 21 | #ifndef _ZLIBIOAPI64_H 22 | #define _ZLIBIOAPI64_H 23 | 24 | #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) 25 | 26 | // Linux needs this to support file operation on files larger then 4+GB 27 | // But might need better if/def to select just the platforms that needs them. 28 | 29 | #ifndef __USE_FILE_OFFSET64 30 | #define __USE_FILE_OFFSET64 31 | #endif 32 | #ifndef __USE_LARGEFILE64 33 | #define __USE_LARGEFILE64 34 | #endif 35 | #ifndef _LARGEFILE64_SOURCE 36 | #define _LARGEFILE64_SOURCE 37 | #endif 38 | #ifndef _FILE_OFFSET_BIT 39 | #define _FILE_OFFSET_BIT 64 40 | #endif 41 | 42 | #endif 43 | 44 | #include 45 | #include 46 | #include "zlib.h" 47 | 48 | #if defined(USE_FILE32API) 49 | #define fopen64 fopen 50 | #define ftello64 ftell 51 | #define fseeko64 fseek 52 | #else 53 | #ifdef __FreeBSD__ 54 | #define fopen64 fopen 55 | #define ftello64 ftello 56 | #define fseeko64 fseeko 57 | #endif 58 | #ifdef _MSC_VER 59 | #define fopen64 fopen 60 | #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) 61 | #define ftello64 _ftelli64 62 | #define fseeko64 _fseeki64 63 | #else // old MSC 64 | #define ftello64 ftell 65 | #define fseeko64 fseek 66 | #endif 67 | #endif 68 | #endif 69 | 70 | /* 71 | #ifndef ZPOS64_T 72 | #ifdef _WIN32 73 | #define ZPOS64_T fpos_t 74 | #else 75 | #include 76 | #define ZPOS64_T uint64_t 77 | #endif 78 | #endif 79 | */ 80 | 81 | #ifdef HAVE_MINIZIP64_CONF_H 82 | #include "mz64conf.h" 83 | #endif 84 | 85 | /* a type choosen by DEFINE */ 86 | #ifdef HAVE_64BIT_INT_CUSTOM 87 | typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; 88 | #else 89 | #ifdef HAS_STDINT_H 90 | #include "stdint.h" 91 | typedef uint64_t ZPOS64_T; 92 | #else 93 | 94 | /* Maximum unsigned 32-bit value used as placeholder for zip64 */ 95 | #define MAXU32 0xffffffff 96 | 97 | #if defined(_MSC_VER) || defined(__BORLANDC__) 98 | typedef unsigned __int64 ZPOS64_T; 99 | #else 100 | typedef unsigned long long int ZPOS64_T; 101 | #endif 102 | #endif 103 | #endif 104 | 105 | 106 | 107 | #ifdef __cplusplus 108 | extern "C" { 109 | #endif 110 | 111 | 112 | #define ZLIB_FILEFUNC_SEEK_CUR (1) 113 | #define ZLIB_FILEFUNC_SEEK_END (2) 114 | #define ZLIB_FILEFUNC_SEEK_SET (0) 115 | 116 | #define ZLIB_FILEFUNC_MODE_READ (1) 117 | #define ZLIB_FILEFUNC_MODE_WRITE (2) 118 | #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) 119 | 120 | #define ZLIB_FILEFUNC_MODE_EXISTING (4) 121 | #define ZLIB_FILEFUNC_MODE_CREATE (8) 122 | 123 | 124 | #ifndef ZCALLBACK 125 | #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) 126 | #define ZCALLBACK CALLBACK 127 | #else 128 | #define ZCALLBACK 129 | #endif 130 | #endif 131 | 132 | 133 | 134 | 135 | typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); 136 | typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); 137 | typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); 138 | typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); 139 | typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); 140 | 141 | typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); 142 | typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); 143 | 144 | 145 | /* here is the "old" 32 bits structure structure */ 146 | typedef struct zlib_filefunc_def_s 147 | { 148 | open_file_func zopen_file; 149 | read_file_func zread_file; 150 | write_file_func zwrite_file; 151 | tell_file_func ztell_file; 152 | seek_file_func zseek_file; 153 | close_file_func zclose_file; 154 | testerror_file_func zerror_file; 155 | voidpf opaque; 156 | } zlib_filefunc_def; 157 | 158 | typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); 159 | typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); 160 | typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); 161 | 162 | typedef struct zlib_filefunc64_def_s 163 | { 164 | open64_file_func zopen64_file; 165 | read_file_func zread_file; 166 | write_file_func zwrite_file; 167 | tell64_file_func ztell64_file; 168 | seek64_file_func zseek64_file; 169 | close_file_func zclose_file; 170 | testerror_file_func zerror_file; 171 | voidpf opaque; 172 | } zlib_filefunc64_def; 173 | 174 | void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); 175 | void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); 176 | 177 | /* now internal definition, only for zip.c and unzip.h */ 178 | typedef struct zlib_filefunc64_32_def_s 179 | { 180 | zlib_filefunc64_def zfile_func64; 181 | open_file_func zopen32_file; 182 | tell_file_func ztell32_file; 183 | seek_file_func zseek32_file; 184 | } zlib_filefunc64_32_def; 185 | 186 | 187 | #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) 188 | #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) 189 | //#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) 190 | //#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) 191 | #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) 192 | #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) 193 | 194 | voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); 195 | long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); 196 | ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); 197 | 198 | void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); 199 | 200 | #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) 201 | #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) 202 | #define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) 203 | 204 | #ifdef __cplusplus 205 | } 206 | #endif 207 | 208 | #endif 209 | -------------------------------------------------------------------------------- /source/menus/menu_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "common.h" 5 | #include "config.h" 6 | #include "dirbrowse.h" 7 | #include "menu_main.h" 8 | #include "menu_options.h" 9 | #include "menu_settings.h" 10 | #include "SDL_helper.h" 11 | #include "status_bar.h" 12 | #include "textures.h" 13 | #include "touch_helper.h" 14 | #include "input_helper.h" 15 | #include "utils.h" 16 | 17 | #define MENUBAR_X_BOUNDARY 0 18 | static float menubar_x = -400.0; 19 | static char multi_select_dir_old[512]; 20 | 21 | void AnimateMenuBar(float delta_time) 22 | { 23 | menubar_x += 400.0f * (delta_time * 0.001); 24 | 25 | if (menubar_x > 0) 26 | menubar_x = MENUBAR_X_BOUNDARY; 27 | } 28 | 29 | static void Menu_ControlMenuBar(uint32_t input, TouchInfo touchInfo) 30 | { 31 | if (input & KEY_A) 32 | MENU_DEFAULT_STATE = MENU_STATE_SETTINGS; 33 | 34 | if ((input & KEY_MINUS) || (input & KEY_B)) 35 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 36 | 37 | if ((touchInfo.state == TouchEnded) && (touchInfo.tapType != TapNone)) 38 | { 39 | if (touchInfo.firstTouch.px >= menubar_x + 400) 40 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 41 | else if (tapped_inside(touchInfo, menubar_x + 20, 630, menubar_x + 80, 710)) 42 | MENU_DEFAULT_STATE = MENU_STATE_SETTINGS; 43 | } 44 | } 45 | 46 | static void Menu_DisplayMenuBar(void) 47 | { 48 | SDL_DrawRect(RENDERER, menubar_x, 0, 400, 720, config_dark_theme? BLACK_BG : WHITE); 49 | SDL_DrawRect(RENDERER, menubar_x + 400, 0, 1, 720, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT); 50 | SDL_DrawImage(RENDERER, bg_header, menubar_x, 0); 51 | SDL_DrawText(RENDERER, Roboto_large, menubar_x + 15, 164, WHITE, "WiiU Shell"); 52 | SDL_DrawImage(RENDERER, config_dark_theme? icon_sd_dark : icon_sd, menubar_x + 20, 254); 53 | SDL_DrawText(RENDERER, Roboto, menubar_x + 100, 254, config_dark_theme? WHITE : BLACK, "External storage"); 54 | SDL_DrawText(RENDERER, Roboto_small, menubar_x + 100, 284, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "sdmc"); 55 | SDL_DrawRect(RENDERER, menubar_x + 10, 630, 80, 80, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 56 | SDL_DrawImage(RENDERER, config_dark_theme? icon_settings_dark : icon_settings, menubar_x + 20, 640); 57 | } 58 | 59 | static void Menu_HandleMultiSelect(void) 60 | { 61 | // multi_select_dir can only hold one dir 62 | strcpy(multi_select_dir_old, cwd); 63 | if (strcmp(multi_select_dir_old, multi_select_dir) != 0) 64 | FileOptions_ResetClipboard(); 65 | 66 | char path[512]; 67 | File *file = Dirbrowse_GetFileIndex(position); 68 | strcpy(path, cwd); 69 | strcpy(path + strlen(path), file->name); 70 | strcpy(multi_select_dir, cwd); 71 | 72 | if (!multi_select[position]) 73 | { 74 | multi_select[position] = true; 75 | multi_select_indices[position] = multi_select_index; // Store the index in the position 76 | Utils_AppendArr(multi_select_paths[multi_select_index], path, multi_select_index); 77 | multi_select_index += 1; 78 | } 79 | else 80 | { 81 | multi_select[position] = false; 82 | strcpy(multi_select_paths[multi_select_indices[position]], ""); 83 | multi_select_indices[position] = -1; 84 | } 85 | 86 | Utils_SetMax(&multi_select_index, 0, 50); 87 | Utils_SetMin(&multi_select_index, 50, 0); 88 | } 89 | 90 | static void Menu_ControlHome(uint32_t input, TouchInfo touchInfo) 91 | { 92 | if (input & KEY_PLUS) 93 | longjmp(exitJmp, 1); 94 | 95 | if (input & KEY_MINUS) 96 | { 97 | if (MENU_DEFAULT_STATE == MENU_STATE_MENUBAR) 98 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 99 | else 100 | { 101 | menubar_x = -400; 102 | MENU_DEFAULT_STATE = MENU_STATE_MENUBAR; 103 | } 104 | } 105 | 106 | if (fileCount >= 0) 107 | { 108 | if (input & KEY_DUP) 109 | position--; 110 | else if (input & KEY_DDOWN) 111 | position++; 112 | 113 | if ((Input_KeysHeld() & KEY_RSTICK_UP) || (Input_KeysHeld() & KEY_LSTICK_UP)) 114 | { 115 | wait(5); 116 | position--; 117 | } 118 | else if ((Input_KeysHeld() & KEY_RSTICK_DOWN) || (Input_KeysHeld() & KEY_LSTICK_DOWN)) 119 | { 120 | wait(5); 121 | position++; 122 | } 123 | 124 | Utils_SetMax(&position, 0, ((strcmp(cwd, ROOT_PATH) == 0? (fileCount - 1) : fileCount))); 125 | Utils_SetMin(&position, ((strcmp(cwd, ROOT_PATH) == 0? (fileCount - 1) : fileCount)), 0); 126 | 127 | if (input & KEY_LEFT) 128 | position = 0; 129 | else if (input & KEY_RIGHT) 130 | position = ((strcmp(cwd, ROOT_PATH) == 0? (fileCount - 1) : fileCount)); 131 | 132 | // Open options 133 | if (input & KEY_X) 134 | { 135 | if (MENU_DEFAULT_STATE == MENU_STATE_OPTIONS) 136 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 137 | else 138 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 139 | } 140 | 141 | if (input & KEY_Y) 142 | Menu_HandleMultiSelect(); 143 | 144 | if (input & KEY_A) 145 | { 146 | wait(5); 147 | Dirbrowse_OpenFile(); 148 | } 149 | else if ((strcmp(cwd, ROOT_PATH) != 0) && (input & KEY_B)) 150 | { 151 | wait(5); 152 | Dirbrowse_Navigate(true); 153 | Dirbrowse_PopulateFiles(true); 154 | } 155 | } 156 | 157 | if (touchInfo.state == TouchStart && tapped_inside(touchInfo, 0, 140, 1280, 720)) 158 | initialPosition = (position == 0) ? 7 : position; 159 | else if (touchInfo.state == TouchMoving && touchInfo.tapType == TapNone && tapped_inside(touchInfo, 0, 140, 1280, 720)) 160 | { 161 | int lastPosition = ((strcmp(cwd, ROOT_PATH) == 0? (fileCount - 1) : fileCount)); 162 | if (lastPosition < 8) 163 | return; 164 | position = initialPosition + floor(((double) touchInfo.firstTouch.py - (double) touchInfo.prevTouch.py) / 73); 165 | 166 | if (position < 7) 167 | position = 7; 168 | else if (position >= lastPosition) 169 | position = lastPosition; 170 | } 171 | else if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 172 | { 173 | if (tapped_inside(touchInfo, (1260 - 64), 58, (1260 - 64) + 64, (58 + 64))) 174 | { 175 | if (MENU_DEFAULT_STATE == MENU_STATE_OPTIONS) 176 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 177 | else 178 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 179 | } 180 | else if (tapped_inside(touchInfo, 20, 66, 68, 114)) 181 | { 182 | menubar_x = -400; 183 | MENU_DEFAULT_STATE = MENU_STATE_MENUBAR; 184 | } 185 | else if (touchInfo.firstTouch.py >= 140) 186 | { 187 | int tapped_selection = floor(((double) touchInfo.firstTouch.py - 140) / 73); 188 | 189 | if (position > 7) 190 | tapped_selection += position - 7; 191 | 192 | position = tapped_selection; 193 | 194 | if ((touchInfo.firstTouch.px >= 0) && (touchInfo.firstTouch.px <= 80 )) 195 | { 196 | wait(1); 197 | Menu_HandleMultiSelect(); 198 | } 199 | else 200 | { 201 | if ((strcmp(cwd, ROOT_PATH) != 0 && position == 0) || touchInfo.tapType == TapShort) 202 | { 203 | wait(1); 204 | Dirbrowse_OpenFile(); 205 | } 206 | else if (touchInfo.tapType == TapLong) 207 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 208 | } 209 | } 210 | } 211 | } 212 | 213 | void Menu_Main(void) 214 | { 215 | TouchInfo touchInfo; 216 | Touch_Init(&touchInfo); 217 | 218 | Dirbrowse_PopulateFiles(false); 219 | memset(multi_select, 0, sizeof(multi_select)); // Reset all multi selected items 220 | 221 | uint64_t current_time = 0, last_time = 0; 222 | 223 | while(WHBProcIsRunning()) 224 | { 225 | last_time = current_time; 226 | current_time = SDL_GetPerformanceCounter(); 227 | double delta_time = (double)((current_time - last_time) * 1000 / SDL_GetPerformanceFrequency()); 228 | 229 | SDL_ClearScreen(RENDERER, config_dark_theme? BLACK_BG : WHITE); 230 | SDL_RenderClear(RENDERER); 231 | SDL_DrawRect(RENDERER, 0, 0, 1280, 40, config_dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT); // Status bar 232 | SDL_DrawRect(RENDERER, 0, 40, 1280, 100, config_dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT); // Menu bar 233 | 234 | StatusBar_DisplayTime(); 235 | Dirbrowse_DisplayFiles(); 236 | 237 | Input_Update(); 238 | Touch_Process(&touchInfo); 239 | uint32_t kDown = Input_KeysDown(); 240 | 241 | if (MENU_DEFAULT_STATE == MENU_STATE_HOME) 242 | Menu_ControlHome(kDown, touchInfo); 243 | else if (MENU_DEFAULT_STATE == MENU_STATE_OPTIONS) 244 | { 245 | Menu_DisplayOptions(); 246 | Menu_ControlOptions(kDown, touchInfo); 247 | } 248 | else if (MENU_DEFAULT_STATE == MENU_STATE_PROPERTIES) 249 | { 250 | Menu_DisplayProperties(); 251 | Menu_ControlProperties(kDown, touchInfo); 252 | } 253 | else if (MENU_DEFAULT_STATE == MENU_STATE_DELETE_DIALOG) 254 | { 255 | Menu_DisplayDeleteDialog(); 256 | Menu_ControlDeleteDialog(kDown, touchInfo); 257 | } 258 | else if (MENU_DEFAULT_STATE == MENU_STATE_MENUBAR) 259 | { 260 | Menu_DisplayMenuBar(); 261 | AnimateMenuBar(delta_time); 262 | Menu_ControlMenuBar(kDown, touchInfo); 263 | } 264 | else if (MENU_DEFAULT_STATE == MENU_STATE_SETTINGS) 265 | Menu_DisplaySettings(); 266 | 267 | SDL_RenderPresent(RENDERER); 268 | } 269 | } -------------------------------------------------------------------------------- /source/textures.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "SDL_helper.h" 3 | #include "textures.h" 4 | 5 | void Textures_Load(void) 6 | { 7 | SDL_LoadImage(RENDERER, &icon_app, "romfs:/res/drawable/ic_fso_type_executable.png"); 8 | SDL_LoadImage(RENDERER, &icon_archive, "romfs:/res/drawable/ic_fso_type_compress.png"); 9 | SDL_LoadImage(RENDERER, &icon_audio, "romfs:/res/drawable/ic_fso_type_audio.png"); 10 | SDL_LoadImage(RENDERER, &icon_dir, "romfs:/res/drawable/ic_fso_folder.png"); 11 | SDL_LoadImage(RENDERER, &icon_dir_dark, "romfs:/res/drawable/ic_fso_folder_dark.png"); 12 | SDL_LoadImage(RENDERER, &icon_doc, "romfs:/res/drawable/ic_fso_type_document.png"); 13 | SDL_LoadImage(RENDERER, &icon_file, "romfs:/res/drawable/ic_fso_default.png"); 14 | SDL_LoadImage(RENDERER, &icon_image, "romfs:/res/drawable/ic_fso_type_image.png"); 15 | SDL_LoadImage(RENDERER, &icon_text, "romfs:/res/drawable/ic_fso_type_text.png"); 16 | SDL_LoadImage(RENDERER, &icon_check, "romfs:/res/drawable/btn_material_light_check_on_normal.png"); 17 | SDL_LoadImage(RENDERER, &icon_check_dark, "romfs:/res/drawable/btn_material_light_check_on_normal_dark.png"); 18 | SDL_LoadImage(RENDERER, &icon_uncheck, "romfs:/res/drawable/btn_material_light_check_off_normal.png"); 19 | SDL_LoadImage(RENDERER, &icon_uncheck_dark, "romfs:/res/drawable/btn_material_light_check_off_normal_dark.png"); 20 | SDL_LoadImage(RENDERER, &dialog, "romfs:/res/drawable/ic_material_dialog.png"); 21 | SDL_LoadImage(RENDERER, &options_dialog, "romfs:/res/drawable/ic_material_options_dialog.png"); 22 | SDL_LoadImage(RENDERER, &properties_dialog, "romfs:/res/drawable/ic_material_properties_dialog.png"); 23 | SDL_LoadImage(RENDERER, &dialog_dark, "romfs:/res/drawable/ic_material_dialog_dark.png"); 24 | SDL_LoadImage(RENDERER, &options_dialog_dark, "romfs:/res/drawable/ic_material_options_dialog_dark.png"); 25 | SDL_LoadImage(RENDERER, &properties_dialog_dark, "romfs:/res/drawable/ic_material_properties_dialog_dark.png"); 26 | SDL_LoadImage(RENDERER, &bg_header, "romfs:/res/drawable/bg_header.png"); 27 | SDL_LoadImage(RENDERER, &icon_settings, "romfs:/res/drawable/ic_material_light_settings.png"); 28 | SDL_LoadImage(RENDERER, &icon_sd, "romfs:/res/drawable/ic_material_light_sdcard.png"); 29 | SDL_LoadImage(RENDERER, &icon_secure, "romfs:/res/drawable/ic_material_light_secure.png"); 30 | SDL_LoadImage(RENDERER, &icon_settings_dark, "romfs:/res/drawable/ic_material_light_settings_dark.png"); 31 | SDL_LoadImage(RENDERER, &icon_sd_dark, "romfs:/res/drawable/ic_material_light_sdcard_dark.png"); 32 | SDL_LoadImage(RENDERER, &icon_secure_dark, "romfs:/res/drawable/ic_material_light_secure_dark.png"); 33 | SDL_LoadImage(RENDERER, &icon_radio_off, "romfs:/res/drawable/btn_material_light_radio_off_normal.png"); 34 | SDL_LoadImage(RENDERER, &icon_radio_on, "romfs:/res/drawable/btn_material_light_radio_on_normal.png"); 35 | SDL_LoadImage(RENDERER, &icon_radio_dark_off, "romfs:/res/drawable/btn_material_light_radio_off_normal_dark.png"); 36 | SDL_LoadImage(RENDERER, &icon_radio_dark_on, "romfs:/res/drawable/btn_material_light_radio_on_normal_dark.png"); 37 | SDL_LoadImage(RENDERER, &icon_toggle_on, "romfs:/res/drawable/btn_material_light_toggle_on_normal.png"); 38 | SDL_LoadImage(RENDERER, &icon_toggle_dark_on, "romfs:/res/drawable/btn_material_light_toggle_on_normal_dark.png"); 39 | SDL_LoadImage(RENDERER, &icon_toggle_off, "romfs:/res/drawable/btn_material_light_toggle_off_normal.png"); 40 | SDL_LoadImage(RENDERER, &default_artwork, "romfs:/res/drawable/default_artwork.png"); 41 | SDL_LoadImage(RENDERER, &default_artwork_blur, "romfs:/res/drawable/default_artwork_blur.png"); 42 | SDL_LoadImage(RENDERER, &btn_play, "romfs:/res/drawable/btn_playback_play.png"); 43 | SDL_LoadImage(RENDERER, &btn_pause, "romfs:/res/drawable/btn_playback_pause.png"); 44 | SDL_LoadImage(RENDERER, &btn_rewind, "romfs:/res/drawable/btn_playback_rewind.png"); 45 | SDL_LoadImage(RENDERER, &btn_forward, "romfs:/res/drawable/btn_playback_forward.png"); 46 | SDL_LoadImage(RENDERER, &btn_repeat, "romfs:/res/drawable/btn_playback_repeat.png"); 47 | SDL_LoadImage(RENDERER, &btn_shuffle, "romfs:/res/drawable/btn_playback_shuffle.png"); 48 | SDL_LoadImage(RENDERER, &btn_repeat_overlay, "romfs:/res/drawable/btn_playback_repeat_overlay.png"); 49 | SDL_LoadImage(RENDERER, &btn_shuffle_overlay, "romfs:/res/drawable/btn_playback_shuffle_overlay.png"); 50 | SDL_LoadImage(RENDERER, &icon_nav_drawer, "romfs:/res/drawable/ic_material_light_navigation_drawer.png"); 51 | SDL_LoadImage(RENDERER, &icon_actions, "romfs:/res/drawable/ic_material_light_contextual_action.png"); 52 | SDL_LoadImage(RENDERER, &icon_back, "romfs:/res/drawable/ic_arrow_back_normal.png"); 53 | SDL_LoadImage(RENDERER, &icon_accept, "romfs:/res/drawable/ic_material_light_accept.png"); 54 | SDL_LoadImage(RENDERER, &icon_accept_dark, "romfs:/res/drawable/ic_material_light_accept_dark.png"); 55 | SDL_LoadImage(RENDERER, &icon_remove, "romfs:/res/drawable/ic_material_light_remove.png"); 56 | SDL_LoadImage(RENDERER, &icon_remove_dark, "romfs:/res/drawable/ic_material_light_remove_dark.png"); 57 | SDL_LoadImage(RENDERER, &battery_20, "romfs:/res/drawable/battery_20.png"); 58 | SDL_LoadImage(RENDERER, &battery_20_charging, "romfs:/res/drawable/battery_20_charging.png"); 59 | SDL_LoadImage(RENDERER, &battery_30, "romfs:/res/drawable/battery_30.png"); 60 | SDL_LoadImage(RENDERER, &battery_30_charging, "romfs:/res/drawable/battery_30_charging.png"); 61 | SDL_LoadImage(RENDERER, &battery_50, "romfs:/res/drawable/battery_50.png"); 62 | SDL_LoadImage(RENDERER, &battery_50_charging, "romfs:/res/drawable/battery_50_charging.png"); 63 | SDL_LoadImage(RENDERER, &battery_60, "romfs:/res/drawable/battery_60.png"); 64 | SDL_LoadImage(RENDERER, &battery_60_charging, "romfs:/res/drawable/battery_60_charging.png"); 65 | SDL_LoadImage(RENDERER, &battery_80, "romfs:/res/drawable/battery_80.png"); 66 | SDL_LoadImage(RENDERER, &battery_80_charging, "romfs:/res/drawable/battery_80_charging.png"); 67 | SDL_LoadImage(RENDERER, &battery_90, "romfs:/res/drawable/battery_90.png"); 68 | SDL_LoadImage(RENDERER, &battery_90_charging, "romfs:/res/drawable/battery_90_charging.png"); 69 | SDL_LoadImage(RENDERER, &battery_full, "romfs:/res/drawable/battery_full.png"); 70 | SDL_LoadImage(RENDERER, &battery_full_charging, "romfs:/res/drawable/battery_full_charging.png"); 71 | SDL_LoadImage(RENDERER, &battery_low, "romfs:/res/drawable/battery_low.png"); 72 | SDL_LoadImage(RENDERER, &battery_unknown, "romfs:/res/drawable/battery_unknown.png"); 73 | SDL_LoadImage(RENDERER, &icon_lock, "romfs:/res/drawable/ic_material_dialog_fs_locked.png"); 74 | } 75 | 76 | void Textures_Free(void) 77 | { 78 | SDL_DestroyTexture(icon_lock); 79 | SDL_DestroyTexture(battery_unknown); 80 | SDL_DestroyTexture(battery_low); 81 | SDL_DestroyTexture(battery_full_charging); 82 | SDL_DestroyTexture(battery_full); 83 | SDL_DestroyTexture(battery_90_charging); 84 | SDL_DestroyTexture(battery_80_charging); 85 | SDL_DestroyTexture(battery_80); 86 | SDL_DestroyTexture(battery_60_charging); 87 | SDL_DestroyTexture(battery_60); 88 | SDL_DestroyTexture(battery_50_charging); 89 | SDL_DestroyTexture(battery_50); 90 | SDL_DestroyTexture(battery_30_charging); 91 | SDL_DestroyTexture(battery_30); 92 | SDL_DestroyTexture(battery_20_charging); 93 | SDL_DestroyTexture(battery_20); 94 | SDL_DestroyTexture(icon_remove_dark); 95 | SDL_DestroyTexture(icon_remove); 96 | SDL_DestroyTexture(icon_accept_dark); 97 | SDL_DestroyTexture(icon_accept); 98 | SDL_DestroyTexture(icon_back); 99 | SDL_DestroyTexture(icon_actions); 100 | SDL_DestroyTexture(icon_nav_drawer); 101 | SDL_DestroyTexture(btn_shuffle_overlay); 102 | SDL_DestroyTexture(btn_repeat_overlay); 103 | SDL_DestroyTexture(btn_shuffle); 104 | SDL_DestroyTexture(btn_repeat); 105 | SDL_DestroyTexture(btn_forward); 106 | SDL_DestroyTexture(btn_rewind); 107 | SDL_DestroyTexture(btn_pause); 108 | SDL_DestroyTexture(btn_play); 109 | SDL_DestroyTexture(default_artwork_blur); 110 | SDL_DestroyTexture(default_artwork); 111 | SDL_DestroyTexture(icon_toggle_off); 112 | SDL_DestroyTexture(icon_toggle_dark_on); 113 | SDL_DestroyTexture(icon_toggle_on); 114 | SDL_DestroyTexture(icon_radio_dark_on); 115 | SDL_DestroyTexture(icon_radio_dark_off); 116 | SDL_DestroyTexture(icon_radio_on); 117 | SDL_DestroyTexture(icon_radio_off); 118 | SDL_DestroyTexture(icon_secure_dark); 119 | SDL_DestroyTexture(icon_sd_dark); 120 | SDL_DestroyTexture(icon_settings_dark); 121 | SDL_DestroyTexture(icon_secure); 122 | SDL_DestroyTexture(icon_sd); 123 | SDL_DestroyTexture(icon_settings); 124 | SDL_DestroyTexture(bg_header); 125 | SDL_DestroyTexture(properties_dialog_dark); 126 | SDL_DestroyTexture(options_dialog_dark); 127 | SDL_DestroyTexture(dialog_dark); 128 | SDL_DestroyTexture(properties_dialog); 129 | SDL_DestroyTexture(options_dialog); 130 | SDL_DestroyTexture(dialog); 131 | SDL_DestroyTexture(icon_uncheck_dark); 132 | SDL_DestroyTexture(icon_uncheck); 133 | SDL_DestroyTexture(icon_check_dark); 134 | SDL_DestroyTexture(icon_check); 135 | SDL_DestroyTexture(icon_text); 136 | SDL_DestroyTexture(icon_image); 137 | SDL_DestroyTexture(icon_file); 138 | SDL_DestroyTexture(icon_doc); 139 | SDL_DestroyTexture(icon_dir_dark); 140 | SDL_DestroyTexture(icon_dir); 141 | SDL_DestroyTexture(icon_audio); 142 | SDL_DestroyTexture(icon_archive); 143 | SDL_DestroyTexture(icon_app); 144 | } -------------------------------------------------------------------------------- /source/minizip/ioapi.c: -------------------------------------------------------------------------------- 1 | /* ioapi.h -- IO base function header for compress/uncompress .zip 2 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) 3 | 4 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) 5 | 6 | Modifications for Zip64 support 7 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) 8 | 9 | For more info read MiniZip_info.txt 10 | 11 | */ 12 | 13 | #if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) 14 | #define _CRT_SECURE_NO_WARNINGS 15 | #endif 16 | 17 | #if defined(__APPLE__) || defined(IOAPI_NO_64) 18 | // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions 19 | #define FOPEN_FUNC(filename, mode) fopen(filename, mode) 20 | #define FTELLO_FUNC(stream) ftello(stream) 21 | #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) 22 | #else 23 | #define FOPEN_FUNC(filename, mode) fopen(filename, mode) 24 | #define FTELLO_FUNC(stream) ftello(stream) 25 | #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) 26 | #endif 27 | 28 | 29 | #include "ioapi.h" 30 | 31 | voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) 32 | { 33 | if (pfilefunc->zfile_func64.zopen64_file != NULL) 34 | return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); 35 | else 36 | { 37 | return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); 38 | } 39 | } 40 | 41 | long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) 42 | { 43 | if (pfilefunc->zfile_func64.zseek64_file != NULL) 44 | return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); 45 | else 46 | { 47 | uLong offsetTruncated = (uLong)offset; 48 | if (offsetTruncated != offset) 49 | return -1; 50 | else 51 | return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); 52 | } 53 | } 54 | 55 | ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) 56 | { 57 | if (pfilefunc->zfile_func64.zseek64_file != NULL) 58 | return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); 59 | else 60 | { 61 | uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); 62 | if ((tell_uLong) == MAXU32) 63 | return (ZPOS64_T)-1; 64 | else 65 | return tell_uLong; 66 | } 67 | } 68 | 69 | void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) 70 | { 71 | p_filefunc64_32->zfile_func64.zopen64_file = NULL; 72 | p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; 73 | p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; 74 | p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; 75 | p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; 76 | p_filefunc64_32->zfile_func64.ztell64_file = NULL; 77 | p_filefunc64_32->zfile_func64.zseek64_file = NULL; 78 | p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; 79 | p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; 80 | p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; 81 | p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; 82 | p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; 83 | } 84 | 85 | 86 | 87 | static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); 88 | static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); 89 | static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); 90 | static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); 91 | static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); 92 | static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); 93 | static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); 94 | 95 | static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) 96 | { 97 | FILE* file = NULL; 98 | const char* mode_fopen = NULL; 99 | if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) 100 | mode_fopen = "rb"; 101 | else 102 | if (mode & ZLIB_FILEFUNC_MODE_EXISTING) 103 | mode_fopen = "r+b"; 104 | else 105 | if (mode & ZLIB_FILEFUNC_MODE_CREATE) 106 | mode_fopen = "wb"; 107 | 108 | if ((filename!=NULL) && (mode_fopen != NULL)) 109 | file = fopen(filename, mode_fopen); 110 | return file; 111 | } 112 | 113 | static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) 114 | { 115 | FILE* file = NULL; 116 | const char* mode_fopen = NULL; 117 | if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) 118 | mode_fopen = "rb"; 119 | else 120 | if (mode & ZLIB_FILEFUNC_MODE_EXISTING) 121 | mode_fopen = "r+b"; 122 | else 123 | if (mode & ZLIB_FILEFUNC_MODE_CREATE) 124 | mode_fopen = "wb"; 125 | 126 | if ((filename!=NULL) && (mode_fopen != NULL)) 127 | file = FOPEN_FUNC((const char*)filename, mode_fopen); 128 | return file; 129 | } 130 | 131 | 132 | static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) 133 | { 134 | uLong ret; 135 | ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); 136 | return ret; 137 | } 138 | 139 | static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) 140 | { 141 | uLong ret; 142 | ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); 143 | return ret; 144 | } 145 | 146 | static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) 147 | { 148 | long ret; 149 | ret = ftell((FILE *)stream); 150 | return ret; 151 | } 152 | 153 | 154 | static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) 155 | { 156 | ZPOS64_T ret; 157 | ret = FTELLO_FUNC((FILE *)stream); 158 | return ret; 159 | } 160 | 161 | static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) 162 | { 163 | int fseek_origin=0; 164 | long ret; 165 | switch (origin) 166 | { 167 | case ZLIB_FILEFUNC_SEEK_CUR : 168 | fseek_origin = SEEK_CUR; 169 | break; 170 | case ZLIB_FILEFUNC_SEEK_END : 171 | fseek_origin = SEEK_END; 172 | break; 173 | case ZLIB_FILEFUNC_SEEK_SET : 174 | fseek_origin = SEEK_SET; 175 | break; 176 | default: return -1; 177 | } 178 | ret = 0; 179 | if (fseek((FILE *)stream, offset, fseek_origin) != 0) 180 | ret = -1; 181 | return ret; 182 | } 183 | 184 | static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) 185 | { 186 | int fseek_origin=0; 187 | long ret; 188 | switch (origin) 189 | { 190 | case ZLIB_FILEFUNC_SEEK_CUR : 191 | fseek_origin = SEEK_CUR; 192 | break; 193 | case ZLIB_FILEFUNC_SEEK_END : 194 | fseek_origin = SEEK_END; 195 | break; 196 | case ZLIB_FILEFUNC_SEEK_SET : 197 | fseek_origin = SEEK_SET; 198 | break; 199 | default: return -1; 200 | } 201 | ret = 0; 202 | 203 | if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) 204 | ret = -1; 205 | 206 | return ret; 207 | } 208 | 209 | 210 | static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) 211 | { 212 | int ret; 213 | ret = fclose((FILE *)stream); 214 | return ret; 215 | } 216 | 217 | static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) 218 | { 219 | int ret; 220 | ret = ferror((FILE *)stream); 221 | return ret; 222 | } 223 | 224 | void fill_fopen_filefunc (pzlib_filefunc_def) 225 | zlib_filefunc_def* pzlib_filefunc_def; 226 | { 227 | pzlib_filefunc_def->zopen_file = fopen_file_func; 228 | pzlib_filefunc_def->zread_file = fread_file_func; 229 | pzlib_filefunc_def->zwrite_file = fwrite_file_func; 230 | pzlib_filefunc_def->ztell_file = ftell_file_func; 231 | pzlib_filefunc_def->zseek_file = fseek_file_func; 232 | pzlib_filefunc_def->zclose_file = fclose_file_func; 233 | pzlib_filefunc_def->zerror_file = ferror_file_func; 234 | pzlib_filefunc_def->opaque = NULL; 235 | } 236 | 237 | void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) 238 | { 239 | pzlib_filefunc_def->zopen64_file = fopen64_file_func; 240 | pzlib_filefunc_def->zread_file = fread_file_func; 241 | pzlib_filefunc_def->zwrite_file = fwrite_file_func; 242 | pzlib_filefunc_def->ztell64_file = ftell64_file_func; 243 | pzlib_filefunc_def->zseek64_file = fseek64_file_func; 244 | pzlib_filefunc_def->zclose_file = fclose_file_func; 245 | pzlib_filefunc_def->zerror_file = ferror_file_func; 246 | pzlib_filefunc_def->opaque = NULL; 247 | } 248 | -------------------------------------------------------------------------------- /source/osk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "config.h" 7 | #include "osk.h" 8 | #include "SDL_helper.h" 9 | #include "status_bar.h" 10 | #include "touch_helper.h" 11 | #include "input_helper.h" 12 | #include "textures.h" 13 | #include "utils.h" 14 | 15 | #define OSK_BG_COLOUR_LIGHT SDL_MakeColour(236, 239, 241, 255) 16 | #define OSK_BG_COLOUR_DARK SDL_MakeColour(39, 50, 56, 255) 17 | #define OSK_SELECTED_COLOUR SDL_MakeColour(77, 182, 172, 255) 18 | 19 | static int osk_index = 0; 20 | 21 | static const char *osk_textdisp[] = 22 | { 23 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 24 | "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", 25 | "a", "s", "d", "f", "g", "h", "j", "k", "l", "z", 26 | "x", "c", "v", "b", "n", "m", ".", "-", "_", "[_]", 27 | "!", "@", "#", "$", "%", "^", "&", "*", "(", ")" 28 | }; 29 | 30 | static const char *osk_textdisp_shift[] = 31 | { 32 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 33 | "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", 34 | "A", "S", "D", "F", "G", "H", "J", "K", "L", "Z", 35 | "X", "C", "V", "B", "N", "M", ",", "\"", "'", "[_]", 36 | "{", "}", "|", "\\", "/", "?", "<", ">", "[", "]" 37 | }; 38 | 39 | static void OSK_DeleteChar(char *str, int i) 40 | { 41 | int len = strlen(str); 42 | 43 | for (; i < len - 1 ; i++) 44 | str[i] = str[i+1]; 45 | 46 | str[i] = '\0'; 47 | } 48 | 49 | static void OSK_ResetIndex(void) 50 | { 51 | if (strlen(osk_buffer) != 0) 52 | osk_index -= 1; 53 | else 54 | osk_index = 0; 55 | } 56 | 57 | static void OSK_BlinkText(int fade, int x, int y) 58 | { 59 | SDL_Color FADE_WHITE, FADE_BLACK; 60 | 61 | FADE_WHITE = SDL_MakeColour(255, 255, 255, fade); 62 | FADE_BLACK = SDL_MakeColour(0, 0, 0, fade); 63 | SDL_DrawText(RENDERER, Roboto_large, x, y, config_dark_theme? FADE_WHITE : FADE_BLACK, "|"); 64 | } 65 | 66 | static void OSK_HandleDelete(void) 67 | { 68 | OSK_DeleteChar(osk_buffer, osk_index == 0? osk_index : osk_index - 1); 69 | 70 | if (strlen(osk_buffer) != 0) 71 | osk_index -= 1; 72 | else 73 | osk_index = 0; 74 | } 75 | 76 | static void OSK_HandleAppend(bool shift, bool caps, int x, int y) 77 | { 78 | if (strcasecmp((shift || caps)? osk_textdisp_shift[x + y * 10] : osk_textdisp[x + y * 10], "[_]") == 0) 79 | Utils_AppendArr(osk_buffer, " ", osk_index); 80 | else if (strcasecmp((shift || caps)? osk_textdisp_shift[x + y * 10] : osk_textdisp[x + y * 10], "[x]") == 0) 81 | OSK_HandleDelete(); 82 | else 83 | Utils_AppendArr(osk_buffer, (shift || caps)? osk_textdisp_shift[x + y * 10] : osk_textdisp[x + y * 10], osk_index); 84 | 85 | osk_index += 1; 86 | shift = false; 87 | } 88 | 89 | void OSK_Display(char *title, char *msg) 90 | { 91 | int text_width = 0, text_height = 0; 92 | TTF_SizeText(Roboto_OSK, " Q W E R T Y U I O P ", &text_width, &text_height); 93 | 94 | int title_height = 0; 95 | TTF_SizeText(Roboto_large, title, NULL, &title_height); 96 | 97 | int cursor_width = 0; 98 | TTF_SizeText(Roboto_large, "|", &cursor_width, NULL); 99 | 100 | char buf2[256]; 101 | int buf_width = 0, buf_height = 0, buf_width_curr; 102 | 103 | OSK_ResetIndex(); 104 | 105 | if (strlen(msg) != 0) 106 | { 107 | osk_index = strlen(msg); 108 | strcpy(osk_buffer, msg); 109 | } 110 | 111 | TouchInfo touchInfo; 112 | Touch_Init(&touchInfo); 113 | 114 | int osk_pos_x = 0, osk_pos_y = 0, transp = 255; 115 | bool osk_text_shift = false, osk_text_caps = false; 116 | 117 | while(WHBProcIsRunning()) 118 | { 119 | SDL_ClearScreen(RENDERER, config_dark_theme? BLACK_BG : WHITE); 120 | SDL_DrawRect(RENDERER, 0, 0, 1280, 40, config_dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT); // Status bar 121 | SDL_DrawRect(RENDERER, 0, 40, 1280, 100, config_dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT); // Menu bar 122 | 123 | SDL_DrawImage(RENDERER, icon_back, 40, 66); 124 | 125 | SDL_DrawText(RENDERER, Roboto_large, 128, 40 + ((100 - title_height)/2), WHITE, title); 126 | 127 | SDL_DrawRect(RENDERER, 0, (660 - (text_height * 5)) - 30, 1280, 720 - ((660 - (text_height * 5)) - 30), config_dark_theme? OSK_BG_COLOUR_DARK : OSK_BG_COLOUR_LIGHT); 128 | 129 | if (strlen(osk_buffer) != 0) 130 | { 131 | TTF_SizeText(Roboto_large, osk_buffer, &buf_width, &buf_height); 132 | snprintf(buf2, osk_index + 1, osk_buffer); 133 | TTF_SizeText(Roboto_large, buf2, &buf_width_curr, NULL); 134 | SDL_DrawTextf(RENDERER, Roboto_large, (1280 - buf_width) / 2, 210, config_dark_theme? WHITE : BLACK, "%s", osk_buffer); 135 | } 136 | 137 | OSK_BlinkText(transp, (((1280 - buf_width) / 2) + (buf_width_curr + cursor_width)) - 11, 210); 138 | transp -= 14; 139 | 140 | for (int x = 0; x <= MAX_X; x++) 141 | { 142 | for (int y = 0; y <= MAX_Y; y++) 143 | { 144 | if (osk_text_shift || osk_text_caps) 145 | { 146 | if (config_dark_theme) 147 | SDL_DrawText(RENDERER, Roboto_OSK, ((1280 - (text_width * 2)) / 2) + (100 * x), (660 - (text_height * 5)) + (60 * y), (x == osk_pos_x && y == osk_pos_y)? 148 | TITLE_COLOUR_DARK : WHITE, osk_textdisp_shift[x + y * 10]); 149 | else 150 | SDL_DrawText(RENDERER, Roboto_OSK, ((1280 - (text_width * 2)) / 2) + (100 * x), (660 - (text_height * 5)) + (60 * y), (x == osk_pos_x && y == osk_pos_y)? 151 | TITLE_COLOUR : BLACK, osk_textdisp_shift[x + y * 10]); 152 | } 153 | else 154 | { 155 | if (config_dark_theme) 156 | SDL_DrawText(RENDERER, Roboto_OSK, ((1280 - (text_width * 2)) / 2) + (100 * x), (660 - (text_height * 5)) + (60 * y), (x == osk_pos_x && y == osk_pos_y)? 157 | TITLE_COLOUR_DARK : WHITE, osk_textdisp[x + y * 10]); 158 | else 159 | SDL_DrawText(RENDERER, Roboto_OSK, ((1280 - (text_width * 2)) / 2) + (100 * x), (660 - (text_height * 5)) + (60 * y), (x == osk_pos_x && y == osk_pos_y)? 160 | TITLE_COLOUR : BLACK, osk_textdisp[x + y * 10]); 161 | } 162 | } 163 | } 164 | 165 | SDL_DrawImage(RENDERER, config_dark_theme? icon_remove_dark : icon_remove, 1190, 480); 166 | SDL_DrawImage(RENDERER, config_dark_theme? icon_accept_dark : icon_accept, 1190, 600); 167 | 168 | StatusBar_DisplayTime(); 169 | 170 | SDL_RenderPresent(RENDERER); 171 | 172 | Input_Update(); 173 | Touch_Process(&touchInfo); 174 | uint32_t kDown = Input_KeysDown(); 175 | 176 | if (kDown & KEY_LEFT) 177 | osk_pos_x--; 178 | else if (kDown & KEY_RIGHT) 179 | osk_pos_x++; 180 | 181 | if (kDown & KEY_UP) 182 | osk_pos_y--; 183 | else if (kDown & KEY_DOWN) 184 | osk_pos_y++; 185 | 186 | Utils_SetMin(&osk_pos_x, MAX_X, 0); 187 | Utils_SetMax(&osk_pos_x, 0, MAX_X); 188 | 189 | Utils_SetMin(&osk_pos_y, MAX_Y, 0); 190 | Utils_SetMax(&osk_pos_y, 0, MAX_Y); 191 | 192 | if (kDown & KEY_L) 193 | { 194 | if (strlen(osk_buffer) != 0) 195 | { 196 | if (osk_index > 0) 197 | osk_index--; 198 | else 199 | osk_index = 0; 200 | } 201 | } 202 | else if (kDown & KEY_R) 203 | { 204 | if (strlen(osk_buffer) != 0) 205 | { 206 | if (osk_index < strlen(osk_buffer)) 207 | osk_index++; 208 | else 209 | osk_index = strlen(osk_buffer); 210 | } 211 | } 212 | 213 | if (kDown & KEY_ZL) 214 | { 215 | if (osk_text_caps) 216 | { 217 | osk_text_shift = false; 218 | osk_text_caps = false; 219 | } 220 | else 221 | osk_text_shift = !osk_text_shift; 222 | } 223 | else if (kDown & KEY_ZR) 224 | { 225 | if (osk_text_shift) 226 | { 227 | osk_text_shift = false; 228 | osk_text_caps = false; 229 | } 230 | else 231 | osk_text_caps = !osk_text_caps; 232 | } 233 | 234 | Utils_SetMax(&transp, 0, 255); 235 | Utils_SetMin(&transp, 255, 0); 236 | 237 | if (kDown & KEY_A) 238 | OSK_HandleAppend(osk_text_shift, osk_text_caps, osk_pos_x, osk_pos_y); 239 | else if (kDown & KEY_B) 240 | OSK_HandleDelete(); 241 | 242 | if (kDown & KEY_PLUS) 243 | break; 244 | else if (kDown & KEY_MINUS) 245 | { 246 | osk_buffer[0] = '\0'; 247 | break; 248 | } 249 | 250 | if (touchInfo.state == TouchStart) 251 | { 252 | int touch_selection_y = floor(((double) touchInfo.firstTouch.py - (660 - (text_height * 5))) / 60); 253 | int touch_selection_x = floor(((double) touchInfo.firstTouch.px - ((1280 - (text_width * 2)) / 2)) / 100); 254 | 255 | if (touch_selection_y >= (660 - (text_height * 5)) && touch_selection_y <= ((660 - (text_height * 5)) + (60 * MAX_Y))) 256 | osk_pos_y = touch_selection_y; 257 | if (touch_selection_x >= ((1280 - (text_width * 2)) / 2) && touch_selection_x <= (((1280 - (text_width * 2)) / 2) + (100 * MAX_X))) 258 | osk_pos_x = touch_selection_x; 259 | } 260 | if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 261 | { 262 | if (tapped_inside(touchInfo, 40, 66, 108, 114)) 263 | { 264 | osk_buffer[0] = '\0'; 265 | break; 266 | } 267 | else if (tapped_inside(touchInfo, 1190, 480, 1250, 540)) 268 | OSK_HandleDelete(); 269 | else if (tapped_inside(touchInfo, 1190, 600, 1250, 660)) 270 | break; 271 | else if (((touchInfo.firstTouch.px >= ((1280 - (text_width * 2)) / 2)) && (touchInfo.firstTouch.px <= (((1280 - (text_width * 2)) / 2) + (100 * (MAX_X + 1))))) 272 | && ((touchInfo.firstTouch.py >= (660 - (text_height * 5))) && (touchInfo.firstTouch.py <= ((660 - (text_height * 5)) + (60 * (MAX_Y + 1)))))) 273 | { 274 | int touch_selection_y = floor(((double) touchInfo.firstTouch.py - (660 - (text_height * 5))) / 60); 275 | int touch_selection_x = floor(((double) touchInfo.firstTouch.px - ((1280 - (text_width * 2)) / 2)) / 100); 276 | 277 | if (touch_selection_y >= 0 && touch_selection_y <= MAX_Y) 278 | osk_pos_y = touch_selection_y; 279 | if (touch_selection_x >= 0 && touch_selection_x <= MAX_X) 280 | osk_pos_x = touch_selection_x; 281 | 282 | OSK_HandleAppend(osk_text_shift, osk_text_caps, osk_pos_x, osk_pos_y); 283 | } 284 | } 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /source/menus/menu_music.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | #include "dirbrowse.h" 9 | #include "fs.h" 10 | #include "menu_music.h" 11 | #include "SDL_helper.h" 12 | #include "status_bar.h" 13 | #include "textures.h" 14 | #include "touch_helper.h" 15 | #include "input_helper.h" 16 | #include "utils.h" 17 | 18 | #define MUSIC_GENRE_COLOUR SDL_MakeColour(97, 97, 97, 255) 19 | #define MUSIC_STATUS_BG_COLOUR SDL_MakeColour(43, 53, 61, 255) 20 | #define MUSIC_SEPARATOR_COLOUR SDL_MakeColour(34, 41, 48, 255) 21 | 22 | typedef enum 23 | { 24 | MUSIC_STATE_NONE, // 0 25 | MUSIC_STATE_REPEAT, // 1 26 | MUSIC_STATE_SHUFFLE // 2 27 | } Music_State; 28 | 29 | static char playlist[1024][512], title[128]; 30 | static int count = 0, selection = 0, state = 0; 31 | static Mix_Music *audio; 32 | 33 | static void Menu_GetMusicList(void) 34 | { 35 | DIR *dir; 36 | struct dirent *entries; 37 | dir = opendir(cwd); 38 | 39 | if (dir != NULL) 40 | { 41 | while ((entries = readdir (dir)) != NULL) 42 | { 43 | if ((strncasecmp(FS_GetFileExt(entries->d_name), "mp3", 3) == 0) || (strncasecmp(FS_GetFileExt(entries->d_name), "ogg", 3) == 0) 44 | || (strncasecmp(FS_GetFileExt(entries->d_name), "wav", 3) == 0)) 45 | { 46 | strcpy(playlist[count], cwd); 47 | strcpy(playlist[count] + strlen(playlist[count]), entries->d_name); 48 | count++; 49 | } 50 | } 51 | 52 | closedir(dir); 53 | } 54 | } 55 | 56 | static int Music_GetCurrentIndex(char *path) 57 | { 58 | for(int i = 0; i < count; ++i) 59 | { 60 | if (!strcmp(playlist[i], path)) 61 | return i; 62 | } 63 | return 0; 64 | } 65 | 66 | static void Music_Play(char *path) 67 | { 68 | audio = Mix_LoadMUS(path); 69 | 70 | if (audio == NULL) 71 | return; 72 | 73 | switch(Mix_GetMusicType(audio)) 74 | { 75 | case MUS_CMD: 76 | break; 77 | case MUS_WAV: 78 | break; 79 | case MUS_MID: 80 | break; 81 | case MUS_MOD: 82 | case MUS_OGG: 83 | case MUS_MP3: 84 | //MP3_Init(path); 85 | //break; 86 | case MUS_NONE: 87 | break; 88 | default: 89 | break; 90 | } 91 | 92 | int ret = 0; 93 | if ((ret = Mix_PlayMusic(audio, 1)) != 0) 94 | return; 95 | 96 | selection = Music_GetCurrentIndex(path); 97 | 98 | strncpy(title, /*strlen(ID3.title) == 0? */strupr(Utils_Basename(path)), /*: strupr(ID3.title), strlen(ID3.title) == 0?*/ strlen(Utils_Basename(path)) + 1 /*: strlen(ID3.title) + 1*/); 99 | } 100 | 101 | static void Music_HandleNext(bool forward, int state) 102 | { 103 | if (state == MUSIC_STATE_NONE) 104 | { 105 | if (forward) 106 | selection++; 107 | else 108 | selection--; 109 | } 110 | else if (state == MUSIC_STATE_SHUFFLE) 111 | { 112 | int old_selection = selection; 113 | time_t t; 114 | srand((unsigned) time(&t)); 115 | selection = rand() % (count - 1); 116 | 117 | if (selection == old_selection) 118 | selection++; 119 | } 120 | 121 | Utils_SetMax(&selection, 0, (count - 1)); 122 | Utils_SetMin(&selection, (count - 1), 0); 123 | 124 | switch(Mix_GetMusicType(audio)) 125 | { 126 | case MUS_MP3: 127 | //MP3_Exit(); 128 | break; 129 | default: 130 | break; 131 | } 132 | 133 | Mix_HaltMusic(); 134 | Mix_FreeMusic(audio); 135 | 136 | Music_Play(playlist[selection]); 137 | } 138 | 139 | static void Music_HandlePause(bool *status) 140 | { 141 | if (*status) 142 | { 143 | Mix_PauseMusic(); 144 | *status = false; 145 | } 146 | else 147 | { 148 | Mix_ResumeMusic(); 149 | *status = true; 150 | } 151 | } 152 | 153 | void Menu_PlayMusic(char *path) 154 | { 155 | Menu_GetMusicList(); 156 | Music_Play(path); 157 | 158 | int title_height = 0; 159 | TTF_SizeText(Roboto_large, title, NULL, &title_height); 160 | 161 | bool isPlaying = true; 162 | 163 | int btn_width = 0, btn_height = 0; 164 | SDL_QueryTexture(btn_pause, NULL, NULL, &btn_width, &btn_height); 165 | 166 | TouchInfo touchInfo; 167 | Touch_Init(&touchInfo); 168 | 169 | bool locked = false; 170 | 171 | while(WHBProcIsRunning()) 172 | { 173 | SDL_ClearScreen(RENDERER, MUSIC_STATUS_BG_COLOUR); 174 | SDL_RenderClear(RENDERER); 175 | 176 | SDL_DrawImage(RENDERER, default_artwork_blur, 0, 0); 177 | SDL_DrawRect(RENDERER, 0, 0, 1280, 40, MUSIC_GENRE_COLOUR); // Status bar 178 | SDL_DrawRect(RENDERER, 0, 140, 1280, 1, MUSIC_SEPARATOR_COLOUR); // Separator 179 | 180 | if (locked) 181 | SDL_DrawImage(RENDERER, icon_lock, 5, 3); 182 | 183 | SDL_DrawImage(RENDERER, icon_back, 40, 66); 184 | 185 | SDL_DrawText(RENDERER, Roboto_large, 128, 40 + ((100 - title_height)/2), WHITE, title); // Audio filename 186 | 187 | SDL_DrawRect(RENDERER, 0, 141, 560, 560, MUSIC_GENRE_COLOUR); // Draw album art background 188 | SDL_DrawImage(RENDERER, default_artwork, 0, 141); // Default album art 189 | 190 | SDL_DrawRect(RENDERER, 570, 141, 710, 559, SDL_MakeColour(45, 48, 50, 255)); // Draw info box (outer) 191 | SDL_DrawRect(RENDERER, 575, 146, 700, 549, SDL_MakeColour(46, 49, 51, 255)); // Draw info box (inner) 192 | 193 | /*if (strlen(ID3.artist) != 0) 194 | SDL_DrawText(RENDERER, Roboto_large, 590, 161, WHITE, ID3.artist); 195 | if (strlen(ID3.album) != 0) 196 | SDL_DrawText(RENDERER, Roboto_large, 590, 201, WHITE, ID3.album); 197 | if (strlen(ID3.year) != 0) 198 | SDL_DrawText(RENDERER, Roboto_large, 590, 241, WHITE, ID3.year); 199 | if (strlen(ID3.genre) != 0) 200 | SDL_DrawText(RENDERER, Roboto_large, 590, 281, WHITE, ID3.genre);*/ 201 | 202 | SDL_DrawCircle(RENDERER, 615 + ((710 - btn_width) / 2), 186 + ((559 - btn_height) / 2), 80, SDL_MakeColour(98, 100, 101, 255)); // Render outer circle 203 | SDL_DrawCircle(RENDERER, (615 + ((710 - btn_width) / 2)), (186 + ((559 - btn_height) / 2)), 60, SDL_MakeColour(46, 49, 51, 255)); // Render inner circle 204 | 205 | if (isPlaying) 206 | SDL_DrawImage(RENDERER, btn_pause, 570 + ((710 - btn_width) / 2), 141 + ((559 - btn_height) / 2)); // Playing 207 | else 208 | SDL_DrawImage(RENDERER, btn_play, 570 + ((710 - btn_width) / 2), 141 + ((559 - btn_height) / 2)); // Paused 209 | 210 | SDL_DrawImage(RENDERER, btn_rewind, (560 + ((710 - btn_width) / 2)) - (btn_width * 2), 141 + ((559 - btn_height) / 2)); // Rewind 211 | SDL_DrawImage(RENDERER, btn_forward, (580 + ((710 - btn_width) / 2)) + (btn_width * 2), 141 + ((559 - btn_height) / 2)); // Forward 212 | SDL_DrawImageScale(RENDERER, state == MUSIC_STATE_SHUFFLE? btn_shuffle_overlay : btn_shuffle, (590 + ((710 - (btn_width - 10)) / 2)) - ((btn_width - 10) * 2), 141 + ((559 - (btn_height - 10)) / 2) + 90, (btn_width - 10), (btn_height - 10)); // Shuffle 213 | SDL_DrawImageScale(RENDERER, state == MUSIC_STATE_REPEAT? btn_repeat_overlay : btn_repeat, (550 + ((710 - (btn_width - 10)) / 2)) + ((btn_width - 10) * 2), 141 + ((559 - (btn_height - 10)) / 2) + 90, (btn_width - 10), (btn_height - 10)); // Repeat 214 | StatusBar_DisplayTime(); 215 | 216 | SDL_RenderPresent(RENDERER); 217 | 218 | Input_Update(); 219 | Touch_Process(&touchInfo); 220 | uint32_t kDown = Input_KeysDown(); 221 | 222 | if (!Mix_PlayingMusic()) 223 | { 224 | wait(1); 225 | 226 | if (state == MUSIC_STATE_NONE) 227 | { 228 | if (count != 0) 229 | Music_HandleNext(true, MUSIC_STATE_NONE); 230 | break; 231 | } 232 | else if (state == MUSIC_STATE_REPEAT) 233 | Music_HandleNext(false, MUSIC_STATE_REPEAT); 234 | else if (state == MUSIC_STATE_SHUFFLE) 235 | { 236 | if (count != 0) 237 | Music_HandleNext(false, MUSIC_STATE_SHUFFLE); 238 | } 239 | } 240 | 241 | if (kDown & KEY_PLUS) 242 | locked = !locked; 243 | 244 | if (kDown & KEY_B) 245 | { 246 | wait(1); 247 | Mix_HaltMusic(); 248 | break; 249 | } 250 | 251 | if (kDown & KEY_A) 252 | Music_HandlePause(&isPlaying); 253 | 254 | if (kDown & KEY_Y) 255 | { 256 | if (state == MUSIC_STATE_REPEAT) 257 | state = MUSIC_STATE_NONE; 258 | else 259 | state = MUSIC_STATE_REPEAT; 260 | } 261 | else if (kDown & KEY_X) 262 | { 263 | if (state == MUSIC_STATE_SHUFFLE) 264 | state = MUSIC_STATE_NONE; 265 | else 266 | state = MUSIC_STATE_SHUFFLE; 267 | } 268 | 269 | if (!locked) 270 | { 271 | if ((kDown & KEY_LEFT) || (kDown & KEY_L)) 272 | { 273 | wait(1); 274 | 275 | if (count != 0) 276 | Music_HandleNext(false, MUSIC_STATE_NONE); 277 | } 278 | else if ((kDown & KEY_RIGHT) || (kDown & KEY_R)) 279 | { 280 | wait(1); 281 | 282 | if (count != 0) 283 | Music_HandleNext(true, MUSIC_STATE_NONE); 284 | } 285 | } 286 | 287 | if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 288 | { 289 | if (tapped_inside(touchInfo, 40, 66, 108, 114)) 290 | { 291 | wait(1); 292 | Mix_HaltMusic(); 293 | break; 294 | } 295 | 296 | if (tapped_inside(touchInfo, 570 + ((710 - btn_width) / 2), 141 + ((559 - btn_height) / 2), (570 + ((710 - btn_width) / 2)) + btn_width, (141 + ((559 - btn_height) / 2) + btn_height))) 297 | Music_HandlePause(&isPlaying); 298 | else if (tapped_inside(touchInfo, (590 + ((710 - (btn_width - 10)) / 2)) - ((btn_width - 10) * 2), 141 + ((559 - (btn_height - 10)) / 2) + 90, ((590 + ((710 - (btn_width - 10)) / 2)) - ((btn_width - 10) * 2)) + (btn_width - 10), (141 + ((559 - (btn_height - 10)) / 2) + 90) + (btn_height - 10))) 299 | { 300 | if (state == MUSIC_STATE_SHUFFLE) 301 | state = MUSIC_STATE_NONE; 302 | else 303 | state = MUSIC_STATE_SHUFFLE; 304 | } 305 | else if (tapped_inside(touchInfo, (550 + ((710 - (btn_width - 10)) / 2)) + ((btn_width - 10) * 2), 141 + ((559 - (btn_height - 10)) / 2) + 90, ((550 + ((710 - (btn_width - 10)) / 2)) + ((btn_width - 10) * 2)) + (btn_width - 10), (141 + ((559 - (btn_height - 10)) / 2) + 90) + (btn_height - 10))) 306 | { 307 | if (state == MUSIC_STATE_REPEAT) 308 | state = MUSIC_STATE_NONE; 309 | else 310 | state = MUSIC_STATE_REPEAT; 311 | } 312 | 313 | if (!locked) 314 | { 315 | if (tapped_inside(touchInfo, (570 + ((710 - btn_width) / 2)) - (btn_width * 2), 141 + ((559 - btn_height) / 2), (570 + ((710 - btn_width) / 2)) - (btn_width * 2) + btn_width, (141 + ((559 - btn_height) / 2) + btn_height))) 316 | { 317 | wait(1); 318 | 319 | if (count != 0) 320 | Music_HandleNext(false, MUSIC_STATE_NONE); 321 | } 322 | else if (tapped_inside(touchInfo, (570 + ((710 - btn_width) / 2)) + (btn_width * 2), 141 + ((559 - btn_height) / 2), (570 + ((710 - btn_width) / 2)) + (btn_width * 2) + btn_width, (141 + ((559 - btn_height) / 2) + btn_height))) 323 | { 324 | wait(1); 325 | 326 | if (count != 0) 327 | Music_HandleNext(true, MUSIC_STATE_NONE); 328 | } 329 | } 330 | } 331 | } 332 | 333 | switch(Mix_GetMusicType(audio)) 334 | { 335 | case MUS_MP3: 336 | //MP3_Exit(); 337 | break; 338 | default: 339 | break; 340 | } 341 | 342 | Mix_FreeMusic(audio); 343 | memset(playlist, 0, sizeof(playlist[0][0]) * 512 * 512); 344 | count = 0; 345 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 346 | } -------------------------------------------------------------------------------- /source/menus/menu_settings.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "config.h" 7 | #include "dirbrowse.h" 8 | #include "menu_settings.h" 9 | #include "SDL_helper.h" 10 | #include "status_bar.h" 11 | #include "textures.h" 12 | #include "touch_helper.h" 13 | #include "utils.h" 14 | 15 | static bool displayAbout; 16 | static int confirm_width = 0, confirm_height = 0; 17 | static int dialog_width = 0, dialog_height = 0; 18 | 19 | static void Save_SortConfig(int selection) 20 | { 21 | switch (selection) 22 | { 23 | case 0: 24 | config_sort_by = 0; 25 | break; 26 | case 1: 27 | config_sort_by = 1; 28 | break; 29 | case 2: 30 | config_sort_by = 2; 31 | break; 32 | case 3: 33 | config_sort_by = 3; 34 | break; 35 | } 36 | 37 | Config_Save(config_dark_theme, config_sort_by); 38 | } 39 | 40 | static void Menu_DisplaySortSettings(void) 41 | { 42 | int selection = 0, max_items = 3, height = 0; 43 | TouchInfo touchInfo; 44 | Touch_Init(&touchInfo); 45 | 46 | int title_height = 0; 47 | TTF_SizeText(Roboto_large, "Settings", NULL, &title_height); 48 | 49 | const char *main_menu_items[] = 50 | { 51 | "By name (ascending)", 52 | "By name (descending)", 53 | "By size (largest first)", 54 | "By size (smallest first)" 55 | }; 56 | 57 | int radio_button_width = 0, radio_button_height = 0; // 1180 58 | SDL_QueryTexture(icon_radio_dark_on, NULL, NULL, &radio_button_width, &radio_button_height); 59 | 60 | while(WHBProcIsRunning()) 61 | { 62 | SDL_ClearScreen(RENDERER, config_dark_theme? BLACK_BG : WHITE); 63 | SDL_RenderClear(RENDERER); 64 | SDL_DrawRect(RENDERER, 0, 0, 1280, 40, config_dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT); // Status bar 65 | SDL_DrawRect(RENDERER, 0, 40, 1280, 100, config_dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT); // Menu bar 66 | 67 | StatusBar_DisplayTime(); 68 | 69 | SDL_DrawImage(RENDERER, icon_back, 40, 66); 70 | SDL_DrawText(RENDERER, Roboto_large, 128, 40 + ((100 - title_height)/2), WHITE, "Sorting Options"); 71 | 72 | int printed = 0; // Print counter 73 | 74 | for (int i = 0; i < max_items + 1; i++) 75 | { 76 | if (printed == FILES_PER_PAGE) 77 | break; 78 | 79 | if (selection < FILES_PER_PAGE || i > (selection - FILES_PER_PAGE)) 80 | { 81 | if (i == selection) 82 | SDL_DrawRect(RENDERER, 0, 140 + (73 * printed), 1280, 73, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 83 | 84 | TTF_SizeText(Roboto, main_menu_items[i], NULL, &height); 85 | SDL_DrawText(RENDERER, Roboto, 40, 140 + ((73 - height)/2) + (73 * printed), config_dark_theme? WHITE : BLACK, main_menu_items[i]); 86 | 87 | printed++; 88 | } 89 | } 90 | 91 | config_sort_by == 0? SDL_DrawImage(RENDERER, config_dark_theme? icon_radio_dark_on : icon_radio_on, (1170 - radio_button_width), 152) : 92 | SDL_DrawImage(RENDERER, config_dark_theme? icon_radio_dark_off : icon_radio_off, (1170 - radio_button_width), 152); 93 | 94 | config_sort_by == 1? SDL_DrawImage(RENDERER, config_dark_theme? icon_radio_dark_on : icon_radio_on, (1170 - radio_button_width), 225) : 95 | SDL_DrawImage(RENDERER, config_dark_theme? icon_radio_dark_off : icon_radio_off, (1170 - radio_button_width), 225); 96 | 97 | config_sort_by == 2? SDL_DrawImage(RENDERER, config_dark_theme? icon_radio_dark_on : icon_radio_on, (1170 - radio_button_width), 298) : 98 | SDL_DrawImage(RENDERER, config_dark_theme? icon_radio_dark_off : icon_radio_off, (1170 - radio_button_width), 298); 99 | 100 | config_sort_by == 3? SDL_DrawImage(RENDERER, config_dark_theme? icon_radio_dark_on : icon_radio_on, (1170 - radio_button_width), 371) : 101 | SDL_DrawImage(RENDERER, config_dark_theme? icon_radio_dark_off : icon_radio_off, (1170 - radio_button_width), 371); 102 | 103 | SDL_RenderPresent(RENDERER); 104 | 105 | Input_Update(); 106 | Touch_Process(&touchInfo); 107 | uint32_t kDown = Input_KeysDown(); 108 | 109 | if (kDown & KEY_B) 110 | break; 111 | 112 | if ((kDown & KEY_DDOWN) || (kDown & KEY_LSTICK_DOWN) || (kDown & KEY_RSTICK_DOWN)) 113 | selection++; 114 | else if ((kDown & KEY_DUP) || (kDown & KEY_LSTICK_UP) || (kDown & KEY_RSTICK_UP)) 115 | selection--; 116 | 117 | Utils_SetMax(&selection, 0, max_items); 118 | Utils_SetMin(&selection, max_items, 0); 119 | 120 | if (kDown & KEY_A) 121 | Save_SortConfig(selection); 122 | 123 | if (touchInfo.state == TouchStart) 124 | { 125 | int touch_selection = floor(((double) touchInfo.firstTouch.py - 140) / 73); 126 | 127 | if (touch_selection >= 0 && touch_selection <= max_items) 128 | selection = touch_selection; 129 | } 130 | else if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 131 | { 132 | if (tapped_inside(touchInfo, 40, 66, 108, 114)) 133 | break; 134 | else if (touchInfo.firstTouch.py >= 140) 135 | { 136 | int tapped_selection = floor(((double) touchInfo.firstTouch.py - 140) / 73); 137 | Save_SortConfig(tapped_selection); 138 | } 139 | } 140 | } 141 | Dirbrowse_PopulateFiles(true); 142 | } 143 | 144 | static void Menu_ControlAboutDialog(uint32_t input) 145 | { 146 | if ((input & KEY_A) || (input & KEY_B)) 147 | displayAbout = false; 148 | } 149 | 150 | static void Menu_TouchAboutDialog(TouchInfo touchInfo) 151 | { 152 | if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 153 | { 154 | // Touched outside 155 | if (tapped_outside(touchInfo, (1280 - dialog_width) / 2, (720 - dialog_height) / 2, (1280 + dialog_width) / 2, (720 + dialog_height) / 2)) 156 | displayAbout = false; 157 | // Confirm Button 158 | if (tapped_inside(touchInfo, 1010 - confirm_width, (720 - dialog_height) / 2 + 225, 1050 + confirm_width, (720 - dialog_height) / 2 + 265 + confirm_height)) 159 | displayAbout = false; 160 | } 161 | } 162 | 163 | static void Menu_DisplayAboutDialog(void) 164 | { 165 | int text1_width = 0, text2_width = 0, text3_width = 0, text4_width = 0, text5_width = 0; 166 | TTF_SizeText(Roboto_small, "WiiU Shell vX.X.X", &text1_width, NULL); 167 | TTF_SizeText(Roboto_small, "Author: Joel16", &text2_width, NULL); 168 | TTF_SizeText(Roboto_small, "Graphics: Preetisketch and CyanogenMod/LineageOS contributors", &text3_width, NULL); 169 | TTF_SizeText(Roboto_small, "Touch screen: StevenMattera", &text4_width, NULL); 170 | TTF_SizeText(Roboto_small, "E-Book Reader: rock88", &text5_width, NULL); 171 | 172 | TTF_SizeText(Roboto, "OK", &confirm_width, &confirm_height); 173 | 174 | SDL_QueryTexture(dialog, NULL, NULL, &dialog_width, &dialog_height); 175 | 176 | SDL_DrawImage(RENDERER, config_dark_theme? dialog_dark : dialog, ((1280 - (dialog_width)) / 2), ((720 - (dialog_height)) / 2)); 177 | SDL_DrawText(RENDERER, Roboto, ((1280 - (dialog_width)) / 2) + 80, ((720 - (dialog_height)) / 2) + 45, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "About"); 178 | SDL_DrawTextf(RENDERER, Roboto_small, ((1280 - (text1_width)) / 2), ((720 - (dialog_height)) / 2) + 70, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "WiiU Shell v%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO); 179 | SDL_DrawText(RENDERER, Roboto_small, ((1280 - (text2_width)) / 2), ((720 - (dialog_height)) / 2) + 100, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Author: Joel16"); 180 | SDL_DrawText(RENDERER, Roboto_small, ((1280 - (text3_width)) / 2), ((720 - (dialog_height)) / 2) + 130, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Graphics: Preetisketch and CyanogenMod/LineageOS contributors"); 181 | SDL_DrawText(RENDERER, Roboto_small, ((1280 - (text4_width)) / 2), ((720 - (dialog_height)) / 2) + 160, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Touch screen: StevenMattera"); 182 | SDL_DrawText(RENDERER, Roboto_small, ((1280 - (text5_width)) / 2), ((720 - (dialog_height)) / 2) + 190, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "E-Book Reader: rock88"); 183 | 184 | SDL_DrawRect(RENDERER, (1030 - (confirm_width)) - 20, (((720 - (dialog_height)) / 2) + 245) - 20, confirm_width + 40, confirm_height + 40, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 185 | SDL_DrawText(RENDERER, Roboto, 1030 - (confirm_width), ((720 - (dialog_height)) / 2) + 245, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "OK"); 186 | } 187 | 188 | void Menu_DisplaySettings(void) 189 | { 190 | int selection = 0, max_items = 2, height = 0; 191 | TouchInfo touchInfo; 192 | Touch_Init(&touchInfo); 193 | 194 | int title_height = 0; 195 | TTF_SizeText(Roboto_large, "Settings", NULL, &title_height); 196 | 197 | const char *main_menu_items[] = 198 | { 199 | "Sorting options", 200 | "Dark theme", 201 | "About" 202 | }; 203 | 204 | int toggle_button_width = 0, toggle_button_height = 0; //1180 205 | SDL_QueryTexture(icon_toggle_on, NULL, NULL, &toggle_button_width, &toggle_button_height); 206 | 207 | displayAbout = false; 208 | 209 | while(WHBProcIsRunning()) 210 | { 211 | SDL_ClearScreen(RENDERER, config_dark_theme? BLACK_BG : WHITE); 212 | SDL_RenderClear(RENDERER); 213 | SDL_DrawRect(RENDERER, 0, 0, 1280, 40, config_dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT); // Status bar 214 | SDL_DrawRect(RENDERER, 0, 40, 1280, 100, config_dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT); // Menu bar 215 | 216 | StatusBar_DisplayTime(); 217 | 218 | SDL_DrawImage(RENDERER, icon_back, 40, 66); 219 | SDL_DrawText(RENDERER, Roboto_large, 128, 40 + ((100 - title_height)/2), WHITE, "Settings"); 220 | 221 | int printed = 0; // Print counter 222 | 223 | for (int i = 0; i < max_items + 1; i++) 224 | { 225 | if (printed == FILES_PER_PAGE) 226 | break; 227 | 228 | if (selection < FILES_PER_PAGE || i > (selection - FILES_PER_PAGE)) 229 | { 230 | if (i == selection) 231 | SDL_DrawRect(RENDERER, 0, 140 + (73 * printed), 1280, 73, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 232 | 233 | if (config_dark_theme) 234 | SDL_DrawImage(RENDERER, config_dark_theme? icon_toggle_dark_on : icon_toggle_off, 1180 - toggle_button_width, 213 + ((73 - toggle_button_height) / 2)); 235 | else 236 | SDL_DrawImage(RENDERER, config_dark_theme? icon_toggle_on : icon_toggle_off, 1180 - toggle_button_width, 213 + ((73 - toggle_button_height) / 2)); 237 | 238 | TTF_SizeText(Roboto, main_menu_items[i], NULL, &height); 239 | SDL_DrawText(RENDERER, Roboto, 40, 140 + ((73 - height)/2) + (73 * printed), config_dark_theme? WHITE : BLACK, main_menu_items[i]); 240 | 241 | printed++; 242 | } 243 | } 244 | 245 | if (displayAbout) 246 | Menu_DisplayAboutDialog(); 247 | 248 | SDL_RenderPresent(RENDERER); 249 | 250 | Input_Update(); 251 | Touch_Process(&touchInfo); 252 | uint32_t kDown = Input_KeysDown(); 253 | 254 | if (displayAbout) 255 | { 256 | Menu_ControlAboutDialog(kDown); 257 | Menu_TouchAboutDialog(touchInfo); 258 | } 259 | else 260 | { 261 | if (kDown & KEY_B) 262 | break; 263 | 264 | if ((kDown & KEY_DDOWN) || (kDown & KEY_LSTICK_DOWN) || (kDown & KEY_RSTICK_DOWN)) 265 | selection++; 266 | else if ((kDown & KEY_DUP) || (kDown & KEY_LSTICK_UP) || (kDown & KEY_RSTICK_UP)) 267 | selection--; 268 | 269 | Utils_SetMax(&selection, 0, max_items); 270 | Utils_SetMin(&selection, max_items, 0); 271 | 272 | if (kDown & KEY_A) 273 | { 274 | switch (selection) 275 | { 276 | case 0: 277 | Menu_DisplaySortSettings(); 278 | break; 279 | case 1: 280 | config_dark_theme = !config_dark_theme; 281 | Config_Save(config_dark_theme, config_sort_by); 282 | break; 283 | case 2: 284 | displayAbout = true; 285 | break; 286 | } 287 | } 288 | 289 | if (touchInfo.state == TouchStart) 290 | { 291 | int touch_selection = floor(((double) touchInfo.firstTouch.py - 140) / 73); 292 | 293 | if (touch_selection > 0 && touch_selection <= max_items) 294 | selection = touch_selection; 295 | } 296 | else if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 297 | { 298 | if (tapped_inside(touchInfo, 40, 66, 108, 114)) 299 | break; 300 | else if (touchInfo.firstTouch.py >= 140) 301 | { 302 | int tapped_selection = floor(((double) touchInfo.firstTouch.py - 140) / 73); 303 | 304 | switch (tapped_selection) 305 | { 306 | case 0: 307 | Menu_DisplaySortSettings(); 308 | break; 309 | case 1: 310 | config_dark_theme = !config_dark_theme; 311 | Config_Save(config_dark_theme, config_sort_by); 312 | break; 313 | case 2: 314 | displayAbout = true; 315 | break; 316 | } 317 | 318 | Config_Save(config_dark_theme, config_sort_by); 319 | } 320 | } 321 | } 322 | } 323 | 324 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 325 | } -------------------------------------------------------------------------------- /source/dirbrowse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "archive.h" 7 | #include "common.h" 8 | #include "config.h" 9 | #include "dirbrowse.h" 10 | #include "fs.h" 11 | #include "menu_gallery.h" 12 | #include "menu_music.h" 13 | #include "SDL_helper.h" 14 | #include "textures.h" 15 | #include "utils.h" 16 | 17 | #define TYPE_DIR(n) (n == DT_DIR ? 1 : 0) 18 | 19 | int initialPosition = 0; 20 | int position = 0; // menu position 21 | int fileCount = 0; // file count 22 | File *files = NULL; // file list 23 | 24 | void Dirbrowse_RecursiveFree(File *node) 25 | { 26 | if (node == NULL) // End of list 27 | return; 28 | 29 | Dirbrowse_RecursiveFree(node->next); // Nest further 30 | free(node); // Free memory 31 | } 32 | 33 | /* function declaration */ 34 | typedef int(*qsort_compar)(const void *, const void *); 35 | 36 | /* Basically scndir implementation */ 37 | static int Dirbrowse_ScanDir(const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *), 38 | int (*compar)(const struct dirent **, const struct dirent **)) 39 | { 40 | DIR *d; 41 | struct dirent *entry; 42 | register int i = 0; 43 | size_t entrysize; 44 | 45 | if ((d=opendir(dir)) == NULL) 46 | return(-1); 47 | 48 | *namelist=NULL; 49 | 50 | while ((entry=readdir(d)) != NULL) 51 | { 52 | if (select == NULL || (select != NULL && (*select)(entry))) 53 | { 54 | *namelist = (struct dirent **)realloc((void *)(*namelist), (size_t)((i + 1) * sizeof(struct dirent *))); 55 | 56 | if (*namelist == NULL) 57 | return(-1); 58 | 59 | entrysize = sizeof(struct dirent) - sizeof(entry->d_name) + strlen(entry->d_name) + 1; 60 | 61 | (*namelist)[i] = (struct dirent *)malloc(entrysize); 62 | 63 | if ((*namelist)[i] == NULL) 64 | return(-1); 65 | 66 | memcpy((*namelist)[i], entry, entrysize); 67 | i++; 68 | } 69 | } 70 | 71 | if (closedir(d)) 72 | return(-1); 73 | if (compar != NULL) 74 | qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), (qsort_compar)compar); 75 | 76 | return(i); 77 | } 78 | 79 | static int cmpstringp(const struct dirent **dent1, const struct dirent **dent2) 80 | { 81 | int ret = 0; 82 | char isDir[2], path1[512], path2[512]; 83 | struct stat sbuf1, sbuf2; 84 | 85 | // push '..' to beginning 86 | if (strcmp("..", (*dent1)->d_name) == 0) 87 | return -1; 88 | else if (strcmp("..", (*dent2)->d_name) == 0) 89 | return 1; 90 | 91 | isDir[0] = TYPE_DIR((*dent1)->d_type); 92 | isDir[1] = TYPE_DIR((*dent2)->d_type); 93 | 94 | strcpy(path1, cwd); 95 | strcpy(path1 + strlen(path1), (*dent1)->d_name); 96 | ret = stat(path1, &sbuf1); 97 | if (ret) 98 | return 0; 99 | 100 | strcpy(path2, cwd); 101 | strcpy(path2 + strlen(path2), (*dent2)->d_name); 102 | ret = stat(path2, &sbuf2); 103 | if (ret) 104 | return 0; 105 | 106 | uint32_t sizeA = FS_GetFileSize(path1); 107 | uint32_t sizeB = FS_GetFileSize(path2); 108 | 109 | switch(config_sort_by) 110 | { 111 | case 0: 112 | if (isDir[0] == isDir[1]) // Alphabetical ascending 113 | return strcasecmp((*dent1)->d_name, (*dent2)->d_name); 114 | else 115 | return isDir[1] - isDir[0]; 116 | break; 117 | 118 | case 1: 119 | if (isDir[0] == isDir[1]) // Alphabetical descending 120 | return strcasecmp((*dent2)->d_name, (*dent1)->d_name); 121 | else 122 | return isDir[1] - isDir[0]; 123 | break; 124 | 125 | case 2: 126 | if (isDir[0] == isDir[1]) // Size newest 127 | return sizeA > sizeB ? -1 : sizeA < sizeB ? 1 : 0; 128 | else 129 | return isDir[1] - isDir[0]; 130 | break; 131 | 132 | case 3: 133 | if (isDir[0] == isDir[1]) // Size oldest 134 | return sizeB > sizeA ? -1 : sizeB < sizeA ? 1 : 0; 135 | else 136 | return isDir[1] - isDir[0]; // put directories first 137 | break; 138 | } 139 | return 0; 140 | } 141 | 142 | void Dirbrowse_PopulateFiles(bool clear) 143 | { 144 | char path[512]; 145 | Dirbrowse_RecursiveFree(files); 146 | files = NULL; 147 | fileCount = 0; 148 | 149 | // Open Working Directory 150 | DIR *directory = opendir(cwd); 151 | 152 | if (directory) 153 | { 154 | /* Add fake ".." entry except on root */ 155 | if (strcmp(cwd, ROOT_PATH)) 156 | { 157 | // New List 158 | files = (File *)malloc(sizeof(File)); 159 | memset(files, 0, sizeof(File)); 160 | 161 | // Copy File Name 162 | strcpy(files->name, ".."); 163 | files->isDir = 1; 164 | fileCount++; 165 | } 166 | 167 | struct dirent **entries; 168 | 169 | fileCount = Dirbrowse_ScanDir(cwd, &entries, NULL, cmpstringp); 170 | 171 | if (fileCount >= 0) 172 | { 173 | for (int i = 0; i < (fileCount); i++) 174 | { 175 | // Ingore null filename 176 | if (entries[i]->d_name[0] == '\0') 177 | continue; 178 | 179 | // Ignore "." in all Directories 180 | if (strcmp(entries[i]->d_name, ".") == 0) 181 | continue; 182 | 183 | // Ignore ".." in Root Directory 184 | if (strcmp(cwd, ROOT_PATH) == 0 && strncmp(entries[i]->d_name, "..", 2) == 0) // Ignore ".." in Root Directory 185 | continue; 186 | 187 | // Allocate Memory 188 | File *item = (File *)malloc(sizeof(File)); 189 | 190 | // Clear Memory 191 | memset(item, 0, sizeof(File)); 192 | 193 | // Copy File Name 194 | strcpy(item->name, entries[i]->d_name); 195 | 196 | // Set Folder Flag 197 | item->isDir = entries[i]->d_type == DT_DIR; 198 | 199 | // Copy file size 200 | if (!item->isDir) 201 | { 202 | strcpy(path, cwd); 203 | strcpy(path + strlen(path), item->name); 204 | item->size = FS_GetFileSize(path); 205 | } 206 | 207 | // New List 208 | if (files == NULL) 209 | files = item; 210 | 211 | // Existing List 212 | else 213 | { 214 | File *list = files; 215 | 216 | // Append to List 217 | while(list->next != NULL) 218 | list = list->next; 219 | 220 | // Link Item 221 | list->next = item; 222 | } 223 | 224 | free(entries[i]); 225 | } 226 | } 227 | 228 | // Close Directory 229 | closedir(directory); 230 | } 231 | 232 | 233 | // Attempt to keep Index 234 | if (!clear) 235 | { 236 | if (position >= fileCount) 237 | position = fileCount - 1; 238 | } 239 | else 240 | position = 0; 241 | } 242 | 243 | void Dirbrowse_DisplayFiles(void) 244 | { 245 | int title_height = 0; 246 | SDL_DrawImage(RENDERER, icon_nav_drawer, 20, 58); 247 | SDL_DrawImage(RENDERER, icon_actions, (1260 - 64), 58); 248 | TTF_SizeText(Roboto_large, cwd, NULL, &title_height); 249 | SDL_DrawText(RENDERER, Roboto_large, 170, 40 + ((100 - title_height)/2), WHITE, cwd); 250 | 251 | int i = 0, printed = 0; 252 | File *file = files; // Draw file list 253 | 254 | for(; file != NULL; file = file->next) 255 | { 256 | if (printed == FILES_PER_PAGE) // Limit the files per page 257 | break; 258 | 259 | if (position < FILES_PER_PAGE || i > (position - FILES_PER_PAGE)) 260 | { 261 | if (i == position) 262 | SDL_DrawRect(RENDERER, 0, 140 + (73 * printed), 1280, 73, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 263 | 264 | if (strcmp(multi_select_dir, cwd) == 0) 265 | { 266 | multi_select[i] == true? SDL_DrawImage(RENDERER, config_dark_theme? icon_check_dark : icon_check, 20, 156 + (73 * printed)) : 267 | SDL_DrawImage(RENDERER, config_dark_theme? icon_uncheck_dark : icon_uncheck, 20, 156 + (73 * printed)); 268 | } 269 | else 270 | SDL_DrawImage(RENDERER, config_dark_theme? icon_uncheck_dark : icon_uncheck, 20, 156 + (73 * printed)); 271 | 272 | char path[512]; 273 | strcpy(path, cwd); 274 | strcpy(path + strlen(path), file->name); 275 | 276 | if (file->isDir) 277 | SDL_DrawImageScale(RENDERER, config_dark_theme? icon_dir_dark : icon_dir, 80, 141 + (73 * printed), 72, 72); 278 | else if ((strncasecmp(FS_GetFileExt(file->name), "nro", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "elf", 3) == 0) 279 | || (strncasecmp(FS_GetFileExt(file->name), "bin", 3) == 0)) 280 | SDL_DrawImageScale(RENDERER, icon_app, 80, 141 + (73 * printed), 72, 72); 281 | else if ((strncasecmp(FS_GetFileExt(file->name), "zip", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "tar", 3) == 0) 282 | || (strncasecmp(FS_GetFileExt(file->name), "lz4", 3) == 0)) 283 | SDL_DrawImageScale(RENDERER, icon_archive, 80, 141 + (73 * printed), 72, 72); 284 | else if ((strncasecmp(FS_GetFileExt(file->name), "mp3", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "ogg", 3) == 0) 285 | || (strncasecmp(FS_GetFileExt(file->name), "wav", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "mod", 3) == 0) 286 | || (strncasecmp(FS_GetFileExt(file->name), "flac", 4) == 0) || (strncasecmp(FS_GetFileExt(file->name), "midi", 4) == 0) 287 | || (strncasecmp(FS_GetFileExt(file->name), "mid", 3) == 0)) 288 | SDL_DrawImageScale(RENDERER, icon_audio, 80, 141 + (73 * printed), 72, 72); 289 | else if ((strncasecmp(FS_GetFileExt(file->name), "png", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "jpg", 3) == 0) 290 | || (strncasecmp(FS_GetFileExt(file->name), "bmp", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "gif", 3) == 0)) 291 | SDL_DrawImageScale(RENDERER, icon_image, 80, 141 + (73 * printed), 72, 72); 292 | else if ((strncasecmp(FS_GetFileExt(file->name), "txt", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "lua", 3) == 0) 293 | || (strncasecmp(FS_GetFileExt(file->name), "cfg", 3) == 0)) 294 | SDL_DrawImageScale(RENDERER, icon_text, 80, 141 + (73 * printed), 72, 72); 295 | else 296 | SDL_DrawImageScale(RENDERER, icon_file, 80, 141 + (73 * printed), 72, 72); 297 | 298 | char buf[64], size[16]; 299 | strncpy(buf, file->name, sizeof(buf)); 300 | buf[sizeof(buf) - 1] = '\0'; 301 | 302 | if (!file->isDir) 303 | { 304 | Utils_GetSizeString(size, file->size); 305 | int width = 0; 306 | TTF_SizeText(Roboto_small, size, &width, NULL); 307 | SDL_DrawText(RENDERER, Roboto_small, 1260 - width, 180 + (73 * printed), config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, size); 308 | } 309 | 310 | int height = 0; 311 | TTF_SizeText(Roboto, buf, NULL, &height); 312 | 313 | if (strncmp(file->name, "..", 2) == 0) 314 | SDL_DrawText(RENDERER, Roboto, 170, 140 + ((73 - height)/2) + (73 * printed), config_dark_theme? WHITE : BLACK, "Parent folder"); 315 | else 316 | SDL_DrawText(RENDERER, Roboto, 170, 140 + ((73 - height)/2) + (73 * printed), config_dark_theme? WHITE : BLACK, buf); 317 | 318 | printed++; // Increase printed counter 319 | } 320 | 321 | i++; // Increase counter 322 | } 323 | } 324 | 325 | static void Dirbrowse_SaveLastDirectory(void) 326 | { 327 | char *buf = (char *)malloc(512); 328 | strcpy(buf, cwd); 329 | 330 | FILE *write = fopen("wiiu/WiiU-Shell/lastdir.txt", "w"); 331 | fprintf(write, "%s", buf); 332 | fclose(write); 333 | free(buf); 334 | } 335 | 336 | // Get file index 337 | File *Dirbrowse_GetFileIndex(int index) 338 | { 339 | int i = 0; 340 | File *file = files; // Find file Item 341 | 342 | for(; file != NULL && i != index; file = file->next) 343 | i++; 344 | 345 | return file; // Return file 346 | } 347 | 348 | /** 349 | * Executes an operation on the file depending on the filetype. 350 | */ 351 | void Dirbrowse_OpenFile(void) 352 | { 353 | char path[512]; 354 | File *file = Dirbrowse_GetFileIndex(position); 355 | 356 | if (file == NULL) 357 | return; 358 | 359 | strcpy(path, cwd); 360 | strcpy(path + strlen(path), file->name); 361 | 362 | if (file->isDir) 363 | { 364 | // Attempt to navigate to target 365 | if (Dirbrowse_Navigate(false) == 0) 366 | { 367 | Dirbrowse_SaveLastDirectory(); 368 | Dirbrowse_PopulateFiles(true); 369 | } 370 | } 371 | else if ((strncasecmp(FS_GetFileExt(file->name), "png", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "jpg", 3) == 0) 372 | || (strncasecmp(FS_GetFileExt(file->name), "bmp", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "gif", 3) == 0)) 373 | Gallery_DisplayImage(path); 374 | else if (strncasecmp(FS_GetFileExt(file->name), "zip", 3) == 0) 375 | { 376 | Archive_ExtractZip(path, cwd); 377 | Dirbrowse_PopulateFiles(true); 378 | } 379 | else if ((strncasecmp(FS_GetFileExt(file->name), "mp3", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "ogg", 3) == 0) 380 | || (strncasecmp(FS_GetFileExt(file->name), "wav", 3) == 0) || (strncasecmp(FS_GetFileExt(file->name), "mod", 3) == 0) 381 | || (strncasecmp(FS_GetFileExt(file->name), "flac", 4) == 0) || (strncasecmp(FS_GetFileExt(file->name), "midi", 4) == 0) 382 | || (strncasecmp(FS_GetFileExt(file->name), "mid", 3) == 0)) 383 | Menu_PlayMusic(path); 384 | 385 | /*else if (strncasecmp(file->ext, "txt", 3) == 0) 386 | TextViewer_DisplayText(path);*/ 387 | } 388 | 389 | // Navigate to Folder 390 | int Dirbrowse_Navigate(bool parent) 391 | { 392 | File *file = Dirbrowse_GetFileIndex(position); // Get index 393 | 394 | if (file == NULL) 395 | return -1; 396 | 397 | // Special case ".." 398 | if ((parent) || (strncmp(file->name, "..", 2) == 0)) 399 | { 400 | char *slash = NULL; 401 | 402 | // Find last '/' in working directory 403 | int i = strlen(cwd) - 2; for(; i >= 0; i--) 404 | { 405 | // Slash discovered 406 | if (cwd[i] == '/') 407 | { 408 | slash = cwd + i + 1; // Save pointer 409 | break; // Stop search 410 | } 411 | } 412 | 413 | slash[0] = 0; // Terminate working directory 414 | } 415 | 416 | // Normal folder 417 | else 418 | { 419 | if (file->isDir) 420 | { 421 | // Append folder to working directory 422 | strcpy(cwd + strlen(cwd), file->name); 423 | cwd[strlen(cwd) + 1] = 0; 424 | cwd[strlen(cwd)] = '/'; 425 | } 426 | } 427 | 428 | Dirbrowse_SaveLastDirectory(); 429 | 430 | return 0; // Return success 431 | } -------------------------------------------------------------------------------- /include/minizip/unzip.h: -------------------------------------------------------------------------------- 1 | /* unzip.h -- IO for uncompress .zip files using zlib 2 | Version 1.1, February 14h, 2010 3 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) 4 | 5 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) 6 | 7 | Modifications of Unzip for Zip64 8 | Copyright (C) 2007-2008 Even Rouault 9 | 10 | Modifications for Zip64 support on both zip and unzip 11 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) 12 | 13 | For more info read MiniZip_info.txt 14 | 15 | --------------------------------------------------------------------------------- 16 | 17 | Condition of use and distribution are the same than zlib : 18 | 19 | This software is provided 'as-is', without any express or implied 20 | warranty. In no event will the authors be held liable for any damages 21 | arising from the use of this software. 22 | 23 | Permission is granted to anyone to use this software for any purpose, 24 | including commercial applications, and to alter it and redistribute it 25 | freely, subject to the following restrictions: 26 | 27 | 1. The origin of this software must not be misrepresented; you must not 28 | claim that you wrote the original software. If you use this software 29 | in a product, an acknowledgment in the product documentation would be 30 | appreciated but is not required. 31 | 2. Altered source versions must be plainly marked as such, and must not be 32 | misrepresented as being the original software. 33 | 3. This notice may not be removed or altered from any source distribution. 34 | 35 | --------------------------------------------------------------------------------- 36 | 37 | Changes 38 | 39 | See header of unzip64.c 40 | 41 | */ 42 | 43 | #ifndef _unz64_H 44 | #define _unz64_H 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | #ifndef _ZLIB_H 51 | #include "zlib.h" 52 | #endif 53 | 54 | #ifndef _ZLIBIOAPI_H 55 | #include "ioapi.h" 56 | #endif 57 | 58 | #ifdef HAVE_BZIP2 59 | #include "bzlib.h" 60 | #endif 61 | 62 | #define Z_BZIP2ED 12 63 | 64 | #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) 65 | /* like the STRICT of WIN32, we define a pointer that cannot be converted 66 | from (void*) without cast */ 67 | typedef struct TagunzFile__ { int unused; } unzFile__; 68 | typedef unzFile__ *unzFile; 69 | #else 70 | typedef voidp unzFile; 71 | #endif 72 | 73 | 74 | #define UNZ_OK (0) 75 | #define UNZ_END_OF_LIST_OF_FILE (-100) 76 | #define UNZ_ERRNO (Z_ERRNO) 77 | #define UNZ_EOF (0) 78 | #define UNZ_PARAMERROR (-102) 79 | #define UNZ_BADZIPFILE (-103) 80 | #define UNZ_INTERNALERROR (-104) 81 | #define UNZ_CRCERROR (-105) 82 | 83 | /* tm_unz contain date/time info */ 84 | typedef struct tm_unz_s 85 | { 86 | uInt tm_sec; /* seconds after the minute - [0,59] */ 87 | uInt tm_min; /* minutes after the hour - [0,59] */ 88 | uInt tm_hour; /* hours since midnight - [0,23] */ 89 | uInt tm_mday; /* day of the month - [1,31] */ 90 | uInt tm_mon; /* months since January - [0,11] */ 91 | uInt tm_year; /* years - [1980..2044] */ 92 | } tm_unz; 93 | 94 | /* unz_global_info structure contain global data about the ZIPfile 95 | These data comes from the end of central dir */ 96 | typedef struct unz_global_info64_s 97 | { 98 | ZPOS64_T number_entry; /* total number of entries in 99 | the central dir on this disk */ 100 | uLong size_comment; /* size of the global comment of the zipfile */ 101 | } unz_global_info64; 102 | 103 | typedef struct unz_global_info_s 104 | { 105 | uLong number_entry; /* total number of entries in 106 | the central dir on this disk */ 107 | uLong size_comment; /* size of the global comment of the zipfile */ 108 | } unz_global_info; 109 | 110 | /* unz_file_info contain information about a file in the zipfile */ 111 | typedef struct unz_file_info64_s 112 | { 113 | uLong version; /* version made by 2 bytes */ 114 | uLong version_needed; /* version needed to extract 2 bytes */ 115 | uLong flag; /* general purpose bit flag 2 bytes */ 116 | uLong compression_method; /* compression method 2 bytes */ 117 | uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ 118 | uLong crc; /* crc-32 4 bytes */ 119 | ZPOS64_T compressed_size; /* compressed size 8 bytes */ 120 | ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ 121 | uLong size_filename; /* filename length 2 bytes */ 122 | uLong size_file_extra; /* extra field length 2 bytes */ 123 | uLong size_file_comment; /* file comment length 2 bytes */ 124 | 125 | uLong disk_num_start; /* disk number start 2 bytes */ 126 | uLong internal_fa; /* internal file attributes 2 bytes */ 127 | uLong external_fa; /* external file attributes 4 bytes */ 128 | 129 | tm_unz tmu_date; 130 | } unz_file_info64; 131 | 132 | typedef struct unz_file_info_s 133 | { 134 | uLong version; /* version made by 2 bytes */ 135 | uLong version_needed; /* version needed to extract 2 bytes */ 136 | uLong flag; /* general purpose bit flag 2 bytes */ 137 | uLong compression_method; /* compression method 2 bytes */ 138 | uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ 139 | uLong crc; /* crc-32 4 bytes */ 140 | uLong compressed_size; /* compressed size 4 bytes */ 141 | uLong uncompressed_size; /* uncompressed size 4 bytes */ 142 | uLong size_filename; /* filename length 2 bytes */ 143 | uLong size_file_extra; /* extra field length 2 bytes */ 144 | uLong size_file_comment; /* file comment length 2 bytes */ 145 | 146 | uLong disk_num_start; /* disk number start 2 bytes */ 147 | uLong internal_fa; /* internal file attributes 2 bytes */ 148 | uLong external_fa; /* external file attributes 4 bytes */ 149 | 150 | tm_unz tmu_date; 151 | } unz_file_info; 152 | 153 | extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, 154 | const char* fileName2, 155 | int iCaseSensitivity)); 156 | /* 157 | Compare two filename (fileName1,fileName2). 158 | If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) 159 | If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi 160 | or strcasecmp) 161 | If iCaseSenisivity = 0, case sensitivity is defaut of your operating system 162 | (like 1 on Unix, 2 on Windows) 163 | */ 164 | 165 | 166 | extern unzFile ZEXPORT unzOpen OF((const char *path)); 167 | extern unzFile ZEXPORT unzOpen64 OF((const void *path)); 168 | /* 169 | Open a Zip file. path contain the full pathname (by example, 170 | on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer 171 | "zlib/zlib113.zip". 172 | If the zipfile cannot be opened (file don't exist or in not valid), the 173 | return value is NULL. 174 | Else, the return value is a unzFile Handle, usable with other function 175 | of this unzip package. 176 | the "64" function take a const void* pointer, because the path is just the 177 | value passed to the open64_file_func callback. 178 | Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path 179 | is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* 180 | does not describe the reality 181 | */ 182 | 183 | 184 | extern unzFile ZEXPORT unzOpen2 OF((const char *path, 185 | zlib_filefunc_def* pzlib_filefunc_def)); 186 | /* 187 | Open a Zip file, like unzOpen, but provide a set of file low level API 188 | for read/write the zip file (see ioapi.h) 189 | */ 190 | 191 | extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, 192 | zlib_filefunc64_def* pzlib_filefunc_def)); 193 | /* 194 | Open a Zip file, like unz64Open, but provide a set of file low level API 195 | for read/write the zip file (see ioapi.h) 196 | */ 197 | 198 | extern int ZEXPORT unzClose OF((unzFile file)); 199 | /* 200 | Close a ZipFile opened with unzOpen. 201 | If there is files inside the .Zip opened with unzOpenCurrentFile (see later), 202 | these files MUST be closed with unzCloseCurrentFile before call unzClose. 203 | return UNZ_OK if there is no problem. */ 204 | 205 | extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, 206 | unz_global_info *pglobal_info)); 207 | 208 | extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, 209 | unz_global_info64 *pglobal_info)); 210 | /* 211 | Write info about the ZipFile in the *pglobal_info structure. 212 | No preparation of the structure is needed 213 | return UNZ_OK if there is no problem. */ 214 | 215 | 216 | extern int ZEXPORT unzGetGlobalComment OF((unzFile file, 217 | char *szComment, 218 | uLong uSizeBuf)); 219 | /* 220 | Get the global comment string of the ZipFile, in the szComment buffer. 221 | uSizeBuf is the size of the szComment buffer. 222 | return the number of byte copied or an error code <0 223 | */ 224 | 225 | 226 | /***************************************************************************/ 227 | /* Unzip package allow you browse the directory of the zipfile */ 228 | 229 | extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); 230 | /* 231 | Set the current file of the zipfile to the first file. 232 | return UNZ_OK if there is no problem 233 | */ 234 | 235 | extern int ZEXPORT unzGoToNextFile OF((unzFile file)); 236 | /* 237 | Set the current file of the zipfile to the next file. 238 | return UNZ_OK if there is no problem 239 | return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. 240 | */ 241 | 242 | extern int ZEXPORT unzLocateFile OF((unzFile file, 243 | const char *szFileName, 244 | int iCaseSensitivity)); 245 | /* 246 | Try locate the file szFileName in the zipfile. 247 | For the iCaseSensitivity signification, see unzStringFileNameCompare 248 | 249 | return value : 250 | UNZ_OK if the file is found. It becomes the current file. 251 | UNZ_END_OF_LIST_OF_FILE if the file is not found 252 | */ 253 | 254 | 255 | /* ****************************************** */ 256 | /* Ryan supplied functions */ 257 | /* unz_file_info contain information about a file in the zipfile */ 258 | typedef struct unz_file_pos_s 259 | { 260 | uLong pos_in_zip_directory; /* offset in zip file directory */ 261 | uLong num_of_file; /* # of file */ 262 | } unz_file_pos; 263 | 264 | extern int ZEXPORT unzGetFilePos( 265 | unzFile file, 266 | unz_file_pos* file_pos); 267 | 268 | extern int ZEXPORT unzGoToFilePos( 269 | unzFile file, 270 | unz_file_pos* file_pos); 271 | 272 | typedef struct unz64_file_pos_s 273 | { 274 | ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ 275 | ZPOS64_T num_of_file; /* # of file */ 276 | } unz64_file_pos; 277 | 278 | extern int ZEXPORT unzGetFilePos64( 279 | unzFile file, 280 | unz64_file_pos* file_pos); 281 | 282 | extern int ZEXPORT unzGoToFilePos64( 283 | unzFile file, 284 | const unz64_file_pos* file_pos); 285 | 286 | /* ****************************************** */ 287 | 288 | extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, 289 | unz_file_info64 *pfile_info, 290 | char *szFileName, 291 | uLong fileNameBufferSize, 292 | void *extraField, 293 | uLong extraFieldBufferSize, 294 | char *szComment, 295 | uLong commentBufferSize)); 296 | 297 | extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, 298 | unz_file_info *pfile_info, 299 | char *szFileName, 300 | uLong fileNameBufferSize, 301 | void *extraField, 302 | uLong extraFieldBufferSize, 303 | char *szComment, 304 | uLong commentBufferSize)); 305 | /* 306 | Get Info about the current file 307 | if pfile_info!=NULL, the *pfile_info structure will contain somes info about 308 | the current file 309 | if szFileName!=NULL, the filemane string will be copied in szFileName 310 | (fileNameBufferSize is the size of the buffer) 311 | if extraField!=NULL, the extra field information will be copied in extraField 312 | (extraFieldBufferSize is the size of the buffer). 313 | This is the Central-header version of the extra field 314 | if szComment!=NULL, the comment string of the file will be copied in szComment 315 | (commentBufferSize is the size of the buffer) 316 | */ 317 | 318 | 319 | /** Addition for GDAL : START */ 320 | 321 | extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); 322 | 323 | /** Addition for GDAL : END */ 324 | 325 | 326 | /***************************************************************************/ 327 | /* for reading the content of the current zipfile, you can open it, read data 328 | from it, and close it (you can close it before reading all the file) 329 | */ 330 | 331 | extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); 332 | /* 333 | Open for reading data the current file in the zipfile. 334 | If there is no error, the return value is UNZ_OK. 335 | */ 336 | 337 | extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, 338 | const char* password)); 339 | /* 340 | Open for reading data the current file in the zipfile. 341 | password is a crypting password 342 | If there is no error, the return value is UNZ_OK. 343 | */ 344 | 345 | extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, 346 | int* method, 347 | int* level, 348 | int raw)); 349 | /* 350 | Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) 351 | if raw==1 352 | *method will receive method of compression, *level will receive level of 353 | compression 354 | note : you can set level parameter as NULL (if you did not want known level, 355 | but you CANNOT set method parameter as NULL 356 | */ 357 | 358 | extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, 359 | int* method, 360 | int* level, 361 | int raw, 362 | const char* password)); 363 | /* 364 | Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) 365 | if raw==1 366 | *method will receive method of compression, *level will receive level of 367 | compression 368 | note : you can set level parameter as NULL (if you did not want known level, 369 | but you CANNOT set method parameter as NULL 370 | */ 371 | 372 | 373 | extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); 374 | /* 375 | Close the file in zip opened with unzOpenCurrentFile 376 | Return UNZ_CRCERROR if all the file was read but the CRC is not good 377 | */ 378 | 379 | extern int ZEXPORT unzReadCurrentFile OF((unzFile file, 380 | voidp buf, 381 | unsigned len)); 382 | /* 383 | Read bytes from the current file (opened by unzOpenCurrentFile) 384 | buf contain buffer where data must be copied 385 | len the size of buf. 386 | 387 | return the number of byte copied if somes bytes are copied 388 | return 0 if the end of file was reached 389 | return <0 with error code if there is an error 390 | (UNZ_ERRNO for IO error, or zLib error for uncompress error) 391 | */ 392 | 393 | extern z_off_t ZEXPORT unztell OF((unzFile file)); 394 | 395 | extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); 396 | /* 397 | Give the current position in uncompressed data 398 | */ 399 | 400 | extern int ZEXPORT unzeof OF((unzFile file)); 401 | /* 402 | return 1 if the end of file was reached, 0 elsewhere 403 | */ 404 | 405 | extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, 406 | voidp buf, 407 | unsigned len)); 408 | /* 409 | Read extra field from the current file (opened by unzOpenCurrentFile) 410 | This is the local-header version of the extra field (sometimes, there is 411 | more info in the local-header version than in the central-header) 412 | 413 | if buf==NULL, it return the size of the local extra field 414 | 415 | if buf!=NULL, len is the size of the buffer, the extra header is copied in 416 | buf. 417 | the return value is the number of bytes copied in buf, or (if <0) 418 | the error code 419 | */ 420 | 421 | /***************************************************************************/ 422 | 423 | /* Get the current file offset */ 424 | extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); 425 | extern uLong ZEXPORT unzGetOffset (unzFile file); 426 | 427 | /* Set the current file offset */ 428 | extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); 429 | extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); 430 | 431 | 432 | 433 | #ifdef __cplusplus 434 | } 435 | #endif 436 | 437 | #endif /* _unz64_H */ 438 | -------------------------------------------------------------------------------- /source/menus/menu_options.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "common.h" 7 | #include "config.h" 8 | #include "dirbrowse.h" 9 | #include "fs.h" 10 | #include "progress_bar.h" 11 | #include "menu_options.h" 12 | #include "osk.h" 13 | #include "SDL_helper.h" 14 | #include "textures.h" 15 | #include "utils.h" 16 | 17 | /* 18 | * Copy Mode 19 | * -1 : Nothing 20 | * 0 : Copy 21 | * 1 : Move 22 | */ 23 | static int copymode = NOTHING_TO_COPY; 24 | /* 25 | * Copy Move Origin 26 | */ 27 | static char copysource[512]; 28 | 29 | static int delete_dialog_selection = 0, row = 0, column = 0; 30 | static bool copy_status = false, cut_status = false; 31 | 32 | static int delete_width = 0, delete_height = 0; 33 | static int delete_confirm_width = 0, delete_confirm_height = 0; 34 | static int delete_cancel_width = 0, delete_cancel_height = 0; 35 | 36 | static int properties_ok_width = 0, properties_ok_height = 0; 37 | 38 | static int options_cancel_width = 0, options_cancel_height = 0; 39 | 40 | void FileOptions_ResetClipboard(void) 41 | { 42 | multi_select_index = 0; 43 | memset(multi_select, 0, sizeof(multi_select)); 44 | memset(multi_select_indices, 0, sizeof(multi_select_indices)); 45 | memset(multi_select_dir, 0, sizeof(multi_select_dir)); 46 | memset(multi_select_paths, 0, sizeof(multi_select_paths)); 47 | } 48 | 49 | static int FileOptions_CreateFolder(void) 50 | { 51 | OSK_Display("Create Folder", ""); 52 | 53 | if (strncmp(osk_buffer, "", 1) == 0) 54 | return -1; 55 | 56 | char path[500]; 57 | strcpy(path, cwd); 58 | strcat(path, osk_buffer); 59 | osk_buffer[0] = '\0'; 60 | 61 | int ret = 0; 62 | if ((ret = FS_RecursiveMakeDir(path)) != 0) 63 | return ret; 64 | 65 | Dirbrowse_PopulateFiles(true); 66 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 67 | return 0; 68 | } 69 | 70 | static int FileOptions_Rename(void) 71 | { 72 | int ret = 0; 73 | File *file = Dirbrowse_GetFileIndex(position); 74 | 75 | if (file == NULL) 76 | return -1; 77 | 78 | if (strncmp(file->name, "..", 2) == 0) 79 | return -2; 80 | 81 | char oldPath[500], newPath[500]; 82 | 83 | strcpy(oldPath, cwd); 84 | strcpy(newPath, cwd); 85 | strcat(oldPath, file->name); 86 | 87 | OSK_Display("Rename", file->name); 88 | 89 | if (strncmp(osk_buffer, "", 1) == 0) 90 | return -1; 91 | 92 | strcat(newPath, osk_buffer); 93 | osk_buffer[0] = '\0'; 94 | 95 | if ((ret = rename(oldPath, newPath)) != 0) 96 | return ret; 97 | 98 | Dirbrowse_PopulateFiles(true); 99 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 100 | return 0; 101 | } 102 | 103 | static int FileOptions_RmdirRecursive(char *path) 104 | { 105 | File *filelist = NULL; 106 | DIR *directory = opendir(path); 107 | 108 | if (directory) 109 | { 110 | struct dirent *entries; 111 | 112 | while ((entries = readdir(directory)) != NULL) 113 | { 114 | if (strlen(entries->d_name) > 0) 115 | { 116 | if (strcmp(entries->d_name, ".") == 0 || strcmp(entries->d_name, "..") == 0) 117 | continue; 118 | 119 | // Allocate Memory 120 | File *item = (File *)malloc(sizeof(File)); 121 | memset(item, 0, sizeof(File)); 122 | 123 | // Copy File Name 124 | strcpy(item->name, entries->d_name); 125 | 126 | // Set Folder Flag 127 | item->isDir = entries->d_type == DT_DIR; 128 | 129 | // New List 130 | if (filelist == NULL) 131 | filelist = item; 132 | 133 | // Existing List 134 | else 135 | { 136 | File *list = filelist; 137 | 138 | while(list->next != NULL) 139 | list = list->next; 140 | 141 | list->next = item; 142 | } 143 | } 144 | } 145 | } 146 | 147 | closedir(directory); 148 | 149 | File *node = filelist; 150 | 151 | // Iterate Files 152 | for(; node != NULL; node = node->next) 153 | { 154 | // Directory 155 | if (node->isDir) 156 | { 157 | // Required Buffer Size 158 | int size = strlen(path) + strlen(node->name) + 2; 159 | 160 | // Allocate Buffer 161 | char *buffer = (char *)malloc(size); 162 | 163 | // Combine Path 164 | strcpy(buffer, path); 165 | strcpy(buffer + strlen(buffer), node->name); 166 | buffer[strlen(buffer) + 1] = 0; 167 | buffer[strlen(buffer)] = '/'; 168 | 169 | // Recursion Delete 170 | FileOptions_RmdirRecursive(buffer); 171 | 172 | free(buffer); 173 | } 174 | 175 | // File 176 | else 177 | { 178 | // Required Buffer Size 179 | int size = strlen(path) + strlen(node->name) + 1; 180 | 181 | // Allocate Buffer 182 | char *buffer = (char *)malloc(size); 183 | 184 | // Combine Path 185 | strcpy(buffer, path); 186 | strcpy(buffer + strlen(buffer), node->name); 187 | 188 | // Delete File 189 | remove(buffer); 190 | 191 | free(buffer); 192 | } 193 | } 194 | 195 | Dirbrowse_RecursiveFree(filelist); 196 | return rmdir(path); 197 | } 198 | 199 | static int FileOptions_DeleteFile(void) 200 | { 201 | // Find File 202 | File *file = Dirbrowse_GetFileIndex(position); 203 | 204 | // Not found 205 | if (file == NULL) 206 | return -1; 207 | 208 | if (strcmp(file->name, "..") == 0) 209 | return -2; 210 | 211 | char path[512]; 212 | 213 | // Puzzle Path 214 | strcpy(path, cwd); 215 | strcpy(path + strlen(path), file->name); 216 | 217 | // Delete Folder 218 | if (file->isDir) 219 | { 220 | // Add Trailing Slash 221 | path[strlen(path) + 1] = 0; 222 | path[strlen(path)] = '/'; 223 | 224 | // Delete Folder 225 | return FileOptions_RmdirRecursive(path); 226 | } 227 | 228 | // Delete File 229 | else 230 | return remove(path); 231 | } 232 | 233 | // Copy file from src to dst 234 | static int FileOptions_CopyFile(char *src, char *dst, bool displayAnim) 235 | { 236 | int chunksize = (512 * 1024); // Chunk size 237 | char *buffer = (char *)malloc(chunksize); // Reading buffer 238 | 239 | uint32_t totalwrite = 0; // Accumulated writing 240 | uint32_t totalread = 0; // Accumulated reading 241 | 242 | int result = 0; // int 243 | 244 | int in = open(src, O_RDONLY, 0777); // Open file for reading 245 | uint32_t size = FS_GetFileSize(src); 246 | 247 | // Opened file for reading 248 | if (in >= 0) 249 | { 250 | if (FS_FileExists(dst)) 251 | remove(dst); // Delete output file (if existing) 252 | 253 | int out = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0777); // Open output file for writing 254 | 255 | if (out >= 0) // Opened file for writing 256 | { 257 | uint32_t b_read = 0; // Read byte count 258 | 259 | // Copy loop (512KB at a time) 260 | while((b_read = read(in, buffer, chunksize)) > 0) 261 | { 262 | totalread += b_read; // Accumulate read data 263 | totalwrite += write(out, buffer, b_read); // Write data 264 | 265 | if (displayAnim) 266 | ProgressBar_DisplayProgress(copymode == 1? "Moving" : "Copying", Utils_Basename(src), totalread, size); 267 | } 268 | 269 | close(out); // Close output file 270 | 271 | if (totalread != totalwrite) // Insufficient copy 272 | result = -3; 273 | } 274 | 275 | else // Output open error 276 | result = -2; 277 | 278 | close(in); // Close input file 279 | } 280 | 281 | // Input open error 282 | else 283 | result = -1; 284 | 285 | free(buffer); // Free memory 286 | return result; // Return result 287 | } 288 | 289 | // Recursively copy file from src to dst 290 | static int FileOptions_CopyDir(char *src, char *dst) 291 | { 292 | DIR *directory = opendir(src); 293 | 294 | if (directory) 295 | { 296 | // Create Output Directory (is allowed to fail, we can merge folders after all) 297 | FS_MakeDir(dst); 298 | 299 | struct dirent *entries; 300 | 301 | // Iterate Files 302 | while ((entries = readdir(directory)) != NULL) 303 | { 304 | if (strlen(entries->d_name) > 0) 305 | { 306 | // Calculate Buffer Size 307 | int insize = strlen(src) + strlen(entries->d_name) + 2; 308 | int outsize = strlen(dst) + strlen(entries->d_name) + 2; 309 | 310 | // Allocate Buffer 311 | char *inbuffer = (char *)malloc(insize); 312 | char *outbuffer = (char *)malloc(outsize); 313 | 314 | // Puzzle Input Path 315 | strcpy(inbuffer, src); 316 | inbuffer[strlen(inbuffer) + 1] = 0; 317 | inbuffer[strlen(inbuffer)] = '/'; 318 | strcpy(inbuffer + strlen(inbuffer), entries->d_name); 319 | 320 | // Puzzle Output Path 321 | strcpy(outbuffer, dst); 322 | outbuffer[strlen(outbuffer) + 1] = 0; 323 | outbuffer[strlen(outbuffer)] = '/'; 324 | strcpy(outbuffer + strlen(outbuffer), entries->d_name); 325 | 326 | // Another Folder 327 | if (entries->d_type == DT_DIR) 328 | FileOptions_CopyDir(inbuffer, outbuffer); // Copy Folder (via recursion) 329 | 330 | // Simple File 331 | else 332 | FileOptions_CopyFile(inbuffer, outbuffer, true); // Copy File 333 | 334 | // Free Buffer 335 | free(inbuffer); 336 | free(outbuffer); 337 | } 338 | } 339 | 340 | closedir(directory); 341 | return 0; 342 | } 343 | 344 | return -1; 345 | } 346 | 347 | static void FileOptions_Copy(int flag) 348 | { 349 | File *file = Dirbrowse_GetFileIndex(position); 350 | 351 | if (file == NULL) 352 | return; 353 | 354 | // Copy file source 355 | strcpy(copysource, cwd); 356 | strcpy(copysource + strlen(copysource), file->name); 357 | 358 | if ((file->isDir) && (strncmp(file->name, "..", 2) != 0)) // If directory, add recursive folder flag 359 | flag |= COPY_FOLDER_RECURSIVE; 360 | 361 | copymode = flag; // Set copy flags 362 | } 363 | 364 | // Paste file or folder 365 | static int FileOptions_Paste(void) 366 | { 367 | if (copymode == NOTHING_TO_COPY) // No copy source 368 | return -1; 369 | 370 | // Source and target folder are identical 371 | char *lastslash = NULL; 372 | int i = 0; 373 | 374 | for(; i < strlen(copysource); i++) 375 | if (copysource[i] == '/') 376 | lastslash = copysource + i; 377 | 378 | char backup = lastslash[1]; 379 | lastslash[1] = 0; 380 | int identical = strcmp(copysource, cwd) == 0; 381 | lastslash[1] = backup; 382 | 383 | if (identical) 384 | return -2; 385 | 386 | char *filename = lastslash + 1; // Source filename 387 | 388 | int requiredlength = strlen(cwd) + strlen(filename) + 1; // Required target path buffer size 389 | char *copytarget = (char *)malloc(requiredlength); // Allocate target path buffer 390 | 391 | // Puzzle target path 392 | strcpy(copytarget, cwd); 393 | strcpy(copytarget + strlen(copytarget), filename); 394 | 395 | int ret = -3; // Return result 396 | 397 | // Recursive folder copy 398 | if ((copymode & COPY_FOLDER_RECURSIVE) == COPY_FOLDER_RECURSIVE) 399 | { 400 | // Check files in current folder 401 | File *node = files; for(; node != NULL; node = node->next) 402 | { 403 | if ((strcmp(filename, node->name) == 0) && (!node->isDir)) // Found a file matching the name (folder = ok, file = not) 404 | return -4; // Error out 405 | } 406 | 407 | ret = FileOptions_CopyDir(copysource, copytarget); // Copy folder recursively 408 | 409 | if (((ret) == 0) && (copymode & COPY_DELETE_ON_FINISH) == COPY_DELETE_ON_FINISH) 410 | { 411 | // Needs to add a forward "/" 412 | if (!(strcmp(&(copysource[(strlen(copysource)-1)]), "/") == 0)) 413 | strcat(copysource, "/"); 414 | 415 | FileOptions_RmdirRecursive(copysource); // Delete dir 416 | } 417 | } 418 | 419 | // Simple file copy 420 | else 421 | { 422 | ret = FileOptions_CopyFile(copysource, copytarget, true); // Copy file 423 | 424 | if (((ret) == 0) && (copymode & COPY_DELETE_ON_FINISH) == COPY_DELETE_ON_FINISH) 425 | remove(copysource); // Delete file 426 | } 427 | 428 | // Paste success 429 | if ((ret) == 0) 430 | { 431 | memset(copysource, 0, sizeof(copysource)); // Erase cache data 432 | copymode = NOTHING_TO_COPY; 433 | } 434 | 435 | free(copytarget); // Free target path buffer 436 | return ret; // Return result 437 | } 438 | 439 | static void HandleDelete(void) 440 | { 441 | if ((multi_select_index > 0) && (strlen(multi_select_dir) != 0)) 442 | { 443 | for (int i = 0; i < multi_select_index; i++) 444 | { 445 | if (strlen(multi_select_paths[i]) != 0) 446 | { 447 | if (strncmp(multi_select_paths[i], "..", 2) != 0) 448 | { 449 | if (FS_DirExists(multi_select_paths[i])) 450 | { 451 | // Add Trailing Slash 452 | multi_select_paths[i][strlen(multi_select_paths[i]) + 1] = 0; 453 | multi_select_paths[i][strlen(multi_select_paths[i])] = '/'; 454 | FileOptions_RmdirRecursive(multi_select_paths[i]); 455 | } 456 | else if (FS_FileExists(multi_select_paths[i])) 457 | remove(multi_select_paths[i]); 458 | } 459 | } 460 | } 461 | 462 | FileOptions_ResetClipboard(); 463 | } 464 | else if (FileOptions_DeleteFile() != 0) 465 | return; 466 | 467 | Dirbrowse_PopulateFiles(true); 468 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 469 | } 470 | 471 | void Menu_ControlDeleteDialog(uint32_t input, TouchInfo touchInfo) 472 | { 473 | if ((input & KEY_RIGHT) || (input & KEY_LSTICK_RIGHT) || (input & KEY_RSTICK_RIGHT)) 474 | delete_dialog_selection++; 475 | else if ((input & KEY_LEFT) || (input & KEY_LSTICK_LEFT) || (input & KEY_RSTICK_LEFT)) 476 | delete_dialog_selection--; 477 | 478 | Utils_SetMax(&delete_dialog_selection, 0, 1); 479 | Utils_SetMin(&delete_dialog_selection, 1, 0); 480 | 481 | if (input & KEY_B) 482 | { 483 | delete_dialog_selection = 0; 484 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 485 | } 486 | 487 | if (input & KEY_A) 488 | { 489 | if (delete_dialog_selection == 0) 490 | HandleDelete(); 491 | else 492 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 493 | 494 | delete_dialog_selection = 0; 495 | } 496 | 497 | if (touchInfo.state == TouchStart) 498 | { 499 | // Confirm Button 500 | if (tapped_inside(touchInfo, 1010 - delete_confirm_width, (720 - delete_height) / 2 + 225, 1050 + delete_confirm_width, (720 - delete_height) / 2 + 265 + delete_confirm_height)) 501 | delete_dialog_selection = 0; 502 | // Cancel Button 503 | else if (tapped_inside(touchInfo, 895 - delete_confirm_width, (720 - delete_height) / 2 + 225, 935 + delete_confirm_width, (720 - delete_height) / 2 + 265 + delete_cancel_height)) 504 | delete_dialog_selection = 1; 505 | } 506 | else if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 507 | { 508 | // Touched outside 509 | if (tapped_outside(touchInfo, (1280 - delete_width) / 2, (720 - delete_height) / 2, (1280 + delete_width) / 2, (720 + delete_height) / 2)) 510 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 511 | // Confirm Button 512 | else if (tapped_inside(touchInfo, 1010 - delete_confirm_width, (720 - delete_height) / 2 + 225, 1050 + delete_confirm_width, (720 - delete_height) / 2 + 265 + delete_confirm_height)) 513 | HandleDelete(); 514 | // Cancel Button 515 | else if (tapped_inside(touchInfo, 895 - delete_confirm_width, (720 - delete_height) / 2 + 225, 935 + delete_confirm_width, (720 - delete_height) / 2 + 265 + delete_cancel_height)) 516 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 517 | } 518 | } 519 | 520 | void Menu_DisplayDeleteDialog(void) 521 | { 522 | int text_width = 0; 523 | TTF_SizeText(Roboto, "Do you want to continue?", &text_width, NULL); 524 | 525 | TTF_SizeText(Roboto, "YES", &delete_confirm_width, &delete_confirm_height); 526 | TTF_SizeText(Roboto, "NO", &delete_cancel_width, &delete_cancel_height); 527 | 528 | SDL_QueryTexture(dialog, NULL, NULL, &delete_width, &delete_height); 529 | 530 | SDL_DrawImage(RENDERER, config_dark_theme? dialog_dark : dialog, ((1280 - (delete_width)) / 2), ((720 - (delete_height)) / 2)); 531 | SDL_DrawText(RENDERER, Roboto, ((1280 - (delete_width)) / 2) + 80, ((720 - (delete_height)) / 2) + 45, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "Confirm deletion"); 532 | SDL_DrawText(RENDERER, Roboto, ((1280 - (text_width)) / 2), ((720 - (delete_height)) / 2) + 130, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Do you wish to continue?"); 533 | 534 | if (delete_dialog_selection == 0) 535 | SDL_DrawRect(RENDERER, (1030 - (delete_confirm_width)) - 20, (((720 - (delete_height)) / 2) + 245) - 20, delete_confirm_width + 40, delete_confirm_height + 40, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 536 | else if (delete_dialog_selection == 1) 537 | SDL_DrawRect(RENDERER, (915 - (delete_confirm_width)) - 20, (((720 - (delete_height)) / 2) + 245) - 20, delete_confirm_width + 40, delete_cancel_height + 40, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 538 | 539 | SDL_DrawText(RENDERER, Roboto, 1030 - (delete_confirm_width), ((720 - (delete_height)) / 2) + 245, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "YES"); 540 | SDL_DrawText(RENDERER, Roboto, 910 - (delete_cancel_width), ((720 - (delete_height)) / 2) + 245, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "NO"); 541 | } 542 | 543 | void Menu_ControlProperties(uint32_t input, TouchInfo touchInfo) 544 | { 545 | if ((input & KEY_A) || (input & KEY_B)) 546 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 547 | 548 | if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 549 | { 550 | if (tapped_outside(touchInfo, 350, 85, 930, 635)) 551 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 552 | // Ok Button 553 | else if (tapped_inside(touchInfo, 870 - properties_ok_width, 575 - properties_ok_height, 910 + properties_ok_width, 615 + properties_ok_height)) 554 | MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; 555 | } 556 | } 557 | 558 | void Menu_DisplayProperties(void) 559 | { 560 | // Find File 561 | File *file = Dirbrowse_GetFileIndex(position); 562 | 563 | char path[512]; 564 | strcpy(path, cwd); 565 | strcpy(path + strlen(path), file->name); 566 | 567 | SDL_DrawImage(RENDERER, config_dark_theme? properties_dialog_dark : properties_dialog, 350, 85); 568 | SDL_DrawText(RENDERER, Roboto, 370, 133, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "Actions"); 569 | 570 | char utils_size[16]; 571 | uint32_t size = FS_GetFileSize(path); 572 | Utils_GetSizeString(utils_size, size); 573 | 574 | SDL_DrawTextf(RENDERER, Roboto, 390, 183, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Name: %s", file->name); 575 | SDL_DrawTextf(RENDERER, Roboto, 390, 233, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Parent: %s", cwd); 576 | 577 | if (!file->isDir) 578 | { 579 | SDL_DrawTextf(RENDERER, Roboto, 390, 283, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Size: %s", utils_size); 580 | //SDL_DrawText(RENDERER, Roboto, 390, 333, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Created: "); 581 | //SDL_DrawText(RENDERER, Roboto, 390, 383, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Modified: "); 582 | } 583 | 584 | TTF_SizeText(Roboto, "OK", &properties_ok_width, &properties_ok_height); 585 | SDL_DrawRect(RENDERER, (890 - properties_ok_width) - 20, (595 - properties_ok_height) - 20, properties_ok_width + 40, properties_ok_height + 40, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 586 | SDL_DrawText(RENDERER, Roboto, 890 - properties_ok_width, 595 - properties_ok_height, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "OK"); 587 | } 588 | 589 | static void HandleCopy() 590 | { 591 | if ((!copy_status) && (!cut_status )) 592 | { 593 | copy_status = true; 594 | FileOptions_Copy(COPY_KEEP_ON_FINISH); 595 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 596 | } 597 | else if (copy_status) 598 | { 599 | if ((multi_select_index > 0) && (strlen(multi_select_dir) != 0)) 600 | { 601 | char dest[512]; 602 | 603 | for (int i = 0; i < multi_select_index; i++) 604 | { 605 | if (strlen(multi_select_paths[i]) != 0) 606 | { 607 | if (strncmp(multi_select_paths[i], "..", 2) != 0) 608 | { 609 | snprintf(dest, 512, "%s%s", cwd, Utils_Basename(multi_select_paths[i])); 610 | 611 | if (FS_DirExists(multi_select_paths[i])) 612 | FileOptions_CopyDir(multi_select_paths[i], dest); 613 | else if (FS_FileExists(multi_select_paths[i])) 614 | FileOptions_CopyFile(multi_select_paths[i], dest, true); 615 | } 616 | } 617 | } 618 | 619 | FileOptions_ResetClipboard(); 620 | copymode = NOTHING_TO_COPY; 621 | 622 | } 623 | else if (FileOptions_Paste() != 0) 624 | return; 625 | 626 | copy_status = false; 627 | Dirbrowse_PopulateFiles(true); 628 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 629 | } 630 | } 631 | 632 | static void HandleCut() 633 | { 634 | if ((!cut_status ) && (!copy_status)) 635 | { 636 | cut_status = true; 637 | FileOptions_Copy(COPY_DELETE_ON_FINISH); 638 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 639 | } 640 | else if (cut_status) 641 | { 642 | char dest[512]; 643 | 644 | if ((multi_select_index > 0) && (strlen(multi_select_dir) != 0)) 645 | { 646 | for (int i = 0; i < multi_select_index; i++) 647 | { 648 | if (strlen(multi_select_paths[i]) != 0) 649 | { 650 | snprintf(dest, 512, "%s%s", cwd, Utils_Basename(multi_select_paths[i])); 651 | 652 | if (FS_DirExists(multi_select_paths[i])) 653 | rename(multi_select_paths[i], dest); 654 | else if (FS_FileExists(multi_select_paths[i])) 655 | rename(multi_select_paths[i], dest); 656 | } 657 | } 658 | 659 | FileOptions_ResetClipboard(); 660 | } 661 | else 662 | { 663 | snprintf(dest, 512, "%s%s", cwd, Utils_Basename(copysource)); 664 | 665 | if (FS_DirExists(copysource)) 666 | rename(copysource, dest); 667 | else if (FS_FileExists(copysource)) 668 | rename(copysource, dest); 669 | } 670 | 671 | cut_status = false; 672 | copymode = NOTHING_TO_COPY; 673 | Dirbrowse_PopulateFiles(true); 674 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 675 | } 676 | } 677 | 678 | void Menu_ControlOptions(uint32_t input, TouchInfo touchInfo) 679 | { 680 | if ((input & KEY_RIGHT) || (input & KEY_LSTICK_RIGHT) || (input & KEY_RSTICK_RIGHT)) 681 | row++; 682 | else if ((input & KEY_LEFT) || (input & KEY_LSTICK_LEFT) || (input & KEY_RSTICK_LEFT)) 683 | row--; 684 | 685 | if ((input & KEY_DDOWN) || (input & KEY_LSTICK_DOWN) || (input & KEY_RSTICK_DOWN)) 686 | column++; 687 | else if ((input & KEY_DUP) || (input & KEY_LSTICK_UP) || (input & KEY_RSTICK_UP)) 688 | column--; 689 | 690 | Utils_SetMax(&row, 0, 1); 691 | Utils_SetMin(&row, 1, 0); 692 | 693 | Utils_SetMax(&column, 0, 2); 694 | Utils_SetMin(&column, 2, 0); 695 | 696 | if (input & KEY_A) 697 | { 698 | if (row == 0 && column == 0) 699 | MENU_DEFAULT_STATE = MENU_STATE_PROPERTIES; 700 | else if (row == 1 && column == 0) 701 | FileOptions_CreateFolder(); 702 | else if (row == 0 && column == 1) 703 | FileOptions_Rename(); 704 | else if (row == 1 && column == 1) 705 | HandleCopy(); 706 | else if (row == 0 && column == 2) 707 | HandleCut(); 708 | else if (row == 1 && column == 2) 709 | MENU_DEFAULT_STATE = MENU_STATE_DELETE_DIALOG; 710 | } 711 | 712 | if (input & KEY_B) 713 | { 714 | copy_status = false; 715 | cut_status = false; 716 | row = 0; 717 | column = 0; 718 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 719 | } 720 | 721 | if (input & KEY_X) 722 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 723 | 724 | if (touchInfo.state == TouchStart) 725 | { 726 | // Column 0 727 | if (touchInfo.firstTouch.py >= 188 && touchInfo.firstTouch.py <= 289) 728 | { 729 | column = 0; 730 | 731 | // Row 0 732 | if (touchInfo.firstTouch.px >= 354 && touchInfo.firstTouch.px <= 638) 733 | row = 0; 734 | // Row 1 735 | else if (touchInfo.firstTouch.px >= 639 && touchInfo.firstTouch.px <= 924) 736 | row = 1; 737 | } 738 | // Column 1 739 | else if (touchInfo.firstTouch.py >= 291 && touchInfo.firstTouch.py <= 392) 740 | { 741 | column = 1; 742 | 743 | // Row 0 744 | if (touchInfo.firstTouch.px >= 354 && touchInfo.firstTouch.px <= 638) 745 | row = 0; 746 | // Row 1 747 | else if (touchInfo.firstTouch.px >= 639 && touchInfo.firstTouch.px <= 924) 748 | row = 1; 749 | } 750 | // Column 2 751 | else if (touchInfo.firstTouch.py >= 393 && touchInfo.firstTouch.py <= 494) 752 | { 753 | column = 2; 754 | 755 | // Row 0 756 | if (touchInfo.firstTouch.px >= 354 && touchInfo.firstTouch.px <= 638) 757 | row = 0; 758 | // Row 1 759 | else if (touchInfo.firstTouch.px >= 639 && touchInfo.firstTouch.px <= 924) 760 | row = 1; 761 | } 762 | } 763 | else if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone) 764 | { 765 | // Touched outside 766 | if (tapped_outside(touchInfo, 350, 85, 930, 635)) 767 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 768 | // Column 0 769 | else if (touchInfo.firstTouch.py >= 188 && touchInfo.firstTouch.py <= 289) 770 | { 771 | // Row 0 772 | if (touchInfo.firstTouch.px >= 354 && touchInfo.firstTouch.px <= 638) 773 | MENU_DEFAULT_STATE = MENU_STATE_PROPERTIES; 774 | // Row 1 775 | else if (touchInfo.firstTouch.px >= 639 && touchInfo.firstTouch.px <= 924) 776 | FileOptions_CreateFolder(); 777 | } 778 | // Column 1 779 | else if (touchInfo.firstTouch.py >= 291 && touchInfo.firstTouch.py <= 392) 780 | { 781 | // Row 0 782 | if (touchInfo.firstTouch.px >= 354 && touchInfo.firstTouch.px <= 638) 783 | FileOptions_Rename(); 784 | // Row 1 785 | else if (touchInfo.firstTouch.px >= 639 && touchInfo.firstTouch.px <= 924) 786 | HandleCopy(); 787 | } 788 | // Column 2 789 | else if (touchInfo.firstTouch.py >= 393 && touchInfo.firstTouch.py <= 494) 790 | { 791 | // Row 0 792 | if (touchInfo.firstTouch.px >= 354 && touchInfo.firstTouch.px <= 638) 793 | HandleCut(); 794 | // Row 1 795 | else if (touchInfo.firstTouch.px >= 639 && touchInfo.firstTouch.px <= 924) 796 | MENU_DEFAULT_STATE = MENU_STATE_DELETE_DIALOG; 797 | } 798 | // Cancel Button 799 | else if (tapped_inside(touchInfo, 880 - options_cancel_width, 585 - options_cancel_height, 920 + options_cancel_width, 625 + options_cancel_height)) 800 | MENU_DEFAULT_STATE = MENU_STATE_HOME; 801 | } 802 | } 803 | 804 | void Menu_DisplayOptions(void) 805 | { 806 | SDL_DrawImage(RENDERER, config_dark_theme? options_dialog_dark : options_dialog, 350, 85); 807 | SDL_DrawText(RENDERER, Roboto, 370, 133, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "Actions"); 808 | 809 | TTF_SizeText(Roboto, "CANCEL", &options_cancel_width, &options_cancel_height); 810 | SDL_DrawText(RENDERER, Roboto, 900 - options_cancel_width, 605 - options_cancel_height, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "CANCEL"); 811 | 812 | if (row == 0 && column == 0) 813 | SDL_DrawRect(RENDERER, 354, 188, 287, 101, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 814 | else if (row == 1 && column == 0) 815 | SDL_DrawRect(RENDERER, 638, 188, 287, 101, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 816 | else if (row == 0 && column == 1) 817 | SDL_DrawRect(RENDERER, 354, 291, 287, 101, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 818 | else if (row == 1 && column == 1) 819 | SDL_DrawRect(RENDERER, 638, 291, 287, 101, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 820 | else if (row == 0 && column == 2) 821 | SDL_DrawRect(RENDERER, 354, 393, 287, 101, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 822 | else if (row == 1 && column == 2) 823 | SDL_DrawRect(RENDERER, 638, 393, 287, 101, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 824 | 825 | SDL_DrawText(RENDERER, Roboto, 385, 225, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Properties"); 826 | SDL_DrawText(RENDERER, Roboto, 385, 327, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Rename"); 827 | SDL_DrawText(RENDERER, Roboto, 385, 429, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, cut_status? "Paste" : "Move"); 828 | 829 | SDL_DrawText(RENDERER, Roboto, 672, 225, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "New folder"); 830 | SDL_DrawText(RENDERER, Roboto, 672, 327, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, copy_status? "Paste" : "Copy"); 831 | SDL_DrawText(RENDERER, Roboto, 672, 429, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Delete"); 832 | } 833 | --------------------------------------------------------------------------------