From e5105714c12b11daa4f3d1d5729d14aaff0cbf87 Mon Sep 17 00:00:00 2001 From: bps Date: Mon, 26 Oct 2026 23:10:42 -0300 Subject: [PATCH 1/2] Fetch blackbearreloaded dependencies from copies The account left GitHub. ps5-homebrew-ui and ProsperoStore come from forks at the same pinned commits, and the ps5-opengl archive from a copy checked by its sha256. Co-Authored-By: Claude Opus 5.5 --- ps5-react/dependencies.lock.json | 4 ++-- ps5-react/tools/build_ps5.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ps5-react/dependencies.lock.json b/ps5-react/dependencies.lock.json index 06fd4bd..c5191a9 100644 --- a/ps5-react/dependencies.lock.json +++ b/ps5-react/dependencies.lock.json @@ -45,7 +45,7 @@ ] }, "platform": { - "url": "https://github.com/blackbearreloaded/ps5-homebrew-ui.git", + "url": "https://github.com/Phononenom/ps5-homebrew-ui.git", "revision": "4bd942579dd981b3df9c740438489ca6a614ddc0", "patches": [ "patches/platform-heap-size.patch", @@ -85,7 +85,7 @@ "sha256": "ce2669c51272b70bc0aafe9a4e6223e5c7720edaebb40201db191634aa503f5e" }, "filesystemHelperClient": { - "url": "https://github.com/blackbearreloaded/ProsperoStore.git", + "url": "https://github.com/JVK3R/ProsperoStore.git", "revision": "335d8c43f916020205f445b76b66106ee50d2eeb" }, "filesystemHelper": { diff --git a/ps5-react/tools/build_ps5.py b/ps5-react/tools/build_ps5.py index eaa970d..8e798ca 100644 --- a/ps5-react/tools/build_ps5.py +++ b/ps5-react/tools/build_ps5.py @@ -65,7 +65,8 @@ def main(): PS5_CLANG=str(llvm / "clang"), PS5_PAYLOAD_SDK=str(sdk), USE_CCACHE="0") archive = args.opengl_archive or DEPS / "ps5-opengl-sdk-1.0.0.tar.gz" - fetch("https://github.com/blackbearreloaded/ps5-opengl/releases/download/v1.0.0/ps5-opengl-sdk-1.0.0.tar.gz", + # A copy of the upstream release (blackbearreloaded left GitHub); GL_HASH checks it is the same file. + fetch("https://github.com/MyLuxy/overdrive-deps/releases/download/ps5-opengl-v1.0.0/ps5-opengl-sdk-1.0.0.tar.gz", archive, GL_HASH) gl = DEPS / "ps5-opengl-sdk-1.0.0/sdk" if not gl.exists(): From e8a5c304003cde2cd4181d1bf04b61785728612d Mon Sep 17 00:00:00 2001 From: bps Date: Mon, 26 Oct 2026 23:10:42 -0300 Subject: [PATCH 2/2] Version 1.4.2: one place on the home screen stays unpinned With every place pinned, the last game opened (the jailbreak's entry) had no place on the home screen and ended up in the game library (#4). Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 7 ++++++ app/api.js | 2 +- app/app.json | 2 +- app/i18n.js | 10 ++++++++ app/index.jsx | 49 ++++++++++++++++++++++++++++----------- app/payloads/lineupd.c | 23 +++++++++++++++++- docs/ARCHITECTURE.md | 7 +++++- docs/pt-BR/ARQUITETURA.md | 7 +++++- docs/pt-BR/NOVIDADES.md | 7 ++++++ 9 files changed, 95 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16fa7a7..78a749b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 1.4.2 + +- One place on the home screen always stays unpinned. With every place pinned, the last game opened (the + jailbreak's entry, say) had nowhere to go and ended up in the game library. Pin the whole row now leaves the + first place free, and Lineup will not save a home screen pinned in full. +- A row pinned in full by an older version opens with an offer to free its first place. + ## 1.4.1 1.4.0 was not released; its changes ship here. diff --git a/app/api.js b/app/api.js index 78ed7f6..c1566e6 100644 --- a/app/api.js +++ b/app/api.js @@ -3,7 +3,7 @@ import {Archives, Downloads, FileSystem, Http, Payloads} from '@ps5-react/core'; import {T} from './i18n.js'; -export const VERSION = '1.4.1'; +export const VERSION = '1.4.2'; const BASE = 'http://127.0.0.1:9077'; /** An error the app shows as is: a short title and what to do about it. */ diff --git a/app/app.json b/app/app.json index 5ecf898..01c36cd 100644 --- a/app/app.json +++ b/app/app.json @@ -3,7 +3,7 @@ "titleId": "PPSA99077", "contentId": "UP9000-PPSA99077_00-LINEUP0000000000", "name": "Lineup", - "version": "01.004.001", + "version": "01.004.002", "render": { "width": 1920, "height": 1080 diff --git a/app/i18n.js b/app/i18n.js index e601f07..0645b1c 100644 --- a/app/i18n.js +++ b/app/i18n.js @@ -53,6 +53,11 @@ const en = { missingBody: 'The home screen database was rebuilt or updated, so the games no longer hold their places. ' + 'Pin them again?', reapply: 'Pin again', later: 'Not now', + keepFree: 'Leave one place on the home screen unpinned, for the last game opened.', + fullTitle: 'Every place on the home screen is pinned', + fullBody: 'The last game opened has no place left there and ends up in the game library. ' + + 'Free the first place for it?', + freeFirst: 'Free the first place', }, saved: ['Order saved', 'Closing the app. The home screen comes back with the new order.'], closeNow: 'Close now', @@ -158,6 +163,11 @@ const pt = { missingBody: 'O banco de dados da tela inicial foi reconstruído ou atualizado, e os jogos não seguram mais o ' + 'lugar. Fixar de novo?', reapply: 'Fixar de novo', later: 'Agora não', + keepFree: 'Deixe um lugar da tela inicial sem fixar, para o último jogo aberto.', + fullTitle: 'Todos os lugares da tela inicial estão fixos', + fullBody: 'O último jogo aberto fica sem lugar ali e vai parar na biblioteca de jogos. ' + + 'Liberar o primeiro lugar para ele?', + freeFirst: 'Liberar o primeiro lugar', }, saved: ['Ordem salva', 'Fechando o app. A tela inicial já volta com a nova ordem.'], closeNow: 'Fechar agora', diff --git a/app/index.jsx b/app/index.jsx index 0b5a93a..4f6fb30 100644 --- a/app/index.jsx +++ b/app/index.jsx @@ -39,6 +39,14 @@ const sortKey = name => name.normalize('NFD').replace(/[̀-ͯ]/g, '').toLowerCas // Games moved or pinned/unpinned since the row was read. `pinned` maps the games read pinned to their slots. const changed = s => s.order.reduce((count, id, i) => count + (s.home[id] !== i || !s.pins[id] !== !(id in s.pinned)), 0); const allPinned = pinned => Object.fromEntries(Object.keys(pinned).map(id => [id, true])); +// Every home place pinned: the last game opened (the jailbreak's entry, say) would have no place there and end up in +// the game library, so one stays free. lineupd refuses such a save too. +const homeFull = (order, pins) => order.slice(0, HOME_LIMIT).every(id => pins[id]); +const without = (pins, id) => { + const rest = {...pins}; + delete rest[id]; + return rest; +}; // The order the pins ask for, as lineupd's triggers work it out: pinned games at their slots (packed at the end of // a row that got shorter), the others in their order in the free places. @@ -295,10 +303,11 @@ function App() { if (game.pinned !== null && game.pinned !== undefined) pinned[game.titleId] = game.pinned; }); const base = list.map(game => game.titleId); - const missing = pins === 'missing'; + // A row pinned in full by 1.4.1 or older. + const layer = pins === 'missing' ? 'pinsMissing' : pins === 'on' && homeFull(base, allPinned(pinned)) ? 'pinsFull' : null; light(false); patch({phase: 'row', profiles, user, games, home, base, order: base, pins: allPinned(pinned), pinned, focus: 0, - dir: 1, lifted: false, layer: missing ? 'pinsMissing' : null, target: null, pending: missing ? null : {index: 0}}); + dir: 1, lifted: false, layer, target: null, pending: layer ? null : {index: 0}}); }; const boot = async () => { @@ -418,6 +427,11 @@ function App() { toast(T.alreadySaved); return; } + if (homeFull(now.order, now.pins)) { + close(); + toast(T.pins.keepFree); + return; + } light(false); patch({lifted: false, layer: 'busy'}); const result = await api.save(now.user, now.order, now.games, now.pins); @@ -480,13 +494,11 @@ function App() { return true; } if (action === 'square') { - patch(p => { - const id = p.order[p.focus]; - const pins = {...p.pins}; - if (pins[id]) delete pins[id]; - else pins[id] = true; - return {pins}; - }); + const p = ref.current; + const id = p.order[p.focus]; + const pins = p.pins[id] ? without(p.pins, id) : {...p.pins, [id]: true}; + if (!p.pins[id] && homeFull(p.order, pins)) toast(T.pins.keepFree); + else patch({pins}); return true; } return false; @@ -496,14 +508,17 @@ function App() { patch(p => ({order: p.base, pins: allPinned(p.pinned), layer: null, pending: {index: 0}})); toast(T.discarded); }; - const pinAll = on => patch(p => ({pins: on ? Object.fromEntries(p.order.map(id => [id, true])) : {}, layer: null, - pending: {index: p.focus}})); - // Puts the games back at their slots and saves, which creates the triggers again. + // The whole row but its first place, which stays free. + const pinAll = on => patch(p => ({pins: on ? Object.fromEntries(p.order.slice(1).map(id => [id, true])) : {}, + layer: null, pending: {index: p.focus}})); + // Puts the games back at their slots and saves, which creates the triggers again. A row pinned in full gets its + // first place freed. const reapply = () => { const now = ref.current; const order = pinnedOrder(now.order, now.pinned); - patch({order}); - save(null, {...now, order}, true); + const pins = homeFull(order, now.pins) ? without(now.pins, order[0]) : now.pins; + patch({order, pins}); + save(null, {...now, order, pins}, true); }; const unpinEverywhere = async () => { patch({layer: 'busy'}); @@ -664,6 +679,12 @@ function App() {