Create Xref-Html Frames Remove All Frames
file:/home/jivera/wd/pcsx/Misc.c (Tue Nov 25 22:46:14 2003
)
1: /* Pcsx - Pc Psx Emulator
2: * Copyright (C) 1999-2003 Pcsx Team
3: *
4: * This program is free software; you can redistribute it and/or modify
5: * it under the terms of the GNU General Public License as published by
6: * the Free Software Foundation; either version 2 of the License, or
7: * (at your option) any later version.
8: *
9: * This program is distributed in the hope that it will be useful,
10: * but WITHOUT ANY WARRANTY; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: * GNU General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with this program; if not, write to the Free Software
16: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17: */
18:
19: #include <stdio.h>
20: #include <string.h>
21: #include <stdlib.h>
22: #include <stdarg.h>
23: #include <ctype.h>
24:
25: #include "Coff.h"
26: #include "PsxCommon.h"
27: #include "plugins.h"
28:
29: int Log = 0;
30:
31: char *LabelAuthors = { N_(
32: "PCSX a psx emulator\n\n"
33: "written by:\n"
34: "main coder: linuzappz\n"
35: "co-coders: shadow\n"
36: "ex-coders: Nocomp, Pete Bernett, nik3d\n"
37: "Webmaster: AkumaX")
38: };
39:
40: char *LabelGreets = { N_(
41: "Greets to: Duddie, Tratax, Kazzuya, JNS, Bobbi, Psychojak, Shunt,\n"
42: " Keith, DarkWatcher, Xeven, Liquid, Dixon, Prafull\n"
43: "Special thanks to:\n"
44: "Twin (we Love you twin0r), Roor (love for you too),\n"
45: "calb (Thanks for help :) ), now3d (for great help to my psxdev stuff :) )")
46: };
47:
48:
49: // LOAD STUFF
50:
51: #ifdef __MACOSX__
52:
53: #define SWAP(b) b = (((unsigned char*)&b)[0]&0xff) | ((((unsigned char*)&b)[1]&0xff)<<8) | ((((unsigned char*)&b)[2]&0xff)<<16) | (((unsigned char*)&b)[3]<<24);
54:
55: void swapEXE_HEADER(EXE_HEADER* exe) {
56: SWAP(exe->text);
57: SWAP(exe->data);
58: SWAP(exe->pc0);
59: SWAP(exe->gp0);
60: SWAP(exe->t_addr);
61: SWAP(exe->t_size);
62: SWAP(exe->d_addr);
63: SWAP(exe->d_size);
64: SWAP(exe->b_addr);
65: SWAP(exe->b_size);
66: SWAP(exe->s_addr);
67: SWAP(exe->s_size);
68: SWAP(exe->SavedSP);
69: SWAP(exe->SavedFP);
70: SWAP(exe->SavedGP);
71: SWAP(exe->SavedRA);
72: SWAP(exe->SavedS0);
73: }
74:
75: #endif
76:
77: #define ISODCL(from, to) (to - from + 1)
78:
79: struct iso_directory_record {
80: char length [ISODCL (1, 1)]; /* 711 */
81: char ext_attr_length [ISODCL (2, 2)]; /* 711 */
82: char extent [ISODCL (3, 10)]; /* 733 */
83: char size [ISODCL (11, 18)]; /* 733 */
84: char date [ISODCL (19, 25)]; /* 7 by 711 */
85: char flags [ISODCL (26, 26)];
86: char file_unit_size [ISODCL (27, 27)]; /* 711 */
87: char interleave [ISODCL (28, 28)]; /* 711 */
88: char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
89: unsigned char name_len [ISODCL (33, 33)]; /* 711 */
90: char name [1];
91: };
92:
93: #define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
94: #define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
95:
96: void mmssdd( char *b, char *p )
97: {
98: int m, s, d;
99: #if defined(__DREAMCAST__) || defined(__MACOSX__)
100: int block = (b[0]&0xff) | ((b[1]&0xff)<<8) | ((b[2]&0xff)<<16) | (b[3]<<24);
101: #else
102: int block = *((int*)b);
103: #endif
104:
105: block += 150;
106: m = block / 4500; // minuten
107: block = block - m * 4500; // minuten rest
108: s = block / 75; // sekunden
109: d = block - s * 75; // sekunden rest
110:
111: m = ( ( m / 10 ) << 4 ) | m % 10;
112: s = ( ( s / 10 ) << 4 ) | s % 10;
113: d = ( ( d / 10 ) << 4 ) | d % 10;
114:
115: p[0] = m;
116: p[1] = s;
117: p[2] = d;
118: }
119:
120: #define incTime() \
121: time[0] = btoi(time[0]); time[1] = btoi(time[1]); time[2] = btoi(time[2]); \
122: time[2]++; \
123: if(time[2] == 75) { \
124: time[2] = 0; \
125: time[1]++; \
126: if (time[1] == 60) { \
127: time[1] = 0; \
128: time[0]++; \
129: } \
130: } \
131: time[0] = itob(time[0]); time[1] = itob(time[1]); time[2] = itob(time[2]);
132:
133: #define READTRACK() \
134: if (CDR_readTrack(time) == -1) return -1; \
135: buf = CDR_getBuffer(); if (buf == NULL) return -1;
136:
137: #define READDIR(_dir) \
138: READTRACK(); \
139: memcpy(_dir, buf+12, 2048); \
140: \
141: incTime(); \
142: READTRACK(); \
143: memcpy(_dir+2048, buf+12, 2048);
144:
145: int GetCdromFile(u8 *mdir, u8 *time, s8 *filename) {
146: struct iso_directory_record *dir;
147: char ddir[4096];
148: u8 *buf;
149: int i;
150:
151: i = 0;
152: while (i < 4096) {
153: dir = (struct iso_directory_record*) &mdir[i];
154: if (dir->length[0] == 0) {
155: return -1;
156: }
157: i += dir->length[0];
158:
159: if (dir->flags[0] & 0x2) { // it's a dir
160: if (!strnicmp((char*)&dir->name[0], filename, dir->name_len[0])) {
161: if (filename[dir->name_len[0]] != '\\') continue;
162:
163: filename+= dir->name_len[0] + 1;
164:
165: mmssdd(dir->extent, (char*)time);
166: READDIR(ddir);
167: i = 0;
168: }
169: } else {
170: if (!strnicmp((char*)&dir->name[0], filename, strlen(filename))) {
171: mmssdd(dir->extent, (char*)time);
172: break;
173: }
174: }
175: }
176: return 0;
177: }
178:
179: int LoadCdrom() {
180: EXE_HEADER tmpHead;
181: struct iso_directory_record *dir;
182: u8 time[4],*buf;
183: u8 mdir[4096];
184: s8 exename[256];
185: int i;
186:
187: if (!Config.HLE) {
188: psxRegs.pc = psxRegs.GPR.n.ra;
189: return 0;
190: }
191:
192: time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
193:
194: READTRACK();
195:
196: // skip head and sub, and go to the root directory record
197: dir = (struct iso_directory_record*) &buf[12+156];
198:
199: mmssdd(dir->extent, (char*)time);
200:
201: READDIR(mdir);
202:
203: if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") == -1) {
204: if (GetCdromFile(mdir, time, "PSX.EXE;1") == -1) return -1;
205:
206: READTRACK();
207: }
208: else {
209: READTRACK();
210:
211: sscanf((char*)buf+12, "BOOT = cdrom:\\%s", exename);
212: if (GetCdromFile(mdir, time, exename) == -1) {
213: sscanf((char*)buf+12, "BOOT = cdrom:%s", exename);
214: if (GetCdromFile(mdir, time, exename) == -1) {
215: char *ptr = strstr(buf+12, "cdrom:");
216: for (i=0; i<32; i++) {
217: if (ptr[i] == ' ') continue;
218: if (ptr[i] == '\\') continue;
219: }
220: strcpy(exename, ptr);
221: if (GetCdromFile(mdir, time, exename) == -1)
222: return -1;
223: }
224: }
225:
226: READTRACK();
227: }
228:
229: memcpy(&tmpHead, buf+12, sizeof(EXE_HEADER));
230:
231: #ifdef __MACOSX__
232: swapEXE_HEADER(&tmpHead);
233: #endif
234:
235: psxRegs.pc = tmpHead.pc0;
236: psxRegs.GPR.n.gp = tmpHead.gp0;
237: psxRegs.GPR.n.sp = tmpHead.s_addr;
238: if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00;
239:
240: while (tmpHead.t_size) {
241: void *ptr = (void *)PSXM(tmpHead.t_addr);
242:
243: incTime();
244: READTRACK();
245:
246: if (ptr != NULL) memcpy(ptr, buf+12, 2048);
247:
248: tmpHead.t_size -= 2048;
249: tmpHead.t_addr += 2048;
250: }
251:
252: return 0;
253: }
254:
255: int LoadCdromFile(char *filename, EXE_HEADER *head) {
256: struct iso_directory_record *dir;
257: u8 time[4],*buf;
258: u8 mdir[4096], exename[256];
259: u32 size, addr;
260:
261: sscanf(filename, "cdrom:\\%s", exename);
262:
263: time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
264:
265: READTRACK();
266:
267: // skip head and sub, and go to the root directory record
268: dir = (struct iso_directory_record*) &buf[12+156];
269:
270: mmssdd(dir->extent, (char*)time);
271:
272: READDIR(mdir);
273:
274: if (GetCdromFile(mdir, time, exename) == -1) return -1;
275:
276: READTRACK();
277:
278: memcpy(head, buf+12, sizeof(EXE_HEADER));
279: size = head->t_size;
280: addr = head->t_addr;
281:
282: while (size) {
283: incTime();
284: READTRACK();
285:
286: memcpy((void *)PSXM(addr), buf+12, 2048);
287:
288: size -= 2048;
289: addr += 2048;
290: }
291:
292: return 0;
293: }
294:
295: int CheckCdrom() {
296: struct iso_directory_record *dir;
297: unsigned char time[4],*buf;
298: unsigned char mdir[4096];
299: char exename[256];
300: int i, c;
301:
302: time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
303:
304: READTRACK();
305:
306: strncpy(CdromLabel, buf+52, 11);
307:
308: // skip head and sub, and go to the root directory record
309: dir = (struct iso_directory_record*) &buf[12+156];
310:
311: mmssdd(dir->extent, (char*)time);
312:
313: READDIR(mdir);
314:
315: if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") != -1) {
316: READTRACK();
317:
318: sscanf((char*)buf+12, "BOOT = cdrom:\\%s", exename);
319: if (GetCdromFile(mdir, time, exename) == -1) {
320: sscanf((char*)buf+12, "BOOT = cdrom:%s", exename);
321: if (GetCdromFile(mdir, time, exename) == -1) {
322: char *ptr = strstr(buf+12, "cdrom:");
323: for (i=0; i<32; i++) {
324: if (ptr[i] == ' ') continue;
325: if (ptr[i] == '\\') continue;
326: }
327: strcpy(exename, ptr);
328: if (GetCdromFile(mdir, time, exename) == -1)
329: return 0;
330: }
331: }
332: }
333:
334: i = strlen(exename);
335: if (i >= 2) {
336: if (exename[i - 2] == ';') i-= 2;
337: c = 8; i--;
338: while (i >= 0 && c >= 0) {
339: if (isalnum(exename[i])) CdromId[c--] = exename[i];
340: i--;
341: }
342: }
343:
344: if (Config.PsxAuto) { // autodetect system (pal or ntsc)
345: if (strstr(exename, "ES") != NULL)
346: Config.PsxType = 1; // pal
347: else Config.PsxType = 0; // ntsc
348: }
349: psxUpdateVSyncRate();
350: if (CdromLabel[0] == ' ') {
351: strcpy(CdromLabel, CdromId);
352: }
353: SysPrintf("*PCSX*: CdromLabel: %s\n", CdromLabel);
354: SysPrintf("*PCSX*: CdromId: %s\n", CdromId);
355:
356: return 0;
357: }
358:
359: #define PSX_EXE 1
360: #define CPE_EXE 2
361: #define COFF_EXE 3
362: #define INVALID_EXE 4
363:
364: static int PSXGetFileType(FILE *f) {
365: unsigned long current;
366: unsigned long mybuf[2048];
367: EXE_HEADER *exe_hdr;
368: FILHDR *coff_hdr;
369:
370: current = ftell(f);
371: fseek(f,0L,SEEK_SET);
372: fread(mybuf,2048,1,f);
373: fseek(f,current,SEEK_SET);
374:
375: exe_hdr = (EXE_HEADER *)mybuf;
376: if (memcmp(exe_hdr->id,"PS-X EXE",8)==0)
377: return PSX_EXE;
378:
379: if (mybuf[0]=='C' && mybuf[1]=='P' && mybuf[2]=='E')
380: return CPE_EXE;
381:
382: coff_hdr = (FILHDR *)mybuf;
383: if (coff_hdr->f_magic == 0x0162)
384: return COFF_EXE;
385:
386: return INVALID_EXE;
387: }
388:
389: int Load(char *ExePath) {
390: FILE *tmpFile;
391: EXE_HEADER tmpHead;
392: int type;
393:
394: strncpy(CdromId, "SLUS99999", 9);
395: strncpy(CdromLabel, "SLUS_999.99", 11);
396:
397: tmpFile = fopen(ExePath,"rb");
398: if (tmpFile == NULL) { SysMessage(_("Error opening file: %s"), ExePath); return 0; }
399:
400: type = PSXGetFileType(tmpFile);
401: switch (type) {
402: case PSX_EXE:
403: fread(&tmpHead,sizeof(EXE_HEADER),1,tmpFile);
404: fseek(tmpFile, 0x800, SEEK_SET);
405: fread((void *)PSXM(tmpHead.t_addr), tmpHead.t_size,1,tmpFile);
406: fclose(tmpFile);
407: psxRegs.pc = tmpHead.pc0;
408: psxRegs.GPR.n.gp = tmpHead.gp0;
409: psxRegs.GPR.n.sp = tmpHead.s_addr;
410: if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00;
411: break;
412: case CPE_EXE:
413: SysMessage(_("Pcsx found that you wanna use a CPE file. CPE files not supported"));
414: break;
415: case COFF_EXE:
416: SysMessage(_("Pcsx found that you wanna use a COFF file. COFF files not supported"));
417: break;
418: case INVALID_EXE:
419: SysMessage(_("This file is not a psx file"));
420: break;
421: }
422: return 1;
423: }
424:
425: // STATES
426:
427: const char PcsxHeader[32] = "STv3 PCSX v" PCSX_VERSION;
428:
429: int SaveState(char *file) {
430: gzFile f;
431: GPUFreeze_t *gpufP;
432: SPUFreeze_t *spufP;
433: int Size;
434: unsigned char *pMem;
435:
436: f = gzopen(file, "wb");
437: if (f == NULL) return -1;
438:
439: gzwrite(f, (void*)PcsxHeader, 32);
440:
441: pMem = (unsigned char *) malloc(128*96*3);
442: if (pMem == NULL) return -1;
443: GPU_getScreenPic(pMem);
444: gzwrite(f, pMem, 128*96*3);
445: free(pMem);
446:
447: gzwrite(f, psxM, 0x00200000);
448: gzwrite(f, psxR, 0x00080000);
449: gzwrite(f, psxH, 0x00010000);
450: gzwrite(f, (void*)&psxRegs, sizeof(psxRegs));
451:
452: // gpu
453: gpufP = (GPUFreeze_t *) malloc(sizeof(GPUFreeze_t));
454: gpufP->ulFreezeVersion = 1;
455: GPU_freeze(1, gpufP);
456: gzwrite(f, gpufP, sizeof(GPUFreeze_t));
457: free(gpufP);
458:
459: // spu
460: spufP = (SPUFreeze_t *) malloc(16);
461: SPU_freeze(2, spufP);
462: Size = spufP->Size; gzwrite(f, &Size, 4);
463: free(spufP);
464: spufP = (SPUFreeze_t *) malloc(Size);
465: SPU_freeze(1, spufP);
466: gzwrite(f, spufP, Size);
467: free(spufP);
468:
469: sioFreeze(f, 1);
470: cdrFreeze(f, 1);
471: psxHwFreeze(f, 1);
472: psxRcntFreeze(f, 1);
473: mdecFreeze(f, 1);
474:
475: gzclose(f);
476:
477: return 0;
478: }
479:
480: int LoadState(char *file) {
481: gzFile f;
482: GPUFreeze_t *gpufP;
483: SPUFreeze_t *spufP;
484: int Size;
485: char header[32];
486:
487: f = gzopen(file, "rb");
488: if (f == NULL) return -1;
489:
490: psxCpu->Reset();
491:
492: gzread(f, header, 32);
493:
494: if (strncmp("STv3 PCSX", header, 9)) { gzclose(f); return -1; }
495:
496: gzseek(f, 128*96*3, SEEK_CUR);
497:
498: gzread(f, psxM, 0x00200000);
499: gzread(f, psxR, 0x00080000);
500: gzread(f, psxH, 0x00010000);
501: gzread(f, (void*)&psxRegs, sizeof(psxRegs));
502:
503: // gpu
504: gpufP = (GPUFreeze_t *) malloc (sizeof(GPUFreeze_t));
505: gzread(f, gpufP, sizeof(GPUFreeze_t));
506: GPU_freeze(0, gpufP);
507: free(gpufP);
508:
509: // spu
510: gzread(f, &Size, 4);
511: spufP = (SPUFreeze_t *) malloc (Size);
512: gzread(f, spufP, Size);
513: SPU_freeze(0, spufP);
514: free(spufP);
515:
516: sioFreeze(f, 0);
517: cdrFreeze(f, 0);
518: psxHwFreeze(f, 0);
519: psxRcntFreeze(f, 0);
520: mdecFreeze(f, 0);
521:
522: gzclose(f);
523:
524: return 0;
525: }
526:
527: int CheckState(char *file) {
528: gzFile f;
529: char header[32];
530:
531: f = gzopen(file, "rb");
532: if (f == NULL) return -1;
533:
534: psxCpu->Reset();
535:
536: gzread(f, header, 32);
537:
538: gzclose(f);
539:
540: if (strncmp("STv3 PCSX", header, 9)) return -1;
541:
542: return 0;
543: }
544:
545: // NET Function Helpers
546:
547: int SendPcsxInfo() {
548: if (NET_recvData == NULL || NET_sendData == NULL)
549: return 0;
550:
551: // SysPrintf("SendPcsxInfo\n");
552:
553: NET_sendData(&Config.Xa, sizeof(Config.Xa), PSE_NET_BLOCKING);
554: NET_sendData(&Config.Sio, sizeof(Config.Sio), PSE_NET_BLOCKING);
555: NET_sendData(&Config.SpuIrq, sizeof(Config.SpuIrq), PSE_NET_BLOCKING);
556: NET_sendData(&Config.RCntFix, sizeof(Config.RCntFix), PSE_NET_BLOCKING);
557: NET_sendData(&Config.PsxType, sizeof(Config.PsxType), PSE_NET_BLOCKING);
558: NET_sendData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING);
559:
560: // SysPrintf("Send OK\n");
561:
562: return 0;
563: }
564:
565: int RecvPcsxInfo() {
566: int tmp;
567:
568: if (NET_recvData == NULL || NET_sendData == NULL)
569: return 0;
570:
571: // SysPrintf("RecvPcsxInfo\n");
572:
573: NET_recvData(&Config.Xa, sizeof(Config.Xa), PSE_NET_BLOCKING);
574: NET_recvData(&Config.Sio, sizeof(Config.Sio), PSE_NET_BLOCKING);
575: NET_recvData(&Config.SpuIrq, sizeof(Config.SpuIrq), PSE_NET_BLOCKING);
576: NET_recvData(&Config.RCntFix, sizeof(Config.RCntFix), PSE_NET_BLOCKING);
577: NET_recvData(&Config.PsxType, sizeof(Config.PsxType), PSE_NET_BLOCKING);
578: psxUpdateVSyncRate();
579:
580: SysUpdate();
581:
582: tmp = Config.Cpu;
583: NET_recvData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING);
584: if (tmp != Config.Cpu) {
585: psxCpu->Shutdown();
586: #ifdef PSXREC
587: if (Config.Cpu)
588: psxCpu = &psxInt;
589: else psxCpu = &psxRec;
590: #else
591: psxCpu = &psxInt;
592: #endif
593: if (psxCpu->Init() == -1) {
594: SysClose(); return -1;
595: }
596: psxCpu->Reset();
597: }
598:
599: // SysPrintf("Recv OK\n");
600:
601: return 0;
602: }
603:
604:
605: void __Log(char *fmt, ...) {
606: va_list list;
607: #ifdef LOG_STDOUT
608: char tmp[1024];
609: #endif
610:
611: va_start(list, fmt);
612: #ifndef LOG_STDOUT
613: vfprintf(emuLog, fmt, list);
614: #else
615: vsprintf(tmp, fmt, list);
616: SysPrintf(tmp);
617: #endif
618: va_end(list);
619: }
620:
621: typedef struct {
622: char id[8];
623: char name[64];
624: } LangDef;
625:
626: LangDef sLangs[] = {
627: { "ar", N_("Arabic") },
628: { "ca", N_("Catalan") },
629: { "de", N_("German") },
630: { "el", N_("Greek") },
631: { "en", N_("English") },
632: { "es", N_("Spanish") },
633: { "fr_FR", N_("French") },
634: { "it_IT", N_("Italian") },
635: { "pt", N_("Portuguese") },
636: { "ro", N_("Romanian") },
637: { "ru", N_("Russian") },
638: { "", "" },
639: };
640:
641:
642: char *ParseLang(char *id) {
643: int i=0;
644:
645: while (sLangs[i].id[0] != 0) {
646: if (!strcmp(id, sLangs[i].id))
647: return _(sLangs[i].name);
648: i++;
649: }
650:
651: return id;
652: }
653:
654: /* arch-tag: Matthew Dempsky Wed Oct 15 10:34:43 CST 2003 (Misc.c)
655: */
656:
Html form generated by Xrefactory version 1.6.4 on Fri Dec 12 20:52:56 2003
Trial version.