Link all of dolphin/os

This commit is contained in:
Cuyler36
2025-06-18 07:08:11 -04:00
parent b95c66be19
commit 1989cd28e6
36 changed files with 4767 additions and 197 deletions
+34
View File
@@ -20,6 +20,40 @@ block_relocations:
- source: 0x80052D58
add_relocations:
# OS.c
- source: .text:0x80078984
type: ha
target: __ArenaLo
- source: .text:0x80078988
type: l
target: __ArenaLo
- source: .text:0x800789BC
type: ha
target: _stack_addr
- source: .text:0x800789C0
type: l
target: _stack_addr
- source: .text:0x800789E0
type: ha
target: __ArenaHi
- source: .text:0x800789E4
type: l
target: __ArenaHi
# OSThread.c
- source: .text:0x8007DC18
type: ha
target: _stack_addr
- source: .text:0x8007DC1C
type: l
target: _stack_addr
- source: .text:0x8007DC20
type: ha
target: _stack_end
- source: .text:0x8007DC28
type: l
target: _stack_end
# emu64
- source: .text:0x8004F4F4 # setup_texture_tile (inlined texture_cache_select)
type: ha
+3 -3
View File
@@ -12,10 +12,10 @@ SECTIONS
} > text
_stack_end = ($LAST_SECTION_SYMBOL + SIZEOF($LAST_SECTION_NAME)+ 0x7) & ~0x7;
_stack_addr = (_stack_end + 0x2000 + 0x7) & ~0x7;
_db_stack_addr = (_stack_addr + 0x1000);
_stack_addr = (_stack_end + 0x1000 + 0x7) & ~0x7;
_db_stack_addr = (_stack_addr + 0x2000);
_db_stack_end = _stack_addr;
__ArenaLo = _db_stack_addr;
__ArenaLo = (_db_stack_addr + 0x1F) & ~0x1F;
__ArenaHi = 0x81700000;
}
+14 -14
View File
@@ -565,27 +565,27 @@ config.libs = [
[
Object(Matching, "dolphin/os/__ppc_eabi_init.cpp"),
Object(Matching, "dolphin/os/__start.c"),
Object(NonMatching, "dolphin/os/OS.c"),
Object(Matching, "dolphin/os/OS.c"),
Object(Matching, "dolphin/os/OSAlarm.c"),
Object(NonMatching, "dolphin/os/OSAlloc.c"),
Object(Matching, "dolphin/os/OSAlloc.c"),
Object(Matching, "dolphin/os/OSArena.c"),
Object(Matching, "dolphin/os/OSAudioSystem.c"),
Object(Matching, "dolphin/os/OSCache.c"),
Object(Matching, "dolphin/os/OSContext.c"),
Object(Matching, "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/OSMemory.c"),
Object(NonMatching, "dolphin/os/OSMessage.c"),
Object(NonMatching, "dolphin/os/OSMutex.c"),
Object(NonMatching, "dolphin/os/OSReboot.c"),
Object(NonMatching, "dolphin/os/OSReset.c"),
Object(NonMatching, "dolphin/os/OSResetSW.c"),
Object(Matching, "dolphin/os/OSFont.c"),
Object(Matching, "dolphin/os/OSInterrupt.c"),
Object(Matching, "dolphin/os/OSLink.c"),
Object(Matching, "dolphin/os/OSMemory.c"),
Object(Matching, "dolphin/os/OSMessage.c"),
Object(Matching, "dolphin/os/OSMutex.c"),
Object(Matching, "dolphin/os/OSReboot.c"),
Object(Matching, "dolphin/os/OSReset.c"),
Object(Matching, "dolphin/os/OSResetSW.c"),
Object(Matching, "dolphin/os/OSRtc.c"),
Object(NonMatching, "dolphin/os/OSSync.c"),
Object(NonMatching, "dolphin/os/OSThread.c"),
Object(NonMatching, "dolphin/os/OSTime.c"),
Object(Matching, "dolphin/os/OSSync.c"),
Object(Matching, "dolphin/os/OSThread.c"),
Object(Matching, "dolphin/os/OSTime.c"),
],
),
DolphinLib(
+1
View File
@@ -3,6 +3,7 @@
#include "types.h"
#include "dolphin/os/OSModule.h"
#include "dolphin/os/OSLink.h"
#include "dolphin/os/OSTime.h"
#ifdef __cplusplus
+17
View File
@@ -94,6 +94,23 @@ void PPCSetFpNonIEEEMode(void);
#define MSR_RI 0x00000002 // Recoverable interrupt
#define MSR_LE 0x00000001 // Little Endian
#define MSR_POW_BIT 13 // Power Management
#define MSR_ILE_BIT 15 // Interrupt Little Endian
#define MSR_EE_BIT 16 // external interrupt
#define MSR_PR_BIT 17 // privilege level (should be 0)
#define MSR_FP_BIT 18 // floating point available
#define MSR_ME_BIT 19 // machine check enable
#define MSR_FE0_BIT 20 // floating point exception enable
#define MSR_SE_BIT 21 // single step trace enable
#define MSR_BE_BIT 22 // branch trace enable
#define MSR_FE1_BIT 23 // floating point exception enable
#define MSR_IP_BIT 25 // Exception prefix
#define MSR_IR_BIT 26 // instruction relocate
#define MSR_DR_BIT 27 // data relocate
#define MSR_PM_BIT 29 // Performance monitor marked mode
#define MSR_RI_BIT 30 // Recoverable interrupt
#define MSR_LE_BIT 31 // Little Endian
#ifdef __cplusplus
}
#endif
+3 -14
View File
@@ -2,6 +2,7 @@
#define DB_H
#include "types.h"
#include <dolphin/db/DBInterface.h>
#ifdef __cplusplus
extern "C"{
@@ -9,20 +10,8 @@ extern "C"{
#define OS_DBINTERFACE_ADDR 0x00000040
typedef struct DBInterface
{
u32 bPresent;
u32 exceptionMask;
void (*ExceptionDestination) ( void );
void *exceptionReturn;
} DBInterface;
extern DBInterface* __DBInterface;
void DBInit(void);
void DBInitComm(int* inputFlagPtr, int* mtrCallback);
static void __DBExceptionDestination(void);
void DBPrintf(char* format, ...);
BOOL DBIsDebuggerPresent(void);
void DBPrintf(char* str, ...);
#ifdef __cplusplus
}
+31
View File
@@ -0,0 +1,31 @@
#ifndef _DOLPHIN_DBINTERFACE_H_
#define _DOLPHIN_DBINTERFACE_H_
#include <dolphin/os.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct DBInterface {
u32 bPresent;
u32 exceptionMask;
void (*ExceptionDestination)(void);
void* exceptionReturn;
} DBInterface;
extern DBInterface* __DBInterface;
void DBInit(void);
void DBInitComm(int* inputFlagPtr, int* mtrCallback);
void __DBExceptionDestination(void);
void __DBExceptionDestinationAux(void);
BOOL __DBIsExceptionMarked(__OSException exception);
void __DBMarkException(u8 exception, int value);
void __DBSetPresent(u32 value);
#ifdef __cplusplus
}
#endif
#endif
+13
View File
@@ -9,6 +9,7 @@
#include "dolphin/os/OSError.h"
#include "dolphin/os/OSInterrupt.h"
#include "dolphin/os/OSModule.h"
#include "dolphin/os/OSLink.h"
#include "dolphin/os/OSMemory.h"
#include "dolphin/os/OSMessage.h"
#include "libforest/osreport.h" /* OSReport funcs */
@@ -100,6 +101,18 @@ typedef struct OSBootInfo_s {
#define OS_BASE_CACHED (OS_CACHED_REGION_PREFIX << 16)
#define OS_BASE_UNCACHED (OS_UNCACHED_REGION_PREFIX << 16)
typedef struct BI2Debug {
/* 0x00 */ s32 debugMonSize;
/* 0x04 */ s32 simMemSize;
/* 0x08 */ u32 argOffset;
/* 0x0C */ u32 debugFlag;
/* 0x10 */ int trackLocation;
/* 0x14 */ int trackSize;
/* 0x18 */ u32 countryCode;
/* 0x1C */ u8 unk[8];
/* 0x24 */ u32 padSpec;
} BI2Debug;
#ifdef __MWERKS__
u32 __OSPhysicalMemSize : (OS_BASE_CACHED | 0x0028);
volatile int __OSTVMode : (OS_BASE_CACHED | 0x00CC);
+2 -1
View File
@@ -9,6 +9,7 @@ extern "C" {
typedef u16 OSError;
typedef void (*OSErrorHandler)(OSError error, OSContext *context, ...);
typedef void (*OSErrorHandlerEx)(OSError error, OSContext* context, ...);
#define OS_ERROR_SYSTEM_RESET 0
#define OS_ERROR_MACHINE_CHECK 1
@@ -37,4 +38,4 @@ extern u32 __OSFpscrEnableBits;
}
#endif
#endif
#endif
+20
View File
@@ -30,6 +30,26 @@ typedef void (*__OSExceptionHandler)(__OSException exception, OSContext* context
__OSExceptionHandler __OSSetExceptionHandler(__OSException exception, __OSExceptionHandler handler);
__OSExceptionHandler __OSGetExceptionHandler(__OSException exception);
#define OS_EXCEPTION_SAVE_GPRS(context) \
stw r0, OS_CONTEXT_R0(context); \
stw r1, OS_CONTEXT_R1(context); \
stw r2, OS_CONTEXT_R2(context); \
stmw r6, OS_CONTEXT_R6(context); \
mfspr r0, GQR1; \
stw r0, OS_CONTEXT_GQR1(context); \
mfspr r0, GQR2; \
stw r0, OS_CONTEXT_GQR2(context); \
mfspr r0, GQR3; \
stw r0, OS_CONTEXT_GQR3(context); \
mfspr r0, GQR4; \
stw r0, OS_CONTEXT_GQR4(context); \
mfspr r0, GQR5; \
stw r0, OS_CONTEXT_GQR5(context); \
mfspr r0, GQR6; \
stw r0, OS_CONTEXT_GQR6(context); \
mfspr r0, GQR7; \
stw r0, OS_CONTEXT_GQR7(context);
#ifdef __cplusplus
}
#endif
+3
View File
@@ -7,6 +7,9 @@
extern "C" {
#endif
#define OS_FONT_ROM_SIZE_ANSI 0x03000
#define OS_FONT_ROM_SIZE_SJIS 0x4D000
typedef struct OSFontHeader {
u16 fontType; // _00
u16 firstChar; // _02, first char code defined in font.
+90 -52
View File
@@ -49,60 +49,98 @@ typedef enum OSInterruptType {
OS_INTR_MAX
} OSInterruptType;
#define OS_INTRMASK_MEM_0 (0x80000000U >> OS_INTR_MEM_0)
#define OS_INTRMASK_MEM_1 (0x80000000U >> OS_INTR_MEM_1)
#define OS_INTRMASK_MEM_2 (0x80000000U >> OS_INTR_MEM_2)
#define OS_INTRMASK_MEM_3 (0x80000000U >> OS_INTR_MEM_3)
#define OS_INTRMASK_MEM_ADDRESS (0x80000000U >> OS_INTR_MEM_ADDRESS)
#define OS_INTRMASK_DSP_AI (0x80000000U >> OS_INTR_DSP_AI)
#define OS_INTRMASK_DSP_ARAM (0x80000000U >> OS_INTR_DSP_ARAM)
#define OS_INTRMASK_DSP_DSP (0x80000000U >> OS_INTR_DSP_DSP)
#define OS_INTRMASK_AI_AI (0x80000000U >> OS_INTR_AI_AI)
#define OS_INTRMASK_EXI_0_EXI (0x80000000U >> OS_INTR_EXI_0_EXI)
#define OS_INTRMASK_EXI_0_TC (0x80000000U >> OS_INTR_EXI_0_TC)
#define OS_INTRMASK_EXI_0_EXT (0x80000000U >> OS_INTR_EXI_0_EXT)
#define OS_INTRMASK_EXI_1_EXI (0x80000000U >> OS_INTR_EXI_1_EXI)
#define OS_INTRMASK_EXI_1_TC (0x80000000U >> OS_INTR_EXI_1_TC)
#define OS_INTRMASK_EXI_1_EXT (0x80000000U >> OS_INTR_EXI_1_EXT)
#define OS_INTRMASK_EXI_2_EXI (0x80000000U >> OS_INTR_EXI_2_EXI)
#define OS_INTRMASK_EXI_2_TC (0x80000000U >> OS_INTR_EXI_2_TC)
#define OS_INTRMASK_PI_CP (0x80000000U >> OS_INTR_PI_CP)
#define OS_INTRMASK_PI_PE_TOKEN (0x80000000U >> OS_INTR_PI_PE_TOKEN)
#define OS_INTRMASK_PI_PE_FINISH (0x80000000U >> OS_INTR_PI_PE_FINISH)
#define OS_INTRMASK_PI_SI (0x80000000U >> OS_INTR_PI_SI)
#define OS_INTRMASK_PI_DI (0x80000000U >> OS_INTR_PI_DI)
#define OS_INTRMASK_PI_RSW (0x80000000U >> OS_INTR_PI_RSW)
#define OS_INTRMASK_PI_ERROR (0x80000000U >> OS_INTR_PI_ERROR)
#define OS_INTRMASK_PI_VI (0x80000000U >> OS_INTR_PI_VI)
#define OS_INTRMASK_PI_DEBUG (0x80000000U >> OS_INTR_PI_DEBUG)
#define OS_INTRMASK_PI_HSP (0x80000000U >> OS_INTR_PI_HSP)
#define __OS_INTERRUPT_MEM_0 0
#define __OS_INTERRUPT_MEM_1 1
#define __OS_INTERRUPT_MEM_2 2
#define __OS_INTERRUPT_MEM_3 3
#define __OS_INTERRUPT_MEM_ADDRESS 4
#define __OS_INTERRUPT_DSP_AI 5
#define __OS_INTERRUPT_DSP_ARAM 6
#define __OS_INTERRUPT_DSP_DSP 7
#define __OS_INTERRUPT_AI_AI 8
#define __OS_INTERRUPT_EXI_0_EXI 9
#define __OS_INTERRUPT_EXI_0_TC 10
#define __OS_INTERRUPT_EXI_0_EXT 11
#define __OS_INTERRUPT_EXI_1_EXI 12
#define __OS_INTERRUPT_EXI_1_TC 13
#define __OS_INTERRUPT_EXI_1_EXT 14
#define __OS_INTERRUPT_EXI_2_EXI 15
#define __OS_INTERRUPT_EXI_2_TC 16
#define __OS_INTERRUPT_PI_CP 17
#define __OS_INTERRUPT_PI_PE_TOKEN 18
#define __OS_INTERRUPT_PI_PE_FINISH 19
#define __OS_INTERRUPT_PI_SI 20
#define __OS_INTERRUPT_PI_DI 21
#define __OS_INTERRUPT_PI_RSW 22
#define __OS_INTERRUPT_PI_ERROR 23
#define __OS_INTERRUPT_PI_VI 24
#define __OS_INTERRUPT_PI_DEBUG 25
#define __OS_INTERRUPT_PI_HSP 26
#define __OS_INTERRUPT_MAX 32
#define OS_INTRMASK_MEM \
(OS_INTRMASK_MEM_0 | OS_INTRMASK_MEM_1 | OS_INTRMASK_MEM_2 | \
OS_INTRMASK_MEM_3 | OS_INTRMASK_MEM_ADDRESS)
#define OS_INTERRUPTMASK(interrupt) (0x80000000u >> (interrupt))
#define OS_INTRMASK_AI (OS_INTRMASK_AI_AI)
#define OS_INTRMASK_DSP \
(OS_INTRMASK_DSP_AI | OS_INTRMASK_DSP_ARAM | OS_INTRMASK_DSP_DSP)
#define OS_INTRMASK_EXI_0 \
(OS_INTRMASK_EXI_0_EXI | OS_INTRMASK_EXI_0_TC | OS_INTRMASK_EXI_0_EXT)
#define OS_INTRMASK_EXI_1 \
(OS_INTRMASK_EXI_1_EXI | OS_INTRMASK_EXI_1_TC | OS_INTRMASK_EXI_1_EXT)
#define OS_INTRMASK_EXI_2 (OS_INTRMASK_EXI_2_EXI | OS_INTRMASK_EXI_2_TC)
#define OS_INTRMASK_EXI \
(OS_INTRMASK_EXI_0_EXI | OS_INTRMASK_EXI_0_TC | OS_INTRMASK_EXI_0_EXT | \
OS_INTRMASK_EXI_1_EXI | OS_INTRMASK_EXI_1_TC | OS_INTRMASK_EXI_1_EXT | \
OS_INTRMASK_EXI_2_EXI | OS_INTRMASK_EXI_2_TC)
#define OS_INTRMASK_PI \
(OS_INTRMASK_PI_CP | OS_INTRMASK_PI_SI | OS_INTRMASK_PI_DI | \
OS_INTRMASK_PI_RSW | OS_INTRMASK_PI_ERROR | OS_INTRMASK_PI_VI | \
OS_INTRMASK_PI_PE_TOKEN | OS_INTRMASK_PI_PE_FINISH | \
OS_INTRMASK_PI_DEBUG | OS_INTRMASK_PI_HSP)
#define OS_INTRMASK_PI_PE (OS_INTRMASK_PI_PE_TOKEN | OS_INTRMASK_PI_PE_FINISH)
#define OS_INTERRUPTMASK_MEM_0 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0)
#define OS_INTERRUPTMASK_MEM_1 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_1)
#define OS_INTERRUPTMASK_MEM_2 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_2)
#define OS_INTERRUPTMASK_MEM_3 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_3)
#define OS_INTERRUPTMASK_MEM_ADDRESS \
OS_INTERRUPTMASK(__OS_INTERRUPT_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)
#define OS_INTERRUPTMASK_DSP_AI OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_AI)
#define OS_INTERRUPTMASK_DSP_ARAM OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_ARAM)
#define OS_INTERRUPTMASK_DSP_DSP OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_DSP)
#define OS_INTERRUPTMASK_DSP \
(OS_INTERRUPTMASK_DSP_AI | OS_INTERRUPTMASK_DSP_ARAM \
| OS_INTERRUPTMASK_DSP_DSP)
#define OS_INTERRUPTMASK_AI_AI OS_INTERRUPTMASK(__OS_INTERRUPT_AI_AI)
#define OS_INTERRUPTMASK_AI (OS_INTERRUPTMASK_AI_AI)
#define OS_INTERRUPTMASK_EXI_0_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_EXI)
#define OS_INTERRUPTMASK_EXI_0_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_TC)
#define OS_INTERRUPTMASK_EXI_0_EXT OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_EXT)
#define OS_INTERRUPTMASK_EXI_0 \
(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC \
| OS_INTERRUPTMASK_EXI_0_EXT)
#define OS_INTERRUPTMASK_EXI_1_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_EXI)
#define OS_INTERRUPTMASK_EXI_1_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_TC)
#define OS_INTERRUPTMASK_EXI_1_EXT OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_EXT)
#define OS_INTERRUPTMASK_EXI_1 \
(OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC \
| OS_INTERRUPTMASK_EXI_1_EXT)
#define OS_INTERRUPTMASK_EXI_2_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_2_EXI)
#define OS_INTERRUPTMASK_EXI_2_TC OS_INTERRUPTMASK(__OS_INTERRUPT_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)
#define OS_INTERRUPTMASK_PI_PE_TOKEN \
OS_INTERRUPTMASK(__OS_INTERRUPT_PI_PE_TOKEN)
#define OS_INTERRUPTMASK_PI_PE_FINISH \
OS_INTERRUPTMASK(__OS_INTERRUPT_PI_PE_FINISH)
#define OS_INTERRUPTMASK_PI_PE \
(OS_INTERRUPTMASK_PI_PE_TOKEN | OS_INTERRUPTMASK_PI_PE_FINISH)
#define OS_INTERRUPTMASK_PI_CP OS_INTERRUPTMASK(__OS_INTERRUPT_PI_CP)
#define OS_INTERRUPTMASK_PI_SI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_SI)
#define OS_INTERRUPTMASK_PI_DI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_DI)
#define OS_INTERRUPTMASK_PI_RSW OS_INTERRUPTMASK(__OS_INTERRUPT_PI_RSW)
#define OS_INTERRUPTMASK_PI_ERROR OS_INTERRUPTMASK(__OS_INTERRUPT_PI_ERROR)
#define OS_INTERRUPTMASK_PI_VI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_VI)
#define OS_INTERRUPTMASK_PI_DEBUG OS_INTERRUPTMASK(__OS_INTERRUPT_PI_DEBUG)
#define OS_INTERRUPTMASK_PI_HSP OS_INTERRUPTMASK(__OS_INTERRUPT_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)
typedef void (*__OSInterruptHandler)(__OSInterrupt, OSContext*);
+111
View File
@@ -0,0 +1,111 @@
#ifndef OSLINK_H
#define OSLINK_H
#include <dolphin/os/OSUtil.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OS_MODULE_VERSION 2
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;
struct OSModuleQueue {
OSModuleInfo* head;
OSModuleInfo* tail;
};
OSModuleQueue __OSModuleList AT_ADDRESS(0x800030C8);
void* __OSStringTable AT_ADDRESS(0x800030D0);
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;
#endif
};
#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);
void OSSetStringTable(const void* string_table);
void __OSModuleInit(void);
#ifdef __cplusplus
};
#endif
#endif /* OSLINK_H */
+46 -46
View File
@@ -7,63 +7,63 @@
extern "C" {
#endif
typedef struct OSModuleInfo_s OSModuleInfo;
// typedef struct OSModuleInfo_s OSModuleInfo;
typedef struct OSModuleQueue_s {
OSModuleInfo* head;
OSModuleInfo* tail;
} OSModuleQueue;
// typedef struct OSModuleQueue_s {
// OSModuleInfo* head;
// OSModuleInfo* tail;
// } OSModuleQueue;
typedef struct OSModuleLink_s {
OSModuleInfo* next;
OSModuleInfo* prev;
} OSModuleLink;
// typedef struct OSModuleLink_s {
// OSModuleInfo* next;
// OSModuleInfo* prev;
// } OSModuleLink;
typedef struct OSModuleInfo_s {
u32 id;
OSModuleLink link;
u32 numSections;
u32 sectionInfoOfs;
u32 nameOfs;
u32 nameSize;
u32 version;
} OSModuleInfo;
// typedef struct OSModuleInfo_s {
// u32 id;
// OSModuleLink link;
// u32 numSections;
// u32 sectionInfoOfs;
// u32 nameOfs;
// u32 nameSize;
// u32 version;
// } OSModuleInfo;
typedef struct OSModuleHeader_s {
OSModuleInfo info;
u32 bssSize;
u32 relOfs;
u32 impOfs;
u32 impSize;
// typedef struct OSModuleHeader_s {
// OSModuleInfo info;
// u32 bssSize;
// u32 relOfs;
// u32 impOfs;
// u32 impSize;
u8 prologSection;
u8 epilogSection;
u8 unresolvedSection;
u8 bssSection;
// u8 prologSection;
// u8 epilogSection;
// u8 unresolvedSection;
// u8 bssSection;
u32 prolog;
u32 epilog;
u32 unresolved;
/* OS_MODULE_VERSION >= 2 */
// u32 prolog;
// u32 epilog;
// u32 unresolved;
// /* OS_MODULE_VERSION >= 2 */
u32 align;
u32 bssAlign;
} OSModuleHeader;
// u32 align;
// u32 bssAlign;
// } OSModuleHeader;
typedef struct OSSectionInfo_s {
u32 offset;
u32 size;
} OSSectionInfo;
// typedef struct OSSectionInfo_s {
// u32 offset;
// u32 size;
// } OSSectionInfo;
#define OSGetSectionInfo(module) \
((OSSectionInfo*) (((OSModuleInfo*) (module))->sectionInfoOfs))
// #define OSGetSectionInfo(module) \
// ((OSSectionInfo*) (((OSModuleInfo*) (module))->sectionInfoOfs))
#define OS_SECTIONINFO_EXEC 1
#define OS_SECTIONINFO_OFFSET(offset) ((offset) & ~OS_SECTIONINFO_EXEC)
// #define OS_SECTIONINFO_EXEC 1
// #define OS_SECTIONINFO_OFFSET(offset) ((offset) & ~OS_SECTIONINFO_EXEC)
void OSSetStringTable (const void* strTable);
BOOL OSLink(OSModuleInfo* module, void* bss);
BOOL OSUnlink(OSModuleInfo* module);
// void OSSetStringTable (const void* strTable);
// BOOL OSLink(OSModuleInfo* module, void* bss);
// BOOL OSUnlink(OSModuleInfo* module);
#ifdef __cplusplus
}
+5
View File
@@ -13,6 +13,11 @@ extern "C" {
#define OS_RESET_HOTRESET 1 /* Soft reset */
#define OS_RESET_SHUTDOWN 2
struct OSResetFunctionQueue {
struct OSResetFunctionInfo* head;
struct OSResetFunctionInfo* tail;
};
typedef BOOL (*OSResetFunction)(BOOL final);
typedef struct OSResetFunctionInfo OSResetFunctionInfo;
+5 -1
View File
@@ -7,7 +7,11 @@
extern "C" {
#endif
BOOL OSGetResetSwitchState();
typedef void (*OSResetCallback)(void);
OSResetCallback OSSetResetCallback(OSResetCallback callback);
BOOL OSGetResetSwitchState(void);
BOOL OSGetResetButtonState(void);
#ifdef __cplusplus
}
+13
View File
@@ -46,6 +46,19 @@ typedef struct OSCalendarTime_s {
OSTime OSCalendarTimeToTicks(OSCalendarTime* td);
void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime* td);
#define USEC_MAX 1000
#define MSEC_MAX 1000
#define MONTH_MAX 12
#define WEEK_DAY_MAX 7
#define YEAR_DAY_MAX 365
#define SECS_IN_MIN 60
#define SECS_IN_HOUR (SECS_IN_MIN * 60)
#define SECS_IN_DAY (SECS_IN_HOUR * 24)
#define SECS_IN_YEAR (SECS_IN_DAY * 365)
#define BIAS 0xB2575
#ifdef __cplusplus
}
#endif
+1 -1
View File
@@ -187,7 +187,7 @@ bool JUTException::searchPartialModule(u32 address, u32* module_id, u32* section
if (section_offset)
*section_offset = address - addr;
if (name_offset)
*name_offset = module->nameOfs;
*name_offset = module->nameOffset;
return true;
}
}
+1 -1
View File
@@ -85,7 +85,7 @@ s32 search_partial_address(u32 addr, u32* module_id, u32* section_idx, u32* sect
*section_addr = addr - section_ofs;
}
if (module_name_ofs != nullptr) {
*module_name_ofs = module_p->info.nameOfs;
*module_name_ofs = module_p->info.nameOffset;
}
return 0; /* success */
+583
View File
@@ -0,0 +1,583 @@
#include <dolphin/os.h>
#include <dolphin/base/PPCArch.h>
#include <dolphin/db.h>
#include <dolphin/exi.h>
#include <string.h>
#include <macros.h>
#include "../src/static/dolphin/os/__os.h"
void EnableMetroTRKInterrupts(void);
#define OS_CURRENTCONTEXT_PADDR 0x00C0
#define OS_EXCEPTIONTABLE_ADDR 0x3000
#define OS_DBJUMPPOINT_ADDR 0x60
// memory locations for important stuff
#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
extern unsigned long __DVDLongFileNameFlag;
extern unsigned long __PADSpec;
extern unsigned char __ArenaLo[];
extern char _stack_addr[];
extern unsigned char __ArenaHi[];
// dummy entry points to the OS Exception vector
void __OSEVStart(void);
void __OSEVEnd(void);
void __OSEVSetNumber(void);
void __OSExceptionVector(void);
void __DBVECTOR(void);
void __OSDBINTSTART(void);
void __OSDBINTEND(void);
void __OSDBJUMPSTART(void);
void __OSDBJUMPEND(void);
#define NOP 0x60000000
static OSBootInfo* BootInfo;
static volatile u32* BI2DebugFlag;
static u32* BI2DebugFlagHolder;
static f64 ZeroPS;
static f64 ZeroF;
static BOOL __OSIsGcam;
static BOOL AreWeInitialized;
typedef void (*OSExceptionHandler)(u8, struct OSContext*);
static OSExceptionHandler* OSExceptionTable;
static void* __OSSavedRegionEnd;
static void* __OSSavedRegionStart;
static BOOL __OSInIPL;
OSTime __OSStartTime;
static DVDDriveInfo DriveInfo __attribute__((aligned(0x20)));
static DVDCommandBlock DriveBlock;
// functions
static asm void __OSInitFPRs(void);
static void OSExceptionInit(void);
static void OSDefaultExceptionHandler(u8 exception /* r3 */,
OSContext* context /* r4 */);
// NOTE: this is unused, but stuff won't align properly without it
static asm void __OSInitFPRs(void)
{
#ifdef __MWERKS__ // 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
#endif // clang-format on
}
unsigned long OSGetConsoleType()
{
if ((!BootInfo) || (BootInfo->consoleType == 0)) {
return OS_CONSOLE_ARTHUR;
}
return BootInfo->consoleType;
}
volatile u16 __OSDeviceCode AT_ADDRESS(0x800030E6);
static void ClearArena()
{
if (OSGetResetCode() != -0x80000000) {
__OSSavedRegionStart = NULL;
__OSSavedRegionEnd = NULL;
memset(OSGetArenaLo(), 0, (u8*)OSGetArenaHi() - (u8*)OSGetArenaLo());
return;
}
__OSSavedRegionStart = BOOT_REGION_START;
__OSSavedRegionEnd = BOOT_REGION_END;
if (BOOT_REGION_START == NULL) {
memset(OSGetArenaLo(), 0, (u8*)OSGetArenaHi() - (u8*)OSGetArenaLo());
return;
}
if ((u8*)OSGetArenaLo() < (u8*)__OSSavedRegionStart) {
if ((u8*)OSGetArenaHi() <= (u8*)__OSSavedRegionStart) {
memset(OSGetArenaLo(), 0,
(u8*)OSGetArenaHi() - (u8*)OSGetArenaLo());
return;
}
memset(OSGetArenaLo(), 0,
(u8*)__OSSavedRegionStart - (u8*)OSGetArenaLo());
if ((u8*)OSGetArenaHi() > (u8*)__OSSavedRegionEnd) {
memset(__OSSavedRegionEnd, 0,
(u8*)OSGetArenaHi() - (u8*)__OSSavedRegionEnd);
}
}
}
static void InquiryCallback(s32 result, struct DVDCommandBlock* block)
{
switch (block->state) {
case 0:
__OSDeviceCode = DriveInfo.deviceCode | 0x8000;
break;
default:
__OSDeviceCode = 1;
break;
}
}
void OSInit()
{
u32 consoleType;
BI2Debug* bi2DebugInfo;
if (AreWeInitialized != 0)
return;
AreWeInitialized = 1;
__OSStartTime = __OSGetSystemTime();
OSDisableInterrupts();
PPCDisableSpeculation();
PPCSetFpNonIEEEMode();
BootInfo = (struct OSBootInfo_s*)OSPhysicalToCached(0);
BI2DebugFlag = NULL;
__DVDLongFileNameFlag = 0;
bi2DebugInfo = (BI2Debug*)*(BI2Debug**)OS_BI2_DEBUG_ADDRESS;
if (bi2DebugInfo != NULL) {
BI2DebugFlag = &bi2DebugInfo->debugFlag;
__PADSpec = bi2DebugInfo->padSpec;
*((u8*)DEBUGFLAG_ADDR) = (u8)*BI2DebugFlag;
*((u8*)OS_DEBUG_ADDRESS_2) = (u8)__PADSpec;
} else if (BootInfo->arenaHi) {
BI2DebugFlagHolder = (u32*)*((u8*)DEBUGFLAG_ADDR);
BI2DebugFlag = (u32*)&BI2DebugFlagHolder;
__PADSpec = (u32) * ((u8*)OS_DEBUG_ADDRESS_2);
}
__DVDLongFileNameFlag = 1;
OSSetArenaLo((!BootInfo->arenaLo) ? &__ArenaLo : BootInfo->arenaLo);
if ((!BootInfo->arenaLo) && (BI2DebugFlag) && (*(u32*)BI2DebugFlag < 2)) {
OSSetArenaLo((void*)(((u32)(char*)&_stack_addr + 0x1F) & 0xFFFFFFE0));
}
OSSetArenaHi((!BootInfo->arenaHi) ? &__ArenaHi : BootInfo->arenaHi);
OSExceptionInit();
__OSInitSystemCall();
OSInitAlarm();
__OSModuleInit();
__OSInterruptInit();
__OSSetInterruptHandler(0x16, &__OSResetSWInterruptHandler);
__OSContextInit();
__OSCacheInit();
EXIInit();
SIInit();
__OSInitSram();
__OSThreadInit();
__OSInitAudioSystem();
PPCMthid2(PPCMfhid2() & 0xbfffffff);
if ((BootInfo->consoleType & OS_CONSOLE_DEVELOPMENT) != 0) {
BootInfo->consoleType = OS_CONSOLE_DEVHW1;
} else {
BootInfo->consoleType = OS_CONSOLE_RETAIL1;
}
BootInfo->consoleType += (__PIRegs[11] & 0xF0000000) >> 28;
if (__OSInIPL == 0) {
__OSInitMemoryProtection();
}
OSReport("\nDolphin OS $Revision: 54 $.\n");
OSReport("Kernel built : %s %s\n", "Jun 5 2002", "02:09:12");
OSReport("Console Type : ");
consoleType = OSGetConsoleType();
// work out what console type this corresponds to and report it
// consoleTypeSwitchHi = inputConsoleType & 0xF0000000;
if ((consoleType & 0x10000000) == OS_CONSOLE_RETAIL) { // check "first" byte
OSReport("Retail %d\n", consoleType);
} else {
switch (consoleType) { // if "first" byte is 2, check "the rest"
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:
OSReport("Development HW%d\n", ((u32)consoleType - 0x10000000) - 3);
break;
}
}
// report memory size
OSReport("Memory %d MB\n", (u32)BootInfo->memorySize >> 0x14U);
// report heap bounds
OSReport("Arena : 0x%x - 0x%x\n", OSGetArenaLo(), OSGetArenaHi());
// if location of debug flag exists, and flag is >= 2, enable
// MetroTRKInterrupts
if (BI2DebugFlag && ((*BI2DebugFlag) >= 2)) {
EnableMetroTRKInterrupts();
}
ClearArena();
OSEnableInterrupts();
if (__OSInIPL == 0) {
DVDInit();
if (__OSIsGcam) {
__OSDeviceCode = 0x9000;
return;
}
DCInvalidateRange(&DriveInfo, 0x20);
DVDInquiryAsync(&DriveBlock, &DriveInfo, InquiryCallback);
}
}
static u32 __OSExceptionLocations[] = {
0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500,
0x00000600, 0x00000700, 0x00000800, 0x00000900, 0x00000C00,
0x00000D00, 0x00000F00, 0x00001300, 0x00001400, 0x00001700,
};
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)__OSDBJUMPSTART - (u32)__OSDBINTSTART);
DCFlushRangeNoSync(destAddr,
(u32)__OSDBJUMPSTART - (u32)__OSDBINTSTART);
__sync();
ICInvalidateRange(destAddr, (u32)__OSDBJUMPSTART - (u32)__OSDBINTSTART);
}
// Copy the right vector into the table
for (exception = 0; exception < __OS_EXCEPTION_MAX; 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 = (void*)OSPhysicalToCached(OS_EXCEPTIONTABLE_ADDR);
// install default exception handlers
for (exception = 0; exception < __OS_EXCEPTION_MAX; 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");
}
static asm void __OSDBIntegrator(void)
{
#ifdef __MWERKS__ // clang-format off
nofralloc
entry __OSDBINTSTART
li r5, OS_DBINTERFACE_ADDR
mflr r3
stw r3, DB_EXCEPTIONRET_OFFSET(r5)
lwz r3, DB_EXCEPTIONDEST_OFFSET(r5)
oris r3, r3, OS_CACHED_REGION_PREFIX
mtlr r3
li r3, 0x30 // MSR_IR | MSR_DR // turn on memory addressing
mtmsr r3
blr
entry __OSDBINTEND
#endif // clang-format on
}
static asm void __OSDBJump(void) {
#ifdef __MWERKS__ // clang-format off
nofralloc
entry __OSDBJUMPSTART
bla OS_DBJUMPPOINT_ADDR
entry __OSDBJUMPEND
#endif // clang-format on
}
__OSExceptionHandler __OSSetExceptionHandler(__OSException exception,
__OSExceptionHandler handler)
{
__OSExceptionHandler oldHandler;
oldHandler = OSExceptionTable[exception];
OSExceptionTable[exception] = handler;
return oldHandler;
}
__OSExceptionHandler __OSGetExceptionHandler(__OSException exception)
{
return OSExceptionTable[exception];
}
static asm void OSExceptionVector(void)
{
#ifdef __MWERKS__ // 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
addi r3, 0, 0x0000
// Load current context virtual address into r4
lwz r4, 0xD4
// Check non-recoverable interrupt
rlwinm. r5, r5, 0, MSR_RI_BIT, MSR_RI_BIT
bne recoverable
addis r5, 0, OSDefaultExceptionHandler@ha
addi r5, r5, OSDefaultExceptionHandler@l
mtsrr0 r5
rfi
// NOT REACHED HERE
recoverable:
// Locate exception handler.
rlwinm r5, r3, 2, 22, 29 // 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 enalbed, not yet recoverable
rfi
// NOT REACHED HERE
// The handler will restore state
entry __OSEVEnd
nop
#endif // clang-format on
}
void __OSUnhandledException(__OSException exception, OSContext* context,
u32 dsisr, u32 dar);
asm void OSDefaultExceptionHandler(register __OSException exception,
register OSContext* context)
{
#ifdef __MWERKS__ // clang-format off
nofralloc
OS_EXCEPTION_SAVE_GPRS(context)
mfdsisr r5
mfdar r6
stwu r1, -0x8(r1)
b __OSUnhandledException
#endif // clang-format on
}
void __OSPSInit(void)
{
PPCMthid2(PPCMfhid2() | 0x80000000 | 0x20000000);
ICFlashInvalidate();
__sync();
#ifdef __MWERKS__ // clang-format off
asm
{
li r3, 0
mtspr GQR0, r3
}
#endif // clang-format on
}
#define DI_CONFIG_IDX 0x9
#define DI_CONFIG_CONFIG_MASK 0xFF
u32 __OSGetDIConfig(void)
{
return (__DIRegs[DI_CONFIG_IDX] & DI_CONFIG_CONFIG_MASK);
}
+389
View File
@@ -0,0 +1,389 @@
#include <dolphin.h>
#include <dolphin/base/PPCArch.h>
#include <dolphin/os.h>
#include <macros.h>
#define ALIGNMENT 32
#define InRange(cell, arenaStart, arenaEnd) \
((u32)arenaStart <= (u32)cell) && ((u32)cell < (u32)arenaEnd)
#define HEADERSIZE 32u
#define MINOBJSIZE 64u
struct Cell {
struct Cell* prev;
struct Cell* next;
long size;
};
struct HeapDesc {
long size;
struct Cell* free;
struct Cell* allocated;
};
volatile int __OSCurrHeap = -1;
static struct HeapDesc* HeapArray;
static int NumHeaps;
static void* ArenaStart;
static void* ArenaEnd;
// functions
static struct Cell* DLAddFront(struct Cell* list, struct Cell* cell);
static struct Cell* DLLookup(struct Cell* list, struct Cell* cell);
static struct Cell* DLExtract(struct Cell* list, struct Cell* cell);
static struct Cell* DLInsert(struct Cell* list, struct Cell* cell);
static struct Cell* DLAddFront(struct Cell* list, struct Cell* cell)
{
cell->next = list;
cell->prev = 0;
if (list) {
list->prev = cell;
}
return cell;
}
static struct Cell* DLLookup(struct Cell* list, struct Cell* cell)
{
for (; list; list = list->next) {
if (list == cell) {
return list;
}
}
return NULL;
}
static struct Cell* DLExtract(struct Cell* list, struct Cell* cell)
{
if (cell->next) {
cell->next->prev = cell->prev;
}
if (cell->prev == NULL) {
return cell->next;
}
cell->prev->next = cell->next;
return list;
}
static struct Cell* DLInsert(struct Cell* list, struct Cell* cell)
{
struct Cell* prev;
struct Cell* next;
for (next = list, prev = NULL; next != 0; prev = next, next = next->next) {
if (cell <= next) {
break;
}
}
cell->next = next;
cell->prev = prev;
if (next) {
next->prev = cell;
if ((u8*)cell + cell->size == (u8*)next) {
cell->size += next->size;
next = next->next;
cell->next = next;
if (next) {
next->prev = cell;
}
}
}
if (prev) {
prev->next = cell;
if ((u8*)prev + prev->size == (u8*)cell) {
prev->size += cell->size;
prev->next = next;
if (next) {
next->prev = prev;
}
}
return list;
}
return cell;
}
void* OSAllocFromHeap(int heap, unsigned long size)
{
struct HeapDesc* hd;
struct Cell* cell;
struct Cell* newCell;
long leftoverSize;
long requested;
requested = size;
ASSERTMSGLINE(0x14D, HeapArray,
"OSAllocFromHeap(): heap is not initialized.");
ASSERTMSGLINE(0x14E, (signed long)size > 0,
"OSAllocFromHeap(): invalid size.");
ASSERTMSGLINE(0x14F, heap >= 0 && heap < NumHeaps,
"OSAllocFromHeap(): invalid heap handle.");
ASSERTMSGLINE(0x150, HeapArray[heap].size >= 0,
"OSAllocFromHeap(): invalid heap handle.");
hd = &HeapArray[heap];
size += 0x20;
size = (size + 0x1F) & 0xFFFFFFE0;
for (cell = hd->free; cell != NULL; cell = cell->next) {
if ((signed)size <= (signed)cell->size) {
break;
}
}
if (cell == NULL) {
return NULL;
}
ASSERTMSGLINE(0x168, !((s32)cell & 0x1F),
"OSAllocFromHeap(): heap is broken.");
ASSERTMSGLINE(0x169, cell->hd == NULL,
"OSAllocFromHeap(): heap is broken.");
leftoverSize = cell->size - size;
if (leftoverSize < 0x40U) {
hd->free = DLExtract(hd->free, cell);
} else {
cell->size = size;
newCell = (void*)((u8*)cell + size);
newCell->size = leftoverSize;
newCell->prev = cell->prev;
newCell->next = cell->next;
if (newCell->next != NULL) {
newCell->next->prev = newCell;
}
if (newCell->prev != NULL) {
newCell->prev->next = newCell;
} else {
ASSERTMSGLINE(0x186, hd->free == cell,
"OSAllocFromHeap(): heap is broken.");
hd->free = newCell;
}
}
hd->allocated = DLAddFront(hd->allocated, cell);
return (u8*)cell + 0x20;
}
void OSFreeToHeap(int heap, void* ptr)
{
struct HeapDesc* hd;
struct Cell* cell;
ASSERTMSGLINE(0x23D, HeapArray, "OSFreeToHeap(): heap is not initialized.");
ASSERTMSGLINE(
0x23F, ((u32)ArenaStart + 0x20) <= (u32)ptr && (u32)ptr < (u32)ArenaEnd,
"OSFreeToHeap(): invalid pointer.");
ASSERTMSGLINE(0x240, OFFSET(ptr, ALIGNMENT) == 0,
"OSFreeToHeap(): invalid pointer.");
ASSERTMSGLINE(0x241, HeapArray[heap].size >= 0,
"OSFreeToHeap(): invalid heap handle.");
cell = (void*)((u32)ptr - 0x20);
hd = &HeapArray[heap];
ASSERTMSGLINE(0x246, cell->hd == hd, "OSFreeToHeap(): invalid pointer.");
ASSERTMSGLINE(0x247, DLLookup(hd->allocated, cell),
"OSFreeToHeap(): invalid pointer.");
hd->allocated = DLExtract(hd->allocated, cell);
hd->free = DLInsert(hd->free, cell);
}
void* OSInitAlloc(void* arenaStart, void* arenaEnd, int maxHeaps)
{
unsigned long arraySize;
int i;
struct HeapDesc* hd;
ASSERTMSGLINE(0x283, maxHeaps > 0,
"OSInitAlloc(): invalid number of heaps.");
ASSERTMSGLINE(0x285, (u32)arenaStart < (u32)arenaEnd,
"OSInitAlloc(): invalid range.");
ASSERTMSGLINE(0x288, maxHeaps <= (((u32)arenaEnd - (u32)arenaStart) / 24U),
"OSInitAlloc(): too small range.");
arraySize = maxHeaps * sizeof(struct HeapDesc);
HeapArray = arenaStart;
NumHeaps = maxHeaps;
for (i = 0; i < NumHeaps; i++) {
hd = &HeapArray[i];
hd->size = -1;
hd->free = hd->allocated = 0;
}
__OSCurrHeap = -1;
arenaStart = (void*)((u32)((char*)HeapArray + arraySize));
arenaStart = (void*)(((u32)arenaStart + 0x1F) & 0xFFFFFFE0);
ArenaStart = arenaStart;
ArenaEnd = (void*)((u32)arenaEnd & 0xFFFFFFE0);
ASSERTMSGLINE(0x2A4, ((u32)ArenaEnd - (u32)ArenaStart) >= 0x40U,
"OSInitAlloc(): too small range.");
return arenaStart;
}
int OSCreateHeap(void* start, void* end)
{
int heap;
struct HeapDesc* hd;
struct Cell* cell;
ASSERTMSGLINE(0x2BD, HeapArray, "OSCreateHeap(): heap is not initialized.");
ASSERTMSGLINE(0x2BE, (u32)start < (u32)end,
"OSCreateHeap(): invalid range.");
start = (void*)(((u32)start + 0x1FU) & ~((32) - 1));
end = (void*)(((u32)end) & ~((32) - 1));
ASSERTMSGLINE(0x2C1, (u32)start < (u32)end,
"OSCreateHeap(): invalid range.");
ASSERTMSGLINE(0x2C3,
(u32)ArenaStart <= (u32)start && (u32)end <= (u32)ArenaEnd,
"OSCreateHeap(): invalid range.");
ASSERTMSGLINE(0x2C5, ((u32)end - (u32)start) >= 0x40U,
"OSCreateHeap(): too small range.");
for (heap = 0; heap < NumHeaps; heap++) {
hd = &HeapArray[heap];
if (hd->size < 0) {
hd->size = (u32)end - (u32)start;
cell = start;
cell->prev = 0;
cell->next = 0;
cell->size = hd->size;
hd->free = cell;
hd->allocated = 0;
return heap;
}
}
return -1;
}
void OSDestroyHeap(int heap)
{
struct HeapDesc* hd;
long size;
ASSERTMSGLINE(0x30A, HeapArray,
"OSDestroyHeap(): heap is not initialized.");
ASSERTMSGLINE(0x30B, (heap >= 0) && (heap < NumHeaps),
"OSDestroyHeap(): invalid heap handle.");
ASSERTMSGLINE(0x30C, HeapArray[heap].size >= 0,
"OSDestroyHeap(): invalid heap handle.");
hd = &HeapArray[heap];
hd->size = -1;
}
// custom macro for OSCheckHeap
#define ASSERTREPORT(line, cond) \
if (!(cond)) { \
OSReport("OSCheckHeap: Failed " #cond " in %d", line); \
return -1; \
}
long OSCheckHeap(int heap)
{
struct HeapDesc* hd;
struct Cell* cell;
long total = 0;
long free = 0;
ASSERTREPORT(0x37D, HeapArray);
ASSERTREPORT(0x37E, 0 <= heap && heap < NumHeaps);
hd = &HeapArray[heap];
ASSERTREPORT(0x381, 0 <= hd->size);
ASSERTREPORT(0x383, hd->allocated == NULL || hd->allocated->prev == NULL);
for (cell = hd->allocated; cell; cell = cell->next) {
ASSERTREPORT(0x386, InRange(cell, ArenaStart, ArenaEnd));
ASSERTREPORT(0x387, OFFSET(cell, ALIGNMENT) == 0);
ASSERTREPORT(0x388, cell->next == NULL || cell->next->prev == cell);
ASSERTREPORT(0x389, MINOBJSIZE <= cell->size);
ASSERTREPORT(0x38A, OFFSET(cell->size, ALIGNMENT) == 0);
total += cell->size;
ASSERTREPORT(0x38D, 0 < total && total <= hd->size);
}
ASSERTREPORT(0x395, hd->free == NULL || hd->free->prev == NULL);
for (cell = hd->free; cell; cell = cell->next) {
ASSERTREPORT(0x398, InRange(cell, ArenaStart, ArenaEnd));
ASSERTREPORT(0x399, OFFSET(cell, ALIGNMENT) == 0);
ASSERTREPORT(0x39A, cell->next == NULL || cell->next->prev == cell);
ASSERTREPORT(0x39B, MINOBJSIZE <= cell->size);
ASSERTREPORT(0x39C, OFFSET(cell->size, ALIGNMENT) == 0);
// NOTE: macro arg is stringified so format mustn't touch it
// clang-format off
ASSERTREPORT(0x39D, cell->next == NULL
|| (char*) cell + cell->size < (char*) cell->next);
// clang-format on
total += cell->size;
free = (cell->size + free);
free -= HEADERSIZE;
ASSERTREPORT(0x3A1, 0 < total && total <= hd->size);
}
ASSERTREPORT(0x3A8, total == hd->size);
return free;
}
unsigned long OSReferentSize(void* ptr)
{
struct Cell* cell;
ASSERTMSGLINE(0x3BB, HeapArray,
"OSReferentSize(): heap is not initialized.");
ASSERTMSGLINE(0x3BD, InRange(ptr, ArenaStart + HEADERSIZE, ArenaEnd),
"OSReferentSize(): invalid pointer.");
ASSERTMSGLINE(0x3BE, !OFFSET(ptr, 32),
"OSReferentSize(): invalid pointer.");
cell = (void*)((u32)ptr - HEADERSIZE);
ASSERTMSGLINE(0x3C2, cell->hd, "OSReferentSize(): invalid pointer.");
ASSERTMSGLINE(0x3C4, !(((u32)cell->hd - (u32)HeapArray) % 24),
"OSReferentSize(): invalid pointer.");
ASSERTMSGLINE(
0x3C6,
((u32)HeapArray <= (u32)cell->hd)
&& ((u32)cell->hd < (u32)((u32)HeapArray + (NumHeaps * 0x18))),
"OSReferentSize(): invalid pointer.");
ASSERTMSGLINE(0x3C7, cell->hd->size >= 0,
"OSReferentSize(): invalid pointer.");
ASSERTMSGLINE(0x3C9, DLLookup(cell->hd->allocated, cell),
"OSReferentSize(): invalid pointer.");
return (long)((u32)cell->size - HEADERSIZE);
}
void OSDumpHeap(int heap)
{
struct HeapDesc* hd;
struct Cell* cell;
OSReport("\nOSDumpHeap(%d):\n", heap);
ASSERTMSGLINE(0x3DE, HeapArray, "OSDumpHeap(): heap is not initialized.");
ASSERTMSGLINE(0x3DF, (heap >= 0) && (heap < NumHeaps),
"OSDumpHeap(): invalid heap handle.");
hd = &HeapArray[heap];
if (hd->size < 0) {
OSReport("--------Inactive\n");
return;
}
ASSERTMSGLINE(0x3E8, OSCheckHeap(heap) >= 0,
"OSDumpHeap(): heap is broken.");
OSReport("addr size end prev next\n");
OSReport("--------Allocated\n");
ASSERTMSGLINE(0x3F5, hd->allocated == NULL || hd->allocated->prev == NULL,
"OSDumpHeap(): heap is broken.");
for (cell = hd->allocated; cell; cell = cell->next) {
OSReport("%x %d %x %x %x\n", cell, cell->size,
(char*)cell + cell->size, cell->prev, cell->next);
}
OSReport("--------Free\n");
for (cell = hd->free; cell; cell = cell->next) {
OSReport("%x %d %x %x %x\n", cell, cell->size,
(char*)cell + cell->size, cell->prev, cell->next);
}
}
+505
View File
@@ -0,0 +1,505 @@
#include <dolphin.h>
#include <dolphin/os.h>
#include <macros.h>
#include "os/__os.h"
static OSFontHeader* FontData; // type unsure
static u8* SheetImage; // type unsure
static u8* WidthTable; // type unsure
static int CharsInSheet; // type unsure
static u16 HankakuToCode[] = {
0x20C, 0x20D, 0x20E, 0x20F, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215, 0x216,
0x217, 0x218, 0x219, 0x21A, 0x21B, 0x21C, 0x21D, 0x21E, 0x21F, 0x220, 0x221,
0x222, 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22A, 0x22B, 0x22C,
0x22D, 0x22E, 0x22F, 0x230, 0x231, 0x232, 0x233, 0x234, 0x235, 0x236, 0x237,
0x238, 0x239, 0x23A, 0x23B, 0x23C, 0x23D, 0x23E, 0x23F, 0x240, 0x241, 0x242,
0x243, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24A, 0x24B, 0x24C, 0x24D,
0x24E, 0x24F, 0x250, 0x251, 0x252, 0x253, 0x254, 0x255, 0x256, 0x257, 0x258,
0x259, 0x25A, 0x25B, 0x25C, 0x25D, 0x25E, 0x25F, 0x260, 0x261, 0x262, 0x263,
0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26A, 0x20C, 0x20C, 0x20C, 0x20C,
0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C,
0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C,
0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x26B, 0x26C, 0x26D,
0x26E, 0x26F, 0x270, 0x271, 0x272, 0x273, 0x274, 0x275, 0x276, 0x277, 0x278,
0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, 0x282, 0x283,
0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E,
0x28F, 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299,
0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, 0x2A1, 0x2A2, 0x2A3, 0x2A4,
0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9,
};
static u16 Zenkaku2Code[] = {
0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00A,
0x00B, 0x00C, 0x00D, 0x00E, 0x00F, 0x010, 0x011, 0x012, 0x013, 0x014, 0x015,
0x016, 0x017, 0x018, 0x019, 0x01A, 0x01B, 0x01C, 0x01D, 0x01E, 0x01F, 0x020,
0x021, 0x022, 0x023, 0x024, 0x025, 0x026, 0x027, 0x028, 0x029, 0x02A, 0x02B,
0x02C, 0x02D, 0x02E, 0x02F, 0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036,
0x037, 0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x03F, 0x040, 0x041,
0x042, 0x043, 0x044, 0x045, 0x046, 0x047, 0x048, 0x049, 0x04A, 0x04B, 0x04C,
0x04D, 0x04E, 0x04F, 0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057,
0x058, 0x059, 0x05A, 0x05B, 0x05C, 0x05D, 0x05E, 0x05F, 0x060, 0x061, 0x062,
0x063, 0x064, 0x065, 0x066, 0x067, 0x068, 0x069, 0x06A, 0x06B, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x06C, 0x06D,
0x06E, 0x06F, 0x070, 0x071, 0x072, 0x073, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07A, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x07B,
0x07C, 0x07D, 0x07E, 0x07F, 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086,
0x087, 0x088, 0x089, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x08A,
0x08B, 0x08C, 0x08D, 0x08E, 0x08F, 0x090, 0x091, 0x000, 0x000, 0x000, 0x000,
0x092, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x093, 0x094, 0x095, 0x096, 0x097, 0x098,
0x099, 0x09A, 0x09B, 0x09C, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x09D, 0x09E, 0x09F, 0x0A0, 0x0A1, 0x0A2, 0x0A3, 0x0A4, 0x0A5, 0x0A6, 0x0A7,
0x0A8, 0x0A9, 0x0AA, 0x0AB, 0x0AC, 0x0AD, 0x0AE, 0x0AF, 0x0B0, 0x0B1, 0x0B2,
0x0B3, 0x0B4, 0x0B5, 0x0B6, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x0B7,
0x0B8, 0x0B9, 0x0BA, 0x0BB, 0x0BC, 0x0BD, 0x0BE, 0x0BF, 0x0C0, 0x0C1, 0x0C2,
0x0C3, 0x0C4, 0x0C5, 0x0C6, 0x0C7, 0x0C8, 0x0C9, 0x0CA, 0x0CB, 0x0CC, 0x0CD,
0x0CE, 0x0CF, 0x0D0, 0x000, 0x000, 0x000, 0x000, 0x0D1, 0x0D2, 0x0D3, 0x0D4,
0x0D5, 0x0D6, 0x0D7, 0x0D8, 0x0D9, 0x0DA, 0x0DB, 0x0DC, 0x0DD, 0x0DE, 0x0DF,
0x0E0, 0x0E1, 0x0E2, 0x0E3, 0x0E4, 0x0E5, 0x0E6, 0x0E7, 0x0E8, 0x0E9, 0x0EA,
0x0EB, 0x0EC, 0x0ED, 0x0EE, 0x0EF, 0x0F0, 0x0F1, 0x0F2, 0x0F3, 0x0F4, 0x0F5,
0x0F6, 0x0F7, 0x0F8, 0x0F9, 0x0FA, 0x0FB, 0x0FC, 0x0FD, 0x0FE, 0x0FF, 0x100,
0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, 0x10B,
0x10C, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116,
0x117, 0x118, 0x119, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121,
0x122, 0x123, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x124, 0x125, 0x126, 0x127, 0x128, 0x129, 0x12A, 0x12B, 0x12C,
0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x132, 0x133, 0x134, 0x135, 0x136, 0x137,
0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141, 0x142,
0x143, 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14A, 0x14B, 0x14C, 0x14D,
0x14E, 0x14F, 0x150, 0x151, 0x152, 0x153, 0x154, 0x155, 0x156, 0x157, 0x158,
0x159, 0x15A, 0x15B, 0x15C, 0x15D, 0x15E, 0x15F, 0x160, 0x161, 0x162, 0x163,
0x164, 0x165, 0x166, 0x167, 0x168, 0x169, 0x16A, 0x16B, 0x16C, 0x16D, 0x16E,
0x16F, 0x170, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0x177, 0x178, 0x179,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x17A, 0x17B, 0x17C,
0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0x184, 0x185, 0x186, 0x187,
0x188, 0x189, 0x18A, 0x18B, 0x18C, 0x18D, 0x18E, 0x18F, 0x190, 0x191, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x192, 0x193, 0x194, 0x195,
0x196, 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19D, 0x19E, 0x19F, 0x1A0,
0x1A1, 0x1A2, 0x1A3, 0x1A4, 0x1A5, 0x1A6, 0x1A7, 0x1A8, 0x1A9, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1AE, 0x1AF, 0x1B0, 0x1B1,
0x1B2, 0x1B3, 0x1B4, 0x1B5, 0x1B6, 0x1B7, 0x1B8, 0x1B9, 0x1BA, 0x1BB, 0x1BC,
0x1BD, 0x1BE, 0x1BF, 0x1C0, 0x1C1, 0x1C2, 0x1C3, 0x1C4, 0x1C5, 0x1C6, 0x1C7,
0x1C8, 0x1C9, 0x1CA, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1CB, 0x1CC, 0x1CD, 0x1CE,
0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1D5, 0x1D6, 0x1D7, 0x1D8, 0x1D9,
0x1DA, 0x1DB, 0x1DC, 0x1DD, 0x1DE, 0x1DF, 0x1E0, 0x1E1, 0x1E2, 0x1E3, 0x1E4,
0x1E5, 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1EA, 0x1EB, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1EC, 0x1ED,
0x1EE, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, 0x1F5, 0x1F6, 0x1F7, 0x1F8,
0x1F9, 0x1FA, 0x1FB, 0x1FC, 0x1FD, 0x1FE, 0x1FF, 0x200, 0x201, 0x202, 0x203,
0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20A, 0x20B, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x20C, 0x20D, 0x20E, 0x20F, 0x210, 0x211, 0x212, 0x213,
0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21A, 0x21B, 0x21C, 0x21D, 0x21E,
0x21F, 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229,
0x22A, 0x22B, 0x22C, 0x22D, 0x22E, 0x22F, 0x230, 0x231, 0x232, 0x233, 0x234,
0x235, 0x236, 0x237, 0x238, 0x239, 0x23A, 0x23B, 0x23C, 0x23D, 0x23E, 0x23F,
0x240, 0x241, 0x242, 0x243, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24A,
0x24B, 0x24C, 0x24D, 0x24E, 0x24F, 0x250, 0x251, 0x252, 0x253, 0x254, 0x255,
0x256, 0x257, 0x258, 0x259, 0x25A, 0x25B, 0x25C, 0x25D, 0x25E, 0x25F, 0x260,
0x261, 0x262, 0x263, 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26A, 0x26B,
0x26C, 0x26D, 0x26E, 0x26F, 0x270, 0x271, 0x272, 0x273, 0x274, 0x275, 0x276,
0x277, 0x278, 0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281,
0x282, 0x283, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C,
0x28D, 0x28E, 0x28F, 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297,
0x298, 0x299, 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, 0x2A1, 0x2A2,
0x2A3, 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, 0x2AA, 0x2AB, 0x2AC, 0x2AD,
0x2AE, 0x2AF, 0x2B0, 0x2B1, 0x2B2, 0x2B3, 0x2B4, 0x2B5, 0x2B6, 0x2B7, 0x2B8,
0x2B9, 0x2BA, 0x2BB, 0x2BC, 0x2BD, 0x2BE, 0x2BF, 0x2C0, 0x2C1, 0x2C2, 0x2C3,
0x2C4, 0x2C5, 0x2C6, 0x2C7, 0x2C8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x2C9, 0x2CA, 0x2CB, 0x2CC, 0x2CD,
0x2CE, 0x2CF, 0x2D0, 0x2D1, 0x2D2, 0x2D3, 0x2D4, 0x2D5, 0x2D6, 0x2D7, 0x2D8,
0x2D9, 0x2DA, 0x2DB, 0x2DC, 0x2DD, 0x2DE, 0x2DF, 0x2E0, 0x2E1, 0x2E2, 0x2E3,
0x2E4, 0x2E5, 0x2E6, 0x000, 0x2E7, 0x2E8, 0x2E9, 0x2EA, 0x2EB, 0x2EC, 0x2ED,
0x2EE, 0x2EF, 0x2F0, 0x2F1, 0x2F2, 0x2F3, 0x2F4, 0x2F5, 0x2F6, 0x2F7, 0x2F8,
0x2F9, 0x2FA, 0x2FB, 0x2FC, 0x2FD, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x2FE, 0x2FF, 0x300, 0x301, 0x302, 0x303, 0x304, 0x305, 0x306,
0x307, 0x308, 0x309, 0x30A, 0x30B, 0x30C, 0x30D, 0x30E, 0x30F, 0x310, 0x311,
0x312, 0x313, 0x314, 0x315, 0x316, 0x317, 0x318, 0x319, 0x31A, 0x31B, 0x000
};
static int GetFontCode(unsigned short code)
{
if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) {
if (code >= 0x20 && code <= 0xDF) {
return HankakuToCode[code - 0x20];
}
if (code > 0x889E) {
int i = ((code >> 8) - 0x88) * 188;
int j = (code & 0xFF) - 0x40;
if (j >= 0x40) {
j--;
}
return (i + j + 0x2BE);
}
if (code < 0x879E) {
int i = ((code >> 8) - 0x81) * 188;
int j = (code & 0xFF) - 0x40;
if (j >= 0x40) {
j--;
}
return Zenkaku2Code[i + j];
}
} else if (code > 0x20 && code <= 0xFF) {
return code - 0x20;
} else {
return 0;
}
return 0;
}
static void Decode(unsigned char* s, unsigned char* d)
{
int i;
int j;
int k;
int p;
int q;
int r7; // huh? DWARF info says these 2 variables might be register names
// and not actual names.
int r25;
int cnt;
int os;
unsigned int flag;
unsigned int code;
os = *(int*)(s + 0x4);
r7 = *(int*)(s + 0x8);
r25 = *(int*)(s + 0xC);
q = 0;
flag = 0;
p = 16;
do {
// Get next mask
if (flag == 0) {
code = *(u32*)(s + p);
p += sizeof(u32);
flag = sizeof(u32) * 8;
}
// Non-linked chunk
if (code & 0x80000000) {
d[q++] = s[r25++];
}
// Linked chunk
else {
// Read offset from link table
j = s[r7] << 8 | s[r7 + 1];
r7 += sizeof(u16);
// Apply offset
k = q - (j & 0x0FFF);
cnt = j >> 12;
if (cnt == 0) {
cnt = s[r25++] + 0x12;
} else {
cnt += 2;
}
// Copy chunk
for (i = 0; i < cnt; i++, q++, k++) {
d[q] = d[k - 1];
}
}
// Prepare next mask bit
code <<= 1;
flag--;
} while (q < os);
}
static u32 GetFontSize(u8* buf)
{
if (buf[0] == 'Y' && buf[1] == 'a' && buf[2] == 'y') {
return *(u32*)(buf + 0x4);
}
return 0;
}
unsigned short OSGetFontEncode(void)
{
static u16 fontEncode = 0xFFFF;
if (fontEncode <= 1) {
return fontEncode;
}
switch (*(int*)OSPhysicalToCached(0xCC)) {
case VI_NTSC:
fontEncode = (__VIRegs[VI_DTV_STAT] & 2) ? 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;
}
return fontEncode;
}
static void ReadROM(void* buf, int length, int offset)
{
int len;
while (length > 0) {
len = (length <= 0x100) ? length : 0x100;
length -= len;
while (!__OSReadROM(buf, len, offset)) {
;
}
offset += len;
(u8*)buf += len;
}
}
static u32 ReadFont(void* img)
{
if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) {
ReadROM(img, OS_FONT_ROM_SIZE_SJIS, 0x1AFF00);
} else {
ReadROM(img, OS_FONT_ROM_SIZE_ANSI, 0x1FCF00);
}
return GetFontSize(img);
}
u32 OSLoadFont(OSFontHeader* fontData, void* temp)
{
u32 size;
SheetImage = NULL;
size = ReadFont(temp);
if (size) {
Decode(temp, (void*)fontData);
FontData = fontData;
WidthTable = (u8*)FontData + FontData->widthTable;
CharsInSheet = FontData->sheetColumn * FontData->sheetRow;
}
return size;
}
char* OSGetFontTexel(char* string, void* image, long pos, long stride,
long* width)
{
unsigned short code;
unsigned char* src;
unsigned char* dst;
int fontCode;
int sheet;
int numChars;
int row;
int column;
int x;
int y;
int offsetSrc;
int offsetDst;
unsigned char* colorIndex;
unsigned char* imageSrc;
ASSERTLINE(0x1F6, FontData && !SheetImage);
code = *string;
if (code == '\0') {
return string;
}
string++;
if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) {
if ((((code >= 0x80) && (code <= 0x9F))
|| ((code >= 0xE0) && (code <= 0xFF)))
&& ((s8)*string != 0U)) {
code = (code << 8) | (*string++); // Shift-JIS encoded byte
}
}
colorIndex = &FontData->c0;
ASSERTLINE(0x209, FontData->sheetFormat == GX_TF_I4);
fontCode = GetFontCode(code);
sheet = fontCode / CharsInSheet;
numChars = fontCode - (sheet * CharsInSheet);
row = numChars / FontData->sheetColumn;
column = (numChars - (row * FontData->sheetColumn));
row *= FontData->cellHeight;
column *= FontData->cellWidth;
imageSrc = (u8*)FontData + FontData->sheetImage;
imageSrc += (sheet * FontData->sheetSize) / 2;
for (y = 0; y < FontData->cellHeight; y++) {
for (x = 0; x < FontData->cellWidth; x++) {
src = imageSrc
+ (((FontData->sheetWidth / 8) * 32) / 2) * ((row + y) / 8);
src += ((column + x) / 8) * 16;
src += ((row + y) % 8) * 2;
src += ((column + x) % 8) / 4;
offsetSrc = (column + x) % 4;
dst = (u8*)image + ((y / 8) * (((stride * 4) / 8) * 32));
dst += (((pos + x) / 8) * 32);
dst += ((y % 8) * 4);
dst += ((pos + x) % 8) / 2;
offsetDst = (pos + x) % 2;
*dst |= colorIndex[*src >> (6 - (offsetSrc * 2)) & 3]
& ((offsetDst != 0) ? 0x0F : 0xF0);
}
}
*width = WidthTable[fontCode];
return string;
}
static void ExpandFontSheet(u8* src, u8* dst)
{
int i;
u8* colorIndex = &FontData->c0;
if (FontData->sheetFormat == GX_TF_I4) {
for (i = (s32)(FontData->sheetFullSize) / 2 - 1; i >= 0; i--) {
dst[i * 2 + 0] = colorIndex[src[i] >> 6 & 3] & 0xF0
| colorIndex[src[i] >> 4 & 3] & 0x0F;
dst[i * 2 + 1] = colorIndex[src[i] >> 2 & 3] & 0xF0
| colorIndex[src[i] >> 0 & 3] & 0x0F;
}
} else if (FontData->sheetFormat == GX_TF_IA4) {
for (i = (s32)(FontData->sheetFullSize) / 4 - 1; i >= 0; i--) {
dst[i * 4 + 0] = colorIndex[src[i] >> 6 & 3];
dst[i * 4 + 1] = colorIndex[src[i] >> 4 & 3];
dst[i * 4 + 2] = colorIndex[src[i] >> 2 & 3];
dst[i * 4 + 3] = colorIndex[src[i] >> 0 & 3];
}
}
DCStoreRange(dst, FontData->sheetFullSize);
}
int OSInitFont(OSFontHeader* fontData)
{
unsigned long size;
void* temp;
if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) {
temp = (void*)((u8*)fontData + 0xD3F00);
} else {
temp = (void*)((u8*)fontData + 0x1D120);
}
temp = ((void*)(((u32)(temp)) & ~((32) - 1)));
size = OSLoadFont(fontData, temp);
if (size == 0) {
return 0;
}
SheetImage = (u8*)FontData + FontData->sheetImage;
SheetImage = (void*)((s32)(SheetImage + 0x1F) & 0xFFFFFFE0);
ExpandFontSheet((u8*)FontData + FontData->sheetImage, SheetImage);
return 1;
}
char* OSGetFontTexture(char* string, void** image, long* x, long* y,
long* width)
{
unsigned short code;
int fontCode;
int sheet;
int numChars;
int row;
int column;
ASSERTLINE(0x291, SheetImage);
ASSERTLINE(0x292, WidthTable);
code = *string;
if (code == 0) {
*image = NULL;
return string;
}
string++;
if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) {
if ((((code >= 0x80) && (code <= 0x9F))
|| ((code >= 0xE0) && (code <= 0xFF)))
&& ((s8)*string != 0U)) {
code = (code << 8) | (*string++); // Shift-JIS encoded byte
}
}
fontCode = GetFontCode(code);
sheet = fontCode / CharsInSheet;
((u32*)image)[0] = (u32)SheetImage + (FontData->sheetSize * sheet);
numChars = fontCode - (sheet * CharsInSheet);
row = numChars / FontData->sheetColumn;
column = (numChars - (row * FontData->sheetColumn));
*x = column * FontData->cellWidth;
*y = row * FontData->cellHeight;
if (width) {
*width = WidthTable[fontCode];
}
return string;
}
char* OSGetFontWidth(char* string, s32* width)
{
unsigned short code;
ASSERTLINE(0x2C2, WidthTable);
code = *string;
if (code == 0) {
return string;
}
string++;
if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) {
if ((((code >= 0x80) && (code <= 0x9F))
|| ((code >= 0xE0) && (code <= 0xFF)))
&& ((s8)*string != 0U)) {
code = (code << 8) | (*string++); // Shift-JIS encoded byte
}
}
*width = WidthTable[GetFontCode(code)];
return string;
}
+417 -36
View File
@@ -1,43 +1,424 @@
#include "dolphin/os/OSInterrupt.h"
#include <dolphin.h>
#include <dolphin/os.h>
#include <macros.h>
#include <string.h>
asm BOOL OSDisableInterrupts(void) {
// clang-format off
nofralloc
#include "../src/static/dolphin/os/__os.h"
entry __RAS_OSDisableInterrupts_begin
mfmsr r3
rlwinm r4, r3, 0, 17, 15
mtmsr r4
entry __RAS_OSDisableInterrupts_end
rlwinm r3, r3, 17, 31, 31
blr
// clang-format on
static asm void ExternalInterruptHandler(register __OSException exception,
register OSContext* context);
extern void __RAS_OSDisableInterrupts_begin(void);
extern void __RAS_OSDisableInterrupts_end(void);
static __OSInterruptHandler* InterruptHandlerTable;
volatile OSTime __OSLastInterruptTime;
volatile __OSInterrupt __OSLastInterrupt;
volatile u32 __OSLastInterruptSrr0;
static OSInterruptMask InterruptPrioTable[] = {
OS_INTERRUPTMASK_PI_ERROR,
OS_INTERRUPTMASK_PI_DEBUG,
OS_INTERRUPTMASK_MEM,
OS_INTERRUPTMASK_PI_RSW,
OS_INTERRUPTMASK_PI_VI,
OS_INTERRUPTMASK_PI_PE,
OS_INTERRUPTMASK_PI_HSP,
OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP | OS_INTERRUPTMASK_AI
| OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI_SI
| OS_INTERRUPTMASK_PI_DI,
OS_INTERRUPTMASK_DSP_AI,
OS_INTERRUPTMASK_PI_CP,
0xFFFFFFFF,
};
asm BOOL OSDisableInterrupts(void)
{
#ifdef __MWERKS__ // clang-format off
nofralloc
entry __RAS_OSDisableInterrupts_begin
mfmsr r3
rlwinm r4, r3, 0, 17, 15
mtmsr r4
rlwinm r3, r3, 17, 31, 31
entry __RAS_OSDisableInterrupts_end
blr
#endif // clang-format on
}
asm BOOL OSEnableInterrupts(void) {
// clang-format off
nofralloc
/* 8007AC38 7C6000A6 */ mfmsr r3
/* 8007AC3C 60648000 */ ori r4, r3, 0x8000
/* 8007AC40 7C800124 */ mtmsr r4
/* 8007AC44 54638FFE */ rlwinm r3, r3, 0x11, 0x1f, 0x1f
/* 8007AC48 4E800020 */ blr
// clang-format on
asm BOOL OSEnableInterrupts(void)
{
#ifdef __MWERKS__ // clang-format off
nofralloc
mfmsr r3
ori r4, r3, 0x8000
mtmsr r4
rlwinm r3, r3, 17, 31, 31
blr
#endif // clang-format on
}
asm BOOL OSRestoreInterrupts(register BOOL level) {
// clang-format off
nofralloc
/* 8007AC4C 2C030000 */ cmpwi level, 0x0
/* 8007AC50 7C8000A6 */ mfmsr r4
/* 8007AC54 4182000C */ beq- lbl_8007ac60
/* 8007AC58 60858000 */ ori r5, r4, 0x8000
/* 8007AC5C 48000008 */ b lbl_8007ac64
lbl_8007ac60:
/* 8007AC60 5485045E */ rlwinm r5, r4, 0, 0x11, 0xf
lbl_8007ac64:
/* 8007AC64 7CA00124 */ mtmsr r5
/* 8007AC68 54838FFE */ rlwinm r3, r4, 0x11, 0x1f, 0x1f
/* 8007AC6C 4E800020 */ blr
// clang-format on
}
#ifdef __MWERKS__ // clang-format off
nofralloc
cmpwi level, 0
mfmsr r4
beq _disable
ori r5, r4, 0x8000
b _restore
_disable:
rlwinm r5, r4, 0, 17, 15
_restore:
mtmsr r5
rlwinm r3, r4, 17, 31, 31
blr
#endif // clang-format on
}
__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt,
__OSInterruptHandler handler)
{
__OSInterruptHandler oldHandler;
oldHandler = InterruptHandlerTable[interrupt];
InterruptHandlerTable[interrupt] = handler;
return oldHandler;
}
__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt)
{
return InterruptHandlerTable[interrupt];
}
void __OSInterruptInit(void)
{
InterruptHandlerTable = (void*)OSPhysicalToCached(0x3040);
memset(InterruptHandlerTable, 0,
__OS_INTERRUPT_MAX * 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, ExternalInterruptHandler);
}
static u32 SetInterruptMask(OSInterruptMask mask, OSInterruptMask current)
{
u32 reg;
switch (__cntlzw(mask)) {
case __OS_INTERRUPT_MEM_0:
case __OS_INTERRUPT_MEM_1:
case __OS_INTERRUPT_MEM_2:
case __OS_INTERRUPT_MEM_3:
case __OS_INTERRUPT_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_INTERRUPT_DSP_AI:
case __OS_INTERRUPT_DSP_ARAM:
case __OS_INTERRUPT_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_INTERRUPT_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_INTERRUPT_EXI_0_EXI:
case __OS_INTERRUPT_EXI_0_TC:
case __OS_INTERRUPT_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_INTERRUPT_EXI_1_EXI:
case __OS_INTERRUPT_EXI_1_TC:
case __OS_INTERRUPT_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_INTERRUPT_EXI_2_EXI:
case __OS_INTERRUPT_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_INTERRUPT_PI_CP:
case __OS_INTERRUPT_PI_SI:
case __OS_INTERRUPT_PI_DI:
case __OS_INTERRUPT_PI_RSW:
case __OS_INTERRUPT_PI_ERROR:
case __OS_INTERRUPT_PI_VI:
case __OS_INTERRUPT_PI_DEBUG:
case __OS_INTERRUPT_PI_PE_TOKEN:
case __OS_INTERRUPT_PI_PE_FINISH:
case __OS_INTERRUPT_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;
}
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 (interrupt > __OS_INTERRUPT_MEM_ADDRESS) {
__OSLastInterrupt = interrupt;
__OSLastInterruptTime = OSGetTime();
__OSLastInterruptSrr0 = context->srr0;
}
OSDisableScheduler();
handler(interrupt, context);
OSEnableScheduler();
__OSReschedule();
OSLoadContext(context);
}
}
OSLoadContext(context);
}
static asm void ExternalInterruptHandler(register __OSException exception,
register OSContext* context)
{
#pragma unused(exception)
#ifdef __MWERKS__ // clang-format off
nofralloc
OS_EXCEPTION_SAVE_GPRS(context)
stwu r1, -0x8(r1)
b __OSDispatchInterrupt
#endif // clang-format on
}
+386
View File
@@ -0,0 +1,386 @@
#include <dolphin.h>
#include <dolphin/os.h>
#include <dolphin/os/OSLink.h>
#include "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 ENQUEUE_INFO(queue, info, link) \
do { \
OSModuleInfo* __prev; \
\
__prev = (queue)->tail; \
if (__prev == NULL) \
(queue)->head = (info); \
else \
__prev->link.next = (info); \
(info)->link.prev = __prev; \
(info)->link.next = NULL; \
(queue)->tail = (info); \
} while (0)
#define DEQUEUE_INFO(info, queue, link) \
do { \
OSModuleInfo* __next; \
OSModuleInfo* __prev; \
\
__next = (info)->link.next; \
__prev = (info)->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 AT_ADDRESS(OS_BASE_CACHED | 0x30C8);
#pragma dont_inline on
__declspec(weak) void OSNotifyLink(void) {}
__declspec(weak) void OSNotifyUnlink() {}
#pragma dont_inline reset
void OSSetStringTable(const void* string_table) {
__OSStringTable = string_table;
}
static BOOL Relocate(OSModuleHeader* newModule, OSModuleHeader* module) {
u32 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_REL24:
x = offset + rel->addend - (u32)p;
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
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;
}
BOOL OSLink(OSModuleInfo* newModule, void* bss) {
u32 i;
OSSectionInfo* si;
OSModuleHeader* moduleHeader;
OSModuleInfo* moduleInfo;
OSImportInfo* imp;
moduleHeader = (OSModuleHeader*)newModule;
if (newModule->version > 2 || (newModule->version >= 2 &&
((moduleHeader->align && (u32)newModule % moduleHeader->align != 0) ||
(moduleHeader->bssAlign && (u32)bss % moduleHeader->bssAlign != 0))))
{
return FALSE;
}
ENQUEUE_INFO(&__OSModuleInfoList, newModule, link);
memset(bss, 0, moduleHeader->bssSize);
newModule->sectionInfoOffset += (u32)moduleHeader;
moduleHeader->relOffset += (u32)moduleHeader;
moduleHeader->impOffset += (u32)moduleHeader;
for (i = 0; i < newModule->numSections; i++) {
si = &OSGetSectionInfo(newModule)[i];
if (si->offset != 0) {
si->offset += (u32)moduleHeader;
} else if (si->size != 0) {
si->offset = (u32)bss;
bss = (void*)((u32)bss + si->size);
}
}
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);
}
}
OSNotifyLink();
return TRUE;
}
static BOOL Undo(OSModuleHeader* newModule, OSModuleHeader* module) {
u32 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_REL24:
if (module->unresolvedSection != SHN_UNDEF) {
x = (u32)module->unresolved - (u32)p;
}
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
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;
moduleHeader = (OSModuleHeader*)oldModule;
DEQUEUE_INFO(oldModule, &__OSModuleInfoList, link);
for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) {
Undo(moduleHeader, (OSModuleHeader*)moduleInfo);
}
OSNotifyUnlink();
return TRUE;
}
void __OSModuleInit(void) {
__OSModuleList.tail = NULL;
__OSModuleList.head = NULL;
__OSStringTable = NULL;
}
+189 -2
View File
@@ -1,11 +1,17 @@
#include <dolphin/os.h>
#include "dolphin/os/OSMemory.h"
#include "dolphin/os/OSError.h"
#include "dolphin/os/OSInterrupt.h"
#include "dolphin/hw_regs.h"
#include "dolphin/os/OSReset.h"
#define TRUNC(n, a) (((u32)(n)) & ~((a)-1))
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
u32 OSGetConsoleSimulatedMemSize(void){
return(SIM_MEM);
}
static BOOL OnReset(BOOL final){
if (final) {
__MEMRegs[8] = 0xff;
@@ -13,6 +19,7 @@ static BOOL OnReset(BOOL final){
}
return TRUE;
}
static void MEMIntrruptHandler(__OSInterrupt interrupt, OSContext* ctx){
u32 cause = __MEMRegs[0xf];
u32 addr = (((u32) __MEMRegs[0x12] & 0x3ff) << 16) | __MEMRegs[0x11];
@@ -22,5 +29,185 @@ static void MEMIntrruptHandler(__OSInterrupt interrupt, OSContext* ctx){
__OSErrorTable[OS_ERROR_PROTECTION](OS_ERROR_PROTECTION, ctx, cause, addr);
return;
}
__OSUnhandledException(OS_ERROR_PROTECTION, ctx, cause, addr);
}
__OSUnhandledException(OS_ERROR_PROTECTION, ctx, cause, addr);
}
#define OS_PROTECT_CONTROL_NONE 0x00
#define OS_PROTECT_CONTROL_READ 0x01
#define OS_PROTECT_CONTROL_WRITE 0x02
#define OS_PROTECT_CONTROL_RDWR \
(OS_PROTECT_CONTROL_READ | OS_PROTECT_CONTROL_WRITE)
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_INTERRUPT_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_INTERRUPT_MEM_0 + chan));
}
OSRestoreInterrupts(enabled);
}
static asm void Config24MB(void)
{
#ifdef __MWERKS__ // 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
#endif // clang-format on
}
static asm void Config48MB(void)
{
#ifdef __MWERKS__ // 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
#endif // clang-format on
}
static asm void RealMode(register u32 config)
{
#ifdef __MWERKS__ // clang-format off
nofralloc
clrlwi config, config, 2
mtspr 0x1a, config
mfmsr config
rlwinm config, config, 0, 0x1c, 0x19
mtspr 0x1b, config
rfi
#endif // clang-format on
}
static OSResetFunctionInfo ResetFunctionInfo = {
OnReset,
0x7F,
};
u32 OSGetPhysicalMemSize() { return __OSPhysicalMemSize; }
void __OSInitMemoryProtection()
{
char padding[0x28]; // TODO: wtf is this?
u32 simulatedSize;
BOOL enabled;
simulatedSize = OSGetConsoleSimulatedMemSize();
enabled = OSDisableInterrupts();
if (simulatedSize <= 0x1800000) {
RealMode((u32)&Config24MB);
} else if (simulatedSize <= 0x3000000) {
RealMode((u32)&Config48MB);
}
__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_INTERRUPT_MEM_0, MEMIntrruptHandler);
__OSSetInterruptHandler(__OS_INTERRUPT_MEM_1, MEMIntrruptHandler);
__OSSetInterruptHandler(__OS_INTERRUPT_MEM_2, MEMIntrruptHandler);
__OSSetInterruptHandler(__OS_INTERRUPT_MEM_3, MEMIntrruptHandler);
__OSSetInterruptHandler(__OS_INTERRUPT_MEM_ADDRESS, MEMIntrruptHandler);
OSRegisterResetFunction(&ResetFunctionInfo);
simulatedSize = OSGetConsoleSimulatedMemSize();
if (simulatedSize < OSGetPhysicalMemSize() && simulatedSize == 0x1800000) {
__MEMRegs[20] = 2;
}
__OSUnmaskInterrupts(OS_INTERRUPTMASK_MEM_ADDRESS);
OSRestoreInterrupts(enabled);
}
+74
View File
@@ -0,0 +1,74 @@
#include <dolphin.h>
#include <dolphin/os.h>
void OSInitMessageQueue(struct OSMessageQueue* mq, OSMessage* msgArray,
int msgCount)
{
OSInitThreadQueue(&mq->queueSend);
OSInitThreadQueue(&mq->queueReceive);
mq->msgArray = msgArray;
mq->msgCount = msgCount;
mq->firstIndex = 0;
mq->usedCount = 0;
}
int OSSendMessage(struct OSMessageQueue* mq, OSMessage msg, int flags)
{
int enabled;
long lastIndex;
enabled = OSDisableInterrupts();
while (mq->msgCount <= mq->usedCount) {
if (!(flags & 1)) {
OSRestoreInterrupts(enabled);
return 0;
}
OSSleepThread(&mq->queueSend);
}
lastIndex = (mq->firstIndex + mq->usedCount) % mq->msgCount;
((u32*)mq->msgArray)[lastIndex] = (u32)msg;
mq->usedCount++;
OSWakeupThread(&mq->queueReceive);
OSRestoreInterrupts(enabled);
return 1;
}
int OSReceiveMessage(struct OSMessageQueue* mq, OSMessage* msg, int flags)
{
int enabled = OSDisableInterrupts();
while (mq->usedCount == 0) {
if (!(flags & 1)) {
OSRestoreInterrupts(enabled);
return 0;
}
OSSleepThread(&mq->queueReceive);
}
if (msg != NULL) {
*(u32*)msg = ((u32*)mq->msgArray)[mq->firstIndex];
}
mq->firstIndex = (mq->firstIndex + 1) % mq->msgCount;
mq->usedCount--;
OSWakeupThread(&mq->queueSend);
OSRestoreInterrupts(enabled);
return 1;
}
int OSJamMessage(struct OSMessageQueue * mq, OSMessage msg, int flags) {
int enabled = OSDisableInterrupts();
while(mq->msgCount <= mq->usedCount) {
if(!(flags & 1)) {
OSRestoreInterrupts(enabled);
return 0;
}
OSSleepThread(&mq->queueSend);
}
mq->firstIndex = (mq->firstIndex + mq->msgCount - 1) % mq->msgCount;
((u32*)mq->msgArray)[mq->firstIndex] = (u32)msg;
mq->usedCount++;
OSWakeupThread(&mq->queueReceive);
OSRestoreInterrupts(enabled);
return 1;
}
+255
View File
@@ -0,0 +1,255 @@
#include <dolphin.h>
#include <dolphin/os.h>
#include <macros.h>
#include "os/__os.h"
#define ENQUEUE_MUTEX(mutex, queue, link) \
do { \
struct OSMutex* __prev = (queue)->tail; \
if (__prev == NULL) { \
(queue)->head = (mutex); \
} else { \
__prev->link.next = (mutex); \
} \
(mutex)->link.prev = __prev; \
(mutex)->link.next = 0; \
(queue)->tail = (mutex); \
} while (0);
#define DEQUEUE_MUTEX(mutex, queue, link) \
do { \
struct OSMutex* __next = (mutex)->link.next; \
struct OSMutex* __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);
#define DEQUEUE_HEAD(mutex, queue, link) \
do { \
struct OSMutex* __next = mutex->link.next; \
if (__next == NULL) { \
(queue)->tail = 0; \
} else { \
__next->link.prev = 0; \
} \
(queue)->head = __next; \
} while (0);
void OSInitMutex(struct OSMutex* mutex)
{
OSInitThreadQueue(&mutex->queue);
mutex->thread = 0;
mutex->count = 0;
}
void OSLockMutex(struct OSMutex* mutex)
{
int enabled = OSDisableInterrupts();
struct OSThread* currentThread = OSGetCurrentThread();
ASSERTMSGLINE(0x8C, currentThread,
"OSLockMutex(): current thread does not exist.");
ASSERTMSGLINE(0x8E, currentThread->state == 2,
"OSLockMutex(): current thread is not running.");
while (1) {
struct OSThread* ownerThread = mutex->thread;
if (ownerThread == 0) {
mutex->thread = currentThread;
mutex->count++;
ENQUEUE_MUTEX(mutex, &currentThread->queueMutex, link);
break;
} else if (ownerThread == currentThread) {
mutex->count++;
break;
} else {
currentThread->mutex = mutex;
__OSPromoteThread(mutex->thread, currentThread->priority);
OSSleepThread(&mutex->queue);
currentThread->mutex = NULL;
}
}
OSRestoreInterrupts(enabled);
}
void OSUnlockMutex(struct OSMutex* mutex)
{
int enabled = OSDisableInterrupts();
struct OSThread* currentThread = OSGetCurrentThread();
ASSERTMSGLINE(0xBD, currentThread,
"OSUnlockMutex(): current thread does not exist.");
ASSERTMSGLINE(0xBF, currentThread->state == 2,
"OSUnlockMutex(): current thread is not running.");
ASSERTMSG2LINE(
0xC2, mutex->thread == currentThread,
"OSUnlockMutex(): current thread %p is not the owner of mutex %p.",
currentThread, mutex);
if (mutex->thread == currentThread) {
if (!--mutex->count) {
DEQUEUE_MUTEX(mutex, &currentThread->queueMutex, link);
mutex->thread = 0;
if (currentThread->priority < currentThread->base) {
currentThread->priority
= __OSGetEffectivePriority(currentThread);
}
OSWakeupThread(&mutex->queue);
}
}
OSRestoreInterrupts(enabled);
}
void __OSUnlockAllMutex(struct OSThread* thread)
{
struct OSMutex* mutex;
while (thread->queueMutex.head) {
mutex = thread->queueMutex.head;
DEQUEUE_HEAD(mutex, &thread->queueMutex, link);
ASSERTLINE(0xE5, mutex->thread == thread);
mutex->count = 0;
mutex->thread = 0;
OSWakeupThread(&mutex->queue);
}
}
int OSTryLockMutex(struct OSMutex* mutex)
{
int enabled = OSDisableInterrupts();
struct OSThread* currentThread = OSGetCurrentThread();
int locked;
ASSERTMSGLINE(0xFF, currentThread,
"OSTryLockMutex(): current thread does not exist.");
ASSERTMSGLINE(0x101, currentThread->state == 2,
"OSTryLockMutex(): current thread is not running.");
if (!mutex->thread) {
mutex->thread = currentThread;
mutex->count++;
ENQUEUE_MUTEX(mutex, &currentThread->queueMutex, link);
locked = 1;
} else if (mutex->thread == currentThread) {
mutex->count++;
locked = 1;
} else {
locked = 0;
}
OSRestoreInterrupts(enabled);
return locked;
}
void OSInitCond(struct OSCond* cond) { OSInitThreadQueue(&cond->queue); }
void OSWaitCond(struct OSCond* cond, struct OSMutex* mutex)
{
int enabled = OSDisableInterrupts();
struct OSThread* currentThread = OSGetCurrentThread();
ASSERTMSGLINE(0x139, currentThread,
"OSWaitCond(): current thread does not exist.");
ASSERTMSGLINE(0x13B, currentThread->state == 2,
"OSWaitCond(): current thread is not running.");
ASSERTMSG2LINE(
0x13E, mutex->thread == currentThread,
"OSWaitCond(): current thread %p is not the owner of mutex %p.",
currentThread, mutex);
if (mutex->thread == currentThread) {
long count = mutex->count;
mutex->count = 0;
DEQUEUE_MUTEX(mutex, &currentThread->queueMutex, link);
mutex->thread = 0;
if (currentThread->priority < currentThread->base) {
currentThread->priority = __OSGetEffectivePriority(currentThread);
}
OSDisableScheduler();
OSWakeupThread(&mutex->queue);
OSEnableScheduler();
OSSleepThread(&cond->queue);
OSLockMutex(mutex);
mutex->count = count;
}
OSRestoreInterrupts(enabled);
}
void OSSignalCond(struct OSCond* cond) { OSWakeupThread(&cond->queue); }
int __OSCheckMutex(struct OSMutex * mutex) {
struct OSThread * thread;
struct OSThreadQueue * queue;
long priority;
priority = 0;
queue = &mutex->queue;
if (queue->head != NULL && queue->head->link.prev != NULL) {
return 0;
}
if (queue->tail != NULL && queue->tail->link.next != NULL) {
return 0;
}
thread = queue->head;
while(thread) {
if (thread->link.next != NULL && (thread != thread->link.next->link.prev)) {
return 0;
}
if (thread->link.prev != NULL && (thread != thread->link.prev->link.next)) {
return 0;
}
if (thread->state != 4) {
return 0;
}
if (thread->priority < priority) {
return 0;
}
priority = thread->priority;
thread = thread->link.next;
}
if (mutex->thread) {
if (mutex->count <= 0) {
return 0;
}
} else if (mutex->count != 0) {
return 0;
}
return 1;
}
int __OSCheckDeadLock(struct OSThread * thread) {
struct OSMutex * mutex = thread->mutex;
while(mutex && mutex->thread) {
if (mutex->thread == thread) {
return 1;
}
mutex = mutex->thread->mutex;
}
return 0;
}
int __OSCheckMutexes(struct OSThread * thread) {
struct OSMutex * mutex = thread->queueMutex.head;
while(mutex) {
if (mutex->thread != thread) {
return 0;
}
if (__OSCheckMutex(mutex) == 0) {
return 0;
}
mutex = mutex->link.next;
}
return 1;
}
+127
View File
@@ -0,0 +1,127 @@
#include <dolphin/os.h>
#include <dolphin/dvd.h>
#include "dvd/__dvd.h"
#include "os/__os.h"
static void* SaveStart = NULL;
static void* SaveEnd = NULL;
static volatile BOOL Prepared;
extern u32 OS_RESET_CODE AT_ADDRESS(0x800030F0);
// unknown function, set to true by __OSReboot
extern u8 OS_REBOOT_BOOL AT_ADDRESS(0x800030E2);
extern u32 UNK_817FFFF8 AT_ADDRESS(0x817FFFF8);
extern u32 UNK_817FFFFC AT_ADDRESS(0x817FFFFC);
#define OS_BOOTROM_ADDR ((void*)0x81300000)
typedef struct _ApploaderHeader {
/* 0x00 */ char date[16];
/* 0x10 */ u32 entry;
/* 0x14 */ u32 size;
/* 0x18 */ u32 rebootSize;
/* 0x1C */ u32 reserved2;
} ApploaderHeader; // Size: 0x20
static ApploaderHeader Header __attribute__((aligned(32)));
static asm void Run(register void (*addr)())
{
#ifdef __MWERKS__ // clang-format off
fralloc
bl OSDisableInterrupts
bl ICFlashInvalidate
sync
isync
mtlr addr
blr
frfree
blr
#endif // clang-format on
}
inline void ReadApploader(DVDCommandBlock* dvdCmd, void* addr, u32 offset,
u32 numBytes)
{
/* Not sure if this inline is correct - might need to call other inlines */
while (Prepared == FALSE) { }
DVDReadAbsAsyncForBS(dvdCmd, addr, numBytes, offset + 0x2440, NULL);
while (TRUE) {
switch (dvdCmd->state) {
case 0:
break;
case 1:
default:
continue;
case -1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
__OSDoHotReset(UNK_817FFFFC);
continue;
}
break;
}
}
static void Callback(s32 result, struct DVDCommandBlock* block)
{
Prepared = TRUE;
}
void __OSReboot(u32 resetCode, u32 bootDol)
{
OSContext exceptionContext;
DVDCommandBlock dvdCmd;
DVDCommandBlock dvdCmd2;
u32 numBytes;
u32 offset;
OSDisableInterrupts();
UNK_817FFFFC = 0;
UNK_817FFFF8 = 0;
OS_REBOOT_BOOL = TRUE;
BOOT_REGION_START = SaveStart;
BOOT_REGION_END = SaveEnd;
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
DVDInit();
DVDSetAutoInvalidation(TRUE);
__DVDPrepareResetAsync(Callback);
if (!DVDCheckDisk()) {
__OSDoHotReset(UNK_817FFFFC);
}
__OSMaskInterrupts(0xffffffe0);
__OSUnmaskInterrupts(0x400);
OSEnableInterrupts();
offset = 0;
numBytes = 32;
ReadApploader(&dvdCmd, (void*)&Header, offset, numBytes);
offset = Header.size + 0x20;
numBytes = OSRoundUp32B(Header.rebootSize);
ReadApploader(&dvdCmd2, OS_BOOTROM_ADDR, offset, numBytes);
ICInvalidateRange(OS_BOOTROM_ADDR, numBytes);
Run(OS_BOOTROM_ADDR);
}
void OSGetSaveRegion(void** start, void** end)
{
*start = SaveStart;
*end = SaveEnd;
}
+239
View File
@@ -0,0 +1,239 @@
#include <dolphin.h>
#include <dolphin/os.h>
#include <dolphin/hw_regs.h>
#include <macros.h>
#include <string.h>
#include "os/__os.h"
// These macros are copied from OSThread.c. Or ARE they the same
// macros? They dont seem to be in the SDK headers.
#define ENQUEUE_INFO(info, queue) \
do { \
struct OSResetFunctionInfo* __prev = (queue)->tail; \
if (__prev == 0) { \
(queue)->head = (info); \
} else { \
__prev->next = (info); \
} \
(info)->prev = __prev; \
(info)->next = 0; \
(queue)->tail = (info); \
} while (0);
#define DEQUEUE_INFO(info, queue) \
do { \
struct OSResetFunctionInfo* __next = (info)->next; \
struct OSResetFunctionInfo* __prev = (info)->prev; \
if (__next == 0) { \
(queue)->tail = __prev; \
} else { \
__next->prev = __prev; \
} \
if (__prev == 0) { \
(queue)->head = __next; \
} else { \
__prev->next = __next; \
} \
} while (0);
#define ENQUEUE_INFO_PRIO(info, queue) \
do { \
struct OSResetFunctionInfo* __prev; \
struct OSResetFunctionInfo* __next; \
for (__next = (queue)->head; \
__next && (__next->priority <= (info)->priority); \
__next = __next->next) \
; \
\
if (__next == 0) { \
ENQUEUE_INFO(info, queue); \
} else { \
(info)->next = __next; \
__prev = __next->prev; \
__next->prev = (info); \
(info)->prev = __prev; \
if (__prev == 0) { \
(queue)->head = (info); \
} else { \
__prev->next = (info); \
} \
} \
} while (0);
static struct OSResetFunctionQueue ResetFunctionQueue;
static int CallResetFunctions(int final);
static asm void Reset(unsigned long resetCode);
void OSRegisterResetFunction(struct OSResetFunctionInfo* info)
{
ENQUEUE_INFO_PRIO(info, &ResetFunctionQueue);
}
void OSUnregisterResetFunction(struct OSResetFunctionInfo* info)
{
DEQUEUE_INFO(info, &ResetFunctionQueue);
}
static int CallResetFunctions(int final)
{
struct OSResetFunctionInfo* info;
int err = 0;
for (info = ResetFunctionQueue.head; info; info = info->next) {
err |= !info->func(final);
}
err |= !__OSSyncSram();
if (err) {
return 0;
}
return 1;
}
static asm void Reset(unsigned long resetCode)
{
#ifdef __MWERKS__ // clang-format off
nofralloc
b L_000001BC
L_000001A0:
mfspr r8, HID0
ori r8, r8, 0x8
mtspr HID0, r8
isync
sync
nop
b L_000001C0
L_000001BC:
b L_000001DC
L_000001C0:
mftb r5, 268
L_000001C4:
mftb r6, 268
subf r7, r5, r6
cmplwi r7, 0x1124
blt L_000001C4
nop
b L_000001E0
L_000001DC:
b L_000001FC
L_000001E0:
lis r8, 0xcc00
ori r8, r8, 0x3000
li r4, 0x3
stw r4, 0x24(r8)
stw r3, 0x24(r8)
nop
b L_00000200
L_000001FC:
b L_00000208
L_00000200:
nop
b L_00000200
L_00000208:
b L_000001A0
#endif // clang-format on
}
void __OSDoHotReset(s32 arg0)
{
OSDisableInterrupts();
__VIRegs[1] = 0;
ICFlashInvalidate();
Reset(arg0 * 8);
}
inline BOOL __OSCallResetFunctions(BOOL arg0)
{
OSResetFunctionInfo* iter;
s32 retCode = 0;
s32 temp;
for (iter = ResetFunctionQueue.head; iter != NULL;) {
temp = !iter->func(arg0);
iter = iter->next;
retCode |= temp;
}
retCode |= !__OSSyncSram();
if (retCode) {
return 0;
}
return 1;
}
inline static void KillThreads(void)
{
OSThread* thread;
OSThread* next;
for (thread = __OSActiveThreadQueue.head; thread; thread = next) {
next = thread->linkActive.next;
switch (thread->state) {
case 1:
case 4:
OSCancelThread(thread);
continue;
default:
continue;
}
}
}
extern u8 OS_REBOOT_BOOL AT_ADDRESS(0x800030E2);
void OSResetSystem(int reset, unsigned long resetCode, int forceMenu)
{
char trash[0x10]; // Either more inlines or more local vars, idk
s32 padThing;
OSDisableScheduler();
__OSStopAudioSystem();
if (reset == OS_RESET_SHUTDOWN)
padThing = __PADDisableRecalibration(1);
do {
} while (CallResetFunctions(0) == 0);
if ((reset == OS_RESET_HOTRESET && (forceMenu != 0))) {
__OSLockSram()->flags |= 0x40;
__OSUnlockSram(1);
do {
} while (__OSSyncSram() == 0);
}
OSDisableInterrupts();
__OSCallResetFunctions(TRUE);
LCDisable();
if (reset == OS_RESET_HOTRESET) {
OSDisableInterrupts();
__VIRegs[1] = 0;
ICFlashInvalidate();
Reset(resetCode * 8);
} else if (reset == OS_RESET_RESTART) {
KillThreads();
OSEnableScheduler();
__OSReboot(resetCode, forceMenu);
}
KillThreads();
// TODO: maybe use AT_ADDRESS vars or macros from other files here?
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(&OS_REBOOT_BOOL, 0, 1);
__PADDisableRecalibration(padThing);
}
u32 OSGetResetCode(void)
{
if (OS_REBOOT_BOOL != 0)
return 0x80000000;
return ((__PIRegs[9] & ~7) >> 3);
}
+92
View File
@@ -0,0 +1,92 @@
#include <dolphin.h>
#include <dolphin/os.h>
#include <dolphin/os/OSResetSW.h>
#include "os/__os.h"
u8 GameChoice AT_ADDRESS(OS_BASE_CACHED | 0x30E3);
static OSResetCallback ResetCallback;
static BOOL Down;
static BOOL LastState;
static OSTime HoldUp;
static OSTime HoldDown;
void __OSResetSWInterruptHandler(__OSInterrupt exception,
struct 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 & 0x3F) {
OSTime fire = (GameChoice & 0x3F) * 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(); }
+48
View File
@@ -0,0 +1,48 @@
#include <dolphin.h>
#include <dolphin/os.h>
void OSInitStopwatch(struct OSStopwatch* sw, char* name)
{
sw->name = name;
sw->total = 0;
sw->hits = 0;
sw->min = 0x00000000FFFFFFFF;
sw->max = 0;
}
void OSStartStopwatch(struct OSStopwatch* sw)
{
sw->running = 1;
sw->last = OSGetTime();
}
void OSStopStopwatch(struct OSStopwatch* sw)
{
long long interval;
if (sw->running != 0) {
interval = OSGetTime() - sw->last;
sw->total += interval;
sw->running = 0;
sw->hits++;
if (sw->max < interval) {
sw->max = interval;
}
if (interval < sw->min) {
sw->min = interval;
}
}
}
long long OSCheckStopwatch(struct OSStopwatch* sw)
{
long long currTotal;
currTotal = sw->total;
if (sw->running != 0) {
currTotal += OSGetTime() - sw->last;
}
return currTotal;
}
void OSResetStopwatch(struct OSStopwatch* sw) { OSInitStopwatch(sw, sw->name); }
+35
View File
@@ -0,0 +1,35 @@
#include <dolphin.h>
#include <dolphin/os.h>
#include "../src/static/dolphin/os/__os.h"
void __OSSystemCallVectorStart();
void __OSSystemCallVectorEnd();
static asm void SystemCallVector(void)
{
#ifdef __MWERKS__ // clang-format off
entry __OSSystemCallVectorStart
nofralloc
mfspr r9, HID0
ori r10, r9, 0x8
mtspr HID0, r10
isync
sync
mtspr HID0, r9
rfi
entry __OSSystemCallVectorEnd
nop
#endif // clang-format on
}
void __OSInitSystemCall(void)
{
void* addr = (void*)OSPhysicalToCached(0xC00);
memcpy(addr, __OSSystemCallVectorStart,
(u32)&__OSSystemCallVectorEnd - (u32)&__OSSystemCallVectorStart);
DCFlushRangeNoSync(addr, 0x100);
__sync();
ICInvalidateRange(addr, 0x100);
}
+806
View File
@@ -0,0 +1,806 @@
#include <dolphin.h>
#include <dolphin/base/PPCArch.h>
#include <dolphin/os.h>
#include <macros.h>
#include "os/__os.h"
#define IsSuspended(suspend) (suspend > 0)
#define ENQUEUE_THREAD(thread, queue, link) \
do { \
OSThread* __prev = (queue)->tail; \
if (__prev == NULL) { \
(queue)->head = (thread); \
} else { \
__prev->link.next = (thread); \
} \
(thread)->link.prev = __prev; \
(thread)->link.next = 0; \
(queue)->tail = (thread); \
} while (0);
#define DEQUEUE_THREAD(thread, queue, link) \
do { \
OSThread* __next = (thread)->link.next; \
OSThread* __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 ENQUEUE_THREAD_PRIO(thread, queue, link) \
do { \
OSThread* __prev; \
OSThread* __next; \
for (__next = (queue)->head; \
__next && (__next->priority <= (thread)->priority); \
__next = __next->link.next) \
; \
\
if (__next == NULL) { \
ENQUEUE_THREAD(thread, queue, 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 DEQUEUE_HEAD(thread, queue, link) \
do { \
OSThread* __next = thread->link.next; \
if (__next == NULL) { \
(queue)->tail = 0; \
} else { \
__next->link.prev = 0; \
} \
(queue)->head = __next; \
} while (0);
// which header should these go in?
extern unsigned char _stack_end[];
extern char _stack_addr[];
// .bss
static OSThreadQueue RunQueue[32];
static OSThread IdleThread;
static OSThread DefaultThread;
static struct OSContext IdleContext;
static volatile unsigned long RunQueueBits;
static volatile int RunQueueHint;
static long Reschedule;
#define ALIGN4(val) (((val) + 0x3) & ~0x3)
#define ALIGN8(val) (((val) + 0x7) & ~0x7)
// functions
static void OSInitMutexQueue(struct OSMutexQueue* queue);
static void __OSSwitchThread(OSThread* nextThread);
static int __OSIsThreadActive(OSThread* thread);
static void SetRun(OSThread* thread);
static void UnsetRun(OSThread* thread);
static OSThread* SetEffectivePriority(OSThread* thread, long priority);
static void UpdatePriority(OSThread* thread);
static OSThread* SelectThread(int yield);
void __OSThreadInit()
{
OSThread* thread = &DefaultThread;
int prio;
thread->state = 2;
thread->attr = 1;
thread->priority = thread->base = 0x10;
thread->suspend = 0;
thread->val = (void*)-1; // wut
thread->mutex = 0;
OSInitThreadQueue(&thread->queueJoin);
thread->queueMutex.head = thread->queueMutex.tail
= 0; // it got inlined? cant reproduce the inline...
ASSERTLINE(282, PPCMfmsr() & MSR_FP);
__gUnkThread1 = thread;
OSClearContext(&thread->context);
OSSetCurrentContext(&thread->context);
thread->stackBase = (unsigned char*)&_stack_addr;
thread->stackEnd = (unsigned long*)&_stack_end;
*(u32*)thread->stackEnd = 0xDEADBABE;
__gCurrentThread = thread;
RunQueueBits = 0;
RunQueueHint = 0;
for (prio = 0; prio <= 31; prio++) {
OSInitThreadQueue(&RunQueue[prio]);
}
OSInitThreadQueue(&__OSActiveThreadQueue);
ENQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive);
OSClearContext(&IdleContext);
Reschedule = 0;
}
void OSInitThreadQueue(OSThreadQueue* queue) { queue->head = queue->tail = 0; }
OSThread* OSGetCurrentThread() { return __gCurrentThread; }
static void __OSSwitchThread(OSThread* nextThread)
{
__gCurrentThread = nextThread;
OSSetCurrentContext(&nextThread->context);
OSLoadContext(&nextThread->context);
}
int OSIsThreadTerminated(OSThread* thread)
{
return (thread->state == 8 || thread->state == 0) ? 1 : 0;
}
static int __OSIsThreadActive(OSThread* thread)
{
OSThread* active;
if (thread->state == 0) {
return 0;
}
for (active = __OSActiveThreadQueue.head; active;
active = active->linkActive.next) {
if (thread == active) {
return 1;
}
}
return 0;
}
s32 OSDisableScheduler(void)
{
register int enabled;
long count;
enabled = OSDisableInterrupts();
count = Reschedule;
Reschedule = count + 1;
OSRestoreInterrupts(enabled);
return count;
}
s32 OSEnableScheduler(void)
{
register int enabled;
long count;
enabled = OSDisableInterrupts();
count = Reschedule;
Reschedule = count - 1;
OSRestoreInterrupts(enabled);
return count;
}
static void SetRun(OSThread* thread)
{
ASSERTLINE(469, !IsSuspended(thread->suspend));
ASSERTLINE(470, thread->state == OS_THREAD_STATE_READY);
ASSERTLINE(472, OS_PRIORITY_MIN <= thread->priority
&& thread->priority <= OS_PRIORITY_MAX);
thread->queue = &RunQueue[thread->priority];
ENQUEUE_THREAD(thread, thread->queue, link);
RunQueueBits |= 1 << (0x1F - thread->priority);
RunQueueHint = 1;
}
static void UnsetRun(OSThread* thread)
{
OSThreadQueue* queue;
ASSERTLINE(0x1ED, thread->state == OS_THREAD_STATE_READY);
ASSERTLINE(0x1EF, OS_PRIORITY_MIN <= thread->priority
&& thread->priority <= OS_PRIORITY_MAX);
ASSERTLINE(0x1F0, thread->queue == &RunQueue[thread->priority]);
queue = thread->queue;
DEQUEUE_THREAD(thread, queue, link);
if (!queue->head) {
RunQueueBits &= ~(1 << (0x1F - thread->priority));
}
thread->queue = NULL;
}
long __OSGetEffectivePriority(OSThread* thread)
{
long priority = thread->base;
struct OSMutex* mutex;
for (mutex = thread->queueMutex.head; mutex; mutex = mutex->link.next) {
OSThread* blocked = mutex->queue.head;
if (blocked && blocked->priority < priority) {
priority = blocked->priority;
}
}
return priority;
}
static OSThread* SetEffectivePriority(OSThread* thread, long priority)
{
ASSERTLINE(547, !IsSuspended(thread->suspend));
switch (thread->state) {
case 1:
UnsetRun(thread);
thread->priority = priority;
SetRun(thread);
break;
case 4:
DEQUEUE_THREAD(thread, thread->queue, link);
thread->priority = priority;
ENQUEUE_THREAD_PRIO(thread, thread->queue, link);
if (thread->mutex) {
ASSERTLINE(0x232, thread->mutex->thread);
return thread->mutex->thread;
}
break;
case 2:
RunQueueHint = 1;
thread->priority = priority;
break;
}
return 0;
}
static void UpdatePriority(OSThread* thread)
{
long priority;
while (1) {
if (thread->suspend > 0) {
break;
}
priority = __OSGetEffectivePriority(thread);
if (thread->priority == priority) {
break;
}
thread = SetEffectivePriority(thread, priority);
if (thread == 0) {
break;
}
}
}
void __OSPromoteThread(OSThread* thread, long priority)
{
while (1) {
if (thread->suspend > 0 || thread->priority <= priority) {
break;
}
thread = SetEffectivePriority(thread, priority);
if (thread == 0) {
break;
}
}
}
static OSThread* SelectThread(int yield)
{
struct OSContext* currentContext;
OSThread* currentThread;
OSThread* nextThread;
long priority;
OSThreadQueue* queue;
if (Reschedule > 0) {
return NULL;
}
currentContext = OSGetCurrentContext();
currentThread = OSGetCurrentThread();
if (currentContext != &currentThread->context) {
return NULL;
}
if (currentThread) {
if (currentThread->state == 2) {
if (yield == 0) {
priority = __cntlzw(RunQueueBits);
if (currentThread->priority <= priority)
return NULL;
}
currentThread->state = 1;
SetRun(currentThread);
}
if (!(currentThread->context.state & 2)
&& (OSSaveContext(&currentThread->context) != 0)) {
return NULL;
}
}
__gCurrentThread = 0;
if (RunQueueBits == 0) {
OSSetCurrentContext(&IdleContext);
do {
OSEnableInterrupts();
while (RunQueueBits == 0)
;
OSDisableInterrupts();
} while (RunQueueBits == 0);
OSClearContext(&IdleContext);
}
RunQueueHint = 0;
priority = __cntlzw(RunQueueBits);
ASSERTLINE(0x2C6,
OS_PRIORITY_MIN <= priority && priority <= OS_PRIORITY_MAX);
queue = &RunQueue[priority];
nextThread = queue->head;
DEQUEUE_HEAD(nextThread, queue, link);
ASSERTLINE(0x2C9, nextThread->priority == priority);
if (!queue->head) {
RunQueueBits &= ~(1 << (0x1F - priority));
}
nextThread->queue = 0;
nextThread->state = 2;
__OSSwitchThread(nextThread);
return nextThread;
}
void __OSReschedule(void)
{
if (RunQueueHint != 0) {
SelectThread(0);
}
}
void OSYieldThread(void)
{
int enabled = OSDisableInterrupts();
SelectThread(1);
OSRestoreInterrupts(enabled);
}
int OSCreateThread(OSThread* thread, void* (*func)(void*), void* param,
void* stack, unsigned long stackSize, long priority,
unsigned short attr)
{
int enabled;
unsigned long sp;
ASSERTMSGLINE(
0x31C, ((priority >= 0) && (priority <= 0x1F)),
"OSCreateThread(): priority out of range (0 <= priority <= 31).");
// why check this for an assert just to check it again right after?
if ((priority < 0) || (priority > 0x1F)) {
return 0;
}
thread->state = 1;
thread->attr = attr & 1U;
thread->base = priority;
thread->priority = priority;
thread->suspend = 1;
thread->val = (void*)-1;
thread->mutex = 0;
OSInitThreadQueue(&thread->queueJoin);
OSInitThreadQueue((void*)&thread->queueMutex); // why
sp = (u32)stack;
sp &= ~7;
sp -= 8;
((u32*)sp)[0] = 0;
((u32*)sp)[1] = 0;
OSInitContext(&thread->context, (u32)func, sp);
thread->context.lr = (unsigned long)&OSExitThread;
thread->context.gpr[3] = (unsigned long)param;
thread->stackBase = stack;
thread->stackEnd = (void*)((unsigned int)stack - stackSize);
*thread->stackEnd = 0xDEADBABE;
enabled = OSDisableInterrupts();
ASSERTMSG1LINE(0x33B, __OSIsThreadActive(thread) == 0L,
"OSCreateThread(): thread %p is still active.", thread);
ENQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive);
OSRestoreInterrupts(enabled);
return 1;
}
void OSExitThread(void* val)
{
int enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
ASSERTMSGLINE(0x354, currentThread,
"OSExitThread(): current thread does not exist.");
ASSERTMSGLINE(0x356, currentThread->state == 2,
"OSExitThread(): current thread is not running.");
ASSERTMSGLINE(0x358, __OSIsThreadActive(currentThread) != 0,
"OSExitThread(): current thread is not active.");
OSClearContext(&currentThread->context);
if (currentThread->attr & 1) {
DEQUEUE_THREAD(currentThread, &__OSActiveThreadQueue, linkActive);
currentThread->state = 0;
} else {
currentThread->state = 8;
currentThread->val = val;
}
__OSUnlockAllMutex(currentThread);
OSWakeupThread(&currentThread->queueJoin);
RunQueueHint = 1;
if (RunQueueHint != 0) {
SelectThread(0);
}
OSRestoreInterrupts(enabled);
}
void OSCancelThread(OSThread* thread)
{
int enabled = OSDisableInterrupts();
ASSERTMSG1LINE(0x37E, __OSIsThreadActive(thread) != 0,
"OSExitThread(): thread %p is not active.", thread);
switch (thread->state) {
case 1:
if (thread->suspend <= 0) {
UnsetRun(thread);
}
break;
case 2:
RunQueueHint = 1;
break;
case 4:
DEQUEUE_THREAD(thread, thread->queue, link);
thread->queue = 0;
if ((thread->suspend <= 0) && (thread->mutex)) {
ASSERTLINE(0x391, thread->mutex->thread);
UpdatePriority(thread->mutex->thread);
}
break;
default:
OSRestoreInterrupts(enabled);
return;
}
OSClearContext(&thread->context);
if (thread->attr & 1) {
DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive);
thread->state = 0;
} else {
thread->state = 8;
}
__OSUnlockAllMutex(thread);
OSWakeupThread(&thread->queueJoin);
__OSReschedule();
OSRestoreInterrupts(enabled);
}
int OSJoinThread(OSThread* thread, void** val)
{
int enabled = OSDisableInterrupts();
ASSERTMSG1LINE(0x3CA, __OSIsThreadActive(thread) != 0,
"OSJoinThread(): thread %p is not active.", thread);
if (!(thread->attr & 1) && (thread->state != 8)
&& (thread->queueJoin.head == NULL)) {
OSSleepThread(&thread->queueJoin);
if (__OSIsThreadActive(thread) == 0) {
OSRestoreInterrupts(enabled);
return 0;
}
}
if (thread->state == 8) {
if (val) {
*val = thread->val;
}
DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive);
thread->state = 0;
OSRestoreInterrupts(enabled);
return 1;
}
OSRestoreInterrupts(enabled);
return 0;
}
void OSDetachThread(OSThread* thread)
{
int enabled = OSDisableInterrupts();
ASSERTMSG1LINE(0x3FC, __OSIsThreadActive(thread) != 0,
"OSDetachThread(): thread %p is not active.", thread);
thread->attr |= 1;
if (thread->state == 8) {
DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive);
thread->state = 0;
}
OSWakeupThread(&thread->queueJoin);
OSRestoreInterrupts(enabled);
}
long OSResumeThread(OSThread* thread)
{
int enabled = OSDisableInterrupts();
long suspendCount;
ASSERTMSG1LINE(0x419, __OSIsThreadActive(thread) != 0,
"OSResumeThread(): thread %p is not active.", thread);
ASSERTMSG1LINE(0x41B, thread->state != 8,
"OSResumeThread(): thread %p is terminated.", thread);
suspendCount = thread->suspend--;
if (thread->suspend < 0) {
thread->suspend = 0;
} else if (thread->suspend == 0) {
switch (thread->state) {
case 1:
thread->priority = __OSGetEffectivePriority(thread);
SetRun(thread);
break;
case 4:
ASSERTLINE(0x42A, thread->queue);
DEQUEUE_THREAD(thread, thread->queue, link);
thread->priority = __OSGetEffectivePriority(thread);
ENQUEUE_THREAD_PRIO(thread, thread->queue, link);
if (thread->mutex) {
UpdatePriority(thread->mutex->thread);
}
}
__OSReschedule();
}
OSRestoreInterrupts(enabled);
return suspendCount;
}
long OSSuspendThread(OSThread* thread)
{
int enabled = OSDisableInterrupts();
long suspendCount;
ASSERTMSG1LINE(0x44C, __OSIsThreadActive(thread) != 0,
"OSSuspendThread(): thread %p is not active.", thread);
ASSERTMSG1LINE(0x44E, thread->state != 8,
"OSSuspendThread(): thread %p is terminated.", thread);
suspendCount = thread->suspend++;
if (suspendCount == 0) {
switch (thread->state) {
case 2:
RunQueueHint = 1;
thread->state = 1;
break;
case 1:
UnsetRun(thread);
break;
case 4:
DEQUEUE_THREAD(thread, thread->queue, link);
thread->priority = 0x20;
ENQUEUE_THREAD(thread, thread->queue, link);
if (thread->mutex) {
ASSERTLINE(0x463, thread->mutex->thread);
UpdatePriority(thread->mutex->thread);
}
break;
}
__OSReschedule();
}
OSRestoreInterrupts(enabled);
return suspendCount;
}
void OSSleepThread(OSThreadQueue* queue)
{
int enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
ASSERTMSGLINE(0x484, currentThread,
"OSSleepThread(): current thread does not exist.");
ASSERTMSG1LINE(0x486, __OSIsThreadActive(currentThread) != 0,
"OSSleepThread(): current thread %p is not active.",
currentThread);
ASSERTMSG1LINE(0x488, currentThread->state == 2,
"OSSleepThread(): current thread %p is not running.",
currentThread);
ASSERTMSG1LINE(0x48A, currentThread->suspend <= 0,
"OSSleepThread(): current thread %p is suspended.",
currentThread);
currentThread->state = 4;
currentThread->queue = queue;
ENQUEUE_THREAD_PRIO(currentThread, queue, link);
RunQueueHint = 1;
__OSReschedule();
OSRestoreInterrupts(enabled);
}
void OSWakeupThread(OSThreadQueue* queue)
{
int enabled = OSDisableInterrupts();
while (queue->head) {
OSThread* thread = queue->head;
DEQUEUE_HEAD(thread, queue, link);
ASSERTLINE(0x4A7, __OSIsThreadActive(thread));
ASSERTLINE(0x4A8, thread->state != OS_THREAD_STATE_MORIBUND);
ASSERTLINE(0x4A9, thread->queue == queue);
thread->state = 1;
if (thread->suspend <= 0) {
SetRun(thread);
}
}
__OSReschedule();
OSRestoreInterrupts(enabled);
}
int OSSetThreadPriority(struct OSThread * thread, long priority) {
int enabled;
ASSERTMSGLINE(0x4C3, (priority >= 0) && (priority <= 0x1F), "OSSetThreadPriority(): priority out of range (0 <= priority <= 31).");
if ((priority < 0) || (priority > 0x1F)) {
return 0;
}
enabled = OSDisableInterrupts();
ASSERTMSG1LINE(0x4CA, __OSIsThreadActive(thread) != 0, "OSSetThreadPriority(): thread %p is not active.", thread);
ASSERTMSG1LINE(0x4CC, thread->state != 8, "OSSetThreadPriority(): thread %p is terminated.", thread);
if (thread->base != priority) {
thread->base = priority;
UpdatePriority(thread);
__OSReschedule();
}
OSRestoreInterrupts(enabled);
return 1;
}
long OSGetThreadPriority(OSThread* thread) { return thread->base; }
static int CheckThreadQueue(struct OSThreadQueue * queue) {
struct OSThread * thread;
if ((queue->head != NULL) && (queue->head->link.prev != NULL)) {
return 0;
}
if ((queue->tail != NULL) && (queue->tail->link.next != NULL)) {
return 0;
}
thread = queue->head;
while(thread) {
if ((thread->link.next != NULL) && (thread != thread->link.next->link.prev)) {
return 0;
}
if ((thread->link.prev != NULL) && (thread != thread->link.prev->link.next)) {
return 0;
}
thread = thread->link.next;
}
return 1;
}
static int IsMember(struct OSThreadQueue * queue, struct OSThread * thread) {
struct OSThread * member = queue->head;
while(member) {
if (thread == member) {
return 1;
}
member = member->link.next;
}
return 0;
}
#define ASSERTREPORT(line, cond) \
if (!(cond)) { \
OSReport("OSCheckActiveThreads: Failed " #cond " in %d\n", line); \
OSPanic(__FILE__, line, ""); \
}
long OSCheckActiveThreads() {
struct OSThread * thread;
long prio;
long cThread;
int enabled;
cThread = 0;
enabled = OSDisableInterrupts();
for(prio = 0; prio <= 0x1F; prio++) {
if (RunQueueBits & (1 << (0x1F - prio))) {
ASSERTREPORT(0x566, RunQueue[prio].head != NULL && RunQueue[prio].tail != NULL);
} else {
ASSERTREPORT(0x56B, RunQueue[prio].head == NULL && RunQueue[prio].tail == NULL);
}
ASSERTREPORT(0x56D, CheckThreadQueue(&RunQueue[prio]));
}
ASSERTREPORT(0x572, __OSActiveThreadQueue.head == NULL || __OSActiveThreadQueue.head->linkActive.prev == NULL);
ASSERTREPORT(0x574, __OSActiveThreadQueue.tail == NULL || __OSActiveThreadQueue.tail->linkActive.next == NULL);
thread = __OSActiveThreadQueue.head;
while(thread) {
cThread++;
ASSERTREPORT(0x57C, thread->linkActive.next == NULL || thread == thread->linkActive.next->linkActive.prev);
ASSERTREPORT(0x57E, thread->linkActive.prev == NULL || thread == thread->linkActive.prev->linkActive.next);
ASSERTREPORT(0x581, *(thread->stackEnd) == OS_THREAD_STACK_MAGIC);
ASSERTREPORT(0x584, OS_PRIORITY_MIN <= thread->priority && thread->priority <= OS_PRIORITY_MAX+1);
ASSERTREPORT(0x585, 0 <= thread->suspend);
ASSERTREPORT(0x586, CheckThreadQueue(&thread->queueJoin));
switch(thread->state) {
case 1:
if (thread->suspend <= 0) {
ASSERTREPORT(0x58C, thread->queue == &RunQueue[thread->priority]);
ASSERTREPORT(0x58D, IsMember(&RunQueue[thread->priority], thread));
ASSERTREPORT(0x58E, thread->priority == __OSGetEffectivePriority(thread));
}
break;
case 2:
ASSERTREPORT(0x592, !IsSuspended(thread->suspend));
ASSERTREPORT(0x593, thread->queue == NULL);
ASSERTREPORT(0x594, thread->priority == __OSGetEffectivePriority(thread));
break;
case 4:
ASSERTREPORT(0x597, thread->queue != NULL);
ASSERTREPORT(0x598, CheckThreadQueue(thread->queue));
ASSERTREPORT(0x599, IsMember(thread->queue, thread));
if (thread->suspend <= 0) {
ASSERTREPORT(0x59C, thread->priority == __OSGetEffectivePriority(thread));
} else {
ASSERTREPORT(0x5A0, thread->priority == 32);
}
ASSERTREPORT(0x5A2, !__OSCheckDeadLock(thread));
break;
case 8:
ASSERTREPORT(0x5A6, thread->queueMutex.head == NULL && thread->queueMutex.tail == NULL);
break;
default:
OSReport("OSCheckActiveThreads: Failed. unkown thread state (%d) of thread %p\n", thread->state, thread);
OSPanic("OSThread.c", 0x5AC, "");
}
ASSERTREPORT(0x5B1, __OSCheckMutexes(thread));
thread = thread->linkActive.next;
}
OSRestoreInterrupts(enabled);
return cThread;
}
+170
View File
@@ -0,0 +1,170 @@
#include <dolphin/exi.h>
#include <dolphin/os.h>
#include <macros.h>
#include "os/__os.h"
// End of each month in standard year
static int YearDays[MONTH_MAX]
= { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
// End of each month in leap year
static int LeapYearDays[MONTH_MAX]
= { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
asm long long OSGetTime(void)
{
#ifdef __MWERKS__ // clang-format off
jump:
nofralloc
mftbu r3
mftb r4
// Check for possible carry from TBL to TBU
mftbu r5
cmpw r3, r5
bne jump
blr
#endif // clang-format on
}
asm unsigned long OSGetTick(void)
{
#ifdef __MWERKS__ // clang-format off
nofralloc
mftb r3
blr
#endif // clang-format on
}
long long __OSGetSystemTime()
{
int enabled;
long long* timeAdjustAddr;
long long result;
timeAdjustAddr = (long long*)0x800030D8;
enabled = OSDisableInterrupts();
result = OSGetTime() + *timeAdjustAddr;
OSRestoreInterrupts(enabled);
return result;
}
static int IsLeapYear(int year)
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
static int GetYearDays(int year, int mon) {
int* md = (IsLeapYear(year)) ? LeapYearDays : YearDays;
return md[mon];
}
static int GetLeapDays(int year)
{
ASSERTLINE(260, 0 <= year);
if (year < 1) {
return 0;
}
return (year + 3) / 4 - (year - 1) / 100 + (year - 1) / 400;
}
static void GetDates(int days, OSCalendarTime* td)
{
int year;
int n;
int month;
int* md;
ASSERTLINE(285, 0 <= days);
td->wday = (days + 6) % WEEK_DAY_MAX;
for (year = days / YEAR_DAY_MAX;
days < (n = year * YEAR_DAY_MAX + GetLeapDays(year)); year--) {
;
}
days -= n;
td->year = year;
td->yday = days;
md = IsLeapYear(year) ? LeapYearDays : YearDays;
for (month = MONTH_MAX; days < md[--month];) {
;
}
td->mon = month;
td->mday = days - md[month] + 1;
}
void OSTicksToCalendarTime(long long ticks, OSCalendarTime* td)
{
int days;
int secs;
long long d;
d = ticks % OSSecondsToTicks(1);
if (d < 0) {
d += OSSecondsToTicks(1);
ASSERTLINE(330, 0 <= d);
}
td->usec = OSTicksToMicroseconds(d) % USEC_MAX;
td->msec = OSTicksToMilliseconds(d) % MSEC_MAX;
ASSERTLINE(334, 0 <= td->usec);
ASSERTLINE(335, 0 <= td->msec);
ticks -= d;
ASSERTLINE(338, ticks % OSSecondsToTicks(1) == 0);
ASSERTLINE(342, 0 <= OSTicksToSeconds(ticks) / 86400 + BIAS
&& OSTicksToSeconds(ticks) / 86400 + BIAS <= INT_MAX);
days = (OSTicksToSeconds(ticks) / SECS_IN_DAY) + BIAS;
secs = OSTicksToSeconds(ticks) % SECS_IN_DAY;
if (secs < 0) {
days -= 1;
secs += SECS_IN_DAY;
ASSERTLINE(349, 0 <= secs);
}
GetDates(days, td);
td->hour = secs / 60 / 60;
td->min = secs / 60 % 60;
td->sec = secs % 60;
}
OSTime OSCalendarTimeToTicks(OSCalendarTime* td) {
OSTime secs;
int ov_mon;
int mon;
int year;
ov_mon = td->mon / MONTH_MAX;
mon = td->mon - (ov_mon * MONTH_MAX);
if (mon < 0) {
mon += MONTH_MAX;
ov_mon--;
}
ASSERTLINE(412, (ov_mon <= 0 && 0 <= td->year + ov_mon) || (0 < ov_mon && td->year <= INT_MAX - ov_mon));
year = td->year + ov_mon;
secs = (OSTime)SECS_IN_YEAR * year +
(OSTime)SECS_IN_DAY * (GetLeapDays(year) + GetYearDays(year, mon) + td->mday - 1) +
(OSTime)SECS_IN_HOUR * td->hour +
(OSTime)SECS_IN_MIN * td->min +
td->sec -
(OSTime)0xEB1E1BF80ULL;
return OSSecondsToTicks(secs) + OSMillisecondsToTicks((OSTime)td->msec) +
OSMicrosecondsToTicks((OSTime)td->usec);
}
+38 -25
View File
@@ -4,11 +4,14 @@
#include <dolphin/os.h>
// OS.c
extern char * __OSExceptionNames[15]; // D ONLY
extern char* __OSExceptionNames[15]; // D ONLY
extern OSTime __OSStartTime;
unsigned long __OSIsDebuggerPresent(void);
void __OSPSInit(void);
unsigned long __OSGetDIConfig(void);
extern void* BOOT_REGION_START AT_ADDRESS(0x812FDFF0);
extern void* BOOT_REGION_END AT_ADDRESS(0x812FDFEC);
// OSAlloc.c
extern volatile int __OSCurrHeap;
@@ -23,18 +26,24 @@ void __OSCacheInit(void);
// OSContext.c
void __OSContextInit(void);
// OSMemory.c
void __OSInitMemoryProtection(void);
// OSError.c
void __OSUnhandledException(unsigned char exception, struct OSContext * context, unsigned long dsisr, unsigned long dar);
void __OSUnhandledException(unsigned char exception, struct OSContext* context,
unsigned long dsisr, unsigned long dar);
// OSInterrupt.c
extern void __RAS_OSDisableInterrupts_begin(void);
extern void __RAS_OSDisableInterrupts_end(void);
extern unsigned long long __OSSpuriousInterrupts; // D ONLY
extern char * __OSInterruptNames[33]; // D ONLY
extern char * __OSPIErrors[8]; // D ONLY
extern char* __OSInterruptNames[33]; // D ONLY
extern char* __OSPIErrors[8]; // D ONLY
extern OSErrorHandlerEx __OSErrorTable[16];
__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, __OSInterruptHandler handler);
__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt,
__OSInterruptHandler handler);
__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt);
void __OSInterruptInit(void);
OSInterruptMask __OSMaskInterrupts(OSInterruptMask global);
@@ -43,25 +52,33 @@ void __OSDispatchInterrupt(__OSException exception, OSContext* context);
void __OSModuleInit(void);
// OSMutex.c
void __OSUnlockAllMutex(struct OSThread *thread);
int __OSCheckDeadLock(struct OSThread *thread);
int __OSCheckMutexes(struct OSThread *thread);
void __OSUnlockAllMutex(struct OSThread* thread);
int __OSCheckDeadLock(struct OSThread* thread);
int __OSCheckMutexes(struct OSThread* thread);
// OSResetSW.c
void __OSResetSWInterruptHandler(short exception, struct OSContext *context);
void __OSResetSWInterruptHandler(__OSInterrupt exception,
struct OSContext* context);
// OSReset.c
void __OSDoHotReset(s32);
// OSReboot.c
void __OSReboot(u32, u32);
// OSRtc.c
int __OSGetRTC(unsigned long * rtc);
int __OSGetRTC(unsigned long* rtc);
int __OSSetRTC(unsigned long rtc);
void __OSInitSram();
struct OSSram * __OSLockSram(void);
struct OSSramEx * __OSLockSramEx(void);
struct OSSram* __OSLockSram(void);
struct OSSramEx* __OSLockSramEx(void);
int __OSUnlockSram(int commit);
int __OSUnlockSramEx(int commit);
int __OSSyncSram(void);
int __OSCheckSram(void);
int __OSReadROM(void * buffer, long length, long offset);
int __OSReadROMAsync(void * buffer, long length, long offset, void (* callback)());
int __OSReadROM(void* buffer, long length, long offset);
int __OSReadROMAsync(void* buffer, long length, long offset,
void (*callback)());
unsigned char __OSGetBootMode(void);
void __OSSetBootMode(unsigned char ntd);
@@ -73,8 +90,8 @@ void __OSInitSystemCall(void);
// OSThread.c
void __OSThreadInit(void);
long __OSGetEffectivePriority(struct OSThread * thread);
void __OSPromoteThread(struct OSThread * thread, long priority);
long __OSGetEffectivePriority(struct OSThread* thread);
void __OSPromoteThread(struct OSThread* thread, long priority);
void __OSReschedule(void);
// OSTime.c
@@ -82,9 +99,12 @@ void __OSSetTime(long long time);
long long __OSGetSystemTime();
void __OSSetTick(register unsigned long newTicks);
extern u32 __OSGetDIConfig(void);
// ppc_eabi_init.c
__declspec(section ".init") asm void __init_hardware(void);
__declspec(section ".init") asm void __flush_cache(void *address, unsigned int size);
__declspec(section ".init") asm void __flush_cache(void* address,
unsigned int size);
void __init_user(void);
void __init_cpp(void);
void __fini_cpp(void);
@@ -94,17 +114,10 @@ void _ExitProcess(void);
void __start(void);
__declspec(section ".init") extern void __start(void);
__declspec(section ".init") void __copy_rom_section(void* dst, const void* src, unsigned long size);
__declspec(section ".init") void __init_bss_section(void* dst, unsigned long size);
__declspec(section ".init") extern void __init_registers(void);
__declspec(section ".init") extern void __init_data(void);
// time.dolphin.c
long long __get_clock(void);
unsigned long __get_time(void);
int __to_gm_time(void);
// EXIUart.c
void __OSEnableBarnacle(s32 chan, u32 dev);
#endif // _DOLPHIN_OS_INTERNAL_H_
+1 -1
View File
@@ -342,7 +342,7 @@ extern void DSPInit2 (DSPTaskInfo2* task){
u16 tmp;
enable = OSDisableInterrupts();
__OSUnmaskInterrupts(OS_INTRMASK_DSP_DSP);
__OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_DSP);
tmp = __DSPRegs[DSP_CONTROL_STATUS];
tmp = (tmp & ~0xA8)| 0x800;