Skip to content

Commit

Permalink
Add Qoob Pro updater
Browse files Browse the repository at this point in the history
  • Loading branch information
9ary committed Dec 6, 2023
1 parent b7d9bfa commit 2ea1b4a
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 29 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ ipl.rom

/subprojects/libogc2

!res/qoob_pro_none_upgrade.elf
!res/qoob_sx_13c_upgrade.elf
29 changes: 21 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,30 @@ using the supplied `iplboot_pico.uf2` (depends on [PicoBoot PR 107][pb-pr-107]).
[pb-install]: https://github.com/webhdx/PicoBoot/wiki/Installation-guide
[pb-pr-107]: https://github.com/webhdx/PicoBoot/pull/107

### Qoob Pro
### Qoob

Qoob Pro only: use the Qoob USB flash utility to install `iplboot_qoob_pro.gcb`
as a BIOS like you normally would.

Flash `iplboot_qoob_pro.gcb` as a BIOS like you normally would.
A modified copy of the updater is also provided for both versions of the Qoob.
It can be run via Swiss, or the original Qoob BIOS, from an ISO9660 DVD or over
the nework using a Broadband Adapter[^qoob-bba].

### Qoob SX
The updater files are `qoob_pro_iplboot_upgrade.elf` and
`qoob_sx_iplboot_upgrade.elf` respectively.
When burning them to a disc, you may need to pad the image with a large (~1GiB)
file, to ensure the drive can read it properly.

- Burn `qoob_sx_iplboot_upgrade.elf` to an ISO9660 DVD.
- Hold D-Pad left while turning the GameCube on to boot into the "backup" BIOS.
- Start the updater from there.
The recommended method however is to burn Swiss to a DVD, and run the updater
from an SD card.

This appears to be the only way to flash a Qoob SX,
otherwise write protection is enabled.
On Qoob SX, you will need to hold D-Pad left while turning the system on to boot
into the "backup" BIOS, otherwise write protection will be enabled.
This means that a DVD drive or a BBA is required to flash anyting to a Qoob SX.
If this is inconvenient, consider upgrading to PicoBoot.

[^qoob-bba]: See the Qoob documentation for more information.

### ViperGC

Flash `iplboot_viper.vgc` as a BIOS like you normally would.
Expand All @@ -101,6 +111,8 @@ iplboot displays useful diagnostic messages as it attempts to load the selected

When choosing a shortcut button, beware that some software checks for buttons held at boot to alter certain behaviors. If your software behaves differently when booted through iplboot, ensure the assigned shortcut button is not used in this way. For example, it is not recommended to assign Swiss to the B button as holding B causes Swiss to disable the DVD drive.

Also on Qoob SX, the "backup" BIOS will run before iplboot, so it may interfere
with some shortcuts.

## Compiling

Expand Down Expand Up @@ -144,6 +156,7 @@ iplboot_memcard.gci
iplboot_pico.uf2
iplboot_qoob_pro.gcb
iplboot_viper.vgc
qoob_pro_iplboot_upgrade.elf
qoob_sx_iplboot_upgrade.elf
...
```
Expand Down
22 changes: 3 additions & 19 deletions buildtools/dol2ipl.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def pack_uf2(data, base_address):

def main():
if len(sys.argv) not in range(3, 4 + 1):
print(f"Usage: {sys.argv[0]} <output> <executable> [<IPL ROM>|<SX updater>]")
print(f"Usage: {sys.argv[0]} <output> <executable> [<IPL ROM>]")
return 1

output = sys.argv[1]
Expand Down Expand Up @@ -200,33 +200,17 @@ def main():

out = pack_uf2(header + img, 0x10080000)

elif output.startswith("qoob_sx_"):
if len(sys.argv) < 4:
print("Missing required updater!")
return 1

updater = sys.argv[3]
with open(updater, "rb") as f:
out = bytearray(f.read())

elif output.endswith(".qbsx"):
# SX BIOSes are always one page long
qoob_header[0xFD] = 1

img = qoob_header + scramble(exe, qoobsx=True)

if len(img) > 62800:
print("Warning: SX BIOS image too big to fit in flasher")
return -1
if len(img) > 1 << 16:
print("SX BIOS image too big")
return -1

msg = b"QOOB SX iplboot install\0"
msg_offset = 7240
img_offset = 7404

out[msg_offset:msg_offset + len(msg)] = msg
out[img_offset:img_offset + len(img)] = img
out = img

else:
print("Unknown output format")
Expand Down
1 change: 1 addition & 0 deletions buildtools/meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
python = find_program('python3')
dol2ipl = [python, files('dol2ipl.py')]
qoob_injector = [python, files('qoob_injector.py')]
psf2c = [python, files('psf2c.py')]

dol2gci = executable(
Expand Down
37 changes: 37 additions & 0 deletions buildtools/qoob_injector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env python3

# Trivial script to inject a BIOS image into a Qoob updater

import sys

bios = sys.argv[1]
updater = sys.argv[2]
outfile = sys.argv[3]

with open(bios, "rb") as f:
img = f.read()

with open(updater, "rb") as f:
out = bytearray(f.read())

if bios.endswith(".gcb"):
if len(img) > 128 * 1024:
raise "Qoob Pro BIOS image too big to fit in flasher"

msg = b"QOOB Pro iplboot install\0"
msg_offset = 0x1A68
img_offset = 0x1AE0

if bios.endswith(".qbsx"):
if len(img) > 62800:
raise "Qoob SX BIOS image too big to fit in flasher"

msg = b"QOOB SX iplboot install\0"
msg_offset = 7240
img_offset = 7404

out[msg_offset:msg_offset + len(msg)] = msg
out[img_offset:img_offset + len(img)] = img

with open(outfile, "wb") as f:
f.write(out)
17 changes: 15 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ if full_rom_opt.allowed()
command: [dol2ipl, '@OUTPUT@', '@INPUT@'],
build_by_default: true,
)
qoob_pro_updater_tgt = custom_target(
'qoob_pro_updater',
input: [qoob_pro, qoob_pro_updater],
output: 'qoob_pro_iplboot_upgrade.elf',
command: [qoob_injector, '@INPUT@', '@OUTPUT@'],
build_by_default: true,
)
endif

iplboot_sx_stripped = custom_target(
Expand All @@ -118,9 +125,15 @@ iplboot_sx_stripped = custom_target(
)
qoob_sx = custom_target(
'qoob_sx',
input: [iplboot_sx_stripped, qoob_sx_updater],
output: 'qoob_sx_iplboot_upgrade.elf',
input: iplboot_sx_stripped,
output: 'iplboot_qoob_sx.qbsx',
command: [dol2ipl, '@OUTPUT@', '@INPUT@'],
)
qoob_sx_updater_tgt = custom_target(
'qoob_sx_updater',
input: [qoob_sx, qoob_sx_updater],
output: 'qoob_sx_iplboot_upgrade.elf',
command: [qoob_injector, '@INPUT@', '@OUTPUT@'],
build_by_default: true,
)

Expand Down
1 change: 1 addition & 0 deletions res/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ summary(
bool_yn: true,
)

qoob_pro_updater = files('qoob_pro_none_upgrade.elf')
qoob_sx_updater = files('qoob_sx_13c_upgrade.elf')

terminus = files('terminus-0.49.1-116b-ll2-td1.psf')
Binary file added res/qoob_pro_none_upgrade.elf
Binary file not shown.

0 comments on commit 2ea1b4a

Please sign in to comment.