mirror of
https://github.com/MoHadiShibli/Control4Free.git
synced 2026-10-06 13:00:27 +02:00
Package: list the app under Applications, not Games
The package declared itself a game (CATEGORY gd), so the PS4 filed it under
Games in the library.
It now uses the values Apollo Save Tool ships with: CATEGORY gde ("Non-Game Mini
App"), ATTRIBUTE 32, APP_TYPE 1. Apollo is built with the same OpenOrbis tools and
lists under Applications. APP_TYPE 4 ("Freemium"), which is reported to move apps
there too, made the PS4 refuse to start ours (CE-39929-2), so it stays 1.
Confirmed on the console (firmware 10.01): the app installs, starts, and lists
under Library > Applications. A test reads the fields back out of the built
package.
This commit is contained in:
1 parent
ffe5615da3
commit
a039ce9532
2 files changed
+29
-1
No files matched your search
@@ -4,6 +4,7 @@ import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import socket
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
@@ -195,6 +196,28 @@ def main():
|
||||
assert not found, 'OpenOrbis Linux-valued constant used directly:\n' + '\n'.join(found)
|
||||
print('PASS no OpenOrbis constant with a Linux value is used directly', flush=True)
|
||||
|
||||
# The package's param.sfo, as the PS4 reads it (built by `make -C launcher`).
|
||||
sfo = ROOT / 'build/launcher/pkg/sce_sys/param.sfo'
|
||||
if not sfo.exists():
|
||||
print('SKIP param.sfo checks: build the package first (make -C launcher)', flush=True)
|
||||
return
|
||||
data = sfo.read_bytes()
|
||||
magic, _, keys, values, count = struct.unpack_from('<4sIIII', data)
|
||||
assert magic == b'\0PSF', magic
|
||||
fields = {}
|
||||
for i in range(count):
|
||||
key_at, kind, length, _, value_at = struct.unpack_from('<HHIII', data, 20 + 16 * i)
|
||||
name = data[keys + key_at:data.index(b'\0', keys + key_at)].decode()
|
||||
raw = data[values + value_at:values + value_at + length]
|
||||
fields[name] = struct.unpack('<I', raw)[0] if kind == 0x0404 else raw.rstrip(b'\0').decode()
|
||||
version = (ROOT / 'VERSION').read_text().strip()
|
||||
major, minor = version.split('.')[:2]
|
||||
# Listed under Applications rather than Games, as Apollo Save Tool is.
|
||||
assert (fields['CATEGORY'], fields['APP_TYPE'], fields['ATTRIBUTE']) == ('gde', 1, 32), fields
|
||||
assert fields['TITLE_ID'] == 'CFRE00001' and fields['TITLE'] == 'Control4Free', fields
|
||||
assert fields['APP_VER'] == fields['VERSION'] == f'{int(major):02d}.{int(minor):02d}', fields
|
||||
print('PASS param.sfo: an application, its title, and the version from VERSION', flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -127,9 +127,14 @@ def main():
|
||||
pkgtool = binary / 'PkgTool.Core'
|
||||
sfo = 'sce_sys/param.sfo'
|
||||
run(pkgtool, 'sfo_new', sfo)
|
||||
# Listed under Applications, not Games: the values Apollo Save Tool ships with
|
||||
# (bucanero/apollo-ps4, built with the same OpenOrbis tools), which lists there
|
||||
# and starts fine. CATEGORY gde is "Non-Game Mini App"; gd, which we had, is
|
||||
# "Game Digital Application". APP_TYPE must stay 1: with 4 ("Freemium") the PS4
|
||||
# refused to start the app (CE-39929-2, firmware 10.01, 2026-10-05).
|
||||
entries = {
|
||||
'APP_TYPE': ('Integer', 4, '1'), 'APP_VER': ('Utf8', 8, SFO_VERSION),
|
||||
'ATTRIBUTE': ('Integer', 4, '0'), 'CATEGORY': ('Utf8', 4, 'gd'),
|
||||
'ATTRIBUTE': ('Integer', 4, '32'), 'CATEGORY': ('Utf8', 4, 'gde'),
|
||||
'CONTENT_ID': ('Utf8', 48, CONTENT_ID), 'DOWNLOAD_DATA_SIZE': ('Integer', 4, '0'),
|
||||
'SYSTEM_VER': ('Integer', 4, '0'), 'TITLE': ('Utf8', 128, 'Control4Free'),
|
||||
'TITLE_ID': ('Utf8', 12, TITLE_ID), 'VERSION': ('Utf8', 8, SFO_VERSION),
|
||||
|
||||
Reference in new issue
Block a user