Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/publish-test-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ jobs:
- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository_url: https://test.pypi.org/legacy/
repository-url: https://test.pypi.org/legacy/
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 andshrew
Copyright (c) 2023, 2025 andshrew

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
64 changes: 60 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pip install ps4-updates
```

## Typical Usage
Create a `Ps4TitleUpdate` object by specifying a PS4 Title Id (eg. `CUSA00001_00` or `CUSA00001`).
Create a `Ps4TitleUpdate` object by specifying a PS4 Title Id (eg. `CUSA00001_00` or `CUSA00001`). A list of known Title Ids is [available here](https://andshrew.github.io/PlayStation-Titles/?platform=ps4&hasContentId).

Invoke `get_update()` on the object to begin retrieving information about the update. If an update is available it will try to retrieve the following:

Expand All @@ -19,11 +19,12 @@ Invoke `get_update()` on the object to begin retrieving information about the up
* Download Size
* Update Creation Date
* changeinfo.xml (developer included update notes)
* param.sfo update pkg parameters

## Limitations
Only information about the current update version can be retrieved.

It is not a guarantee that changeinfo.xml will be included within the updates pkg file. The file is typically located at the start of the file, however it does not appear to be in a fixed location. This package attempts to locate it by downloading up to the first 30MB of the pkg file. You can increase (or decrease) this search range by setting `byte_limit` when creating a `Ps4TitleUpdate` object.
It is not a guarantee that `changeinfo.xml` will be included within the updates pkg file. This package attempts to locate it (and `param.sfo`) by parsing the update PKG file header. By default it will download up to the first 50MB of the PKG file, but if either the `changeinfo.xml` or `param.sfo` are located beyond this range then neither will be downloaded and no more data will be downloaded beyond the range of the PKG header. You can increase (or decrease) this limit by setting the `byte_limit` when creating a `Ps4TitleUpdate` object.

## Usage Examples

Expand All @@ -49,7 +50,6 @@ title.print_update_info()

#### Console Output
```
vscode ➜ /workspaces/PS4-Updates-Python (main) $ python app.py
Title Id: CUSA00001
Update Url: http://gs-sec.ww.np.dl.playstation.net/plo/np/CUSA00001/1123f23c1f00810a5e43fcb409ada7823bc5ad21b357817e314b6c4832cf6f9f/CUSA00001-ver.xml
Title Name: THE PLAYROOM
Expand Down Expand Up @@ -122,12 +122,68 @@ You can manually invoke `_get_partial_pkg_file()`, which makes the following ava
| update_pkg_exists | `True` if some data was found in pkg file at `update_pkg_url` |
| update_pkg_cdate | Update creation date as string YYYYMMDD |
| update_pkg_cdate_as_date | Update creation date as datetime |
| update_pkg_param_sfo | An `SFO` object if the pkg param.sfo file was found and parsed |
| update_pkg_bytes_exceeded | `True` if the pkg file header was parsed but data exists beyond the range of the specified `bytes_limit` |
| changeinfo_exists | `True` if changeinfo.xml was found |
| changeinfo | List of dicts for each change in changeinfo.xml |
| changeinfo_count | Number of changes in changeinfo.xml |
| changeinfo_current_exists | `True` if a change matching the current version number was in changeinfo.xml |
| changeinfo_current | List of dicts for change matching the current version |
| changeinfo_xml | Full XML for changeinfo.xml

## `SFO` and `SFO_Entry` Object Reference
By default, if an update exists then `get_update()` will download and attempt to parse the beginning of the updates pkg file. If the [`param.sfo`](https://www.psdevwiki.com/ps4/Param.sfo) file is located then the entries that it contains will be parsed into `SFO_Entry` objects and attached to a single `SFO` object that is then accessible from the `update_pkg_param_sfo` attribute of a `Ps4TitleUpdate` object.

For details of the information that might be in these objects, see the [Parameter Descriptions on psdevwiki.com](https://www.psdevwiki.com/ps4/Param.sfo#Parameters_Descriptions).

The entries data (as bytes) is saved in the `SFO_Entry` objects `data_bytes` attribute. Your application will need to further parse this information into a usable format.

### Example for parsing the SAVE_DATA_TRANSFER_TITLE_ID_LIST parameter
There will be an entry in the param.sfo file named `SAVE_DATA_TRANSFER_TITLE_ID_LIST` if the title supports reading another titles save data files (ie. for save transfer between games).

This example will print a titles update information to the screen, and then additionally print information from this specific SFO entry (if it exists).

```python
from ps4_updates import title as ps4up

title = ps4up.Ps4TitleUpdate('CUSA00897')
title.get_update()
title.print_update_info()

if title.update_pkg_exists is True:
entry = next((x for x in title.update_pkg_param_sfo.entries if x.name == "SAVE_DATA_TRANSFER_TITLE_ID_LIST"), None)
if entry is not None:
entry = entry.data_bytes.decode().strip('\x00').split('\n')
if len(entry) == 1:
print(f'This title shares save data with {len(entry)} title:')
if len(entry) > 1:
print(f'This title shares save data with {len(entry)} titles:')
if len(entry) > 0:
entry = sorted(entry, key=lambda x: x)
for i in entry:
print(f'\t{i}')
```
#### Console Output
```
Title Id: CUSA00897
Update Url: http://gs-sec.ww.np.dl.playstation.net/plo/np/CUSA00897/7d49cb7e0fd38b63970664874c3f4149fd86446456cc020a6555afaa79a10239/CUSA00897-ver.xml
Title Name: inFAMOUS™ First Light
Content Id: EP9000-CUSA00897_00-FIRSTLIGHTSHIP00
Current Version: 01.04
Download Size: 2.38 GB
Creation Date: Fri, 18-Nov-2016

01.04
- Graphics Bug Fixes

This title shares save data with 5 titles:
CUSA00004
CUSA00223
CUSA00263
CUSA00305
CUSA00309
```

## Additional Thanks
[Zer0xFF](https://gist.github.com/Zer0xFF/d94818f15e3e85b0b4d48000a4be1c73) - sharing the method for generating a title update URL
[Zer0xFF](https://gist.github.com/Zer0xFF/d94818f15e3e85b0b4d48000a4be1c73) - sharing the method for generating a title update URL
[psdevwiki](https://www.psdevwiki.com/ps4) - documentation on [PKG file format](https://www.psdevwiki.com/ps4/PKG_files) and [param.sfo files](https://www.psdevwiki.com/ps4/Param.sfo)
Loading