/[pcsx2_0.9.7]/trunk/pcsx2/IopBios.cpp
ViewVC logotype

Annotation of /trunk/pcsx2/IopBios.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 5 months ago) by william
File size: 13969 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 william 31 /* PCSX2 - PS2 Emulator for PCs
2     * Copyright (C) 2002-2010 PCSX2 Dev Team
3     *
4     * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5     * of the GNU Lesser General Public License as published by the Free Software Found-
6     * ation, either version 3 of the License, or (at your option) any later version.
7     *
8     * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10     * PURPOSE. See the GNU General Public License for more details.
11     *
12     * You should have received a copy of the GNU General Public License along with PCSX2.
13     * If not, see <http://www.gnu.org/licenses/>.
14     */
15    
16    
17     #include "PrecompiledHeader.h"
18     #include "IopCommon.h"
19     #include "R5900.h" // for g_GameStarted
20    
21     #include <ctype.h>
22     #include <string.h>
23    
24     #ifndef O_BINARY
25     #define O_BINARY 0
26     #endif
27    
28 william 62 // set this to 0 to disable rewriting 'host:' paths!
29     #define USE_HOST_REWRITE 1
30    
31     #if USE_HOST_REWRITE
32     # ifdef WIN32
33     // disable this if you DON'T want "host:/usr/local/" paths
34     // to get rewritten into host:/
35     # define HOST_REWRITE_USR_LOCAL 1
36     # else
37     // unix/linux users might want to set it to 1
38     // if they DO want to keep demos from accessing their systems' /usr/local
39     # define HOST_REWRITE_USR_LOCAL 0
40     # endif
41    
42     static char HostRoot[1024];
43     #endif
44    
45     void Hle_SetElfPath(const char* elfFileName)
46     {
47     #if USE_HOST_REWRITE
48     DevCon.WriteLn("HLE Host: Will load ELF: %s\n", elfFileName);
49    
50     const char* pos1 = strrchr(elfFileName,'/');
51     const char* pos2 = strrchr(elfFileName,'\\');
52    
53     if(pos2 > pos1) // we want the LAST path separator
54     pos1=pos2;
55    
56     if(!pos1) // if pos1 is NULL, then pos2 was not > pos1, so it must also be NULL
57     {
58     Console.Warning("HLE Warning: ELF does not have a path!!\n");
59    
60     // use %CD%/host/
61     getcwd(HostRoot,1000); // save the other 23 chars to append /host/ :P
62     HostRoot[1000]=0; // Be Safe.
63    
64     char* last = HostRoot + strlen(HostRoot) - 1;
65    
66     if((*last!='/') && (*last!='\\')) // PathAppend()-ish
67     last++;
68    
69     strcpy(last,"/host/");
70    
71     return;
72     }
73    
74     int len = pos1-elfFileName+1;
75     memcpy(HostRoot,elfFileName,len); // include the / (or \\)
76     HostRoot[len] = 0;
77    
78     Console.WriteLn("HLE Host: Set 'host:' root path to: %s\n", HostRoot);
79    
80     #endif
81     }
82    
83 william 31 namespace R3000A {
84    
85     #define v0 (psxRegs.GPR.n.v0)
86     #define a0 (psxRegs.GPR.n.a0)
87     #define a1 (psxRegs.GPR.n.a1)
88     #define a2 (psxRegs.GPR.n.a2)
89     #define a3 (psxRegs.GPR.n.a3)
90     #define sp (psxRegs.GPR.n.sp)
91     #define ra (psxRegs.GPR.n.ra)
92     #define pc (psxRegs.pc)
93    
94     #define Ra0 (iopVirtMemR<char>(a0))
95     #define Ra1 (iopVirtMemR<char>(a1))
96     #define Ra2 (iopVirtMemR<char>(a2))
97     #define Ra3 (iopVirtMemR<char>(a3))
98    
99     // TODO: sandbox option, other permissions
100     class HostFile : public IOManFile
101     {
102     public:
103     int fd;
104    
105     HostFile(int hostfd)
106     {
107     fd = hostfd;
108     }
109    
110 william 62 static __fi int translate_error(int err)
111 william 31 {
112     if (err >= 0)
113     return err;
114    
115     switch(err)
116     {
117     case -ENOENT:
118     return -IOP_ENOENT;
119     case -EACCES:
120     return -IOP_EACCES;
121     case -EISDIR:
122     return -IOP_EISDIR;
123     case -EIO:
124     default:
125     return -IOP_EIO;
126     }
127     }
128    
129     static int open(IOManFile **file, const char *name, s32 flags, u16 mode)
130     {
131     const char *path = strchr(name, ':') + 1;
132    
133 william 62 // host: actually DOES let you write!
134     //if (flags != IOP_O_RDONLY)
135     // return -IOP_EROFS;
136 william 31
137 william 62 // WIP code. Works well on win32, not so sure on unixes
138     // TODO: get rid of dependency on CWD/PWD
139     #if USE_HOST_REWRITE
140     // we want filenames to be relative to pcs2dir / host
141    
142     static char pathMod[1024];
143    
144     // partial "rooting",
145     // it will NOT avoid a path like "../../x" from escaping the pcsx2 folder!
146    
147     #if HOST_REWRITE_USR_LOCAL
148     const char *_local_root = "/usr/local/";
149     if(strncmp(path,_local_root,strlen(_local_root))==0)
150     {
151     strcpy(pathMod,HostRoot);
152     strcat(pathMod,path+strlen(_local_root));
153     }
154     else
155     #endif
156     if((path[0] == '/') || (path[0] == '\\') || (isalpha(path[0]) && (path[1] == ':'))) // absolute NATIVE path (X:\blah)
157     {
158     // TODO: allow some way to use native paths in non-windows platforms
159     // maybe hack it so linux prefixes the path with "X:"? ;P
160     // or have all platforms use a common prefix for native paths
161     strcpy(pathMod,path);
162     }
163     else // relative paths
164     {
165     strcpy(pathMod,HostRoot);
166     strcat(pathMod,path);
167     }
168     #else
169     const char* pathMod = path;
170     #endif
171    
172     int native_flags = O_BINARY; // necessary in Windows.
173    
174     switch(flags&IOP_O_RDWR)
175     {
176     case IOP_O_RDONLY: native_flags |= O_RDONLY; break;
177     case IOP_O_WRONLY: native_flags |= O_WRONLY; break;
178     case IOP_O_RDWR: native_flags |= O_RDWR; break;
179     }
180    
181     if(flags&IOP_O_APPEND) native_flags |= O_APPEND;
182     if(flags&IOP_O_CREAT) native_flags |= O_CREAT;
183     if(flags&IOP_O_TRUNC) native_flags |= O_TRUNC;
184    
185     int hostfd = ::open(pathMod, native_flags);
186 william 31 if (hostfd < 0)
187     return translate_error(hostfd);
188    
189     *file = new HostFile(hostfd);
190     if (!*file)
191     return -IOP_ENOMEM;
192    
193     return 0;
194     }
195    
196     virtual void close()
197     {
198     ::close(fd);
199     delete this;
200     }
201    
202     virtual int lseek(s32 offset, s32 whence)
203     {
204     int err;
205    
206     switch (whence)
207     {
208     case IOP_SEEK_SET:
209     err = ::lseek(fd, offset, SEEK_SET);
210     break;
211     case IOP_SEEK_CUR:
212     err = ::lseek(fd, offset, SEEK_CUR);
213     break;
214     case IOP_SEEK_END:
215     err = ::lseek(fd, offset, SEEK_END);
216     break;
217     default:
218     return -IOP_EIO;
219     }
220    
221     return translate_error(err);
222     }
223    
224     virtual int read(void *buf, u32 count)
225     {
226     return translate_error(::read(fd, buf, count));
227     }
228 william 62
229     virtual int write(void *buf, u32 count)
230     {
231     return translate_error(::write(fd, buf, count));
232     }
233 william 31 };
234    
235     namespace ioman {
236     const int firstfd = 0x100;
237     const int maxfds = 0x100;
238     int openfds = 0;
239    
240     int freefdcount()
241     {
242     return maxfds - openfds;
243     }
244    
245     struct filedesc
246     {
247     enum {
248     FILE_FREE,
249     FILE_FILE,
250     FILE_DIR,
251     } type;
252     union {
253     IOManFile *file;
254     IOManDir *dir;
255     };
256    
257     operator bool() const { return type != FILE_FREE; }
258     operator IOManFile*() const { return type == FILE_FILE ? file : NULL; }
259     operator IOManDir*() const { return type == FILE_DIR ? dir : NULL; }
260     void operator=(IOManFile *f) { type = FILE_FILE; file = f; openfds++; }
261     void operator=(IOManDir *d) { type = FILE_DIR; dir = d; openfds++; }
262    
263     void close()
264     {
265     if (type == FILE_FREE)
266     return;
267    
268     switch (type)
269     {
270     case FILE_FILE:
271     file->close();
272     file = NULL;
273     break;
274     case FILE_DIR:
275     dir->close();
276     dir = NULL;
277     break;
278     }
279    
280     type = FILE_FREE;
281     openfds--;
282     }
283     };
284    
285     filedesc fds[maxfds];
286    
287     template<typename T>
288     T* getfd(int fd)
289     {
290     fd -= firstfd;
291    
292     if (fd < 0 || fd >= maxfds)
293     return NULL;
294    
295     return fds[fd];
296     }
297    
298     template <typename T>
299     int allocfd(T *obj)
300     {
301     for (int i = 0; i < maxfds; i++)
302     {
303     if (!fds[i])
304     {
305     fds[i] = obj;
306     return firstfd + i;
307     }
308     }
309    
310     obj->close();
311     return -IOP_EMFILE;
312     }
313    
314     void freefd(int fd)
315     {
316     fd -= firstfd;
317    
318     if (fd < 0 || fd >= maxfds)
319     return;
320    
321     fds[fd].close();
322     }
323    
324     void reset()
325     {
326     for (int i = 0; i < maxfds; i++)
327     fds[i].close();
328     }
329    
330     int open_HLE()
331     {
332     IOManFile *file = NULL;
333     const char *name = Ra0;
334     s32 flags = a1;
335     u16 mode = a2;
336    
337     if ((!g_GameStarted || EmuConfig.HostFs)
338     && !strncmp(name, "host", 4) && name[4 + strspn(name + 4, "0123456789")] == ':')
339     {
340     if (!freefdcount())
341     {
342     v0 = -IOP_EMFILE;
343     pc = ra;
344     return 1;
345     }
346    
347     int err = HostFile::open(&file, name, flags, mode);
348    
349     if (err != 0 || !file)
350     {
351     if (err == 0) // ???
352     err = -IOP_EIO;
353     if (file) // ??????
354     file->close();
355     v0 = err;
356     }
357     else
358     {
359     v0 = allocfd(file);
360 william 62 if ((s32)v0 < 0)
361 william 31 file->close();
362     }
363    
364     pc = ra;
365     return 1;
366     }
367    
368     return 0;
369     }
370    
371     int close_HLE()
372     {
373     s32 fd = a0;
374    
375     if (getfd<IOManFile>(fd))
376     {
377     freefd(fd);
378     v0 = 0;
379     pc = ra;
380     return 1;
381     }
382    
383     return 0;
384     }
385    
386     int lseek_HLE()
387     {
388     s32 fd = a0;
389     s32 offset = a1;
390     s32 whence = a2;
391    
392     if (IOManFile *file = getfd<IOManFile>(fd))
393     {
394     v0 = file->lseek(offset, whence);
395     pc = ra;
396     return 1;
397     }
398    
399     return 0;
400     }
401    
402     int read_HLE()
403     {
404     s32 fd = a0;
405     u32 buf = a1;
406     u32 count = a2;
407    
408     if (IOManFile *file = getfd<IOManFile>(fd))
409     {
410     if (!iopVirtMemR<void>(buf))
411     return 0;
412    
413     v0 = file->read(iopVirtMemW<void>(buf), count);
414     pc = ra;
415     return 1;
416     }
417    
418     return 0;
419     }
420    
421     int write_HLE()
422     {
423 william 62 s32 fd = a0;
424     u32 buf = a1;
425     u32 count = a2;
426 william 31
427     if (fd == 1) // stdout
428     {
429 william 62 iopConLog(ShiftJIS_ConvertString(Ra1, a2));
430 william 31 pc = ra;
431     v0 = a2;
432     return 1;
433     }
434 william 62 else if (IOManFile *file = getfd<IOManFile>(fd))
435     {
436     if (!iopVirtMemR<void>(buf))
437     return 0;
438 william 31
439 william 62 v0 = file->write(iopVirtMemW<void>(buf), count);
440     pc = ra;
441     return 1;
442     }
443    
444 william 31 return 0;
445     }
446     }
447    
448     namespace sysmem {
449     int Kprintf_HLE()
450     {
451 william 62 // Emulate the expected Kprintf functionality:
452 william 31 iopMemWrite32(sp, a0);
453     iopMemWrite32(sp + 4, a1);
454     iopMemWrite32(sp + 8, a2);
455     iopMemWrite32(sp + 12, a3);
456 william 62 pc = ra;
457 william 31
458 william 62
459     // From here we're intercepting the Kprintf and piping it to our console, complete with
460     // printf-style formatting processing. This part can be skipped if the user has the
461     // console disabled.
462    
463     if (!SysConsole.iopConsole.IsActive()) return 1;
464    
465     char tmp[1024], tmp2[1024];
466     char *ptmp = tmp;
467     int n=1, i=0, j = 0;
468    
469 william 31 while (Ra0[i])
470     {
471     switch (Ra0[i])
472     {
473     case '%':
474     j = 0;
475     tmp2[j++] = '%';
476     _start:
477     switch (Ra0[++i])
478     {
479     case '.':
480     case 'l':
481     tmp2[j++] = Ra0[i];
482     goto _start;
483     default:
484     if (Ra0[i] >= '0' && Ra0[i] <= '9')
485     {
486     tmp2[j++] = Ra0[i];
487     goto _start;
488     }
489     break;
490     }
491    
492     tmp2[j++] = Ra0[i];
493     tmp2[j] = 0;
494    
495     switch (Ra0[i])
496     {
497     case 'f': case 'F':
498     ptmp+= sprintf(ptmp, tmp2, (float)iopMemRead32(sp + n * 4));
499     n++;
500     break;
501    
502     case 'a': case 'A':
503     case 'e': case 'E':
504     case 'g': case 'G':
505     ptmp+= sprintf(ptmp, tmp2, (double)iopMemRead32(sp + n * 4));
506     n++;
507     break;
508    
509     case 'p':
510     case 'i':
511     case 'd': case 'D':
512     case 'o': case 'O':
513     case 'x': case 'X':
514     ptmp+= sprintf(ptmp, tmp2, (u32)iopMemRead32(sp + n * 4));
515     n++;
516     break;
517    
518     case 'c':
519     ptmp+= sprintf(ptmp, tmp2, (u8)iopMemRead32(sp + n * 4));
520     n++;
521     break;
522    
523     case 's':
524     ptmp+= sprintf(ptmp, tmp2, iopVirtMemR<char>(iopMemRead32(sp + n * 4)));
525     n++;
526     break;
527    
528     case '%':
529     *ptmp++ = Ra0[i];
530     break;
531    
532     default:
533     break;
534     }
535     i++;
536     break;
537    
538     default:
539     *ptmp++ = Ra0[i++];
540     break;
541     }
542     }
543     *ptmp = 0;
544 william 62 iopConLog( ShiftJIS_ConvertString(tmp, 1023) );
545 william 31
546     return 1;
547     }
548     }
549    
550     namespace loadcore {
551     void RegisterLibraryEntries_DEBUG()
552     {
553     DbgCon.WriteLn(Color_Gray, "RegisterLibraryEntries: %8.8s", iopVirtMemR<char>(a0 + 12));
554     }
555     }
556    
557     namespace intrman {
558     static const char* intrname[] = {
559     "INT_VBLANK", "INT_GM", "INT_CDROM", "INT_DMA", //00
560     "INT_RTC0", "INT_RTC1", "INT_RTC2", "INT_SIO0", //04
561     "INT_SIO1", "INT_SPU", "INT_PIO", "INT_EVBLANK", //08
562     "INT_DVD", "INT_PCMCIA", "INT_RTC3", "INT_RTC4", //0C
563     "INT_RTC5", "INT_SIO2", "INT_HTR0", "INT_HTR1", //10
564     "INT_HTR2", "INT_HTR3", "INT_USB", "INT_EXTR", //14
565     "INT_FWRE", "INT_FDMA", "INT_1A", "INT_1B", //18
566     "INT_1C", "INT_1D", "INT_1E", "INT_1F", //1C
567     "INT_dmaMDECi", "INT_dmaMDECo", "INT_dmaGPU", "INT_dmaCD", //20
568     "INT_dmaSPU", "INT_dmaPIO", "INT_dmaOTC", "INT_dmaBERR", //24
569     "INT_dmaSPU2", "INT_dma8", "INT_dmaSIF0", "INT_dmaSIF1", //28
570     "INT_dmaSIO2i", "INT_dmaSIO2o", "INT_2E", "INT_2F", //2C
571     "INT_30", "INT_31", "INT_32", "INT_33", //30
572     "INT_34", "INT_35", "INT_36", "INT_37", //34
573     "INT_38", "INT_39", "INT_3A", "INT_3B", //38
574     "INT_3C", "INT_3D", "INT_3E", "INT_3F", //3C
575     "INT_MAX" //40
576     };
577    
578     void RegisterIntrHandler_DEBUG()
579     {
580     DbgCon.WriteLn(Color_Gray, "RegisterIntrHandler: intr %s, handler %x", intrname[a0], a2);
581     }
582     }
583    
584     namespace sifcmd {
585     void sceSifRegisterRpc_DEBUG()
586     {
587     DbgCon.WriteLn( Color_Gray, "sifcmd sceSifRegisterRpc: rpc_id %x", a1);
588     }
589     }
590    
591     const char* irxImportLibname(u32 entrypc)
592     {
593     u32 i;
594    
595     i = entrypc;
596     while (iopMemRead32(i -= 4) != 0x41e00000) // documented magic number
597     ;
598    
599     return iopVirtMemR<char>(i + 12);
600     }
601    
602     const char* irxImportFuncname(const char libname[8], u16 index)
603     {
604     #include "IopModuleNames.cpp"
605    
606     switch (index) {
607     case 0: return "start";
608     // case 1: reinit?
609     case 2: return "shutdown";
610     // case 3: ???
611     }
612    
613     return 0;
614     }
615    
616     #define MODULE(n) if (!strncmp(libname, #n, 8)) { using namespace n; switch (index) {
617     #define END_MODULE }}
618     #define EXPORT_D(i, n) case (i): return n ## _DEBUG;
619     #define EXPORT_H(i, n) case (i): return n ## _HLE;
620    
621     irxHLE irxImportHLE(const char libname[8], u16 index)
622     {
623     // debugging output
624     MODULE(sysmem)
625     EXPORT_H( 14, Kprintf)
626     END_MODULE
627 william 62
628 william 31 MODULE(ioman)
629     EXPORT_H( 4, open)
630     EXPORT_H( 5, close)
631     EXPORT_H( 6, read)
632     EXPORT_H( 7, write)
633     EXPORT_H( 8, lseek)
634     END_MODULE
635    
636     return 0;
637     }
638    
639     irxDEBUG irxImportDebug(const char libname[8], u16 index)
640     {
641     MODULE(loadcore)
642     EXPORT_D( 6, RegisterLibraryEntries)
643     END_MODULE
644     MODULE(intrman)
645     EXPORT_D( 4, RegisterIntrHandler)
646     END_MODULE
647     MODULE(sifcmd)
648     EXPORT_D( 17, sceSifRegisterRpc)
649     END_MODULE
650    
651     return 0;
652     }
653    
654     #undef MODULE
655     #undef END_MODULE
656     #undef EXPORT_D
657     #undef EXPORT_H
658    
659     void __fastcall irxImportLog(const char libname[8], u16 index, const char *funcname)
660     {
661     PSXBIOS_LOG("%8.8s.%03d: %s (%x, %x, %x, %x)",
662     libname, index, funcname ? funcname : "unknown",
663     a0, a1, a2, a3);
664     }
665    
666     int __fastcall irxImportExec(const char libname[8], u16 index)
667     {
668     const char *funcname = irxImportFuncname(libname, index);
669     irxHLE hle = irxImportHLE(libname, index);
670     irxDEBUG debug = irxImportDebug(libname, index);
671    
672     irxImportLog(libname, index, funcname);
673    
674     if (debug)
675     debug();
676    
677     if (hle)
678     return hle();
679     else
680     return 0;
681     }
682    
683     } // end namespace R3000A

  ViewVC Help
Powered by ViewVC 1.1.22