dspatch.py/DownloadStation/DemoMenu.py
2025-04-27 19:12:29 -07:00

133 lines
3.6 KiB
Python

from collections.abc import MutableSequence
u32_le = lambda i: i.to_bytes(length=4, byteorder='little')
class Rating:
EC = 0
E = 1
E10 = 2
T = 3
M = 4
AO = 5
RP = 6
class GuideMode:
N = 0x11 # nothing
B = 0x13 # buttons only
T = 0x15 # touch only
BT = 0x17 # buttons + touch
class Button:
START = 0
SELECT = 1
A = 2
B = 3
X = 4
Y = 5
L = 6
R = 7
DPAD = 8
class DemoMenu(MutableSequence):
def __init__(self):
self.entries: list[DemoMenu.DemoMenuEntry] = []
def encode(self) -> bytes:
return b''.join([
u32_le(len(self.entries)),
b''.join(entry.encode() for entry in self.entries),
u32_le(0)
])
__bytes__ = encode
def __getitem__(self, index):
return self.entries[index]
def __setitem__(self, index, value):
self.entries[index] = value
def __delitem__(self, index):
del self.entries[index]
def __len__(self):
return len(self.entries)
def insert(self, index, value):
self.entries.insert(index, value)
class DemoMenuEntry:
def __init__(self, data: bytes|None = None):
if data is None:
self.banner_image = bytes(0x200)
self.banner_palette = bytes(0x20)
self.banner_text = [''] * 2
self.rating = Rating.E
self.guide_mode = GuideMode.N
self.buttons_text = [''] * 9
self.unknown_text = [''] * 3
self.touch_text = [''] * 2
self.padding = bytes(0x40)
self.internal_name = ''
return
self.banner_image = data[:0x200]
self.banner_palette = data[0x200:0x220]
self.banner_text = [
data[i:i+0x80].decode('latin-1').rstrip('\0')
for i in range(0x220, 0x320, 0x80)
]
self.rating = data[0x320]
self.guide_mode = data[0x321]
self.buttons_text = [
data[i:i+0x20].decode('latin-1').rstrip('\0')
for i in range(0x322, 0x442, 0x20)
]
self.unknown_text = [
data[i:i+0x20].decode('latin-1').rstrip('\0')
for i in range(0x442, 0x4a2, 0x20)
]
self.touch_text = [
data[i:i+0x20].decode('latin-1').rstrip('\0')
for i in range(0x4a2, 0x4e2, 0x20)
]
self.padding = data[0x4e2:0x522]
self.internal_name = data[0x522:0x52c].decode('latin-1').rstrip('\0')
def encode(self) -> bytes:
return b''.join([
self.banner_image,
self.banner_palette,
b''.join(
text.ljust(0x80, '\0').encode('latin-1')
for text in self.banner_text
), self.rating.to_bytes(1),
self.guide_mode.to_bytes(1),
b''.join(
text.ljust(0x20, '\0').encode('latin-1')
for text in self.buttons_text
), b''.join(
text.ljust(0x20, '\0').encode('latin-1')
for text in self.unknown_text
), b''.join(
text.ljust(0x20, '\0').encode('latin-1')
for text in self.touch_text
), self.padding,
self.internal_name.ljust(0xa, '\0').encode('latin-1')
])
__bytes__ = encode
def __len__(self):
return 0x52c