Copy dolphin/os progress from TP decomp

This commit is contained in:
LagoLunatic 2024-07-07 13:24:14 -04:00
parent fcbfe1e299
commit 09e3562a32
47 changed files with 6695 additions and 152 deletions

View File

@ -965,22 +965,22 @@ config.libs = [
Object(NonMatching, "dolphin/os/OS.c"),
Object(NonMatching, "dolphin/os/OSAlarm.c"),
Object(NonMatching, "dolphin/os/OSAlloc.c"),
Object(NonMatching, "dolphin/os/OSArena.c"),
Object(NonMatching, "dolphin/os/OSAudioSystem.c"),
Object(Matching, "dolphin/os/OSArena.c"),
Object(Matching, "dolphin/os/OSAudioSystem.c"),
Object(NonMatching, "dolphin/os/OSCache.c"),
Object(NonMatching, "dolphin/os/OSContext.c"),
Object(NonMatching, "dolphin/os/OSError.c"),
Object(NonMatching, "dolphin/os/OSFont.c"),
Object(NonMatching, "dolphin/os/OSInterrupt.c"),
Object(NonMatching, "dolphin/os/OSLink.c"),
Object(NonMatching, "dolphin/os/OSMessage.c"),
Object(Matching, "dolphin/os/OSInterrupt.c"),
Object(Matching, "dolphin/os/OSLink.c"),
Object(Matching, "dolphin/os/OSMessage.c"),
Object(NonMatching, "dolphin/os/OSMemory.c"),
Object(NonMatching, "dolphin/os/OSMutex.c"),
Object(Matching, "dolphin/os/OSMutex.c"),
Object(NonMatching, "dolphin/os/OSReboot.c"),
Object(NonMatching, "dolphin/os/OSReset.c"),
Object(NonMatching, "dolphin/os/OSResetSW.c"),
Object(NonMatching, "dolphin/os/OSRtc.c"),
Object(NonMatching, "dolphin/os/OSSync.c"),
Object(Matching, "dolphin/os/OSSync.c"),
Object(NonMatching, "dolphin/os/OSThread.c"),
Object(NonMatching, "dolphin/os/OSTime.c"),
Object(NonMatching, "dolphin/os/__ppc_eabi_init.cpp"),

View File

@ -1,9 +1,8 @@
#ifndef DYNAMICLINK_H
#define DYNAMICLINK_H
#include "dolphin/types.h"
#include "dolphin/os/OS.h"
typedef struct OSModuleInfo OSModuleInfo;
class JKRArchive;
class JKRFileCache;
class mDoDvdThd_callback_c;
@ -57,7 +56,7 @@ struct DynamicModuleControl : DynamicModuleControlBase {
static bool initialize();
static bool callback(void*);
/* 0x10 */ OSModuleInfo* mModule;
/* 0x10 */ OSModuleHeader* mModule;
/* 0x14 */ void* mBss;
/* 0x18 */ u32 unk_24;
/* 0x1c */ const char* mName;

View File

@ -20,6 +20,29 @@ extern "C" {
#define DSP_TASK_STATE_YIELD 2
#define DSP_TASK_STATE_DONE 3
#define DSP_MAILBOX_IN_HI (0)
#define DSP_MAILBOX_IN_LO (1)
#define DSP_MAILBOX_OUT_HI (2)
#define DSP_MAILBOX_OUT_LO (3)
#define DSP_CONTROL_STATUS (5)
#define DSP_ARAM_SIZE (9)
#define DSP_ARAM_MODE (11)
#define DSP_ARAM_REFRESH (13)
#define DSP_ARAM_DMA_MM_HI (16) // Main mem address
#define DSP_ARAM_DMA_MM_LO (17)
#define DSP_ARAM_DMA_ARAM_HI (18) // ARAM address
#define DSP_ARAM_DMA_ARAM_LO (19)
#define DSP_ARAM_DMA_SIZE_HI (20) // DMA buffer size
#define DSP_ARAM_DMA_SIZE_LO (21)
#define DSP_DMA_START_HI (24) // DMA start address
#define DSP_DMA_START_LO (25)
#define DSP_DMA_CONTROL_LEN (27)
#define DSP_DMA_BYTES_LEFT (29)
#define DSP_DMA_START_FLAG (0x8000) // set to start DSP
typedef void (*DSPCallback)(void* task);
typedef struct STRUCT_DSP_TASK {

View File

@ -1,5 +1,8 @@
#ifndef DVDFS_H
#define DVDFS_H
#include "dolphin/types.h"
extern u32 __DVDLongFileNameFlag;
#endif /* DVDFS_H */

View File

@ -0,0 +1,109 @@
#ifndef EXIBIOS_H
#define EXIBIOS_H
#include "dolphin/types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OSContext OSContext;
vu32 __EXIRegs[16] : 0xCC006800;
#define EXI_MEMORY_CARD_59 0x00000004
#define EXI_MEMORY_CARD_123 0x00000008
#define EXI_MEMORY_CARD_251 0x00000010
#define EXI_MEMORY_CARD_507 0x00000020
#define EXI_MEMORY_CARD_1019 0x00000040
#define EXI_MEMORY_CARD_2043 0x00000080
#define EXI_MEMORY_CARD_1019A 0x00000140
#define EXI_MEMORY_CARD_1019B 0x00000240
#define EXI_MEMORY_CARD_1019C 0x00000340
#define EXI_MEMORY_CARD_1019D 0x00000440
#define EXI_MEMORY_CARD_1019E 0x00000540
#define EXI_MEMORY_CARD_1019F 0x00000640
#define EXI_MEMORY_CARD_1019G 0x00000740
#define EXI_MEMORY_CARD_2043A 0x00000180
#define EXI_MEMORY_CARD_2043B 0x00000280
#define EXI_MEMORY_CARD_2043C 0x00000380
#define EXI_MEMORY_CARD_2043D 0x00000480
#define EXI_MEMORY_CARD_2043E 0x00000580
#define EXI_MEMORY_CARD_2043F 0x00000680
#define EXI_MEMORY_CARD_2043G 0x00000780
#define EXI_USB_ADAPTER 0x01010000
#define EXI_NPDP_GDEV 0x01020000
#define EXI_MODEM 0x02020000
#define EXI_ETHER 0x04020200
#define EXI_ETHER_VIEWER 0x04220001
#define EXI_STREAM_HANGER 0x04130000
#define EXI_MARLIN 0x03010000
#define EXI_IS_VIEWER 0x05070000
#define EXI_FREQ_1M 0
#define EXI_FREQ_2M 1
#define EXI_FREQ_4M 2
#define EXI_FREQ_8M 3
#define EXI_FREQ_16M 4
#define EXI_FREQ_32M 5
#define EXI_READ 0
#define EXI_WRITE 1
#define EXI_STATE_IDLE 0x00
#define EXI_STATE_DMA 0x01
#define EXI_STATE_IMM 0x02
#define EXI_STATE_BUSY (EXI_STATE_DMA | EXI_STATE_IMM)
#define EXI_STATE_SELECTED 0x04
#define EXI_STATE_ATTACHED 0x08
#define EXI_STATE_LOCKED 0x10
typedef void (*EXICallback)(s32 chan, OSContext* context);
typedef struct EXIControl {
EXICallback exiCallback;
EXICallback tcCallback;
EXICallback extCallback;
vu32 state;
int immLen;
u8* immBuf;
u32 dev;
u32 id;
s32 idTime;
int items;
struct {
u32 dev;
EXICallback callback;
} queue[3];
} EXIControl;
s32 EXIImm(s32 chan, void* buf, s32 len, u32 type, EXICallback callback);
s32 EXIImmEx(s32 chan, void* buf, s32 len, u32 mode);
BOOL EXIDma(s32 chan, void* buf, s32 len, u32 type, EXICallback callback);
BOOL EXISync(s32 chan);
EXICallback EXISetExiCallback(s32 chan, EXICallback exiCallback);
BOOL EXIProbe(s32 chan);
s32 EXIProbeEx(s32 chan);
BOOL EXIAttach(s32 chan, EXICallback extCallback);
BOOL EXIDetach(s32 chan);
BOOL EXISelect(s32 chan, u32 dev, u32 freq);
BOOL EXIDeselect(s32 chan);
void EXIInit(void);
BOOL EXILock(s32 chan, u32 dev, EXICallback unlockedCallback);
BOOL EXIUnlock(s32 chan);
u32 EXIGetState(s32 chan);
static void UnlockedHandler(s32 chan, OSContext* context);
s32 EXIGetID(s32 chan, u32 dev, u32* id);
#ifdef __cplusplus
};
#endif
#endif /* EXIBIOS_H */

View File

@ -0,0 +1,5 @@
#ifndef EXIUART_H
#define EXIUART_H
#endif /* EXIUART_H */

View File

@ -88,11 +88,16 @@ extern u8 __OSReport_Warning_disable;
extern u8 __OSReport_System_disable;
extern u8 __OSReport_enable;
extern BOOL __OSIsGcam;
extern u32 BOOT_REGION_START : 0x8044babc;
extern u32 BOOT_REGION_END : 0x812FDFEC;
void OSReportInit__Fv(void); // needed for inline asm
u8* OSGetStackPointer(void);
void __OSFPRInit(void);
static void InquiryCallback(u32 param_0, DVDCommandBlock* param_1);
static void InquiryCallback(s32 param_0, DVDCommandBlock* param_1);
void OSInit(void);
static void OSExceptionInit(void);
void __OSDBIntegrator(void);
@ -147,7 +152,7 @@ inline void OSf32tou8(f32* f, u8* out) {
*out = __OSf32tou8(*f);
}
inline void OSInitFastCast(void) {
static inline void OSInitFastCast(void) {
// clang-format off
asm {
li r3, 4
@ -178,16 +183,6 @@ typedef struct OSBootInfo {
/* 0x3C */ u32 fst_max_length;
} OSBootInfo;
typedef struct {
BOOL valid;
u32 restartCode;
u32 bootDol;
void* regionStart;
void* regionEnd;
BOOL argsUseDefault;
void* argsAddr; // valid only when argsUseDefault = FALSE
} OSExecParams;
typedef struct BI2Debug {
/* 0x00 */ s32 debugMonSize;
/* 0x04 */ s32 simMemSize;
@ -234,7 +229,7 @@ struct GLOBAL_MEMORY {
u8 padding_0x30e0[4];
u32 field_0x30e4; /* __OSPADButton */
u8 padding_0x30ec[8];
u32 field_0x30f0; /* DOL Execute Parameters */
OSExecParams* field_0x30f0; /* DOL Execute Parameters */
u8 padding_0x30f4[12];
u32 field_0x3100; /* Physical MEM1 size */
u32 field_0x3104; /* Simulated MEM1 size */
@ -292,6 +287,7 @@ struct GLOBAL_MEMORY {
#define OSUncachedToCached(ucaddr) ((void*)((u8*)(ucaddr) - (OS_BASE_UNCACHED - OS_BASE_CACHED)))
extern OSTime __OSStartTime;
extern BOOL __OSInIPL;
#ifdef __cplusplus
};

View File

@ -7,14 +7,23 @@
extern "C" {
#endif
typedef struct {
/* 0x00 */ BOOL valid;
/* 0x04 */ u32 restartCode;
/* 0x08 */ u32 bootDol;
/* 0x0C */ void* regionStart;
/* 0x10 */ void* regionEnd;
/* 0x18 */ BOOL argsUseDefault;
/* 0x14 */ void* argsAddr; // valid only when argsUseDefault = FALSE
} OSExecParams;
static s32 PackArgs(void* param_0, u32 param_1, void* param_2);
static void Run(void);
static void Run(int param_0);
static void ReadDisc(void* param_0, s32 param_1, s32 param_2);
static void Callback(void);
void __OSGetExecParams(void* param_0);
static void GetApploaderPosition(void);
void __OSGetExecParams(OSExecParams* param_0);
void __OSBootDolSimple(u32 param_0, u32 param_1, void* param_2, void* param_3, s32 param_4, u32 param_5, void* param_6);
void __OSBootDol(s32 param_0, u32 param_1, s32 param_2);
void __OSBootDol(s32 param_0, u32 param_1, char** param_2);
#ifdef __cplusplus
};

View File

@ -7,9 +7,45 @@
extern "C" {
#endif
static u32 GetFontCode(s16 param_0, u32 param_1);
typedef enum {
OS_FONT_ENCODE_ANSI,
OS_FONT_ENCODE_SJIS,
OS_FONT_ENCODE_2,
OS_FONT_ENCODE_UTF8,
OS_FONT_ENCODE_UTF16,
OS_FONT_ENCODE_UTF32,
OS_FONT_ENCODE_MAX
} OSFontEncode;
typedef struct OSFontHeader {
/* 0x00 */ u16 type;
/* 0x02 */ u16 firstChar;
/* 0x04 */ u16 lastChar;
/* 0x06 */ u16 invalidChar;
/* 0x08 */ u16 ascent;
/* 0x0A */ u16 descent;
/* 0x0C */ u16 width;
/* 0x0E */ u16 leading;
/* 0x10 */ u16 cellWidth;
/* 0x12 */ u16 cellHeight;
/* 0x14 */ u32 sheetSize;
/* 0x18 */ u16 sheetFormat;
/* 0x1A */ u16 sheetNumCol;
/* 0x1C */ u16 sheetNumRow;
/* 0x1E */ u16 sheetWidth;
/* 0x20 */ u16 sheetHeight;
/* 0x22 */ u16 widthTableOfs;
/* 0x24 */ u32 sheetImageOfs;
/* 0x28 */ u32 sheetFullSize;
/* 0x2C */ u8 c0;
/* 0x2D */ u8 c1;
/* 0x2E */ u8 c2;
/* 0x2F */ u8 c3;
} OSFontHeader;
static u32 GetFontCode(u16 param_0, u16 param_1);
u16 OSGetFontEncode(void);
static char* ParseStringS(s16 param_0, char* param_1, void* param_2, u32* param_3, u32 param_4, void* param_5);
static const u8* ParseStringS(u16 encode, const u8* str, OSFontHeader** fontOut, u32* codeOut);
#ifdef __cplusplus
};

View File

@ -53,15 +53,18 @@ typedef enum {
#define OS_INTERRUPTMASK_MEM_2 OS_INTERRUPTMASK(OS_INTR_MEM_2)
#define OS_INTERRUPTMASK_MEM_3 OS_INTERRUPTMASK(OS_INTR_MEM_3)
#define OS_INTERRUPTMASK_MEM_ADDRESS OS_INTERRUPTMASK(OS_INTR_MEM_ADDRESS)
#define OS_INTERRUPTMASK_MEM_RESET \
(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | \
OS_INTERRUPTMASK_MEM_3)
#define OS_INTERRUPTMASK_MEM \
(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | \
OS_INTERRUPTMASK_MEM_3 | OS_INTERRUPTMASK_MEM_ADDRESS)
(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | \
OS_INTERRUPTMASK_MEM_3 | OS_INTERRUPTMASK_MEM_ADDRESS)
#define OS_INTERRUPTMASK_DSP_AI OS_INTERRUPTMASK(OS_INTR_DSP_AI)
#define OS_INTERRUPTMASK_DSP_ARAM OS_INTERRUPTMASK(OS_INTR_DSP_ARAM)
#define OS_INTERRUPTMASK_DSP_DSP OS_INTERRUPTMASK(OS_INTR_DSP_DSP)
#define OS_INTERRUPTMASK_DSP \
(OS_INTERRUPTMASK_DSP_AI | OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP)
(OS_INTERRUPTMASK_DSP_AI | OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP)
#define OS_INTERRUPTMASK_AI_AI OS_INTERRUPTMASK(OS_INTR_AI_AI)
#define OS_INTERRUPTMASK_AI (OS_INTERRUPTMASK_AI_AI)
@ -70,21 +73,21 @@ typedef enum {
#define OS_INTERRUPTMASK_EXI_0_TC OS_INTERRUPTMASK(OS_INTR_EXI_0_TC)
#define OS_INTERRUPTMASK_EXI_0_EXT OS_INTERRUPTMASK(OS_INTR_EXI_0_EXT)
#define OS_INTERRUPTMASK_EXI_0 \
(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT)
(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT)
#define OS_INTERRUPTMASK_EXI_1_EXI OS_INTERRUPTMASK(OS_INTR_EXI_1_EXI)
#define OS_INTERRUPTMASK_EXI_1_TC OS_INTERRUPTMASK(OS_INTR_EXI_1_TC)
#define OS_INTERRUPTMASK_EXI_1_EXT OS_INTERRUPTMASK(OS_INTR_EXI_1_EXT)
#define OS_INTERRUPTMASK_EXI_1 \
(OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT)
(OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT)
#define OS_INTERRUPTMASK_EXI_2_EXI OS_INTERRUPTMASK(OS_INTR_EXI_2_EXI)
#define OS_INTERRUPTMASK_EXI_2_TC OS_INTERRUPTMASK(OS_INTR_EXI_2_TC)
#define OS_INTERRUPTMASK_EXI_2 (OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC)
#define OS_INTERRUPTMASK_EXI \
(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT | \
OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT | \
OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC)
(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT | \
OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT | \
OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC)
#define OS_INTERRUPTMASK_PI_PE_TOKEN OS_INTERRUPTMASK(OS_INTR_PI_PE_TOKEN)
#define OS_INTERRUPTMASK_PI_PE_FINISH OS_INTERRUPTMASK(OS_INTR_PI_PE_FINISH)
@ -99,27 +102,27 @@ typedef enum {
#define OS_INTERRUPTMASK_PI_DEBUG OS_INTERRUPTMASK(OS_INTR_PI_DEBUG)
#define OS_INTERRUPTMASK_PI_HSP OS_INTERRUPTMASK(OS_INTR_PI_HSP)
#define OS_INTERRUPTMASK_PI \
(OS_INTERRUPTMASK_PI_CP | OS_INTERRUPTMASK_PI_SI | OS_INTERRUPTMASK_PI_DI | \
OS_INTERRUPTMASK_PI_RSW | OS_INTERRUPTMASK_PI_ERROR | OS_INTERRUPTMASK_PI_VI | \
OS_INTERRUPTMASK_PI_PE_TOKEN | OS_INTERRUPTMASK_PI_PE_FINISH | OS_INTERRUPTMASK_PI_DEBUG | \
OS_INTERRUPTMASK_PI_HSP)
(OS_INTERRUPTMASK_PI_CP | OS_INTERRUPTMASK_PI_SI | OS_INTERRUPTMASK_PI_DI | \
OS_INTERRUPTMASK_PI_RSW | OS_INTERRUPTMASK_PI_ERROR | OS_INTERRUPTMASK_PI_VI | \
OS_INTERRUPTMASK_PI_PE_TOKEN | OS_INTERRUPTMASK_PI_PE_FINISH | OS_INTERRUPTMASK_PI_DEBUG | \
OS_INTERRUPTMASK_PI_HSP)
typedef s16 OSInterrupt;
typedef s16 __OSInterrupt;
typedef u32 OSInterruptMask;
typedef void (*OSInterruptHandler)(OSInterrupt interrupt, OSContext* context);
typedef void (*__OSInterruptHandler)(__OSInterrupt interrupt, OSContext* context);
BOOL OSDisableInterrupts(void);
void __RAS_OSDisableInterrupts_end(void);
BOOL OSEnableInterrupts(void);
BOOL OSRestoreInterrupts(BOOL enable);
OSInterruptHandler __OSSetInterruptHandler(OSInterrupt interrupt, OSInterruptHandler handler);
OSInterruptHandler __OSGetInterruptHandler(s16 index);
__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, __OSInterruptHandler handler);
__OSInterruptHandler __OSGetInterruptHandler(s16 index);
void __OSInterruptInit(void);
static OSInterruptMask SetInterruptMask(OSInterruptMask param_0, OSInterruptMask param_1);
OSInterruptMask __OSMaskInterrupts(OSInterruptMask mask);
OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask mask);
void __OSDispatchInterrupt(u8 interrupt, OSContext* context);
static void ExternalInterruptHandler(OSInterrupt interrupt, OSContext* context);
static void ExternalInterruptHandler(__OSInterrupt interrupt, OSContext* context);
void __RAS_OSDisableInterrupts_begin(void);
void __RAS_OSDisableInterrupts_end(void);

View File

@ -1,61 +1,106 @@
#ifndef OSLINK_H
#define OSLINK_H
#include "dolphin/types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OSModuleQueue {
int* first;
int* last;
} OSModuleQueue;
#define OS_MODULE_VERSION 3
typedef struct OSModuleHeader OSModuleHeader;
typedef u32 OSModuleID;
typedef struct OSModuleQueue OSModuleQueue;
typedef struct OSModuleLink OSModuleLink;
typedef struct OSModuleInfo OSModuleInfo;
typedef struct OSSectionInfo OSSectionInfo;
typedef struct OSImportInfo OSImportInfo;
typedef struct OSRel OSRel;
OSModuleQueue __OSModuleList : 0x800030C8;
void* __OSStringTable : 0x800030D0;
typedef struct OSSectionInfo {
u32 mOffset;
u32 mSize;
} OSSectionInfo;
struct OSModuleQueue {
OSModuleInfo* head;
OSModuleInfo* tail;
};
typedef struct OSModuleInfo {
u32 mId;
u32 mNext;
u32 mPrev;
u32 mNumSections;
struct { // Needed to get an assert correct; very likely bigger
u32 sectionInfoOffset;
} info;
u32 mModuleNameOffset;
u32 mModuleNameSize;
u32 mModuleVersion;
u32 mBssSize;
u32 mRelocationTableOffset;
u32 mImportTableOffset;
u32 mImportTableSize;
u8 mPrologSection;
u8 mEpilogSection;
u8 mUnresolvedSection;
u8 mBssSection;
u32 prolog;
u32 epilog;
u32 mUnresolvedFuncOffset;
u32 mModuleAlignment;
u32 mBssAlignment;
struct OSModuleLink {
OSModuleInfo* next;
OSModuleInfo* prev;
};
struct OSSectionInfo {
u32 offset;
u32 size;
};
struct OSModuleInfo {
OSModuleID id; // unique identifier for the module
OSModuleLink link; // doubly linked list of modules
u32 numSections; // # of sections
u32 sectionInfoOffset; // offset to section info table
u32 nameOffset; // offset to module name
u32 nameSize; // size of module name
u32 version; // version number
};
struct OSModuleHeader {
// CAUTION: info must be the 1st member
OSModuleInfo info;
// OS_MODULE_VERSION == 1
u32 bssSize; // total size of bss sections in bytes
u32 relOffset;
u32 impOffset;
u32 impSize; // size in bytes
u8 prologSection; // section # for prolog function
u8 epilogSection; // section # for epilog function
u8 unresolvedSection; // section # for unresolved function
u8 bssSection; // section # for bss section (set at run-time)
u32 prolog; // prolog function offset
u32 epilog; // epilog function offset
u32 unresolved; // unresolved function offset
// OS_MODULE_VERSION == 2
#if (2 <= OS_MODULE_VERSION)
u32 align; // module alignment constraint
u32 bssAlign; // bss alignment constraint
#endif
// OS_MODULE_VERSION == 3
#if (3 <= OS_MODULE_VERSION)
u32 fixSize;
} OSModuleInfo;
#endif
};
BOOL OSLink(OSModuleInfo* module);
BOOL OSLinkFixed(OSModuleInfo* module, u32 param_1);
#define OSGetSectionInfo(module) ((OSSectionInfo*)(((OSModuleInfo*)(module))->sectionInfoOffset))
#define OS_SECTIONINFO_EXEC 0x1
#define OS_SECTIONINFO_OFFSET(offset) ((offset) & ~0x1)
struct OSImportInfo {
OSModuleID id; // external module id
u32 offset; // offset to OSRel instructions
};
struct OSRel {
u16 offset; // byte offset from the previous entry
u8 type;
u8 section;
u32 addend;
};
#define R_DOLPHIN_NOP 201 // C9h current offset += OSRel.offset
#define R_DOLPHIN_SECTION 202 // CAh current section = OSRel.section
#define R_DOLPHIN_END 203 // CBh
#define R_DOLPHIN_MRKREF 204 // CCh
BOOL OSLink(OSModuleInfo* newModule, void* bss);
BOOL OSLinkFixed(OSModuleInfo* newModule, void* bss);
BOOL OSUnlink(OSModuleInfo* module);
static void OSNotifyLink(void);
static void OSNotifyUnlink(void);
void OSSetStringTable(void* string_table);
static BOOL Relocate(OSModuleInfo* param_0, OSModuleInfo* param_1);
static BOOL Link(OSModuleInfo* module, u32 param_1);
static BOOL Undo(OSModuleInfo* param_0, OSModuleInfo* param_1);
void __OSModuleInit(void);
#ifdef __cplusplus

View File

@ -18,7 +18,7 @@ extern "C" {
#define OS_PROTECT_CONTROL_RDWR (OS_PROTECT_CONTROL_READ | OS_PROTECT_CONTROL_WRITE)
u32 OSGetConsoleSimulatedMemSize();
static void MEMIntrruptHandler(OSInterrupt interrupt, struct OSContext* context);
static void MEMIntrruptHandler(__OSInterrupt interrupt, struct OSContext* context);
void OSProtectRange(u32 channel, void* address, u32 nBytes, u32 control);
static void Config24MB(void);
static void Config48MB(void);

View File

@ -22,6 +22,10 @@ typedef struct OSMessageQueue {
#define OS_MESSAGE_NOBLOCK 0
#define OS_MESSAGE_BLOCK 1
typedef enum {
OS_MSG_PERSISTENT = (1 << 0),
} OSMessageFlags;
void OSInitMessageQueue(OSMessageQueue* queue, OSMessage* msgArray, s32 msgCount);
BOOL OSSendMessage(OSMessageQueue* queue, OSMessage msg, s32 flags);
BOOL OSReceiveMessage(OSMessageQueue* queue, OSMessage* msg, s32 flags);

View File

@ -28,7 +28,7 @@ vu32 __PIRegs[12] : 0xCC003000;
#define OS_RESET_PRIO_GX 127
#define OS_RESET_PRIO_ALARM 4294967295
typedef s32 (*OSResetFunction)(s32);
typedef BOOL (*OSResetFunction)(BOOL final);
typedef struct OSResetFunctionInfo {
/* 0x0 */ OSResetFunction func;

View File

@ -1,7 +1,7 @@
#ifndef OSRESETSW_H
#define OSRESETSW_H
#include "dolphin/types.h"
#include "dolphin/os/OSInterrupt.h"
#ifdef __cplusplus
extern "C" {
@ -11,6 +11,7 @@ typedef void (*OSResetCallback)(void);
static BOOL OSGetResetButtonState(void);
BOOL OSGetResetSwitchState(void);
void __OSResetSWInterruptHandler(__OSInterrupt interrupt, OSContext* context);
#ifdef __cplusplus
};

View File

@ -68,7 +68,7 @@ struct OSThread {
OSMutexQueue owned_mutexes;
OSThreadLink active_threads_link;
u8* stack_base;
u8* stack_end;
u32* stack_end;
u8* error_code;
void* data[2];
};

View File

@ -1,5 +0,0 @@
#ifndef __PPC_EABI_INIT_H
#define __PPC_EABI_INIT_H
#endif /* __PPC_EABI_INIT_H */

View File

@ -76,6 +76,8 @@ static void PADProbeCallback(s32 chan, u32 error, OSContext* context);
static void PADTypeAndStatusCallback(s32 chan, u32 type);
static void PADReceiveCheckCallback(s32 chan, u32 type);
extern u32 __PADSpec;
#ifdef __cplusplus
};
#endif

View File

@ -102,10 +102,10 @@ typedef union SIComm_u {
BOOL SIBusy(void);
BOOL SIIsChanBusy(s32 chan);
static void SIInterruptHandler(OSInterrupt interrupt, OSContext* context);
static void SIInterruptHandler(__OSInterrupt interrupt, OSContext* context);
static BOOL SIEnablePollingInterrupt(BOOL enable);
BOOL SIRegisterPollingHandler(OSInterruptHandler handler);
BOOL SIUnregisterPollingHandler(OSInterruptHandler handler);
BOOL SIRegisterPollingHandler(__OSInterruptHandler handler);
BOOL SIUnregisterPollingHandler(__OSInterruptHandler handler);
void SIInit(void);
u32 SIGetStatus(s32 chan);
void SISetCommand(s32 chan, u32 command);

View File

@ -4,14 +4,12 @@
*/
#include "DynamicLink.h"
#include "JSystem/JKernel/JKRArchive.h"
#include "JSystem/JKernel/JKRDvdRipper.h"
#include "JSystem/JKernel/JKRExpHeap.h"
#include "JSystem/JKernel/JKRFileCache.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTConsole.h"
#include "stdio.h"
#include "REL/executor.h"
#include "m_Do/m_Do_dvd_thread.h"
#include "m_Do/m_Do_ext.h"
#include "m_Do/m_Do_printf.h"
@ -51,8 +49,6 @@ DynamicModuleControlBase::DynamicModuleControlBase() {
mLast = this;
}
extern OSThread mainThread;
BOOL DynamicModuleControlBase::link() {
OSThread* thread = OSGetCurrentThread();
if (thread != &mainThread) {
@ -64,12 +60,12 @@ BOOL DynamicModuleControlBase::link() {
if (do_link() == false) {
return false;
}
if (mDoLinkCount < 65535) {
if (mDoLinkCount < 0xFFFF) {
mDoLinkCount++;
}
}
JUT_ASSERT(100, mLinkCount < 65535);
if (mLinkCount < 65535) {
if (mLinkCount < 0xFFFF) {
mLinkCount++;
}
return true;
@ -212,19 +208,19 @@ bool DynamicModuleControl::do_load() {
snprintf(buffer, 64, "%s.rel", mName);
if (mModule == NULL && sArchive != NULL) {
if (mModule == NULL) {
mModule = (OSModuleInfo*)JKRGetResource('MMEM', buffer, sArchive);
mModule = (OSModuleHeader*)JKRGetResource('MMEM', buffer, sArchive);
if (mModule != NULL) {
mResourceType = 1;
}
}
if (mModule == NULL) {
mModule = (OSModuleInfo*)JKRGetResource('AMEM', buffer, sArchive);
mModule = (OSModuleHeader*)JKRGetResource('AMEM', buffer, sArchive);
if (mModule != NULL) {
mResourceType = 2;
}
}
if (mModule == NULL) {
mModule = (OSModuleInfo*)JKRGetResource('DMEM', buffer, sArchive);
mModule = (OSModuleHeader*)JKRGetResource('DMEM', buffer, sArchive);
if (mModule != NULL) {
mResourceType = 3;
}
@ -236,7 +232,7 @@ bool DynamicModuleControl::do_load() {
} else {
if (mModule == NULL) {
snprintf(buffer, 64, "/rels/%s.rel", mName);
mModule = (OSModuleInfo*)JKRDvdToMainRam(
mModule = (OSModuleHeader*)JKRDvdToMainRam(
buffer, NULL, EXPAND_SWITCH_UNKNOWN1, NULL, archiveHeap,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, 0, NULL);
if (mModule != NULL) {
@ -245,7 +241,7 @@ bool DynamicModuleControl::do_load() {
}
}
if (mModule == NULL && sFileCache != NULL) {
mModule = (OSModuleInfo*)sFileCache->getResource('rels', buffer);
mModule = (OSModuleHeader*)sFileCache->getResource('rels', buffer);
if (mModule != NULL) {
mSize = 0;
mResourceType = 11;
@ -254,7 +250,7 @@ bool DynamicModuleControl::do_load() {
}
}
if (mModule == NULL) {
// "DynamicModuleControl::do_load() Resource loading failure [%s]\n"
// "DynamicModuleControl::do_load() Resource load failure [%s]\n"
OSReport_Error("DynamicModuleControl::do_load() リソース読み込み失敗 [%s]\n", mName);
return false;
}
@ -297,8 +293,7 @@ BOOL DynamicModuleControl::do_load_async() {
if (mModule != NULL) {
return true;
}
mAsyncLoadCallback = mDoDvdThd_callback_c::create(
(mDoDvdThd_callback_func)DynamicModuleControl::callback, this);
mAsyncLoadCallback = mDoDvdThd_callback_c::create((mDoDvdThd_callback_func)DynamicModuleControl::callback, this);
if (mAsyncLoadCallback == NULL) {
OSReport_Error(
// "DynamicModuleControl::do_load_async() async load callback entry failure [%s]\n"
@ -326,9 +321,9 @@ bool DynamicModuleControl::do_unload() {
void DynamicModuleControl::dump2() {
if (mModule != NULL) {
OSSectionInfo* section = (OSSectionInfo*)mModule->info.sectionInfoOffset;
OSReport("mModule=%08x %08x %08x %08x %08x\n", mModule, section[1].mOffset & ~1,
section[1].mSize, mModule->mImportTableOffset - mModule->mRelocationTableOffset,
mModule->mImportTableSize);
OSReport("mModule=%08x %08x %08x %08x %08x\n", mModule, section[1].offset & ~1,
section[1].size, mModule->impOffset - mModule->relOffset,
mModule->impSize);
}
}
@ -342,57 +337,57 @@ BOOL DynamicModuleControl::do_link() {
JUT_ASSERT(615, (u32)mModule + mModule->fixSize < 0x82000000);
OSGetTime();
OSGetTime();
if (mModule->mModuleVersion >= 3) {
if (mModule->info.version >= 3) {
u32 fixSizePtr;
u32 fixSize = mModule->fixSize;
u32 fixSize2 = (fixSize + 0x1f) & ~0x1f;
fixSizePtr = (u32)mModule + fixSize2;
s32 size = JKRGetMemBlockSize(NULL, mModule);
if (size < 0) {
void* bss = JKRAlloc(mModule->mBssSize, 0x20);
void* bss = JKRAlloc(mModule->bssSize, 0x20);
if (bss == NULL) {
// "BSS Memory allocation failed\n"
OSReport_Error("BSSメモリ確保失敗\n", bss);
goto error;
}
mBss = bss;
BOOL linkResult = OSLink(mModule);
BOOL linkResult = OSLink(&mModule->info, bss);
if (linkResult == FALSE) {
// "link failed\n"
OSReport_Error("リンク失敗\n");
goto error;
}
} else {
if (fixSize2 + mModule->mBssSize < size) {
BOOL linkResult = OSLinkFixed(mModule, fixSizePtr);
if (fixSize2 + mModule->bssSize < size) {
BOOL linkResult = OSLinkFixed(&mModule->info, (void*)fixSizePtr);
if (linkResult == FALSE) {
// "link failed\n"
OSReport_Error("リンク失敗\n");
goto error;
}
s32 result = JKRResizeMemBlock(NULL, mModule, fixSize2 + mModule->mBssSize);
s32 result = JKRResizeMemBlock(NULL, mModule, fixSize2 + mModule->bssSize);
if (result < 0) {
// "Module size (resize) failed\n"
OSReport_Error("モジュールリサイズ(縮小)失敗\n");
}
} else {
s32 result = JKRResizeMemBlock(NULL, mModule, fixSize2 + mModule->mBssSize);
s32 result = JKRResizeMemBlock(NULL, mModule, fixSize2 + mModule->bssSize);
if (result > 0) {
BOOL linkResult = OSLinkFixed(mModule, fixSizePtr);
BOOL linkResult = OSLinkFixed(&mModule->info, (void*)fixSizePtr);
if (linkResult == FALSE) {
// "link failed\n"
OSReport_Error("リンク失敗\n");
goto error;
}
} else {
void* bss = JKRAlloc(mModule->mBssSize, 0x20);
void* bss = JKRAlloc(mModule->bssSize, 0x20);
if (bss == NULL) {
// "BSS Memory allocation failure [%x]\n"
OSReport_Error("BSSメモリ確保失敗 [%x]\n", mModule->mBssSize);
OSReport_Error("BSSメモリ確保失敗 [%x]\n", mModule->bssSize);
goto error;
}
mBss = bss;
BOOL linkResult = OSLinkFixed(mModule, (u32)bss);
BOOL linkResult = OSLinkFixed(&mModule->info, bss);
if (linkResult == FALSE) {
// "link failed\n"
OSReport_Error("リンク失敗\n");
@ -434,7 +429,7 @@ bool DynamicModuleControl::do_unlink() {
OSTime time1 = OSGetTime();
((void (*)())mModule->epilog)();
OSTime time2 = OSGetTime();
BOOL unklink = OSUnlink(mModule);
BOOL unklink = OSUnlink(&mModule->info);
OSTime time3 = OSGetTime();
if (unklink == FALSE) {
// "Unlink failed mModule=%08x mBss=%08x\n"
@ -456,7 +451,7 @@ int DynamicModuleControl::getModuleSize() const {
if (mBss != NULL) {
JKRGetMemBlockSize(NULL, mBss);
}
return size + mModule->mBssSize;
return size + mModule->bssSize;
} else {
return 0;
}
@ -467,15 +462,15 @@ const char* DynamicModuleControl::getModuleTypeString() const {
return strings[mResourceType & 3];
}
void ModuleProlog() {
extern "C" void ModuleProlog() {
/* empty function */
}
void ModuleEpilog() {
extern "C" void ModuleEpilog() {
/* empty function */
}
void ModuleUnresolved() {
extern "C" void ModuleUnresolved() {
// "\nError: Unlinked function was called.\n"
OSReport_Error("\nError: リンクされていない関数が呼び出されました.\n");
OSReport_Error("Address: Back Chain LR Save\n");
@ -488,7 +483,7 @@ void ModuleUnresolved() {
OSReport_Error("\n");
}
void ModuleConstructorsX(const VoidFunc* _ctors) {
extern "C" void ModuleConstructorsX(void (**_ctors)()) {
JUT_ASSERT(850, _ctors);
while (*_ctors != 0) {
(**_ctors)();
@ -496,7 +491,7 @@ void ModuleConstructorsX(const VoidFunc* _ctors) {
}
}
void ModuleDestructorsX(const VoidFunc* _dtors) {
extern "C" void ModuleDestructorsX(void (**_dtors)()) {
JUT_ASSERT(864, _dtors);
while (*_dtors != 0) {
(**_dtors)();

View File

@ -265,20 +265,20 @@ bool JUTException::searchPartialModule(u32 address, u32* module_id, u32* section
}
OSModuleInfo* module = *(OSModuleInfo**)0x800030C8;
for (; module != NULL; module = (OSModuleInfo*)module->mNext) {
OSSectionInfo* section = (OSSectionInfo*)module->info.sectionInfoOffset;
for (u32 i = 0; i < module->mNumSections; section++, i++) {
if (section->mSize != 0) {
u32 addr = section->mOffset & ~0x01;
if ((addr <= address) && (address < addr + section->mSize)) {
for (; module != NULL; module = (OSModuleInfo*)module->link.next) {
OSSectionInfo* section = (OSSectionInfo*)module->sectionInfoOffset;
for (u32 i = 0; i < module->numSections; section++, i++) {
if (section->size != 0) {
u32 addr = section->offset & ~0x01;
if ((addr <= address) && (address < addr + section->size)) {
if (module_id)
*module_id = module->mId;
*module_id = module->id;
if (section_id)
*section_id = i;
if (section_offset)
*section_offset = address - addr;
if (name_offset)
*name_offset = module->mModuleNameOffset;
*name_offset = module->nameOffset;
return true;
}
}

View File

@ -4,7 +4,7 @@ static GBASecParam SecParams[4];
GBAControl __GBA[4];
BOOL __GBAReset = FALSE;
static s32 OnReset(s32);
static BOOL OnReset(BOOL final);
static OSResetFunctionInfo ResetFunctionInfo = {OnReset, 127};
@ -87,7 +87,7 @@ s32 GBAReset(s32 chan, u8* status) {
return __GBASync(chan);
}
s32 OnReset(s32) {
BOOL OnReset(BOOL final) {
__GBAReset = TRUE;
return TRUE;
}

661
src/dolphin/os/OS.c Normal file
View File

@ -0,0 +1,661 @@
//
// OS
//
#include "dolphin/os/OS.h"
#include "dolphin/base/PPCArch.h"
// #include "dolphin/db.h"
#include "dolphin/pad/Pad.h"
#include "dolphin/dvd/dvdfs.h"
// #include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.h"
#define OS_BI2_DEBUG_ADDRESS 0x800000F4
#define OS_BI2_DEBUGFLAG_OFFSET 0xC
#define PAD3_BUTTON_ADDR 0x800030E4
#define OS_DVD_DEVICECODE 0x800030E6
#define DEBUGFLAG_ADDR 0x800030E8
#define OS_DEBUG_ADDRESS_2 0x800030E9
#define DB_EXCEPTIONRET_OFFSET 0xC
#define DB_EXCEPTIONDEST_OFFSET 0x8
#define OS_EXCEPTIONTABLE_ADDR 0x3000
#define OS_DBJUMPPOINT_ADDR 0x60
#define OS_CURRENTCONTEXT_PADDR 0xC0
//
// External References:
//
void _epilog();
static OSBootInfo* BootInfo;
static volatile u32* BI2DebugFlag;
static u32* BI2DebugFlagHolder;
OSTime __OSStartTime;
BOOL __OSInIPL;
extern OSExceptionHandler* OSExceptionTable;
OSExceptionHandler* OSExceptionTable;
extern BOOL AreWeInitialized;
BOOL AreWeInitialized;
extern f64 ZeroPS;
f64 ZeroPS;
extern f64 ZeroF;
f64 ZeroF;
BOOL __OSIsGcam;
asm void __OSFPRInit(void) {
// clang-format off
nofralloc
mfmsr r3
ori r3, r3, 0x2000
mtmsr r3
mfspr r3, 0x398
rlwinm. r3, r3, 3, 0x1f, 0x1f
beq skip_ps_init
lis r3, ZeroPS@ha
addi r3, r3, ZeroPS@l
psq_l f0, 0(r3), 0, 0
ps_mr f1, f0
ps_mr f2, f0
ps_mr f3, f0
ps_mr f4, f0
ps_mr f5, f0
ps_mr f6, f0
ps_mr f7, f0
ps_mr f8, f0
ps_mr f9, f0
ps_mr f10, f0
ps_mr f11, f0
ps_mr f12, f0
ps_mr f13, f0
ps_mr f14, f0
ps_mr f15, f0
ps_mr f16, f0
ps_mr f17, f0
ps_mr f18, f0
ps_mr f19, f0
ps_mr f20, f0
ps_mr f21, f0
ps_mr f22, f0
ps_mr f23, f0
ps_mr f24, f0
ps_mr f25, f0
ps_mr f26, f0
ps_mr f27, f0
ps_mr f28, f0
ps_mr f29, f0
ps_mr f30, f0
ps_mr f31, f0
skip_ps_init:
lfd f0, ZeroF(r13)
fmr f1, f0
fmr f2, f0
fmr f3, f0
fmr f4, f0
fmr f5, f0
fmr f6, f0
fmr f7, f0
fmr f8, f0
fmr f9, f0
fmr f10, f0
fmr f11, f0
fmr f12, f0
fmr f13, f0
fmr f14, f0
fmr f15, f0
fmr f16, f0
fmr f17, f0
fmr f18, f0
fmr f19, f0
fmr f20, f0
fmr f21, f0
fmr f22, f0
fmr f23, f0
fmr f24, f0
fmr f25, f0
fmr f26, f0
fmr f27, f0
fmr f28, f0
fmr f29, f0
fmr f30, f0
fmr f31, f0
mtfsf 0xff, f0
blr
// clang-format on
}
u32 OSGetConsoleType(void) {
if (BootInfo == NULL || BootInfo->console_type == 0) {
return OS_CONSOLE_ARTHUR;
}
return BootInfo->console_type;
}
static DVDDriveInfo DriveInfo;
void* __OSSavedRegionStart;
void* __OSSavedRegionEnd;
extern OSExecParams __OSRebootParams;
static inline void ClearArena(void) {
BOOL var_r0;
if (OSGetResetCode() & 0x80000000) {
var_r0 = TRUE;
} else {
var_r0 = FALSE;
}
if (!var_r0) {
memset(OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo());
return;
}
if (*(u32*)&__OSRebootParams.regionStart == 0U) {
memset(OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo());
return;
}
if ((u32)OSGetArenaLo() < *(u32*)&__OSRebootParams.regionStart) {
if ((u32)OSGetArenaHi() <= *(u32*)&__OSRebootParams.regionStart) {
memset((u32)OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo());
return;
}
memset(OSGetArenaLo(), 0U, *(u32*)&__OSRebootParams.regionStart - (u32)OSGetArenaLo());
if ((u32)OSGetArenaHi() > *(u32*)&__OSRebootParams.regionEnd) {
memset(*(u32*)&__OSRebootParams.regionEnd, 0,
(u32)OSGetArenaHi() - *(u32*)&__OSRebootParams.regionEnd);
}
}
}
static void InquiryCallback(s32 result, DVDCommandBlock* block) {
switch (block->state) {
case 0:
__OSDeviceCode = (u16)(0x8000 | DriveInfo.device_code);
break;
default:
__OSDeviceCode = 1;
break;
}
}
static u8 DriveBlock[48];
OSExecParams __OSRebootParams;
static const char* __OSVersion = "<< Dolphin SDK - OS release build: Nov 10 2004 06:26:41 (0x2301) >>";
extern u8 __ArenaHi[];
extern u8 __ArenaLo[];
extern void* _stack_end;
extern char _db_stack_end[];
void OSInit(void) {
/*
Initializes the Dolphin operating system.
- most of the main operations get farmed out to other functions
- loading debug info and setting up heap bounds largely happen here
- a lot of OS reporting also gets controlled here
*/
BI2Debug* DebugInfo;
void* debugArenaLo;
u32 inputConsoleType;
u32 tdev;
if ((BOOL)AreWeInitialized == FALSE) {
AreWeInitialized = TRUE;
// SYSTEM //
__OSStartTime = __OSGetSystemTime();
OSDisableInterrupts();
__OSGetExecParams(&__OSRebootParams);
PPCMtmmcr0(0);
PPCMtmmcr1(0);
PPCMtpmc1(0);
PPCMtpmc2(0);
PPCMtpmc3(0);
PPCMtpmc4(0);
PPCDisableSpeculation();
PPCSetFpNonIEEEMode();
// DEBUG //
BI2DebugFlag = 0; // debug flag from the DVD BI2 header
BootInfo = (OSBootInfo*)OS_BASE_CACHED; // set pointer to BootInfo
__DVDLongFileNameFlag =
(u32)0; // flag to tell us whether we make it through the debug loading
// time to grab a bunch of debug info from the DVD
// the address for where the BI2 debug info is, is stored at OS_BI2_DEBUG_ADDRESS
DebugInfo = (BI2Debug*)*((u32*)OS_BI2_DEBUG_ADDRESS);
if (DebugInfo != NULL) {
BI2DebugFlag = &DebugInfo->debugFlag; // debug flag from DVD BI2
__PADSpec = (u32)DebugInfo->padSpec; // some other info from DVD BI2
*((u8*)DEBUGFLAG_ADDR) = (u8)*BI2DebugFlag; // store flag in mem
*((u8*)OS_DEBUG_ADDRESS_2) = (u8)__PADSpec; // store other info in mem
} else if (BootInfo->arena_hi) {
BI2DebugFlagHolder =
(u32*)*((u8*)DEBUGFLAG_ADDR); // grab whatever's stored at 0x800030E8
BI2DebugFlag = (u32*)&BI2DebugFlagHolder; // flag is then address of flag holder
__PADSpec = (u32) * ((u8*)OS_DEBUG_ADDRESS_2); // pad spec is whatever's at 0x800030E9
}
__DVDLongFileNameFlag = 1;
// HEAP //
OSSetArenaLo((BootInfo->arena_lo == NULL) ? __ArenaLo : BootInfo->arena_lo);
// if the input arenaLo is null, and debug flag location exists (and flag is < 2),
// set arenaLo to just past the end of the db stack
if ((BootInfo->arena_lo == NULL) && (BI2DebugFlag != 0) && (*BI2DebugFlag < 2)) {
debugArenaLo = (char*)(((u32)_db_stack_end + 0x1f) & ~0x1f);
OSSetArenaLo(debugArenaLo);
}
OSSetArenaHi((BootInfo->arena_hi == NULL) ? __ArenaHi : BootInfo->arena_hi);
// OS INIT AND REPORT //
OSExceptionInit();
__OSInitSystemCall();
OSInitAlarm();
__OSModuleInit();
__OSInterruptInit();
__OSSetInterruptHandler(OS_INTR_PI_RSW, (void*)__OSResetSWInterruptHandler);
__OSContextInit();
__OSCacheInit();
EXIInit();
SIInit();
__OSInitSram();
__OSThreadInit();
__OSInitAudioSystem();
PPCMthid2(PPCMfhid2() & 0xBFFFFFFF);
if ((BOOL)__OSInIPL == FALSE) {
__OSInitMemoryProtection();
}
OSReport("\nDolphin OS\n");
OSReport("Kernel built : %s %s\n", "Nov 10 2004", "06:26:41");
OSReport("Console Type : ");
if (BootInfo == NULL || (inputConsoleType = BootInfo->console_type) == 0) {
inputConsoleType = OS_CONSOLE_ARTHUR; // default console type
} else {
inputConsoleType = BootInfo->console_type;
}
switch (inputConsoleType & 0xF0000000) {
case OS_CONSOLE_RETAIL:
OSReport("Retail %d\n", inputConsoleType);
break;
case OS_CONSOLE_DEVELOPMENT:
case OS_CONSOLE_TDEV:
switch (inputConsoleType & 0x0FFFFFFF) {
case OS_CONSOLE_EMULATOR:
OSReport("Mac Emulator\n");
break;
case OS_CONSOLE_PC_EMULATOR:
OSReport("PC Emulator\n");
break;
case OS_CONSOLE_ARTHUR:
OSReport("EPPC Arthur\n");
break;
case OS_CONSOLE_MINNOW:
OSReport("EPPC Minnow\n");
break;
default:
tdev = (u32)inputConsoleType & 0x0FFFFFFF;
OSReport("Development HW%d (%08x)\n", tdev - 3, inputConsoleType);
break;
}
break;
default:
OSReport("%08x\n", inputConsoleType);
break;
}
OSReport("Memory %d MB\n", (u32)BootInfo->memory_size >> 0x14U);
OSReport("Arena : 0x%x - 0x%x\n", OSGetArenaLo(), OSGetArenaHi());
OSRegisterVersion(__OSVersion);
if (BI2DebugFlag && ((*BI2DebugFlag) >= 2)) {
EnableMetroTRKInterrupts();
}
ClearArena();
OSEnableInterrupts();
if ((BOOL)__OSInIPL == FALSE) {
DVDInit();
if ((BOOL)__OSIsGcam) {
__OSDeviceCode = 0x9000;
return;
}
DCInvalidateRange(&DriveInfo, sizeof(DriveInfo));
DVDInquiryAsync((DVDCommandBlock*)&DriveBlock, &DriveInfo, InquiryCallback);
}
}
}
static u32 __OSExceptionLocations[] = {
0x00000100, // 0 System reset
0x00000200, // 1 Machine check
0x00000300, // 2 DSI - seg fault or DABR
0x00000400, // 3 ISI
0x00000500, // 4 External interrupt
0x00000600, // 5 Alignment
0x00000700, // 6 Program
0x00000800, // 7 FP Unavailable
0x00000900, // 8 Decrementer
0x00000C00, // 9 System call
0x00000D00, // 10 Trace
0x00000F00, // 11 Performance monitor
0x00001300, // 12 Instruction address breakpoint.
0x00001400, // 13 System management interrupt
0x00001700 // 14 Thermal interrupt
};
// dummy entry points to the OS Exception vector
void __OSEVStart(void);
void __OSDBINTSTART(void);
void __OSDBINTEND(void);
void __OSDBJUMPSTART(void);
void __OSDBJUMPEND(void);
#define NOP 0x60000000
static void OSExceptionInit(void) {
__OSException exception;
void* destAddr;
// These two vars help us change the exception number embedded
// in the exception handler code.
u32* opCodeAddr;
u32 oldOpCode;
// Address range of the actual code to be copied.
u8* handlerStart;
u32 handlerSize;
// Install the first level exception vector.
opCodeAddr = (u32*)__OSEVSetNumber;
oldOpCode = *opCodeAddr;
handlerStart = (u8*)__OSEVStart;
handlerSize = (u32)((u8*)__OSEVEnd - (u8*)__OSEVStart);
// Install the DB integrator, only if we are the first OSInit to be run
destAddr = (void*)OSPhysicalToCached(OS_DBJUMPPOINT_ADDR);
if (*(u32*)destAddr == 0) // Lomem should be zero cleared only once by BS2
{
DBPrintf("Installing OSDBIntegrator\n");
memcpy(destAddr, (void*)__OSDBINTSTART, (u32)__OSDBINTEND - (u32)__OSDBINTSTART);
DCFlushRangeNoSync(destAddr, (u32)__OSDBINTEND - (u32)__OSDBINTSTART);
__sync();
ICInvalidateRange(destAddr, (u32)__OSDBINTEND - (u32)__OSDBINTSTART);
}
// Copy the right vector into the table
for (exception = 0; exception < 15; exception++) {
if (BI2DebugFlag && (*BI2DebugFlag >= 2) && __DBIsExceptionMarked(exception)) {
// this DBPrintf is suspicious.
DBPrintf(">>> OSINIT: exception %d commandeered by TRK\n", exception);
continue;
}
// Modify the copy of code in text before transferring
// to the exception table.
*opCodeAddr = oldOpCode | exception;
// Modify opcodes at __DBVECTOR if necessary
if (__DBIsExceptionMarked(exception)) {
DBPrintf(">>> OSINIT: exception %d vectored to debugger\n", exception);
memcpy((void*)__DBVECTOR, (void*)__OSDBJUMPSTART,
(u32)__OSDBJUMPEND - (u32)__OSDBJUMPSTART);
} else {
// make sure the opcodes are still nop
u32* ops = (u32*)__DBVECTOR;
int cb;
for (cb = 0; cb < (u32)__OSDBJUMPEND - (u32)__OSDBJUMPSTART; cb += sizeof(u32)) {
*ops++ = NOP;
}
}
// Install the modified handler.
destAddr = (void*)OSPhysicalToCached(__OSExceptionLocations[(u32)exception]);
memcpy(destAddr, handlerStart, handlerSize);
DCFlushRangeNoSync(destAddr, handlerSize);
__sync();
ICInvalidateRange(destAddr, handlerSize);
}
// initialize pointer to exception table
OSExceptionTable = OSPhysicalToCached(OS_EXCEPTIONTABLE_ADDR);
// install default exception handlers
for (exception = 0; exception < 15; exception++) {
__OSSetExceptionHandler(exception, OSDefaultExceptionHandler);
}
// restore the old opcode, so that we can re-start an application without
// downloading the text segments
*opCodeAddr = oldOpCode;
DBPrintf("Exceptions initialized...\n");
}
asm void __OSDBIntegrator(void) {
// clang-format off
nofralloc
entry __OSDBINTSTART
li r5, 0x40
mflr r3
stw r3, 0xc(r5)
lwz r3, 8(r5)
oris r3, r3, 0x8000
mtlr r3
li r3, 0x30
mtmsr r3
blr
entry __OSDBINTEND
// clang-format on
}
asm void __OSDBJump(void){
// clang-format off
nofralloc
entry __OSDBJUMPSTART
bla 0x60
entry __OSDBJUMPEND
// clang-format on
}
OSExceptionHandler __OSSetExceptionHandler(__OSException exception, OSExceptionHandler handler) {
OSExceptionHandler old = OSExceptionTable[exception];
OSExceptionTable[exception] = handler;
return old;
}
OSExceptionHandler __OSGetExceptionHandler(__OSException exception) {
return OSExceptionTable[exception];
}
static asm void OSExceptionVector(void) {
// clang-format off
nofralloc
entry __OSEVStart
// Save r4 into SPRG0
mtsprg 0, r4
// Load current context physical address into r4
lwz r4, OS_CURRENTCONTEXT_PADDR
// Save r3 - r5 into the current context
stw r3, OS_CONTEXT_R3(r4)
mfsprg r3, 0
stw r3, OS_CONTEXT_R4(r4)
stw r5, OS_CONTEXT_R5(r4)
lhz r3, OS_CONTEXT_STATE(r4)
ori r3, r3, OS_CONTEXT_STATE_EXC
sth r3, OS_CONTEXT_STATE(r4)
// Save misc registers
mfcr r3
stw r3, OS_CONTEXT_CR(r4)
mflr r3
stw r3, OS_CONTEXT_LR(r4)
mfctr r3
stw r3, OS_CONTEXT_CTR(r4)
mfxer r3
stw r3, OS_CONTEXT_XER(r4)
mfsrr0 r3
stw r3, OS_CONTEXT_SRR0(r4)
mfsrr1 r3
stw r3, OS_CONTEXT_SRR1(r4)
mr r5, r3
entry __DBVECTOR
nop
// Set SRR1[IR|DR] to turn on address
// translation at the next RFI
mfmsr r3
ori r3, r3, 0x30
mtsrr1 r3
// This lets us change the exception number based on the
// exception we're installing.
entry __OSEVSetNumber
li r3, 0
// Load current context virtual address into r4
lwz r4, 0xd4(r0)
// Check non-recoverable interrupt
rlwinm. r5, r5, 0, MSR_RI_BIT, MSR_RI_BIT
bne recoverable
lis r5, OSDefaultExceptionHandler@ha
addi r5, r5, OSDefaultExceptionHandler@l
mtsrr0 r5
rfi
// NOT REACHED HERE
recoverable:
// Locate exception handler.
rlwinm r5, r3, 2, 0x16, 0x1d // r5 contains exception*4
lwz r5, OS_EXCEPTIONTABLE_ADDR(r5)
mtsrr0 r5
// Final state
// r3 - exception number
// r4 - pointer to context
// r5 - garbage
// srr0 - exception handler
// srr1 - address translation enabled, not yet recoverable
rfi
// NOT REACHED HERE
// The handler will restore state
entry __OSEVEnd
nop
// clang-format on
}
static asm void OSDefaultExceptionHandler(register __OSException exception,
register OSContext* context) {
// clang-format off
nofralloc
stw r0, 0(context)
stw r1, 4(context)
stw r2, 8(context)
stmw r6, 0x18(context)
mfspr r0, 0x391
stw r0, 0x1a8(context)
mfspr r0, 0x392
stw r0, 0x1ac(context)
mfspr r0, 0x393
stw r0, 0x1b0(context)
mfspr r0, 0x394
stw r0, 0x1b4(context)
mfspr r0, 0x395
stw r0, 0x1b8(context)
mfspr r0, 0x396
stw r0, 0x1bc(context)
mfspr r0, 0x397
stw r0, 0x1c0(context)
mfdsisr r5
mfdar r6
stwu r1, -8(r1)
b __OSUnhandledException
// clang-format on
}
asm void __OSPSInit(void){
// clang-format off
nofralloc
mflr r0
stw r0, 4(r1)
stwu r1, -8(r1)
bl PPCMfhid2
oris r3, r3, 0xa000
bl PPCMthid2
bl ICFlashInvalidate
sync
li r3, 0
mtspr 0x390, r3
mtspr 0x391, r3
mtspr 0x392, r3
mtspr 0x393, r3
mtspr 0x394, r3
mtspr 0x395, r3
mtspr 0x396, r3
mtspr 0x397, r3
lwz r0, 0xc(r1)
addi r1, r1, 8
mtlr r0
blr
// clang-format on
}
vu32 __DIRegs[16] : 0xCC006000;
#define DI_CONFIG_IDX 0x9
#define DI_CONFIG_CONFIG_MASK 0xFF
u32 __OSGetDIConfig(void) {
return (__DIRegs[DI_CONFIG_IDX] & DI_CONFIG_CONFIG_MASK);
}
void OSRegisterVersion(const char* version) {
OSReport("%s\n", version);
}

228
src/dolphin/os/OSAlarm.c Normal file
View File

@ -0,0 +1,228 @@
#include "dolphin/os/OSAlarm.h"
#include "dolphin/os/OS.h"
static BOOL OnReset(BOOL final);
BOOL __DVDTestAlarm(OSAlarm* alarm);
static OSResetFunctionInfo ResetFunctionInfo = {
OnReset,
0xFFFFFFFF,
};
static OSAlarmQueue AlarmQueue;
void OSInitAlarm(void) {
if (__OSGetExceptionHandler(8) != DecrementerExceptionHandler) {
AlarmQueue.head = AlarmQueue.tail = NULL;
__OSSetExceptionHandler(8, DecrementerExceptionHandler);
OSRegisterResetFunction(&ResetFunctionInfo);
}
}
void OSCreateAlarm(OSAlarm* alarm) {
alarm->handler = NULL;
alarm->tag = 0;
}
static inline SetTimer(OSAlarm* alarm) {
OSTime delta;
delta = alarm->fire_time - __OSGetSystemTime();
if (delta < 0) {
PPCMtdec(0);
} else if (delta < 0x80000000) {
PPCMtdec((u32)delta);
} else {
PPCMtdec(0x7fffffff);
}
}
static void InsertAlarm(OSAlarm* alarm, OSTime fire, OSAlarmHandler handler) {
OSAlarm* next;
OSAlarm* prev;
if (0 < alarm->period_time) {
OSTime time = __OSGetSystemTime();
fire = alarm->start_time;
if (alarm->start_time < time) {
fire += alarm->period_time * ((time - alarm->start_time) / alarm->period_time + 1);
}
}
alarm->handler = handler;
alarm->fire_time = fire;
for (next = AlarmQueue.head; next; next = next->link.next) {
if (next->fire_time <= fire) {
continue;
}
alarm->link.prev = next->link.prev;
next->link.prev = alarm;
alarm->link.next = next;
prev = alarm->link.prev;
if (prev) {
prev->link.next = alarm;
} else {
AlarmQueue.head = alarm;
SetTimer(alarm);
}
return;
}
alarm->link.next = 0;
prev = AlarmQueue.tail;
AlarmQueue.tail = alarm;
alarm->link.prev = prev;
if (prev) {
prev->link.next = alarm;
} else {
AlarmQueue.head = AlarmQueue.tail = alarm;
SetTimer(alarm);
}
}
void OSSetAlarm(OSAlarm* alarm, OSTime tick, OSAlarmHandler handler) {
BOOL enabled;
enabled = OSDisableInterrupts();
alarm->period_time = 0;
InsertAlarm(alarm, __OSGetSystemTime() + tick, handler);
OSRestoreInterrupts(enabled);
}
void OSSetPeriodicAlarm(OSAlarm* alarm, OSTime start, OSTime period, OSAlarmHandler handler) {
BOOL enabled;
enabled = OSDisableInterrupts();
alarm->period_time = period;
alarm->start_time = __OSTimeToSystemTime(start);
InsertAlarm(alarm, 0, handler);
OSRestoreInterrupts(enabled);
}
void OSCancelAlarm(OSAlarm* alarm) {
OSAlarm* next;
BOOL enabled;
enabled = OSDisableInterrupts();
if (alarm->handler == 0) {
OSRestoreInterrupts(enabled);
return;
}
next = alarm->link.next;
if (next == 0) {
AlarmQueue.tail = alarm->link.prev;
} else {
next->link.prev = alarm->link.prev;
}
if (alarm->link.prev) {
alarm->link.prev->link.next = next;
} else {
AlarmQueue.head = next;
if (next) {
SetTimer(next);
}
}
alarm->handler = 0;
OSRestoreInterrupts(enabled);
}
static void DecrementerExceptionCallback(register __OSException exception,
register OSContext* context) {
OSAlarm* alarm;
OSAlarm* next;
OSAlarmHandler handler;
OSTime time;
OSContext exceptionContext;
time = __OSGetSystemTime();
alarm = AlarmQueue.head;
if (alarm == 0) {
OSLoadContext(context);
}
if (time < alarm->fire_time) {
SetTimer(alarm);
OSLoadContext(context);
}
next = alarm->link.next;
AlarmQueue.head = next;
if (next == 0) {
AlarmQueue.tail = 0;
} else {
next->link.prev = 0;
}
handler = alarm->handler;
alarm->handler = 0;
if (0 < alarm->period_time) {
InsertAlarm(alarm, 0, handler);
}
if (AlarmQueue.head) {
SetTimer(AlarmQueue.head);
}
OSDisableScheduler();
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
handler(alarm, context);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
OSEnableScheduler();
__OSReschedule();
OSLoadContext(context);
}
static asm void DecrementerExceptionHandler(register __OSException exception,
register OSContext* context) {
// clang-format off
nofralloc
stw r0, 0(context)
stw r1, 4(context)
stw r2, 8(context)
stmw r6, 0x18(context)
mfspr r0, 0x391
stw r0, 0x1a8(context)
mfspr r0, 0x392
stw r0, 0x1ac(context)
mfspr r0, 0x393
stw r0, 0x1b0(context)
mfspr r0, 0x394
stw r0, 0x1b4(context)
mfspr r0, 0x395
stw r0, 0x1b8(context)
mfspr r0, 0x396
stw r0, 0x1bc(context)
mfspr r0, 0x397
stw r0, 0x1c0(context)
stwu r1, -8(r1)
b DecrementerExceptionCallback
// clang-format on
}
static BOOL OnReset(BOOL final) {
OSAlarm* alarm;
OSAlarm* next;
if (final != FALSE) {
alarm = AlarmQueue.head;
next = (alarm) ? alarm->link.next : NULL;
while (alarm != NULL) {
if (__DVDTestAlarm(alarm) == FALSE) {
OSCancelAlarm(alarm);
}
alarm = next;
next = (alarm) ? alarm->link.next : NULL;
}
}
return TRUE;
}

127
src/dolphin/os/OSAlloc.c Normal file
View File

@ -0,0 +1,127 @@
#include "dolphin/os/OSAlloc.h"
static OSHeapCell* DLInsert(OSHeapCell* list, OSHeapCell* child) {
OSHeapCell* prev = NULL;
OSHeapCell* next = list;
for (; next != NULL; prev = next, next = next->next) {
if ((char*)child <= (char*)next) {
break;
}
}
child->next = next;
child->prev = prev;
if (next != NULL) {
next->prev = child;
if ((char*)child + child->size == (char*)next) {
child->size += next->size;
next = next->next;
child->next = next;
if (next != NULL) {
next->prev = child;
}
}
}
if (prev != NULL) {
prev->next = child;
if ((char*)prev + prev->size == (char*)child) {
prev->size += child->size;
prev->next = next;
if (next != NULL) {
next->prev = prev;
}
}
return list;
} else {
return child;
}
}
inline OSHeapCell* DLExtract(OSHeapCell* list, OSHeapCell* child) {
if (child->next != NULL) {
child->next->prev = child->prev;
}
if (child->prev == NULL) {
return child->next;
}
child->prev->next = child->next;
return list;
}
static OSHeapDescriptor* HeapArray;
void OSFreeToHeap(OSHeapHandle handle, void* ptr) {
OSHeapDescriptor* hd = &HeapArray[handle];
OSHeapCell* cell = (OSHeapCell*)((char*)ptr - sizeof(OSHeapCell));
hd->usedList = DLExtract(hd->usedList, cell);
hd->freeList = DLInsert(hd->freeList, cell);
}
volatile s32 __OSCurrHeap = -1;
s32 OSSetCurrentHeap(OSHeapHandle handle) {
s32 old = __OSCurrHeap;
__OSCurrHeap = handle;
return old;
}
static s32 NumHeaps;
static void* ArenaStart;
static void* ArenaEnd;
void* OSInitAlloc(void* lo, void* hi, s32 maxHeaps) {
u32 totalSize = maxHeaps * sizeof(OSHeapDescriptor);
int i;
HeapArray = lo;
NumHeaps = maxHeaps;
for (i = 0; i < NumHeaps; i++) {
OSHeapDescriptor* hd = &HeapArray[i];
hd->size = -1;
hd->freeList = hd->usedList = NULL;
}
__OSCurrHeap = -1;
lo = (u8*)HeapArray + totalSize;
lo = OSRoundUpPtr(lo, 0x20);
ArenaStart = lo;
ArenaEnd = OSRoundDownPtr(hi, 0x20);
return ArenaStart;
}
OSHeapHandle OSCreateHeap(void* start, void* end) {
int i;
OSHeapCell* cell = OSRoundUpPtr(start, 0x20);
end = OSRoundDownPtr(end, 0x20);
for (i = 0; i < NumHeaps; i++) {
OSHeapDescriptor* hd = &HeapArray[i];
if (hd->size < 0) {
hd->size = (u8*)end - (u8*)cell;
cell->prev = NULL;
cell->next = NULL;
cell->size = hd->size;
hd->freeList = cell;
hd->usedList = NULL;
return i;
}
}
return -1;
}

31
src/dolphin/os/OSArena.c Normal file
View File

@ -0,0 +1,31 @@
#include "dolphin/os/OSArena.h"
#include "dolphin/os/OSAlloc.h"
static void* __OSArenaHi;
void* OSGetArenaHi(void) {
return __OSArenaHi;
}
static void* __OSArenaLo = (void*)0xFFFFFFFF;
void* OSGetArenaLo(void) {
return __OSArenaLo;
}
void OSSetArenaHi(void* hi) {
__OSArenaHi = hi;
}
void OSSetArenaLo(void* lo) {
__OSArenaLo = lo;
}
void* OSAllocFromArenaLo(u32 size, s32 alignment) {
u8* blk_start = OSRoundUpPtr(__OSArenaLo, alignment);
u8* blk_end = blk_start + size;
blk_end = OSRoundUpPtr(blk_end, alignment);
__OSArenaLo = blk_end;
return blk_start;
}

View File

@ -0,0 +1,105 @@
#include "dolphin/os/OSAudioSystem.h"
#include "dolphin/dsp.h"
#include "string.h"
static u8 DSPInitCode[128] = {
0x02, 0x9F, 0x00, 0x10, 0x02, 0x9F, 0x00, 0x33, 0x02, 0x9F, 0x00, 0x34, 0x02, 0x9F, 0x00, 0x35,
0x02, 0x9F, 0x00, 0x36, 0x02, 0x9F, 0x00, 0x37, 0x02, 0x9F, 0x00, 0x38, 0x02, 0x9F, 0x00, 0x39,
0x12, 0x06, 0x12, 0x03, 0x12, 0x04, 0x12, 0x05, 0x00, 0x80, 0x80, 0x00, 0x00, 0x88, 0xFF, 0xFF,
0x00, 0x84, 0x10, 0x00, 0x00, 0x64, 0x00, 0x1D, 0x02, 0x18, 0x00, 0x00, 0x81, 0x00, 0x1C, 0x1E,
0x00, 0x44, 0x1B, 0x1E, 0x00, 0x84, 0x08, 0x00, 0x00, 0x64, 0x00, 0x27, 0x19, 0x1E, 0x00, 0x00,
0x00, 0xDE, 0xFF, 0xFC, 0x02, 0xA0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x28, 0x16, 0xFC, 0x00, 0x54,
0x16, 0xFD, 0x43, 0x48, 0x00, 0x21, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF,
0x02, 0xFF, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define __DSPWorkBuffer (void*)0x81000000
void __OSInitAudioSystem(void) {
u32 r28;
u16 r3;
u32 padding;
memcpy((void*)((u8*)OSGetArenaHi() - 128), __DSPWorkBuffer, 128);
memcpy(__DSPWorkBuffer, (void*)DSPInitCode, 128);
DCFlushRange(__DSPWorkBuffer, 128);
__DSPRegs[9] = 0x43;
__DSPRegs[5] = 0x8AC;
__DSPRegs[5] |= 1;
while (__DSPRegs[5] & 1)
;
__DSPRegs[0] = 0;
while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000)
;
*(u32*)&__DSPRegs[16] = 0x1000000;
*(u32*)&__DSPRegs[18] = 0;
*(u32*)&__DSPRegs[20] = 0x20;
r3 = __DSPRegs[5];
while (!(r3 & 0x20))
r3 = __DSPRegs[5];
__DSPRegs[5] = r3;
r28 = OSGetTick();
while ((s32)(OSGetTick() - r28) < 0x892)
;
*(u32*)&__DSPRegs[16] = 0x1000000;
*(u32*)&__DSPRegs[18] = 0;
*(u32*)&__DSPRegs[20] = 0x20;
r3 = __DSPRegs[5];
while (!(r3 & 0x20))
r3 = __DSPRegs[5];
__DSPRegs[5] = r3;
__DSPRegs[5] &= ~0x800;
while ((__DSPRegs[5]) & 0x400)
;
__DSPRegs[5] &= ~4;
r3 = __DSPRegs[2];
while (!(r3 & 0x8000))
r3 = __DSPRegs[2];
(void)__DSPRegs[3];
r3 != 42069;
__DSPRegs[5] |= 4;
__DSPRegs[5] = 0x8AC;
__DSPRegs[5] |= 1;
while (__DSPRegs[5] & 1)
;
memcpy(__DSPWorkBuffer, (void*)((u8*)OSGetArenaHi() - 128), 128);
}
void __OSStopAudioSystem(void) {
u32 r28;
#define waitUntil(load, mask) \
r28 = (load); \
while (r28 & (mask)) { \
r28 = (load); \
}
__DSPRegs[5] = 0x804;
r28 = __DSPRegs[27];
__DSPRegs[27] = r28 & ~0x8000;
waitUntil(__DSPRegs[5], 0x400);
waitUntil(__DSPRegs[5], 0x200);
__DSPRegs[5] = 0x8ac;
__DSPRegs[0] = 0;
while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000)
;
r28 = OSGetTick();
while ((s32)(OSGetTick() - r28) < 0x2c)
;
__DSPRegs[5] |= 1;
waitUntil(__DSPRegs[5], 0x001);
#undef waitUntil
}

432
src/dolphin/os/OSCache.c Normal file
View File

@ -0,0 +1,432 @@
#include "dolphin/os/OSCache.h"
#include "dolphin/base/PPCArch.h"
// #include "dolphin/db.h"
#include "dolphin/os/OS.h"
static asm void DCEnable(void) {
// clang-format off
nofralloc
sync
mfspr r3, 0x3F0
ori r3, r3, 0x4000
mtspr 0x3F0, r3
blr
// clang-format on
}
asm void DCInvalidateRange(register void* start, register u32 nBytes) {
// clang-format off
nofralloc
cmplwi nBytes, 0
blelr
clrlwi r5, start, 0x1B
add nBytes, nBytes, r5
addi nBytes, nBytes, 0x1F
srwi nBytes, nBytes, 5
mtctr nBytes
do_invalidate:
dcbi 0, start
addi start, start, 0x20
bdnz do_invalidate
blr
// clang-format on
}
asm void DCFlushRange(register void* start, register u32 nBytes) {
// clang-format off
nofralloc
cmplwi nBytes, 0
blelr
clrlwi r5, start, 0x1B
add nBytes, nBytes, r5
addi nBytes, nBytes, 0x1F
srwi nBytes, nBytes, 5
mtctr nBytes
do_flush:
dcbf 0, start
addi start, start, 0x20
bdnz do_flush
sc
blr
// clang-format on
}
asm void DCStoreRange(register void* start, register u32 nBytes) {
// clang-format off
nofralloc
cmplwi nBytes, 0
blelr
clrlwi r5, start, 0x1B
add nBytes, nBytes, r5
addi nBytes, nBytes, 0x1F
srwi nBytes, nBytes, 5
mtctr nBytes
do_store:
dcbst 0, start
addi start, start, 0x20
bdnz do_store
sc
blr
// clang-format on
}
asm void DCFlushRangeNoSync(register void* start, register u32 nBytes) {
// clang-format off
nofralloc
cmplwi nBytes, 0
blelr
clrlwi r5, start, 0x1B
add nBytes, nBytes, r5
addi nBytes, nBytes, 0x1F
srwi nBytes, nBytes, 5
mtctr nBytes
do_flush:
dcbf 0, start
addi start, start, 0x20
bdnz do_flush
blr
// clang-format on
}
asm void DCStoreRangeNoSync(register void* start, register u32 nBytes) {
// clang-format off
nofralloc
cmplwi nBytes, 0
blelr
clrlwi r5, start, 0x1B
add nBytes, nBytes, r5
addi nBytes, nBytes, 0x1F
srwi nBytes, nBytes, 5
mtctr nBytes
do_store:
dcbst 0, start
addi start, start, 0x20
bdnz do_store
blr
// clang-format on
}
asm void DCZeroRange(register void* start, register u32 nBytes) {
// clang-format off
nofralloc
cmplwi nBytes, 0
blelr
clrlwi r5, start, 0x1B
add nBytes, nBytes, r5
addi nBytes, nBytes, 0x1F
srwi nBytes, nBytes, 5
mtctr nBytes
do_zero:
dcbz 0, start
addi start, start, 0x20
bdnz do_zero
blr
// clang-format on
}
asm void ICInvalidateRange(register void* start, register u32 nBytes) {
// clang-format off
nofralloc
cmplwi nBytes, 0
blelr
clrlwi r5, start, 0x1B
add nBytes, nBytes, r5
addi nBytes, nBytes, 0x1F
srwi nBytes, nBytes, 5
mtctr nBytes
do_invalidate:
icbi 0, start
addi start, start, 0x20
bdnz do_invalidate
sync
isync
blr
// clang-format on
}
asm void ICFlashInvalidate(void) {
// clang-format off
nofralloc
mfspr r3, 0x3F0
ori r3, r3, 0x800
mtspr 0x3F0, r3
blr
// clang-format on
}
static asm void ICEnable(void) {
// clang-format off
nofralloc
isync
mfspr r3, 0x3F0
ori r3, r3, 0x8000
mtspr 0x3F0, r3
blr
// clang-format on
}
asm void __LCEnable(void) {
// clang-format off
nofralloc
mfmsr r5
ori r5, r5, 0x1000
mtmsr r5
lis r3, 0x8000
li r4, 0x400
mtctr r4
do_store:
dcbt 0, r3
dcbst 0, r3
addi r3, r3, 0x20
bdnz do_store
mfspr r4, 0x398
oris r4, r4, 0x100F
mtspr 0x398, r4
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
lis r3, 0xE000
ori r3, r3, 0x0002
mtdbatl 3, r3
ori r3, r3, 0x1FE
mtdbatu 3, r3
isync
lis r3, 0xE000
li r6, 0x200
mtctr r6
li r6, 0
do_load:
dcbz_l r6, r3
addi r3, r3, 0x0020
bdnz do_load
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
blr
// clang-format on
}
void LCEnable(void) {
BOOL interrupt = OSDisableInterrupts();
__LCEnable();
OSRestoreInterrupts(interrupt);
}
asm void LCDisable(void) {
// clang-format off
nofralloc
lis r3, 0xE000
li r4, 0x200
mtctr r4
do_invalidate:
dcbi 0, r3
addi r3, r3, 0x20
bdnz do_invalidate
mfspr r4, 0x398
rlwinm r4, r4, 0, 4, 2
mtspr 0x398, r4
blr
// clang-format on
}
static asm void LCStoreBlocks(register void* destAddr, register void* srcAddr,
register u32 blockNum){
// clang-format off
nofralloc
rlwinm r6, blockNum, 0x1E, 0x1B, 0x1F
clrlwi destAddr, destAddr, 4
or r6, r6, destAddr
mtspr 0x39A, r6
rlwinm r6, blockNum, 2, 0x1C, 0x1D
or r6, r6, srcAddr
ori r6, r6, 2
mtspr 0x39B, r6
blr
// clang-format on
} /* 8033B838-8033B8E4 336178 00AC+00 0/0 0/0 3/3 .text LCStoreData */
u32 LCStoreData(void* destAddr, void* srcAddr, u32 nBytes) {
u32 blocks = (nBytes + 31) / 32;
u32 ret = (blocks + 127) / 128;
while (blocks > 0) {
if (blocks < 128) {
LCStoreBlocks(destAddr, srcAddr, blocks);
blocks = 0;
} else {
LCStoreBlocks(destAddr, srcAddr, 0);
blocks -= 128;
destAddr = (char*)destAddr + 0x1000;
srcAddr = (char*)srcAddr + 0x1000;
}
}
return ret;
}
asm void LCQueueWait(register u32 len) {
// clang-format off
nofralloc
mfspr r4, 0x398
rlwinm r4, r4, 8, 28, 31
cmpw r4, len
bgt LCQueueWait
blr
// clang-format on
}
static void L2Disable(void) {
__sync();
PPCMtl2cr(PPCMfl2cr() & ~0x80000000);
__sync();
}
void L2GlobalInvalidate(void) {
L2Disable();
PPCMtl2cr(PPCMfl2cr() | 0x00200000);
while (PPCMfl2cr() & 0x00000001u)
;
PPCMtl2cr(PPCMfl2cr() & ~0x00200000);
while (PPCMfl2cr() & 0x00000001u) {
DBPrintf(">>> L2 INVALIDATE : SHOULD NEVER HAPPEN\n");
}
}
void DMAErrorHandler(u16 error, OSContext* context, ...) {
u32 hid2 = PPCMfhid2();
OSReport("Machine check received\n");
OSReport("HID2 = 0x%x SRR1 = 0x%x\n", hid2, context->srr1);
if (!(hid2 & (HID2_DCHERR | HID2_DNCERR | HID2_DCMERR | HID2_DQOERR)) ||
!(context->srr1 & SRR1_DMA_BIT)) {
OSReport("Machine check was not DMA/locked cache related\n");
OSDumpContext(context);
PPCHalt();
}
OSReport("DMAErrorHandler(): An error occurred while processing DMA.\n");
OSReport("The following errors have been detected and cleared :\n");
if (hid2 & HID2_DCHERR) {
OSReport("\t- Requested a locked cache tag that was already in the cache\n");
}
if (hid2 & HID2_DNCERR) {
OSReport("\t- DMA attempted to access normal cache\n");
}
if (hid2 & HID2_DCMERR) {
OSReport("\t- DMA missed in data cache\n");
}
if (hid2 & HID2_DQOERR) {
OSReport("\t- DMA queue overflowed\n");
}
// write hid2 back to clear the error bits
PPCMthid2(hid2);
}
static void L2Init(void) {
u32 oldMSR;
oldMSR = PPCMfmsr();
__sync();
PPCMtmsr(MSR_IR | MSR_DR);
__sync();
L2Disable();
L2GlobalInvalidate();
PPCMtmsr(oldMSR);
}
void L2Enable(void) {
PPCMtl2cr((PPCMfl2cr() | L2CR_L2E) & ~L2CR_L2I);
}
void __OSCacheInit() {
if (!(PPCMfhid0() & HID0_ICE)) {
ICEnable();
DBPrintf("L1 i-caches initialized\n");
}
if (!(PPCMfhid0() & HID0_DCE)) {
DCEnable();
DBPrintf("L1 d-caches initialized\n");
}
if (!(PPCMfl2cr() & L2CR_L2E)) {
L2Init();
L2Enable();
DBPrintf("L2 cache initialized\n");
}
OSSetErrorHandler(OS_ERROR_MACHINE_CHECK, DMAErrorHandler);
DBPrintf("Locked cache machine check handler installed\n");
}

611
src/dolphin/os/OSContext.c Normal file
View File

@ -0,0 +1,611 @@
#include "dolphin/os/OSContext.h"
// #include "dolphin/db.h"
#include "dolphin/os/OS.h"
volatile OSContext* __OSCurrentContext : (OS_BASE_CACHED | 0x00D4);
volatile OSContext* __OSFPUContext : (OS_BASE_CACHED | 0x00D8);
asm void __OSLoadFPUContext(void) {
// clang-format off
nofralloc
lhz r5, 0x1A2(r4)
clrlwi. r5, r5, 0x1f
beq exit
lfd f0, 0x190(r4)
mtfsf 0xFF, f0
mfspr r5, 0x398
rlwinm. r5, r5, 3, 0x1F, 0x1F
beq load_fprs
psq_l f0, 0x1C8(r4), 0, 0
psq_l f1, 0x1D0(r4), 0, 0
psq_l f2, 0x1D8(r4), 0, 0
psq_l f3, 0x1E0(r4), 0, 0
psq_l f4, 0x1E8(r4), 0, 0
psq_l f5, 0x1F0(r4), 0, 0
psq_l f6, 0x1F8(r4), 0, 0
psq_l f7, 0x200(r4), 0, 0
psq_l f8, 0x208(r4), 0, 0
psq_l f9, 0x210(r4), 0, 0
psq_l f10, 0x218(r4), 0, 0
psq_l f11, 0x220(r4), 0, 0
psq_l f12, 0x228(r4), 0, 0
psq_l f13, 0x230(r4), 0, 0
psq_l f14, 0x238(r4), 0, 0
psq_l f15, 0x240(r4), 0, 0
psq_l f16, 0x248(r4), 0, 0
psq_l f17, 0x250(r4), 0, 0
psq_l f18, 0x258(r4), 0, 0
psq_l f19, 0x260(r4), 0, 0
psq_l f20, 0x268(r4), 0, 0
psq_l f21, 0x270(r4), 0, 0
psq_l f22, 0x278(r4), 0, 0
psq_l f23, 0x280(r4), 0, 0
psq_l f24, 0x288(r4), 0, 0
psq_l f25, 0x290(r4), 0, 0
psq_l f26, 0x298(r4), 0, 0
psq_l f27, 0x2A0(r4), 0, 0
psq_l f28, 0x2A8(r4), 0, 0
psq_l f29, 0x2B0(r4), 0, 0
psq_l f30, 0x2B8(r4), 0, 0
psq_l f31, 0x2C0(r4), 0, 0
load_fprs:
lfd f0, 0x90(r4)
lfd f1, 0x98(r4)
lfd f2, 0xA0(r4)
lfd f3, 0xA8(r4)
lfd f4, 0xB0(r4)
lfd f5, 0xB8(r4)
lfd f6, 0xC0(r4)
lfd f7, 0xC8(r4)
lfd f8, 0xD0(r4)
lfd f9, 0xD8(r4)
lfd f10, 0xE0(r4)
lfd f11, 0xE8(r4)
lfd f12, 0xF0(r4)
lfd f13, 0xF8(r4)
lfd f14, 0x100(r4)
lfd f15, 0x108(r4)
lfd f16, 0x110(r4)
lfd f17, 0x118(r4)
lfd f18, 0x120(r4)
lfd f19, 0x128(r4)
lfd f20, 0x130(r4)
lfd f21, 0x138(r4)
lfd f22, 0x140(r4)
lfd f23, 0x148(r4)
lfd f24, 0x150(r4)
lfd f25, 0x158(r4)
lfd f26, 0x160(r4)
lfd f27, 0x168(r4)
lfd f28, 0x170(r4)
lfd f29, 0x178(r4)
lfd f30, 0x180(r4)
lfd f31, 0x188(r4)
exit:
blr
// clang-format on
}
asm void __OSSaveFPUContext(s32 unused0, s32 unused1, register OSContext* context) {
// clang-format off
nofralloc
lhz r3, 0x1A2(context)
ori r3, r3, 1
sth r3, 0x1A2(context)
stfd f0, 0x90(context)
stfd f1, 0x98(context)
stfd f2, 0xa0(context)
stfd f3, 0xa8(context)
stfd f4, 0xb0(context)
stfd f5, 0xb8(context)
stfd f6, 0xc0(context)
stfd f7, 0xc8(context)
stfd f8, 0xd0(context)
stfd f9, 0xd8(context)
stfd f10, 0xe0(context)
stfd f11, 0xe8(context)
stfd f12, 0xf0(context)
stfd f13, 0xf8(context)
stfd f14, 0x100(context)
stfd f15, 0x108(context)
stfd f16, 0x110(context)
stfd f17, 0x118(context)
stfd f18, 0x120(context)
stfd f19, 0x128(context)
stfd f20, 0x130(context)
stfd f21, 0x138(context)
stfd f22, 0x140(context)
stfd f23, 0x148(context)
stfd f24, 0x150(context)
stfd f25, 0x158(context)
stfd f26, 0x160(context)
stfd f27, 0x168(context)
stfd f28, 0x170(context)
stfd f29, 0x178(context)
stfd f30, 0x180(context)
stfd f31, 0x188(context)
mffs f0
stfd f0, 0x190(context)
lfd f0, 0x90(context)
mfspr r3, 0x398
rlwinm. r3, r3, 3, 0x1f, 0x1f
beq exit
psq_st f0, 456(context), 0, 0
psq_st f1, 464(context), 0, 0
psq_st f2, 472(context), 0, 0
psq_st f3, 480(context), 0, 0
psq_st f4, 488(context), 0, 0
psq_st f5, 496(context), 0, 0
psq_st f6, 504(context), 0, 0
psq_st f7, 512(context), 0, 0
psq_st f8, 520(context), 0, 0
psq_st f9, 528(context), 0, 0
psq_st f10, 536(context), 0, 0
psq_st f11, 544(context), 0, 0
psq_st f12, 552(context), 0, 0
psq_st f13, 560(context), 0, 0
psq_st f14, 568(context), 0, 0
psq_st f15, 576(context), 0, 0
psq_st f16, 584(context), 0, 0
psq_st f17, 592(context), 0, 0
psq_st f18, 600(context), 0, 0
psq_st f19, 608(context), 0, 0
psq_st f20, 616(context), 0, 0
psq_st f21, 624(context), 0, 0
psq_st f22, 632(context), 0, 0
psq_st f23, 640(context), 0, 0
psq_st f24, 648(context), 0, 0
psq_st f25, 656(context), 0, 0
psq_st f26, 664(context), 0, 0
psq_st f27, 672(context), 0, 0
psq_st f28, 680(context), 0, 0
psq_st f29, 688(context), 0, 0
psq_st f30, 696(context), 0, 0
psq_st f31, 704(context), 0, 0
exit:
blr
// clang-format on
}
asm void OSSaveFPUContext(register OSContext* context) {
// clang-format off
nofralloc
addi r5, context, 0
b __OSSaveFPUContext
// clang-format on
}
asm void OSSetCurrentContext(register OSContext* context) {
// clang-format off
nofralloc
lis r4, OS_CURRENT_CONTEXT@ha
stw context, OS_CURRENT_CONTEXT@l(r4)
clrlwi r5, context, 2
stw r5, 0xc0(r4)
lwz r5, 0xd8(r4)
cmpw r5, context
bne lbl_800EE9AC
lwz r6, 0x19c(context)
ori r6, r6, 0x2000
stw r6, 0x19c(context)
mfmsr r6
ori r6, r6, 2
mtmsr r6
blr
lbl_800EE9AC:
lwz r6, 0x19c(context)
rlwinm r6, r6, 0, 0x13, 0x11
stw r6, 0x19c(context)
mfmsr r6
rlwinm r6, r6, 0, 0x13, 0x11
ori r6, r6, 2
mtmsr r6
isync
blr
// clang-format on
}
OSContext* OSGetCurrentContext(void) {
return OS_CURRENT_CONTEXT;
}
asm u32 OSSaveContext(register OSContext* context) {
// clang-format off
nofralloc
stmw r13, 0x34(context)
mfspr r0, GQR1
stw r0, 0x1a8(context)
mfspr r0, GQR2
stw r0, 0x1ac(context)
mfspr r0, GQR3
stw r0, 0x1b0(context)
mfspr r0, GQR4
stw r0, 0x1b4(context)
mfspr r0, GQR5
stw r0, 0x1b8(context)
mfspr r0, GQR6
stw r0, 0x1bc(context)
mfspr r0, GQR7
stw r0, 0x1c0(context)
mfcr r0
stw r0, 0x80(context)
mflr r0
stw r0, 0x84(context)
stw r0, 0x198(context)
mfmsr r0
stw r0, 0x19c(context)
mfctr r0
stw r0, 0x88(context)
mfxer r0
stw r0, 0x8c(context)
stw r1, 4(context)
stw r2, 8(context)
li r0, 1
stw r0, 0xc(context)
li r3, 0
blr
// clang-format on
}
asm void OSLoadContext(register OSContext* context) {
// clang-format off
nofralloc
lis r4, OSDisableInterrupts@ha
lwz r6, 0x198(context)
addi r5, r4, OSDisableInterrupts@l
cmplw r6, r5
ble srr0_not_in_disableintr
lis r4, __RAS_OSDisableInterrupts_end@ha
addi r0, r4, __RAS_OSDisableInterrupts_end@l
cmplw r6, r0
bge srr0_not_in_disableintr
stw r5, 0x198(context)
srr0_not_in_disableintr:
lwz r0, 0(context)
lwz r1, 4(context)
lwz r2, 8(context)
lhz r4, 0x1a2(context)
rlwinm. r5, r4, 0, 0x1e, 0x1e
beq load_saved_gprs
rlwinm r4, r4, 0, 0x1f, 0x1d
sth r4, 0x1a2(context)
lmw r5, 0x14(context)
b load_special_regs
load_saved_gprs:
lmw r13, 0x34(context)
load_special_regs:
lwz r4, 0x1a8(context)
mtspr 0x391, r4
lwz r4, 0x1ac(context)
mtspr 0x392, r4
lwz r4, 0x1b0(context)
mtspr 0x393, r4
lwz r4, 0x1b4(context)
mtspr 0x394, r4
lwz r4, 0x1b8(context)
mtspr 0x395, r4
lwz r4, 0x1bc(context)
mtspr 0x396, r4
lwz r4, 0x1c0(context)
mtspr 0x397, r4
lwz r4, 0x80(context)
mtcrf 0xff, r4
lwz r4, 0x84(context)
mtlr r4
lwz r4, 0x88(context)
mtctr r4
lwz r4, 0x8c(context)
mtxer r4
mfmsr r4
rlwinm r4, r4, 0, 0x11, 0xf
rlwinm r4, r4, 0, 0x1f, 0x1d
mtmsr r4
lwz r4, 0x198(context)
mtspr 0x1a, r4
lwz r4, 0x19c(context)
mtspr 0x1b, r4
lwz r4, 0x10(context)
lwz context, 0xc(context)
rfi
// clang-format on
}
asm u8* OSGetStackPointer(void) {
// clang-format off
nofralloc
mr r3, r1
blr
// clang-format on
}
void OSClearContext(OSContext* context) {
context->mode = 0;
context->state = 0;
if (context == OS_CURRENT_FPU_CONTEXT) {
OS_CURRENT_FPU_CONTEXT = NULL;
}
}
asm void OSInitContext(register OSContext* context, register u32 srr0, register u32 stack) {
// clang-format off
nofralloc
stw srr0, 0x198(context)
stw stack, 4(context)
li r11, 0
ori r11, r11, 0x9032
stw r11, 0x19c(context)
li r0, 0
stw r0, 0x80(context)
stw r0, 0x8c(context)
stw r2, 8(context)
stw r13, 0x34(context)
stw r0, 0xc(context)
stw r0, 0x10(context)
stw r0, 0x14(context)
stw r0, 0x18(context)
stw r0, 0x1c(context)
stw r0, 0x20(context)
stw r0, 0x24(context)
stw r0, 0x28(context)
stw r0, 0x2c(context)
stw r0, 0x30(context)
stw r0, 0x38(context)
stw r0, 0x3c(context)
stw r0, 0x40(context)
stw r0, 0x44(context)
stw r0, 0x48(context)
stw r0, 0x4c(context)
stw r0, 0x50(context)
stw r0, 0x54(context)
stw r0, 0x58(context)
stw r0, 0x5c(context)
stw r0, 0x60(context)
stw r0, 0x64(context)
stw r0, 0x68(context)
stw r0, 0x6c(context)
stw r0, 0x70(context)
stw r0, 0x74(context)
stw r0, 0x78(context)
stw r0, 0x7c(context)
stw r0, 0x1a4(context)
stw r0, 0x1a8(context)
stw r0, 0x1ac(context)
stw r0, 0x1b0(context)
stw r0, 0x1b4(context)
stw r0, 0x1b8(context)
stw r0, 0x1bc(context)
stw r0, 0x1c0(context)
b OSClearContext
// clang-format on
}
// inline duplicates for OSDumpContext to match
// maybe need to change inlining compiler flag for better match?
inline void i_OSClearContext(OSContext* context) {
context->mode = 0;
context->state = 0;
if (context == OS_CURRENT_FPU_CONTEXT) {
OS_CURRENT_FPU_CONTEXT = NULL;
}
}
inline OSContext* i_OSGetCurrentContext(void) {
return OS_CURRENT_CONTEXT;
}
void OSDumpContext(OSContext* context) {
u32 i;
u32* p;
OSReport("------------------------- Context 0x%08x -------------------------\n", context);
for (i = 0; i < 16; ++i) {
OSReport("r%-2d = 0x%08x (%14d) r%-2d = 0x%08x (%14d)\n", i, context->gpr[i],
context->gpr[i], i + 16, context->gpr[i + 16], context->gpr[i + 16]);
}
OSReport("LR = 0x%08x CR = 0x%08x\n", context->lr, context->cr);
OSReport("SRR0 = 0x%08x SRR1 = 0x%08x\n", context->srr0, context->srr1);
OSReport("\nGQRs----------\n");
for (i = 0; i < 4; ++i) {
OSReport("gqr%d = 0x%08x \t gqr%d = 0x%08x\n", i, context->gqr[i], i + 4,
context->gqr[i + 4]);
}
if (context->state & OS_CONTEXT_STATE_FPSAVED) {
OSContext* currentContext;
OSContext fpuContext;
BOOL enabled;
enabled = OSDisableInterrupts();
currentContext = i_OSGetCurrentContext();
i_OSClearContext(&fpuContext);
OSSetCurrentContext(&fpuContext);
OSReport("\n\nFPRs----------\n");
for (i = 0; i < 32; i += 2) {
OSReport("fr%d \t= %d \t fr%d \t= %d\n", i, (u32)context->fpr[i], i + 1,
(u32)context->fpr[i + 1]);
}
OSReport("\n\nPSFs----------\n");
for (i = 0; i < 32; i += 2) {
OSReport("ps%d \t= 0x%x \t ps%d \t= 0x%x\n", i, (u32)context->ps[i], i + 1,
(u32)context->ps[i + 1]);
}
i_OSClearContext(&fpuContext);
OSSetCurrentContext(currentContext);
OSRestoreInterrupts(enabled);
}
OSReport("\nAddress: Back Chain LR Save\n");
for (i = 0, p = (u32*)context->gpr[1]; p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) {
OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]);
}
}
static asm void OSSwitchFPUContext(register u8 err, register OSContext* context) {
// clang-format off
nofralloc
mfmsr r5
ori r5, r5, 0x2000
mtmsr r5
isync
lwz r5, 0x19c(context)
ori r5, r5, 0x2000
mtspr 0x1b, r5
lis r3, OS_CURRENT_FPU_CONTEXT@ha
lwz r5, OS_CURRENT_FPU_CONTEXT@l(r3)
stw context, 0xd8(r3)
cmpw r5, context
beq context_is_curr_fpu_context
cmpwi r5, 0
beq context_is_null
bl __OSSaveFPUContext
context_is_null:
bl __OSLoadFPUContext
context_is_curr_fpu_context:
lwz r3, 0x80(context)
mtcrf 0xff, r3
lwz r3, 0x84(context)
mtlr r3
lwz r3, 0x198(context)
mtspr 0x1a, r3
lwz r3, 0x88(context)
mtctr r3
lwz r3, 0x8c(context)
mtxer r3
lhz r3, 0x1a2(context)
rlwinm r3, r3, 0, 0x1f, 0x1d
sth r3, 0x1a2(context)
lwz r5, 0x14(context)
lwz r3, 0xc(context)
lwz context, 0x10(context)
rfi
// clang-format on
}
void __OSContextInit(void) {
__OSSetExceptionHandler(EXCEPTION_FLOATING_POINT, OSSwitchFPUContext);
__OSFPUContext = NULL;
DBPrintf("FPU-unavailable handler installed\n");
}
asm void OSFillFPUContext(register OSContext* context) {
// clang-format off
nofralloc
mfmsr r5
ori r5, r5, 0x2000
mtmsr r5
isync
stfd f0, 0x90(context)
stfd f1, 0x98(context)
stfd f2, 0xa0(context)
stfd f3, 0xa8(context)
stfd f4, 0xb0(context)
stfd f5, 0xb8(context)
stfd f6, 0xc0(context)
stfd f7, 0xc8(context)
stfd f8, 0xd0(context)
stfd f9, 0xd8(context)
stfd f10, 0xe0(context)
stfd f11, 0xe8(context)
stfd f12, 0xf0(context)
stfd f13, 0xf8(context)
stfd f14, 0x100(context)
stfd f15, 0x108(context)
stfd f16, 0x110(context)
stfd f17, 0x118(context)
stfd f18, 0x120(context)
stfd f19, 0x128(context)
stfd f20, 0x130(context)
stfd f21, 0x138(context)
stfd f22, 0x140(context)
stfd f23, 0x148(context)
stfd f24, 0x150(context)
stfd f25, 0x158(context)
stfd f26, 0x160(context)
stfd f27, 0x168(context)
stfd f28, 0x170(context)
stfd f29, 0x178(context)
stfd f30, 0x180(context)
stfd f31, 0x188(context)
mffs f0
stfd f0, 0x190(context)
lfd f0, 0x90(context)
mfspr r5, 0x398
rlwinm. r5, r5, 3, 0x1f, 0x1f
beq exit
psq_st f0, 456(context), 0, 0
psq_st f1, 464(context), 0, 0
psq_st f2, 472(context), 0, 0
psq_st f3, 480(context), 0, 0
psq_st f4, 488(context), 0, 0
psq_st f5, 496(context), 0, 0
psq_st f6, 504(context), 0, 0
psq_st f7, 512(context), 0, 0
psq_st f8, 520(context), 0, 0
psq_st f9, 528(context), 0, 0
psq_st f10, 536(context), 0, 0
psq_st f11, 544(context), 0, 0
psq_st f12, 552(context), 0, 0
psq_st f13, 560(context), 0, 0
psq_st f14, 568(context), 0, 0
psq_st f15, 576(context), 0, 0
psq_st f16, 584(context), 0, 0
psq_st f17, 592(context), 0, 0
psq_st f18, 600(context), 0, 0
psq_st f19, 608(context), 0, 0
psq_st f20, 616(context), 0, 0
psq_st f21, 624(context), 0, 0
psq_st f22, 632(context), 0, 0
psq_st f23, 640(context), 0, 0
psq_st f24, 648(context), 0, 0
psq_st f25, 656(context), 0, 0
psq_st f26, 664(context), 0, 0
psq_st f27, 672(context), 0, 0
psq_st f28, 680(context), 0, 0
psq_st f29, 688(context), 0, 0
psq_st f30, 696(context), 0, 0
psq_st f31, 704(context), 0, 0
exit:
blr
// clang-format on
}

227
src/dolphin/os/OSError.c Normal file
View File

@ -0,0 +1,227 @@
#include "dolphin/os/OSError.h"
#include "dolphin/base/PPCArch.h"
#include "dolphin/dsp.h"
#include "dolphin/dvd/dvdlow.h"
#include "dolphin/os/OS.h"
OSThread* __OSCurrentThread : (OS_BASE_CACHED | 0x00E4);
OSThreadQueue __OSActiveThreadQueue : (OS_BASE_CACHED | 0x00DC);
volatile OSContext* __OSFPUContext : (OS_BASE_CACHED | 0x00D8);
extern volatile u32 __OSLastInterruptSrr0;
extern volatile s16 __OSLastInterrupt;
extern volatile OSTime __OSLastInterruptTime;
extern OSErrorHandlerEx __OSErrorTable[16];
OSErrorHandlerEx __OSErrorTable[16];
#define FPSCR_ENABLE (FPSCR_VE | FPSCR_OE | FPSCR_UE | FPSCR_ZE | FPSCR_XE)
extern u32 __OSFpscrEnableBits = FPSCR_ENABLE;
__declspec(weak) void OSReport(const char* msg, ...) {
va_list marker;
va_start(marker, msg);
vprintf(msg, marker);
va_end(marker);
}
__declspec(weak) void OSVReport(const char* msg, va_list list) {
vprintf(msg, list);
}
__declspec(weak) void OSPanic(const char* file, s32 line, const char* msg, ...) {
va_list marker;
u32 i;
u32* p;
OSDisableInterrupts();
va_start(marker, msg);
vprintf(msg, marker);
va_end(marker);
OSReport(" in \"%s\" on line %d.\n", file, line);
// actually useful for debugging- stack crawl
OSReport("\nAddress: Back Chain LR Save\n");
for (i = 0, p = (u32*)OSGetStackPointer(); // get current stack pointer
p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) // get caller stack pointer
{
OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]);
}
PPCHalt();
}
OSErrorHandler OSSetErrorHandler(OSError error, OSErrorHandler handler) {
OSErrorHandlerEx oldHandler;
BOOL enabled;
enabled = OSDisableInterrupts();
oldHandler = __OSErrorTable[error];
__OSErrorTable[error] = (OSErrorHandlerEx)handler;
if (error == EXCEPTION_FLOATING_POINT_EXCEPTION) {
u32 msr;
u32 fpscr;
OSThread* thread;
msr = PPCMfmsr();
PPCMtmsr(msr | MSR_FP);
fpscr = PPCMffpscr();
if (handler) {
for (thread = __OSActiveThreadQueue.head; thread;
thread = thread->active_threads_link.next)
{
thread->context.srr1 |= MSR_FE0 | MSR_FE1;
if ((thread->context.state & OS_CONTEXT_STATE_FPSAVED) == 0) {
int i;
thread->context.state |= OS_CONTEXT_STATE_FPSAVED;
for (i = 0; i < 32; ++i) {
*(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL;
*(u64*)&thread->context.ps[i] = (u64)0xffffffffffffffffLL;
}
thread->context.fpscr = FPSCR_NI;
}
thread->context.fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE;
thread->context.fpscr &=
~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
}
fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE;
msr |= MSR_FE0 | MSR_FE1;
} else {
for (thread = __OSActiveThreadQueue.head; thread;
thread = thread->active_threads_link.next)
{
thread->context.srr1 &= ~(MSR_FE0 | MSR_FE1);
thread->context.fpscr &= ~FPSCR_ENABLE;
thread->context.fpscr &=
~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
}
fpscr &= ~FPSCR_ENABLE;
msr &= ~(MSR_FE0 | MSR_FE1);
}
fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX |
FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
PPCMtfpscr(fpscr);
PPCMtmsr(msr);
}
OSRestoreInterrupts(enabled);
return oldHandler;
}
void __OSUnhandledException(__OSException exception, OSContext* context, u32 dsisr, u32 dar) {
OSTime now;
now = OSGetTime();
if (!(context->srr1 & 2)) {
OSReport("Non-recoverable Exception %d", exception);
} else {
if (exception == EXCEPTION_PROGRAM && (context->srr1 & (0x80000000 >> 11)) &&
__OSErrorTable[EXCEPTION_FLOATING_POINT_EXCEPTION] != 0)
{
u32 fpscr;
u32 msr;
exception = EXCEPTION_FLOATING_POINT_EXCEPTION;
msr = PPCMfmsr();
PPCMtmsr(msr | 0x2000);
if (__OSFPUContext) {
OSSaveFPUContext((OSContext*)__OSFPUContext);
}
fpscr = PPCMffpscr();
fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
PPCMtfpscr(fpscr);
PPCMtmsr(msr);
if (__OSFPUContext == context) {
OSDisableScheduler();
__OSErrorTable[exception](exception, context, dsisr, dar);
context->srr1 &= ~0x2000;
__OSFPUContext = NULL;
context->fpscr &=
~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
OSEnableScheduler();
__OSReschedule();
} else {
context->srr1 &= ~0x2000;
__OSFPUContext = NULL;
}
OSLoadContext(context);
}
if (__OSErrorTable[exception]) {
OSDisableScheduler();
__OSErrorTable[exception](exception, context, dsisr, dar);
OSEnableScheduler();
__OSReschedule();
OSLoadContext(context);
}
if (exception == OS_ERROR_DECREMENTER) {
OSLoadContext(context);
}
OSReport("Unhandled Exception %d", exception);
}
OSReport("\n");
OSDumpContext(context);
OSReport("\nDSISR = 0x%08x DAR = 0x%08x\n", dsisr, dar);
OSReport("TB = 0x%016llx\n", now);
switch (exception) {
case EXCEPTION_DSI:
OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access "
"invalid address 0x%x (read from DAR)\n",
context->srr0, dar);
break;
case EXCEPTION_ISI:
OSReport("\nAttempted to fetch instruction from invalid address 0x%x "
"(read from SRR0)\n",
context->srr0);
break;
case EXCEPTION_ALIGNMENT:
OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access "
"unaligned address 0x%x (read from DAR)\n",
context->srr0, dar);
break;
case EXCEPTION_PROGRAM:
OSReport("\nProgram exception : Possible illegal instruction/operation "
"at or around 0x%x (read from SRR0)\n",
context->srr0, dar);
break;
case EXCEPTION_MEMORY_PROTECTION:
OSReport("\n");
OSReport("AI DMA Address = 0x%04x%04x\n", __DSPRegs[DSP_DMA_START_HI],
__DSPRegs[DSP_DMA_START_LO]);
OSReport("ARAM DMA Address = 0x%04x%04x\n", __DSPRegs[DSP_ARAM_DMA_MM_HI],
__DSPRegs[DSP_ARAM_DMA_MM_LO]);
OSReport("DI DMA Address = 0x%08x\n", __DIRegs[5]);
break;
}
OSReport("\nLast interrupt (%d): SRR0 = 0x%08x TB = 0x%016llx\n", __OSLastInterrupt,
__OSLastInterruptSrr0, __OSLastInterruptTime);
PPCHalt();
}

299
src/dolphin/os/OSExec.c Normal file
View File

@ -0,0 +1,299 @@
//
// Generated By: dol2asm
// Translation Unit: OSExec
//
#include "dolphin/os/OSExec.h"
#include "dolphin/os/OS.h"
#include "dolphin/ai.h"
#include "dol2asm.h"
#include "string.h"
#include "printf.h"
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
static asm s32 PackArgs(void* param_0, u32 param_1, void* param_2) {
nofralloc
#include "asm/dolphin/os/OSExec/PackArgs.s"
}
#pragma pop
static asm void Run(int param_0) {
// clang-format off
nofralloc
mflr r0
stw r0, 4(r1)
stwu r1, -0x18(r1)
stw r31, 0x14(r1)
mr r31, r3
bl ICFlashInvalidate
sync
isync
mtlr r31
blr
lwz r0, 0x1c(r1)
lwz r31, 0x14(r1)
addi r1, r1, 0x18
mtlr r0
blr
// clang-format on
}
static void ReadDisc(void* param_0, s32 param_1, s32 param_2) {
DVDCommandBlock cmd;
DVDReadAbsAsyncPrio(&cmd, param_0, param_1, param_2, NULL, 0);
while (DVDGetCommandBlockStatus(&cmd)) {
if (!DVDCheckDisk()) {
__OSDoHotReset(0);
}
}
}
static BOOL Prepared;
static void Callback(void) {
Prepared = TRUE;
}
OSExecParams* osExecParams : 0x800030f0;
void __OSGetExecParams(OSExecParams* param_0) {
if (OSPhysicalToCached(0) <= osExecParams) {
memcpy(param_0, osExecParams, sizeof(OSExecParams));
} else {
param_0->valid = FALSE;
}
}
static __OSSetExecParams(const OSExecParams* src, OSExecParams* dst) {
memcpy(dst, src, sizeof(OSExecParams));
osExecParams = dst;
}
static s32 apploaderPosition;
s32 appLoaderOffset : 0x800030f4;
static int GetApploaderPosition(void) {
u8 padding[8];
if (apploaderPosition != 0) {
return apploaderPosition;
}
if (appLoaderOffset) {
void* buffer = OSAllocFromArenaLo(0x40, 0x20);
ReadDisc(buffer, 0x40, appLoaderOffset);
apploaderPosition = appLoaderOffset + ((s32*)buffer)[0xe];
} else {
apploaderPosition = 0x2440;
}
return apploaderPosition;
}
SECTION_DATA static char lit_115[] = "2004/02/01";
// GetApploaderPosition inline issue + end of function
#ifdef NONMATCHING
typedef int (*AppLoaderInnerCallback)(void*, s32*, s32*);
typedef void (*LogCallback)(void*);
typedef void (*AppLoaderCallback)(LogCallback*, AppLoaderInnerCallback*, int (**callback)(void));
typedef struct {
char version[10];
s16 field_0xa;
s32 field_0xc;
AppLoaderCallback field_0x10;
s32 field_0x14;
s32 field_0x18;
s32 field_0x1c;
} AppLoaderStruct;
static AppLoaderStruct* LoadApploader() {
AppLoaderStruct* iVar1;
s32 pos;
s32 nextPos;
iVar1 = (AppLoaderStruct*)OSAllocFromArenaLo(sizeof(AppLoaderStruct), sizeof(AppLoaderStruct));
pos = GetApploaderPosition();
ReadDisc(iVar1, sizeof(AppLoaderStruct), pos);
nextPos = GetApploaderPosition();
ReadDisc((void*)0x81200000, iVar1->field_0x14 + 0x1fU & 0xffffffe0, nextPos + 0x20);
ICInvalidateRange((void*)0x81200000, iVar1->field_0x14 + 0x1fU & 0xffffffe0);
return iVar1;
}
static BOOL IsNewApploader(const char* version) {
BOOL rv;
if (strncmp(version, "2004/02/01", 10) > 0) {
rv = TRUE;
} else {
rv = FALSE;
}
return rv;
}
static int LoadDol(OSExecParams* def, AppLoaderCallback cb) {
LogCallback local_c;
AppLoaderInnerCallback innercb;
int (*local_14)(void);
OSExecParams* execParams;
void* local_18;
s32 local_1c;
s32 local_20;
cb(&local_c, &innercb, &local_14);
execParams = OSAllocFromArenaLo(sizeof(OSExecParams), 1);
__OSSetExecParams(def, execParams);
local_c(OSReport);
OSSetArenaLo(execParams);
while (innercb(&local_18, &local_1c, &local_20)) {
ReadDisc(local_18, local_1c, local_20);
}
return (*local_14)();
}
static void StartDol(OSExecParams* execParams, int param_1) {
OSExecParams* uVar1 = (OSExecParams*)OSAllocFromArenaLo(sizeof(OSExecParams), 1);
__OSSetExecParams(execParams, uVar1);
__PIRegs[9] = 7;
OSDisableInterrupts();
Run(param_1);
}
u8 DAT_800030e2 : 0x800030E2;
void __OSBootDolSimple(u32 param_0, u32 param_1, void* param_2, void* param_3, s32 param_4, u32 param_5, void* param_6) {
OSExecParams* puVar1;
AppLoaderStruct* iVar3;
DVDDiskID* id;
int uVar2;
s32 iVar4;
s32 is_streaming;
DVDCommandBlock cmd;
OSDisableInterrupts();
puVar1 = (OSExecParams*)OSAllocFromArenaLo(sizeof(OSExecParams), 1);
puVar1->valid = 1;
puVar1->restartCode = param_1;
puVar1->regionStart = param_2;
puVar1->regionEnd = param_3;
puVar1->argsUseDefault = param_4;
if (param_4 == 0) {
puVar1->argsAddr = OSAllocFromArenaLo(0x2000, 1);
PackArgs(puVar1->argsAddr, param_5, param_6);
}
DVDInit();
DVDSetAutoInvalidation(TRUE);
DVDResume();
Prepared = FALSE;
__DVDPrepareResetAsync((DVDCBCallback)Callback);
__OSMaskInterrupts(0xffffffe0);
__OSUnmaskInterrupts(0x400);
OSEnableInterrupts();
while (Prepared != TRUE) {
if (!DVDCheckDisk()) {
__OSDoHotReset(0);
}
}
if (!__OSIsGcam) {
id = DVDGetCurrentDiskID();
if (id->is_streaming) {
is_streaming = TRUE;
} else {
is_streaming = FALSE;
}
if (is_streaming) {
AISetStreamVolLeft(0);
AISetStreamVolRight(0);
DVDCancelStreamAsync(&cmd, NULL);
while (DVDGetCommandBlockStatus(&cmd)) {
if (!DVDCheckDisk()) {
__OSDoHotReset(0);
}
}
AISetStreamPlayState(0);
}
}
iVar3 = LoadApploader();
if (IsNewApploader(iVar3->version)) {
if (param_0 == -1) {
param_0 = GetApploaderPosition();
param_0 += iVar3->field_0x14;
param_0 += 0x20;
}
puVar1->bootDol = param_0;
uVar2 = LoadDol(puVar1, iVar3->field_0x10);
StartDol(puVar1, uVar2);
} else {
BOOT_REGION_START = (u32)param_2;
BOOT_REGION_END = (u32)param_3;
DAT_800030e2 = 1;
// GetApploaderPosition is inlined for some reason
iVar4 = GetApploaderPosition() + iVar3->field_0x14;
ReadDisc((void*)0x81300000, iVar3->field_0x18 + 0x1fU & 0xffffffe0,
iVar4 + 0x20);
ICInvalidateRange((void*)0x81300000, iVar3->field_0x18 + 0x1fU & 0xffffffe0);
OSDisableInterrupts();
ICFlashInvalidate();
Run(0x81300000);
}
}
#else
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
asm void __OSBootDolSimple(u32 param_0, u32 param_1, void* param_2, void* param_3, s32 param_4, u32 param_5, void* param_6) {
nofralloc
#include "asm/dolphin/os/OSExec/__OSBootDolSimple.s"
}
#pragma pop
#endif
SECTION_SDATA static char lit_213[] = "%d";
#ifdef NONMATCHING
void __OSBootDol(s32 param_0, u32 param_1, char** param_2) {
char acStack_28[20];
void* local_2c;
void* local_30;
s32 iVar3;
char** ppcVar1;
char** ppcVar2;
char** ppcVarDst;
char** ppcVarSrc;
int iVar2;
OSGetSaveRegion(&local_2c, &local_30);
sprintf(acStack_28, "%d", param_0);
iVar3 = 0;
if (param_2 != NULL) {
ppcVar2 = param_2;
while (*ppcVar2 != NULL) {
ppcVar2++;
iVar3++;
}
}
ppcVar1 = (char**)OSAllocFromArenaLo((iVar3 + 2) * 4, 1);
*ppcVar1 = acStack_28;
ppcVarSrc = param_2;
ppcVarDst = ppcVar1 + 1;
for (iVar2 = 1; iVar2 < iVar3 + 1; iVar2++) {
*ppcVarDst++ = *ppcVarSrc++;
}
__OSBootDolSimple(0xffffffff, param_1, local_2c, local_30, 0, iVar3 + 1, ppcVar1);
}
#else
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
asm void __OSBootDol(s32 param_0, u32 param_1, char** param_2) {
nofralloc
#include "asm/dolphin/os/OSExec/__OSBootDol.s"
}
#pragma pop
#endif

303
src/dolphin/os/OSFont.c Normal file
View File

@ -0,0 +1,303 @@
#include "dolphin/os/OSFont.h"
#include "dolphin/os/OS.h"
#include "dolphin/vi/vi.h"
static u16 HankakuToCode[192] = {
0x020C, 0x020D, 0x020E, 0x020F, 0x0210, 0x0211, 0x0212, 0x0213,
0x0214, 0x0215, 0x0216, 0x0217, 0x0218, 0x0219, 0x021A, 0x021B,
0x021C, 0x021D, 0x021E, 0x021F, 0x0220, 0x0221, 0x0222, 0x0223,
0x0224, 0x0225, 0x0226, 0x0227, 0x0228, 0x0229, 0x022A, 0x022B,
0x022C, 0x022D, 0x022E, 0x022F, 0x0230, 0x0231, 0x0232, 0x0233,
0x0234, 0x0235, 0x0236, 0x0237, 0x0238, 0x0239, 0x023A, 0x023B,
0x023C, 0x023D, 0x023E, 0x023F, 0x0240, 0x0241, 0x0242, 0x0243,
0x0244, 0x0245, 0x0246, 0x0247, 0x0248, 0x0249, 0x024A, 0x024B,
0x024C, 0x024D, 0x024E, 0x024F, 0x0250, 0x0251, 0x0252, 0x0253,
0x0254, 0x0255, 0x0256, 0x0257, 0x0258, 0x0259, 0x025A, 0x025B,
0x025C, 0x025D, 0x025E, 0x025F, 0x0260, 0x0261, 0x0262, 0x0263,
0x0264, 0x0265, 0x0266, 0x0267, 0x0268, 0x0269, 0x026A, 0x020C,
0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C,
0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C,
0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C,
0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C, 0x020C,
0x020C, 0x026B, 0x026C, 0x026D, 0x026E, 0x026F, 0x0270, 0x0271,
0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, 0x0278, 0x0279,
0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, 0x0280, 0x0281,
0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289,
0x028A, 0x028B, 0x028C, 0x028D, 0x028E, 0x028F, 0x0290, 0x0291,
0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, 0x0298, 0x0299,
0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1,
0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9,
};
static u16 Zenkaku2Code[1221] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006A, 0x006B, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x006C,
0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0074,
0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081,
0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x008A,
0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091, 0x0000,
0x0000, 0x0000, 0x0000, 0x0092, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x009D, 0x009E, 0x009F, 0x00A0,
0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8,
0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0,
0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x00B7, 0x00B8, 0x00B9, 0x00BA,
0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2,
0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA,
0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x0000, 0x0000,
0x0000, 0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6,
0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE,
0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6,
0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE,
0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6,
0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE,
0x00FF, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E,
0x010F, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
0x0117, 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E,
0x011F, 0x0120, 0x0121, 0x0122, 0x0123, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129, 0x012A, 0x012B,
0x012C, 0x012D, 0x012E, 0x012F, 0x0130, 0x0131, 0x0132, 0x0133,
0x0134, 0x0135, 0x0136, 0x0137, 0x0138, 0x0139, 0x013A, 0x013B,
0x013C, 0x013D, 0x013E, 0x013F, 0x0140, 0x0141, 0x0142, 0x0143,
0x0144, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149, 0x014A, 0x014B,
0x014C, 0x014D, 0x014E, 0x014F, 0x0150, 0x0151, 0x0152, 0x0153,
0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015A, 0x015B,
0x015C, 0x015D, 0x015E, 0x015F, 0x0160, 0x0161, 0x0162, 0x0163,
0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016A, 0x016B,
0x016C, 0x016D, 0x016E, 0x016F, 0x0170, 0x0171, 0x0172, 0x0173,
0x0174, 0x0175, 0x0176, 0x0177, 0x0178, 0x0179, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x017A, 0x017B,
0x017C, 0x017D, 0x017E, 0x017F, 0x0180, 0x0181, 0x0182, 0x0183,
0x0184, 0x0185, 0x0186, 0x0187, 0x0188, 0x0189, 0x018A, 0x018B,
0x018C, 0x018D, 0x018E, 0x018F, 0x0190, 0x0191, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0193,
0x0194, 0x0195, 0x0196, 0x0197, 0x0198, 0x0199, 0x019A, 0x019B,
0x019C, 0x019D, 0x019E, 0x019F, 0x01A0, 0x01A1, 0x01A2, 0x01A3,
0x01A4, 0x01A5, 0x01A6, 0x01A7, 0x01A8, 0x01A9, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x01AA, 0x01AB, 0x01AC, 0x01AD,
0x01AE, 0x01AF, 0x01B0, 0x01B1, 0x01B2, 0x01B3, 0x01B4, 0x01B5,
0x01B6, 0x01B7, 0x01B8, 0x01B9, 0x01BA, 0x01BB, 0x01BC, 0x01BD,
0x01BE, 0x01BF, 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5,
0x01C6, 0x01C7, 0x01C8, 0x01C9, 0x01CA, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x01CB, 0x01CC, 0x01CD, 0x01CE,
0x01CF, 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6,
0x01D7, 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE,
0x01DF, 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E4, 0x01E5, 0x01E6,
0x01E7, 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x01EC, 0x01ED, 0x01EE, 0x01EF, 0x01F0, 0x01F1,
0x01F2, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9,
0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, 0x0200, 0x0201,
0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
0x020A, 0x020B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x020C,
0x020D, 0x020E, 0x020F, 0x0210, 0x0211, 0x0212, 0x0213, 0x0214,
0x0215, 0x0216, 0x0217, 0x0218, 0x0219, 0x021A, 0x021B, 0x021C,
0x021D, 0x021E, 0x021F, 0x0220, 0x0221, 0x0222, 0x0223, 0x0224,
0x0225, 0x0226, 0x0227, 0x0228, 0x0229, 0x022A, 0x022B, 0x022C,
0x022D, 0x022E, 0x022F, 0x0230, 0x0231, 0x0232, 0x0233, 0x0234,
0x0235, 0x0236, 0x0237, 0x0238, 0x0239, 0x023A, 0x023B, 0x023C,
0x023D, 0x023E, 0x023F, 0x0240, 0x0241, 0x0242, 0x0243, 0x0244,
0x0245, 0x0246, 0x0247, 0x0248, 0x0249, 0x024A, 0x024B, 0x024C,
0x024D, 0x024E, 0x024F, 0x0250, 0x0251, 0x0252, 0x0253, 0x0254,
0x0255, 0x0256, 0x0257, 0x0258, 0x0259, 0x025A, 0x025B, 0x025C,
0x025D, 0x025E, 0x025F, 0x0260, 0x0261, 0x0262, 0x0263, 0x0264,
0x0265, 0x0266, 0x0267, 0x0268, 0x0269, 0x026A, 0x026B, 0x026C,
0x026D, 0x026E, 0x026F, 0x0270, 0x0271, 0x0272, 0x0273, 0x0274,
0x0275, 0x0276, 0x0277, 0x0278, 0x0279, 0x027A, 0x027B, 0x027C,
0x027D, 0x027E, 0x027F, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284,
0x0285, 0x0286, 0x0287, 0x0288, 0x0289, 0x028A, 0x028B, 0x028C,
0x028D, 0x028E, 0x028F, 0x0290, 0x0291, 0x0292, 0x0293, 0x0294,
0x0295, 0x0296, 0x0297, 0x0298, 0x0299, 0x029A, 0x029B, 0x029C,
0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4,
0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC,
0x02AD, 0x02AE, 0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4,
0x02B5, 0x02B6, 0x02B7, 0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC,
0x02BD, 0x02BE, 0x02BF, 0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4,
0x02C5, 0x02C6, 0x02C7, 0x02C8, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF, 0x02D0,
0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, 0x02D8,
0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF, 0x02E0,
0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x0000, 0x02E7,
0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF,
0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7,
0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x02FE, 0x02FF,
0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
0x0318, 0x0319, 0x031A, 0x031B, 0x0000,
};
static BOOL IsSjisLeadByte(u8 ch) {
return (0x81 <= ch && ch <= 0x9F) || (0xE0 <= ch && ch <= 0xFC);
}
static BOOL IsSjisTrailByte(u8 ch) {
return (0x40 <= ch && ch <= 0xFC) && (ch != 0x7F);
}
static u32 GetFontCode(u16 encode, u16 code) {
u32 tmp;
s32 trail;
if (encode == OS_FONT_ENCODE_SJIS) {
if (0x20 <= code && code <= 0xDF) {
return HankakuToCode[code - 0x20];
} else if (0x889E < code && code <= 0x9872) {
tmp = ((code >> 8) - 0x88) * 0xBC;
trail = code & 0xFF;
if (!IsSjisTrailByte(trail)) {
return 0;
}
trail -= 0x40;
if (trail >= 0x40) {
trail--;
}
return tmp + trail + 0x2BE;
} else if (0x8140 <= code && code < 0x879E) {
tmp = ((code >> 8) - 0x81) * 0xBC;
trail = code & 0xFF;
if (!IsSjisTrailByte(trail)) {
return 0;
}
trail -= 0x40;
if (trail >= 0x40) {
trail--;
}
return Zenkaku2Code[tmp + trail];
}
} else if (code > 0x20 && code <= 0xFF) {
return code - 0x20;
}
return 0;
}
static u16 FontEncode = 0xFFFF;
static OSFontHeader* FontDataAnsi;
static OSFontHeader* FontDataSjis;
static void* ParseString;
u16 OSGetFontEncode(void) {
if (FontEncode != 0xFFFF) {
return FontEncode;
}
switch (*(u32*)OSPhysicalToCached(0xCC)) {
case VI_NTSC:
FontEncode = ((__VIRegs[55] & 2) != 0)
? OS_FONT_ENCODE_SJIS
: OS_FONT_ENCODE_ANSI;
break;
case VI_PAL:
case VI_MPAL:
case VI_DEBUG:
case VI_DEBUG_PAL:
case VI_EURGB60:
default:
FontEncode = OS_FONT_ENCODE_ANSI;
}
ParseString = ParseStringS;
return FontEncode;
}
static const u8* ParseStringS(u16 encode, const u8* str, OSFontHeader** fontOut,
u32* codeOut) {
OSFontHeader* font;
u16 code = 0;
switch (encode) {
case OS_FONT_ENCODE_ANSI:
font = FontDataAnsi;
code = *str;
if (code != 0) {
str++;
}
break;
case OS_FONT_ENCODE_SJIS:
font = FontDataSjis;
code = *str;
if (code == 0) {
break;
}
str++;
if (IsSjisLeadByte(code) && IsSjisTrailByte(*str)) {
code = (code << 8 | *str++);
}
break;
}
*fontOut = font;
*codeOut = GetFontCode(encode, code);
return str;
}

View File

@ -0,0 +1,430 @@
#include "dolphin/os/OSInterrupt.h"
#include "dolphin/dsp.h"
#include "dolphin/exi/EXIBios.h"
#include "dolphin/os/OS.h"
vu32 __PIRegs[12] : 0xCC003000;
vu16 __MEMRegs[64] : 0xCC004000;
asm BOOL OSDisableInterrupts(void) {
// clang-format off
nofralloc
entry __RAS_OSDisableInterrupts_begin
mfmsr r3
// Clear external interrupts bit
rlwinm r4, r3, 0, 17, 15
mtmsr r4
entry __RAS_OSDisableInterrupts_end
// Return old interrupt status
rlwinm r3, r3, 17, 31, 31
blr
// clang-format on
}
asm BOOL OSEnableInterrupts(void) {
// clang-format off
nofralloc
mfmsr r3
// Set external interrupts bit
ori r4, r3, (1 << 15)
mtmsr r4
// Return old interrupt status
rlwinm r3, r3, 17, 31, 31
blr
// clang-format on
}
asm BOOL OSRestoreInterrupts(register BOOL status) {
// clang-format off
nofralloc
cmpwi status, 0
mfmsr r4
beq disable
// Set external interrupts bit
ori r5, r4, (1 << 15)
b set_msr
disable:
// Clear external interrupts bit
rlwinm r5, r4, 0, 17, 15
set_msr:
mtmsr r5
// Return old interrupt status
rlwinm r3, r4, 17, 31, 31
blr
// clang-format on
}
static __OSInterruptHandler* InterruptHandlerTable;
__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt type, __OSInterruptHandler handler) {
__OSInterruptHandler old = InterruptHandlerTable[type];
InterruptHandlerTable[type] = handler;
return old;
}
__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt type) {
return InterruptHandlerTable[type];
}
void __OSInterruptInit(void) {
InterruptHandlerTable = OSPhysicalToCached(0x3040);
memset(InterruptHandlerTable, 0, 32 * sizeof(__OSInterruptHandler));
*(OSInterruptMask*)OSPhysicalToCached(0x00C4) = 0;
*(OSInterruptMask*)OSPhysicalToCached(0x00C8) = 0;
__PIRegs[1] = 0xf0;
__OSMaskInterrupts(OS_INTERRUPTMASK_MEM | OS_INTERRUPTMASK_DSP | OS_INTERRUPTMASK_AI |
OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI);
__OSSetExceptionHandler(4, (OSExceptionHandler)ExternalInterruptHandler);
}
u32 SetInterruptMask(OSInterruptMask mask, OSInterruptMask current) {
u32 reg;
switch (__cntlzw(mask)) {
case OS_INTR_MEM_0:
case OS_INTR_MEM_1:
case OS_INTR_MEM_2:
case OS_INTR_MEM_3:
case OS_INTR_MEM_ADDRESS:
reg = 0;
if (!(current & OS_INTERRUPTMASK_MEM_0))
reg |= 0x1;
if (!(current & OS_INTERRUPTMASK_MEM_1))
reg |= 0x2;
if (!(current & OS_INTERRUPTMASK_MEM_2))
reg |= 0x4;
if (!(current & OS_INTERRUPTMASK_MEM_3))
reg |= 0x8;
if (!(current & OS_INTERRUPTMASK_MEM_ADDRESS))
reg |= 0x10;
__MEMRegs[0x0000000e] = (u16)reg;
mask &= ~OS_INTERRUPTMASK_MEM;
break;
case OS_INTR_DSP_AI:
case OS_INTR_DSP_ARAM:
case OS_INTR_DSP_DSP:
reg = __DSPRegs[0x00000005];
reg &= ~0x1F8;
if (!(current & OS_INTERRUPTMASK_DSP_AI))
reg |= 0x10;
if (!(current & OS_INTERRUPTMASK_DSP_ARAM))
reg |= 0x40;
if (!(current & OS_INTERRUPTMASK_DSP_DSP))
reg |= 0x100;
__DSPRegs[0x00000005] = (u16)reg;
mask &= ~OS_INTERRUPTMASK_DSP;
break;
case OS_INTR_AI_AI:
reg = __AIRegs[0];
reg &= ~0x2C;
if (!(current & OS_INTERRUPTMASK_AI_AI))
reg |= 0x4;
__AIRegs[0] = reg;
mask &= ~OS_INTERRUPTMASK_AI;
break;
case OS_INTR_EXI_0_EXI:
case OS_INTR_EXI_0_TC:
case OS_INTR_EXI_0_EXT:
reg = __EXIRegs[0];
reg &= ~0x2C0F;
if (!(current & OS_INTERRUPTMASK_EXI_0_EXI))
reg |= 0x1;
if (!(current & OS_INTERRUPTMASK_EXI_0_TC))
reg |= 0x4;
if (!(current & OS_INTERRUPTMASK_EXI_0_EXT))
reg |= 0x400;
__EXIRegs[0] = reg;
mask &= ~OS_INTERRUPTMASK_EXI_0;
break;
case OS_INTR_EXI_1_EXI:
case OS_INTR_EXI_1_TC:
case OS_INTR_EXI_1_EXT:
reg = __EXIRegs[5];
reg &= ~0xC0F;
if (!(current & OS_INTERRUPTMASK_EXI_1_EXI))
reg |= 0x1;
if (!(current & OS_INTERRUPTMASK_EXI_1_TC))
reg |= 0x4;
if (!(current & OS_INTERRUPTMASK_EXI_1_EXT))
reg |= 0x400;
__EXIRegs[5] = reg;
mask &= ~OS_INTERRUPTMASK_EXI_1;
break;
case OS_INTR_EXI_2_EXI:
case OS_INTR_EXI_2_TC:
reg = __EXIRegs[10];
reg &= ~0xF;
if (!(current & OS_INTERRUPTMASK_EXI_2_EXI))
reg |= 0x1;
if (!(current & OS_INTERRUPTMASK_EXI_2_TC))
reg |= 0x4;
__EXIRegs[10] = reg;
mask &= ~OS_INTERRUPTMASK_EXI_2;
break;
case OS_INTR_PI_CP:
case OS_INTR_PI_SI:
case OS_INTR_PI_DI:
case OS_INTR_PI_RSW:
case OS_INTR_PI_ERROR:
case OS_INTR_PI_VI:
case OS_INTR_PI_DEBUG:
case OS_INTR_PI_PE_TOKEN:
case OS_INTR_PI_PE_FINISH:
case OS_INTR_PI_HSP:
reg = 0xF0;
if (!(current & OS_INTERRUPTMASK_PI_CP)) {
reg |= 0x800;
}
if (!(current & OS_INTERRUPTMASK_PI_SI)) {
reg |= 0x8;
}
if (!(current & OS_INTERRUPTMASK_PI_DI)) {
reg |= 0x4;
}
if (!(current & OS_INTERRUPTMASK_PI_RSW)) {
reg |= 0x2;
}
if (!(current & OS_INTERRUPTMASK_PI_ERROR)) {
reg |= 0x1;
}
if (!(current & OS_INTERRUPTMASK_PI_VI)) {
reg |= 0x100;
}
if (!(current & OS_INTERRUPTMASK_PI_DEBUG)) {
reg |= 0x1000;
}
if (!(current & OS_INTERRUPTMASK_PI_PE_TOKEN)) {
reg |= 0x200;
}
if (!(current & OS_INTERRUPTMASK_PI_PE_FINISH)) {
reg |= 0x400;
}
if (!(current & OS_INTERRUPTMASK_PI_HSP)) {
reg |= 0x2000;
}
__PIRegs[1] = reg;
mask &= ~OS_INTERRUPTMASK_PI;
break;
default:
break;
}
return mask;
}
OSInterruptMask __OSMaskInterrupts(OSInterruptMask global) {
BOOL enabled;
OSInterruptMask prev;
OSInterruptMask local;
OSInterruptMask mask;
enabled = OSDisableInterrupts();
prev = *(OSInterruptMask*)OSPhysicalToCached(0x00C4);
local = *(OSInterruptMask*)OSPhysicalToCached(0x00C8);
mask = ~(prev | local) & global;
global |= prev;
*(OSInterruptMask*)OSPhysicalToCached(0x00C4) = global;
while (mask) {
mask = SetInterruptMask(mask, global | local);
}
OSRestoreInterrupts(enabled);
return prev;
}
OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask global) {
BOOL enabled;
OSInterruptMask prev;
OSInterruptMask local;
OSInterruptMask mask;
enabled = OSDisableInterrupts();
prev = *(OSInterruptMask*)OSPhysicalToCached(0x00C4);
local = *(OSInterruptMask*)OSPhysicalToCached(0x00C8);
mask = (prev | local) & global;
global = prev & ~global;
*(OSInterruptMask*)OSPhysicalToCached(0x00C4) = global;
while (mask) {
mask = SetInterruptMask(mask, global | local);
}
OSRestoreInterrupts(enabled);
return prev;
}
static u32 InterruptPrioTable[] = {
0x00000100, 0x00000040, 0xF8000000, 0x00000200, 0x00000080, 0x00003000,
0x00000020, 0x03FF8C00, 0x04000000, 0x00004000, 0xFFFFFFFF,
};
extern OSTime __OSLastInterruptTime;
OSTime __OSLastInterruptTime;
extern s16 __OSLastInterrupt;
s16 __OSLastInterrupt;
extern u32 __OSLastInterruptSrr0;
u32 __OSLastInterruptSrr0;
void __OSDispatchInterrupt(__OSException exception, OSContext* context) {
u32 intsr;
u32 reg;
OSInterruptMask cause;
OSInterruptMask unmasked;
OSInterruptMask* prio;
__OSInterrupt interrupt;
__OSInterruptHandler handler;
intsr = __PIRegs[0];
intsr &= ~0x00010000;
if (intsr == 0 || (intsr & __PIRegs[1]) == 0) {
OSLoadContext(context);
}
cause = 0;
if (intsr & 0x00000080) {
reg = __MEMRegs[15];
if (reg & 0x1)
cause |= OS_INTERRUPTMASK_MEM_0;
if (reg & 0x2)
cause |= OS_INTERRUPTMASK_MEM_1;
if (reg & 0x4)
cause |= OS_INTERRUPTMASK_MEM_2;
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_MEM_3;
if (reg & 0x10)
cause |= OS_INTERRUPTMASK_MEM_ADDRESS;
}
if (intsr & 0x00000040) {
reg = __DSPRegs[5];
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_DSP_AI;
if (reg & 0x20)
cause |= OS_INTERRUPTMASK_DSP_ARAM;
if (reg & 0x80)
cause |= OS_INTERRUPTMASK_DSP_DSP;
}
if (intsr & 0x00000020) {
reg = __AIRegs[0];
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_AI_AI;
}
if (intsr & 0x00000010) {
reg = __EXIRegs[0];
if (reg & 0x2)
cause |= OS_INTERRUPTMASK_EXI_0_EXI;
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_EXI_0_TC;
if (reg & 0x800)
cause |= OS_INTERRUPTMASK_EXI_0_EXT;
reg = __EXIRegs[5];
if (reg & 0x2)
cause |= OS_INTERRUPTMASK_EXI_1_EXI;
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_EXI_1_TC;
if (reg & 0x800)
cause |= OS_INTERRUPTMASK_EXI_1_EXT;
reg = __EXIRegs[10];
if (reg & 0x2)
cause |= OS_INTERRUPTMASK_EXI_2_EXI;
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_EXI_2_TC;
}
if (intsr & 0x00002000)
cause |= OS_INTERRUPTMASK_PI_HSP;
if (intsr & 0x00001000)
cause |= OS_INTERRUPTMASK_PI_DEBUG;
if (intsr & 0x00000400)
cause |= OS_INTERRUPTMASK_PI_PE_FINISH;
if (intsr & 0x00000200)
cause |= OS_INTERRUPTMASK_PI_PE_TOKEN;
if (intsr & 0x00000100)
cause |= OS_INTERRUPTMASK_PI_VI;
if (intsr & 0x00000008)
cause |= OS_INTERRUPTMASK_PI_SI;
if (intsr & 0x00000004)
cause |= OS_INTERRUPTMASK_PI_DI;
if (intsr & 0x00000002)
cause |= OS_INTERRUPTMASK_PI_RSW;
if (intsr & 0x00000800)
cause |= OS_INTERRUPTMASK_PI_CP;
if (intsr & 0x00000001)
cause |= OS_INTERRUPTMASK_PI_ERROR;
unmasked = cause & ~(*(OSInterruptMask*)OSPhysicalToCached(0x00C4) |
*(OSInterruptMask*)OSPhysicalToCached(0x00C8));
if (unmasked) {
for (prio = InterruptPrioTable;; ++prio) {
if (unmasked & *prio) {
interrupt = (__OSInterrupt)__cntlzw(unmasked & *prio);
break;
}
}
handler = __OSGetInterruptHandler(interrupt);
if (handler) {
if (OS_INTR_MEM_ADDRESS < interrupt) {
__OSLastInterrupt = interrupt;
__OSLastInterruptTime = OSGetTime();
__OSLastInterruptSrr0 = context->srr0;
}
OSDisableScheduler();
handler(interrupt, context);
OSEnableScheduler();
__OSReschedule();
OSLoadContext(context);
}
}
OSLoadContext(context);
}
static asm void ExternalInterruptHandler(register __OSInterrupt type, register OSContext* context) {
// clang-format off
nofralloc
stw r0, context->gpr[0]
stw r1, context->gpr[1]
stw r2, context->gpr[2]
stmw r6, context->gpr[6]
mfspr r0, GQR1
stw r0, context->gqr[1]
mfspr r0, GQR2
stw r0, context->gqr[2]
mfspr r0, GQR3
stw r0, context->gqr[3]
mfspr r0, GQR4
stw r0, context->gqr[4]
mfspr r0, GQR5
stw r0, context->gqr[5]
mfspr r0, GQR6
stw r0, context->gqr[6]
mfspr r0, GQR7
stw r0, context->gqr[7]
stwu r1, -8(r1)
b __OSDispatchInterrupt
// clang-format on
}

474
src/dolphin/os/OSLink.c Normal file
View File

@ -0,0 +1,474 @@
#include "dolphin/os/OS.h"
#define SHN_UNDEF 0
#define SHN_LORESERVE 0xff00
#define SHN_LOPROC 0xff00
#define SHN_HIPROC 0xff1f
#define SHN_ABS 0xfff1
#define SHN_COMMON 0xfff2
#define SHN_HIRESERVE 0xffff
#define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
// Name Value Field Calculation
#define R_PPC_NONE 0 // none none
#define R_PPC_ADDR32 1 // word32 S + A
#define R_PPC_ADDR24 2 // low24* (S + A) >> 2
#define R_PPC_ADDR16 3 // half16* S + A
#define R_PPC_ADDR16_LO 4 // half16 #lo(S + A)
#define R_PPC_ADDR16_HI 5 // half16 #hi(S + A)
#define R_PPC_ADDR16_HA 6 // half16 #ha(S + A)
#define R_PPC_ADDR14 7 // low14* (S + A) >> 2
#define R_PPC_ADDR14_BRTAKEN 8 // low14* (S + A) >> 2
#define R_PPC_ADDR14_BRNTAKEN 9 // low14* (S + A) >> 2
#define R_PPC_REL24 10 // low24* (S + A - P) >> 2
#define R_PPC_REL14 11 // low14* (S + A - P) >> 2
#define R_PPC_REL14_BRTAKEN 12 // low14* (S + A - P) >> 2
#define R_PPC_REL14_BRNTAKEN 13 // low14* (S + A - P) >> 2
#define R_PPC_GOT16 14 // half16* G + A
#define R_PPC_GOT16_LO 15 // half16 #lo(G + A)
#define R_PPC_GOT16_HI 16 // half16 #hi(G + A)
#define R_PPC_GOT16_HA 17 // half16 #ha(G + A)
#define R_PPC_PLTREL24 18 // low24* (L + A - P) >> 2
#define R_PPC_COPY 19 // none none
#define R_PPC_GLOB_DAT 20 // word32 S + A
#define R_PPC_JMP_SLOT 21 // none
#define R_PPC_RELATIVE 22 // word32 B + A
#define R_PPC_LOCAL24PC 23 // low24*
#define R_PPC_UADDR32 24 // word32 S + A
#define R_PPC_UADDR16 25 // half16* S + A
#define R_PPC_REL32 26 // word32 S + A - P
#define R_PPC_PLT32 27 // word32 L + A
#define R_PPC_PLTREL32 28 // word32 L + A - P
#define R_PPC_PLT16_LO 29 // half16 #lo(L + A)
#define R_PPL_PLT16_HI 30 // half16 #hi(L + A)
#define R_PPC_PLT16_HA 31 // half16 #ha(L + A)
#define R_PPC_SDAREL16 32 // half16* S + A - _SDA_BASE_
#define R_PPC_SECTOFF 33 // half16* R + A
#define R_PPC_SECTOFF_LO 34 // half16 #lo(R + A)
#define R_PPC_SECTOFF_HI 35 // half16 #hi(R + A)
#define R_PPC_SECTOFF_HA 36 // half16 #ha(R + A)
#define R_PPC_ADDR30 37 // word30 (S + A - P) >> 2
#define R_PPC_EMB_NADDR32 101 // uword32 N (A - S)
#define R_PPC_EMB_NADDR16 102 // uhalf16 Y (A - S)
#define R_PPC_EMB_NADDR16_LO 103 // uhalf16 N #lo(A - S)
#define R_PPC_EMB_NADDR16_HI 104 // uhalf16 N #hi(A - S)
#define R_PPC_EMB_NADDR16_HA 105 // uhalf16 N #ha(A - S)
#define R_PPC_EMB_SDAI16 106 // uhalf16 Y T
#define R_PPC_EMB_SDA2I16 107 // uhalf16 Y U
#define R_PPC_EMB_SDA2REL 108 // uhalf16 Y S + A - _SDA2_BASE_
#define R_PPC_EMB_SDA21 109 // ulow21 N
#define R_PPC_EMB_MRKREF 110 // none N
#define R_PPC_EMB_RELSEC16 111 // uhalf16 Y V + A
#define R_PPC_EMB_RELST_LO 112 // uhalf16 N #lo(W + A)
#define R_PPC_EMB_RELST_HI 113 // uhalf16 N #hi(W + A)
#define R_PPC_EMB_RELST_HA 114 // uhalf16 N #ha(W + A)
#define R_PPC_EMB_BIT_FLD 115 // uword32 Y
#define R_PPC_EMB_RELSDA 116 // uhalf16 Y
#define EnqueueTail(queue, moduleInfo, link) \
do { \
OSModuleInfo* __prev; \
\
__prev = (queue)->tail; \
if (__prev == NULL) \
(queue)->head = (moduleInfo); \
else \
__prev->link.next = (moduleInfo); \
(moduleInfo)->link.prev = __prev; \
(moduleInfo)->link.next = NULL; \
(queue)->tail = (moduleInfo); \
} while (0)
#define DequeueItem(queue, moduleInfo, link) \
do { \
OSModuleInfo* __next; \
OSModuleInfo* __prev; \
\
__next = (moduleInfo)->link.next; \
__prev = (moduleInfo)->link.prev; \
\
if (__next == NULL) \
(queue)->tail = __prev; \
else \
__next->link.prev = __prev; \
\
if (__prev == NULL) \
(queue)->head = __next; \
else \
__prev->link.next = __next; \
} while (0)
OSModuleQueue __OSModuleInfoList : (OS_BASE_CACHED | 0x30C8);
#pragma dont_inline on
__declspec(weak) void OSNotifyLink(OSModuleInfo* module) {}
__declspec(weak) void OSNotifyUnlink(OSModuleInfo* module) {}
#pragma dont_inline reset
void OSSetStringTable(void* string_table) {
__OSStringTable = string_table;
}
static BOOL Relocate(OSModuleHeader* newModule, OSModuleHeader* module) {
OSModuleID idNew;
OSImportInfo* imp;
OSRel* rel;
OSSectionInfo* si;
OSSectionInfo* siFlush;
u32* p;
u32 offset;
u32 x;
idNew = newModule ? newModule->info.id : 0;
for (imp = (OSImportInfo*)module->impOffset;
imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++)
{
if (imp->id == idNew) {
goto Found;
}
}
return FALSE;
Found:
siFlush = 0;
for (rel = (OSRel*)imp->offset; rel->type != R_DOLPHIN_END; rel++) {
(u8*)p += rel->offset;
if (idNew) {
si = &OSGetSectionInfo(newModule)[rel->section];
offset = OS_SECTIONINFO_OFFSET(si->offset);
} else {
offset = 0;
}
switch (rel->type) {
case R_PPC_NONE:
break;
case R_PPC_ADDR32:
x = offset + rel->addend;
*p = x;
break;
case R_PPC_ADDR24:
x = offset + rel->addend;
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
break;
case R_PPC_ADDR16:
x = offset + rel->addend;
*(u16*)p = (u16)(x & 0xffff);
break;
case R_PPC_ADDR16_LO:
x = offset + rel->addend;
*(u16*)p = (u16)(x & 0xffff);
break;
case R_PPC_ADDR16_HI:
x = offset + rel->addend;
*(u16*)p = (u16)(((x >> 16) & 0xffff));
break;
case R_PPC_ADDR16_HA:
x = offset + rel->addend;
*(u16*)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff);
break;
case R_PPC_ADDR14:
case R_PPC_ADDR14_BRTAKEN:
case R_PPC_ADDR14_BRNTAKEN:
x = offset + rel->addend;
*p = (*p & ~0x0000fffc) | (x & 0x0000fffc);
break;
case R_PPC_REL24:
x = offset + rel->addend - (u32)p;
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
break;
case R_PPC_REL14:
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
x = offset + rel->addend - (u32)p;
*p = (*p & ~0x0000fffc) | (x & 0x0000fffc);
break;
case R_DOLPHIN_NOP:
break;
case R_DOLPHIN_SECTION:
si = &OSGetSectionInfo(module)[rel->section];
p = (u32*)OS_SECTIONINFO_OFFSET(si->offset);
if (siFlush) {
offset = OS_SECTIONINFO_OFFSET(siFlush->offset);
DCFlushRange((void*)offset, siFlush->size);
ICInvalidateRange((void*)offset, siFlush->size);
}
siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0;
break;
default:
OSReport("OSLink: unknown relocation type %3d\n", rel->type);
break;
}
}
if (siFlush) {
offset = OS_SECTIONINFO_OFFSET(siFlush->offset);
DCFlushRange((void*)offset, siFlush->size);
ICInvalidateRange((void*)offset, siFlush->size);
}
return TRUE;
}
static BOOL Link(OSModuleInfo* newModule, void* bss, BOOL fixed) {
u32 i;
OSSectionInfo* si;
OSModuleHeader* moduleHeader;
OSModuleInfo* moduleInfo;
OSImportInfo* imp;
moduleHeader = (OSModuleHeader*)newModule;
moduleHeader->bssSection = 0;
if (OS_MODULE_VERSION < newModule->version ||
2 <= newModule->version &&
(moduleHeader->align && (u32)newModule % moduleHeader->align != 0 ||
moduleHeader->bssAlign && (u32)bss % moduleHeader->bssAlign != 0))
{
return FALSE;
}
EnqueueTail(&__OSModuleInfoList, newModule, link);
newModule->sectionInfoOffset += (u32)moduleHeader;
moduleHeader->relOffset += (u32)moduleHeader;
moduleHeader->impOffset += (u32)moduleHeader;
if (3 <= newModule->version) {
moduleHeader->fixSize += (u32)moduleHeader;
}
for (i = 1; i < newModule->numSections; i++) {
si = &OSGetSectionInfo(newModule)[i];
if (si->offset != 0) {
si->offset += (u32)moduleHeader;
} else if (si->size != 0) {
moduleHeader->bssSection = (u8)i;
si->offset = (u32)bss;
}
}
for (imp = (OSImportInfo*)moduleHeader->impOffset;
imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++)
{
imp->offset += (u32)moduleHeader;
}
if (moduleHeader->prologSection != SHN_UNDEF) {
moduleHeader->prolog +=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->prologSection].offset);
}
if (moduleHeader->epilogSection != SHN_UNDEF) {
moduleHeader->epilog +=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->epilogSection].offset);
}
if (moduleHeader->unresolvedSection != SHN_UNDEF) {
moduleHeader->unresolved += OS_SECTIONINFO_OFFSET(
OSGetSectionInfo(newModule)[moduleHeader->unresolvedSection].offset);
}
if (__OSStringTable) {
newModule->nameOffset += (u32)__OSStringTable;
}
Relocate(0, moduleHeader);
for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) {
Relocate(moduleHeader, (OSModuleHeader*)moduleInfo);
if (moduleInfo != newModule) {
Relocate((OSModuleHeader*)moduleInfo, moduleHeader);
}
}
if (fixed) {
for (imp = (OSImportInfo*)moduleHeader->impOffset;
imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++)
{
if (imp->id == 0 || imp->id == newModule->id) {
moduleHeader->impSize = (u32)((u8*)imp - (u8*)moduleHeader->impOffset);
break;
}
}
}
memset(bss, 0, moduleHeader->bssSize);
OSNotifyLink(newModule);
return TRUE;
}
BOOL OSLink(OSModuleInfo* newModule, void* bss) {
return Link(newModule, bss, FALSE);
}
BOOL OSLinkFixed(OSModuleInfo* newModule, void* bss) {
if (OS_MODULE_VERSION < newModule->version || newModule->version < 3) {
return FALSE;
}
return Link(newModule, bss, TRUE);
}
static BOOL Undo(OSModuleHeader* newModule, OSModuleHeader* module) {
OSModuleID idNew;
OSImportInfo* imp;
OSRel* rel;
OSSectionInfo* si;
OSSectionInfo* siFlush;
u32* p;
u32 offset;
u32 x;
idNew = newModule->info.id;
for (imp = (OSImportInfo*)module->impOffset;
imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++)
{
if (imp->id == idNew) {
goto Found;
}
}
return FALSE;
Found:
siFlush = 0;
for (rel = (OSRel*)imp->offset; rel->type != R_DOLPHIN_END; rel++) {
(u8*)p += rel->offset;
si = &OSGetSectionInfo(newModule)[rel->section];
offset = OS_SECTIONINFO_OFFSET(si->offset);
x = 0;
switch (rel->type) {
case R_PPC_NONE:
break;
case R_PPC_ADDR32:
*p = x;
break;
case R_PPC_ADDR24:
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
break;
case R_PPC_ADDR16:
*(u16*)p = (u16)(x & 0xffff);
break;
case R_PPC_ADDR16_LO:
*(u16*)p = (u16)(x & 0xffff);
break;
case R_PPC_ADDR16_HI:
*(u16*)p = (u16)(((x >> 16) & 0xffff));
break;
case R_PPC_ADDR16_HA:
*(u16*)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff);
break;
case R_PPC_ADDR14:
case R_PPC_ADDR14_BRTAKEN:
case R_PPC_ADDR14_BRNTAKEN:
*p = (*p & ~0x0000fffc) | (x & 0x0000fffc);
break;
case R_PPC_REL24:
if (module->unresolvedSection != SHN_UNDEF) {
x = (u32)module->unresolved - (u32)p;
}
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
break;
case R_PPC_REL14:
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
*p = (*p & ~0x0000fffc) | (x & 0x0000fffc);
break;
case R_DOLPHIN_NOP:
break;
case R_DOLPHIN_SECTION:
si = &OSGetSectionInfo(module)[rel->section];
p = (u32*)OS_SECTIONINFO_OFFSET(si->offset);
if (siFlush) {
offset = OS_SECTIONINFO_OFFSET(siFlush->offset);
DCFlushRange((void*)offset, siFlush->size);
ICInvalidateRange((void*)offset, siFlush->size);
}
siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0;
break;
default:
OSReport("OSUnlink: unknown relocation type %3d\n", rel->type);
break;
}
}
if (siFlush) {
offset = OS_SECTIONINFO_OFFSET(siFlush->offset);
DCFlushRange((void*)offset, siFlush->size);
ICInvalidateRange((void*)offset, siFlush->size);
}
return TRUE;
}
BOOL OSUnlink(OSModuleInfo* oldModule) {
OSModuleHeader* moduleHeader;
OSModuleInfo* moduleInfo;
u32 i;
OSSectionInfo* si;
OSImportInfo* imp;
moduleHeader = (OSModuleHeader*)oldModule;
DequeueItem(&__OSModuleInfoList, oldModule, link);
for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) {
Undo(moduleHeader, (OSModuleHeader*)moduleInfo);
}
OSNotifyUnlink(oldModule);
if (__OSStringTable) {
oldModule->nameOffset -= (u32)__OSStringTable;
}
if (moduleHeader->prologSection != SHN_UNDEF) {
moduleHeader->prolog -=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->prologSection].offset);
}
if (moduleHeader->epilogSection != SHN_UNDEF) {
moduleHeader->epilog -=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->epilogSection].offset);
}
if (moduleHeader->unresolvedSection != SHN_UNDEF) {
moduleHeader->unresolved -= OS_SECTIONINFO_OFFSET(
OSGetSectionInfo(oldModule)[moduleHeader->unresolvedSection].offset);
}
for (imp = (OSImportInfo*)moduleHeader->impOffset;
imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++)
{
imp->offset -= (u32)moduleHeader;
}
for (i = 1; i < oldModule->numSections; i++) {
si = &OSGetSectionInfo(oldModule)[i];
if (i == moduleHeader->bssSection) {
moduleHeader->bssSection = 0;
si->offset = 0;
} else if (si->offset != 0) {
si->offset -= (u32)moduleHeader;
}
}
moduleHeader->relOffset -= (u32)moduleHeader;
moduleHeader->impOffset -= (u32)moduleHeader;
oldModule->sectionInfoOffset -= (u32)moduleHeader;
return TRUE;
}
void __OSModuleInit(void) {
__OSModuleList.tail = NULL;
__OSModuleList.head = NULL;
__OSStringTable = NULL;
}

210
src/dolphin/os/OSMemory.c Normal file
View File

@ -0,0 +1,210 @@
#include "dolphin/os/OSMemory.h"
#include "dolphin/os/OS.h"
#define TRUNC(n, a) (((u32)(n)) & ~((a)-1))
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
vu16 __MEMRegs[64] : 0xCC004000;
extern OSErrorHandlerEx __OSErrorTable[16];
static BOOL OnReset(BOOL final) {
if (final != FALSE) {
__MEMRegs[8] = 0xFF;
__OSMaskInterrupts(OS_INTERRUPTMASK_MEM_RESET);
}
return TRUE;
}
static void MEMIntrruptHandler(__OSInterrupt interrupt, OSContext* context) {
u32 addr;
u32 cause;
cause = __MEMRegs[0xf];
addr = (((u32)__MEMRegs[0x12] & 0x3ff) << 16) | __MEMRegs[0x11];
__MEMRegs[0x10] = 0;
if (__OSErrorTable[EXCEPTION_MEMORY_PROTECTION]) {
__OSErrorTable[EXCEPTION_MEMORY_PROTECTION](EXCEPTION_MEMORY_PROTECTION, context, cause,
addr);
return;
}
__OSUnhandledException(EXCEPTION_MEMORY_PROTECTION, context, cause, addr);
}
void OSProtectRange(u32 chan, void* addr, u32 nBytes, u32 control) {
BOOL enabled;
u32 start;
u32 end;
u16 reg;
if (4 <= chan) {
return;
}
control &= OS_PROTECT_CONTROL_RDWR;
end = (u32)addr + nBytes;
start = TRUNC(addr, 1u << 10);
end = ROUND(end, 1u << 10);
DCFlushRange((void*)start, end - start);
enabled = OSDisableInterrupts();
__OSMaskInterrupts(OS_INTERRUPTMASK(OS_INTR_MEM_0 + chan));
__MEMRegs[0 + 2 * chan] = (u16)(start >> 10);
__MEMRegs[1 + 2 * chan] = (u16)(end >> 10);
reg = __MEMRegs[8];
reg &= ~(OS_PROTECT_CONTROL_RDWR << 2 * chan);
reg |= control << 2 * chan;
__MEMRegs[8] = reg;
if (control != OS_PROTECT_CONTROL_RDWR) {
__OSUnmaskInterrupts(OS_INTERRUPTMASK(OS_INTR_MEM_0 + chan));
}
OSRestoreInterrupts(enabled);
}
static asm void Config24MB(void) {
// clang-format off
nofralloc
li r7, 0
lis r4, 0x0000
addi r4, r4, 0x0002
lis r3, 0x8000
addi r3, r3, 0x01FF
lis r6, 0x0100
addi r6, r6, 0x0002
lis r5, 0x8100
addi r5, r5, 0x00FF
isync
mtdbatu 0, r7
mtdbatl 0, r4
mtdbatu 0, r3
isync
mtibatu 0, r7
mtibatl 0, r4
mtibatu 0, r3
isync
mtdbatu 2, r7
mtdbatl 2, r6
mtdbatu 2, r5
isync
mtibatu 2, r7
mtibatl 2, r6
mtibatu 2, r5
isync
mfmsr r3
ori r3, r3, 0x30
mtspr 0x1b, r3
mflr r3
mtspr 0x1a, r3
rfi
// clang-format on
}
static asm void Config48MB(void) {
// clang-format off
nofralloc
li r7, 0
lis r4, 0x0000
addi r4, r4, 0x0002
lis r3, 0x8000
addi r3, r3, 0x03FF
lis r6, 0x0200
addi r6, r6, 0x0002
lis r5, 0x8200
addi r5, r5, 0x01FF
isync
mtdbatu 0, r7
mtdbatl 0, r4
mtdbatu 0, r3
isync
mtibatu 0, r7
mtibatl 0, r4
mtibatu 0, r3
isync
mtdbatu 2, r7
mtdbatl 2, r6
mtdbatu 2, r5
isync
mtibatu 2, r7
mtibatl 2, r6
mtibatu 2, r5
isync
mfmsr r3
ori r3, r3, 0x30
mtspr 0x1b, r3
mflr r3
mtspr 0x1a, r3
rfi
// clang-format on
}
static asm void RealMode(register u32 config) {
// clang-format off
nofralloc
clrlwi config, config, 2
mtspr 0x1a, config
mfmsr config
rlwinm config, config, 0, 0x1c, 0x19
mtspr 0x1b, config
rfi
// clang-format on
}
static OSResetFunctionInfo ResetFunctionInfo = {
OnReset,
0x7F,
};
inline u32 OSGetPhysicalMemSize() {
return *(u32*)(OSPhysicalToCached(0x0028));
}
inline u32 OSGetConsoleSimulatedMemSize() {
return *(u32*)(OSPhysicalToCached(0x00F0));
}
void __OSInitMemoryProtection() {
u32 padding[8];
u32 simulatedSize;
BOOL enabled;
simulatedSize = OSGetConsoleSimulatedMemSize();
enabled = OSDisableInterrupts();
__MEMRegs[16] = 0;
__MEMRegs[8] = 0xFF;
__OSMaskInterrupts(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 |
OS_INTERRUPTMASK_MEM_3);
__OSSetInterruptHandler(OS_INTR_MEM_0, MEMIntrruptHandler);
__OSSetInterruptHandler(OS_INTR_MEM_1, MEMIntrruptHandler);
__OSSetInterruptHandler(OS_INTR_MEM_2, MEMIntrruptHandler);
__OSSetInterruptHandler(OS_INTR_MEM_3, MEMIntrruptHandler);
__OSSetInterruptHandler(OS_INTR_MEM_ADDRESS, MEMIntrruptHandler);
OSRegisterResetFunction(&ResetFunctionInfo);
if (OSGetConsoleSimulatedMemSize() < OSGetPhysicalMemSize() &&
OSGetConsoleSimulatedMemSize() == 0x1800000)
{
DCInvalidateRange((void*)0x81800000, 0x1800000);
__MEMRegs[20] = 2;
}
if (simulatedSize <= 0x1800000) {
RealMode((u32)&Config24MB);
} else if (simulatedSize <= 0x3000000) {
RealMode((u32)&Config48MB);
}
__OSUnmaskInterrupts(OS_INTERRUPTMASK_MEM_ADDRESS);
OSRestoreInterrupts(enabled);
}

View File

@ -0,0 +1,87 @@
#include "dolphin/os/OSMessage.h"
void OSInitMessageQueue(OSMessageQueue* mq, OSMessage* msgArray, s32 msgCount) {
OSInitThreadQueue(&mq->sending_queue);
OSInitThreadQueue(&mq->receiving_queue);
mq->message_array = msgArray;
mq->num_messages = msgCount;
mq->first_index = 0;
mq->num_used = 0;
}
BOOL OSSendMessage(OSMessageQueue* mq, OSMessage msg, s32 flags) {
BOOL enabled;
s32 lastIndex;
enabled = OSDisableInterrupts();
while (mq->num_messages <= mq->num_used) {
if (!(flags & OS_MESSAGE_BLOCK)) {
OSRestoreInterrupts(enabled);
return FALSE;
} else {
OSSleepThread(&mq->sending_queue);
}
}
lastIndex = (mq->first_index + mq->num_used) % mq->num_messages;
mq->message_array[lastIndex] = msg;
mq->num_used++;
OSWakeupThread(&mq->receiving_queue);
OSRestoreInterrupts(enabled);
return TRUE;
}
BOOL OSReceiveMessage(OSMessageQueue* mq, OSMessage* msg, s32 flags) {
BOOL enabled;
enabled = OSDisableInterrupts();
while (mq->num_used == 0) {
if (!(flags & OS_MESSAGE_BLOCK)) {
OSRestoreInterrupts(enabled);
return FALSE;
} else {
OSSleepThread(&mq->receiving_queue);
}
}
if (msg != NULL) {
*msg = mq->message_array[mq->first_index];
}
mq->first_index = (mq->first_index + 1) % mq->num_messages;
mq->num_used--;
OSWakeupThread(&mq->sending_queue);
OSRestoreInterrupts(enabled);
return TRUE;
}
BOOL OSJamMessage(OSMessageQueue* queue, void* msg, s32 flags) {
s32 lastMesg;
u32 interrupt;
interrupt = OSDisableInterrupts();
while (queue->num_messages <= queue->num_used) {
if (!(flags & OS_MSG_PERSISTENT)) {
OSRestoreInterrupts(interrupt);
return FALSE;
}
OSSleepThread(&queue->sending_queue);
}
// Find last position in queue
lastMesg = (queue->first_index + queue->num_messages - 1) % queue->num_messages;
queue->first_index = lastMesg;
queue->message_array[queue->first_index] = msg;
queue->num_used++;
OSWakeupThread(&queue->receiving_queue);
OSRestoreInterrupts(interrupt);
return TRUE;
}

231
src/dolphin/os/OSMutex.c Normal file
View File

@ -0,0 +1,231 @@
#include "dolphin/os/OSMutex.h"
#include "dolphin/os/OS.h"
#define PushTail(queue, mutex, link) \
do { \
OSMutex* __prev; \
\
__prev = (queue)->tail; \
if (__prev == NULL) \
(queue)->head = (mutex); \
else \
__prev->link.next = (mutex); \
(mutex)->link.prev = __prev; \
(mutex)->link.next = NULL; \
(queue)->tail = (mutex); \
} while (0)
#define PopHead(queue, mutex, link) \
do { \
OSMutex* __next; \
\
(mutex) = (queue)->head; \
__next = (mutex)->link.next; \
if (__next == NULL) \
(queue)->tail = NULL; \
else \
__next->link.prev = NULL; \
(queue)->head = __next; \
} while (0)
#define PopItem(queue, mutex, link) \
do { \
OSMutex* __next; \
OSMutex* __prev; \
\
__next = (mutex)->link.next; \
__prev = (mutex)->link.prev; \
\
if (__next == NULL) \
(queue)->tail = __prev; \
else \
__next->link.prev = __prev; \
\
if (__prev == NULL) \
(queue)->head = __next; \
else \
__prev->link.next = __next; \
} while (0)
//
// Declarations:
//
void OSInitMutex(OSMutex* mutex) {
OSInitThreadQueue(&mutex->queue);
mutex->thread = 0;
mutex->count = 0;
}
void OSLockMutex(OSMutex* mutex) {
BOOL enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
OSThread* ownerThread;
while (TRUE) {
ownerThread = ((OSMutex*)mutex)->thread;
if (ownerThread == 0) {
mutex->thread = currentThread;
mutex->count++;
PushTail(&currentThread->owned_mutexes, mutex, link);
break;
} else if (ownerThread == currentThread) {
mutex->count++;
break;
} else {
currentThread->mutex = mutex;
__OSPromoteThread(mutex->thread, currentThread->effective_priority);
OSSleepThread(&mutex->queue);
currentThread->mutex = 0;
}
}
OSRestoreInterrupts(enabled);
}
void OSUnlockMutex(OSMutex* mutex) {
BOOL enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
if (mutex->thread == currentThread && --mutex->count == 0) {
PopItem(&currentThread->owned_mutexes, mutex, link);
mutex->thread = NULL;
if ((s32)currentThread->effective_priority < (s32)currentThread->base_priority) {
currentThread->effective_priority = __OSGetEffectivePriority(currentThread);
}
OSWakeupThread(&mutex->queue);
}
OSRestoreInterrupts(enabled);
}
void __OSUnlockAllMutex(OSThread* thread) {
OSMutex* mutex;
while (thread->owned_mutexes.head) {
PopHead(&thread->owned_mutexes, mutex, link);
mutex->count = 0;
mutex->thread = NULL;
OSWakeupThread(&mutex->queue);
}
}
BOOL OSTryLockMutex(OSMutex* mutex) {
BOOL enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
BOOL locked;
if (mutex->thread == 0) {
mutex->thread = currentThread;
mutex->count++;
PushTail(&currentThread->owned_mutexes, mutex, link);
locked = TRUE;
} else if (mutex->thread == currentThread) {
mutex->count++;
locked = TRUE;
} else {
locked = FALSE;
}
OSRestoreInterrupts(enabled);
return locked;
}
void OSInitCond(OSCond* cond) { OSInitThreadQueue(&cond->queue); }
void OSWaitCond(OSCond* cond, OSMutex* mutex) {
BOOL enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
s32 count;
if (mutex->thread == currentThread) {
count = mutex->count;
mutex->count = 0;
PopItem(&currentThread->owned_mutexes, mutex, link);
mutex->thread = NULL;
if (currentThread->effective_priority < (s32)currentThread->base_priority) {
currentThread->effective_priority = __OSGetEffectivePriority(currentThread);
}
OSDisableScheduler();
OSWakeupThread(&mutex->queue);
OSEnableScheduler();
OSSleepThread(&cond->queue);
OSLockMutex(mutex);
mutex->count = count;
}
OSRestoreInterrupts(enabled);
}
void OSSignalCond(OSCond* cond) {
OSWakeupThread(&cond->queue);
}
static BOOL IsMember(OSMutexQueue* queue, OSMutex* mutex) {
OSMutex* member;
for (member = queue->head; member; member = member->link.next) {
if (mutex == member)
return TRUE;
}
return FALSE;
}
BOOL __OSCheckMutex(OSMutex* mutex) {
OSThread* thread;
OSThreadQueue* queue;
OSPriority priority = 0;
queue = &mutex->queue;
if (!(queue->head == NULL || queue->head->link.prev == NULL))
return FALSE;
if (!(queue->tail == NULL || queue->tail->link.next == NULL))
return FALSE;
for (thread = queue->head; thread; thread = thread->link.next) {
if (!(thread->link.next == NULL || thread == thread->link.next->link.prev))
return FALSE;
if (!(thread->link.prev == NULL || thread == thread->link.prev->link.next))
return FALSE;
if (thread->state != OS_THREAD_STATE_WAITING)
return FALSE;
if (thread->effective_priority < priority)
return FALSE;
priority = thread->effective_priority;
}
if (mutex->thread) {
if (mutex->count <= 0)
return FALSE;
} else {
if (0 != mutex->count)
return FALSE;
}
return TRUE;
}
BOOL __OSCheckDeadLock(OSThread* thread) {
OSMutex* mutex;
mutex = thread->mutex;
while (mutex && mutex->thread) {
if (mutex->thread == thread)
return TRUE;
mutex = mutex->thread->mutex;
}
return FALSE;
}
BOOL __OSCheckMutexes(OSThread* thread) {
OSMutex* mutex;
for (mutex = thread->owned_mutexes.head; mutex; mutex = mutex->link.next) {
if (mutex->thread != thread)
return FALSE;
if (!__OSCheckMutex(mutex))
return FALSE;
}
return TRUE;
}

29
src/dolphin/os/OSReboot.c Normal file
View File

@ -0,0 +1,29 @@
#include "dolphin/os/OSReboot.h"
#include "dolphin/os/OSContext.h"
#include "dolphin/os/OSExec.h"
void __OSReboot(u32 resetCode, u32 bootDol) {
struct OSContext context;
char* iVar1;
OSDisableInterrupts();
OSSetArenaLo((void*)0x81280000);
OSSetArenaHi((void*)0x812f0000);
OSClearContext(&context);
OSSetCurrentContext(&context);
iVar1 = NULL;
__OSBootDol(bootDol, resetCode | 0x80000000, &iVar1);
}
static void* SaveStart;
static void* SaveEnd;
void OSSetSaveRegion(void* start, void* end) {
SaveStart = start;
SaveEnd = end;
}
void OSGetSaveRegion(void** start, void** end) {
*start = SaveStart;
*end = SaveEnd;
}

210
src/dolphin/os/OSReset.c Normal file
View File

@ -0,0 +1,210 @@
#include "dolphin/os/OSReset.h"
#include "dolphin/os/OS.h"
vu16 __VIRegs[59] : 0xCC002000;
OSThreadQueue __OSActiveThreadQueue : (OS_BASE_CACHED | 0x00DC);
extern OSExecParams __OSRebootParams;
static OSResetQueue ResetFunctionQueue;
void OSRegisterResetFunction(OSResetFunctionInfo* func) {
OSResetFunctionInfo* tmp;
OSResetFunctionInfo* iter;
for (iter = ResetFunctionQueue.first; iter && iter->priority <= func->priority;
iter = iter->next)
;
if (iter == NULL) {
tmp = ResetFunctionQueue.last;
if (tmp == NULL) {
ResetFunctionQueue.first = func;
} else {
tmp->next = func;
}
func->prev = tmp;
func->next = NULL;
ResetFunctionQueue.last = func;
return;
}
func->next = iter;
tmp = iter->prev;
iter->prev = func;
func->prev = tmp;
if (tmp == NULL) {
ResetFunctionQueue.first = func;
return;
}
tmp->next = func;
}
BOOL __OSCallResetFunctions(u32 arg0) {
OSResetFunctionInfo* iter;
s32 retCode = 0;
u32 priority = 0;
s32 temp;
for (iter = ResetFunctionQueue.first; iter != NULL;) {
if (retCode != 0 && priority != iter->priority)
break;
temp = !iter->func(arg0);
priority = iter->priority;
iter = iter->next;
retCode |= temp;
}
retCode |= !__OSSyncSram();
if (retCode) {
return 0;
}
return 1;
}
static asm void Reset(register s32 param_0) {
// clang-format off
nofralloc
b lbl_8033F7AC
lbl_8033F790:
mfspr r8, 0x3f0
ori r8, r8, 8
mtspr 0x3f0, r8
isync
sync
nop
b lbl_8033F7B0
lbl_8033F7AC:
b lbl_8033F7CC
lbl_8033F7B0:
mftb r5, 0x10c
lbl_8033F7B4:
mftb r6, 0x10c
subf r7, r5, r6
cmplwi r7, 0x1124
blt lbl_8033F7B4
nop
b lbl_8033F7D0
lbl_8033F7CC:
b lbl_8033F7EC
lbl_8033F7D0:
lis r8, 0xCC00
ori r8, r8, 0x3000
li r4, 3
stw r4, 0x24(r8)
stw param_0, 0x24(r8)
nop
b lbl_8033F7F0
lbl_8033F7EC:
b lbl_8033F7F8
lbl_8033F7F0:
nop
b lbl_8033F7F0
lbl_8033F7F8:
b lbl_8033F790
// clang-format on
}
#pragma dont_inline on
static void KillThreads(void) {
OSThread* thread;
OSThread* next;
for (thread = __OSActiveThreadQueue.head; thread; thread = next) {
next = thread->active_threads_link.next;
switch (thread->state) {
case 1:
case 4:
OSCancelThread(thread);
continue;
default:
continue;
}
}
}
#pragma dont_inline reset
void __OSDoHotReset(s32 arg0) {
OSDisableInterrupts();
__VIRegs[1] = 0;
ICFlashInvalidate();
Reset(arg0 * 8);
}
static u32 bootThisDol;
void OSResetSystem(int reset, u32 resetCode, BOOL forceMenu) {
BOOL rc;
BOOL disableRecalibration;
u32 unk;
OSDisableScheduler();
if (reset == OS_RESET_HOTRESET && forceMenu) {
OSSram* sram;
sram = __OSLockSram();
sram->flags |= 0x40;
__OSUnlockSram(TRUE);
resetCode = 0;
}
if (reset == OS_RESET_SHUTDOWN ||
(reset == OS_RESET_RESTART && (bootThisDol || resetCode + 0x3fff0000 == 0)))
{
__OSStopAudioSystem();
disableRecalibration = __PADDisableRecalibration(TRUE);
while (!__OSCallResetFunctions(FALSE))
;
while (!__OSSyncSram())
;
OSDisableInterrupts();
__OSCallResetFunctions(TRUE);
LCDisable();
__PADDisableRecalibration(disableRecalibration);
KillThreads();
} else {
__OSStopAudioSystem();
while (!__OSCallResetFunctions(FALSE))
;
while (!__OSSyncSram())
;
OSDisableInterrupts();
__OSCallResetFunctions(TRUE);
LCDisable();
KillThreads();
}
if (reset == OS_RESET_HOTRESET) {
__OSDoHotReset(resetCode);
} else if (reset == OS_RESET_RESTART) {
if (forceMenu == TRUE) {
OSReport(
"OSResetSystem(): You can't specify TRUE to forceMenu if you restart. Ignored\n");
}
OSEnableScheduler();
__OSReboot(resetCode, bootThisDol);
}
memset(OSPhysicalToCached(0x40), 0, 0xcc - 0x40);
memset(OSPhysicalToCached(0xd4), 0, 0xe8 - 0xd4);
memset(OSPhysicalToCached(0xf4), 0, 0xf8 - 0xf4);
memset(OSPhysicalToCached(0x3000), 0, 0xc0);
memset(OSPhysicalToCached(0x30c8), 0, 0xd4 - 0xc8);
memset(OSPhysicalToCached(0x30e2), 0, 1);
}
u32 OSGetResetCode(void) {
if (__OSRebootParams.valid)
return 0x80000000 | __OSRebootParams.restartCode;
return ((__PIRegs[9] & ~7) >> 3);
}

View File

@ -0,0 +1,92 @@
#include "dolphin/os/OSResetSW.h"
#include "dolphin/os/OS.h"
#include "dolphin/os/OSReset.h"
u8 GameChoice : (OS_BASE_CACHED | 0x30E3);
void __OSResetSWInterruptHandler(__OSInterrupt interrupt, OSContext* context);
static OSResetCallback ResetCallback;
static BOOL Down;
static BOOL LastState;
static OSTime HoldUp;
static OSTime HoldDown;
void __OSResetSWInterruptHandler(__OSInterrupt interrupt, OSContext* context) {
OSResetCallback callback;
HoldDown = __OSGetSystemTime();
while (__OSGetSystemTime() - HoldDown < OSMicrosecondsToTicks(100) &&
!(__PIRegs[0] & 0x00010000)) {
;
}
if (!(__PIRegs[0] & 0x00010000)) {
LastState = Down = TRUE;
__OSMaskInterrupts(OS_INTERRUPTMASK_PI_RSW);
if (ResetCallback) {
callback = ResetCallback;
ResetCallback = NULL;
callback();
}
}
__PIRegs[0] = 2;
}
BOOL OSGetResetButtonState(void) {
BOOL enabled = OSDisableInterrupts();
BOOL state;
OSTime now = __OSGetSystemTime();
u32 reg = __PIRegs[0];
if (!(reg & 0x00010000)) {
if (!Down) {
Down = TRUE;
state = HoldUp ? TRUE : FALSE;
HoldDown = now;
} else {
state = HoldUp || (OSMicrosecondsToTicks(100) < now - HoldDown)
? TRUE
: FALSE;
}
} else if (Down) {
Down = FALSE;
state = LastState;
if (state) {
HoldUp = now;
} else {
HoldUp = 0;
}
} else if (HoldUp && (now - HoldUp < OSMillisecondsToTicks(40))) {
state = TRUE;
} else {
state = FALSE;
HoldUp = 0;
}
LastState = state;
if (GameChoice & 0x1F) {
OSTime fire = (GameChoice & 0x1F) * 60;
fire = __OSStartTime + OSSecondsToTicks(fire);
if (fire < now) {
now -= fire;
now = OSTicksToSeconds(now) / 2;
if ((now & 1) == 0) {
state = TRUE;
} else {
state = FALSE;
}
}
}
OSRestoreInterrupts(enabled);
return state;
}
BOOL OSGetResetSwitchState(void) {
return OSGetResetButtonState();
}

251
src/dolphin/os/OSRtc.c Normal file
View File

@ -0,0 +1,251 @@
#include "global.h"
#include "dolphin/os/OSRtc.h"
#include "dolphin/os/OSInterrupt.h"
static void WriteSramCallback(s32 chan, OSContext* context);
static BOOL WriteSram(void* buffer, u32 offset, u32 size);
static BOOL UnlockSram(BOOL commit, u32 offset);
static SramControlBlock Scb ALIGN_DECL(32);
static void WriteSramCallback(s32 chan, OSContext* context) {
Scb.sync = WriteSram(Scb.sram + Scb.offset, Scb.offset, RTC_SRAM_SIZE - Scb.offset);
if (Scb.sync) {
Scb.offset = RTC_SRAM_SIZE;
}
}
static inline BOOL ReadSram(void* buffer) {
BOOL err;
u32 cmd;
DCInvalidateRange(buffer, RTC_SRAM_SIZE);
if (!EXILock(RTC_CHAN, RTC_DEV, 0)) {
return FALSE;
}
if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) {
EXIUnlock(RTC_CHAN);
return FALSE;
}
cmd = RTC_CMD_READ | RTC_SRAM_ADDR;
err = FALSE;
err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL);
err |= !EXISync(RTC_CHAN);
err |= !EXIDma(RTC_CHAN, buffer, RTC_SRAM_SIZE, 0, NULL);
err |= !EXISync(RTC_CHAN);
err |= !EXIDeselect(RTC_CHAN);
EXIUnlock(RTC_CHAN);
return !err;
}
BOOL WriteSram(void* buffer, u32 offset, u32 size) {
BOOL err;
u32 cmd;
if (!EXILock(RTC_CHAN, RTC_DEV, WriteSramCallback)) {
return FALSE;
}
if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) {
EXIUnlock(RTC_CHAN);
return FALSE;
}
offset <<= 6;
cmd = RTC_CMD_WRITE | RTC_SRAM_ADDR + offset;
err = FALSE;
err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL);
err |= !EXISync(RTC_CHAN);
err |= !EXIImmEx(RTC_CHAN, buffer, (s32)size, 1);
err |= !EXIDeselect(RTC_CHAN);
EXIUnlock(RTC_CHAN);
return !err;
}
void __OSInitSram(void) {
Scb.locked = Scb.enabled = FALSE;
Scb.sync = ReadSram(Scb.sram);
Scb.offset = RTC_SRAM_SIZE;
OSSetGbsMode(OSGetGbsMode());
}
static void* LockSram(u32 offset) {
BOOL enabled;
enabled = OSDisableInterrupts();
if (Scb.locked != FALSE) {
OSRestoreInterrupts(enabled);
return NULL;
}
Scb.enabled = enabled;
Scb.locked = TRUE;
return Scb.sram + offset;
}
OSSram* __OSLockSram() {
return LockSram(0);
}
OSSramEx* __OSLockSramEx() {
return LockSram(sizeof(OSSram));
}
static BOOL UnlockSram(BOOL commit, u32 offset) {
u16* p;
if (commit) {
if (offset == 0) {
OSSram* sram = (OSSram*)Scb.sram;
if (2u < (sram->flags & 3)) {
sram->flags &= ~3;
}
sram->checkSum = sram->checkSumInv = 0;
for (p = (u16*)&sram->counterBias; p < (u16*)(Scb.sram + sizeof(OSSram)); p++) {
sram->checkSum += *p;
sram->checkSumInv += ~*p;
}
}
if (offset < Scb.offset) {
Scb.offset = offset;
}
if (Scb.offset <= 0x14) {
OSSramEx* sram = (OSSramEx*)(Scb.sram + sizeof(OSSram));
if (((u32)sram->gbs & 0x7c00) == 0x5000 || ((u32)sram->gbs & 0xc0) == 0xc0) {
sram->gbs = 0;
}
}
Scb.sync = WriteSram(Scb.sram + Scb.offset, Scb.offset, RTC_SRAM_SIZE - Scb.offset);
if (Scb.sync) {
Scb.offset = RTC_SRAM_SIZE;
}
}
Scb.locked = FALSE;
OSRestoreInterrupts(Scb.enabled);
return Scb.sync;
}
BOOL __OSUnlockSram(BOOL commit) {
return UnlockSram(commit, 0);
}
BOOL __OSUnlockSramEx(BOOL commit) {
return UnlockSram(commit, sizeof(OSSram));
}
BOOL __OSSyncSram(void) {
return Scb.sync;
}
u32 OSGetSoundMode() {
OSSram* sram;
u32 mode;
sram = __OSLockSram();
mode = (sram->flags & 0x4) ? OS_SOUND_MODE_STEREO : OS_SOUND_MODE_MONO;
__OSUnlockSram(FALSE);
return mode;
}
void OSSetSoundMode(u32 mode) {
OSSram* sram;
mode <<= 2;
mode &= 4;
sram = __OSLockSram();
if (mode == (sram->flags & 4)) {
__OSUnlockSram(FALSE);
return;
}
sram->flags &= ~4;
sram->flags |= mode;
__OSUnlockSram(TRUE);
}
u32 OSGetProgressiveMode() {
OSSram* sram;
u32 mode;
sram = __OSLockSram();
mode = (sram->flags & 0x80) >> 7;
__OSUnlockSram(FALSE);
return mode;
}
void OSSetProgressiveMode(u32 mode) {
OSSram* sram;
mode <<= 7;
mode &= 0x80;
sram = __OSLockSram();
if (mode == (sram->flags & 0x80)) {
__OSUnlockSram(FALSE);
return;
}
sram->flags &= ~0x80;
sram->flags |= mode;
__OSUnlockSram(TRUE);
}
u16 OSGetWirelessID(s32 channel) {
OSSramEx* sram;
u16 id;
sram = __OSLockSramEx();
id = sram->wirelessPadID[channel];
__OSUnlockSramEx(FALSE);
return id;
}
void OSSetWirelessID(s32 channel, u16 id) {
OSSramEx* sram;
sram = __OSLockSramEx();
if (sram->wirelessPadID[channel] != id) {
sram->wirelessPadID[channel] = id;
__OSUnlockSramEx(TRUE);
return;
}
__OSUnlockSramEx(FALSE);
}
u16 OSGetGbsMode() {
OSSramEx* sram;
u16 gbs;
sram = __OSLockSramEx();
gbs = sram->gbs;
__OSUnlockSramEx(FALSE);
return gbs;
}
void OSSetGbsMode(u16 mode) {
OSSramEx* sram;
if (((u32)mode & 0x7c00) == 0x5000 || ((u32)mode & 0xc0) == 0xc0) {
mode = 0;
}
sram = __OSLockSramEx();
if (mode == sram->gbs) {
__OSUnlockSramEx(FALSE);
return;
}
sram->gbs = mode;
__OSUnlockSramEx(TRUE);
}

32
src/dolphin/os/OSSync.c Normal file
View File

@ -0,0 +1,32 @@
#include "dolphin/os/OSSync.h"
#include "dolphin/os/OS.h"
void __OSSystemCallVectorStart();
void __OSSystemCallVectorEnd();
static asm void SystemCallVector(void) {
// clang-format off
nofralloc
entry __OSSystemCallVectorStart
mfspr r9, HID0
ori r10, r9, 8
mtspr HID0, r10
isync
sync
mtspr HID0, r9
rfi
entry __OSSystemCallVectorEnd
nop
// clang-format on
}
void __OSInitSystemCall(void) {
void* addr = OSPhysicalToCached(0x00C00);
memcpy(addr, __OSSystemCallVectorStart,
(size_t)__OSSystemCallVectorEnd - (size_t)__OSSystemCallVectorStart);
DCFlushRangeNoSync(addr, 0x100);
__sync();
ICInvalidateRange(addr, 0x100);
}

901
src/dolphin/os/OSThread.c Normal file
View File

@ -0,0 +1,901 @@
//
// Generated By: dol2asm
// Translation Unit: OSThread
//
#include "global.h"
#include "dolphin/os/OSThread.h"
#include "dolphin/os/OS.h"
OSThread* __OSCurrentThread : OS_BASE_CACHED + 0x00E4;
OSThreadQueue __OSActiveThreadQueue : OS_BASE_CACHED + 0x00DC;
volatile OSContext __OSCurrentContext : OS_BASE_CACHED + 0x00D4;
volatile OSContext* __OSFPUContext : OS_BASE_CACHED + 0x00D8;
#define AddTail(queue, thread, link) \
do { \
OSThread* prev; \
\
prev = (queue)->tail; \
if (prev == NULL) \
(queue)->head = (thread); \
else \
prev->link.next = (thread); \
(thread)->link.prev = prev; \
(thread)->link.next = NULL; \
(queue)->tail = (thread); \
} while (0)
#define AddPrio(queue, thread, link) \
do { \
OSThread *prev, *next; \
\
for (next = (queue)->head; next && next->effective_priority <= thread->effective_priority; \
next = next->link.next) \
; \
if (next == NULL) \
AddTail(queue, thread, link); \
else { \
(thread)->link.next = next; \
prev = next->link.prev; \
next->link.prev = (thread); \
(thread)->link.prev = prev; \
if (prev == NULL) \
(queue)->head = (thread); \
else \
prev->link.next = (thread); \
} \
} while (0)
#define RemoveItem(queue, thread, link) \
do { \
OSThread *next, *prev; \
next = (thread)->link.next; \
prev = (thread)->link.prev; \
if (next == NULL) \
(queue)->tail = prev; \
else \
next->link.prev = prev; \
if (prev == NULL) \
(queue)->head = next; \
else \
prev->link.next = next; \
} while (0)
#define RemoveHead(queue, thread, link) \
do { \
OSThread* __next; \
(thread) = (queue)->head; \
__next = (thread)->link.next; \
if (__next == NULL) \
(queue)->tail = NULL; \
else \
__next->link.prev = NULL; \
(queue)->head = __next; \
} while (0)
//
// External References:
//
extern OSErrorHandlerEx __OSErrorTable[17];
extern u32 __OSFpscrEnableBits;
void _epilog();
//
// Declarations:
//
static void DefaultSwitchThreadCallback(OSThread* from, OSThread* to) {}
static OSSwitchThreadCallback SwitchThreadCallback = DefaultSwitchThreadCallback;
OSSwitchThreadCallback OSSetSwitchThreadCallback(OSSwitchThreadCallback func) {
BOOL enable = OSDisableInterrupts();
OSSwitchThreadCallback prev = SwitchThreadCallback;
OSSwitchThreadCallback temp;
if (func) {
temp = func;
} else {
temp = DefaultSwitchThreadCallback;
}
SwitchThreadCallback = temp;
OSRestoreInterrupts(enable);
if (prev == DefaultSwitchThreadCallback) {
return NULL;
}
return prev;
}
static OSThreadQueue RunQueue[32];
#pragma push
#pragma force_active on
static OSThread IdleThread;
#pragma pop
#pragma push
#pragma force_active on
static OSThread DefaultThread;
#pragma pop
#pragma push
#pragma force_active on
static OSContext IdleContext;
#pragma pop
static vu32 RunQueueBits;
static volatile BOOL RunQueueHint;
static volatile s32 Reschedule;
extern u8 _stack_end[];
extern u8 _stack_addr[];
static inline void OSInitMutexQueue(OSMutexQueue* queue) {
queue->head = queue->tail = NULL;
}
static inline void OSSetCurrentThread(OSThread* thread) {
SwitchThreadCallback(__OSCurrentThread, thread);
__OSCurrentThread = thread;
}
void __OSThreadInit() {
OSThread* thread = &DefaultThread;
int prio;
thread->state = OS_THREAD_STATE_RUNNING;
thread->attributes = OS_THREAD_ATTR_DETACH;
thread->effective_priority = thread->base_priority = 16;
thread->suspend_count = 0;
thread->exit_value = (void*)-1;
thread->mutex = NULL;
OSInitThreadQueue(&thread->join_queue);
OSInitMutexQueue(&thread->owned_mutexes);
__OSFPUContext = &thread->context;
OSClearContext(&thread->context);
OSSetCurrentContext(&thread->context);
thread->stack_base = (void*)_stack_addr;
thread->stack_end = (void*)_stack_end;
*(thread->stack_end) = OS_THREAD_STACK_MAGIC;
OSSetCurrentThread(thread);
OSClearStack(0);
RunQueueBits = 0;
RunQueueHint = FALSE;
for (prio = OS_PRIORITY_MIN; prio <= OS_PRIORITY_MAX; ++prio) {
OSInitThreadQueue(&RunQueue[prio]);
}
OSInitThreadQueue(&__OSActiveThreadQueue);
AddTail(&__OSActiveThreadQueue, thread, active_threads_link);
OSClearContext(&IdleContext);
Reschedule = 0;
}
void OSInitThreadQueue(OSThreadQueue* queue) {
queue->tail = NULL;
queue->head = NULL;
}
OSThread* OSGetCurrentThread(void) {
return OS_CURRENT_THREAD;
}
BOOL OSIsThreadTerminated(OSThread* thread) {
return thread->state == OS_THREAD_STATE_DEAD || thread->state == OS_THREAD_STATE_UNINITIALIZED ?
TRUE :
FALSE;
}
s32 OSDisableScheduler(void) {
BOOL intr = OSDisableInterrupts();
s32 ret = Reschedule++;
OSRestoreInterrupts(intr);
return ret;
}
s32 OSEnableScheduler(void) {
BOOL intr = OSDisableInterrupts();
s32 ret = Reschedule--;
OSRestoreInterrupts(intr);
return ret;
}
static inline void SetRun(OSThread* thread) {
thread->queue = &RunQueue[thread->effective_priority];
AddTail(thread->queue, thread, link);
RunQueueBits |= 1u << (OS_PRIORITY_MAX - thread->effective_priority);
RunQueueHint = TRUE;
}
#pragma dont_inline on
static void UnsetRun(OSThread* thread) {
OSThreadQueue* queue;
OSThread* next;
OSThread* prev;
prev = thread->link.next;
queue = thread->queue;
next = thread->link.prev;
if (prev == NULL) {
queue->tail = next;
} else {
prev->link.prev = next;
}
if (next == NULL) {
queue->head = prev;
} else {
next->link.next = prev;
}
if (queue->head == NULL) {
RunQueueBits &= ~(1 << 31 - thread->effective_priority);
}
thread->queue = NULL;
}
#pragma dont_inline reset
s32 __OSGetEffectivePriority(OSThread* thread) {
s32 prio = thread->base_priority;
OSMutex* mutex;
for (mutex = thread->owned_mutexes.head; mutex != NULL; mutex = mutex->link.next) {
OSThread* mutexThread = mutex->queue.head;
if (mutexThread != NULL && mutexThread->effective_priority < prio) {
prio = mutexThread->effective_priority;
}
}
return prio;
}
static OSThread* SetEffectivePriority(OSThread* thread, s32 priority) {
switch (thread->state) {
case OS_THREAD_STATE_READY:
UnsetRun(thread);
thread->effective_priority = priority;
SetRun(thread);
break;
case OS_THREAD_STATE_WAITING:
RemoveItem(thread->queue, thread, link);
thread->effective_priority = priority;
AddPrio(thread->queue, thread, link);
if (thread->mutex) {
return thread->mutex->thread;
}
break;
case OS_THREAD_STATE_RUNNING:
RunQueueHint = TRUE;
thread->effective_priority = priority;
break;
}
return NULL;
}
static void UpdatePriority(OSThread* thread) {
OSPriority priority;
do {
if (0 < thread->suspend_count) {
break;
}
priority = __OSGetEffectivePriority(thread);
if (thread->effective_priority == priority) {
break;
}
thread = SetEffectivePriority(thread, priority);
} while (thread);
}
void __OSPromoteThread(OSThread* thread, s32 priority) {
do {
if (thread->suspend_count > 0 || thread->effective_priority <= priority) {
break;
}
thread = SetEffectivePriority(thread, priority);
} while (thread != NULL);
}
static inline void __OSSwitchThread(OSThread* nextThread) {
OSSetCurrentThread(nextThread);
OSSetCurrentContext(&nextThread->context);
OSLoadContext(&nextThread->context);
}
inline OSThread* i_OSGetCurrentThread(void) {
return OS_CURRENT_THREAD;
}
static OSThread* SelectThread(BOOL yield) {
OSContext* currentContext;
OSThread* currentThread;
OSThread* nextThread;
OSPriority priority;
OSThreadQueue* queue;
if (0 < Reschedule) {
return 0;
}
currentContext = OSGetCurrentContext();
currentThread = i_OSGetCurrentThread();
if (currentContext != &currentThread->context) {
return 0;
}
if (currentThread) {
if (currentThread->state == OS_THREAD_STATE_RUNNING) {
if (!yield) {
priority = __cntlzw(RunQueueBits);
if (currentThread->effective_priority <= priority) {
return 0;
}
}
currentThread->state = OS_THREAD_STATE_READY;
SetRun(currentThread);
}
if (!(currentThread->context.state & OS_CONTEXT_STATE_EXC) &&
OSSaveContext(&currentThread->context))
{
return 0;
}
}
if (RunQueueBits == 0) {
OSSetCurrentThread(NULL);
OSSetCurrentContext(&IdleContext);
do {
OSEnableInterrupts();
while (RunQueueBits == 0)
;
OSDisableInterrupts();
} while (RunQueueBits == 0);
OSClearContext(&IdleContext);
}
RunQueueHint = FALSE;
priority = __cntlzw(RunQueueBits);
queue = &RunQueue[priority];
RemoveHead(queue, nextThread, link);
if (queue->head == 0) {
RunQueueBits &= ~(1u << (OS_PRIORITY_MAX - priority));
}
nextThread->queue = NULL;
nextThread->state = OS_THREAD_STATE_RUNNING;
__OSSwitchThread(nextThread);
return nextThread;
}
void __OSReschedule(void) {
if (!RunQueueHint) {
return;
}
SelectThread(FALSE);
}
void OSYieldThread(void) {
BOOL enabled;
enabled = OSDisableInterrupts();
SelectThread(TRUE);
OSRestoreInterrupts(enabled);
}
BOOL OSCreateThread(OSThread* thread_, void* func, void* param, void* stackBase, u32 stackSize,
s32 priority, u16 attribute) {
BOOL enabled;
u32 i;
u32* stack;
OSThread* thread;
u32 stack1, stack2;
if (priority < 0 || priority > 31) {
return FALSE;
}
thread = thread_;
thread->state = OS_THREAD_STATE_READY;
thread->attributes = attribute & 1;
thread->base_priority = priority;
thread->effective_priority = priority;
thread->suspend_count = 1;
thread->exit_value = (void*)-1;
thread->mutex = NULL;
thread->join_queue.tail = NULL;
thread->join_queue.head = NULL;
thread->owned_mutexes.tail = NULL;
thread->owned_mutexes.head = NULL;
stack = (u32*)((u32)stackBase & 0xfffffff8);
stack[-2] = 0;
stack[-1] = 0;
OSInitContext(&thread->context, (u32)func, (u32)stack - 8);
thread->context.lr = (u32)OSExitThread;
thread->context.gpr[3] = (u32)param;
thread->stack_base = (u8*)stackBase;
thread->stack_end = (void*)((u32)stackBase - stackSize);
*(u32*)thread->stack_end = OS_THREAD_STACK_MAGIC;
thread->error_code = NULL;
thread->data[0] = NULL;
thread->data[1] = NULL;
enabled = OSDisableInterrupts();
if (__OSErrorTable[16]) {
thread->context.srr1 |= 0x900;
thread->context.state |= 1;
thread->context.fpscr = (__OSFpscrEnableBits & 0xf8) | 4;
for (i = 0; i < 32; ++i) {
*(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL;
*(u64*)&thread->context.ps[i] = (u64)0xffffffffffffffffLL;
}
}
AddTail(&OS_THREAD_QUEUE, thread, active_threads_link);
OSRestoreInterrupts(enabled);
return TRUE;
}
void OSExitThread(void* exitValue) {
OSThread* currentThread;
BOOL enabled;
enabled = OSDisableInterrupts();
currentThread = OS_CURRENT_THREAD;
OSClearContext(&currentThread->context);
if (currentThread->attributes & OS_THREAD_ATTR_DETACH) {
RemoveItem(&OS_THREAD_QUEUE, currentThread, active_threads_link);
currentThread->state = OS_THREAD_STATE_UNINITIALIZED;
} else {
currentThread->state = OS_THREAD_STATE_DEAD;
currentThread->exit_value = exitValue;
}
__OSUnlockAllMutex(currentThread);
OSWakeupThread(&currentThread->join_queue);
RunQueueHint = TRUE;
if (RunQueueHint) {
SelectThread(FALSE);
}
OSRestoreInterrupts(enabled);
}
void OSCancelThread(OSThread* thread) {
BOOL enabled;
enabled = OSDisableInterrupts();
switch (thread->state) {
case OS_THREAD_STATE_READY:
if (!(0 < thread->suspend_count)) {
UnsetRun(thread);
}
break;
case OS_THREAD_STATE_RUNNING:
RunQueueHint = TRUE;
break;
case OS_THREAD_STATE_WAITING:
RemoveItem(thread->queue, thread, link);
thread->queue = NULL;
if (!(0 < thread->suspend_count) && thread->mutex) {
UpdatePriority(thread->mutex->thread);
}
break;
default:
OSRestoreInterrupts(enabled);
return;
}
OSClearContext(&thread->context);
if (thread->attributes & OS_THREAD_ATTR_DETACH) {
RemoveItem(&__OSActiveThreadQueue, thread, active_threads_link);
thread->state = 0;
} else {
thread->state = OS_THREAD_STATE_DEAD;
}
__OSUnlockAllMutex(thread);
OSWakeupThread(&thread->join_queue);
__OSReschedule();
OSRestoreInterrupts(enabled);
}
void OSDetachThread(OSThread* thread) {
BOOL enabled;
enabled = OSDisableInterrupts();
thread->attributes |= OS_THREAD_ATTR_DETACH;
if (thread->state == OS_THREAD_STATE_DEAD) {
RemoveItem(&__OSActiveThreadQueue, thread, active_threads_link);
thread->state = OS_THREAD_STATE_UNINITIALIZED;
}
OSWakeupThread(&thread->join_queue);
OSRestoreInterrupts(enabled);
}
s32 OSResumeThread(OSThread* thread) {
BOOL enabled;
s32 suspendCount;
enabled = OSDisableInterrupts();
suspendCount = thread->suspend_count--;
if (thread->suspend_count < 0) {
thread->suspend_count = 0;
} else if (thread->suspend_count == 0) {
switch (thread->state) {
case OS_THREAD_STATE_READY:
thread->effective_priority = __OSGetEffectivePriority(thread);
SetRun(thread);
break;
case OS_THREAD_STATE_WAITING:
RemoveItem(thread->queue, thread, link);
thread->effective_priority = __OSGetEffectivePriority(thread);
AddPrio(thread->queue, thread, link);
if (thread->mutex) {
UpdatePriority(thread->mutex->thread);
}
break;
}
__OSReschedule();
}
OSRestoreInterrupts(enabled);
return suspendCount;
}
s32 OSSuspendThread(OSThread* thread) {
BOOL enabled;
s32 suspendCount;
enabled = OSDisableInterrupts();
suspendCount = thread->suspend_count++;
if (suspendCount == 0) {
switch (thread->state) {
case OS_THREAD_STATE_RUNNING:
RunQueueHint = TRUE;
thread->state = OS_THREAD_STATE_READY;
break;
case OS_THREAD_STATE_READY:
UnsetRun(thread);
break;
case OS_THREAD_STATE_WAITING:
RemoveItem(thread->queue, thread, link);
thread->effective_priority = 32;
AddTail(thread->queue, thread, link);
if (thread->mutex) {
UpdatePriority(thread->mutex->thread);
}
break;
}
__OSReschedule();
}
OSRestoreInterrupts(enabled);
return suspendCount;
}
void OSSleepThread(OSThreadQueue* queue) {
BOOL enabled;
OSThread* currentThread;
enabled = OSDisableInterrupts();
currentThread = OSGetCurrentThread();
currentThread->state = OS_THREAD_STATE_WAITING;
currentThread->queue = queue;
AddPrio(queue, currentThread, link);
RunQueueHint = TRUE;
__OSReschedule();
OSRestoreInterrupts(enabled);
}
void OSWakeupThread(OSThreadQueue* queue) {
BOOL enabled;
OSThread* thread;
enabled = OSDisableInterrupts();
while (queue->head) {
RemoveHead(queue, thread, link);
thread->state = OS_THREAD_STATE_READY;
if (!(0 < thread->suspend_count)) {
SetRun(thread);
}
}
__OSReschedule();
OSRestoreInterrupts(enabled);
}
s32 OSSetThreadPriority(OSThread* thread, s32 priority) {
BOOL enabled;
if (priority < 0 || priority > 31) {
return FALSE;
}
enabled = OSDisableInterrupts();
if ((s32)thread->base_priority != priority) {
thread->base_priority = priority;
UpdatePriority(thread);
__OSReschedule();
}
OSRestoreInterrupts(enabled);
return TRUE;
}
s32 OSGetThreadPriority(OSThread* thread) {
return thread->base_priority;
}
s32 CheckThreadQueue(OSThreadQueue* thread) {
OSThread* current;
if (thread->head && thread->head->link.prev) {
return 0;
}
if (thread->tail && thread->tail->link.next) {
return 0;
}
current = thread->head;
while (current) {
if (current->link.next && current != current->link.next->link.prev) {
return 0;
}
if (current->link.prev && current != current->link.prev->link.next) {
return 0;
}
current = current->link.next;
}
return 1;
}
static BOOL isMember(OSThreadQueue* queue, OSThread* thread) {
OSThread* current = queue->head;
while (current != NULL) {
if (thread == current) {
return TRUE;
}
current = current->link.next;
}
return FALSE;
}
s32 OSCheckActiveThreads(void) {
s32 i;
OSThread* thread;
s32 rv = 0;
BOOL enabled;
enabled = OSDisableInterrupts();
for (i = 0; i <= 31; i++) {
if (RunQueueBits & (1 << (31 - i))) {
if (RunQueue[i].head == NULL || RunQueue[i].tail == NULL) {
OSReport("OSCheckActiveThreads: Failed RunQueue[prio].head != NULL && "
"RunQueue[prio].tail != NULL in %d\n",
0x5e0);
OSPanic(__FILE__, 0x5e0, "");
}
} else {
if (RunQueue[i].head != NULL || RunQueue[i].tail != NULL) {
OSReport("OSCheckActiveThreads: Failed RunQueue[prio].head == NULL && "
"RunQueue[prio].tail == NULL in %d\n",
0x5e5);
OSPanic(__FILE__, 0x5e5, "");
}
}
if (CheckThreadQueue(&RunQueue[i]) == 0) {
OSReport("OSCheckActiveThreads: Failed CheckThreadQueue(&RunQueue[prio]) in %d\n",
0x5e7);
OSPanic(__FILE__, 0x5e7, "");
}
}
if (OS_THREAD_QUEUE.head != NULL && OS_THREAD_QUEUE.head->active_threads_link.prev != NULL) {
OSReport("OSCheckActiveThreads: Failed __OSActiveThreadQueue.head == NULL || "
"__OSActiveThreadQueue.head->linkActive.prev == NULL in %d\n",
0x5ec);
OSPanic(__FILE__, 0x5ec, "");
}
if (OS_THREAD_QUEUE.tail != NULL && OS_THREAD_QUEUE.tail->active_threads_link.next != NULL) {
OSReport("OSCheckActiveThreads: Failed __OSActiveThreadQueue.tail == NULL || "
"__OSActiveThreadQueue.tail->linkActive.next == NULL in %d\n",
0x5ee);
OSPanic(__FILE__, 0x5ee, "");
}
thread = OS_THREAD_QUEUE.head;
while (thread != NULL) {
rv++;
if (thread->active_threads_link.next != NULL &&
thread != thread->active_threads_link.next->active_threads_link.prev)
{
OSReport("OSCheckActiveThreads: Failed thread->linkActive.next == NULL || thread == "
"thread->linkActive.next->linkActive.prev in %d\n",
0x5f6);
OSPanic(__FILE__, 0x5f6, "");
}
if (thread->active_threads_link.prev != NULL &&
thread != thread->active_threads_link.prev->active_threads_link.next)
{
OSReport("OSCheckActiveThreads: Failed thread->linkActive.prev == NULL || thread == "
"thread->linkActive.prev->linkActive.next in %d\n",
0x5f8);
OSPanic(__FILE__, 0x5f8, "");
}
if (*(u32*)thread->stack_end != OS_THREAD_STACK_MAGIC) {
OSReport(
"OSCheckActiveThreads: Failed *(thread->stackEnd) == OS_THREAD_STACK_MAGIC in %d\n",
0x5fb);
OSPanic(__FILE__, 0x5fb, "");
}
if (OS_PRIORITY_MIN > thread->effective_priority ||
thread->effective_priority > OS_PRIORITY_MAX + 1)
{
OSReport("OSCheckActiveThreads: Failed OS_PRIORITY_MIN <= thread->priority && "
"thread->priority <= OS_PRIORITY_MAX+1 in %d\n",
0x5fe);
OSPanic(__FILE__, 0x5fe, "");
}
if (thread->suspend_count < 0) {
OSReport("OSCheckActiveThreads: Failed 0 <= thread->suspend in %d\n", 0x5ff);
OSPanic(__FILE__, 0x5ff, "");
}
if (!CheckThreadQueue(&thread->join_queue)) {
OSReport("OSCheckActiveThreads: Failed CheckThreadQueue(&thread->queueJoin) in %d\n",
0x600);
OSPanic(__FILE__, 0x600, "");
}
switch (thread->state) {
case OS_THREAD_STATE_READY:
if (thread->suspend_count <= 0) {
if (thread->queue != &RunQueue[thread->effective_priority]) {
OSReport("OSCheckActiveThreads: Failed thread->queue == "
"&RunQueue[thread->priority] in %d\n",
0x606);
OSPanic(__FILE__, 0x606, "");
}
if (!isMember(&RunQueue[thread->effective_priority], thread)) {
OSReport("OSCheckActiveThreads: Failed IsMember(&RunQueue[thread->priority], "
"thread) in %d\n",
0x607);
OSPanic(__FILE__, 0x607, "");
}
if (thread->effective_priority != __OSGetEffectivePriority(thread)) {
OSReport("OSCheckActiveThreads: Failed thread->priority == "
"__OSGetEffectivePriority(thread) in %d\n",
0x608);
OSPanic(__FILE__, 0x608, "");
}
}
break;
case OS_THREAD_STATE_RUNNING:
if (thread->suspend_count > 0) {
OSReport("OSCheckActiveThreads: Failed !IsSuspended(thread->suspend) in %d\n",
0x60c);
OSPanic(__FILE__, 0x60c, "");
}
if (thread->queue != NULL) {
OSReport("OSCheckActiveThreads: Failed thread->queue == NULL in %d\n", 0x60d);
OSPanic(__FILE__, 0x60d, "");
}
if (thread->effective_priority != __OSGetEffectivePriority(thread)) {
OSReport("OSCheckActiveThreads: Failed thread->priority == "
"__OSGetEffectivePriority(thread) in %d\n",
0x60e);
OSPanic(__FILE__, 0x60e, "");
}
break;
case OS_THREAD_STATE_WAITING:
if (thread->queue == NULL) {
OSReport("OSCheckActiveThreads: Failed thread->queue != NULL in %d\n", 0x611);
OSPanic(__FILE__, 0x611, "");
}
if (CheckThreadQueue(thread->queue) == 0) {
OSReport("OSCheckActiveThreads: Failed CheckThreadQueue(thread->queue) in %d\n",
0x612);
OSPanic(__FILE__, 0x612, "");
}
if (!isMember(thread->queue, thread)) {
OSReport("OSCheckActiveThreads: Failed IsMember(thread->queue, thread) in %d\n",
0x613);
OSPanic(__FILE__, 0x613, "");
}
if (thread->suspend_count <= 0) {
if (thread->effective_priority != __OSGetEffectivePriority(thread)) {
OSReport("OSCheckActiveThreads: Failed thread->priority == "
"__OSGetEffectivePriority(thread) in %d\n",
0x616);
OSPanic(__FILE__, 0x616, "");
}
} else if (thread->effective_priority != 32) {
OSReport("OSCheckActiveThreads: Failed thread->priority == 32 in %d\n", 0x61a);
OSPanic(__FILE__, 0x61a, "");
}
if (__OSCheckDeadLock(thread)) {
OSReport("OSCheckActiveThreads: Failed !__OSCheckDeadLock(thread) in %d\n", 0x61c);
OSPanic(__FILE__, 0x61c, "");
}
break;
case OS_THREAD_STATE_DEAD:
if (thread->owned_mutexes.head != NULL || thread->owned_mutexes.tail != NULL) {
OSReport("OSCheckActiveThreads: Failed thread->queueMutex.head == NULL && "
"thread->queueMutex.tail == NULL in %d\n",
0x620);
OSPanic(__FILE__, 0x620, "");
}
break;
default:
OSReport("OSCheckActiveThreads: Failed. unkown thread state (%d) of thread %p\n",
thread->state, thread);
OSPanic(__FILE__, 0x626, "");
break;
}
if (!__OSCheckMutexes(thread)) {
OSReport("OSCheckActiveThreads: Failed __OSCheckMutexes(thread) in %d\n", 0x62b);
OSPanic(__FILE__, 0x62b, "");
}
thread = thread->active_threads_link.next;
}
OSRestoreInterrupts(enabled);
return rv;
}
void OSClearStack(u8 val) {
u32* sp;
u32* p;
u32 pattern;
pattern = ((u32)val << 24) | ((u32)val << 16) | ((u32)val << 8) | (u32)val;
sp = (u32*)OSGetStackPointer();
for (p = ((u32*)__OSCurrentThread->stack_end) + 1; p < sp; ++p) {
*p = pattern;
}
}
extern u8 data_804516D0[8];
u8 data_804516D0[8] ALIGN_DECL(8);

138
src/dolphin/os/OSTime.c Normal file
View File

@ -0,0 +1,138 @@
#include "dolphin/os/OSTime.h"
#include "dolphin/os/OS.h"
#define OS_TIME_MONTH_MAX 12
#define OS_TIME_WEEK_DAY_MAX 7
#define OS_TIME_YEAR_DAY_MAX 365
asm OSTime OSGetTime(void) {
// clang-format off
nofralloc
mftbu r3
mftb r4, 0x10C
mftbu r5
cmpw r3, r5
bne OSGetTime
blr
// clang-format on
}
asm OSTick OSGetTick(void) {
// clang-format off
nofralloc
mftb r3, 0x10C
blr
// clang-format on
}
#define OS_SYSTEMTIME_BASE 0x30D8
OSTime __OSGetSystemTime(void) {
BOOL enabled;
OSTime* timeAdjustAddr = (OSTime*)(OS_BASE_CACHED + OS_SYSTEMTIME_BASE);
OSTime result;
enabled = OSDisableInterrupts();
result = *timeAdjustAddr + OSGetTime();
OSRestoreInterrupts(enabled);
return result;
}
OSTime __OSTimeToSystemTime(OSTime time) {
BOOL enabled;
OSTime* timeAdjustAddr = (OSTime*)(OS_BASE_CACHED + OS_SYSTEMTIME_BASE);
OSTime result;
enabled = OSDisableInterrupts();
result = *timeAdjustAddr + time;
OSRestoreInterrupts(enabled);
return result;
}
// End of each month in standard year
static s32 YearDays[] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
};
// End of each month in leap year
static s32 LeapYearDays[] = {
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
};
static inline BOOL IsLeapYear(s32 year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
static inline s32 GetYearDays(s32 year, s32 mon) {
return (IsLeapYear(year) ? LeapYearDays : YearDays)[mon];
}
static inline s32 GetLeapDays(s32 year) {
if (year < 1) {
return 0;
}
return (year + 3) / 4 - (year - 1) / 100 + (year - 1) / 400;
}
static void GetDates(s32 days, OSCalendarTime* cal) {
s32 year;
s32 totalDays;
s32* p_days;
s32 month;
cal->week_day = (days + 6) % OS_TIME_WEEK_DAY_MAX;
for (year = days / OS_TIME_YEAR_DAY_MAX;
days < (totalDays = year * OS_TIME_YEAR_DAY_MAX + GetLeapDays(year));)
{
year--;
}
days -= totalDays;
cal->year = year;
cal->year_day = days;
p_days = IsLeapYear(year) ? LeapYearDays : YearDays;
month = OS_TIME_MONTH_MAX;
while (days < p_days[--month]) {
;
}
cal->month = month;
cal->day_of_month = days - p_days[month] + 1;
}
#define BIAS (2000 * 365 + (2000 + 3) / 4 - (2000 - 1) / 100 + (2000 - 1) / 400)
#pragma dont_inline on
void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime* td) {
int days;
int secs;
OSTime d;
d = ticks % OSSecondsToTicks(1);
if (d < 0) {
d += OSSecondsToTicks(1);
}
td->microseconds = (int)(OSTicksToMicroseconds(d) % 1000);
td->milliseconds = (int)(OSTicksToMilliseconds(d) % 1000);
ticks -= d;
days = (int)(OSTicksToSeconds(ticks) / 86400 + BIAS);
secs = (int)(OSTicksToSeconds(ticks) % 86400);
if (secs < 0) {
days -= 1;
secs += 24 * 60 * 60;
}
GetDates(days, td);
td->hours = secs / 60 / 60;
td->minutes = (secs / 60) % 60;
td->seconds = secs % 60;
}
#pragma dont_inline reset

View File

@ -0,0 +1,49 @@
//
// __ppc_eabi_init
//
#include "global.h"
#include "dolphin/base/PPCArch.h"
#ifdef __cplusplus
extern "C" {
#endif
//
// Forward References:
//
void __init_user();
void __init_cpp();
void _ExitProcess();
//
// External References:
//
typedef void (*voidfunctionptr)(); // pointer to function returning void
extern voidfunctionptr __init_cpp_exceptions_reference[];
void __init_user(void) {
__init_cpp();
}
#pragma peephole off
void __init_cpp(void) {
/**
* call static initializers
*/
voidfunctionptr* constructor;
for (constructor = __init_cpp_exceptions_reference; *constructor; constructor++) {
(*constructor)();
}
}
#pragma peephole reset
void _ExitProcess(void) {
PPCHalt();
}
#ifdef __cplusplus
}
#endif

160
src/dolphin/os/__start.c Normal file
View File

@ -0,0 +1,160 @@
#include "stdlib.h"
#include "global.h"
// #include "init.h"
//
// Forward References:
//
SECTION_INIT void __check_pad3(void);
SECTION_INIT void __set_debug_bba(void);
SECTION_INIT u8 __get_debug_bba(void);
SECTION_INIT void __start(void);
//
// External References:
//
void main();
void OSInit();
void OSResetSystem(s32, s32, s32);
void __init_user();
void DBInit();
void InitMetroTRK();
void InitMetroTRK_BBA();
extern u8 data_804516D0;
void __init_data();
void __init_hardware();
void __init_registers();
//
// Declarations:
//
SECTION_INIT void __check_pad3(void) {
if ((*(u16*)0x800030E4 & 0xEEF) == 0xEEF) {
OSResetSystem(0, 0, 0);
}
}
void __set_debug_bba(void) {
data_804516D0 = 1;
}
SECTION_INIT u8 __get_debug_bba(void) {
return data_804516D0;
}
SECTION_INIT asm void __start(void) {
// clang-format off
nofralloc
bl __init_registers
bl __init_hardware
li r0, -1
stwu r1, -8(r1)
stw r0, 4(r1)
stw r0, 0(r1)
bl __init_data
li r0, 0
lis r6, 0x8000
addi r6, r6, 0x0044
stw r0, 0(r6)
lis r6, 0x8000
addi r6, r6, 0x00F4
lwz r6, 0(r6)
cmplwi r6, 0
beq lbl_8000319C
lwz r7, 0xc(r6)
b lbl_800031BC
lbl_8000319C:
lis r5, 0x8000
addi r5, r5, 0x0034
lwz r5, 0(r5)
cmplwi r5, 0
beq lbl_800031F8
lis r7, 0x8000
addi r7, r7, 0x30E8
lwz r7, 0(r7)
lbl_800031BC:
li r5, 0
cmplwi r7, 2
beq lbl_800031E8
cmplwi r7, 3
li r5, 1
beq lbl_800031E8
cmplwi r7, 4
bne lbl_800031F8
li r5, 2
bl __set_debug_bba
b lbl_800031F8
lbl_800031E8:
lis r6, InitMetroTRK@ha
addi r6, r6, InitMetroTRK@l
mtlr r6
blrl
lbl_800031F8:
lis r6, 0x8000
addi r6, r6, 0x00F4
lwz r5, 0(r6)
cmplwi r5, 0
beq+ lbl_80003258
lwz r6, 8(r5)
cmplwi r6, 0
beq+ lbl_80003258
add r6, r5, r6
lwz r14, 0(r6)
cmplwi r14, 0
beq lbl_80003258
addi r15, r6, 4
mtctr r14
lbl_80003230:
addi r6, r6, 4
lwz r7, 0(r6)
add r7, r7, r5
stw r7, 0(r6)
bdnz lbl_80003230
lis r5, 0x8000
addi r5, r5, 0x0034
rlwinm r7, r15, 0, 0, 0x1a
stw r7, 0(r5)
b lbl_80003260
lbl_80003258:
li r14, 0
li r15, 0
lbl_80003260:
bl DBInit
bl OSInit
lis r4, 0x8000
addi r4, r4, 0x30E6
lhz r3, 0(r4)
andi. r5, r3, 0x8000
beq lbl_80003288
andi. r3, r3, 0x7fff
cmplwi r3, 1
bne lbl_8000328C
lbl_80003288:
bl __check_pad3
lbl_8000328C:
bl __get_debug_bba
cmplwi r3, 1
bne lbl_8000329C
bl InitMetroTRK_BBA
lbl_8000329C:
bl __init_user
mr r3, r14
mr r4, r15
bl main
b exit
// clang-format on
}

View File

@ -45,22 +45,22 @@ extern "C" int search_partial_address(void* address, int* module_id, int* sectio
return 0xFFFFFFFF;
OSModuleInfo* module = *(OSModuleInfo**)0x800030C8;
for (; module != NULL; module = (OSModuleInfo*)module->mNext) {
for (; module != NULL; module = (OSModuleInfo*)module->link.next) {
u32 i, addr;
OSSectionInfo* section = (OSSectionInfo*)module->info.sectionInfoOffset;
OSSectionInfo* section = (OSSectionInfo*)module->sectionInfoOffset;
for (i = 0; i < module->mNumSections; section++, i++) {
if (section->mSize != 0) {
addr = section->mOffset & ~0x01;
if ((addr <= (u32)address) && (u32)address < (addr + section->mSize)) {
for (i = 0; i < module->numSections; section++, i++) {
if (section->size != 0) {
addr = section->offset & ~0x01;
if ((addr <= (u32)address) && (u32)address < (addr + section->size)) {
if (module_id != NULL)
*module_id = module->mId;
*module_id = module->id;
if (section_id != NULL)
*section_id = i;
if (section_offset)
*section_offset = (u32)address - addr;
if (name_offset)
*name_offset = module->mModuleNameOffset;
*name_offset = module->nameOffset;
return 0;
}
}