From 60c1003845035ad4cd0e9ea50862bad7626faf0e Mon Sep 17 00:00:00 2001 From: Pixel Date: Sat, 21 Sep 2002 18:47:46 +0000 Subject: Added the Pcsx source. --- PcsxSrc/Misc.c | 451 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 451 insertions(+) create mode 100644 PcsxSrc/Misc.c (limited to 'PcsxSrc/Misc.c') diff --git a/PcsxSrc/Misc.c b/PcsxSrc/Misc.c new file mode 100644 index 0000000..d3d4128 --- /dev/null +++ b/PcsxSrc/Misc.c @@ -0,0 +1,451 @@ +/* Pcsx - Pc Psx Emulator + * Copyright (C) 1999-2002 Pcsx Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#ifdef __LINUX__ +#define strnicmp strncasecmp +#endif + +#include "Coff.h" +#include "PsxCommon.h" +#include "plugins.h" + +int Log = 0; + +// LOAD STUFF + +typedef struct { + unsigned char id[8]; + unsigned long text; + unsigned long data; + unsigned long pc0; + unsigned long gp0; + unsigned long t_addr; + unsigned long t_size; + unsigned long d_addr; + unsigned long d_size; + unsigned long b_addr; + unsigned long b_size; + unsigned long S_addr;//normal must a s not a S but error (???) + unsigned long s_size; + unsigned long SavedSP; + unsigned long SavedFP; + unsigned long SavedGP; + unsigned long SavedRA; + unsigned long SavedS0; +} EXE_HEADER; + +#define ISODCL(from, to) (to - from + 1) + +struct iso_directory_record { + char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + char name [1]; +}; + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +void mmssdd( int block, char *p ) + { + int m, s, d; + + block += 150; + m = block / 4500; // minuten + block = block - m * 4500; // minuten rest + s = block / 75; // sekunden + d = block - s * 75; // sekunden rest + + m = ( ( m / 10 ) << 4 ) | m % 10; + s = ( ( s / 10 ) << 4 ) | s % 10; + d = ( ( d / 10 ) << 4 ) | d % 10; + + p[0] = m; + p[1] = s; + p[2] = d; +} + +int GetCdromFile(unsigned char *buf, unsigned char *time, char * filename) { + struct iso_directory_record *dir; + int i; + + i = 0; + while (i < 4096) { + dir = (struct iso_directory_record*) &buf[i]; + if (dir->length[0] == 0) { + return -1; + } + i += dir->length[0]; + + if (!strnicmp((char*)&dir->name[0],filename,strlen(filename))) { + mmssdd(*((int *)dir->extent), (char*)time); + break; + } + } + return 0; +} + +#define incTime() \ + time[0] = btoi(time[0]); time[1] = btoi(time[1]); time[2] = btoi(time[2]); \ + time[2]++; \ + if(time[2] == 75) { \ + time[2] = 0; \ + time[1]++; \ + if (time[1] == 60) { \ + time[1] = 0; \ + time[0]++; \ + } \ + } \ + time[0] = itob(time[0]); time[1] = itob(time[1]); time[2] = itob(time[2]); + +int LoadCdrom() { + EXE_HEADER tmpHead; + struct iso_directory_record *dir; + unsigned char time[4],*buf; + unsigned char mdir[4096]; + char exename[256]; + int i; + + if (!Config.HLE) { + psxRegs.pc = psxRegs.GPR.n.ra; + return 0; + } + + time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10); + + if (CDR_readTrack(time) == -1) return -1; + buf = CDR_getBuffer(); + + // skip head and sub, and go to the root directory record + dir = (struct iso_directory_record*) &buf[12+156]; + + mmssdd(*((int *)dir->extent), (char*)time); + + if (CDR_readTrack(time) == -1) return -1; + buf = CDR_getBuffer(); + memcpy(mdir, buf+12, 2048); + + incTime(); + if (CDR_readTrack(time) == -1) return -1; + buf = CDR_getBuffer(); + memcpy(mdir+2048, buf+12, 2048); + + if (GetCdromFile(mdir, time, "SYSTEM.CNF") == -1) { + if (GetCdromFile(mdir, time, "PSX.EXE") == -1) return -1; + + if (CDR_readTrack(time) == -1) return -1; + buf = CDR_getBuffer(); + } + else { + if (CDR_readTrack(time) == -1) return -1; + buf = CDR_getBuffer(); + + sscanf((char*)buf+12, "BOOT = cdrom:\\%s;2", exename); + if (GetCdromFile(mdir, time, exename) == -1) { + sscanf((char*)buf+12, "BOOT = cdrom:%s;2", exename); + if (GetCdromFile(mdir, time, exename) == -1) { + char *ptr = strstr(buf+12, "cdrom:"); + for (i=0; i<32; i++) { + if (ptr[i] == ' ') continue; + if (ptr[i] == '\\') continue; + } + strcpy(exename, ptr); + if (GetCdromFile(mdir, time, exename) == -1) + return -1; + } + } + + if (CDR_readTrack(time) == -1) return -1; + buf = CDR_getBuffer(); + } + + memcpy(&tmpHead, buf+12, sizeof(EXE_HEADER)); + + psxRegs.pc = tmpHead.pc0; + psxRegs.GPR.n.gp = tmpHead.gp0; + psxRegs.GPR.n.sp = tmpHead.S_addr; + if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; + + while (tmpHead.t_size) { + incTime(); + if (CDR_readTrack(time) == -1) return -1; + buf = CDR_getBuffer(); + + memcpy((void *)PSXM(tmpHead.t_addr), buf+12, 2048); + + tmpHead.t_size -= 2048; + tmpHead.t_addr += 2048; + } + + return 0; +} + +int CheckCdrom() { + struct iso_directory_record *dir; + unsigned char time[4],*buf; + unsigned char mdir[4096]; + char exename[256]; + int i; + + time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10); + + if (CDR_readTrack(time) == -1) return -1; + buf = CDR_getBuffer(); + + strncpy(CdromId, buf+52, 10); + + // skip head and sub, and go to the root directory record + dir = (struct iso_directory_record*) &buf[12+156]; + + mmssdd(*((int *)dir->extent), (char*)time); + + if (CDR_readTrack(time) == -1) return 0; + buf = CDR_getBuffer(); + memcpy(mdir, buf+12, 2048); + + incTime(); + if (CDR_readTrack(time) == -1) return 0; + buf = CDR_getBuffer(); + memcpy(mdir+2048, buf+12, 2048); + + if (GetCdromFile(mdir, time, "SYSTEM.CNF") != -1) { + if (CDR_readTrack(time) == -1) return 0; + buf = CDR_getBuffer(); + + sscanf((char*)buf+12, "BOOT = cdrom:\\%s;2", exename); + if (GetCdromFile(mdir, time, exename) == -1) { + sscanf((char*)buf+12, "BOOT = cdrom:%s;2", exename); + if (GetCdromFile(mdir, time, exename) == -1) { + char *ptr = strstr(buf+12, "cdrom:"); + for (i=0; i<32; i++) { + if (ptr[i] == ' ') continue; + if (ptr[i] == '\\') continue; + } + strcpy(exename, ptr); + if (GetCdromFile(mdir, time, exename) == -1) + return 0; + } + } + } + + if (Config.PsxAuto) { // autodetect system (pal or ntsc) + if (strstr(exename, "ES") != NULL) + Config.PsxType = 1; // pal + else Config.PsxType = 0; // ntsc + } + UpdateVSyncRate(); + + return 0; +} + +#define PSX_EXE 1 +#define CPE_EXE 2 +#define COFF_EXE 3 +#define INVALID_EXE 4 + +static int PSXGetFileType(FILE *f) { + unsigned long current; + unsigned long mybuf[2048]; + EXE_HEADER *exe_hdr; + FILHDR *coff_hdr; + + current = ftell(f); + fseek(f,0L,SEEK_SET); + fread(mybuf,2048,1,f); + fseek(f,current,SEEK_SET); + + exe_hdr = (EXE_HEADER *)mybuf; + if (memcmp(exe_hdr->id,"PS-X EXE",8)==0) + return PSX_EXE; + + if (mybuf[0]=='C' && mybuf[1]=='P' && mybuf[2]=='E') + return CPE_EXE; + + coff_hdr = (FILHDR *)mybuf; + if (coff_hdr->f_magic == 0x0162) + return COFF_EXE; + + return INVALID_EXE; +} + +int Load(char *ExePath) { + FILE *tmpFile; + EXE_HEADER tmpHead; + int type; + + strcpy(CdromId, "SLUS_999.99"); + + tmpFile = fopen(ExePath,"rb"); + if (tmpFile == NULL) { SysMessage("Error opening file: %s", ExePath); return 0; } + + type = PSXGetFileType(tmpFile); + switch (type) { + case PSX_EXE: + fread(&tmpHead,sizeof(EXE_HEADER),1,tmpFile); + fseek(tmpFile, 0x800, SEEK_SET); + fread((void *)PSXM(tmpHead.t_addr), tmpHead.t_size,1,tmpFile); + fclose(tmpFile); + psxRegs.pc = tmpHead.pc0; + psxRegs.GPR.n.gp = tmpHead.gp0; + psxRegs.GPR.n.sp = tmpHead.S_addr; + if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; + break; + case CPE_EXE: + SysMessage("Pcsx found that you wanna use a CPE file. CPE files not support yet"); + break; + case COFF_EXE: + SysMessage("Pcsx found that you wanna use a COFF file.COFF files not support yet"); + break; + case INVALID_EXE: + SysMessage("This file is not a psx file"); + break; + } + return 1; +} + +// STATES + +static const char PcsxHeader[32] = "STv3 PCSX v" PCSX_VERSION; + +int SaveState(char *file) { + gzFile f; + GPUFreeze_t *gpufP; + SPUFreeze_t *spufP; + int Size; + unsigned char *pMem; + + f = gzopen(file, "wb"); + if (f == NULL) return -1; + + gzwrite(f, (void*)PcsxHeader, 32); + + pMem = (unsigned char *) malloc(128*96*3); + if (pMem == NULL) return -1; + GPU_getScreenPic(pMem); + gzwrite(f, pMem, 128*96*3); + free(pMem); + + gzwrite(f, psxM, 0x00200000); + if (Config.HLE) psxBiosFreeze(1); + gzwrite(f, psxR, 0x00080000); + gzwrite(f, psxH, 0x00010000); + gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); + + // gpu + gpufP = (GPUFreeze_t *) malloc(sizeof(GPUFreeze_t)); + gpufP->ulFreezeVersion = 1; + GPU_freeze(1, gpufP); + gzwrite(f, gpufP, sizeof(GPUFreeze_t)); + free(gpufP); + + // spu + spufP = (SPUFreeze_t *) malloc(16); + SPU_freeze(2, spufP); + Size = spufP->Size; gzwrite(f, &Size, 4); + free(spufP); + spufP = (SPUFreeze_t *) malloc(Size); + SPU_freeze(1, spufP); + gzwrite(f, spufP, Size); + free(spufP); + + sioFreeze(f, 1); + cdrFreeze(f, 1); + psxHwFreeze(f, 1); + psxRcntFreeze(f, 1); + mdecFreeze(f, 1); + + gzclose(f); + + return 0; +} + + +int LoadState(char *file) { + gzFile f; + GPUFreeze_t *gpufP; + SPUFreeze_t *spufP; + int Size; + char header[32]; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + psxCpu->Reset(); + + gzread(f, header, 32); + + if (strncmp("STv3 PCSX", header, 9)) return -1; + + gzseek(f, 128*96*3, SEEK_CUR); + + gzread(f, psxM, 0x00200000); + gzread(f, psxR, 0x00080000); + if (Config.HLE) psxBiosFreeze(0); + gzread(f, psxH, 0x00010000); + gzread(f, (void*)&psxRegs, sizeof(psxRegs)); + + // gpu + gpufP = (GPUFreeze_t *) malloc (sizeof(GPUFreeze_t)); + gzread(f, gpufP, sizeof(GPUFreeze_t)); + GPU_freeze(0, gpufP); + free(gpufP); + + // spu + gzread(f, &Size, 4); + spufP = (SPUFreeze_t *) malloc (Size); + gzread(f, spufP, Size); + SPU_freeze(0, spufP); + free(spufP); + + sioFreeze(f, 0); + cdrFreeze(f, 0); + psxHwFreeze(f, 0); + psxRcntFreeze(f, 0); + mdecFreeze(f, 0); + + gzclose(f); + + return 0; +} + +void __Log(char *fmt, ...) { + va_list list; +#ifdef LOG_STDOUT + char tmp[1024]; +#endif + + va_start(list, fmt); +#ifndef LOG_STDOUT + vfprintf(emuLog, fmt, list); +#else + vsprintf(tmp, fmt, list); + SysPrintf(tmp); +#endif + va_end(list); +} \ No newline at end of file -- cgit v1.2.3