| 83 | } |
| 84 | |
| 85 | TestStats run_test(const std::filesystem::path& tests_dir, const std::string& test_name) { |
| 86 | std::filesystem::path input_path = tests_dir / (test_name + "_data.bin"); |
| 87 | std::filesystem::path data_dump_path = tests_dir / (test_name + "_data_out.bin"); |
| 88 | |
| 89 | bool found; |
| 90 | std::vector<uint8_t> file_data = read_file(input_path, found); |
| 91 | |
| 92 | if (!found) { |
| 93 | printf("Failed to open file: %s\n", input_path.string().c_str()); |
| 94 | return { TestError::FailedToOpenInput }; |
| 95 | } |
| 96 | |
| 97 | // Parse the test file. |
| 98 | uint32_t text_offset = read_u32_swap(file_data, 0x00); |
| 99 | uint32_t text_length = read_u32_swap(file_data, 0x04); |
| 100 | uint32_t init_data_offset = read_u32_swap(file_data, 0x08); |
| 101 | uint32_t good_data_offset = read_u32_swap(file_data, 0x0C); |
| 102 | uint32_t data_length = read_u32_swap(file_data, 0x10); |
| 103 | uint32_t text_address = read_u32_swap(file_data, 0x14); |
| 104 | uint32_t data_address = read_u32_swap(file_data, 0x18); |
| 105 | uint32_t next_struct_address = read_u32_swap(file_data, 0x1C); |
| 106 | |
| 107 | recomp_context ctx{}; |
| 108 | |
| 109 | byteswap_copy(&rdram[text_address - 0x80000000], &file_data[text_offset], text_length); |
| 110 | byteswap_copy(&rdram[data_address - 0x80000000], &file_data[init_data_offset], data_length); |
| 111 | |
| 112 | // Build recompiler context. |
| 113 | N64Recomp::Context context{}; |
| 114 | |
| 115 | // Move the file data into the context. |
| 116 | context.rom = std::move(file_data); |
| 117 | |
| 118 | context.sections.resize(2); |
| 119 | // Create a section for the function to exist in. |
| 120 | context.sections[0].ram_addr = text_address; |
| 121 | context.sections[0].rom_addr = text_offset; |
| 122 | context.sections[0].size = text_length; |
| 123 | context.sections[0].name = ".text"; |
| 124 | context.sections[0].executable = true; |
| 125 | context.sections[0].relocatable = true; |
| 126 | context.section_functions.resize(context.sections.size()); |
| 127 | // Create a section for .data (used for relocations) |
| 128 | context.sections[1].ram_addr = data_address; |
| 129 | context.sections[1].rom_addr = init_data_offset; |
| 130 | context.sections[1].size = data_length; |
| 131 | context.sections[1].name = ".data"; |
| 132 | context.sections[1].executable = false; |
| 133 | context.sections[1].relocatable = true; |
| 134 | |
| 135 | size_t start_func_index; |
| 136 | uint32_t function_desc_address = 0; |
| 137 | uint32_t reloc_desc_address = 0; |
| 138 | |
| 139 | // Read any extra structs. |
| 140 | while (next_struct_address != 0) { |
| 141 | uint32_t cur_struct_address = next_struct_address; |
| 142 | uint32_t struct_type = read_u32_swap(context.rom, next_struct_address + 0x00); |
no test coverage detected