PS2SDK
PS2 Homebrew Libraries
ExecPS2.c
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Licenced under Academic Free License version 2.0
7 # Review ps2sdk README & LICENSE files for further details.
8 */
9 
10 #include <kernel.h>
11 
12 #include "ExecPS2.h"
13 
14 static int *p_ThreadID = (int *)0x800125EC; // Pointer to a variable containing the running thread's ID.
15 static int *p_ThreadStatus = (int *)0x800125F4; // Pointer to a variable containing the running thread's status.
16 static int (*p_CancelWakeupThread)(int ThreadID) = (void *)0x80004970;
17 static int (*p_ChangeThreadPriority)(int ThreadID, int priority) = (void *)0x80004288;
18 static int (*p_InitPgifHandler2)(void) = (void *)0x800021b0;
19 static int (*p_InitSemaphores)(void) = (void *)0x80004e68;
20 static int (*p_DeleteThread)(int thread_id) = (void *)0x80003f00;
21 static int (*p_TerminateThread)(int ThreadID) = (void *)0x80003e00;
22 static struct TCB *p_TCBs = (struct TCB *)0x80017400;
23 static void (*p_InitializeINTC)(int interrupts) = (void *)0x8000b8d0;
24 static void (*p_InitializeTIMER)(void) = (void *)0x8000b900;
25 static void (*p_InitializeFPU)(void) = (void *)0x8000b7a8;
26 static void (*p_InitializeScratchPad)(void) = (void *)0x8000b840;
27 static int (*p_ResetEE)(int flags) = (void *)0x8000ad68;
28 static void (*p_InitializeGS)(void) = (void *)0x8000aa60;
29 static void (*p_SetGSCrt)(unsigned short int interlace, unsigned short int mode, unsigned short int ffmd) = (void *)0x8000a060;
30 
31 #ifndef REUSE_EXECPS2
32 
33 static void (*p_FlushDCache)(void) = (void *)0x80002a80;
34 static void (*p_FlushICache)(void) = (void *)0x80002ac0;
35 static char *(*p_eestrcpy)(char *dst, const char *src) = (void *)0x80005560;
36 // static void *p_unk80012600 = (void *)0x80012600; // Not sure what this is, as it isn't used by the patch.
37 static char *p_ArgsBuffer = (char *)0x80012608;
38 
39 #else
40 
41 static void *(*p_ExecPS2)(void *entry, void *gp, int argc, char *argv[]) = (void *)0x800057E8; // Not part of the SONY patch. See below.
42 
43 #endif
44 
45 // Taken from PCSX2's FPS2BIOS
46 struct TCB
47 { // internal struct
48  struct TCB *next; //+00
49  struct TCB *prev; //+04
50  int status; //+08
51  void (*entry)(void *d); //+0C
52  void *stack_res; //+10 initial $sp
53  void *gpReg; //+14
54  short currentPriority; //+18
55  short initPriority; //+1A
56  int waitSema, //+1C waitType?
57  semaId, //+20
58  wakeupCount, //+24
59  attr, //+28
60  option; //+2C
61  void (*entry_)(void *d);//+30
62  int argc; //+34
63  char *argstring; //+38
64  void *stack; //+3C
65  int stackSize; //+40
66  int (*root)(); //+44
67  void *heap_base; //+48
68 };
69 
70 static inline void SoftPeripheralEEReset(void)
71 {
72  *(volatile unsigned int *)0x1000f000 = 4;
73  while (((*((volatile unsigned int *)0x1000f000)) & 4) == 0) {};
74  *(volatile unsigned int *)0x1000f000 = 4;
75 
76  p_InitializeGS();
77  p_SetGSCrt(1, 2, 1); // Interlaced, NTSC, field mode.
78  p_InitializeINTC(0xdffd);
79  p_InitializeTIMER();
80  p_ResetEE(0x7F);
81  p_InitializeFPU();
82  p_InitializeScratchPad();
83 }
84 
85 void *ExecPS2Patch(void *EntryPoint, void *gp, int argc, char *argv[])
86 {
87  int i, CurrentThreadID;
88  struct TCB *tcb;
89 #ifndef REUSE_EXECPS2
90  char *ArgsPtr;
91 #endif
92 
93  CurrentThreadID = *p_ThreadID;
94  p_CancelWakeupThread(CurrentThreadID);
95  p_ChangeThreadPriority(CurrentThreadID, 0);
96 
97  // Like IOP kernels, the first thread is the idle thread.
98  for (i = 1, tcb = &p_TCBs[1]; i < MAX_THREADS; i++, tcb++) {
99  if (tcb->status != 0 && i != CurrentThreadID) {
100  if (tcb->status != THS_DORMANT)
101  p_TerminateThread(i);
102 
103  p_DeleteThread(i);
104  }
105  }
106 
107  p_InitSemaphores();
108  p_InitPgifHandler2();
109 
110  *p_ThreadStatus = 0;
111  SoftPeripheralEEReset();
112 
113 #ifdef REUSE_EXECPS2
114  // Unlike the Sony patch, why don't we just reuse the original function in the kernel?
115  return p_ExecPS2(EntryPoint, gp, argc, argv);
116 #else
117  for (i = 0, ArgsPtr = p_ArgsBuffer; i < argc; i++) {
118  ArgsPtr = p_eestrcpy(ArgsPtr, argv[i]);
119  }
120 
121  tcb = &p_TCBs[CurrentThreadID];
122  tcb->argstring = p_ArgsBuffer;
123  tcb->argc = argc;
124  tcb->entry = EntryPoint;
125  tcb->entry_ = EntryPoint;
126  tcb->gpReg = gp;
127  tcb->initPriority = 0;
128  tcb->currentPriority = 0;
129  tcb->wakeupCount = 0;
130  tcb->waitSema = 0;
131  tcb->semaId = 0;
132 
133  p_FlushICache();
134  p_FlushDCache();
135 
136  return EntryPoint;
137 #endif
138 }
kernel.h
MAX_THREADS
#define MAX_THREADS
Definition: kernel.h:71
TCB
Definition: ExecPS2.c:46