diff options
author | Jesse Talavera-Greenberg <jesse@jesse.tg> | 2023-07-08 16:17:30 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-08 22:17:30 +0200 |
commit | 0947e941b83b23b701edb31345c119f14e5ad56f (patch) | |
tree | 8162328db5d7b881fe8ed1cd9a0ea4a72e5aaf28 /src/DSi_TMD.h | |
parent | d1ff103259bf44047b0da458cbd22d5e66a70773 (diff) |
Modest cleanups for DSi_NAND (#1714)
* Add a definition for TMD files
* Wrap TitleMetadata in a namespace
* Add a comment
* Remove TitleMetadataCertificate
- melonDS ignores it anyway
* Refactor the use of title metadata
- Move bitwise operations on the title ID into helper methods
- Use TitleMetadata objects instead of pointers to raw data
* Slight cleanup in DSi_NAND
- Replace some constants with sizeof
- Use an NDSHeader object instead of a raw array of bytes
* Add a DSi_NAND::ImportFile overload that loads a file from memory
* Split most of ImportTitle into InitTitleFileStructure
- It will be reused in the next commit
* Add ability to import title from memory
* Fix another potential issue
* Fix broken DSiWare installation
- The bytes of the title ID/category were being swapped in most places, but not all
* Add some logging calls
* Declare array sizes in DSi_TMD in decimal, not hex
* Add a space after the #endif
- To adhere to the style guide
* Assert the size of TitleMetadataContent
* Change the type of SignatureName
* Don't mark the TMD structs as packed
* Remove extraneous comments
* Cut down some newlines
Diffstat (limited to 'src/DSi_TMD.h')
-rw-r--r-- | src/DSi_TMD.h | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/DSi_TMD.h b/src/DSi_TMD.h new file mode 100644 index 0000000..12226c5 --- /dev/null +++ b/src/DSi_TMD.h @@ -0,0 +1,119 @@ +/* + Copyright 2016-2023 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef DSI_TMD_H +#define DSI_TMD_H + +#include "types.h" +#include <array> + +namespace DSi_TMD +{ + +struct TitleMetadataContent { + u8 ContentId[4]; /// Content ID (00,00,00,vv) ;lowercase/hex ;"0000000vv.app" + u8 ContentIndex[2]; /// Content Index (00,00) + u8 ContentType[2]; /// Content Type (00,01) ;aka DSi .app + u8 ContentSize[8]; /// Content Size (00,00,00,00,00,19,E4,00) + u8 ContentSha1Hash[20]; /// Content SHA1 (on decrypted ".app" file) + + [[nodiscard]] u32 GetVersion() const noexcept + { + return (ContentId[0] << 24) | (ContentId[1] << 16) | (ContentId[2] << 8) | ContentId[3]; + } +}; + +static_assert(sizeof(TitleMetadataContent) == 36, "TitleMetadataContent is not 36 bytes!"); + +/// Metadata for a DSiWare title. +/// Used to install DSiWare titles to NAND. +/// @see https://problemkaputt.de/gbatek.htm#dsisdmmcdsiwareticketsandtitlemetadata +struct TitleMetadata +{ + u32 SignatureType; + u8 Signature[256]; + u8 SignatureAlignment[60]; + char SignatureName[64]; + + u8 TmdVersion; + u8 CaCrlVersion; + u8 SignerCrlVersion; + u8 Padding0; + + u8 SystemVersion[8]; + u8 TitleId[8]; + u32 TitleType; + u8 GroupId[2]; + u8 PublicSaveSize[4]; + u8 PrivateSaveSize[4]; + u8 Padding1[4]; + + u8 SrlFlag; + u8 Padding2[3]; + + u8 AgeRatings[16]; + u8 Padding3[30]; + + u32 AccessRights; + u16 TitleVersion; + + u16 NumberOfContents; /// There's always one or zero content entries in practice + u16 BootContentIndex; + u8 Padding4[2]; + + TitleMetadataContent Contents; + + [[nodiscard]] bool HasPublicSaveData() const noexcept { return GetPublicSaveSize() != 0; } + [[nodiscard]] bool HasPrivateSaveData() const noexcept { return GetPrivateSaveSize() != 0; } + + [[nodiscard]] u32 GetPublicSaveSize() const noexcept + { + return (PublicSaveSize[0] << 24) | (PublicSaveSize[1] << 16) | (PublicSaveSize[2] << 8) | PublicSaveSize[3]; + } + + [[nodiscard]] u32 GetPrivateSaveSize() const noexcept + { + return (PrivateSaveSize[0] << 24) | (PrivateSaveSize[1] << 16) | (PrivateSaveSize[2] << 8) | PrivateSaveSize[3]; + } + + [[nodiscard]] u32 GetCategory() const noexcept + { + return (TitleId[0] << 24) | (TitleId[1] << 16) | (TitleId[2] << 8) | TitleId[3]; + } + + [[nodiscard]] u32 GetCategoryNoByteswap() const noexcept + { + return reinterpret_cast<const u32&>(TitleId); + } + + [[nodiscard]] u32 GetID() const noexcept + { + return (TitleId[4] << 24) | (TitleId[5] << 16) | (TitleId[6] << 8) | TitleId[7]; + } + + [[nodiscard]] u32 GetIDNoByteswap() const noexcept + { + return *reinterpret_cast<const u32*>(&TitleId[4]); + } +}; + +static_assert(sizeof(TitleMetadata) == 520, "TitleMetadata is not 520 bytes!"); + +} + +#endif // DSI_TMD_H |