├── 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 |
13 |
14 |
15 |
16 |
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 | }
--------------------------------------------------------------------------------