├── bootparam.yml ├── bhbb_dl ├── .gitignore ├── bhbb_dl.emd ├── SceLsdb.emd ├── include │ ├── promote.h │ ├── installer.h │ ├── main.h │ ├── offsets.h │ ├── sha1.h │ ├── zip.h │ ├── compressed_file.h │ ├── tgz.h │ ├── notice.h │ └── head_bin.h ├── src │ ├── libc2paf.c │ ├── compressed_file.cpp │ ├── offsets.c │ ├── sha1.c │ ├── minizip │ │ └── crypt.h │ ├── zip.cpp │ ├── tgz.cpp │ ├── main.cpp │ └── promote.c └── CMakeLists.txt ├── imgs ├── ui1.png ├── ui2.png ├── cbpsdb_icon.png ├── download1.png ├── download2.png ├── download3.png ├── download4.png └── vitadb_icon.png ├── sce_sys ├── icon0.png ├── pic0.png └── livearea │ └── contents │ ├── bg0.png │ ├── default_gate.png │ └── template.xml ├── module └── libcurl.suprx ├── resource ├── texture │ ├── bg.png │ ├── data_button.png │ ├── search_icon.png │ ├── top_bar_bg.png │ ├── missing_image.png │ ├── refresh_button.png │ ├── tex_info_icon.png │ ├── download_button.png │ ├── screenshot_icon.png │ ├── search_back_button.png │ └── tex_info_icon_glow.png ├── file │ └── bhbb_settings.xml └── locale │ ├── zh.xml │ ├── ko.xml │ ├── ja.xml │ ├── en.xml │ ├── fi.xml │ ├── ptbr.xml │ ├── es.xml │ ├── pl.xml │ ├── ru.xml │ ├── it.xml │ ├── de.xml │ └── fr.xml ├── common ├── print.h ├── bhbb_dl.h └── dialog.h ├── include ├── event.h ├── bhbb_settings.h ├── common.h ├── csv.h ├── utils.h ├── db │ ├── cbpsdb.h │ ├── vhbd.h │ ├── psphbb.h │ ├── vitadb.h │ └── source.h ├── pages │ ├── text_page.h │ ├── image_viewer.h │ ├── page.h │ └── app_viewer.h ├── error_codes.h ├── downloader.h ├── bhbb_locale.h ├── settings.h ├── bhbb_plugin.h └── tex_pool.h ├── .gitignore ├── param.sfx ├── src ├── event.cpp ├── pages │ ├── text_page.cpp │ ├── page.cpp │ └── image_viewer.cpp ├── paf_runtime.cpp ├── fread_line.c ├── downloader.cpp ├── main.cpp ├── db │ ├── source.cpp │ └── psphbb.cpp └── utils.cpp └── README.md /bootparam.yml: -------------------------------------------------------------------------------- 1 | APP_MEMSIZE: 32768 2 | ATTRIBUTE: 8 -------------------------------------------------------------------------------- /bhbb_dl/.gitignore: -------------------------------------------------------------------------------- 1 | include/notification_util.h 2 | build -------------------------------------------------------------------------------- /imgs/ui1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/imgs/ui1.png -------------------------------------------------------------------------------- /imgs/ui2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/imgs/ui2.png -------------------------------------------------------------------------------- /sce_sys/icon0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/sce_sys/icon0.png -------------------------------------------------------------------------------- /sce_sys/pic0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/sce_sys/pic0.png -------------------------------------------------------------------------------- /imgs/cbpsdb_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/imgs/cbpsdb_icon.png -------------------------------------------------------------------------------- /imgs/download1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/imgs/download1.png -------------------------------------------------------------------------------- /imgs/download2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/imgs/download2.png -------------------------------------------------------------------------------- /imgs/download3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/imgs/download3.png -------------------------------------------------------------------------------- /imgs/download4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/imgs/download4.png -------------------------------------------------------------------------------- /imgs/vitadb_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/imgs/vitadb_icon.png -------------------------------------------------------------------------------- /module/libcurl.suprx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/module/libcurl.suprx -------------------------------------------------------------------------------- /resource/texture/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/bg.png -------------------------------------------------------------------------------- /resource/texture/data_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/data_button.png -------------------------------------------------------------------------------- /resource/texture/search_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/search_icon.png -------------------------------------------------------------------------------- /resource/texture/top_bar_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/top_bar_bg.png -------------------------------------------------------------------------------- /resource/texture/missing_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/missing_image.png -------------------------------------------------------------------------------- /resource/texture/refresh_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/refresh_button.png -------------------------------------------------------------------------------- /resource/texture/tex_info_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/tex_info_icon.png -------------------------------------------------------------------------------- /sce_sys/livearea/contents/bg0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/sce_sys/livearea/contents/bg0.png -------------------------------------------------------------------------------- /resource/texture/download_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/download_button.png -------------------------------------------------------------------------------- /resource/texture/screenshot_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/screenshot_icon.png -------------------------------------------------------------------------------- /resource/texture/search_back_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/search_back_button.png -------------------------------------------------------------------------------- /resource/texture/tex_info_icon_glow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/resource/texture/tex_info_icon_glow.png -------------------------------------------------------------------------------- /sce_sys/livearea/contents/default_gate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ibrahim778/BetterHomebrewBrowser/HEAD/sce_sys/livearea/contents/default_gate.png -------------------------------------------------------------------------------- /bhbb_dl/bhbb_dl.emd: -------------------------------------------------------------------------------- 1 | Module: bhbb_dl major_version: 3 minor_version: 0 2 | sceModuleInfo_type: 6 3 | module_function: module_start localname: module_start 4 | module_function: module_stop localname: module_stop -------------------------------------------------------------------------------- /common/print.h: -------------------------------------------------------------------------------- 1 | #ifndef BHBB_PRINT_H 2 | #define BHBB_PRINT_H 3 | #ifdef _DEBUG 4 | #define print(...) sceClibPrintf(__VA_ARGS__) 5 | #else 6 | #define print(...) {(void)SCE_NULL;} 7 | #endif 8 | 9 | #endif -------------------------------------------------------------------------------- /bhbb_dl/SceLsdb.emd: -------------------------------------------------------------------------------- 1 | emd: 1 2 | 3 | Library: SceLsdb attr: auto_export 4 | Library: SceLsdb version: 1 5 | Library: SceLsdb stubfile: "SceLsdb_stub" 6 | Library: SceLsdb nidsuffix: "" 7 | Library: SceLsdb libnamenid: 0x6BC25E17 8 | 9 | Library: SceLsdb function: sceLsdbSendNotification nidvalue: 0x315B9FD6 10 | -------------------------------------------------------------------------------- /sce_sys/livearea/contents/template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | bg0.png 5 | 6 | 7 | default_gate.png 8 | 9 | 10 | -------------------------------------------------------------------------------- /include/event.h: -------------------------------------------------------------------------------- 1 | // From NetStream (https://github.com/GrapheneCt/NetStream) by @GrapheneCt 2 | 3 | #ifndef _EVENT_UTIL_H_ 4 | #define _EVENT_UTIL_H_ 5 | 6 | #include 7 | #include 8 | 9 | using namespace paf; 10 | 11 | namespace event 12 | { 13 | void BroadcastGlobalEvent(Plugin *workPlugin, uint32_t type, int32_t d0 = 0, int32_t d1 = 0, int32_t d2 = 0, int32_t d3 = 0); 14 | }; 15 | 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.fleet 2 | /.vscode 3 | /.vs 4 | /cmake-build-debug-vdsuite 5 | /build 6 | /build.bat 7 | /build.sh 8 | /run.sh 9 | /resource/rco/cxml 10 | /resource/*.rco 11 | /resource/rco/src/locale/*.rcs 12 | /resource/bhbb_plugin.rco 13 | /resource/libScePafPreload.suprx 14 | /build_mac.sh 15 | /.DS_Store 16 | /clean.sh 17 | /resource/bhbb_plugin.rcd 18 | *.DS_Store 19 | /update_rco.sh 20 | bhbb_dl/.vscode 21 | /genhashheaders.py 22 | ._* 23 | /.idea 24 | /run.bat 25 | *.rcs -------------------------------------------------------------------------------- /include/bhbb_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef _bhbb_settings_H_ 2 | #define _bhbb_settings_H_ 3 | 4 | /* This file was generated automatically by genhashheaders.py */ 5 | 6 | #define bhbb_options 0xF6C9D4C0 7 | #define list_source 0x92EFFF4E 8 | #define list_source_00 0xC862B99A 9 | #define list_source_01 0x2B44C5AA 10 | #define list_source_02 0x2D5A2E6B 11 | #define list_source_03 0xFD1C515D 12 | #define verinfo_setting 0x45EB30EB 13 | #define label_verinfo 0x804FF666 14 | #define credits_setting 0x65B3A7E9 15 | #define label_credinfo 0x85D107C3 16 | #define button_dl_dev 0x05E1FC07 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /common/bhbb_dl.h: -------------------------------------------------------------------------------- 1 | #ifndef BHBB_DL_H 2 | #define BHBB_DL_H 3 | 4 | #define BHBB_DL_MAGIC 'BG' 5 | #define BHBB_DL_CFG_VER 3 6 | 7 | #pragma pack(push, 1) 8 | struct pdb_flags_t // size is 0xB 9 | { 10 | char unk[3]; 11 | uint16_t size; 12 | char unk2[2]; 13 | uint16_t size2; 14 | char unk3[2]; 15 | }; 16 | #pragma pack(pop) 17 | 18 | typedef enum 19 | { 20 | BGDLTarget_CompressedFile = 0, 21 | BGDLTarget_App = 1 22 | } BGDLTarget; 23 | 24 | typedef struct BGDLParam 25 | { 26 | uint16_t magic; // bhbb_dl magic | cfg version 27 | uint8_t type; // 0 - zip, 1 - app 28 | char path[0x100]; // This is used when type is set to 0 (custom path) 29 | char data_icon[0x100]; // Fallback icon for operating with data files and while saving the vpk without install 30 | } BGDLParam; 31 | 32 | #endif -------------------------------------------------------------------------------- /param.sfx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01.00 4 | 32832 5 | 0 6 | 16 7 | gdc 8 | HB0000-BHBB00001_00-0000000000000000 9 | 0 10 | 0 11 | 1 12 | 03.600 13 | 56623104 14 | 1048576 15 | Homebrew Browser 16 | Homebrew Browser 17 | BHBB00001 18 | 05.00 19 | 20 | -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _COMMON_H_ 20 | #define _COMMON_H_ 21 | 22 | #include 23 | 24 | extern paf::Plugin *g_appPlugin; 25 | 26 | #endif -------------------------------------------------------------------------------- /bhbb_dl/include/promote.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _PROMOTE_H_ 20 | #define _PROMOTE_H_ 21 | 22 | #include 23 | 24 | SCE_CDECL_BEGIN 25 | 26 | int promoteApp(const char* path, const char *out_titleID); 27 | 28 | SCE_CDECL_END 29 | 30 | #endif -------------------------------------------------------------------------------- /bhbb_dl/include/installer.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _INSTALLER_H_ 20 | #define _INSTALLER_H_ 21 | 22 | #include "bhbb_dl.h" 23 | 24 | int ProcessExport(::uint32_t id, const char *name, const char *path, const char *icon_path, BGDLParam *param); 25 | 26 | #endif -------------------------------------------------------------------------------- /bhbb_dl/include/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _MAIN_H_ 20 | #define _MAIN_H_ 21 | 22 | #include 23 | 24 | SCE_CDECL_BEGIN 25 | 26 | int module_start(size_t args, void *argp); 27 | int module_stop(size_t args, void *argp); 28 | 29 | SCE_CDECL_END 30 | 31 | #endif -------------------------------------------------------------------------------- /bhbb_dl/include/offsets.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _OFFSETS_H_ 20 | #define _OFFSETS_H_ 21 | 22 | #include 23 | 24 | SCE_CDECL_BEGIN 25 | 26 | int GetShellOffsets(uint32_t nid, uint32_t *exp_off, uint32_t *rec_off, uint32_t *notif_off); 27 | 28 | SCE_CDECL_END 29 | 30 | #endif -------------------------------------------------------------------------------- /resource/file/bhbb_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/event.cpp: -------------------------------------------------------------------------------- 1 | // From NetStream (https://github.com/GrapheneCt/NetStream) by @GrapheneCt 2 | 3 | #include 4 | #include 5 | 6 | #include "event.h" 7 | 8 | static void PostEventRecursive(ui::Widget *target, int32_t type, ui::Event *ev) 9 | { 10 | for (int i = 0; i < target->GetChildrenNum(); i++) 11 | { 12 | ui::Widget *subtarget = target->GetChild(i); 13 | if (subtarget) 14 | { 15 | PostEventRecursive(subtarget, type, ev); 16 | } 17 | } 18 | target->DoEvent(type, ev); 19 | } 20 | 21 | void event::BroadcastGlobalEvent(Plugin *workPlugin, uint32_t type, int32_t d0, int32_t d1, int32_t d2, int32_t d3) 22 | { 23 | ui::Event ev(ui::EV_COMMAND, ui::Event::MODE_DISPATCH, ui::Event::ROUTE_FORWARD, 0, d0, d1, d2, d3); 24 | resource::ResourceObj *res = workPlugin->GetResource(); 25 | if (res) 26 | { 27 | cxml::Element el = res->GetTableElement(resource::TableType_Page); 28 | el = el.GetFirstChild(); 29 | while (el == true) 30 | { 31 | uint32_t pageId = 0; 32 | cxml::util::GetIDHash(el, "id", &pageId); 33 | ui::Widget *target = workPlugin->PageRoot(pageId); 34 | if (target) 35 | { 36 | PostEventRecursive(target, type, &ev); 37 | } 38 | el = el.GetNextSibling(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /include/csv.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef CSV_DOT_H_INCLUDE_GUARD 20 | #define CSV_DOT_H_INCLUDE_GUARD 21 | 22 | #include 23 | #include 24 | 25 | #define CSV_ERR_LONGLINE -1 26 | #define CSV_ERR_NO_MEMORY -2 27 | 28 | // SCE_CDECL_BEGIN 29 | 30 | char *fread_line(sce_paf_FILE *fp, int max_line_size, int *done, int *err); 31 | 32 | // SCE_CDECL_END 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _UTILS_H_ 20 | #define _UTILS_H_ 21 | 22 | #include 23 | 24 | namespace Utils 25 | { 26 | void InitMusic(); 27 | SceVoid StartBGDL(); 28 | 29 | void HttpsToHttp(const char *src, paf::string &outURL); 30 | bool IsValidURLSCE(const char *url); //Can this URL be used with SceHttp? 31 | 32 | int DownloadFile(const char *url, const char *path); 33 | void Decapitalise(wchar_t *wcstring); 34 | }; 35 | #endif -------------------------------------------------------------------------------- /bhbb_dl/src/libc2paf.c: -------------------------------------------------------------------------------- 1 | // From bgvpk by @SKGleba. Under MIT 2 | // (https://github.com/SKGleba/VitaTools/tree/main/bgvpk/source) 3 | 4 | void *malloc(int size) { 5 | return sce_paf_malloc(size); 6 | } 7 | 8 | void free(void *ptr) { 9 | sce_paf_free(ptr); 10 | } 11 | 12 | void *fopen(const char* file, const char* mode) { 13 | return sce_paf_fopen(file, mode); 14 | } 15 | 16 | int fclose(void *fp) { 17 | return sce_paf_fclose(fp); 18 | } 19 | 20 | unsigned int fread(void* buf, int size, int count, void* fp) { 21 | return sce_paf_fread(buf, size, count, fp); 22 | } 23 | 24 | int fwrite(void* buf, int size, int count, void* fp) { 25 | return sce_paf_fwrite(buf, size, count, fp); 26 | } 27 | 28 | int fseek(void* fp, long offset, int whence) { 29 | return sce_paf_fseek(fp, offset, whence); 30 | } 31 | 32 | long ftell(void* fp) { 33 | return sce_paf_ftell(fp); 34 | } 35 | 36 | void* memset(void* b, int c, int sz) { 37 | return sce_paf_memset(b, c, sz); 38 | } 39 | 40 | void* memcpy(void* dst, void* src, int sz) { 41 | return sce_paf_memcpy(dst, src, sz); 42 | } 43 | 44 | int strcmp(const char* str1, const char* str2) { 45 | return sce_paf_strcmp(str1, str2); 46 | } 47 | 48 | int strlen(const char *str) { 49 | return sce_paf_strlen(str); 50 | } 51 | 52 | char* strncpy(char* str1, const char *str2, int len) { 53 | return sce_paf_strncpy(str1, str2, len); 54 | } -------------------------------------------------------------------------------- /bhbb_dl/include/sha1.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: sha1.h 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: Defines the API for the corresponding SHA1 implementation. 7 | *********************************************************************/ 8 | 9 | #ifndef SHA1_H 10 | #define SHA1_H 11 | 12 | /*************************** HEADER FILES ***************************/ 13 | #include 14 | #include 15 | 16 | /****************************** MACROS ******************************/ 17 | #define SHA1_BLOCK_SIZE 20 // SHA1 outputs a 20 byte digest 18 | 19 | /**************************** DATA TYPES ****************************/ 20 | typedef uint8_t BYTE; // 8-bit byte 21 | typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines 22 | 23 | typedef struct { 24 | BYTE data[64]; 25 | WORD datalen; 26 | unsigned long long bitlen; 27 | WORD state[5]; 28 | WORD k[4]; 29 | } SHA1_CTX; 30 | 31 | /*********************** FUNCTION DECLARATIONS **********************/ 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | void sha1_init(SHA1_CTX* ctx); 37 | void sha1_update(SHA1_CTX* ctx, const BYTE data[], size_t len); 38 | void sha1_final(SHA1_CTX* ctx, BYTE hash[]); 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | #endif // SHA1_H -------------------------------------------------------------------------------- /include/db/cbpsdb.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _CPBSDB_H_ 20 | #define _CPBSDB_H_ 21 | 22 | #include 23 | 24 | #include "source.h" 25 | 26 | class CBPSDB : public Source 27 | { 28 | public: 29 | CBPSDB(); 30 | virtual ~CBPSDB(); 31 | 32 | int Parse(); 33 | int DownloadIndex(bool forceRefresh); 34 | int GetDescription(Entry &entry, paf::wstring& out); 35 | int GetDownloadURL(Entry &entry, paf::string& out); 36 | int GetDataURL(Entry &entry, paf::string& out); 37 | wchar_t *GetName() 38 | { 39 | return L"CBPS DB"; 40 | } 41 | 42 | protected: 43 | static int GetSCECompatibleURL(std::vector &list, paf::string &out); 44 | 45 | }; 46 | 47 | #endif -------------------------------------------------------------------------------- /bhbb_dl/include/zip.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _ZIP_H_ 20 | #define _ZIP_H_ 21 | 22 | #include 23 | #include 24 | 25 | #include "compressed_file.h" 26 | #include "minizip/unzip.h" 27 | 28 | class Zipfile : public CompressedFile 29 | { 30 | public: 31 | enum 32 | { 33 | ZIP_CUNK_SIZE = SCE_KERNEL_128KiB 34 | }; 35 | 36 | Zipfile(const paf::string filePath); 37 | ~Zipfile(); 38 | 39 | virtual int Decompress(const paf::string outPath, ProgressCallback progressCB, void *progressData) override; 40 | virtual int CalculateUncompressedSize() override; 41 | 42 | private: 43 | unzFile handle; 44 | unz_global_info globalInfo; 45 | char *readBuff; 46 | }; 47 | 48 | #endif //_ZIP_H_ -------------------------------------------------------------------------------- /include/pages/text_page.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _TEXT_PAGE_H_ 20 | #define _TEXT_PAGE_H_ 21 | 22 | #include 23 | 24 | #include "page.h" 25 | 26 | namespace page 27 | { 28 | class TextPage : public page::Base 29 | { 30 | public: 31 | TextPage(); 32 | 33 | TextPage(const paf::string& txt); 34 | TextPage(const paf::wstring& txt); 35 | TextPage(uint32_t strHash); 36 | 37 | virtual ~TextPage(){} 38 | 39 | virtual void SetText(const paf::string& txt); 40 | virtual void SetText(uint32_t hash); 41 | virtual void SetText(const paf::wstring& str); 42 | 43 | protected: 44 | paf::ui::Text *text; 45 | }; 46 | }; 47 | 48 | #endif -------------------------------------------------------------------------------- /include/pages/image_viewer.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _IMAGE_VIEWER_H_ 20 | #define _IMAGE_VIEWER_H_ 21 | 22 | #include 23 | #include 24 | 25 | #include "page.h" 26 | 27 | class ImageViewer : page::Base 28 | { 29 | public: 30 | ImageViewer(const char *path = nullptr); 31 | 32 | int Load(const char *path); 33 | void LoadAsync(const char *path); 34 | 35 | protected: 36 | class DisplayJob : public paf::job::JobItem 37 | { 38 | public: 39 | using paf::job::JobItem::JobItem; 40 | 41 | void Run(); 42 | void Finish(); 43 | 44 | ImageViewer *workPage; 45 | paf::string path; 46 | }; 47 | 48 | int LoadLocal(const char *path); 49 | int LoadNet(const char *path); 50 | }; 51 | 52 | #endif -------------------------------------------------------------------------------- /include/error_codes.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _ERROR_CODES_H_ 20 | #define _ERROR_CODES_H_ 21 | 22 | #define SCE_PAF_ERROR_ERRNO_ENOENT (0x80AF5022) 23 | #define SCE_PAF_ERROR_ERRNO_EBADF (0x80AF5021) 24 | #define SCE_PAF_ERROR_ERRNO_ENOMEM (0x80AF5003) 25 | #define SCE_PAF_ERROR_ERRNO_EACCES (0x80AF5025) 26 | #define SCE_PAF_ERROR_ERRNO_EFAULT (0x80AF5002) 27 | #define SCE_PAF_ERROR_ERRNO_EINVAL (0x80AF5002) 28 | #define SCE_PAF_ERROR_ERRNO_EBUSY (0x80AF5041) 29 | #define SCE_PAF_ERROR_ERRNO_EEXIST (0x80AF5026) 30 | #define SCE_PAF_ERROR_ERRNO_ENODEV (0x80AF5024) 31 | #define SCE_PAF_ERROR_ERRNO_EMFILE (0x80AF5023) 32 | #define SCE_PAF_ERROR_ERRNO_ENOSPC (0x80AF5027) 33 | #define SCE_PAF_ERROR_ERRNO_EROFS (0x80AF5004) 34 | 35 | #endif -------------------------------------------------------------------------------- /include/db/vhbd.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _VHBDB_H_ 20 | #define _VHBDB_H_ 21 | 22 | #include 23 | 24 | #include "source.h" 25 | 26 | class VHBD : public Source 27 | { 28 | public: 29 | VHBD(); 30 | virtual ~VHBD(); 31 | 32 | int Parse(); 33 | int DownloadIndex(bool forceRefresh); 34 | int GetDescription(Entry &entry, paf::wstring& out); 35 | int GetDownloadURL(Entry &entry, paf::string& out); 36 | int GetDataURL(Entry &entry, paf::string& out); 37 | wchar_t *GetName() 38 | { 39 | return L"Vita Homebrew DB"; 40 | } 41 | 42 | protected: 43 | static int GetSCECompatibleURL(std::vector &list, paf::string &out); 44 | 45 | enum Category 46 | { 47 | APP = 0, 48 | GAME, 49 | EMU 50 | }; 51 | }; 52 | 53 | #endif -------------------------------------------------------------------------------- /include/pages/page.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _PAGE_H_ 20 | #define _PAGE_H_ 21 | 22 | #include 23 | 24 | namespace page 25 | { 26 | class Base 27 | { 28 | public: 29 | Base(uint32_t hash, paf::Plugin::PageOpenParam openParam, paf::Plugin::PageCloseParam closeParam); 30 | virtual ~Base(); 31 | 32 | uint32_t GetHash(); 33 | 34 | paf::ui::Scene *root; 35 | 36 | static void DeleteCurrentPage(); 37 | static page::Base *GetCurrentPage(); 38 | static void DefaultBackButtonCB(uint32_t eventID, paf::ui::Handler *self, paf::ui::Event *event, ScePVoid pUserData); 39 | 40 | protected: 41 | paf::ui::CornerButton *backButton; 42 | paf::Plugin::PageCloseParam closeParam; 43 | }; 44 | 45 | } 46 | 47 | #endif -------------------------------------------------------------------------------- /include/db/psphbb.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _PSPHBB_H_ 20 | #define _PSPHBB_H_ 21 | 22 | #include 23 | 24 | #include "source.h" 25 | #include "bhbb_dl.h" 26 | 27 | class PSPHBDB : public Source 28 | { 29 | public: 30 | PSPHBDB(); 31 | virtual ~PSPHBDB(); 32 | 33 | int Parse(); 34 | int DownloadIndex(bool forceRefresh); 35 | int GetDescription(Entry &entry, paf::wstring& out); 36 | int GetDownloadURL(Entry &entry, paf::string& out); 37 | int GetDataURL(Entry &entry, paf::string& out); 38 | wchar_t *GetName() 39 | { 40 | return L"PSP Homebrew Browser"; 41 | } 42 | 43 | int CreateDownloadParam(Entry &entry, BGDLParam ¶m) override; 44 | 45 | protected: 46 | enum Category 47 | { 48 | GAME = 1, 49 | UTIL, 50 | EMU, 51 | PORT 52 | }; 53 | }; 54 | 55 | #endif -------------------------------------------------------------------------------- /bhbb_dl/include/compressed_file.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _COMPRESSED_FILE_H_ 20 | #define _COMPRESSED_FILE_H_ 21 | 22 | #include 23 | #include 24 | 25 | class CompressedFile 26 | { 27 | public: 28 | typedef void (*ProgressCallback)(const char *fname, uint64_t current, uint64_t total, void *pUserData); 29 | 30 | CompressedFile(); 31 | virtual ~CompressedFile(); 32 | 33 | virtual int Decompress(const paf::string outPath, ProgressCallback progressCB, void *progressData) = 0; 34 | virtual int CalculateUncompressedSize() = 0; 35 | 36 | int GetLastError() 37 | { 38 | return error; 39 | } 40 | size_t GetUncompressedSize() 41 | { 42 | return uncompressedSize; 43 | } 44 | 45 | static paf::common::SharedPtr Create(const char *path); 46 | 47 | protected: 48 | size_t uncompressedSize; 49 | int error; 50 | }; 51 | 52 | #endif //_COMPRESSED_FILE_H_ -------------------------------------------------------------------------------- /include/db/vitadb.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _VITADB_H_ 20 | #define _VITADB_H_ 21 | 22 | #include 23 | 24 | #include "source.h" 25 | 26 | class VitaDB : public Source 27 | { 28 | public: 29 | VitaDB(); 30 | virtual ~VitaDB(); 31 | 32 | int Parse(); 33 | int DownloadIndex(bool forceRefresh); 34 | int GetDescription(Entry &entry, paf::wstring& out); 35 | int GetDownloadURL(Entry &entry, paf::string& out); 36 | int GetDataURL(Entry &entry, paf::string& out); 37 | wchar_t *GetName() 38 | { 39 | return L"Vita DB"; 40 | } 41 | 42 | protected: 43 | static int GetSCECompatibleURL(std::vector &urlList, paf::string &out); 44 | static size_t SaveCore(char *ptr, size_t size, size_t nmeb, VitaDB *workDB); 45 | 46 | size_t buffSize; 47 | char *buff; 48 | 49 | enum Category 50 | { 51 | GAME = 1, 52 | PORT = 2, 53 | UTIL = 4, 54 | EMU = 5, 55 | }; 56 | }; 57 | 58 | #endif -------------------------------------------------------------------------------- /bhbb_dl/src/compressed_file.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "compressed_file.h" 22 | #include "print.h" 23 | #include "zip.h" 24 | #include "tgz.h" 25 | 26 | using namespace paf; 27 | 28 | CompressedFile::CompressedFile() 29 | { 30 | uncompressedSize = 0; 31 | error = 0; 32 | } 33 | 34 | CompressedFile::~CompressedFile() 35 | { 36 | 37 | } 38 | 39 | // Check the extension at the end of the string and return the apporpriate handle 40 | paf::common::SharedPtr CompressedFile::Create(const char *path) 41 | { 42 | auto len = sce_paf_strlen(path); 43 | 44 | if(sce_paf_strcasecmp(&path[len - 7], ".tar.gz") == 0) 45 | return common::SharedPtr(new TgzFile(path)); 46 | else if(sce_paf_strcasecmp(&path[len - 4], ".vpk") == 0 || sce_paf_strcasecmp(&path[len - 4], ".zip") == 0) 47 | return common::SharedPtr(new Zipfile(path)); 48 | 49 | return common::SharedPtr(nullptr); 50 | } -------------------------------------------------------------------------------- /src/pages/text_page.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "pages/text_page.h" 22 | #include "bhbb_plugin.h" 23 | #include "common.h" 24 | #include "print.h" 25 | 26 | using namespace paf; 27 | 28 | page::TextPage::TextPage(): 29 | page::Base( 30 | text_page, 31 | Plugin::PageOpenParam(false, 200, Plugin::TransitionType_SlideFromBottom), 32 | Plugin::PageCloseParam(true) 33 | ), text(SCE_NULL) 34 | { 35 | text = (ui::Text *)root->FindChild(IDParam(page_text)); 36 | } 37 | 38 | page::TextPage::TextPage(const string& displayText):TextPage() 39 | { 40 | SetText(displayText); 41 | } 42 | 43 | page::TextPage::TextPage(const wstring& displayText):TextPage() 44 | { 45 | SetText(displayText); 46 | } 47 | 48 | void page::TextPage::SetText(const string& text) 49 | { 50 | wstring text16; 51 | common::Utf8ToUtf16(text, &text16); 52 | 53 | this->text->SetString(text16); 54 | } 55 | 56 | void page::TextPage::SetText(const wstring& text) 57 | { 58 | this->text->SetString(text); 59 | } 60 | 61 | void page::TextPage::SetText(uint32_t hash) 62 | { 63 | text->SetString(g_appPlugin->GetString(IDParam(hash))); 64 | } 65 | 66 | page::TextPage::TextPage(uint32_t hash):TextPage() 67 | { 68 | SetText(hash); 69 | } 70 | -------------------------------------------------------------------------------- /include/downloader.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | Copyright (C) 2023 GrapheneCt 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | // This file is an extended version of @GrapheneCt's downloader.h used in EMPV-A 21 | 22 | #ifndef _ELEVENMPV_DOWNLOADER_H_ 23 | #define _ELEVENMPV_DOWNLOADER_H_ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "bhbb_dl.h" 31 | 32 | using namespace paf; 33 | 34 | class Downloader 35 | { 36 | public: 37 | 38 | enum 39 | { 40 | DownloaderEvent = (ui::Handler::CB_STATE + 0x60000), 41 | }; 42 | 43 | Downloader(); 44 | 45 | ~Downloader(); 46 | 47 | int32_t Enqueue(Plugin *workPlugin, const char *url, const char *name, const char *icon_path = nullptr, BGDLParam *param = nullptr); 48 | 49 | int32_t EnqueueAsync(Plugin *workPlugin, const char *url, const char *name); 50 | 51 | static Downloader *GetCurrentInstance(); 52 | 53 | private: 54 | 55 | class AsyncEnqueue : public job::JobItem 56 | { 57 | public: 58 | 59 | using job::JobItem::JobItem; 60 | 61 | ~AsyncEnqueue() {} 62 | 63 | void Run() 64 | { 65 | Downloader *pdownloader = (Downloader *)downloader; 66 | pdownloader->Enqueue(plugin, url8.c_str(), name8.c_str()); 67 | } 68 | 69 | void Finish() {} 70 | 71 | paf::string url8; 72 | paf::string name8; 73 | void *downloader; 74 | paf::Plugin *plugin; 75 | }; 76 | 77 | sce::Download dw; 78 | 79 | static Downloader *s_currentInstance; 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /common/dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef _DIALOG_H_ 2 | #define _DIALOG_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace paf; 9 | 10 | namespace dialog 11 | { 12 | enum ButtonCode 13 | { 14 | ButtonCode_X = 1, 15 | ButtonCode_Ok, 16 | ButtonCode_Cancel, 17 | ButtonCode_Yes, 18 | ButtonCode_No, 19 | ButtonCode_Button1 = ButtonCode_Yes, 20 | ButtonCode_Button2 = ButtonCode_No, 21 | ButtonCode_Button3 = ButtonCode_Cancel 22 | }; 23 | 24 | typedef void(*EventHandler)(ButtonCode buttonCode, ScePVoid pUserArg); 25 | 26 | int Current(); 27 | 28 | SceVoid OpenPleaseWait(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageText, SceBool withCancel = SCE_FALSE, EventHandler eventHandler= SCE_NULL, ScePVoid userArg = SCE_NULL); 29 | 30 | SceVoid OpenYesNo(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageText, EventHandler eventHandler = SCE_NULL, ScePVoid userArg = SCE_NULL); 31 | 32 | SceVoid OpenOk(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageText, EventHandler eventHandler = SCE_NULL, ScePVoid userArg = SCE_NULL); 33 | 34 | SceVoid OpenError(Plugin *workPlugin, SceInt32 errorCode, const wchar_t *messageText = SCE_NULL, EventHandler eventHandler = SCE_NULL, ScePVoid userArg = SCE_NULL); 35 | 36 | SceVoid OpenTwoButton( 37 | Plugin *workPlugin, 38 | const wchar_t *titleText, 39 | const wchar_t *messageText, 40 | SceUInt32 button1TextHashref, 41 | SceUInt32 button2TextHashref, 42 | EventHandler eventHandler = SCE_NULL, 43 | ScePVoid userArg = SCE_NULL); 44 | 45 | SceVoid OpenThreeButton( 46 | Plugin *workPlugin, 47 | const wchar_t *titleText, 48 | const wchar_t *messageText, 49 | SceUInt32 button1TextHashref, 50 | SceUInt32 button2TextHashref, 51 | SceUInt32 button3TextHashref, 52 | EventHandler eventHandler = SCE_NULL, 53 | ScePVoid userArg = SCE_NULL); 54 | 55 | ui::ListView *dialog::OpenListView( 56 | Plugin *workPlugin, 57 | const wchar_t *titleText, 58 | EventHandler eventHandler = SCE_NULL, 59 | ScePVoid userArg = SCE_NULL); 60 | 61 | ui::ScrollView *dialog::OpenScrollView( 62 | Plugin *workPlugin, 63 | const wchar_t *titleText, 64 | EventHandler eventHandler = SCE_NULL, 65 | ScePVoid userArg = SCE_NULL); 66 | 67 | SceVoid Close(); 68 | 69 | SceVoid WaitEnd(); 70 | }; 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /include/bhbb_locale.h: -------------------------------------------------------------------------------- 1 | #ifndef __BHBB_LOCALE_H__ 2 | #define __BHBB_LOCALE_H__ 3 | 4 | //generated by acdc from C:/Users/ibrahim/Documents/Projects/BetterHomebrewBrowser/resource/locale/fi.xml 5 | 6 | #define msg_settings_credits (0x0ccd2374) 7 | #define msg_download_queued (0x0dbe5bd1) 8 | #define msg_desc_error (0x0e709182) 9 | #define db_category_emu (0x10796e99) 10 | #define msg_no_desc (0x216ed54a) 11 | #define msg_options (0x28b9e30e) 12 | #define msg_sort_header (0x2d6d0406) 13 | #define download_button_text (0x2dd858f7) 14 | #define msg_error_parse (0x31e50d81) 15 | #define msg_settings_verinfo (0x32a4c75a) 16 | #define msg_screenshot_error (0x36159610) 17 | #define msg_list_header (0x3702a77b) 18 | #define db_category_app (0x49c5b97d) 19 | #define msg_icon_no_source (0x4bd16ecf) 20 | #define msg_settings_downloadInterval (0x59cd4e83) 21 | #define db_category_all (0x5a1b9eeb) 22 | #define msg_entry_error (0x5b05fe46) 23 | #define msg_donations (0x5f28786d) 24 | #define msg_wait (0x632b6733) 25 | #define msg_error_ssl (0x681e4b52) 26 | #define msg_downloading_icon (0x6bc3de8e) 27 | #define msg_check_update (0x6cea58d9) 28 | #define msg_net_fix (0x710cf737) 29 | #define msg_sort_alpha (0x7454a689) 30 | #define data_dl_name (0x797ef6b3) 31 | #define data_button_text (0x7b1129f6) 32 | #define msg_sort_mostrecent (0x8130a636) 33 | #define db_category_single_app (0x8bc97306) 34 | #define msg_wait_fix (0x97c937d8) 35 | #define msg_donate (0x9a8a10c9) 36 | #define msg_icon_error (0x9ac23d64) 37 | #define msg_sort_oldfirst (0x9e70b72d) 38 | #define msg_error_index (0x9f897b1c) 39 | #define db_category_unk (0x9fa785c1) 40 | #define msg_sort_alpharev (0xa9ca93f3) 41 | #define msg_download_nosize (0xad11d949) 42 | #define icons_dl_name (0xb3fb0b3a) 43 | #define msg_settings_source (0xb5fcdd42) 44 | #define db_category_game (0xb8963f17) 45 | #define db_category_util (0xbcd10f2f) 46 | #define db_category_single_emu (0xbeb9cfb6) 47 | #define msg_src_err (0xc38f3a4b) 48 | #define msg_download_error (0xca898cb7) 49 | #define msg_icon_redownload (0xcb6c8521) 50 | #define msg_sort_mostdownloaded (0xd184dc6f) 51 | #define db_category_single_util (0xd4357290) 52 | #define db_category_single_port (0xdb8349b4) 53 | #define msg_settings_downloadInterval_always (0xdf222133) 54 | #define msg_sort_leastdownloaded (0xe1653439) 55 | #define db_category_single_game (0xe4362a49) 56 | #define msg_error_net (0xeb4b3b29) 57 | #define msg_no_itls (0xee9e64c5) 58 | #define db_category_port (0xf3001db9) 59 | 60 | #endif // __BHBB_LOCALE_H__ 61 | -------------------------------------------------------------------------------- /bhbb_dl/src/offsets.c: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "offsets.h" 20 | 21 | //Originally by @SKGleba for bgvpk 22 | 23 | // This is (glebs) pain 24 | int GetShellOffsets(uint32_t nid, uint32_t *exp_off, uint32_t *rec_off, uint32_t *notif_off) 25 | { 26 | *exp_off = *rec_off = *notif_off = 0; 27 | switch (nid) 28 | { 29 | case 0x0552F692: // 3.60 retail 30 | { 31 | *exp_off = 0x1163F6; 32 | *rec_off = 0x11B5E4; 33 | *notif_off = 0xFD8F4; 34 | break; 35 | } 36 | 37 | case 0x6CB01295: // 3.60 PDEL 38 | { 39 | *exp_off = 0x111D5A; 40 | *rec_off = 0x116F48; 41 | *notif_off = 0xF9258; 42 | break; 43 | } 44 | 45 | case 0xEAB89D5C: // 3.60 PTEL 46 | { 47 | *exp_off = 0x112756; 48 | *rec_off = 0x117944; 49 | *notif_off = 0xF9C54; 50 | break; 51 | } 52 | 53 | case 0x5549BF1F: // 3.65 retail 54 | case 0x34B4D82E: // 3.67 retail 55 | case 0x12DAC0F3: // 3.68 retail 56 | case 0x0703C828: // 3.69 retail 57 | case 0x2053B5A5: // 3.70 retail 58 | case 0xF476E785: // 3.71 retail 59 | case 0x939FFBE9: // 3.72 retail 60 | case 0x734D476A: // 3.73 retail 61 | { 62 | *exp_off = 0x11644E; 63 | *rec_off = 0x11B63C; 64 | *notif_off = 0xFD94C; 65 | break; 66 | } 67 | 68 | case 0xE6A02F2B: // 3.65 PDEL 69 | { 70 | *exp_off = 0x111DB2; 71 | *rec_off = 0x116FA0; 72 | *notif_off = 0xF92B0; 73 | break; 74 | } 75 | 76 | case 0x587F9CED: // 3.65 PTEL 77 | { 78 | *exp_off = 0x1127AE; 79 | *rec_off = 0x11799C; 80 | *notif_off = 0xF9CAC; 81 | break; 82 | } 83 | default: 84 | return -1; 85 | } 86 | if (!*exp_off || !*rec_off || !*notif_off) 87 | return -1; 88 | return 0; 89 | } -------------------------------------------------------------------------------- /include/settings.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _SETTINGS_H_ 20 | #define _SETTINGS_H_ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "db/source.h" 27 | #include "bhbb_locale.h" 28 | 29 | class Settings 30 | { 31 | public: 32 | enum 33 | { 34 | SettingsEvent = (paf::ui::Handler::CB_STATE + 0x30000), 35 | }; 36 | 37 | enum SettingsEvent 38 | { 39 | SettingsEvent_ValueChange 40 | }; 41 | 42 | Settings(); 43 | ~Settings(); 44 | 45 | static Settings *GetInstance(); 46 | static sce::AppSettings *GetAppSettings(); 47 | void Open(); 48 | void Close(); 49 | 50 | static void OpenCB(int id, paf::ui::Handler *widget, paf::ui::Event *event, void *data); 51 | 52 | int source; 53 | 54 | private: 55 | static sce::AppSettings *appSettings; 56 | 57 | static void CBOnStartPageTransition(const char *elementId, int32_t type); 58 | 59 | static void CBOnPageActivate(const char *elementId, int32_t type); 60 | 61 | static void CBOnPageDeactivate(const char *elementId, int32_t type); 62 | 63 | static int32_t CBOnCheckVisible(const char *elementId, int *pIsVisible); 64 | 65 | static int32_t CBOnPreCreate(const char *elementId, sce::AppSettings::Element *element); 66 | 67 | static int32_t CBOnPostCreate(const char *elementId, paf::ui::Widget *widget); 68 | 69 | static int32_t CBOnPress(const char *elementId, const char *newValue); 70 | 71 | static int32_t CBOnPress2(const char *elementId, const char *newValue); 72 | 73 | static void CBOnTerm(int32_t result); 74 | 75 | static wchar_t *CBOnGetString(const char *elementId); 76 | 77 | static int32_t CBOnGetSurface(paf::graph::Surface **surf, const char *elementId); 78 | 79 | const int d_settingsVersion = 2; 80 | const int d_source = Source::VITA_DB; 81 | }; 82 | 83 | #endif -------------------------------------------------------------------------------- /bhbb_dl/include/tgz.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _TGZ_H_ 20 | #define _TGZ_H_ 21 | 22 | #include 23 | #include 24 | 25 | #include "compressed_file.h" 26 | 27 | class TgzFile : public CompressedFile 28 | { 29 | public: 30 | struct TarHeader // Taken from GNU tar 31 | { /* byte offset */ 32 | char name[100]; /* 0 */ 33 | char mode[8]; /* 100 */ 34 | char uid[8]; /* 108 */ 35 | char gid[8]; /* 116 */ 36 | char size[12]; /* 124 */ 37 | char mtime[12]; /* 136 */ 38 | char chksum[8]; /* 148 */ 39 | char typeflag; /* 156 */ 40 | char linkname[100]; /* 157 */ 41 | char magic[6]; /* 257 */ 42 | char version[2]; /* 263 */ 43 | char uname[32]; /* 265 */ 44 | char gname[32]; /* 297 */ 45 | char devmajor[8]; /* 329 */ 46 | char devminor[8]; /* 337 */ 47 | char prefix[155]; /* 345 */ 48 | /* 500 */ 49 | char padd[12]; // I had to add this to fit the 512 size per spec (why wasn't this here before?...) 50 | }; 51 | 52 | enum 53 | { 54 | TGZ_OK = 0, 55 | TGZ_EVAL = -101, 56 | TGZ_FERR = -102, 57 | TGZ_MEMERR = -103, 58 | TGZ_EOF = -104, 59 | TGZ_CHUNK_SIZE = SCE_KERNEL_128KiB, 60 | }; 61 | 62 | 63 | TgzFile(paf::string path); 64 | ~TgzFile(); 65 | 66 | virtual int Decompress(const paf::string outPath, ProgressCallback progressCB, void *progressData) override; 67 | virtual int CalculateUncompressedSize(); 68 | 69 | private: 70 | static voidpf sce_paf_gzip_zalloc(voidpf opaque, uInt items, uInt size) 71 | { 72 | return sce_paf_calloc(items, size); 73 | } 74 | 75 | static void sce_paf_gzip_zfree(voidpf opaque, voidpf address) 76 | { 77 | sce_paf_free(address); 78 | } 79 | 80 | int64_t Read(void *buff, size_t readSize); 81 | 82 | paf::common::SharedPtr file; 83 | unsigned char *readBuff; 84 | z_stream zstrm; 85 | }; 86 | 87 | #endif -------------------------------------------------------------------------------- /resource/locale/zh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /include/pages/app_viewer.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _APP_VIEWER_H_ 20 | #define _APP_VIEWER_H_ 21 | 22 | #include 23 | 24 | #include "page.h" 25 | #include "db/source.h" 26 | #include "dialog.h" 27 | #include "app_browser.h" 28 | 29 | class AppViewer : public page::Base 30 | { 31 | public: 32 | enum 33 | { 34 | DescriptionEvent = (paf::ui::Handler::CB_STATE + 0x45000), 35 | }; 36 | 37 | class AsyncDescriptionJob : public paf::job::JobItem 38 | { 39 | public: 40 | using paf::job::JobItem::JobItem; 41 | 42 | AsyncDescriptionJob(Source::Entry& e, AppViewer *_workPage):JobItem("AsyncDescriptionJob"),entry(e),workPage(_workPage) {} 43 | ~AsyncDescriptionJob() {} 44 | 45 | void Run(); 46 | void Finish(){} 47 | 48 | Source::Entry& entry; 49 | AppViewer *workPage; 50 | }; 51 | 52 | 53 | class IconDownloadJob : public paf::job::JobItem 54 | { 55 | public: 56 | using paf::job::JobItem::JobItem; 57 | 58 | void Run(); 59 | void Finish(){} 60 | 61 | AppViewer *workPage; 62 | }; 63 | 64 | class DownloadJob : public paf::job::JobItem 65 | { 66 | public: 67 | enum DownloadType 68 | { 69 | DownloadType_Data, 70 | DownloadType_App 71 | }; 72 | 73 | using paf::job::JobItem::JobItem; 74 | 75 | void Run(); 76 | void Finish(){} 77 | 78 | AppViewer *workPage; 79 | DownloadType type; 80 | }; 81 | 82 | static void ScreenshotCB(int id, paf::ui::Handler *self, paf::ui::Event *event, void *pUserData); 83 | static void IconButtonCB(int id, paf::ui::Handler *self, paf::ui::Event *event, void *pUserData); 84 | static void InfoButtonCB(int id, paf::ui::Handler *self, paf::ui::Event *event, void *pUserData); 85 | static void DownloadButtonCB(int id, paf::ui::Handler *self, paf::ui::Event *event, void *pUserData); 86 | static void DescriptionTextCB(int id, paf::ui::Handler *self, paf::ui::Event *event, void *pUserData); 87 | 88 | AppViewer(Source::Entry& entry, AppBrowser::TexPool *pTexPool); 89 | ~AppViewer(); 90 | 91 | ui::Text *descText; 92 | ui::BusyIndicator *busyIndicator; 93 | 94 | protected: 95 | Source::Entry &app; 96 | AppBrowser::TexPool *pool; 97 | }; 98 | 99 | #endif -------------------------------------------------------------------------------- /bhbb_dl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | set(CMAKE_TOOLCHAIN_FILE "$ENV{SCE_PSP2_SDK_DIR}/host_tools/build/cmake/psp2-snc-toolchain.cmake") 3 | project(bhbb_dl) 4 | include(VitaDevelopmentSuite) 5 | 6 | set(CMAKE_C_STANDARD 99) 7 | set(CMAKE_CXX_STANDARD 11) 8 | enable_language(EMD) 9 | 10 | if(${CMAKE_BUILD_TYPE} STREQUAL Debug) 11 | add_compile_options( 12 | -D_SCE_TARGET_OS_PSP2=1 -Xdiag=0 -Xquit=2 -Od -g -noex -D_DEBUG=1 -DPAF_BUILD=1 -D__psp2__ -D__SNC__ 13 | #-D_SCE_TARGET_OS_PSP2=1 -Xdiag=0 -Xquit=2 -Od -g -noex -DSCE_PAF_TOOL_PRX=1 -D_DEBUG=1 #use this if non devkit libpaf 14 | ) 15 | else() 16 | add_compile_options( 17 | -D_SCE_TARGET_OS_PSP2=1 -Xdiag=0 -Xquit=2 -O3 -noex -DPAF_BUILD=1 18 | ) 19 | endif() 20 | 21 | add_link_options( 22 | --prx-no-runtime-support 23 | ) 24 | 25 | add_custom_target(${PROJECT_NAME}.elf.target 26 | DEPENDS ${PROJECT_NAME}.elf ${PROJECT_NAME}.suprx 27 | ) 28 | 29 | VDSuiteCreateStubs(stubs SceLsdb.emd 30 | LIBRARIES 31 | SceLsdb_stub_weak 32 | ) 33 | 34 | add_library(${PROJECT_NAME} MODULE 35 | 36 | include/head_bin.h 37 | include/main.h 38 | include/offsets.h 39 | include/promote.h 40 | include/sha1.h 41 | include/compressed_file.h 42 | include/zip.h 43 | include/installer.h 44 | include/tgz.h 45 | 46 | src/main.cpp 47 | src/offsets.c 48 | src/zip.cpp 49 | src/promote.c 50 | src/sha1.c 51 | src/installer.cpp 52 | src/compressed_file.cpp 53 | src/tgz.cpp 54 | 55 | # minizip 56 | src/minizip/unzip.c 57 | src/minizip/ioapi.c 58 | src/minizip/zip.c 59 | 60 | src/libc2paf.c 61 | 62 | ../common/bhbb_dl.h 63 | ../common/dialog.cpp 64 | ../common/dialog.h 65 | 66 | bhbb_dl.emd 67 | ) 68 | 69 | add_dependencies(${PROJECT_NAME} 70 | stubs.target 71 | ) 72 | 73 | 74 | target_link_directories(${PROJECT_NAME} PRIVATE 75 | ${VDSUITE_LIBRARY_DIRECTORIES} 76 | ${CMAKE_BINARY_DIR}/stubs 77 | ) 78 | 79 | target_include_directories(${PROJECT_NAME} PRIVATE 80 | ../common 81 | include 82 | ${VDSUITE_USER_INCLUDE_DIRECTORIES} 83 | ${VDSUITE_STANDARD_INCLUDE_DIRECTORIES} 84 | $ENV{SCE_PSP2_SDK_DIR}/target/include 85 | $ENV{SCE_PSP2_SDK_DIR}/target/include_common 86 | ) 87 | 88 | target_link_libraries(${PROJECT_NAME} 89 | SceLibKernel_stub 90 | ScePafStdc_stub 91 | ScePafResource_stub 92 | ScePafWidget_stub 93 | ScePafThread_stub 94 | ScePafGraphics_stub 95 | ScePafTopLevel_stub 96 | ScePafMisc_stub 97 | ScePafCommon_stub 98 | SceAppMgrUser_stub 99 | SceCommonGuiDialog_stub 100 | SceAppMgr_stub 101 | SceThreadMgr_stub 102 | taihenUnsafe_stub 103 | SceModulemgr_stub 104 | taihen_stub 105 | SceSysmodule_stub 106 | SceIofilemgr_stub 107 | ScePromoterUtil_stub_weak 108 | SceLsdb_stub 109 | SceShellUtil_stub 110 | SceLsdb_stub_weak 111 | z 112 | ) 113 | VDSuiteSignElf(${PROJECT_NAME}.suprx ${PROJECT_NAME}) -------------------------------------------------------------------------------- /src/paf_runtime.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | Copyright (C) 2023 GrapheneCt 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | // This file is an extended version of @GrapheneCt's paf_runtime.cpp used in NetStream 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "print.h" 27 | 28 | extern "C" { 29 | typedef struct SceSysmoduleOpt { 30 | int flags; 31 | int *result; 32 | int unused[2]; 33 | } SceSysmoduleOpt; 34 | 35 | typedef struct ScePafInit { 36 | SceSize global_heap_size; 37 | int a2; 38 | int a3; 39 | int cdlg_mode; 40 | int heap_opt_param1; 41 | int heap_opt_param2; 42 | } ScePafInit; 43 | 44 | int sceAppMgrGrowMemory3(unsigned int a1, int a2); 45 | 46 | void __cxa_set_dso_handle_main(void *dso) 47 | { 48 | 49 | } 50 | 51 | int _sceLdTlsRegisterModuleInfo() 52 | { 53 | return 0; 54 | } 55 | 56 | int __at_quick_exit() 57 | { 58 | return 0; 59 | } 60 | 61 | void * memmove(void *to, const void *from, size_t numBytes) 62 | { 63 | return sce_paf_memmove(to, from, numBytes); 64 | } 65 | 66 | int __aeabi_unwind_cpp_pr0() 67 | { 68 | return 9; 69 | } 70 | 71 | int __aeabi_unwind_cpp_pr1() 72 | { 73 | return 9; 74 | } 75 | 76 | } 77 | 78 | #ifndef __INTELLISENSE__ 79 | __attribute__((constructor(101))) 80 | #endif 81 | void preloadPaf() 82 | { 83 | SceInt32 ret = -1, load_res; 84 | void* pRet = 0; 85 | 86 | ScePafInit initParam; 87 | SceSysmoduleOpt opt; 88 | 89 | initParam.global_heap_size = 10 * 1024 * 1024; 90 | 91 | initParam.a2 = 0x0000EA60; 92 | initParam.a3 = 0x00040000; 93 | 94 | initParam.cdlg_mode = SCE_FALSE; 95 | 96 | initParam.heap_opt_param1 = 0; 97 | initParam.heap_opt_param2 = 0; 98 | 99 | //Specify that we will pass some arguments 100 | opt.flags = 0; 101 | opt.result = &load_res; 102 | 103 | ret = _sceSysmoduleLoadModuleInternalWithArg(SCE_SYSMODULE_INTERNAL_PAF, sizeof(initParam), &initParam, &opt); 104 | 105 | if (ret < 0) { 106 | print("[PAF PRX] Loader: 0x%x\n", ret); 107 | print("[PAF PRX] Loader result: 0x%x\n", load_res); 108 | } 109 | } 110 | 111 | namespace std { 112 | const char * _Syserror_map(int) 113 | { 114 | return NULL; 115 | } 116 | size_t strlen(const char *a1) 117 | { 118 | return sce_paf_strlen(a1); 119 | } 120 | }; 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Better Homebrew Browser 3 | 4 | 5 | 6 | A homebrew browser that supports multiple DB's with background downloading support 7 | 8 | 9 | 10 | # Features 11 | 12 | #### It can download from various sources, meaning a larger content library to chose from 13 |
14 |
15 | 16 | 17 |
18 |
19 |

It is designed to be sleek and easy to use with a nice UI

20 |
21 | 22 | 23 |
24 | 25 | #### It can download files in the background just like the official store and will install with a native-looking UI along with proper notifications to complete the look 26 |
27 | 28 | 29 | 30 | 31 |
32 |

It also supports several languages

33 | 34 | ## Adding a new language 35 | 36 | 37 | 38 | (Instructions by [GrapheneCt](https://github.com/GrapheneCt)) 39 | 40 | 41 | 42 | - Use [English locale](https://github.com/Ibrahim778/BetterHomebrewBrowser/blob/master/resource/locale/en.xml) as base. Name your translation XX.xml, where XX is language code. 43 | 44 | Supported language codes can be seen [here](https://github.com/Ibrahim778/BetterHomebrewBrowser/blob/master/resource/bhbb_plugin.xml#L365) (id attribute). 45 | 46 | - Submit your translation as pull request, it will be added in the next release. 47 | 48 | 49 | 50 | # Credits 51 | 52 | 53 | 54 | ### @GrapheneCt 55 | - ScePaf reversing 56 | - EMPVA (Reference) 57 | - NetStream (Reference) 58 | - CXML Compiler (Not Released) 59 | - SceIPMI & SceDownload reversing 60 | 61 | ### @CreepNT 62 | - SceDownload reversing 63 | 64 | ### @Princess-of-sleeping 65 | - Help with debugging and development 66 | - Reversing SceLsdb notifications (SceShell notice PoC) 67 | 68 | ### @SKGleba & TheFlow 69 | - bgvpk & Download Enabler (basis for bhbb_dl) 70 | 71 | ### CBPS 72 | - Original SceDownload PoC 73 | 74 | ### Beta Testers 75 | - @SomeOnPC 76 | - @ShadowKnight1620 77 | - @Koutsie 78 | - @SparklingPheonix 79 | - @gl33ntwine 80 | 81 | ### Translators 82 | - @isage - RU 83 | - @S1ngyy - DE 84 | - @CreepNT - FR 85 | - @Princess-of-sleeping - JA 86 | - @maniek6666 - PL 87 | - @michael-moon-lee - ZH 88 | - @Sfresneda - ES 89 | - @gilgilgan - KO 90 | - @Koutsie - FI 91 | 92 | Livearea assets by SomeonPC 93 | 94 | ## Donations 95 | 96 | If you like my work, you can support me via [PayPal](https://www.paypal.com/paypalme/GloveTekLtd) -------------------------------------------------------------------------------- /resource/locale/ko.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /resource/locale/ja.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/pages/page.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | #include "pages/page.h" 26 | #include "common.h" 27 | #include "print.h" 28 | #include "bhbb_plugin.h" 29 | 30 | using namespace paf; 31 | 32 | std::vector s_pageStack; //Why didn't I think of this? (Thanks Graphene) 33 | 34 | page::Base::Base(uint32_t _hash, Plugin::PageOpenParam openParam, Plugin::PageCloseParam cParam):closeParam(cParam),backButton(SCE_NULL) 35 | { 36 | if(_hash == 0) 37 | return; //¿How did we get here? 38 | 39 | IDParam param(_hash); 40 | root = g_appPlugin->PageOpen(param, openParam); 41 | param = back_button; 42 | backButton = (ui::CornerButton *)root->FindChild(param); 43 | 44 | if(!s_pageStack.empty()) //We have previous pages 45 | { 46 | page::Base *previousPage = s_pageStack.back(); //Get the previous menu 47 | previousPage->root->SetActivate(false); //Disable touch and button controls 48 | if(backButton) 49 | { 50 | backButton->Show(common::transition::Type_Reset); 51 | backButton->AddEventCallback(ui::CornerButton::CB_BTN_DECIDE, (ui::HandlerCB)page::Base::DefaultBackButtonCB); 52 | } 53 | } 54 | else if(backButton) 55 | backButton->Hide(common::transition::Type_Reset); 56 | 57 | s_pageStack.push_back(this); //Add our current page to the stack 58 | } 59 | 60 | page::Base *page::Base::GetCurrentPage() 61 | { 62 | return s_pageStack.back(); 63 | } 64 | 65 | uint32_t page::Base::GetHash() 66 | { 67 | return root->GetName().GetIDHash(); 68 | } 69 | 70 | page::Base::~Base() 71 | { 72 | s_pageStack.erase(std::remove(s_pageStack.begin(), s_pageStack.end(), this), s_pageStack.end()); //Remove our page from the list. 73 | 74 | g_appPlugin->PageClose(root->GetName(), closeParam); //Delete our page 75 | 76 | if(!s_pageStack.empty()) //We have other pages 77 | { 78 | page::Base *previousPage = s_pageStack.back(); //Get our previous page 79 | previousPage->root->SetActivate(true); //Enable touch and button controls 80 | } 81 | } 82 | 83 | void page::Base::DefaultBackButtonCB(uint32_t type, ui::Handler *self, ui::Event *event, ScePVoid pUserData) 84 | { 85 | page::Base::DeleteCurrentPage(); 86 | } 87 | 88 | SceVoid page::Base::DeleteCurrentPage() 89 | { 90 | auto button = page::Base::GetCurrentPage()->backButton; 91 | if(button) 92 | button->Hide(common::transition::Type_Reset); 93 | 94 | delete s_pageStack.back(); 95 | } -------------------------------------------------------------------------------- /include/bhbb_plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef __BHBB_PLUGIN_H__ 2 | #define __BHBB_PLUGIN_H__ 3 | 4 | //generated by acdc from C:/Users/ibrahim/Documents/Projects/BetterHomebrewBrowser/resource/bhbb_plugin.xml 5 | 6 | #define download_button (0x01383ea9) 7 | #define textobj (0x01f875b1) 8 | #define list_button_bg (0x04ee2175) 9 | #define text_label_sort (0x0a2ebeb1) 10 | #define apps_page_bg (0x0bd99fbd) 11 | #define picture (0x0e66b49d) 12 | #define plane_categories (0x0e7479a4) 13 | #define app_button (0x0ff6b41a) 14 | #define button_label (0x130f97aa) 15 | #define screenshot_button (0x141b53ff) 16 | #define info_author_text (0x155bf1bb) 17 | #define template_ref_apps_page_list_template (0x15644830) 18 | #define options_button (0x16623214) 19 | #define plane_sort (0x185ddbeb) 20 | #define screenshot_box (0x208febc8) 21 | #define glow_obj (0x22ff88bd) 22 | #define app_button_list_item_1x1_template (0x24ada687) 23 | #define label_obj (0x28ccf273) 24 | #define plane_button_recent_style (0x2affde46) 25 | #define info_description_text (0x2f8b5309) 26 | #define text_header (0x33c6855b) 27 | #define app_info_page_bg (0x3cd40746) 28 | #define style_button_list_button_icon (0x411da904) 29 | #define info_button (0x484c7041) 30 | #define _common_snd01 (0x48d64cf1) 31 | #define app_list_view (0x4bb109a1) 32 | #define text_list_item_category (0x526345b8) 33 | #define template_image_button_list (0x569ae85f) 34 | #define glowobj0 (0x579be4b9) 35 | #define info_title_text (0x5bc514a0) 36 | #define page_root (0x5e5bc488) 37 | #define page_text (0x62a7c933) 38 | #define text_list_item_author (0x62bbec4d) 39 | #define tex_missing_icon (0x6490991c) 40 | #define file_bhbb_settings (0x678061b9) 41 | #define category_button_template (0x68a96713) 42 | #define list_button (0x68ef628a) 43 | #define search_back_button (0x6a2c094c) 44 | #define button_header_sort (0x6a39a260) 45 | #define plane_search (0x749096ea) 46 | #define info_version_text (0x76a09d62) 47 | #define search_box (0x7bb7d799) 48 | #define description_plane (0x8118f75e) 49 | #define info_screenshot_button_template (0x8a5010ed) 50 | #define planeobj1 (0x8f56c33f) 51 | #define plane_seperator (0x91f4f4fe) 52 | #define bg_obj (0x9c96918b) 53 | #define page_image_viewer (0xa03b9af6) 54 | #define back_button (0xa20371f2) 55 | #define button_glow (0xa5082d74) 56 | #define app_button_list_item_67x37_template (0xa50af0be) 57 | #define text_obj1 (0xa56e4ba2) 58 | #define obj2 (0xa7ac3802) 59 | #define plane_list_item_icon (0xa7e671aa) 60 | #define glowobj1 (0xaa063e30) 61 | #define search_enter_button (0xab8cb65e) 62 | #define top_plane (0xad9ac745) 63 | #define icon_busy (0xb14f2899) 64 | #define app_info_page (0xb50e17ad) 65 | #define list_button_glow (0xb52eac04) 66 | #define bgobj0 (0xb9d90aa7) 67 | #define obj1 (0xbc21fd1f) 68 | #define description_busy (0xbc9fd07f) 69 | #define app_page (0xc77e992c) 70 | #define text_normal_obj (0xc8bb0270) 71 | #define button_bg (0xca43bdd2) 72 | #define search_button (0xccce2527) 73 | #define text_list_item_title (0xce986358) 74 | #define icon_button (0xd117ef01) 75 | #define list_plane (0xd1a3ff38) 76 | #define text_page (0xd23b357f) 77 | #define bhbb_plugin (0xd493e057) 78 | #define plane_category_buttons (0xd91df91f) 79 | #define text_list_item_version (0xdcc83e92) 80 | #define refresh_button (0xdf43db7a) 81 | #define app_button_list_item (0xe08d4e4c) 82 | #define busy (0xe18a89f9) 83 | #define screenshot_plane (0xe310fb60) 84 | #define planeobj (0xe95f1628) 85 | #define glowobj (0xeb3b8f6e) 86 | #define plane_obj1 (0xf239aa56) 87 | #define plane_header (0xf2bfe50e) 88 | #define apps_page_list_template (0xf5d46175) 89 | #define data_download_button (0xfadb190a) 90 | 91 | #endif // __BHBB_PLUGIN_H__ 92 | -------------------------------------------------------------------------------- /resource/locale/en.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /resource/locale/fi.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /resource/locale/ptbr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /resource/locale/es.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /resource/locale/pl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /resource/locale/ru.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/pages/image_viewer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "pages/image_viewer.h" 23 | #include "bhbb_plugin.h" 24 | #include "bhbb_locale.h" 25 | #include "common.h" 26 | #include "dialog.h" 27 | #include "print.h" 28 | 29 | using namespace paf; 30 | using namespace common; 31 | using namespace math; 32 | using namespace thread; 33 | 34 | ImageViewer::ImageViewer(const char *path): 35 | page::Base( 36 | page_image_viewer, 37 | Plugin::PageOpenParam(), 38 | Plugin::PageCloseParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom) 39 | ) 40 | { 41 | if(path) 42 | LoadAsync(path); 43 | } 44 | 45 | void ImageViewer::LoadAsync(const char *path) 46 | { 47 | auto item = new DisplayJob("ImageViewer::DisplayJob"); 48 | item->workPage = this; 49 | item->path = path; 50 | auto itemParam = SharedPtr(item); 51 | job::JobQueue::default_queue->Enqueue(itemParam); 52 | } 53 | 54 | int ImageViewer::LoadNet(const char *path) 55 | { 56 | int32_t res = -1; 57 | CurlFile::OpenArg oarg; 58 | oarg.ParseUrl(path); 59 | oarg.SetOption(3000, CurlFile::OpenArg::OptionType_ConnectTimeOut); 60 | oarg.SetOption(5000, CurlFile::OpenArg::OptionType_RecvTimeOut); 61 | 62 | CurlFile *file = new CurlFile(); 63 | res = file->Open(&oarg); 64 | if (res != SCE_PAF_OK) 65 | { 66 | delete file; 67 | print("Failed to open curl file: 0x%X\n", res); 68 | return res; 69 | } 70 | 71 | common::SharedPtr hfile(file); 72 | auto tex = graph::Surface::Load(gutil::GetDefaultSurfacePool(), (common::SharedPtr&)hfile); 73 | if(tex.get()) 74 | { 75 | auto plane = root->FindChild(picture); 76 | plane->SetTexture(tex, 0, 0); 77 | plane->SetColor(1,1,1,1); 78 | return 0; 79 | } 80 | 81 | return -1; 82 | } 83 | 84 | int ImageViewer::LoadLocal(const char *path) 85 | { 86 | int result = 0; 87 | auto fileParam = LocalFile::Open(path, SCE_O_RDONLY, 0, &result); 88 | if(result != 0) 89 | return result; 90 | 91 | auto tex = graph::Surface::Load(gutil::GetDefaultSurfacePool(), (common::SharedPtr&)fileParam); 92 | if(tex.get()) 93 | { 94 | auto plane = root->FindChild(picture); 95 | plane->SetTexture(tex, 0, 0); 96 | plane->SetColor(1,1,1,1); 97 | return 0; 98 | } 99 | 100 | return -1; 101 | } 102 | 103 | int ImageViewer::Load(const char *path) 104 | { 105 | if(sce_paf_strncmp(path, "http", 4) == 0) 106 | return LoadNet(path); 107 | 108 | return LoadLocal(path); 109 | } 110 | 111 | void ImageViewer::DisplayJob::Run() 112 | { 113 | dialog::OpenPleaseWait(g_appPlugin, nullptr, g_appPlugin->GetString(msg_wait)); 114 | 115 | int ret = workPage->Load(path.c_str()); 116 | 117 | dialog::Close(); 118 | 119 | if(ret != 0) 120 | { 121 | dialog::OpenError(g_appPlugin, ret, g_appPlugin->GetString(msg_screenshot_error)); 122 | page::Base::DeleteCurrentPage(); 123 | return; 124 | } 125 | } 126 | 127 | void ImageViewer::DisplayJob::Finish() 128 | { 129 | 130 | } -------------------------------------------------------------------------------- /include/tex_pool.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | Copyright (C) 2023 GrapheneCt 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | // This file is an extended version of @GrapheneCt's tex_pool.h used in NetStream 21 | 22 | #ifndef _TEX_POOL_H_ 23 | #define _TEX_POOL_H_ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "event.h" 30 | 31 | using namespace paf; 32 | 33 | class TexPool 34 | { 35 | public: 36 | 37 | typedef void(*OnAddAsyncComplete)(uint32_t hash, bool result, void *pArgBlock); 38 | 39 | TexPool(Plugin *_cbPlugin = NULL); 40 | 41 | ~TexPool(); 42 | 43 | void DestroyAsync(); 44 | 45 | intrusive_ptr Get(IDParam const& id); 46 | 47 | bool Add(Plugin *plugin, IDParam const& id, bool allowReplace = false); 48 | bool Add(IDParam const& id, uint8_t *buffer, size_t bufferSize, bool allowReplace = false); 49 | bool Add(IDParam const& id, const char *path, bool allowReplace = false); 50 | bool Add(IDParam const& id, intrusive_ptr& surf, bool allowReplace = false); 51 | 52 | bool AddAsync(IDParam const& id, uint8_t *buffer, size_t bufferSize, bool allowReplace = false); 53 | bool AddAsync(IDParam const& id, const char *path, bool allowReplace = false); 54 | 55 | void Remove(IDParam const& id); 56 | void RemoveAll(); 57 | 58 | bool Exist(IDParam const& id); 59 | 60 | void AddAsyncWaitComplete(); 61 | int32_t AddAsyncActiveNum(); 62 | 63 | uint32_t GetSize(); 64 | 65 | inline void SetShare(CurlFile::Share *sh) 66 | { 67 | share = sh; 68 | } 69 | 70 | inline bool IsAlive() 71 | { 72 | return alive; 73 | } 74 | 75 | inline void SetAlive(bool value) 76 | { 77 | alive = value; 78 | } 79 | 80 | protected: 81 | 82 | class AddAsyncJob : public job::JobItem 83 | { 84 | public: 85 | 86 | using job::JobItem::JobItem; 87 | 88 | ~AddAsyncJob() 89 | { 90 | 91 | } 92 | 93 | void Run() 94 | { 95 | bool result = false; 96 | 97 | if (buf) 98 | { 99 | result = workObj->Add(hash, buf, bufSize, true); 100 | } 101 | else 102 | { 103 | result = workObj->Add(hash, path.c_str(), true); 104 | } 105 | 106 | if (result && workObj->IsAlive() && workObj->cbPlugin) 107 | { 108 | event::BroadcastGlobalEvent(workObj->cbPlugin, ui::Handler::CB_STATE_READY_CACHEIMAGE, hash); 109 | } 110 | } 111 | 112 | void Finish() 113 | { 114 | 115 | } 116 | 117 | TexPool *workObj; 118 | uint8_t *buf; 119 | size_t bufSize; 120 | uint32_t hash; 121 | paf::string path; 122 | }; 123 | 124 | class DestroyJob : public job::JobItem 125 | { 126 | public: 127 | 128 | using job::JobItem::JobItem; 129 | 130 | ~DestroyJob() 131 | { 132 | 133 | } 134 | 135 | void Run() 136 | { 137 | delete pool; 138 | } 139 | 140 | void Finish() 141 | { 142 | 143 | } 144 | 145 | TexPool *pool; 146 | }; 147 | 148 | void RemoveForReplace(IDParam const& id); 149 | 150 | bool AddHttp(IDParam const& id, const char *path); 151 | 152 | bool AddLocal(IDParam const& id, const char *path); 153 | 154 | map> stor; 155 | CurlFile::Share *share; 156 | thread::RMutex *storMtx; 157 | job::JobQueue *addAsyncQueue; 158 | bool alive; 159 | Plugin *cbPlugin; 160 | }; 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /resource/locale/it.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /resource/locale/de.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /bhbb_dl/include/notice.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _NOTICE_H_ 20 | #define _NOTICE_H_ 21 | 22 | #include 23 | 24 | //Based off of reversing done by @Princess-of-Sleeping and @Rinnegatamante along with field information in app.db 25 | class SceLsdbNotificationParam 26 | { 27 | public: 28 | 29 | // 0x3 = Download progress 30 | enum Type 31 | { 32 | AppInstallFailed = 0, // Happened when int wasnt set 33 | LiveAreaRefreshed = 0x900, 34 | AppInstalledSuccessfully = 0x52, 35 | DownloadComplete = 0x51, 36 | Custom = 0x100, // One single line of text (desc, or title, desc takes priority, used by SCE for testing?) 37 | UserDefined = 0x102, // type used by sceNotificationUtilSendNotification (same as Custom??) 38 | }; 39 | 40 | enum Action 41 | { 42 | AppBound = 1, 43 | AppOpen = 2, // Opens LA 44 | AppHighlight = 3, 45 | Unk = 0xb // ?? found in RE (possibly some app launch) 46 | };// Other known: 0x8 47 | 48 | SceLsdbNotificationParam() 49 | { 50 | sce_paf_memset(unk, 0, sizeof(unk)); 51 | sce_paf_memset(unk1, 0xFF, sizeof(unk1)); 52 | sce_paf_memset(unk2, 0, sizeof(unk2)); 53 | sce_paf_memset(unk3, 0, sizeof(unk3)); 54 | 55 | msg_type = (Type)0; 56 | iunk = 0; 57 | new_flag = 0; 58 | display_type = 0; 59 | iUnk2 = 0; 60 | action_type = (Action)0; 61 | exec_mode = 0; 62 | } 63 | 64 | paf::string title_id; // Usually titleID of the caller, can sometimes be empty 65 | paf::string item_id; // Possibly paf::IDParam? 66 | int unk[2]; // del flag? (0) 67 | Type msg_type; //see (@Type) 68 | int iunk; // unused? always 0 69 | Action action_type; //action on press (see @Action) 70 | SceByte8 new_flag; // Blue highlight when opening centre 71 | SceByte8 display_type; // << possibly popup_no << 0 = no popup & no highlight in notif centre 1 = popup & no highlight, if 1 when @new_flag = 0 then popup 72 | SceChar8 unk1[2]; // Set to 0xFF 73 | paf::string icon_path; 74 | int unk2[2]; 75 | //Some of these are covnerted to int's via sce_paf_atoi 76 | paf::string msg_arg0; 77 | paf::string msg_arg1; 78 | paf::string msg_arg2; 79 | paf::string msg_arg3; 80 | paf::string msg_arg4; 81 | paf::string msg_arg5; 82 | paf::string msg_arg6; 83 | paf::string msg_arg7; // int (error code) 84 | paf::string msg_arg8; // int 85 | paf::string title; 86 | paf::string desc; 87 | int exec_mode; 88 | paf::string exec_titleid; // basically work titleid. Will be used depending on opt (APP_HIGHTLIGHT or APP_OPEN) and will use it's icon if none specified in icon_path 89 | paf::string exec_arg; //Launch arguments for the app upon launch 90 | paf::string icon_data; // unverified 91 | int unk3[3]; 92 | int iUnk2; //Princess set this to 0x10 ¿:/? (0 also works) 93 | }; 94 | 95 | SCE_CDECL_BEGIN 96 | 97 | int sceLsdbSendNotification(SceLsdbNotificationParam *param, int allowReplace); 98 | 99 | SCE_CDECL_END 100 | 101 | #endif -------------------------------------------------------------------------------- /resource/locale/fr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/fread_line.c: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | Copyright (C) 2023 Samuel Alexander 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | // This file is a modified version of fread_csv_line.c made by @semi_trivial for his csv_parser here https://github.com/semitrivial/csv_parser 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "csv.h" 28 | 29 | #define READ_BLOCK_SIZE 65536 30 | #define QUICK_GETC(ch, fp) \ 31 | do \ 32 | { \ 33 | if (read_ptr == read_end) \ 34 | { \ 35 | fread_len = sce_paf_fread(read_buf, sizeof(char), READ_BLOCK_SIZE, fp); \ 36 | if (fread_len < READ_BLOCK_SIZE) \ 37 | { \ 38 | read_buf[fread_len] = '\0'; \ 39 | } \ 40 | read_ptr = read_buf; \ 41 | } \ 42 | ch = *read_ptr++; \ 43 | } while (0) 44 | 45 | char *strdup(const char *src) 46 | { 47 | size_t len = sce_paf_strlen(src); 48 | char *buff = sce_paf_malloc(len + 1); 49 | sce_paf_strncpy(buff, src, len); 50 | buff[len] = '\0'; 51 | return buff; 52 | } 53 | 54 | char *fread_line(sce_paf_FILE *fp, int max_line_size, int *done, int *err) 55 | { 56 | static sce_paf_FILE *bookmark; 57 | static char read_buf[READ_BLOCK_SIZE], *read_ptr, *read_end; 58 | static int fread_len, prev_max_line_size = -1; 59 | static char *buf; 60 | char *bptr, *limit; 61 | char ch; 62 | int fQuote; 63 | 64 | if (max_line_size > prev_max_line_size) 65 | { 66 | if (prev_max_line_size != -1) 67 | { 68 | sce_paf_free(buf); 69 | } 70 | buf = sce_paf_malloc(max_line_size + 1); 71 | if (!buf) 72 | { 73 | *err = CSV_ERR_NO_MEMORY; 74 | prev_max_line_size = -1; 75 | return NULL; 76 | } 77 | prev_max_line_size = max_line_size; 78 | } 79 | bptr = buf; 80 | limit = buf + max_line_size; 81 | 82 | if (bookmark != fp) 83 | { 84 | read_ptr = read_end = read_buf + READ_BLOCK_SIZE; 85 | bookmark = fp; 86 | } 87 | 88 | for (fQuote = 0;;) 89 | { 90 | QUICK_GETC(ch, fp); 91 | 92 | if (!ch || (ch == '\n' && !fQuote)) 93 | { 94 | break; 95 | } 96 | 97 | if (bptr >= limit) 98 | { 99 | sce_paf_free(buf); 100 | *err = CSV_ERR_LONGLINE; 101 | return NULL; 102 | } 103 | *bptr++ = ch; 104 | 105 | if (fQuote) 106 | { 107 | if (ch == '\"') 108 | { 109 | QUICK_GETC(ch, fp); 110 | 111 | if (ch != '\"') 112 | { 113 | if (!ch || ch == '\n') 114 | { 115 | break; 116 | } 117 | fQuote = 0; 118 | } 119 | *bptr++ = ch; 120 | } 121 | } 122 | else if (ch == '\"') 123 | { 124 | fQuote = 1; 125 | } 126 | } 127 | 128 | *done = !ch; 129 | *bptr = '\0'; 130 | return strdup(buf); 131 | } -------------------------------------------------------------------------------- /bhbb_dl/src/sha1.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: sha1.c 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: Implementation of the SHA1 hashing algorithm. 7 | Algorithm specification can be found here: 8 | * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf 9 | This implementation uses little endian byte order. 10 | *********************************************************************/ 11 | 12 | /*************************** HEADER FILES ***************************/ 13 | #include "sha1.h" 14 | #include 15 | 16 | /****************************** MACROS ******************************/ 17 | #define ROTLEFT(a, b) ((a << b) | (a >> (32 - b))) 18 | 19 | /*********************** FUNCTION DEFINITIONS ***********************/ 20 | void sha1_transform(SHA1_CTX* ctx, const BYTE data[]) { 21 | WORD a, b, c, d, e, i, j, t, m[80]; 22 | 23 | for (i = 0, j = 0; i < 16; ++i, j += 4) 24 | m[i] = (data[j] << 24) + (data[j + 1] << 16) + (data[j + 2] << 8) + (data[j + 3]); 25 | for (; i < 80; ++i) { 26 | m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]); 27 | m[i] = (m[i] << 1) | (m[i] >> 31); 28 | } 29 | 30 | a = ctx->state[0]; 31 | b = ctx->state[1]; 32 | c = ctx->state[2]; 33 | d = ctx->state[3]; 34 | e = ctx->state[4]; 35 | 36 | for (i = 0; i < 20; ++i) { 37 | t = ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + ctx->k[0] + m[i]; 38 | e = d; 39 | d = c; 40 | c = ROTLEFT(b, 30); 41 | b = a; 42 | a = t; 43 | } 44 | for (; i < 40; ++i) { 45 | t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + ctx->k[1] + m[i]; 46 | e = d; 47 | d = c; 48 | c = ROTLEFT(b, 30); 49 | b = a; 50 | a = t; 51 | } 52 | for (; i < 60; ++i) { 53 | t = ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d)) + e + ctx->k[2] + m[i]; 54 | e = d; 55 | d = c; 56 | c = ROTLEFT(b, 30); 57 | b = a; 58 | a = t; 59 | } 60 | for (; i < 80; ++i) { 61 | t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + ctx->k[3] + m[i]; 62 | e = d; 63 | d = c; 64 | c = ROTLEFT(b, 30); 65 | b = a; 66 | a = t; 67 | } 68 | 69 | ctx->state[0] += a; 70 | ctx->state[1] += b; 71 | ctx->state[2] += c; 72 | ctx->state[3] += d; 73 | ctx->state[4] += e; 74 | } 75 | 76 | void sha1_init(SHA1_CTX* ctx) { 77 | ctx->datalen = 0; 78 | ctx->bitlen = 0; 79 | ctx->state[0] = 0x67452301; 80 | ctx->state[1] = 0xEFCDAB89; 81 | ctx->state[2] = 0x98BADCFE; 82 | ctx->state[3] = 0x10325476; 83 | ctx->state[4] = 0xc3d2e1f0; 84 | ctx->k[0] = 0x5a827999; 85 | ctx->k[1] = 0x6ed9eba1; 86 | ctx->k[2] = 0x8f1bbcdc; 87 | ctx->k[3] = 0xca62c1d6; 88 | } 89 | 90 | void sha1_update(SHA1_CTX* ctx, const BYTE data[], size_t len) { 91 | size_t i; 92 | 93 | for (i = 0; i < len; ++i) { 94 | ctx->data[ctx->datalen] = data[i]; 95 | ctx->datalen++; 96 | if (ctx->datalen == 64) { 97 | sha1_transform(ctx, ctx->data); 98 | ctx->bitlen += 512; 99 | ctx->datalen = 0; 100 | } 101 | } 102 | } 103 | 104 | void sha1_final(SHA1_CTX* ctx, BYTE hash[]) { 105 | WORD i; 106 | 107 | i = ctx->datalen; 108 | 109 | // Pad whatever data is left in the buffer. 110 | if (ctx->datalen < 56) { 111 | ctx->data[i++] = 0x80; 112 | while (i < 56) 113 | ctx->data[i++] = 0x00; 114 | } else { 115 | ctx->data[i++] = 0x80; 116 | while (i < 64) 117 | ctx->data[i++] = 0x00; 118 | sha1_transform(ctx, ctx->data); 119 | sce_paf_memset(ctx->data, 0, 56); 120 | } 121 | 122 | // Append to the padding the total message's length in bits and transform. 123 | ctx->bitlen += ctx->datalen * 8; 124 | ctx->data[63] = ctx->bitlen; 125 | ctx->data[62] = ctx->bitlen >> 8; 126 | ctx->data[61] = ctx->bitlen >> 16; 127 | ctx->data[60] = ctx->bitlen >> 24; 128 | ctx->data[59] = ctx->bitlen >> 32; 129 | ctx->data[58] = ctx->bitlen >> 40; 130 | ctx->data[57] = ctx->bitlen >> 48; 131 | ctx->data[56] = ctx->bitlen >> 56; 132 | sha1_transform(ctx, ctx->data); 133 | 134 | // Since this implementation uses little endian byte ordering and MD uses big endian, 135 | // reverse all the bytes when copying the final state to the output hash. 136 | for (i = 0; i < 4; ++i) { 137 | hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; 138 | hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; 139 | hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; 140 | hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; 141 | hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; 142 | } 143 | } -------------------------------------------------------------------------------- /src/downloader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | Copyright (C) 2023 GrapheneCt 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | // This file is an extended version of @GrapheneCt's downloader.cpp used in EMPV-A 21 | 22 | // Based off of downloader by @GrapheneCt, RE by: @GrapheneCt @CreeptNT and @dots_tb 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "downloader.h" 31 | #include "event.h" 32 | #include "print.h" 33 | 34 | using namespace paf; 35 | 36 | Downloader *Downloader::s_currentInstance = nullptr; 37 | 38 | Downloader::Downloader() 39 | { 40 | IPMI::Client::Config conf; 41 | IPMI::Client *client; 42 | uint32_t clMemSize; 43 | int32_t ret; 44 | 45 | sce_paf_memset(&dw, 0, sizeof(sce::Download)); 46 | sce_paf_memset(&conf, 0, sizeof(IPMI::Client::Config)); 47 | 48 | sce_paf_strncpy((char *)conf.serviceName, "SceDownload", sizeof(conf.serviceName)); 49 | conf.pipeBudgetType = IPMI::BudgetType_Default; 50 | conf.numResponses = 1; 51 | conf.requestQueueSize = 0x1E00; 52 | conf.receptionQueueSize = 0x1E00; 53 | conf.numAsyncResponses = 1; 54 | conf.requestQueueAddsize1 = 0xF00; 55 | conf.requestQueueAddsize2 = 0xF00; 56 | conf.numEventFlags = 1; 57 | conf.msgQueueSize = 0; 58 | conf.serverPID = SCE_UID_INVALID_UID; 59 | 60 | clMemSize = conf.estimateClientMemorySize(); 61 | dw.clientMem = sce_paf_malloc(clMemSize); 62 | dw.bufMem = sce_paf_malloc(SCE_KERNEL_4KiB); 63 | 64 | IPMI::Client::create(&client, &conf, &dw, dw.clientMem); 65 | 66 | dw.client = client; 67 | 68 | sce::Download::ConnectionOpt connOpt; 69 | sce_paf_memset(&connOpt, 0, sizeof(sce::Download::ConnectionOpt)); 70 | connOpt.budgetType = conf.pipeBudgetType; 71 | 72 | client->connect(&connOpt, sizeof(sce::Download::ConnectionOpt), &ret); 73 | 74 | dw.unk_00 = SCE_UID_INVALID_UID; 75 | dw.unk_04 = SCE_UID_INVALID_UID; 76 | dw.unk_08 = SCE_UID_INVALID_UID; 77 | 78 | s_currentInstance = this; 79 | } 80 | 81 | Downloader::~Downloader() 82 | { 83 | dw.client->disconnect(); 84 | dw.client->destroy(); 85 | sce_paf_free(dw.clientMem); 86 | sce_paf_free(dw.bufMem); 87 | } 88 | 89 | void WriteParam(BGDLParam *param, int32_t dwRes) 90 | { 91 | int ret = SCE_PAF_OK; 92 | auto param_file = LocalFile::Open(common::FormatString("ux0:/bgdl/t/%08x/bhbb.param", dwRes).c_str(), SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0666, &ret); 93 | if(ret < 0) 94 | return; 95 | 96 | param_file.get()->Write(param, sizeof(BGDLParam)); 97 | } 98 | 99 | int32_t Downloader::Enqueue(Plugin *workPlugin, const char *url, const char *name, const char *icon_path, BGDLParam *param) 100 | { 101 | IPMI::DataInfo dtInfo[1]; 102 | IPMI::BufferInfo bfInfo[2]; 103 | 104 | char output0[0x2E0]; 105 | sce_paf_memset(output0, 0, sizeof(output0)); 106 | 107 | int32_t ret = SCE_OK; 108 | int32_t ret2 = SCE_OK; 109 | int32_t dwRes = SCE_OK; 110 | 111 | sce::Download::RegistTaskParam rparam; 112 | sce_paf_memset(&rparam, 0, sizeof(rparam)); 113 | 114 | sce_paf_strcpy((char *)&rparam.downloadName, name); 115 | sce_paf_strcpy((char *)&rparam.url, url); 116 | if(icon_path != nullptr) 117 | sce_paf_strcpy((char *)&rparam.icon, icon_path); 118 | 119 | rparam.contentType = sce::Download::ContentType_Multimedia; 120 | 121 | dtInfo[0].data = &rparam; 122 | dtInfo[0].dataSize = sizeof(rparam); 123 | 124 | bfInfo[0].data = output0; 125 | bfInfo[0].dataSize = sizeof(output0); 126 | 127 | bfInfo[1].data = &dwRes; 128 | bfInfo[1].dataSize = sizeof(dwRes); 129 | 130 | ret = dw.client->invokeSyncMethod(sce::Download::Method_DownloadExt, dtInfo, 1, &ret2, bfInfo, 2); 131 | print("ret = 0x%X ret2 = 0x%X dwRes = 0x%X\n", ret, ret2, dwRes); 132 | if(ret2 != 0) 133 | { 134 | ret = ret2; 135 | goto end; 136 | } 137 | 138 | if(param) 139 | WriteParam(param, dwRes); 140 | end: 141 | event::BroadcastGlobalEvent(workPlugin, DownloaderEvent, ret); 142 | return ret; 143 | } 144 | 145 | int32_t Downloader::EnqueueAsync(Plugin *workPlugin, const char *url, const char *name) 146 | { 147 | AsyncEnqueue *dwJob = new AsyncEnqueue("Downloader::AsyncEnqueue"); 148 | dwJob->downloader = this; 149 | dwJob->url8 = url; 150 | dwJob->name8 = name; 151 | dwJob->plugin = workPlugin; 152 | 153 | common::SharedPtr itemParam(dwJob); 154 | 155 | return job::JobQueue::default_queue->Enqueue(itemParam); 156 | } 157 | 158 | Downloader *Downloader::GetCurrentInstance() 159 | { 160 | return s_currentInstance; 161 | } -------------------------------------------------------------------------------- /bhbb_dl/src/minizip/crypt.h: -------------------------------------------------------------------------------- 1 | /* crypt.h -- base code for traditional PKWARE encryption 2 | Version 1.01e, February 12th, 2005 3 | 4 | Copyright (C) 1998-2005 Gilles Vollant 5 | Modifications for Info-ZIP crypting 6 | Copyright (C) 2003 Terry Thorsen 7 | 8 | This code is a modified version of crypting code in Info-ZIP distribution 9 | 10 | Copyright (C) 1990-2000 Info-ZIP. All rights reserved. 11 | 12 | See the Info-ZIP LICENSE file version 2000-Apr-09 or later for terms of use 13 | which also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 14 | 15 | The encryption/decryption parts of this source code (as opposed to the 16 | non-echoing password parts) were originally written in Europe. The 17 | whole source package can be freely distributed, including from the USA. 18 | (Prior to January 2000, re-export from the US was a violation of US law.) 19 | 20 | This encryption code is a direct transcription of the algorithm from 21 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This 22 | file (appnote.txt) is distributed with the PKZIP program (even in the 23 | version without encryption capabilities). 24 | 25 | If you don't need crypting in your application, just define symbols 26 | NOCRYPT and NOUNCRYPT. 27 | 28 | Mar 8th, 2016 - Lucio Cosmo 29 | Fixed support for 64bit builds for archives with "PKWARE" password. 30 | Changed long, unsigned long, unsigned to unsigned int in 31 | access functions to crctables and pkeys 32 | 33 | */ 34 | 35 | #define CRC32(c, b) ((*(pcrc_32_tab+(((unsigned int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) 36 | 37 | /*********************************************************************** 38 | * Return the next byte in the pseudo-random sequence 39 | */ 40 | static int decrypt_byte(unsigned int* pkeys) 41 | { 42 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an 43 | * unpredictable manner on 16-bit systems; not a problem 44 | * with any known compiler so far, though */ 45 | 46 | temp = ((unsigned int)(*(pkeys+2)) & 0xffff) | 2; 47 | return (unsigned int)(((temp * (temp ^ 1)) >> 8) & 0xff); 48 | } 49 | 50 | /*********************************************************************** 51 | * Update the encryption keys with the next byte of plain text 52 | */ 53 | static int update_keys(unsigned int* pkeys,const unsigned int* pcrc_32_tab,int c) 54 | { 55 | (*(pkeys+0)) = CRC32((*(pkeys+0)), c); 56 | (*(pkeys+1)) += (*(pkeys+0)) & 0xff; 57 | (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; 58 | { 59 | register int keyshift = (int)((*(pkeys+1)) >> 24); 60 | (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); 61 | } 62 | return c; 63 | } 64 | 65 | 66 | /*********************************************************************** 67 | * Initialize the encryption keys and the random header according to 68 | * the given password. 69 | */ 70 | static void init_keys(const char* passwd,unsigned int* pkeys,const unsigned int* pcrc_32_tab) 71 | { 72 | *(pkeys+0) = 305419896L; 73 | *(pkeys+1) = 591751049L; 74 | *(pkeys+2) = 878082192L; 75 | while (*passwd != 0) 76 | { 77 | update_keys(pkeys,pcrc_32_tab,(int)*passwd); 78 | passwd++; 79 | } 80 | } 81 | 82 | #define zdecode(pkeys,pcrc_32_tab,c) \ 83 | (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys))) 84 | 85 | #define zencode(pkeys,pcrc_32_tab,c,t) \ 86 | (t=decrypt_byte(pkeys), update_keys(pkeys,pcrc_32_tab,c), t^(c)) 87 | 88 | #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED 89 | 90 | #define RAND_HEAD_LEN 12 91 | /* "last resort" source for second part of crypt seed pattern */ 92 | # ifndef ZCR_SEED2 93 | # define ZCR_SEED2 3141592654UL /* use PI as default pattern */ 94 | # endif 95 | 96 | static int crypthead(const char* passwd, /* password string */ 97 | unsigned char* buf, /* where to write header */ 98 | int bufSize, 99 | unsigned int* pkeys, 100 | const unsigned int* pcrc_32_tab, 101 | unsigned int crcForCrypting) 102 | { 103 | int n; /* index in random header */ 104 | int t; /* temporary */ 105 | int c; /* random byte */ 106 | unsigned char header[RAND_HEAD_LEN-2]; /* random header */ 107 | static unsigned calls = 0; /* ensure different random header each time */ 108 | 109 | if (bufSize < RAND_HEAD_LEN) 110 | return 0; 111 | 112 | /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the 113 | * output of rand() to get less predictability, since rand() is 114 | * often poorly implemented. 115 | */ 116 | if (++calls == 1) 117 | { 118 | srand((unsigned)(time(NULL) ^ ZCR_SEED2)); 119 | } 120 | init_keys(passwd, pkeys, pcrc_32_tab); 121 | for (n = 0; n < RAND_HEAD_LEN-2; n++) 122 | { 123 | c = (rand() >> 7) & 0xff; 124 | header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); 125 | } 126 | /* Encrypt random header (last two bytes is high word of crc) */ 127 | init_keys(passwd, pkeys, pcrc_32_tab); 128 | for (n = 0; n < RAND_HEAD_LEN-2; n++) 129 | { 130 | buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); 131 | } 132 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); 133 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); 134 | return n; 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /include/db/source.h: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef _SOURCE_H_ 20 | #define _SOURCE_H_ 21 | 22 | #include 23 | #include 24 | 25 | #include "bhbb_dl.h" 26 | 27 | class Source 28 | { 29 | public: 30 | static const int CategoryAll = -1; 31 | 32 | enum ID 33 | { 34 | CBPS_DB = 0, 35 | VITA_DB, 36 | VHB_DB, 37 | PSPHBB, 38 | }; 39 | 40 | struct CategoryInfo 41 | { 42 | CategoryInfo(int _id, uint32_t sHash, uint32_t nHash):id(_id),singleHash(sHash),nameHash(nHash) 43 | { 44 | 45 | } 46 | 47 | int id; 48 | uint32_t singleHash; 49 | uint32_t nameHash; 50 | }; 51 | 52 | class Entry 53 | { 54 | public: 55 | Entry(Source *source):hash(0xDEADBEEF),pSource(source) 56 | { 57 | 58 | }; 59 | 60 | Source *pSource; 61 | 62 | uint32_t hash; 63 | int category; 64 | 65 | paf::wstring titleID; 66 | paf::wstring title; 67 | paf::wstring author; 68 | 69 | std::vector iconURL; 70 | paf::string iconPath; 71 | 72 | std::vector dataURL; 73 | paf::string dataPath; 74 | 75 | paf::wstring description; 76 | std::vector downloadURL; 77 | 78 | std::vector screenshotURL; 79 | 80 | paf::wstring version; 81 | 82 | paf::datetime::DateTime lastUpdated; 83 | unsigned int downloadNum; 84 | 85 | size_t downloadSize; 86 | size_t dataSize; 87 | }; 88 | 89 | class List 90 | { 91 | public: 92 | struct CategorisedEntries 93 | { 94 | CategorisedEntries(int _category):category(_category){} 95 | 96 | int category; 97 | std::vector entries; 98 | }; 99 | 100 | typedef bool (*SortFunc)(Source::Entry&a, Source::Entry& b); 101 | 102 | List(); 103 | virtual ~List(); 104 | 105 | void Categorise(Source *source); 106 | void Clear(); 107 | void Sort(SortFunc func); 108 | 109 | void Add(Source::Entry &entry) 110 | { 111 | entries.push_back(entry); 112 | } 113 | 114 | void Add(const Source::Entry &entry) 115 | { 116 | entries.push_back(entry); 117 | } 118 | 119 | size_t GetSize(int categoryID = -1); 120 | Source::Entry& Get(uint32_t hash); 121 | CategorisedEntries& GetCategory(int categoryID); 122 | 123 | std::vector entries; 124 | 125 | static bool Sort_MostDownloaded(Source::Entry &a,Source::Entry &b); 126 | static bool Sort_LeastDownloaded(Source::Entry &a,Source::Entry &b); 127 | static bool Sort_MostRecent(Source::Entry &a,Source::Entry &b); 128 | static bool Sort_OldestFirst(Source::Entry &a,Source::Entry &b); 129 | static bool Sort_Alphabetical(Source::Entry &a,Source::Entry &b); 130 | static bool Sort_AlphabeticalRev(Source::Entry &a,Source::Entry &b); 131 | static bool Sort_None(Source::Entry &a,Source::Entry &b) 132 | { 133 | return false; 134 | } 135 | 136 | private: 137 | std::vector categoriedEntries; 138 | }; 139 | 140 | struct SortMode // Could use a map for this maybe? 141 | { 142 | SortMode(uint32_t _hash, List::SortFunc _func):hash(_hash),func(_func) 143 | { 144 | 145 | } 146 | 147 | uint32_t hash; // label hash 148 | List::SortFunc func; 149 | }; 150 | 151 | enum IconAspectRatio 152 | { 153 | r1x1, 154 | r67x37 // PSPHBB uses this for icons (wtf?) 155 | }; 156 | 157 | Source(); 158 | 159 | static paf::common::SharedPtr Create(ID id); 160 | 161 | virtual ~Source(){}; 162 | 163 | virtual int Parse() = 0; 164 | virtual int DownloadIndex(bool forceRefresh = false) = 0; 165 | virtual int GetDescription(Entry &entry, paf::wstring& out) = 0; 166 | virtual int GetDownloadURL(Entry &entry, paf::string& out) = 0; 167 | virtual int GetDataURL(Entry &entry, paf::string& out) = 0; 168 | virtual wchar_t *GetName() = 0; 169 | 170 | // These functions HAVE defaults and sources are not expected to override them unless they have special download logic 171 | virtual int CreateDownloadParam(Entry& entry, BGDLParam& param); 172 | virtual int CreateDataDownloadParam(Entry& entry, BGDLParam& param); 173 | 174 | const CategoryInfo& GetCategoryByID(int id); 175 | const Source::CategoryInfo& GetCategoryByHash(uint32_t hash); 176 | List::SortFunc GetSortFunction(uint32_t hash); 177 | 178 | // List to parse to 179 | List *pList; 180 | 181 | // Info 182 | IconAspectRatio iconRatio; 183 | paf::string iconFolderPath; 184 | paf::string iconsURL; 185 | std::vector categories; 186 | std::vector sortModes; // first sort mode will be default! 187 | bool screenshotsSupported; 188 | uint8_t id; 189 | }; 190 | 191 | #endif -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "print.h" 31 | #include "utils.h" 32 | #include "common.h" 33 | #include "bhbb_plugin.h" 34 | #include "bhbb_locale.h" 35 | #include "pages/app_browser.h" 36 | #include "pages/text_page.h" 37 | #include "db/source.h" 38 | #include "settings.h" 39 | #include "downloader.h" 40 | 41 | #define NET_HEAP_SIZE SCE_KERNEL_256KiB 42 | #define HTTP_HEAP_SIZE SCE_KERNEL_256KiB 43 | #define SSL_HEAP_SIZE SCE_KERNEL_256KiB 44 | 45 | extern "C" { 46 | const char sceUserMainThreadName[] = "BHBB_MAIN"; 47 | const int sceUserMainThreadPriority = SCE_KERNEL_DEFAULT_PRIORITY_USER; 48 | const unsigned int sceUserMainThreadStackSize = SCE_KERNEL_THREAD_STACK_SIZE_DEFAULT_USER_MAIN; 49 | 50 | SceUID _vshKernelSearchModuleByName(const char *name, SceUInt64 *unk); 51 | int curl_global_memmanager_set_np(void *(*allocate)(size_t), void (*deallocate)(void *), void *(*reallocate)(void *, size_t)); 52 | } 53 | 54 | using namespace paf; 55 | 56 | Plugin *g_appPlugin = nullptr; 57 | 58 | SceVoid PluginStart(Plugin *plugin) 59 | { 60 | if(plugin == nullptr) 61 | { 62 | print("[bhbb_plugin] Error Plugin load failed!\n"); 63 | return; 64 | } 65 | 66 | g_appPlugin = plugin; 67 | print("[bhbb_plugin] Create success! %p\n", plugin); 68 | 69 | SceKernelFwInfo fw; 70 | fw.size = sizeof(fw); 71 | _vshSblGetSystemSwVersion(&fw); 72 | 73 | int subVersion = sce_paf_atoi(&fw.versionString[2]); // Too lazy to figure out how fw.version works (lol) 74 | 75 | if(subVersion < 68) // Version 3.68 introduced TLS 1.2 and doesn't need iTLS-Enso 76 | { 77 | SceUInt64 buff = 0; 78 | SceUID itlsID = _vshKernelSearchModuleByName("itlsKernel", &buff); 79 | 80 | print("iTLS-Enso: 0x%X\n", itlsID); 81 | if(itlsID < 0) 82 | { 83 | new page::TextPage(msg_no_itls); 84 | return; 85 | } 86 | } 87 | 88 | sceShellUtilInitEvents(0); 89 | 90 | job::JobQueue::Option opt; 91 | opt.workerNum = 1; 92 | opt.workerStackSize = SCE_KERNEL_256KiB; 93 | 94 | job::JobQueue::Init(&opt); 95 | 96 | SceNetInitParam netInitParam; 97 | netInitParam.memory = sce_paf_malloc(NET_HEAP_SIZE); 98 | netInitParam.size = NET_HEAP_SIZE; 99 | netInitParam.flags = 0; 100 | sceNetInit(&netInitParam); 101 | 102 | sceNetCtlInit(); 103 | 104 | /* HTTPS */ 105 | sceSysmoduleLoadModule(SCE_SYSMODULE_SSL); 106 | sceSysmoduleLoadModule(SCE_SYSMODULE_HTTPS); 107 | sceHttpInit(HTTP_HEAP_SIZE); 108 | sceSslInit(SSL_HEAP_SIZE); 109 | 110 | new Downloader(); 111 | new Settings(); 112 | 113 | auto page = new AppBrowser(Source::Create((Source::ID)Settings::GetInstance()->source)); 114 | page->Load(); 115 | } 116 | 117 | int main() 118 | { 119 | #if defined(SCE_PAF_TOOL_PRX) && defined(_DEBUG) && !defined(__INTELLISENSE__) 120 | //This line will break things if using non devkit libpaf 121 | SCE_PAF_AUTO_TEST_SET_EXTRA_TTY(sceIoOpen("tty0:", SCE_O_WRONLY, 0)); 122 | #endif 123 | 124 | Utils::StartBGDL(); // Init bhbb_dl 125 | Utils::InitMusic(); // BG Music 126 | 127 | sceSysmoduleLoadModule(SCE_SYSMODULE_NET); 128 | sceSysmoduleLoadModule(SCE_SYSMODULE_FIBER); 129 | sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_COMMON_GUI_DIALOG); 130 | 131 | new Module("app0:module/libcurl.suprx", "libcurl"); 132 | curl_global_memmanager_set_np(sce_paf_malloc, sce_paf_free, sce_paf_realloc); 133 | 134 | Framework::InitParam fwParam; 135 | 136 | Framework::SampleInit(&fwParam); 137 | fwParam.mode = Framework::Mode_Application; 138 | 139 | fwParam.surface_pool_size = SCE_KERNEL_8MiB; 140 | fwParam.text_surface_pool_size = SCE_KERNEL_4MiB; 141 | 142 | Framework *fw = new Framework(fwParam); 143 | 144 | fw->LoadCommonResourceSync(); 145 | 146 | SceAppUtilInitParam init; 147 | SceAppUtilBootParam boot; 148 | 149 | //Can use sce_paf_... because paf is preloaded 150 | sce_paf_memset(&init, 0, sizeof(SceAppUtilInitParam)); 151 | sce_paf_memset(&boot, 0, sizeof(SceAppUtilBootParam)); 152 | 153 | sceAppUtilInit(&init, &boot); 154 | 155 | Plugin::InitParam piParam; 156 | 157 | piParam.name = "bhbb_plugin"; 158 | piParam.resource_file = "app0:resource/bhbb_plugin.rco"; 159 | piParam.caller_name = "__main__"; 160 | 161 | #if defined(SCE_PAF_TOOL_PRX) && defined(_DEBUG) 162 | //This line will break things if using non devkit libpaf 163 | piParam.option = Plugin::Option_ResourceLoadWithDebugSymbol; 164 | #endif 165 | 166 | piParam.start_func = PluginStart; 167 | 168 | Plugin::LoadAsync(piParam); 169 | 170 | fw->Run(); 171 | 172 | return sceKernelExitProcess(0); 173 | } -------------------------------------------------------------------------------- /bhbb_dl/src/zip.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "zip.h" 23 | #include "print.h" 24 | 25 | #include "minizip/unzip.h" 26 | 27 | #define dir_delimter '/' 28 | #define MAX_FILENAME 512 29 | 30 | Zipfile::Zipfile(const paf::string zip_path) 31 | { 32 | handle = unzOpen(zip_path.c_str()); 33 | if (handle == nullptr) 34 | { 35 | print("[Error] unzOpen %s -> %p\n", zip_path.c_str(), handle); 36 | error = -0xC0FFEE; 37 | return; 38 | } 39 | 40 | error = unzGetGlobalInfo(handle, &globalInfo); 41 | if (error != UNZ_OK) 42 | { 43 | print("Cannot read zip info %d\n", error); 44 | return; 45 | } 46 | 47 | readBuff = (char *)sce_paf_malloc(ZIP_CUNK_SIZE); 48 | } 49 | 50 | Zipfile::~Zipfile() 51 | { 52 | if (handle != nullptr) 53 | unzClose(handle); 54 | if(readBuff != nullptr) 55 | sce_paf_free(readBuff); 56 | } 57 | 58 | int Zipfile::Decompress(const paf::string outPath, ProgressCallback progressCallback, void *progressUserData) 59 | { 60 | if(!handle && error != UNZ_OK) 61 | return error; 62 | 63 | if (uncompressedSize == 0) 64 | CalculateUncompressedSize(); 65 | 66 | error = unzGoToFirstFile(handle); 67 | if(error != UNZ_OK) 68 | { 69 | print("Error going to first file!\n", error); 70 | return error; 71 | } 72 | 73 | error = UNZ_OK; 74 | uint64_t extractedBytes = 0; 75 | for(unsigned long i = 0; i < globalInfo.number_entry; i++, error = unzGoToNextFile(handle)) 76 | { 77 | unz_file_info info; 78 | char fileName[0x200]; 79 | paf::string fullPath; 80 | 81 | if(error != UNZ_OK) 82 | { 83 | print("error going to next file %d\n", error); 84 | return error; 85 | } 86 | 87 | error = unzGetCurrentFileInfo(handle, &info, fileName, sizeof(fileName), nullptr, 0, nullptr, 0); 88 | if(error != UNZ_OK) 89 | { 90 | print("Error getting file info %d\n", error); 91 | return error; 92 | } 93 | 94 | fullPath = outPath + paf::string(fileName); 95 | 96 | if(fullPath.c_str()[fullPath.size() - 1] == '/') // Check to see if entry is a directory 97 | { 98 | print("Creating dir: %s\n", fullPath.c_str()); 99 | paf::Dir::CreateRecursive(fullPath.c_str()); 100 | } 101 | else 102 | { 103 | paf::string destdir = paf::common::StripFilename(fullPath, "P"); 104 | paf::Dir::CreateRecursive(destdir.c_str()); 105 | 106 | error = unzOpenCurrentFile(handle); 107 | if(error != UNZ_OK) 108 | { 109 | print("Error opening zip file %s -> %d (Save To: %s)\n", fileName, error, fullPath.c_str()); 110 | unzCloseCurrentFile(handle); 111 | return error; 112 | } 113 | 114 | auto fHandle = paf::LocalFile::Open(fullPath.c_str(), SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0666, &error); 115 | if(error != SCE_PAF_OK) 116 | { 117 | print("Error opening file %s -> 0x%X\n", fullPath.c_str(), error); 118 | unzCloseCurrentFile(handle); 119 | return error; 120 | } 121 | 122 | do 123 | { 124 | error = unzReadCurrentFile(handle, readBuff, ZIP_CUNK_SIZE); 125 | if(error < 0) 126 | { 127 | print("[Error] failed to read zfile %s %d\n", fileName, error); 128 | break; 129 | } 130 | 131 | fHandle.get()->Write(readBuff, error); 132 | 133 | } while(error > 0); 134 | 135 | print("Extracted: %s -> %s\n", fileName, fullPath.c_str()); 136 | if(progressCallback) 137 | progressCallback(fileName, i, globalInfo.number_entry, progressUserData); 138 | 139 | unzCloseCurrentFile(handle); 140 | 141 | } 142 | } 143 | 144 | return UNZ_OK; 145 | } 146 | 147 | int Zipfile::CalculateUncompressedSize() 148 | { 149 | error = unzGoToFirstFile(handle); 150 | if(error != UNZ_OK) 151 | { 152 | print("Error going to first file!\n", error); 153 | unzClose(handle); 154 | return error; 155 | } 156 | 157 | uncompressedSize = 0; 158 | for(unsigned long i = 0; i < globalInfo.number_entry; i++, error = unzGoToNextFile(handle)) 159 | { 160 | unz_file_info info; 161 | char fileName[0x200]; 162 | 163 | if(error != UNZ_OK) 164 | { 165 | print("error going to next file %d\n", error); 166 | unzClose(handle); 167 | return error; 168 | } 169 | 170 | error = unzGetCurrentFileInfo(handle, &info, fileName, sizeof(fileName), nullptr, 0, nullptr, 0); 171 | if(error != UNZ_OK) 172 | { 173 | print("Error getting file info %d\n", error); 174 | unzClose(handle); 175 | return error; 176 | } 177 | 178 | uncompressedSize += info.uncompressed_size; 179 | } 180 | 181 | return UNZ_OK; 182 | } 183 | -------------------------------------------------------------------------------- /bhbb_dl/src/tgz.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2023 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "tgz.h" 23 | #include "dialog.h" 24 | #include "print.h" 25 | 26 | using namespace paf; 27 | 28 | TgzFile::TgzFile(paf::string path) 29 | { 30 | file = LocalFile::Open(path.c_str(), SCE_O_RDONLY, 0, &error); 31 | if(error != SCE_PAF_OK) 32 | { 33 | print("[TgzFile] %s -> 0x%X -> TGZ_FERR\n", path.c_str(), error); 34 | error = TGZ_FERR; 35 | return; 36 | } 37 | 38 | readBuff = (Bytef *)sce_paf_malloc(TGZ_CHUNK_SIZE); 39 | if(!readBuff) 40 | { 41 | print("[TgzFile::TgzFile] TGZ_MEMERR Error allocating buffer\n"); 42 | error = TGZ_MEMERR; 43 | return; 44 | } 45 | 46 | zstrm.zalloc = sce_paf_gzip_zalloc; 47 | zstrm.zfree = sce_paf_gzip_zfree; 48 | zstrm.opaque = Z_NULL; 49 | zstrm.avail_in = 0; 50 | zstrm.next_in = Z_NULL; 51 | zstrm.avail_out = -1; // Queue file read in next Read() call 52 | 53 | error = inflateInit2_(&zstrm, 15 | 16, "1.2.5", sizeof(z_stream)); 54 | if(error != Z_OK) 55 | { 56 | sce_paf_free(readBuff); 57 | print("[TgzFile::TgzFile] inflateInit2_ error -> 0x%X\n", error); 58 | return; 59 | } 60 | 61 | error = TGZ_OK; 62 | } 63 | 64 | TgzFile::~TgzFile() 65 | { 66 | if(readBuff) 67 | sce_paf_free(readBuff); 68 | 69 | inflateEnd(&zstrm); 70 | } 71 | 72 | int64_t TgzFile::Read(void *buff, size_t rsize) 73 | { 74 | if(zstrm.avail_out != 0 /*buffer has inflated*/) 75 | { 76 | if(file->IsEof()) 77 | return TGZ_EOF; 78 | 79 | sce_paf_memset(readBuff, 0, TGZ_CHUNK_SIZE); 80 | auto rSize = file->Read(readBuff, TGZ_CHUNK_SIZE); 81 | if(rSize < 0) 82 | { 83 | print("[TgzFile::Read] file->Read() FAIL! 0x%X\n", rSize); 84 | return TGZ_FERR; 85 | } 86 | 87 | zstrm.avail_in = rSize; 88 | zstrm.next_in = (Bytef *)readBuff; 89 | } 90 | 91 | zstrm.next_out = (Bytef *)buff; 92 | zstrm.avail_out = rsize; 93 | 94 | auto ret = inflate(&zstrm, Z_NO_FLUSH); 95 | 96 | switch (ret) 97 | { 98 | case Z_NEED_DICT: 99 | ret = Z_DATA_ERROR; /* and fall through */ 100 | case Z_DATA_ERROR: 101 | case Z_MEM_ERROR: 102 | return ret; 103 | } 104 | 105 | return rsize - zstrm.avail_out; 106 | } 107 | 108 | int TgzFile::Decompress(paf::string outPath, ProgressCallback progressCB, void *progressData) 109 | { 110 | print("[TgzFile::Decompress] START\n"); 111 | 112 | paf::Dir::CreateRecursive(outPath.c_str()); 113 | 114 | TarHeader tHeader; 115 | unsigned long fileSize; 116 | unsigned long remainingBytes; 117 | size_t padding; 118 | int64_t ret; 119 | 120 | do 121 | { 122 | ret = Read(&tHeader, sizeof(tHeader)); 123 | 124 | auto fullPath = outPath + tHeader.name; 125 | 126 | switch(tHeader.typeflag) 127 | { 128 | case '0': 129 | case '\0': // Normal file 130 | { 131 | auto extractedFile = LocalFile::Open(fullPath.c_str(), SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0666, &error); 132 | if(error != SCE_OK) 133 | { 134 | print("[TgzFile::Decompress] Open(%s) FAIL! 0x%X\n", fullPath.c_str(), error); 135 | error = TGZ_FERR; 136 | return; 137 | } 138 | 139 | remainingBytes = fileSize = sce_paf_strtoul(tHeader.size, nullptr, 8); 140 | padding = ((int)sce_paf_ceilf((float)fileSize / 512.0f) * 512) - fileSize; // Round up to nearest 512th byte and calculate extra padding size 141 | 142 | print("[Tgs::Decompress] Extracting: %s (%zu bytes, %zu padding)\n", tHeader.name, fileSize, padding); 143 | 144 | char *rbuff = (char *)sce_paf_malloc(TGZ_CHUNK_SIZE); 145 | do 146 | { 147 | ret = Read(rbuff, remainingBytes > TGZ_CHUNK_SIZE ? TGZ_CHUNK_SIZE : remainingBytes); 148 | if(ret < 0) 149 | { 150 | sce_paf_free(rbuff); 151 | return ret; 152 | } 153 | 154 | extractedFile->Write(rbuff, ret); 155 | 156 | remainingBytes -= ret; 157 | 158 | } while(fileSize > 0 && ret > 0); 159 | 160 | progressCB(tHeader.name, zstrm.total_in, file->GetFileSize(), progressData); 161 | ret = Read(rbuff, padding); // Read padding just to advance the file pointer in the compressed file 162 | sce_paf_free(rbuff); 163 | 164 | break; 165 | } 166 | case '5': //Directory 167 | Dir::CreateRecursive(fullPath.c_str()); 168 | 169 | print("Directory: %s\n", tHeader.name); 170 | break; 171 | } 172 | 173 | } while(ret >= 0 && !file->IsEof()); 174 | print("[TgzFile::Decompress] success STOP\n"); 175 | return TGZ_OK; 176 | } 177 | 178 | int TgzFile::CalculateUncompressedSize() 179 | { 180 | auto fileSize = file->GetFileSize(); 181 | uncompressedSize = fileSize * 2; 182 | return 0; 183 | } -------------------------------------------------------------------------------- /src/db/source.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "db/source.h" 23 | #include "print.h" 24 | #include "bhbb_dl.h" 25 | 26 | #include "db/vitadb.h" 27 | #include "db/vhbd.h" 28 | #include "db/cbpsdb.h" 29 | #include "db/psphbb.h" 30 | 31 | Source::Source() 32 | { 33 | iconRatio = IconAspectRatio::r1x1; 34 | } 35 | 36 | Source::List::List() 37 | { 38 | 39 | } 40 | 41 | Source::List::~List() 42 | { 43 | Clear(); 44 | } 45 | 46 | paf::common::SharedPtr Source::Create(Source::ID id) 47 | { 48 | switch(id) 49 | { 50 | case VITA_DB: 51 | return paf::common::SharedPtr(new VitaDB()); 52 | case VHB_DB: 53 | return paf::common::SharedPtr(new VHBD()); 54 | case CBPS_DB: 55 | return paf::common::SharedPtr(new CBPSDB()); 56 | case PSPHBB: 57 | return paf::common::SharedPtr(new PSPHBDB()); 58 | } 59 | } 60 | 61 | const Source::CategoryInfo& Source::GetCategoryByID(int id) 62 | { 63 | for(const Source::CategoryInfo& cat : categories) 64 | if(cat.id == id) 65 | return cat; 66 | 67 | const Source::CategoryInfo notFound(0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF); 68 | return notFound; 69 | } 70 | 71 | const Source::CategoryInfo& Source::GetCategoryByHash(uint32_t hash) 72 | { 73 | for(const Source::CategoryInfo& cat : categories) 74 | if(cat.nameHash == hash) 75 | return cat; 76 | 77 | const Source::CategoryInfo notFound(0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF); 78 | return notFound; 79 | } 80 | 81 | void Source::List::Clear() 82 | { 83 | categoriedEntries.clear(); 84 | entries.clear(); 85 | } 86 | 87 | size_t Source::List::GetSize(int category) 88 | { 89 | if(category == Source::CategoryAll) 90 | return entries.size(); 91 | 92 | for(auto& cat : categoriedEntries) 93 | if(cat.category == category) 94 | return cat.entries.size(); 95 | 96 | return 0; 97 | } 98 | 99 | Source::Entry& Source::List::Get(uint32_t hash) 100 | { 101 | for(Source::Entry& entry : entries) 102 | if(entry.hash == hash) return entry; 103 | } 104 | 105 | Source::List::CategorisedEntries& Source::List::GetCategory(int category) 106 | { 107 | auto errList = List::CategorisedEntries(0xDEADBEEF); 108 | if(category == Source::CategoryAll) 109 | { 110 | print("[Error] Please use the entries property in order to acces an element without a specific category!\n"); 111 | return errList; 112 | } 113 | 114 | for(CategorisedEntries &catList : categoriedEntries) 115 | { 116 | if(catList.category == category) 117 | return catList; 118 | } 119 | return errList; 120 | } 121 | 122 | Source::List::SortFunc Source::GetSortFunction(uint32_t hash) 123 | { 124 | for(auto& i : sortModes) 125 | { 126 | if(i.hash == hash) 127 | return i.func; 128 | } 129 | return List::Sort_None; 130 | } 131 | 132 | void Source::List::Categorise(Source *source) 133 | { 134 | if(!categoriedEntries.empty()) 135 | categoriedEntries.clear(); 136 | 137 | for (Source::CategoryInfo &category : source->categories) 138 | { 139 | if(category.id == Source::CategoryAll) 140 | continue; 141 | 142 | CategorisedEntries entryList = CategorisedEntries(category.id); 143 | 144 | for(Source::Entry& entry : entries) 145 | if(entry.category == category.id) 146 | entryList.entries.push_back(&entry); 147 | 148 | categoriedEntries.push_back(entryList); 149 | } 150 | } 151 | 152 | bool Source::List::Sort_MostRecent(Source::Entry &a, Source::Entry &b) 153 | { 154 | return b.lastUpdated < a.lastUpdated; 155 | } 156 | 157 | bool Source::List::Sort_OldestFirst(Source::Entry &a, Source::Entry &b) 158 | { 159 | return a.lastUpdated < b.lastUpdated; 160 | } 161 | 162 | bool Source::List::Sort_MostDownloaded(Source::Entry &a, Source::Entry &b) 163 | { 164 | return b.downloadNum < a.downloadNum; 165 | } 166 | 167 | bool Source::List::Sort_LeastDownloaded(Source::Entry &a, Source::Entry &b) 168 | { 169 | return a.downloadNum < b.downloadNum; 170 | } 171 | 172 | bool Source::List::Sort_Alphabetical(Source::Entry &a, Source::Entry &b) 173 | { 174 | return sce_paf_wcscasecmp(a.title.c_str(), b.title.c_str()) < 0; 175 | } 176 | 177 | bool Source::List::Sort_AlphabeticalRev(Source::Entry &a, Source::Entry &b) 178 | { 179 | return sce_paf_wcscasecmp(b.title.c_str(), a.title.c_str()) < 0; 180 | } 181 | 182 | void Source::List::Sort(SortFunc func) 183 | { 184 | std::sort(entries.begin(), entries.end(), func); 185 | } 186 | 187 | int Source::CreateDownloadParam(Entry& entry, BGDLParam& dlParam) 188 | { 189 | dlParam.type = BGDLTarget_App; 190 | sce_paf_strncpy(dlParam.data_icon, entry.iconPath.c_str(), sizeof(dlParam.data_icon)); 191 | 192 | return 0; 193 | } 194 | 195 | int Source::CreateDataDownloadParam(Entry& entry, BGDLParam& dlParam) 196 | { 197 | dlParam.type = BGDLTarget_CompressedFile; 198 | sce_paf_strncpy(dlParam.path, entry.dataPath.c_str(), sizeof(dlParam.path)); 199 | sce_paf_strncpy(dlParam.data_icon, entry.iconPath.c_str(), sizeof(dlParam.data_icon)); 200 | 201 | return 0; 202 | } -------------------------------------------------------------------------------- /bhbb_dl/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | //Based of off bgvpk by SKGleba, download_enabler by TheFlow and NetStream-DE by GrapheneCt 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "main.h" 27 | #include "print.h" 28 | #include "offsets.h" 29 | #include "bhbb_dl.h" 30 | #include "installer.h" 31 | 32 | using namespace paf; 33 | 34 | tai_hook_ref_t ToastRef; 35 | SceUID ToastID = SCE_UID_INVALID_UID; 36 | int ToastPatch(void *off, unsigned int arg) 37 | { 38 | if(!arg && off != nullptr) 39 | { 40 | if(LocalFile::Exists(common::FormatString("ux0:/bgdl/t/%08x/.installed", *(::uint32_t *)off).c_str())) 41 | return 0; // Notification should already be handled in export function 42 | } 43 | 44 | return TAI_NEXT(ToastPatch, ToastRef, off, arg); 45 | } 46 | 47 | tai_hook_ref_t ExportFileRef; 48 | SceUID ExportFileID = SCE_UID_INVALID_UID; 49 | int ExportFilePatched(unsigned int *data) 50 | { 51 | int res = TAI_NEXT(ExportFilePatched, ExportFileRef, data); 52 | 53 | if(res == 0x80101A09) // Unsupported file 54 | { 55 | char buff[SCE_IO_MAX_PATH_BUFFER_SIZE]; 56 | ::uint32_t bgdlID = *(::uint32_t *)data[0]; 57 | pdb_flags_t flags; 58 | BGDLParam param; 59 | 60 | // BHBB files will have a param file as a flag. 61 | string bgdl_path = common::FormatString("ux0:bgdl/t/%08x/bhbb.param", bgdlID); 62 | 63 | SceUID fd = sceIoOpen(bgdl_path.c_str(), SCE_O_RDONLY, 0); 64 | if(fd < 0) // prob doesn't exist 65 | return 0x80101A09; // We can leave this to other download plugins 66 | 67 | sceIoRead(fd, ¶m, sizeof(BGDLParam)); 68 | sceIoClose(fd); 69 | 70 | bgdl_path = common::FormatString("ux0:bgdl/t/%08x/d0.pdb", bgdlID); 71 | 72 | string title; 73 | string icon_path; 74 | 75 | // offset of current entry's flags 76 | uint16_t offset = 0xD3; 77 | 78 | // paf::LocalFile would be nice but it doesn't have pread?! :( sony L 79 | fd = sceIoOpen(bgdl_path.c_str(), SCE_O_RDONLY, 0); 80 | if(fd < 0) 81 | return fd; 82 | 83 | sceIoPread(fd, &flags, sizeof(flags), offset); // Read first (title) flags 84 | 85 | sceIoPread(fd, buff, flags.size, offset + sizeof(flags)); // offset + sizeof(flags) = offset of entry itself 86 | 87 | title = buff; 88 | 89 | offset += flags.size + 0xC; // sizeof(flags) + 1 90 | sceIoPread(fd, &flags, sizeof(flags), offset); 91 | 92 | if(flags.size == 1) // Apparently this means that the title is the url and next one is file name so we skip? 93 | { 94 | offset += flags.size + 0xC; 95 | sceIoPread(fd, &flags, sizeof(flags), offset); 96 | } 97 | 98 | sceIoPread(fd, buff, flags.size, offset + sizeof(flags)); // We now have the file_name 99 | bgdl_path = common::FormatString("ux0:bgdl/t/%08x/%s", bgdlID, buff); 100 | 101 | // Next entry is download url (we skip) 102 | offset += flags.size + 0xC; 103 | sceIoPread(fd, &flags, sizeof(flags), offset); 104 | // Read next flags 105 | offset += flags.size + 0xC; 106 | sceIoPread(fd, &flags, sizeof(flags), offset); 107 | // Read icon path 108 | sceIoPread(fd, buff, flags.size, offset + sizeof(flags)); 109 | 110 | icon_path = buff; 111 | 112 | sceIoClose(fd); 113 | 114 | return ProcessExport(bgdlID, title.c_str(), bgdl_path.c_str(), icon_path.c_str(), ¶m); 115 | } 116 | 117 | return res; 118 | } 119 | 120 | tai_hook_ref_t GetFileTypeRef; 121 | SceUID GetFileTypeID = SCE_UID_INVALID_UID; 122 | int GetFileTypePatched(int unk, int *type, char **filename, char **mime_type) 123 | { 124 | print("unk: %p type: %p fileName: %p mime_type: %s\n", unk, type, filename, *mime_type); 125 | int res = TAI_NEXT(GetFileTypePatched, GetFileTypeRef, unk, type, filename, mime_type); 126 | 127 | if (res == 0x80103A21) 128 | { 129 | if(type != nullptr) 130 | *type = 1; //Type photo 131 | return 0; 132 | } 133 | 134 | return res; 135 | } 136 | 137 | 138 | int module_start(size_t args, void *argp) 139 | { 140 | tai_module_info_t info; 141 | 142 | sceClibMemset(&info, 0, sizeof(info)); 143 | info.size = sizeof(info); 144 | 145 | if(taiGetModuleInfo("SceShell", &info) < 0) 146 | return SCE_KERNEL_START_FAILED; 147 | 148 | unsigned int exp_off, rec_off, notif_off; 149 | 150 | if(GetShellOffsets(info.module_nid, &exp_off, &rec_off, ¬if_off) < 0) 151 | { 152 | sceClibPrintf("[BHBB_DL] unsupported firmware! FATAL\n"); 153 | return SCE_KERNEL_START_FAILED; 154 | } 155 | 156 | ExportFileID = taiHookFunctionOffset(&ExportFileRef, info.modid, 0, exp_off, 1, (void *)ExportFilePatched); 157 | GetFileTypeID = taiHookFunctionOffset(&GetFileTypeRef, info.modid, 0, rec_off, 1, (void *)GetFileTypePatched); 158 | ToastID = taiHookFunctionOffset(&ToastRef, info.modid, 0, notif_off, 1, (void *)ToastPatch); 159 | 160 | return SCE_KERNEL_START_SUCCESS; 161 | } 162 | 163 | int module_stop(size_t args, void *argp) 164 | { 165 | if(ToastID >= 0) 166 | taiHookRelease(ToastID, ToastRef); 167 | if(GetFileTypeID >= 0) 168 | taiHookRelease(GetFileTypeID, GetFileTypeRef); 169 | if(ExportFileID >= 0) 170 | taiHookRelease(ExportFileID, ExportFileRef); 171 | 172 | return SCE_KERNEL_STOP_SUCCESS; 173 | } 174 | -------------------------------------------------------------------------------- /src/db/psphbb.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "db/psphbb.h" 22 | #include "bhbb_locale.h" 23 | #include "utils.h" 24 | #include "print.h" 25 | #include "json.h" 26 | 27 | #define PSPHBB_INDEX_URL "http://archive.org/download/all_20240613/all.json" 28 | #define PSPHBB_SAVE_PATH "savedata0:psphbb.json" 29 | 30 | using namespace paf; 31 | 32 | PSPHBDB::PSPHBDB() 33 | { 34 | iconFolderPath = "ux0:/data/betterHomebrewBrowser/icons/psphbb/"; 35 | screenshotsSupported = true; 36 | categories = { 37 | { 38 | CategoryAll, 39 | db_category_all, 40 | db_category_all 41 | }, 42 | { 43 | GAME, 44 | db_category_single_game, 45 | db_category_game 46 | }, 47 | { 48 | UTIL, 49 | db_category_single_util, 50 | db_category_util 51 | }, 52 | { 53 | EMU, 54 | db_category_single_emu, 55 | db_category_emu 56 | }, 57 | { 58 | PORT, 59 | db_category_single_port, 60 | db_category_port 61 | } 62 | }; 63 | 64 | sortModes = { 65 | { 66 | msg_sort_mostrecent, 67 | List::Sort_MostRecent 68 | }, 69 | { 70 | msg_sort_oldfirst, 71 | List::Sort_OldestFirst 72 | }, 73 | { 74 | msg_sort_alpha, 75 | List::Sort_Alphabetical 76 | }, 77 | { 78 | msg_sort_alpharev, 79 | List::Sort_AlphabeticalRev 80 | } 81 | }; 82 | iconRatio = r67x37; 83 | 84 | Dir::CreateRecursive(iconFolderPath.c_str()); 85 | } 86 | 87 | PSPHBDB::~PSPHBDB() 88 | { 89 | 90 | } 91 | 92 | int PSPHBDB::Parse() 93 | { 94 | pList->Clear(); 95 | 96 | int ret = SCE_OK; 97 | auto file = paf::LocalFile::Open(PSPHBB_SAVE_PATH, SCE_O_RDONLY, 0, &ret); 98 | if(ret < 0) 99 | { 100 | print("[PSPHBDB::DownloadIndex] LocalFile::Open -> 0x%X\n", ret); 101 | return ret; 102 | } 103 | 104 | auto fileSize = file->GetFileSize(); 105 | 106 | char *jstring = new char[fileSize + 1]; 107 | if(jstring == nullptr) 108 | { 109 | print("[PSPHBDB::Parse] Failed to allocate read buffer"); 110 | return 0xC0FFEE; 111 | } 112 | 113 | ret = file->Read(jstring, fileSize); 114 | if(ret < 0) 115 | { 116 | print("[PSPHBDB::Parse] Failed to read file"); 117 | delete[] jstring; 118 | return 0xAAABBB; 119 | } 120 | 121 | DynamicJsonDocument jdoc(SCE_KERNEL_32KiB); 122 | 123 | DeserializationError err = deserializeJson(jdoc, jstring); 124 | if(err != DeserializationError::Ok) 125 | { 126 | print("Error parsing JSON: %s\n", err.c_str()); 127 | return err.code(); 128 | } 129 | 130 | size_t elemCount = jdoc.size(); 131 | print("[PSPHBB::Parse] %zu elements\n", elemCount); 132 | for(size_t i = 0; i < elemCount; i++) 133 | { 134 | Source::Entry entry(this); 135 | 136 | entry.hash = IDParam(jdoc[i]["id"].as()).GetIDHash(); 137 | entry.lastUpdated.ParseSQLiteDateTime(jdoc[i]["date"].as()); 138 | common::Utf8ToUtf16(jdoc[i]["author"].as(), &entry.author); 139 | common::Utf8ToUtf16(jdoc[i]["description"].as(), &entry.description); 140 | common::Utf8ToUtf16(jdoc[i]["name"].as(), &entry.title); 141 | common::Utf8ToUtf16(jdoc[i]["version"].as(), &entry.version); 142 | 143 | entry.category = jdoc[i]["category"].as(); 144 | entry.downloadSize = jdoc[i]["size"].as(); 145 | 146 | entry.dataPath = "ux0:/pspemu/"; 147 | 148 | if(jdoc[i]["icon"] != nullptr) 149 | { 150 | entry.iconURL.push_back(jdoc[i]["icon"].as()); 151 | entry.iconPath = common::FormatString("%s%x.png", iconFolderPath.c_str(), entry.hash); 152 | } 153 | 154 | if(jdoc[i]["download_url"] != nullptr) 155 | entry.downloadURL.push_back(jdoc[i]["download_url"].as()); 156 | 157 | if(jdoc[i]["screenshots"] != nullptr) 158 | { 159 | for(int x = 0; x < jdoc[i]["screenshots"].size(); x++) 160 | entry.screenshotURL.push_back(jdoc[i]["screenshots"][x].as()); 161 | } 162 | 163 | entry.dataSize = 0; 164 | 165 | pList->Add(entry); 166 | } 167 | 168 | delete[] jstring; 169 | 170 | return 0; 171 | } 172 | 173 | int PSPHBDB::DownloadIndex(bool forceRefresh) 174 | { 175 | if(paf::LocalFile::Exists(PSPHBB_SAVE_PATH) && !forceRefresh) // No need to redownload 176 | { 177 | return 0; 178 | } 179 | 180 | int ret = Utils::DownloadFile(PSPHBB_INDEX_URL, PSPHBB_SAVE_PATH); 181 | 182 | print("[PSPHBDB::DownloadIndex] Utils::DownloadFile -> 0x%X\n", ret); 183 | 184 | return ret; 185 | } 186 | 187 | int PSPHBDB::GetDescription(Source::Entry &entry, paf::wstring& out) 188 | { 189 | out = entry.description; 190 | return 0; 191 | } 192 | 193 | int PSPHBDB::GetDownloadURL(Source::Entry &entry, paf::string& out) 194 | { 195 | if(entry.downloadURL.empty()) 196 | return -1; 197 | 198 | out = entry.downloadURL[0]; 199 | return 0; 200 | } 201 | 202 | int PSPHBDB::CreateDownloadParam(Source::Entry &entry, BGDLParam& dlParam) 203 | { 204 | dlParam.type = BGDLTarget_CompressedFile; 205 | sce_paf_strncpy(dlParam.path, entry.dataPath.c_str(), sizeof(dlParam.path)); 206 | sce_paf_strncpy(dlParam.data_icon, entry.iconPath.c_str(), sizeof(dlParam.data_icon)); 207 | } 208 | 209 | int PSPHBDB::GetDataURL(Source::Entry &entry, paf::string& out) 210 | { 211 | print("[PSPHBDB::GetDataURL] This source does not support data files!"); 212 | return 0; 213 | } -------------------------------------------------------------------------------- /bhbb_dl/include/head_bin.h: -------------------------------------------------------------------------------- 1 | // From bgvpk by @SKGleba. Under MIT 2 | // (https://github.com/SKGleba/VitaTools/tree/main/bgvpk/source) 3 | 4 | static const unsigned char tpl_head_bin[] = { 5 | 0x7f, 0x50, 0x4b, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x80, 6 | 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x03, 7 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0x0a, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 9 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 10 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 12 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 13 | 0xa6, 0x89, 0x94, 0x38, 0x19, 0xf2, 0xdd, 0x05, 0x87, 0x94, 0xb0, 0xb6, 14 | 0x7f, 0xc9, 0x30, 0x76, 0xdc, 0x2f, 0x22, 0xf2, 0x25, 0x40, 0xc6, 0xdf, 15 | 0x94, 0xcb, 0xb7, 0x78, 0xf8, 0xa2, 0x54, 0x95, 0x8c, 0xe6, 0xfd, 0x74, 16 | 0x81, 0x0c, 0xf7, 0x9d, 0x47, 0xb2, 0x86, 0x60, 0x3c, 0x2e, 0x00, 0xbb, 17 | 0xa2, 0x07, 0x59, 0x51, 0xe7, 0x95, 0xa4, 0xed, 0x83, 0x50, 0x35, 0xbc, 18 | 0x65, 0x63, 0xfe, 0x70, 0x8b, 0xab, 0x0c, 0x49, 0x73, 0x9d, 0xa3, 0xc9, 19 | 0x1f, 0x74, 0x48, 0x22, 0x70, 0x93, 0xfc, 0xe9, 0x40, 0xca, 0x74, 0x97, 20 | 0xba, 0xf1, 0xde, 0x1c, 0xaa, 0x67, 0xb7, 0x41, 0x78, 0xd7, 0x15, 0x68, 21 | 0x7f, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 22 | 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x10, 23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x00, 24 | 0xc0, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 25 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 26 | 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 27 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xa2, 0xcb, 0x21, 28 | 0x8b, 0x37, 0x06, 0x2d, 0x3e, 0x05, 0xfa, 0x11, 0x72, 0x72, 0x88, 0x85, 29 | 0xc9, 0x7b, 0x03, 0x99, 0xa0, 0x70, 0x9c, 0xf8, 0xcf, 0x9d, 0x41, 0x01, 30 | 0xd6, 0x17, 0x9f, 0xd3, 0x57, 0x79, 0x67, 0xf9, 0xb6, 0xf8, 0x56, 0x3d, 31 | 0xca, 0xfc, 0xa1, 0x98, 0xe2, 0xc7, 0xcf, 0xd6, 0x2e, 0x1b, 0xd6, 0x1b, 32 | 0xbe, 0x6f, 0xc1, 0x92, 0xbe, 0xe0, 0xb3, 0xc2, 0xe5, 0x65, 0x5a, 0x45, 33 | 0xd9, 0x88, 0xb4, 0x97, 0x5e, 0x16, 0x31, 0x3d, 0xa2, 0x3e, 0x16, 0xae, 34 | 0xd4, 0xb7, 0xd5, 0x36, 0xe3, 0xac, 0x80, 0x8f, 0x18, 0xfe, 0xad, 0x1a, 35 | 0x85, 0x20, 0xce, 0xee, 0xda, 0x5d, 0xb7, 0x95, 0x46, 0x34, 0xcc, 0x49, 36 | 0x52, 0x09, 0xf6, 0xeb, 0xa5, 0x0a, 0xe5, 0x7c, 0xb5, 0x7f, 0xaf, 0x6f, 37 | 0x4c, 0x06, 0x8c, 0xe4, 0xd8, 0x5a, 0x03, 0xaf, 0x92, 0x4e, 0x95, 0x5b, 38 | 0xbc, 0xe0, 0xc2, 0xac, 0xff, 0x12, 0x95, 0x31, 0x92, 0xad, 0x06, 0xe8, 39 | 0x17, 0x2c, 0xb1, 0xdc, 0x36, 0xa4, 0xc3, 0x9b, 0xe2, 0x3e, 0x2b, 0xec, 40 | 0x65, 0x53, 0xeb, 0x58, 0x84, 0x49, 0x09, 0x0b, 0xf4, 0xc6, 0xb4, 0x02, 41 | 0x70, 0xf3, 0x64, 0x58, 0x75, 0x14, 0x00, 0xf8, 0x68, 0x88, 0x46, 0x7e, 42 | 0x5c, 0xbc, 0xbe, 0x8b, 0x5f, 0xac, 0xe0, 0xe4, 0xa6, 0xf5, 0x77, 0xdd, 43 | 0xd9, 0xe5, 0xaf, 0x05, 0xf0, 0x5d, 0xae, 0x22, 0x7f, 0xb4, 0xd1, 0x1c, 44 | 0x7f, 0xcc, 0x3e, 0x98, 0x55, 0xb9, 0x69, 0xd2, 0xd2, 0x10, 0x55, 0x45, 45 | 0x4b, 0x3c, 0x95, 0x70, 0xb7, 0xc3, 0xdb, 0xfe, 0x23, 0xaf, 0xcd, 0x27, 46 | 0xa2, 0xd3, 0xac, 0x8c, 0x11, 0x09, 0xbf, 0xf6, 0xb2, 0x01, 0x62, 0x09, 47 | 0xc1, 0xda, 0xfd, 0xa7, 0x47, 0xa9, 0x48, 0xf4, 0x46, 0x26, 0x06, 0xf2, 48 | 0x76, 0x4d, 0xfe, 0x6f, 0x3f, 0x10, 0xb0, 0x1c, 0x1a, 0xde, 0x73, 0x8b, 49 | 0x14, 0x73, 0x3c, 0x39, 0xb6, 0xc6, 0x1b, 0xa1, 0x65, 0x99, 0xb8, 0x33, 50 | 0xac, 0xb8, 0x16, 0xb4, 0xe6, 0xa5, 0xec, 0x02, 0x0b, 0x5b, 0x70, 0x23, 51 | 0xeb, 0x24, 0x1a, 0xf7, 0x8c, 0xda, 0x55, 0x96, 0xdd, 0x4b, 0x1c, 0x85, 52 | 0x83, 0x49, 0x01, 0xb2, 0x39, 0xbc, 0x31, 0x3b, 0xe8, 0xf1, 0x5a, 0x49, 53 | 0xcc, 0xcf, 0x0f, 0x85, 0x5f, 0x54, 0x79, 0xe8, 0x31, 0x8d, 0x57, 0x1b, 54 | 0xb1, 0xc2, 0x93, 0x87, 0xe2, 0xe6, 0x56, 0xcf, 0x92, 0x51, 0xfc, 0x49, 55 | 0x94, 0xcd, 0xb5, 0x04, 0x1b, 0x04, 0x47, 0xf7, 0xb4, 0xd2, 0x67, 0x31, 56 | 0x54, 0xf0, 0xad, 0x3a, 0xd4, 0x25, 0x8c, 0xed, 0xe9, 0x9b, 0x12, 0xfc, 57 | 0x47, 0x1c, 0xfc, 0x6e, 0x81, 0x29, 0x8b, 0x39, 0xab, 0xbb, 0xf0, 0x35, 58 | 0x00, 0x87, 0x88, 0x87, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 59 | 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 60 | 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 61 | 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x05, 63 | 0x00, 0x00, 0x00, 0x04, 0x19, 0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 64 | 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 | 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 66 | 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x28, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x1a, 0x92, 0x07, 0x04, 68 | 0x61, 0x0c, 0x9d, 0x14, 0x55, 0x8e, 0x17, 0x74, 0xb6, 0x44, 0xd2, 0x5c, 69 | 0x93, 0xf3, 0xc1, 0x58, 0x0f, 0x91, 0x22, 0x2f, 0xfd, 0xb4, 0x42, 0xaa, 70 | 0x64, 0xfc, 0x8a, 0xd0, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x48, 71 | 0x00, 0x00, 0x05, 0x90, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 72 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 | 0x00, 0x00, 0x00, 0x00, 0xbe, 0x9a, 0x07, 0x26, 0x1a, 0x91, 0xd6, 0x35, 75 | 0x93, 0xcd, 0x59, 0xf4, 0x13, 0x23, 0x34, 0x05, 0x5b, 0xc4, 0xf5, 0xc3, 76 | 0x31, 0xf3, 0xf9, 0xf1, 0x7e, 0xdb, 0x7f, 0x53, 0x0f, 0x1a, 0x0a, 0x79, 77 | 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x0a, 0x30, 78 | 0x00, 0x00, 0x00, 0x60, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x2a, 0xa0, 0xf7, 80 | 0x3a, 0x41, 0x84, 0x7c, 0xb8, 0x66, 0x43, 0x7b, 0xca, 0xcd, 0x68, 0x5e, 81 | 0x44, 0xab, 0xd9, 0x85, 0xc9, 0x6b, 0xad, 0x33, 0xa9, 0xbc, 0x88, 0xc6, 82 | 0x75, 0xc5, 0x23, 0x9e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x28, 83 | 0x01, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 84 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 | 0x00, 0x00, 0x00, 0x00, 0x7a, 0xfe, 0xf5, 0x79, 0x30, 0xaf, 0x76, 0xe0, 87 | 0x46, 0xfc, 0x75, 0xdf, 0x08, 0x4e, 0xb8, 0x45, 0x3d, 0x4f, 0xcb, 0xf4, 88 | 0x3d, 0x9b, 0xfa, 0x5f, 0x61, 0x99, 0x6a, 0xde, 0x9c, 0x2e, 0x1a, 0x9c, 89 | 0x19, 0x15, 0x10, 0x1d, 0x71, 0xe6, 0xc0, 0x5a, 0x84, 0x3d, 0x20, 0xe8, 90 | 0xae, 0x1e, 0x1c, 0x71, 0x94, 0xee, 0xbc, 0x73, 0x4d, 0x2c, 0x46, 0xbf, 91 | 0x3c, 0xf3, 0x5b, 0x30, 0x3a, 0xc3, 0x18, 0x20, 0xff, 0xff, 0xff, 0xff, 92 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 93 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 94 | 0xff, 0xff, 0xff, 0xff 95 | }; 96 | static const unsigned int tpl_head_bin_len = 1072; 97 | -------------------------------------------------------------------------------- /src/utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2025 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "utils.h" 27 | #include "print.h" 28 | #include "common.h" 29 | #include "bhbb_dl.h" 30 | #include "error_codes.h" 31 | 32 | using namespace paf; 33 | using namespace paf::common; 34 | 35 | void Utils::HttpsToHttp(const char *src, paf::string& outURL) 36 | { 37 | if(sce_paf_strncmp(src, "https", 5) != 0) 38 | { 39 | outURL = src; 40 | return; 41 | } 42 | 43 | outURL = common::FormatString("http%s", &src[5]); 44 | } 45 | 46 | bool Utils::IsValidURLSCE(const char *url) 47 | { 48 | print("[Utils::IsValidURLSCE] START\n"); 49 | 50 | paf::HttpFile file; 51 | paf::HttpFile::OpenArg openArg; 52 | SceInt32 ret = SCE_OK; 53 | 54 | openArg.ParseUrl(url); 55 | openArg.SetOption(4000000, HttpFile::OpenArg::OptionType_ResolveTimeOut); 56 | openArg.SetOption(10000000, HttpFile::OpenArg::OptionType_ConnectTimeOut); 57 | 58 | ret = file.Open(&openArg); 59 | 60 | // if(ret == SCE_HTTP_ERROR_SSL) ret = SCE_OK; // Temporary fix till I figure out wot is going on with this SSL stuff (SceDownload should report proper error anyways) 61 | 62 | if(ret == SCE_OK) 63 | { 64 | file.Close(); 65 | return true; 66 | } 67 | print("Open %s FAIL 0x%X\n", url, ret); 68 | 69 | print("[Utils::IsValidURLSCE] END\n"); 70 | 71 | return false; 72 | } 73 | 74 | void Utils::InitMusic() 75 | { 76 | SceInt32 ret = -1; 77 | 78 | ret = sceMusicInternalAppInitialize(0); 79 | print("[sceMusicInternalAppInitialize] 0x%X\n", ret); 80 | 81 | SceMusicOpt optParams; 82 | sce_paf_memset(&optParams, 0, 0x10); 83 | 84 | optParams.flag = -1; 85 | 86 | ret = sceMusicInternalAppSetUri((char *)"pd0:data/systembgm/store.at9", &optParams); 87 | print("[sceMusicInternalAppSetUri] 0x%X\n", ret); 88 | 89 | ret = sceMusicInternalAppSetVolume(SCE_AUDIO_VOLUME_0DB); 90 | print("[sceMusicInternalAppSetVolume] 0x%X\n", ret); 91 | 92 | ret = sceMusicInternalAppSetRepeatMode(SCE_MUSIC_REPEAT_ONE); 93 | print("[sceMusicInternalAppSetRepeatMode] 0x%X\n", ret); 94 | 95 | ret = sceMusicInternalAppSetPlaybackCommand(SCE_MUSIC_EVENTID_DEFAULT, 0); 96 | print("[sceMusicInternalAppSetPlaybackCommand] 0x%X\n", ret); 97 | } 98 | 99 | size_t SaveCore(char *ptr, size_t size, size_t nmeb, SharedPtr *file) 100 | { 101 | return file->get()->Write(ptr, size * nmeb); 102 | } 103 | 104 | int Utils::DownloadFile(const char *url, const char *dest) 105 | { 106 | int ret = SCE_OK; 107 | SharedPtr file = LocalFile::Open(dest, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0666, &ret); 108 | if(ret != SCE_OK) 109 | { 110 | print("[Utils::DownloadFile] Failed to open %s for writing -> 0x%X\n", dest, ret); 111 | return ret; 112 | } 113 | 114 | CURL *handle = curl_easy_init(); 115 | if(!handle) 116 | { 117 | print("[Utils::DownloadFile] Failed to create curl handle!\n"); 118 | return -1; 119 | } 120 | 121 | curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 1L); 122 | curl_easy_setopt(handle, CURLOPT_HTTPGET, 1L); 123 | curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L); 124 | curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L); 125 | curl_easy_setopt(handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"); 126 | curl_easy_setopt(handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); 127 | curl_easy_setopt(handle, CURLOPT_USE_SSL, CURLUSESSL_ALL); 128 | 129 | #ifdef _DEBUG 130 | curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); 131 | #endif 132 | 133 | curl_easy_setopt(handle, CURLOPT_URL, url); 134 | 135 | curl_easy_setopt(handle, CURLOPT_WRITEDATA, &file); 136 | curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, SaveCore); 137 | 138 | ret = curl_easy_perform(handle); 139 | 140 | curl_easy_cleanup(handle); 141 | 142 | if(ret != CURLE_OK) 143 | { 144 | file.release(); 145 | LocalFile::RemoveFile(dest); 146 | } 147 | 148 | print("[Utils::DownloadFile] (%s -> %s) result > 0x%X\n", url, dest, ret); 149 | return ret; 150 | } 151 | 152 | void Utils::Decapitalise(wchar_t *wcstring) 153 | { 154 | //Convert to lowerCase 155 | for(int i = 0; wcstring[i] != '\0'; i++) 156 | wcstring[i] = sce_paf_towlower(wcstring[i]); 157 | } 158 | 159 | void Utils::StartBGDL() 160 | { 161 | SceInt32 res = SCE_OK; 162 | SceUID moduleID = SCE_UID_INVALID_UID; 163 | SceUID sceShellID = SCE_UID_INVALID_UID; 164 | 165 | res = sceAppMgrGetIdByName(&sceShellID, "NPXS19999"); 166 | if(res != SCE_OK) 167 | { 168 | print("Unable to get SceShell ID! 0x%X\n", res); 169 | return; 170 | } 171 | #ifdef _DEBUG 172 | if(LocalFile::Exists("ux0:data/bgdlid")) 173 | { 174 | SceUID id; 175 | 176 | common::SharedPtr openResult = LocalFile::Open("ux0:data/bgdlid", SCE_O_RDONLY, 0, NULL); 177 | openResult.get()->Read(&id, sizeof(SceUID)); 178 | print("Unloading....\n"); 179 | taiStopUnloadModuleForPid(sceShellID, id, 0, NULL, 0, NULL, NULL); 180 | print("Done!\n"); 181 | } 182 | #endif 183 | res = taiLoadStartModuleForPid(sceShellID, "ux0:app/BHBB00001/module/bhbb_dl.suprx", 0, NULL, 0); 184 | if(res < 0) 185 | { 186 | print("Unable to start BGDL! (Already Running?) 0x%X\n", res); 187 | return; 188 | } 189 | 190 | moduleID = res; 191 | 192 | print("BGDL started with ID 0x%X\n", moduleID); 193 | #ifdef _DEBUG 194 | common::SharedPtr openResult = LocalFile::Open("ux0:data/bgdlid", SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0666, NULL); 195 | openResult.get()->Write(&moduleID, sizeof(SceUID)); 196 | #endif 197 | } -------------------------------------------------------------------------------- /bhbb_dl/src/promote.c: -------------------------------------------------------------------------------- 1 | /* 2 | BetterHomebrewBrowser, A homebrew browser for the PlayStation Vita with background downloading support 3 | Copyright (C) 2024 Muhammad Ibrahim 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | // This file is based off of package_installer.c by TheFlow for VitaShell (https://github.com/TheOfficialFloW/VitaShell) 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | // #include "sha1.h" 29 | #include "head_bin.h" 30 | 31 | #define BSWAP32(x) (((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24)) 32 | 33 | #define ntohl BSWAP32 34 | 35 | #define SFO_MAGIC 0x46535000 36 | 37 | #define PSF_TYPE_BIN 0 38 | #define PSF_TYPE_STR 2 39 | #define PSF_TYPE_VAL 4 40 | 41 | extern int sceAppMgrQuitApp(SceUID); 42 | 43 | typedef struct SfoHeader { 44 | uint32_t magic; 45 | uint32_t version; 46 | uint32_t keyofs; 47 | uint32_t valofs; 48 | uint32_t count; 49 | } SfoHeader; 50 | 51 | typedef struct SfoEntry { 52 | uint16_t nameofs; 53 | uint8_t alignment; 54 | uint8_t type; 55 | uint32_t valsize; 56 | uint32_t totalsize; 57 | uint32_t dataofs; 58 | } SfoEntry; 59 | 60 | 61 | int getSfoString(char* buffer, char* name, char* string, int length) { 62 | SfoHeader* header = (SfoHeader*)buffer; 63 | SfoEntry* entries = (SfoEntry*)((uint32_t)buffer + sizeof(SfoHeader)); 64 | 65 | if (header->magic != SFO_MAGIC) 66 | return -1; 67 | 68 | int i; 69 | for (i = 0; i < header->count; i++) { 70 | if (sce_paf_strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) { 71 | sce_paf_memset(string, 0, length); 72 | sce_paf_strncpy(string, buffer + header->valofs + entries[i].dataofs, length); 73 | string[length - 1] = '\0'; 74 | return 0; 75 | } 76 | } 77 | 78 | return -2; 79 | } 80 | 81 | static void fpkg_hmac(const uint8_t* data, unsigned int len, uint8_t hmac[16]) { 82 | // SHA1_CTX ctx; 83 | SHA1Context ctx; 84 | uint8_t sha1[20]; 85 | uint8_t buf[64]; 86 | 87 | sce_paf_memset(sha1, 0, sizeof(sha1)); 88 | 89 | SHA1Reset(&ctx); 90 | SHA1Input(&ctx, data, len); 91 | SHA1Result(&ctx, sha1); 92 | 93 | // sha1_init(&ctx); 94 | // sha1_update(&ctx, data, len); 95 | // sha1_final(&ctx, sha1); 96 | 97 | sce_paf_memset(buf, 0, 64); 98 | sce_paf_memcpy(&buf[0], &sha1[4], 8); 99 | sce_paf_memcpy(&buf[8], &sha1[4], 8); 100 | sce_paf_memcpy(&buf[16], &sha1[12], 4); 101 | buf[20] = sha1[16]; 102 | buf[21] = sha1[1]; 103 | buf[22] = sha1[2]; 104 | buf[23] = sha1[3]; 105 | sce_paf_memcpy(&buf[24], &buf[16], 8); 106 | 107 | SHA1Reset(&ctx); 108 | SHA1Input(&ctx, buf, sizeof(buf)); 109 | SHA1Result(&ctx, sha1); 110 | 111 | // sha1_init(&ctx); 112 | // sha1_update(&ctx, buf, 64); 113 | // sha1_final(&ctx, sha1); 114 | 115 | sce_paf_memcpy(hmac, sha1, 16); 116 | } 117 | 118 | int makeHead(const char *path, char *out_titleID) { 119 | char tmp_path[1088]; 120 | uint8_t hmac[16]; 121 | uint32_t off; 122 | uint32_t len; 123 | uint32_t out; 124 | 125 | // Read param.sfo 126 | sce_paf_snprintf(tmp_path, sizeof(tmp_path), "%s/sce_sys/param.sfo", path); 127 | SceUID fd = sceIoOpen(tmp_path, SCE_O_RDONLY, 0); 128 | if (fd < 0) 129 | return fd; 130 | int size = sceIoLseek32(fd, 0, SCE_SEEK_END); 131 | sceIoLseek32(fd, 0, SCE_SEEK_SET); 132 | void *sfo_buffer = sce_paf_malloc(size); 133 | if (!sfo_buffer || sceIoRead(fd, sfo_buffer, size) < 0) { 134 | sce_paf_free(sfo_buffer); 135 | sceIoClose(fd); 136 | return -1; 137 | } 138 | sceIoClose(fd); 139 | // Get title id 140 | 141 | sce_paf_memset(out_titleID, 0, 12); 142 | getSfoString((char *)sfo_buffer, "TITLE_ID", out_titleID, 12); 143 | 144 | // Get content id 145 | char contentid[48]; 146 | sce_paf_memset(contentid, 0, sizeof(contentid)); 147 | getSfoString((char *)sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid)); 148 | 149 | // Free sfo buffer 150 | sce_paf_free(sfo_buffer); 151 | 152 | // Allocate head.bin buffer 153 | uint8_t* head_bin = (uint8_t*)sce_paf_malloc(tpl_head_bin_len); 154 | sce_paf_memcpy(head_bin, tpl_head_bin, tpl_head_bin_len); 155 | 156 | // Write full title id 157 | char full_title_id[48]; 158 | sce_paf_snprintf(full_title_id, sizeof(full_title_id), "EP9000-%s_00-0000000000000000", out_titleID); 159 | sce_paf_strncpy((char*)&head_bin[0x30], sce_paf_strlen(contentid) > 0 ? contentid : full_title_id, 48); 160 | 161 | // hmac of pkg header 162 | len = ntohl(*(uint32_t*)&head_bin[0xD0]); 163 | fpkg_hmac(&head_bin[0], len, hmac); 164 | sce_paf_memcpy(&head_bin[len], hmac, 16); 165 | 166 | // hmac of pkg info 167 | off = ntohl(*(uint32_t*)&head_bin[0x8]); 168 | len = ntohl(*(uint32_t*)&head_bin[0x10]); 169 | out = ntohl(*(uint32_t*)&head_bin[0xD4]); 170 | fpkg_hmac(&head_bin[off], len - 64, hmac); 171 | sce_paf_memcpy(&head_bin[out], hmac, 16); 172 | 173 | // hmac of everything 174 | len = ntohl(*(uint32_t*)&head_bin[0xE8]); 175 | fpkg_hmac(&head_bin[0], len, hmac); 176 | sce_paf_memcpy(&head_bin[len], hmac, 16); 177 | 178 | // Make dir 179 | sce_paf_snprintf(tmp_path, sizeof(tmp_path), "%s/sce_sys/package", path); 180 | sceIoMkdir(tmp_path, 0666); 181 | 182 | // Write head.bin 183 | sce_paf_snprintf(tmp_path, sizeof(tmp_path), "%s/sce_sys/package/head.bin", path); 184 | fd = sceIoOpen(tmp_path, SCE_O_WRONLY | SCE_O_TRUNC | SCE_O_CREAT, 0666); 185 | if (fd < 0) { 186 | sce_paf_free(head_bin); 187 | return fd; 188 | } 189 | int res = sceIoWrite(fd, head_bin, tpl_head_bin_len); 190 | sceIoClose(fd); 191 | 192 | sce_paf_free(head_bin); 193 | 194 | return res; 195 | } 196 | 197 | int promoteApp(const char* path, char *out_titleID) { 198 | int res = makeHead(path, out_titleID); 199 | if (res < 0) 200 | return res; 201 | 202 | SceAppMgrAppStatus status; 203 | if(sceAppMgrGetStatusByName(out_titleID, &status) >= 0) 204 | sceAppMgrQuitApp(status.appId); 205 | 206 | sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_PROMOTER_UTIL); 207 | 208 | res = scePromoterUtilityInit(); 209 | if (res < 0) 210 | return res; 211 | 212 | res = scePromoterUtilityPromotePkgWithRif(path, 1); 213 | if(res < 0) 214 | return res; 215 | res = scePromoterUtilityExit(); 216 | if (res < 0) 217 | return res; 218 | 219 | sceSysmoduleUnloadModuleInternal(SCE_SYSMODULE_INTERNAL_PROMOTER_UTIL); 220 | 221 | return 0; 222 | } --------------------------------------------------------------------------------