mirror of
https://github.com/Xpl0itU/WiiUDownloader.git
synced 2025-05-09 13:52:02 -04:00
147 lines
3.8 KiB
Go
147 lines
3.8 KiB
Go
package wiiudownloader
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
const (
|
|
TMD_VERSION_WII = 0x00
|
|
TMD_VERSION_WIIU = 0x01
|
|
)
|
|
|
|
type TMD struct {
|
|
TitleID uint64
|
|
Version byte
|
|
TitleVersion uint16
|
|
ContentCount uint16
|
|
Contents []Content
|
|
Certificate1 []byte
|
|
Certificate2 []byte
|
|
}
|
|
|
|
func ParseTMD(data []byte) (*TMD, error) {
|
|
tmd := &TMD{}
|
|
reader := bytes.NewReader(data)
|
|
|
|
reader.Seek(0x180, io.SeekStart)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.Version); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch tmd.Version {
|
|
case TMD_VERSION_WII:
|
|
reader.Seek(0x18C, io.SeekStart)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.TitleID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
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 := 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(0x1E8+(0x24*int64(i)), io.SeekStart)
|
|
tmd.Contents[i].Index = make([]byte, 2)
|
|
if _, err := io.ReadFull(reader, tmd.Contents[i].Index); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
tmd.Contents[i].Hash = make([]byte, 0x20)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[i].Hash); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
tmd.Certificate1 = make([]byte, 0x400)
|
|
if _, err := io.ReadFull(reader, tmd.Certificate1); err != nil {
|
|
return nil, err
|
|
}
|
|
tmd.Certificate2 = make([]byte, 0x300)
|
|
if _, err := io.ReadFull(reader, tmd.Certificate2); err != nil {
|
|
return nil, err
|
|
}
|
|
case TMD_VERSION_WIIU:
|
|
reader.Seek(0x18C, io.SeekStart)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.TitleID); err != nil {
|
|
return nil, err
|
|
}
|
|
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 c := uint16(0); c < tmd.ContentCount; c++ {
|
|
offset := 2820 + (48 * c)
|
|
reader.Seek(int64(offset), io.SeekStart)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[c].ID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reader.Seek(0xB08+(0x30*int64(c)), io.SeekStart)
|
|
tmd.Contents[c].Index = make([]byte, 2)
|
|
if _, err := io.ReadFull(reader, tmd.Contents[c].Index); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reader.Seek(0xB0A+(0x30*int64(c)), io.SeekStart)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[c].Type); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reader.Seek(0xB0C+(0x30*int64(c)), io.SeekStart)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[c].Size); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reader.Seek(0xB14+(0x30*int64(c)), io.SeekStart)
|
|
tmd.Contents[c].Hash = make([]byte, 0x20)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.Contents[c].Hash); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
tmd.Certificate1 = make([]byte, 0x400)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.Certificate1); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
tmd.Certificate2 = make([]byte, 0x300)
|
|
if err := binary.Read(reader, binary.BigEndian, &tmd.Certificate2); err != nil {
|
|
return nil, err
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("unknown TMD version: %d", tmd.Version)
|
|
}
|
|
return tmd, nil
|
|
}
|