// Copyright 2008 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #include "Core/Boot/DolReader.h" #include #include #include #include #include "Common/File.h" #include "Common/Swap.h" #include "Core/HW/Memmap.h" DolReader::DolReader(std::vector buffer) : BootExecutableReader(std::move(buffer)) { m_is_valid = Initialize(m_bytes); } DolReader::DolReader(File::IOFile file) : BootExecutableReader(std::move(file)) { m_is_valid = Initialize(m_bytes); } DolReader::DolReader(const std::string& filename) : BootExecutableReader(filename) { m_is_valid = Initialize(m_bytes); } DolReader::~DolReader() = default; bool DolReader::Initialize(const std::vector& buffer) { if (buffer.size() < sizeof(SDolHeader) || buffer.size() > UINT32_MAX) return false; memcpy(&m_dolheader, buffer.data(), sizeof(SDolHeader)); // swap memory u32* p = (u32*)&m_dolheader; for (size_t i = 0; i < (sizeof(SDolHeader) / sizeof(u32)); i++) p[i] = Common::swap32(p[i]); const u32 HID4_pattern = Common::swap32(0x7c13fba6); const u32 HID4_mask = Common::swap32(0xfc1fffff); m_is_wii = false; m_text_sections.reserve(DOL_NUM_TEXT); for (int i = 0; i < DOL_NUM_TEXT; ++i) { if (m_dolheader.textSize[i] != 0) { if (buffer.size() < m_dolheader.textOffset[i] + m_dolheader.textSize[i]) return false; const u8* text_start = &buffer[m_dolheader.textOffset[i]]; m_text_sections.emplace_back(text_start, &text_start[m_dolheader.textSize[i]]); for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j) { u32 word = ((u32*)text_start)[j]; if ((word & HID4_mask) == HID4_pattern) m_is_wii = true; } } else { // Make sure that m_text_sections indexes match header indexes m_text_sections.emplace_back(); } } m_data_sections.reserve(DOL_NUM_DATA); for (int i = 0; i < DOL_NUM_DATA; ++i) { if (m_dolheader.dataSize[i] != 0) { u32 section_size = m_dolheader.dataSize[i]; u32 section_offset = m_dolheader.dataOffset[i]; if (buffer.size() < section_offset) return false; std::vector data(section_size); const u8* data_start = &buffer[section_offset]; std::memcpy(&data[0], data_start, std::min((size_t)section_size, buffer.size() - section_offset)); m_data_sections.emplace_back(data); } else { // Make sure that m_data_sections indexes match header indexes m_data_sections.emplace_back(); } } return true; } bool DolReader::LoadIntoMemory(bool only_in_mem1) const { if (!m_is_valid) return false; // load all text (code) sections for (size_t i = 0; i < m_text_sections.size(); ++i) if (!m_text_sections[i].empty() && !(only_in_mem1 && m_dolheader.textAddress[i] + m_text_sections[i].size() >= Memory::GetRamSizeReal())) { Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(), m_text_sections[i].size()); } // load all data sections for (size_t i = 0; i < m_data_sections.size(); ++i) if (!m_data_sections[i].empty() && !(only_in_mem1 && m_dolheader.dataAddress[i] + m_data_sections[i].size() >= Memory::GetRamSizeReal())) { Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(), m_data_sections[i].size()); } return true; }