/[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 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years ago) by william
File size: 10825 byte(s)
committing r3113 initial commit again...
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     namespace R3000A {
29    
30     #define v0 (psxRegs.GPR.n.v0)
31     #define a0 (psxRegs.GPR.n.a0)
32     #define a1 (psxRegs.GPR.n.a1)
33     #define a2 (psxRegs.GPR.n.a2)
34     #define a3 (psxRegs.GPR.n.a3)
35     #define sp (psxRegs.GPR.n.sp)
36     #define ra (psxRegs.GPR.n.ra)
37     #define pc (psxRegs.pc)
38    
39     #define Ra0 (iopVirtMemR<char>(a0))
40     #define Ra1 (iopVirtMemR<char>(a1))
41     #define Ra2 (iopVirtMemR<char>(a2))
42     #define Ra3 (iopVirtMemR<char>(a3))
43    
44     // TODO: sandbox option, other permissions
45     class HostFile : public IOManFile
46     {
47     public:
48     int fd;
49    
50     HostFile(int hostfd)
51     {
52     fd = hostfd;
53     }
54    
55     static __forceinline int translate_error(int err)
56     {
57     if (err >= 0)
58     return err;
59    
60     switch(err)
61     {
62     case -ENOENT:
63     return -IOP_ENOENT;
64     case -EACCES:
65     return -IOP_EACCES;
66     case -EISDIR:
67     return -IOP_EISDIR;
68     case -EIO:
69     default:
70     return -IOP_EIO;
71     }
72     }
73    
74     static int open(IOManFile **file, const char *name, s32 flags, u16 mode)
75     {
76     const char *path = strchr(name, ':') + 1;
77    
78     if (flags != IOP_O_RDONLY)
79     return -IOP_EROFS;
80    
81     int hostfd = ::open(path, O_BINARY | O_RDONLY);
82     if (hostfd < 0)
83     return translate_error(hostfd);
84    
85     *file = new HostFile(hostfd);
86     if (!*file)
87     return -IOP_ENOMEM;
88    
89     return 0;
90     }
91    
92     virtual void close()
93     {
94     ::close(fd);
95     delete this;
96     }
97    
98     virtual int lseek(s32 offset, s32 whence)
99     {
100     int err;
101    
102     switch (whence)
103     {
104     case IOP_SEEK_SET:
105     err = ::lseek(fd, offset, SEEK_SET);
106     break;
107     case IOP_SEEK_CUR:
108     err = ::lseek(fd, offset, SEEK_CUR);
109     break;
110     case IOP_SEEK_END:
111     err = ::lseek(fd, offset, SEEK_END);
112     break;
113     default:
114     return -IOP_EIO;
115     }
116    
117     return translate_error(err);
118     }
119    
120     virtual int read(void *buf, u32 count)
121     {
122     return translate_error(::read(fd, buf, count));
123     }
124     };
125    
126     namespace ioman {
127     const int firstfd = 0x100;
128     const int maxfds = 0x100;
129     int openfds = 0;
130    
131     int freefdcount()
132     {
133     return maxfds - openfds;
134     }
135    
136     struct filedesc
137     {
138     enum {
139     FILE_FREE,
140     FILE_FILE,
141     FILE_DIR,
142     } type;
143     union {
144     IOManFile *file;
145     IOManDir *dir;
146     };
147    
148     operator bool() const { return type != FILE_FREE; }
149     operator IOManFile*() const { return type == FILE_FILE ? file : NULL; }
150     operator IOManDir*() const { return type == FILE_DIR ? dir : NULL; }
151     void operator=(IOManFile *f) { type = FILE_FILE; file = f; openfds++; }
152     void operator=(IOManDir *d) { type = FILE_DIR; dir = d; openfds++; }
153    
154     void close()
155     {
156     if (type == FILE_FREE)
157     return;
158    
159     switch (type)
160     {
161     case FILE_FILE:
162     file->close();
163     file = NULL;
164     break;
165     case FILE_DIR:
166     dir->close();
167     dir = NULL;
168     break;
169     }
170    
171     type = FILE_FREE;
172     openfds--;
173     }
174     };
175    
176     filedesc fds[maxfds];
177    
178     template<typename T>
179     T* getfd(int fd)
180     {
181     fd -= firstfd;
182    
183     if (fd < 0 || fd >= maxfds)
184     return NULL;
185    
186     return fds[fd];
187     }
188    
189     template <typename T>
190     int allocfd(T *obj)
191     {
192     for (int i = 0; i < maxfds; i++)
193     {
194     if (!fds[i])
195     {
196     fds[i] = obj;
197     return firstfd + i;
198     }
199     }
200    
201     obj->close();
202     return -IOP_EMFILE;
203     }
204    
205     void freefd(int fd)
206     {
207     fd -= firstfd;
208    
209     if (fd < 0 || fd >= maxfds)
210     return;
211    
212     fds[fd].close();
213     }
214    
215     void reset()
216     {
217     for (int i = 0; i < maxfds; i++)
218     fds[i].close();
219     }
220    
221     int open_HLE()
222     {
223     IOManFile *file = NULL;
224     const char *name = Ra0;
225     s32 flags = a1;
226     u16 mode = a2;
227    
228     if ((!g_GameStarted || EmuConfig.HostFs)
229     && !strncmp(name, "host", 4) && name[4 + strspn(name + 4, "0123456789")] == ':')
230     {
231     if (!freefdcount())
232     {
233     v0 = -IOP_EMFILE;
234     pc = ra;
235     return 1;
236     }
237    
238     int err = HostFile::open(&file, name, flags, mode);
239    
240     if (err != 0 || !file)
241     {
242     if (err == 0) // ???
243     err = -IOP_EIO;
244     if (file) // ??????
245     file->close();
246     v0 = err;
247     }
248     else
249     {
250     v0 = allocfd(file);
251     if (v0 < 0)
252     file->close();
253     }
254    
255     pc = ra;
256     return 1;
257     }
258    
259     return 0;
260     }
261    
262     int close_HLE()
263     {
264     s32 fd = a0;
265    
266     if (getfd<IOManFile>(fd))
267     {
268     freefd(fd);
269     v0 = 0;
270     pc = ra;
271     return 1;
272     }
273    
274     return 0;
275     }
276    
277     int lseek_HLE()
278     {
279     s32 fd = a0;
280     s32 offset = a1;
281     s32 whence = a2;
282    
283     if (IOManFile *file = getfd<IOManFile>(fd))
284     {
285     v0 = file->lseek(offset, whence);
286     pc = ra;
287     return 1;
288     }
289    
290     return 0;
291     }
292    
293     int read_HLE()
294     {
295     s32 fd = a0;
296     u32 buf = a1;
297     u32 count = a2;
298    
299     if (IOManFile *file = getfd<IOManFile>(fd))
300     {
301     if (!iopVirtMemR<void>(buf))
302     return 0;
303    
304     v0 = file->read(iopVirtMemW<void>(buf), count);
305     pc = ra;
306     return 1;
307     }
308    
309     return 0;
310     }
311    
312     int write_HLE()
313     {
314     int fd = a0;
315    
316     #ifdef PCSX2_DEVBUILD
317     if (fd == 1) // stdout
318     {
319     Console.Write(ConColor_IOP, L"%s", ShiftJIS_ConvertString(Ra1, a2).c_str());
320     pc = ra;
321     v0 = a2;
322     return 1;
323     }
324     #endif
325    
326     return 0;
327     }
328     }
329    
330     namespace sysmem {
331     int Kprintf_HLE()
332     {
333     char tmp[1024], tmp2[1024];
334     char *ptmp = tmp;
335     int n=1, i=0, j = 0;
336    
337     iopMemWrite32(sp, a0);
338     iopMemWrite32(sp + 4, a1);
339     iopMemWrite32(sp + 8, a2);
340     iopMemWrite32(sp + 12, a3);
341    
342     while (Ra0[i])
343     {
344     switch (Ra0[i])
345     {
346     case '%':
347     j = 0;
348     tmp2[j++] = '%';
349     _start:
350     switch (Ra0[++i])
351     {
352     case '.':
353     case 'l':
354     tmp2[j++] = Ra0[i];
355     goto _start;
356     default:
357     if (Ra0[i] >= '0' && Ra0[i] <= '9')
358     {
359     tmp2[j++] = Ra0[i];
360     goto _start;
361     }
362     break;
363     }
364    
365     tmp2[j++] = Ra0[i];
366     tmp2[j] = 0;
367    
368     switch (Ra0[i])
369     {
370     case 'f': case 'F':
371     ptmp+= sprintf(ptmp, tmp2, (float)iopMemRead32(sp + n * 4));
372     n++;
373     break;
374    
375     case 'a': case 'A':
376     case 'e': case 'E':
377     case 'g': case 'G':
378     ptmp+= sprintf(ptmp, tmp2, (double)iopMemRead32(sp + n * 4));
379     n++;
380     break;
381    
382     case 'p':
383     case 'i':
384     case 'd': case 'D':
385     case 'o': case 'O':
386     case 'x': case 'X':
387     ptmp+= sprintf(ptmp, tmp2, (u32)iopMemRead32(sp + n * 4));
388     n++;
389     break;
390    
391     case 'c':
392     ptmp+= sprintf(ptmp, tmp2, (u8)iopMemRead32(sp + n * 4));
393     n++;
394     break;
395    
396     case 's':
397     ptmp+= sprintf(ptmp, tmp2, iopVirtMemR<char>(iopMemRead32(sp + n * 4)));
398     n++;
399     break;
400    
401     case '%':
402     *ptmp++ = Ra0[i];
403     break;
404    
405     default:
406     break;
407     }
408     i++;
409     break;
410    
411     default:
412     *ptmp++ = Ra0[i++];
413     break;
414     }
415     }
416     *ptmp = 0;
417    
418     // Use "%s" even though it seems indirect: this avoids chaos if/when the IOP decides
419     // to feed us strings that contain percentages or other printf formatting control chars.
420     Console.Write( ConColor_IOP, L"%s", ShiftJIS_ConvertString(tmp).c_str(), 1023 );
421    
422     pc = ra;
423     return 1;
424     }
425     }
426    
427     namespace loadcore {
428     void RegisterLibraryEntries_DEBUG()
429     {
430     DbgCon.WriteLn(Color_Gray, "RegisterLibraryEntries: %8.8s", iopVirtMemR<char>(a0 + 12));
431     }
432     }
433    
434     namespace intrman {
435     static const char* intrname[] = {
436     "INT_VBLANK", "INT_GM", "INT_CDROM", "INT_DMA", //00
437     "INT_RTC0", "INT_RTC1", "INT_RTC2", "INT_SIO0", //04
438     "INT_SIO1", "INT_SPU", "INT_PIO", "INT_EVBLANK", //08
439     "INT_DVD", "INT_PCMCIA", "INT_RTC3", "INT_RTC4", //0C
440     "INT_RTC5", "INT_SIO2", "INT_HTR0", "INT_HTR1", //10
441     "INT_HTR2", "INT_HTR3", "INT_USB", "INT_EXTR", //14
442     "INT_FWRE", "INT_FDMA", "INT_1A", "INT_1B", //18
443     "INT_1C", "INT_1D", "INT_1E", "INT_1F", //1C
444     "INT_dmaMDECi", "INT_dmaMDECo", "INT_dmaGPU", "INT_dmaCD", //20
445     "INT_dmaSPU", "INT_dmaPIO", "INT_dmaOTC", "INT_dmaBERR", //24
446     "INT_dmaSPU2", "INT_dma8", "INT_dmaSIF0", "INT_dmaSIF1", //28
447     "INT_dmaSIO2i", "INT_dmaSIO2o", "INT_2E", "INT_2F", //2C
448     "INT_30", "INT_31", "INT_32", "INT_33", //30
449     "INT_34", "INT_35", "INT_36", "INT_37", //34
450     "INT_38", "INT_39", "INT_3A", "INT_3B", //38
451     "INT_3C", "INT_3D", "INT_3E", "INT_3F", //3C
452     "INT_MAX" //40
453     };
454    
455     void RegisterIntrHandler_DEBUG()
456     {
457     DbgCon.WriteLn(Color_Gray, "RegisterIntrHandler: intr %s, handler %x", intrname[a0], a2);
458     }
459     }
460    
461     namespace sifcmd {
462     void sceSifRegisterRpc_DEBUG()
463     {
464     DbgCon.WriteLn( Color_Gray, "sifcmd sceSifRegisterRpc: rpc_id %x", a1);
465     }
466     }
467    
468     const char* irxImportLibname(u32 entrypc)
469     {
470     u32 i;
471    
472     i = entrypc;
473     while (iopMemRead32(i -= 4) != 0x41e00000) // documented magic number
474     ;
475    
476     return iopVirtMemR<char>(i + 12);
477     }
478    
479     const char* irxImportFuncname(const char libname[8], u16 index)
480     {
481     #include "IopModuleNames.cpp"
482    
483     switch (index) {
484     case 0: return "start";
485     // case 1: reinit?
486     case 2: return "shutdown";
487     // case 3: ???
488     }
489    
490     return 0;
491     }
492    
493     #define MODULE(n) if (!strncmp(libname, #n, 8)) { using namespace n; switch (index) {
494     #define END_MODULE }}
495     #define EXPORT_D(i, n) case (i): return n ## _DEBUG;
496     #define EXPORT_H(i, n) case (i): return n ## _HLE;
497    
498     irxHLE irxImportHLE(const char libname[8], u16 index)
499     {
500     #ifdef PCSX2_DEVBUILD
501     // debugging output
502     MODULE(sysmem)
503     EXPORT_H( 14, Kprintf)
504     END_MODULE
505     #endif
506     MODULE(ioman)
507     EXPORT_H( 4, open)
508     EXPORT_H( 5, close)
509     EXPORT_H( 6, read)
510     EXPORT_H( 7, write)
511     EXPORT_H( 8, lseek)
512     END_MODULE
513    
514     return 0;
515     }
516    
517     irxDEBUG irxImportDebug(const char libname[8], u16 index)
518     {
519     MODULE(loadcore)
520     EXPORT_D( 6, RegisterLibraryEntries)
521     END_MODULE
522     MODULE(intrman)
523     EXPORT_D( 4, RegisterIntrHandler)
524     END_MODULE
525     MODULE(sifcmd)
526     EXPORT_D( 17, sceSifRegisterRpc)
527     END_MODULE
528    
529     return 0;
530     }
531    
532     #undef MODULE
533     #undef END_MODULE
534     #undef EXPORT_D
535     #undef EXPORT_H
536    
537     void __fastcall irxImportLog(const char libname[8], u16 index, const char *funcname)
538     {
539     PSXBIOS_LOG("%8.8s.%03d: %s (%x, %x, %x, %x)",
540     libname, index, funcname ? funcname : "unknown",
541     a0, a1, a2, a3);
542     }
543    
544     int __fastcall irxImportExec(const char libname[8], u16 index)
545     {
546     const char *funcname = irxImportFuncname(libname, index);
547     irxHLE hle = irxImportHLE(libname, index);
548     irxDEBUG debug = irxImportDebug(libname, index);
549    
550     irxImportLog(libname, index, funcname);
551    
552     if (debug)
553     debug();
554    
555     if (hle)
556     return hle();
557     else
558     return 0;
559     }
560    
561     } // end namespace R3000A

  ViewVC Help
Powered by ViewVC 1.1.22