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

Contents of /trunk/pcsx2/IopBios.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 4 months ago) by william
File size: 10825 byte(s)
committing r3113 initial commit again...
1 /* 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