Added MM aspMain parameters to rsp recomp, added voice and flash to special function lists

This commit is contained in:
Mr-Wiseguy 2023-02-19 22:43:08 -05:00
parent 5c5f6a51ad
commit 52644095f0
3 changed files with 144 additions and 39 deletions

View file

@ -510,6 +510,7 @@ void write_indirect_jumps(std::ofstream& output_file, const BranchTargets& branc
} }
// TODO de-hardcode these // TODO de-hardcode these
// OoT njpgdspMain
//constexpr size_t rsp_text_offset = 0xB8BAD0; //constexpr size_t rsp_text_offset = 0xB8BAD0;
//constexpr size_t rsp_text_size = 0xAF0; //constexpr size_t rsp_text_size = 0xAF0;
//constexpr size_t rsp_text_address = 0x04001080; //constexpr size_t rsp_text_address = 0x04001080;
@ -518,13 +519,25 @@ void write_indirect_jumps(std::ofstream& output_file, const BranchTargets& branc
//std::string output_function_name = "njpgdspMain"; //std::string output_function_name = "njpgdspMain";
//const std::vector<uint32_t> extra_indirect_branch_targets{}; //const std::vector<uint32_t> extra_indirect_branch_targets{};
constexpr size_t rsp_text_offset = 0xB89260; // OoT aspMain
constexpr size_t rsp_text_size = 0xFB0; //constexpr size_t rsp_text_offset = 0xB89260;
//constexpr size_t rsp_text_size = 0xFB0;
//constexpr size_t rsp_text_address = 0x04001000;
//std::string rom_file_path = "../test/oot_mq_debug.z64";
//std::string output_file_path = "../test/rsp/aspMain.cpp";
//std::string output_function_name = "aspMain";
//const std::vector<uint32_t> extra_indirect_branch_targets{ 0x1F68, 0x1230, 0x114C, 0x1F18, 0x1E2C, 0x14F4, 0x1E9C, 0x1CB0, 0x117C, 0x17CC, 0x11E8, 0x1AA4, 0x1B34, 0x1190, 0x1C5C, 0x1220, 0x1784, 0x1830, 0x1A20, 0x1884, 0x1A84, 0x1A94, 0x1A48, 0x1BA0 };
// MM's njpgdspMain is identical to OoT's
// MM aspMain
constexpr size_t rsp_text_offset = 0xC40FF0;
constexpr size_t rsp_text_size = 0x1000;
constexpr size_t rsp_text_address = 0x04001000; constexpr size_t rsp_text_address = 0x04001000;
std::string rom_file_path = "../test/oot_mq_debug.z64"; std::string rom_file_path = "../../MMRecomp/mm.us.rev1.z64"; // uncompressed rom!
std::string output_file_path = "../test/rsp/aspMain.cpp"; std::string output_file_path = "../../MMRecomp/rsp/aspMain.cpp";
std::string output_function_name = "aspMain"; std::string output_function_name = "aspMain";
const std::vector<uint32_t> extra_indirect_branch_targets{ 0x1F68, 0x1230, 0x114C, 0x1F18, 0x1E2C, 0x14F4, 0x1E9C, 0x1CB0, 0x117C, 0x17CC, 0x11E8, 0x1AA4, 0x1B34, 0x1190, 0x1C5C, 0x1220, 0x1784, 0x1830, 0x1A20, 0x1884, 0x1A84, 0x1A94, 0x1A48, 0x1BA0 }; const std::vector<uint32_t> extra_indirect_branch_targets{ 0x1F80, 0x1250, 0x1154, 0x1094, 0x1E0C, 0x1514, 0x1E7C, 0x1C90, 0x1180, 0x1808, 0x11E8, 0x1ADC, 0x1B6C, 0x1194, 0x1EF8, 0x1240, 0x17C0, 0x186C, 0x1A58, 0x18BC, 0x1ABC, 0x1ACC, 0x1A80, 0x1BD4 };
#ifdef _MSC_VER #ifdef _MSC_VER
inline uint32_t byteswap(uint32_t val) { inline uint32_t byteswap(uint32_t val) {
@ -578,8 +591,8 @@ int main() {
// Open output file and write beginning // Open output file and write beginning
std::ofstream output_file(output_file_path); std::ofstream output_file(output_file_path);
fmt::print(output_file, fmt::print(output_file,
"#include \"../src/rsp.h\"\n" "#include \"rsp.h\"\n"
"#include \"../src/rsp_vu_impl.h\"\n" "#include \"rsp_vu_impl.h\"\n"
"RspExitReason {}(uint8_t* rdram) {{\n" "RspExitReason {}(uint8_t* rdram) {{\n"
" uint32_t r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0;\n" " uint32_t r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0;\n"
" uint32_t r8 = 0, r9 = 0, r10 = 0, r11 = 0, r12 = 0, r13 = 0, r14 = 0, r15 = 0;\n" " uint32_t r8 = 0, r9 = 0, r10 = 0, r11 = 0, r12 = 0, r13 = 0, r14 = 0, r15 = 0;\n"

View file

@ -76,6 +76,20 @@ std::unordered_set<std::string> reimplemented_funcs{
"osPiGetStatus", "osPiGetStatus",
"osEPiRawStartDma", "osEPiRawStartDma",
"osEPiReadIo", "osEPiReadIo",
// Flash saving functions
"osFlashInit",
"osFlashReadStatus",
"osFlashReadId",
"osFlashClearStatus",
"osFlashAllErase",
"osFlashAllEraseThrough",
"osFlashSectorErase",
"osFlashSectorEraseThrough",
"osFlashCheckEraseEnd",
"osFlashWriteBuffer",
"osFlashWriteArray",
"osFlashReadArray",
"osFlashChange",
// Threading functions // Threading functions
"osCreateThread", "osCreateThread",
"osStartThread", "osStartThread",
@ -94,6 +108,16 @@ std::unordered_set<std::string> reimplemented_funcs{
"osGetTime", "osGetTime",
"osSetTimer", "osSetTimer",
"osStopTimer", "osStopTimer",
// Voice functions
"osVoiceSetWord",
"osVoiceCheckWord",
"osVoiceStopReadData",
"osVoiceInit",
"osVoiceMaskDictionary",
"osVoiceStartReadData",
"osVoiceControlGain",
"osVoiceGetReadData",
"osVoiceClearDictionary",
// interrupt functions // interrupt functions
"osSetIntMask", "osSetIntMask",
"__osDisableInt", "__osDisableInt",
@ -194,6 +218,7 @@ std::unordered_set<std::string> ignored_funcs {
"__osContGetInitData", "__osContGetInitData",
"__osContRamRead", "__osContRamRead",
"__osContRamWrite", "__osContRamWrite",
"__osContChannelReset",
// EEPROM functions // EEPROM functions
"osEepromLongRead", "osEepromLongRead",
"osEepromLongWrite", "osEepromLongWrite",
@ -286,6 +311,20 @@ std::unordered_set<std::string> ignored_funcs {
"__osLeoAbnormalResume", "__osLeoAbnormalResume",
"__osLeoInterrupt", "__osLeoInterrupt",
"__osLeoResume", "__osLeoResume",
// Flash saving functions
"osFlashInit",
"osFlashReadStatus",
"osFlashReadId",
"osFlashClearStatus",
"osFlashAllErase",
"osFlashAllEraseThrough",
"osFlashSectorErase",
"osFlashSectorEraseThrough",
"osFlashCheckEraseEnd",
"osFlashWriteBuffer",
"osFlashWriteArray",
"osFlashReadArray",
"osFlashChange",
// Threading functions // Threading functions
"osCreateThread", "osCreateThread",
"osStartThread", "osStartThread",
@ -311,6 +350,26 @@ std::unordered_set<std::string> ignored_funcs {
"__osTimerInterrupt", "__osTimerInterrupt",
"__osTimerServicesInit", "__osTimerServicesInit",
"__osSetTimerIntr", "__osSetTimerIntr",
// Voice functions
"osVoiceSetWord",
"osVoiceCheckWord",
"osVoiceStopReadData",
"osVoiceInit",
"osVoiceMaskDictionary",
"osVoiceStartReadData",
"osVoiceControlGain",
"osVoiceGetReadData",
"osVoiceClearDictionary",
"__osVoiceCheckResult",
"__osVoiceContRead36",
"__osVoiceContWrite20",
"__osVoiceContWrite4",
"__osVoiceContRead2",
"__osVoiceSetADConverter",
"__osVoiceContDataCrc",
"__osVoiceGetStatus",
"corrupted",
"corrupted_init",
// exceptasm functions // exceptasm functions
"__osExceptionPreamble", "__osExceptionPreamble",
"__osException", "__osException",
@ -547,7 +606,11 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL
} }
// Check if this symbol is the entrypoint // Check if this symbol is the entrypoint
if (value == entrypoint && type == ELFIO::STT_FUNC) { if (value == entrypoint /*&& type == ELFIO::STT_FUNC*/) {
if (found_entrypoint_func) {
fmt::print(stderr, "Ambiguous entrypoint\n");
return false;
}
found_entrypoint_func = true; found_entrypoint_func = true;
size = 0x50; // dummy size for entrypoints, should cover them all size = 0x50; // dummy size for entrypoints, should cover them all
name = "recomp_entrypoint"; name = "recomp_entrypoint";
@ -638,6 +701,20 @@ struct SegmentEntry {
ELFIO::Elf_Xword memory_size; ELFIO::Elf_Xword memory_size;
}; };
std::optional<size_t> get_segment(const std::vector<SegmentEntry>& segments, ELFIO::Elf_Xword section_size, ELFIO::Elf64_Off section_offset) {
// A linear search is safest even if the segment list is sorted, as there may be overlapping segments
for (size_t i = 0; i < segments.size(); i++) {
const auto& segment = segments[i];
// Check that the section's data in the elf file is within bounds of the segment's data
if (section_offset >= segment.data_offset && section_offset + section_size <= segment.data_offset + segment.memory_size) {
return i;
}
}
return std::nullopt;
}
ELFIO::section* read_sections(RecompPort::Context& context, const ELFIO::elfio& elf_file) { ELFIO::section* read_sections(RecompPort::Context& context, const ELFIO::elfio& elf_file) {
ELFIO::section* symtab_section = nullptr; ELFIO::section* symtab_section = nullptr;
std::vector<SegmentEntry> segments{}; std::vector<SegmentEntry> segments{};
@ -648,15 +725,15 @@ ELFIO::section* read_sections(RecompPort::Context& context, const ELFIO::elfio&
const auto& segment = *elf_file.segments[segment_index]; const auto& segment = *elf_file.segments[segment_index];
segments[segment_index].data_offset = segment.get_offset(); segments[segment_index].data_offset = segment.get_offset();
segments[segment_index].physical_address = segment.get_physical_address(); segments[segment_index].physical_address = segment.get_physical_address();
segments[segment_index].memory_size = segment.get_memory_size(); segments[segment_index].memory_size = segment.get_file_size();
} }
// Sort the segments by physical address //// Sort the segments by physical address
std::sort(segments.begin(), segments.end(), //std::sort(segments.begin(), segments.end(),
[](const SegmentEntry& lhs, const SegmentEntry& rhs) { // [](const SegmentEntry& lhs, const SegmentEntry& rhs) {
return lhs.data_offset < rhs.data_offset; // return lhs.data_offset < rhs.data_offset;
} // }
); //);
std::unordered_map<std::string, ELFIO::section*> reloc_sections_by_name; std::unordered_map<std::string, ELFIO::section*> reloc_sections_by_name;
@ -694,25 +771,31 @@ ELFIO::section* read_sections(RecompPort::Context& context, const ELFIO::elfio&
// If this section isn't bss (SHT_NOBITS) and ends up in the rom (SHF_ALLOC), // If this section isn't bss (SHT_NOBITS) and ends up in the rom (SHF_ALLOC),
// find this section's rom address and copy it into the rom // find this section's rom address and copy it into the rom
if (type != ELFIO::SHT_NOBITS && section->get_flags() & ELFIO::SHF_ALLOC) { if (type != ELFIO::SHT_NOBITS && section->get_flags() & ELFIO::SHF_ALLOC && section->get_size() != 0) {
// Find the segment this section is in to determine the physical (rom) address of the section //// Find the segment this section is in to determine the physical (rom) address of the section
auto segment_it = std::upper_bound(segments.begin(), segments.end(), section->get_offset(), //auto segment_it = std::upper_bound(segments.begin(), segments.end(), section->get_offset(),
[](ELFIO::Elf64_Off section_offset, const SegmentEntry& segment) { // [](ELFIO::Elf64_Off section_offset, const SegmentEntry& segment) {
return section_offset < segment.data_offset; // return section_offset < segment.data_offset;
} // }
); //);
if (segment_it == segments.begin()) { //if (segment_it == segments.begin()) {
// fmt::print(stderr, "Could not find segment that section {} belongs to!\n", section_name.c_str());
// return nullptr;
//}
//// Upper bound returns the iterator after the element we're looking for, so rewind by one
//// This is safe because we checked if segment_it was segments.begin() already, which is the minimum value it could be
//const SegmentEntry& segment = *(segment_it - 1);
//// Check to be sure that the section is actually in this segment
//if (section->get_offset() >= segment.data_offset + segment.memory_size) {
// fmt::print(stderr, "Section {} out of range of segment at offset 0x{:08X}\n", section_name.c_str(), segment.data_offset);
// return nullptr;
//}
std::optional<size_t> segment_index = get_segment(segments, section_out.size, section->get_offset());
if (!segment_index.has_value()) {
fmt::print(stderr, "Could not find segment that section {} belongs to!\n", section_name.c_str()); fmt::print(stderr, "Could not find segment that section {} belongs to!\n", section_name.c_str());
return nullptr; return nullptr;
} }
// Upper bound returns the iterator after the element we're looking for, so rewind by one const SegmentEntry& segment = segments[segment_index.value()];
// This is safe because we checked if segment_it was segments.begin() already, which is the minimum value it could be
const SegmentEntry& segment = *(segment_it - 1);
// Check to be sure that the section is actually in this segment
if (section->get_offset() >= segment.data_offset + segment.memory_size) {
fmt::print(stderr, "Section {} out of range of segment at offset 0x{:08X}\n", section_name.c_str(), segment.data_offset);
return nullptr;
}
// Calculate the rom address based on this section's offset into the segment and the segment's rom address // Calculate the rom address based on this section's offset into the segment and the segment's rom address
section_out.rom_addr = segment.physical_address + (section->get_offset() - segment.data_offset); section_out.rom_addr = segment.physical_address + (section->get_offset() - segment.data_offset);
// Resize the output rom if needed to fit this section // Resize the output rom if needed to fit this section
@ -895,8 +978,8 @@ bool read_list_file(const char* filename, std::unordered_set<std::string>& entri
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (argc < 3 || argc > 4) { if (argc < 4 || argc > 5) {
fmt::print("Usage: {} [input elf file] [entrypoint RAM address] [relocatable sections list file (optional)]\n", argv[0]); fmt::print("Usage: {} [input elf file] [entrypoint RAM address] [output path] [relocatable sections list file (optional)]\n", argv[0]);
std::exit(EXIT_SUCCESS); std::exit(EXIT_SUCCESS);
} }
@ -913,14 +996,19 @@ int main(int argc, char** argv) {
std::unordered_set<std::string> relocatable_sections{}; std::unordered_set<std::string> relocatable_sections{};
if (argc == 4) { if (argc == 5) {
if (!read_list_file(argv[3], relocatable_sections)) { if (!read_list_file(argv[4], relocatable_sections)) {
exit_failure("Failed to load the relocatable section list file: " + std::string(argv[3]) + "\n"); exit_failure("Failed to load the relocatable section list file: " + std::string(argv[4]) + "\n");
} }
} }
std::string output_dir{ argv[3] };
std::string elf_name{ argv[1] }; std::string elf_name{ argv[1] };
if (!output_dir.ends_with('/')) {
output_dir += "/";
}
if (!elf_file.load(elf_name)) { if (!elf_file.load(elf_name)) {
exit_failure("Failed to load provided elf file\n"); exit_failure("Failed to load provided elf file\n");
} }
@ -962,8 +1050,8 @@ int main(int argc, char** argv) {
fmt::print("Function count: {}\n", context.functions.size()); fmt::print("Function count: {}\n", context.functions.size());
std::ofstream lookup_file{ "test/funcs/lookup.cpp" }; std::ofstream lookup_file{ output_dir + "lookup.cpp" };
std::ofstream func_header_file{ "test/funcs/funcs.h" }; std::ofstream func_header_file{ output_dir + "funcs.h" };
fmt::print(lookup_file, fmt::print(lookup_file,
//"#include <utility>\n" //"#include <utility>\n"
@ -984,7 +1072,7 @@ int main(int argc, char** argv) {
std::vector<std::vector<uint32_t>> static_funcs_by_section{ context.sections.size() }; std::vector<std::vector<uint32_t>> static_funcs_by_section{ context.sections.size() };
std::string output_dir = "test/funcs/"; fmt::print("Working dir: {}\n", std::filesystem::current_path().string());
//#pragma omp parallel for //#pragma omp parallel for
for (size_t i = 0; i < context.functions.size(); i++) { for (size_t i = 0; i < context.functions.size(); i++) {

View file

@ -974,6 +974,10 @@ bool RecompPort::recompile_function(const RecompPort::Context& context, const Re
// Open the output file and write the file header // Open the output file and write the file header
std::ofstream output_file{ output_path.data() }; std::ofstream output_file{ output_path.data() };
if (!output_file.good()) {
fmt::print(stderr, "Failed to open file for writing: {}\n", output_path);
return false;
}
fmt::print(output_file, fmt::print(output_file,
"#include \"recomp.h\"\n" "#include \"recomp.h\"\n"
"#include \"disable_warnings.h\"\n" "#include \"disable_warnings.h\"\n"