Work around FOR PFS BUG with O_TRUNC
[open-ps2-loader/simon.git] / ee_core / src / iopmgr.c
blobec901c93904437ade519bd5d00c44627e3c43a49
1 /*
2 Copyright 2009-2010, Ifcaro, jimmikaelkael & Polo
3 Copyright 2006-2008 Polo
4 Licenced under Academic Free License version 3.0
5 Review OpenUsbLd README & LICENSE files for further details.
7 Some parts of the code are taken from HD Project by Polo
8 */
10 #include "ee_core.h"
11 #include "iopmgr.h"
12 #include "modmgr.h"
13 #include "util.h"
14 #include "syshook.h"
15 #include "smbauth.h"
17 extern void *imgdrv_irx;
18 extern int size_imgdrv_irx;
20 extern void *usbd_irx;
21 extern int size_usbd_irx;
23 #ifdef VMC
24 extern void *mcemu_irx;
25 extern int size_mcemu_irx;
26 #endif
28 extern void *cdvdman_irx;
29 extern int size_cdvdman_irx;
31 extern void *cdvdfsv_irx;
32 extern int size_cdvdfsv_irx;
34 extern void *eesync_irx;
35 extern int size_eesync_irx;
37 extern void *smstcpip_irx;
38 extern int size_smstcpip_irx;
40 extern void *smsmap_irx;
41 extern int size_smsmap_irx;
43 extern void *udptty_irx;
44 extern int size_udptty_irx;
46 extern void *ioptrap_irx;
47 extern int size_ioptrap_irx;
49 /*----------------------------------------------------------------------------------------*/
50 /* Reset IOP processor. This fonction hook reset iop if an update sequence is requested. */
51 /*----------------------------------------------------------------------------------------*/
52 int New_Reset_Iop(const char *arg, int flag)
54 void *rom_iop;
55 int i, j, fd = 0;
56 ioprp_t ioprp_img;
57 char ioprp_path[0x50] = "\0";
58 int eeloadcnf_reset = 0;
60 DPRINTF("New_Reset_Iop start!\n");
61 if(!DisableDebug)
62 GS_BGCOLOUR = 0xFF00FF;
64 iop_reboot_count++;
65 DPRINTF("IOP reboot count = %d\n", iop_reboot_count);
67 SifInitRpc(0);
69 if (iop_reboot_count > 1) {
70 // above 2nd IOP reset, we can't be sure we'll be able to read IOPRP without
71 // Resetting IOP (game IOPRP is loaded at 2nd reset), so...
72 // Reseting IOP.
74 delay(1);
75 SifExitRpc();
76 SifExitIopHeap();
77 LoadFileExit();
78 fioExit();
80 // Reseting IOP.
81 while (!Reset_Iop("rom0:UDNL rom0:EELOADCNF", 0)) {;}
82 while (!Sync_Iop()){;}
84 SifInitRpc(0);
85 SifInitIopHeap();
86 LoadFileInit();
87 Sbv_Patch();
89 if (GameMode == ETH_MODE)
90 start_smbauth_thread();
92 LoadIRXfromKernel(cdvdman_irx, size_cdvdman_irx, 0, NULL);
94 if(!DisableDebug)
95 GS_BGCOLOUR = 0x00A5FF;
97 if (GameMode == USB_MODE) {
98 LoadIRXfromKernel(usbd_irx, size_usbd_irx, 0, NULL);
99 delay(USBDelay);
100 #ifdef __LOAD_DEBUG_MODULES
101 LoadIRXfromKernel(smstcpip_irx, size_smstcpip_irx, 0, NULL);
102 LoadIRXfromKernel(smsmap_irx, size_smsmap_irx, g_ipconfig_len, g_ipconfig);
103 LoadIRXfromKernel(udptty_irx, size_udptty_irx, 0, NULL);
104 LoadIRXfromKernel(ioptrap_irx, size_ioptrap_irx, 0, NULL);
105 #endif
107 else if (GameMode == ETH_MODE) {
108 LoadIRXfromKernel(smstcpip_irx, size_smstcpip_irx, 0, NULL);
109 LoadIRXfromKernel(smsmap_irx, size_smsmap_irx, g_ipconfig_len, g_ipconfig);
110 #ifdef __LOAD_DEBUG_MODULES
111 LoadIRXfromKernel(udptty_irx, size_udptty_irx, 0, NULL);
112 LoadIRXfromKernel(ioptrap_irx, size_ioptrap_irx, 0, NULL);
113 #endif
115 else if (GameMode == HDD_MODE) {
116 #ifdef __LOAD_DEBUG_MODULES
117 LoadIRXfromKernel(smstcpip_irx, size_smstcpip_irx, 0, NULL);
118 LoadIRXfromKernel(smsmap_irx, size_smsmap_irx, g_ipconfig_len, g_ipconfig);
119 LoadIRXfromKernel(udptty_irx, size_udptty_irx, 0, NULL);
120 LoadIRXfromKernel(ioptrap_irx, size_ioptrap_irx, 0, NULL);
121 #endif
125 // check for reboot with IOPRP from cdrom
126 char *ioprp_pattern = "rom0:UDNL cdrom";
127 for (i=0; i<0x50; i++) {
128 for (j=0; j<15; j++) {
129 if (arg[i+j] != ioprp_pattern[j])
130 break;
132 if (j == 15) {
133 // get IOPRP img file path
134 _strcpy(ioprp_path, &arg[i+10]);
135 break;
139 // check for reboot with IOPRP from rom
140 char *eeloadcnf_pattern = "rom0:UDNL rom";
141 for (i=0; i<0x50; i++) {
142 for (j=0; j<13; j++) {
143 if (arg[i+j] != eeloadcnf_pattern[j])
144 break;
146 if (j == 13) {
147 _strcpy(ioprp_path, &arg[i+10]);
148 eeloadcnf_reset = 1;
149 break;
153 if ((eeloadcnf_reset) || (ioprp_path[0] == '\0')) {
154 ioprp_img.data_in = (void *)g_buf;
155 Build_EELOADCNF_Img(&ioprp_img, XLoadfileCheck());
157 else {
158 DPRINTF("Reading IOPRP: '%s'\n", ioprp_path);
160 fioInit();
161 fd = open(ioprp_path, O_RDONLY);
162 if (fd < 0){
163 DPRINTF("Failed to open IOPRP...\n");
164 if(!DisableDebug)
165 GS_BGCOLOUR = 0x000080;
167 register int retry_count = 0;
168 while (retry_count++ < 2) {
169 // some games like SOCOM3 uses faulty IOPRP path like "cdrom0:\RUN\IRX\DNAS300.IMGG;1"
170 // some games from Army Men series uses faulty IOPRP path like "cdrom0:\IRX\IOPRP205.IMG.IMG;1"
171 // this part ensure it will not get stucked on red screen
172 char *p = NULL;
173 if (retry_count == 1)
174 p = _strrchr(ioprp_path, '.');
175 else if (retry_count == 2)
176 p = _strchr(ioprp_path, '.');
178 if (p) {
179 p[4] = ';';
180 p[5] = '1';
181 p[6] = 0;
183 fd = open(ioprp_path, O_RDONLY);
187 if (fd < 0)
188 while (1){;}
191 ioprp_img.size_in = lseek(fd, 0, SEEK_END);
192 DPRINTF("IOPRP size: %d bytes\n", ioprp_img.size_in);
193 if (ioprp_img.size_in % 0x40)
194 ioprp_img.size_in = (ioprp_img.size_in & 0xffffffc0) + 0x40;
196 lseek(fd, 0, SEEK_SET);
198 ioprp_img.data_in = (void *)g_buf;
199 ioprp_img.data_out = ioprp_img.data_in;
200 ioprp_img.size_out = ioprp_img.size_in;
202 read(fd, ioprp_img.data_in , ioprp_img.size_in);
204 close(fd);
205 fioExit();
207 DPRINTF("IOPRP readed\n");
209 DPRINTF("Patching CDVDMAN...\n");
210 Patch_Mod(&ioprp_img, "CDVDMAN", cdvdman_irx, size_cdvdman_irx);
211 DPRINTF("Patching CDVDFSV...\n");
212 Patch_Mod(&ioprp_img, "CDVDFSV", cdvdfsv_irx, size_cdvdfsv_irx);
213 DPRINTF("Patching EESYNC...\n");
214 Patch_Mod(&ioprp_img, "EESYNC", eesync_irx, size_eesync_irx);
217 DPRINTF("Exiting services...\n");
218 SifExitRpc();
219 SifExitIopHeap();
220 LoadFileExit();
222 // Reseting IOP.
223 DPRINTF("Resetting IOP...\n");
224 while (!Reset_Iop("rom0:UDNL rom0:EELOADCNF", 0)) {;}
225 while (!Sync_Iop()){;}
227 DPRINTF("Init services...\n");
228 SifInitRpc(0);
229 SifInitIopHeap();
230 LoadFileInit();
231 DPRINTF("Applying Sbv patches...\n");
232 Sbv_Patch();
234 if (GameMode == ETH_MODE)
235 start_smbauth_thread();
237 DPRINTF("Sending patched IOPRP on IOP and try to reset with...\n");
238 rom_iop = SifAllocIopHeap(ioprp_img.size_out);
240 if (rom_iop){
241 CopyToIop(ioprp_img.data_out, ioprp_img.size_out, rom_iop);
243 // get back imgdrv from kernel ram
244 DIntr();
245 ee_kmode_enter();
246 memcpy(g_buf, imgdrv_irx, size_imgdrv_irx);
247 ee_kmode_exit();
248 EIntr();
250 *(u32*)(&g_buf[0x180]) = (u32)rom_iop;
251 *(u32*)(&g_buf[0x184]) = ioprp_img.size_out;
252 FlushCache(0);
254 LoadMemModule(g_buf, size_imgdrv_irx, 0, NULL);
255 LoadModuleAsync("rom0:UDNL", 5, "img0:");
257 SifExitRpc();
258 LoadFileExit();
260 DIntr();
261 ee_kmode_enter();
262 Old_SifSetReg(SIF_REG_SMFLAG, 0x10000);
263 Old_SifSetReg(SIF_REG_SMFLAG, 0x20000);
264 Old_SifSetReg(0x80000002, 0);
265 Old_SifSetReg(0x80000000, 0);
266 ee_kmode_exit();
267 EIntr();
268 } else {
269 DPRINTF("IOP memory allocation (%d bytes) failed!\n", ioprp_img.size_out);
270 if(!DisableDebug)
271 GS_BGCOLOUR = 0xFF0000;
272 while (1){;}
275 while (!Sync_Iop()) {;}
277 SifExitIopHeap();
278 DPRINTF("Init services...\n");
279 SifInitRpc(0);
280 SifInitIopHeap();
281 LoadFileInit();
282 DPRINTF("Applying Sbv patches...\n");
283 Sbv_Patch();
285 if(!DisableDebug)
286 GS_BGCOLOUR = 0x00FFFF;
288 DPRINTF("Loading extra IOP modules...\n");
289 if (GameMode == USB_MODE) {
290 LoadIRXfromKernel(usbd_irx, size_usbd_irx, 0, NULL);
291 delay(USBDelay);
292 #ifdef __LOAD_DEBUG_MODULES
293 LoadIRXfromKernel(smstcpip_irx, size_smstcpip_irx, 0, NULL);
294 LoadIRXfromKernel(smsmap_irx, size_smsmap_irx, g_ipconfig_len, g_ipconfig);
295 LoadIRXfromKernel(udptty_irx, size_udptty_irx, 0, NULL);
296 LoadIRXfromKernel(ioptrap_irx, size_ioptrap_irx, 0, NULL);
297 #endif
299 else if (GameMode == ETH_MODE) {
300 LoadIRXfromKernel(smstcpip_irx, size_smstcpip_irx, 0, NULL);
301 LoadIRXfromKernel(smsmap_irx, size_smsmap_irx, g_ipconfig_len, g_ipconfig);
302 #ifdef __LOAD_DEBUG_MODULES
303 LoadIRXfromKernel(udptty_irx, size_udptty_irx, 0, NULL);
304 LoadIRXfromKernel(ioptrap_irx, size_ioptrap_irx, 0, NULL);
305 #endif
307 else if (GameMode == HDD_MODE) {
308 #ifdef __LOAD_DEBUG_MODULES
309 LoadIRXfromKernel(smstcpip_irx, size_smstcpip_irx, 0, NULL);
310 LoadIRXfromKernel(smsmap_irx, size_smsmap_irx, g_ipconfig_len, g_ipconfig);
311 LoadIRXfromKernel(udptty_irx, size_udptty_irx, 0, NULL);
312 LoadIRXfromKernel(ioptrap_irx, size_ioptrap_irx, 0, NULL);
313 #endif
316 #ifdef VMC
317 if ((iop_reboot_count >= 2) && size_mcemu_irx) {
318 LoadIRXfromKernel(mcemu_irx, size_mcemu_irx, 0, NULL);
320 #endif
322 FlushCache(0);
324 DPRINTF("Exiting services...\n");
325 SifExitRpc();
326 SifExitIopHeap();
327 LoadFileExit();
329 if (g_compat_mask & COMPAT_MODE_8)
330 ChangeModuleName("dev9", "cdvdman");
332 DPRINTF("New_Reset_Iop complete!\n");
333 // we have 4 SifSetReg calls to skip in ELF's SifResetIop, not when we use it ourselves
334 if (set_reg_disabled)
335 set_reg_hook = 4;
337 return 1;
340 /*----------------------------------------------------------------------------------------*/
341 /* Reset IOP processor. This fonction replace SifIopReset from Ps2Sdk */
342 /*----------------------------------------------------------------------------------------*/
343 int Reset_Iop(const char *arg, int flag)
345 SifCmdResetData reset_pkt;
346 struct t_SifDmaTransfer dmat;
348 SifExitRpc();
350 SifStopDma();
352 memset(&reset_pkt, 0, sizeof(SifCmdResetData));
354 reset_pkt.chdr.psize = sizeof(SifCmdResetData);
355 reset_pkt.chdr.fcode = 0x80000003;
357 reset_pkt.flag = flag;
359 if (arg != NULL){
360 strncpy(reset_pkt.arg, arg, 0x50-1);
361 reset_pkt.arg[0x50-1] = '\0';
362 reset_pkt.size = strlen(reset_pkt.arg) + 1;
365 dmat.src = &reset_pkt;
366 dmat.dest = (void *)SifGetReg(0x80000000); // SIF_REG_SUBADDR
367 dmat.size = sizeof reset_pkt;
368 dmat.attr = 0x40 | SIF_DMA_INT_O;
369 SifWriteBackDCache(&reset_pkt, sizeof reset_pkt);
371 DIntr();
372 ee_kmode_enter();
373 if (!Old_SifSetDma(&dmat, 1)){
374 ee_kmode_exit();
375 EIntr();
376 return 0;
379 Old_SifSetReg(SIF_REG_SMFLAG, 0x10000);
380 Old_SifSetReg(SIF_REG_SMFLAG, 0x20000);
381 Old_SifSetReg(0x80000002, 0);
382 Old_SifSetReg(0x80000000, 0);
383 ee_kmode_exit();
384 EIntr();
386 return 1;
389 /*----------------------------------------------------------------------------------------*/
390 /* Synchronize IOP processor. This fonction replace SifIopReset from Ps2Sdk */
391 /*----------------------------------------------------------------------------------------*/
392 int Sync_Iop(void)
394 if (SifGetReg(SIF_REG_SMFLAG) & 0x40000)
395 return 1;
397 return 0;