| 125 | } |
| 126 | |
| 127 | bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uint16_t>& sections_by_vrom, N64Recomp::Context& mod_context) { |
| 128 | size_t offset = sizeof(FileHeader); |
| 129 | const FileSubHeaderV1* subheader = reinterpret_data<FileSubHeaderV1>(data, offset); |
| 130 | if (subheader == nullptr) { |
| 131 | return false; |
| 132 | } |
| 133 | |
| 134 | size_t num_sections = subheader->num_sections; |
| 135 | size_t num_dependencies = subheader->num_dependencies; |
| 136 | size_t num_imports = subheader->num_imports; |
| 137 | size_t num_dependency_events = subheader->num_dependency_events; |
| 138 | size_t num_replacements = subheader->num_replacements; |
| 139 | size_t num_exports = subheader->num_exports; |
| 140 | size_t num_callbacks = subheader->num_callbacks; |
| 141 | size_t num_provided_events = subheader->num_provided_events; |
| 142 | size_t num_hooks = subheader->num_hooks; |
| 143 | size_t string_data_size = subheader->string_data_size; |
| 144 | |
| 145 | if (string_data_size & 0b11) { |
| 146 | printf("String data size of %zu is not a multiple of 4\n", string_data_size); |
| 147 | return false; |
| 148 | } |
| 149 | |
| 150 | const char* string_data = reinterpret_data<char>(data, offset, string_data_size); |
| 151 | if (string_data == nullptr) { |
| 152 | return false; |
| 153 | } |
| 154 | |
| 155 | // TODO add proper creation methods for the remaining vectors and change these to reserves instead. |
| 156 | mod_context.sections.resize(num_sections); // Add method |
| 157 | mod_context.dependencies_by_name.reserve(num_dependencies); |
| 158 | mod_context.import_symbols.reserve(num_imports); |
| 159 | mod_context.dependency_events.reserve(num_dependency_events); |
| 160 | mod_context.replacements.resize(num_replacements); // Add method |
| 161 | mod_context.exported_funcs.resize(num_exports); // Add method |
| 162 | mod_context.callbacks.reserve(num_callbacks); |
| 163 | mod_context.event_symbols.reserve(num_provided_events); |
| 164 | mod_context.hooks.reserve(num_provided_events); |
| 165 | |
| 166 | for (size_t section_index = 0; section_index < num_sections; section_index++) { |
| 167 | const SectionHeaderV1* section_header = reinterpret_data<SectionHeaderV1>(data, offset); |
| 168 | if (section_header == nullptr) { |
| 169 | return false; |
| 170 | } |
| 171 | |
| 172 | N64Recomp::Section& cur_section = mod_context.sections[section_index]; |
| 173 | |
| 174 | cur_section.rom_addr = section_header->file_offset; |
| 175 | cur_section.ram_addr = section_header->vram; |
| 176 | cur_section.size = section_header->rom_size; |
| 177 | cur_section.bss_size = section_header->bss_size; |
| 178 | cur_section.name = "mod_section_" + std::to_string(section_index); |
| 179 | cur_section.relocatable = true; |
| 180 | cur_section.fixed_address = (section_header->flags & static_cast<uint32_t>(SectionFlags::FixedAddress)) != 0; |
| 181 | cur_section.globally_loaded = (section_header->flags & static_cast<uint32_t>(SectionFlags::GloballyLoaded)) != 0; |
| 182 | |
| 183 | if (cur_section.fixed_address && !cur_section.globally_loaded) { |
| 184 | printf("Fixed address sections that aren't globally loaded aren't currently supported\n"); |
no test coverage detected