1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
#include "ultra64.h"
#include "ultra64/bcp.h"
typedef struct __osExceptionVector {
u32 inst1; // lui $k0, %hi(__osException)
u32 inst2; // addiu $k0, $k0, %lo(__osException)
u32 inst3; // jr $k0
u32 inst4; // nop
} __osExceptionVector;
extern __osExceptionVector __osExceptionPreamble;
extern OSPiHandle __Dom1SpeedParam;
extern OSPiHandle __Dom2SpeedParam;
u64 osClockRate = OS_CLOCK_RATE;
s32 osViClock = VI_NTSC_CLOCK;
u32 __osShutdown = false;
OSIntMask __OSGlobalIntMask = OS_IM_ALL;
u32 __osFinalrom;
#if LIBULTRA_VERSION < LIBULTRA_VERSION_K
#define OSINITIALIZE_FUNC osInitialize
#define SPEED_PARAM_FUNC createSpeedParam
#if (LIBULTRA_VERSION == LIBULTRA_VERSION_I && LIBULTRA_PATCH == 1) || (LIBULTRA_VERSION == LIBULTRA_VERSION_J)
static void SPEED_PARAM_FUNC(void);
#endif
#else
#define OSINITIALIZE_FUNC __osInitialize_common
#define SPEED_PARAM_FUNC __createSpeedParam
void SPEED_PARAM_FUNC(void) {
__Dom1SpeedParam.type = DEVICE_TYPE_INIT;
__Dom1SpeedParam.latency = IO_READ(PI_BSD_DOM1_LAT_REG);
__Dom1SpeedParam.pulse = IO_READ(PI_BSD_DOM1_PWD_REG);
__Dom1SpeedParam.pageSize = IO_READ(PI_BSD_DOM1_PGS_REG);
__Dom1SpeedParam.relDuration = IO_READ(PI_BSD_DOM1_RLS_REG);
__Dom2SpeedParam.type = DEVICE_TYPE_INIT;
__Dom2SpeedParam.latency = IO_READ(PI_BSD_DOM2_LAT_REG);
__Dom2SpeedParam.pulse = IO_READ(PI_BSD_DOM2_PWD_REG);
__Dom2SpeedParam.pageSize = IO_READ(PI_BSD_DOM2_PGS_REG);
__Dom2SpeedParam.relDuration = IO_READ(PI_BSD_DOM2_RLS_REG);
}
#endif
void OSINITIALIZE_FUNC(void) {
u32 pifdata;
#if LIBULTRA_VERSION < LIBULTRA_VERSION_K
u32 clock = 0;
#endif
__osFinalrom = true;
__osSetSR(__osGetSR() | SR_CU1);
__osSetFpcCsr(FPCSR_FS | FPCSR_EV | FPCSR_RM_RN);
#if LIBULTRA_VERSION >= LIBULTRA_VERSION_K
__osSetWatchLo(0x04900000);
#endif
#ifdef BBPLAYER
{
u32 x, y;
// Check for iQue Player hardware by enabling and disabling FLASH and IDE interrupts and checking if the
// register gives the correct response.
IO_WRITE(MI_EX_INTR_MASK_REG, MI_EX_INTR_MASK_SET_FLASH | MI_EX_INTR_MASK_SET_IDE);
x = IO_READ(MI_EX_INTR_MASK_REG);
IO_WRITE(MI_EX_INTR_MASK_REG, MI_EX_INTR_MASK_CLR_FLASH | MI_EX_INTR_MASK_CLR_IDE);
y = IO_READ(MI_EX_INTR_MASK_REG);
__osBbIsBb =
((x & (MI_EX_INTR_MASK_FLASH | MI_EX_INTR_MASK_IDE)) == (MI_EX_INTR_MASK_FLASH | MI_EX_INTR_MASK_IDE)) &&
((y & (MI_EX_INTR_MASK_FLASH | MI_EX_INTR_MASK_IDE)) == 0);
}
//! @bug Most games do not have permission to use GPIO, so they often cannot correctly tell if they are running on
//! HW V1 or V2.
if (__osBbIsBb && PI_GPIO_IS_HW_V2(IO_READ(PI_GPIO_REG))) {
__osBbIsBb = 2;
}
if (__osBbIsBb) {
// Set IPL boot parameters
osTvType = OS_TV_NTSC;
osRomType = 0;
osResetType = 0;
osVersion = 1;
osMemSize = 0x400000;
}
if (!__osBbIsBb) {
// The PIF doesn't exist on iQue, no need to enable NMI from PIF
#endif
while (__osSiRawReadIo((void*)(PIF_RAM_END - 3), &pifdata)) {
;
}
while (__osSiRawWriteIo((void*)(PIF_RAM_END - 3), pifdata | 8)) {
;
}
#ifdef BBPLAYER
}
#endif
*(__osExceptionVector*)UT_VEC = __osExceptionPreamble; // TLB miss
*(__osExceptionVector*)XUT_VEC = __osExceptionPreamble; // XTLB miss
*(__osExceptionVector*)ECC_VEC = __osExceptionPreamble; // cache errors
*(__osExceptionVector*)E_VEC = __osExceptionPreamble; // general exceptions
osWritebackDCache((void*)K0BASE, E_VEC - K0BASE + sizeof(__osExceptionVector));
osInvalICache((void*)K0BASE, E_VEC - K0BASE + sizeof(__osExceptionVector));
#if (LIBULTRA_VERSION == LIBULTRA_VERSION_I && LIBULTRA_PATCH == 1) || (LIBULTRA_VERSION > LIBULTRA_VERSION_I)
SPEED_PARAM_FUNC();
osUnmapTLBAll();
osMapTLBRdb();
#endif
osClockRate = osClockRate * 3 / 4;
if (!osResetType) {
bzero(osAppNMIBuffer, sizeof(osAppNMIBuffer));
}
if (osTvType == OS_TV_PAL) {
osViClock = VI_PAL_CLOCK;
} else if (osTvType == OS_TV_MPAL) {
osViClock = VI_MPAL_CLOCK;
} else {
osViClock = VI_NTSC_CLOCK;
}
#if (LIBULTRA_VERSION == LIBULTRA_VERSION_I && LIBULTRA_PATCH == 1) || (LIBULTRA_VERSION >= LIBULTRA_VERSION_J)
// If PreNMI is pending, loop until reset
if (__osGetCause() & CAUSE_IP5) {
while (true) {
;
}
}
#endif
#ifdef BBPLAYER
if (!__osBbIsBb) {
// In a real iQue Player environment (that is, real hardware + app launched from the system menu)
// these are set on app launch by the system menu based on the contents of the game's associated
// ticket. Set some dummy values if not running on iQue Player hardware.
__osBbEepromSize = 0x200;
__osBbPakSize = 0x8000;
__osBbFlashSize = 0x20000;
__osBbEepromAddress = 0x80400000 - 0x200;
__osBbPakAddress[0] = 0x80400000 - 0x8200;
__osBbPakAddress[1] = 0;
__osBbPakAddress[2] = 0;
__osBbPakAddress[3] = 0;
__osBbFlashAddress = 0x80400000 - 0x20000;
__osBbSramSize = __osBbFlashSize;
__osBbSramAddress = __osBbFlashAddress;
}
if (__osBbIsBb) {
IO_WRITE(PI_64_REG, IO_READ(PI_64_REG) & ~0x80000000);
IO_WRITE(MI_EX_INTR_MASK_REG, MI_EX_INTR_MASK_SET_IDE);
IO_WRITE(SI_0C_REG, 0);
IO_WRITE(SI_1C_REG, (IO_READ(SI_1C_REG) & ~0x7F000000) | 0x2F400000);
}
#endif
IO_WRITE(AI_CONTROL_REG, AI_CONTROL_DMA_ON);
IO_WRITE(AI_DACRATE_REG, AI_MAX_DAC_RATE - 1);
IO_WRITE(AI_BITRATE_REG, AI_MAX_BIT_RATE - 1);
}
#if (LIBULTRA_VERSION == LIBULTRA_VERSION_I && LIBULTRA_PATCH == 1) || (LIBULTRA_VERSION == LIBULTRA_VERSION_J)
static void SPEED_PARAM_FUNC(void) {
__Dom1SpeedParam.type = DEVICE_TYPE_INIT;
__Dom1SpeedParam.latency = IO_READ(PI_BSD_DOM1_LAT_REG);
__Dom1SpeedParam.pulse = IO_READ(PI_BSD_DOM1_PWD_REG);
__Dom1SpeedParam.pageSize = IO_READ(PI_BSD_DOM1_PGS_REG);
__Dom1SpeedParam.relDuration = IO_READ(PI_BSD_DOM1_RLS_REG);
__Dom2SpeedParam.type = DEVICE_TYPE_INIT;
__Dom2SpeedParam.latency = IO_READ(PI_BSD_DOM2_LAT_REG);
__Dom2SpeedParam.pulse = IO_READ(PI_BSD_DOM2_PWD_REG);
__Dom2SpeedParam.pageSize = IO_READ(PI_BSD_DOM2_PGS_REG);
__Dom2SpeedParam.relDuration = IO_READ(PI_BSD_DOM2_RLS_REG);
}
#else
void __osInitialize_autodetect(void) {
}
#endif
|