From 164f3fc620e90fe8855038700c024ad8d3fede9c Mon Sep 17 00:00:00 2001 From: Xpl0itU <24777100+Xpl0itU@users.noreply.github.com> Date: Mon, 15 Apr 2024 16:40:44 +0200 Subject: [PATCH] Inital support for Wii TMD parsing --- tmd.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 17 deletions(-) diff --git a/tmd.go b/tmd.go index b038383..dfa2942 100644 --- a/tmd.go +++ b/tmd.go @@ -3,10 +3,17 @@ package wiiudownloader import ( "bytes" "encoding/binary" + "fmt" "io" ) +const ( + TMD_VERSION_WII = 0x00 + TMD_VERSION_WIIU = 0x01 +) + type TMD struct { + Version byte TitleVersion uint16 ContentCount uint16 Contents []Content @@ -16,35 +23,76 @@ func parseTMD(data []byte) (*TMD, error) { tmd := &TMD{} reader := bytes.NewReader(data) - reader.Seek(476, io.SeekStart) - - if err := binary.Read(reader, binary.BigEndian, &tmd.TitleVersion); err != nil { + reader.Seek(0x180, io.SeekStart) + if err := binary.Read(reader, binary.BigEndian, &tmd.Version); err != nil { return nil, err } - if err := binary.Read(reader, binary.BigEndian, &tmd.ContentCount); err != nil { - return nil, err - } + switch tmd.Version { + case TMD_VERSION_WII: + reader.Seek(0x1DC, io.SeekStart) - tmd.Contents = make([]Content, tmd.ContentCount) - - for i := 0; i < int(tmd.ContentCount); i++ { - offset := 0xB04 + (0x30 * i) - - reader.Seek(int64(offset), io.SeekStart) - if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].ID); err != nil { + if err := binary.Read(reader, binary.BigEndian, &tmd.TitleVersion); err != nil { return nil, err } - reader.Seek(2, io.SeekCurrent) - - if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].Type); err != nil { + if err := binary.Read(reader, binary.BigEndian, &tmd.ContentCount); err != nil { return nil, err } - if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].Size); err != nil { + tmd.Contents = make([]Content, tmd.ContentCount) + + for i := 0; i < int(tmd.ContentCount); i++ { + offset := 0x1E4 + (0x24 * i) + + reader.Seek(int64(offset), io.SeekStart) + if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].ID); err != nil { + return nil, err + } + + reader.Seek(2, io.SeekCurrent) + + if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].Type); err != nil { + return nil, err + } + + if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].Size); err != nil { + return nil, err + } + } + case TMD_VERSION_WIIU: + reader.Seek(0x1DC, io.SeekStart) + + if err := binary.Read(reader, binary.BigEndian, &tmd.TitleVersion); err != nil { return nil, err } + + if err := binary.Read(reader, binary.BigEndian, &tmd.ContentCount); err != nil { + return nil, err + } + + tmd.Contents = make([]Content, tmd.ContentCount) + + for i := 0; i < int(tmd.ContentCount); i++ { + offset := 0xB04 + (0x30 * i) + + reader.Seek(int64(offset), io.SeekStart) + if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].ID); err != nil { + return nil, err + } + + reader.Seek(2, io.SeekCurrent) + + if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].Type); err != nil { + return nil, err + } + + if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].Size); err != nil { + return nil, err + } + } + default: + return nil, fmt.Errorf("unknown TMD version: %d", tmd.Version) } return tmd, nil }