mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-03-20 22:02:40 -04:00
This implements MIOS's PPC bootstrapping functionality, which enables users to start a GameCube game from the Wii System Menu. Because we aren't doing Starlet LLE (and don't have a boot1), we can just jump to MIOS when the emulated software does an ES_LAUNCH or uses ioctlv 0x25 to launch BC. Note that the process is more complex on a real Wii and goes through several more steps before getting to MIOS: * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game. [Dolphin does this too.] * BC, which is reportedly very similar to boot1, lowers the Hollywood clock speed to the Flipper's and then launches boot2. * boot2 sees the lowered clock speed and launches MIOS (1-101) instead of the System Menu. MIOS runs instead of IOS in GC mode and has an embedded GC IPL (which is the code actually responsible for loading the disc game) and a PPC bootstrap code. To get things working properly, we simply need to load both to memory, then jump to the bootstrap code at 0x3400. Obviously, because of the way this works, a real MIOS is required.
67 lines
1.9 KiB
C++
67 lines
1.9 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include "Core/Boot/ElfTypes.h"
|
|
|
|
enum KnownElfTypes
|
|
{
|
|
KNOWNELF_PSP = 0,
|
|
KNOWNELF_DS = 1,
|
|
KNOWNELF_GBA = 2,
|
|
KNOWNELF_GC = 3,
|
|
};
|
|
|
|
typedef int SectionID;
|
|
|
|
class ElfReader
|
|
{
|
|
private:
|
|
char* base;
|
|
u32* base32;
|
|
|
|
Elf32_Ehdr* header;
|
|
Elf32_Phdr* segments;
|
|
Elf32_Shdr* sections;
|
|
|
|
u32* sectionAddrs;
|
|
bool bRelocate;
|
|
u32 entryPoint;
|
|
|
|
public:
|
|
ElfReader(void* ptr);
|
|
~ElfReader() {}
|
|
u32 Read32(int off) const { return base32[off >> 2]; }
|
|
// Quick accessors
|
|
ElfType GetType() const { return (ElfType)(header->e_type); }
|
|
ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); }
|
|
u32 GetEntryPoint() const { return entryPoint; }
|
|
u32 GetFlags() const { return (u32)(header->e_flags); }
|
|
bool LoadIntoMemory(bool only_in_mem1 = false);
|
|
bool LoadSymbols();
|
|
|
|
int GetNumSegments() const { return (int)(header->e_phnum); }
|
|
int GetNumSections() const { return (int)(header->e_shnum); }
|
|
const u8* GetPtr(int offset) const { return (u8*)base + offset; }
|
|
const char* GetSectionName(int section) const;
|
|
const u8* GetSectionDataPtr(int section) const
|
|
{
|
|
if (section < 0 || section >= header->e_shnum)
|
|
return nullptr;
|
|
if (sections[section].sh_type != SHT_NOBITS)
|
|
return GetPtr(sections[section].sh_offset);
|
|
else
|
|
return nullptr;
|
|
}
|
|
bool IsCodeSegment(int segment) const { return segments[segment].p_flags & PF_X; }
|
|
const u8* GetSegmentPtr(int segment) { return GetPtr(segments[segment].p_offset); }
|
|
int GetSegmentSize(int segment) const { return segments[segment].p_filesz; }
|
|
u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; }
|
|
int GetSectionSize(SectionID section) const { return sections[section].sh_size; }
|
|
SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
|
|
|
|
bool DidRelocate() const { return bRelocate; }
|
|
};
|