libnedit
Lightweight C++ library for Nintendo DS(i) formats
Loading...
Searching...
No Matches
fmt_ROM.hpp
1
2#pragma once
3#include <ntr/fmt/nfs/nfs_NitroFs.hpp>
4#include <ntr/gfx/gfx_BannerIcon.hpp>
5#include <ntr/util/util_String.hpp>
6#include <ntr/util/util_System.hpp>
7
8namespace ntr::fmt {
9
10 struct ROM : public nfs::NitroFsFileFormat {
11
12 // TODO: use this
13 enum class NDSRegion : u8 {
14 Normal = 0x00,
15 Korea = 0x40,
16 China = 0x80
17 };
18
19 enum class UnitCode : u8 {
20 NDS = 0x00,
21 NDS_NDSi = 0x02,
22 NDSi = 0x03
23 };
24
25 struct Header {
26 char game_title[12];
27 char game_code[4];
28 char maker_code[2];
29 UnitCode unit_code;
30 u8 encryption_seed_select;
31 u8 device_capacity;
32 u8 reserved_1[7];
33 union {
34 u16 ndsi_game_revision;
35 struct {
36 u8 reserved;
37 u8 region;
38 } nds;
39 } game_revision;
40 u8 version;
41 u8 flags;
42 u32 arm9_rom_offset;
43 u32 arm9_entry_address;
44 u32 arm9_ram_address;
45 u32 arm9_size;
46 u32 arm7_rom_offset;
47 u32 arm7_entry_address;
48 u32 arm7_ram_address;
49 u32 arm7_size;
50 u32 fnt_offset;
51 u32 fnt_size;
52 u32 fat_offset;
53 u32 fat_size;
54 u32 arm9_ovl_offset;
55 u32 arm9_ovl_size;
56 u32 arm7_ovl_offset;
57 u32 arm7_ovl_size;
58 u32 normal_card_control_register_settings;
59 u32 secure_card_control_register_settings;
60 u32 banner_offset;
61 u16 secure_area_crc;
62 u16 secure_transfer_timeout;
63 u32 arm9_autoload;
64 u32 arm7_autoload;
65 u64 secure_disable;
66 u32 ntr_region_size;
67 u32 header_size;
68 u8 reserved_2[56];
69 u8 nintendo_logo[156];
70 u16 nintendo_logo_crc;
71 u16 header_crc;
72 u8 reserved_debugger[32];
73
74 // Note: helpers since these strings don't neccessarily end with a null character, so std::string(<c_str>) wouldn't work as expected there
75
76 inline std::string GetGameTitle() {
77 return util::GetNonNullTerminatedCString(this->game_title);
78 }
79
80 inline void SetGameTitle(const std::string &game_title_str) {
81 return util::SetNonNullTerminatedCString(this->game_title, game_title_str);
82 }
83
84 inline std::string GetGameCode() {
85 return util::GetNonNullTerminatedCString(this->game_code);
86 }
87
88 inline void SetGameCode(const std::string &game_code_str) {
89 return util::SetNonNullTerminatedCString(this->game_code, game_code_str);
90 }
91
92 inline std::string GetMakerCode() {
93 return util::GetNonNullTerminatedCString(this->maker_code);
94 }
95
96 inline void SetMakerCode(const std::string &maker_code_str) {
97 return util::SetNonNullTerminatedCString(this->maker_code, maker_code_str);
98 }
99 };
100 static_assert(sizeof(Header) == 0x180);
101
102 static constexpr u32 GameTitleLength = 128;
103
104 struct Banner {
105 u8 version;
106 u8 reserved_1;
107 u16 crc16_v1;
108 u8 reserved_2[28];
109 u8 icon_chr[gfx::IconCharSize];
110 u8 icon_plt[gfx::IconPaletteSize];
111 char16_t game_titles[static_cast<u32>(util::SystemLanguage::Count)][GameTitleLength];
112
113 inline std::u16string GetGameTitle(const util::SystemLanguage lang) {
114 if(lang < util::SystemLanguage::Count) {
115 return util::GetNonNullTerminatedCString(this->game_titles[static_cast<u32>(lang)]);
116 }
117 return u"";
118 }
119
120 inline void SetGameTitle(const util::SystemLanguage lang, const std::u16string &game_title_str) {
121 if(lang < util::SystemLanguage::Count) {
122 util::SetNonNullTerminatedCString(this->game_titles[static_cast<u32>(lang)], game_title_str);
123 }
124 }
125 };
126
127 Header header;
128 Banner banner;
129
130 ROM() {}
131 ROM(const ROM&) = delete;
132
133 bool GetAlignmentBetweenFileData(size_t &out_align) override {
134 out_align = 0x200;
135 return true;
136 }
137
138 size_t GetFatEntriesOffset() override {
139 return this->header.fat_offset;
140 }
141
142 size_t GetFatEntryCount() override {
143 return this->header.fat_size / sizeof(nfs::FileAllocationTableEntry);
144 }
145
146 Result OnFileSystemWrite(fs::BinaryFile &w_bf, const ssize_t size_diff) override {
147 size_t actual_rom_size;
148 NTR_R_TRY(w_bf.GetAbsoluteOffset(actual_rom_size));
149 this->header.ntr_region_size += size_diff;
150 auto capacity_size = actual_rom_size;
151 capacity_size |= capacity_size >> 16;
152 capacity_size |= capacity_size >> 8;
153 capacity_size |= capacity_size >> 4;
154 capacity_size |= capacity_size >> 2;
155 capacity_size |= capacity_size >> 1;
156 capacity_size++;
157 if(capacity_size <= 0x20000) {
158 capacity_size = 0x20000;
159 }
160 auto capacity = -18;
161 while(capacity_size != 0) {
162 capacity_size >>= 1;
163 capacity++;
164 }
165 this->header.device_capacity = (capacity < 0) ? 0 : static_cast<u8>(capacity);
166
167 NTR_R_TRY(w_bf.SetAbsoluteOffset(0));
168 NTR_R_TRY(w_bf.Write(this->header));
169
170 NTR_R_TRY(w_bf.SetAbsoluteOffset(this->header.banner_offset));
171 NTR_R_TRY(w_bf.Write(this->banner));
172
173 NTR_R_SUCCEED();
174 }
175
176 Result ValidateImpl(const std::string &path, std::shared_ptr<fs::FileHandle> file_handle, const fs::FileCompression comp) override;
177 Result ReadImpl(const std::string &path, std::shared_ptr<fs::FileHandle> file_handle, const fs::FileCompression comp) override;
178 };
179
180 using ROMFileHandle = nfs::NitroFsFileHandle<ROM>;
181
182}
Definition fmt_ROM.hpp:104
Definition fmt_ROM.hpp:25
Definition fmt_ROM.hpp:10
Definition nfs_NitroFs.hpp:43