예제 #1
0
파일: Misc.c 프로젝트: mistydemeo/modizer
PSFINFO *sexy_load(char *path,const char *pathDir,int loop_infinite)
{
	PSFINFO *ret;

        if( psxInit() < 0 ) return(0);
        psxReset();

        sexySPUinit();
        sexySPUopen();

	if(!(ret=LoadPSF(path,0,0,pathDir)))
	{
	 psxShutdown();
	 return(0);
	}
	strcpy(save_path,path);
	strcpy(save_pathDir,pathDir);	

	// Taken from aosdk's eng_psf.c file ...
	// patch illegal Chocobo Dungeon 2 code - CaitSith2 put a jump in the delay slot from a BNE
	// and rely on Highly Experimental's buggy-ass CPU to rescue them.  Verified on real hardware
	// that the initial code is wrong.
	if (ret->game) {
		if (!strcmp(ret->game, "Chocobo Dungeon 2")) {
			if (psxMu32(0xbc090) == (0x0802f040))
			{
			 psxMemWrite32(0xbc090, 0);
			 psxMemWrite32(0xbc094, 0x0802f040);
			 psxMemWrite32(0xbc098, 0);
			}
		}
	}
	
	if(ret->stop==~0) {
		ret->fade=10000; // Infinity ? limit to 3 minutes
		ret->stop=170000;
	}
    
    if (loop_infinite) {
		ret->stop=~0;
	}

	sexysetlength(ret->stop,ret->fade);
	ret->length=ret->stop+ret->fade;

	return(ret);
}
예제 #2
0
파일: Misc.c 프로젝트: mistydemeo/modizer
PSFINFO *sexy_memload(char *addr, int size)
{
	PSFINFO *ret;

        psxInit();
        psxReset();

        sexySPUinit();
        sexySPUopen();

	if(!(ret=memLoadPSF(addr,size,0,0)))
	{
	 psxShutdown();
	 return(0);
	}

	// Taken from aosdk's eng_psf.c file ...
	// patch illegal Chocobo Dungeon 2 code - CaitSith2 put a jump in the delay slot from a BNE
	// and rely on Highly Experimental's buggy-ass CPU to rescue them.  Verified on real hardware
	// that the initial code is wrong.
	if (ret->game) {
		if (!strcmp(ret->game, "Chocobo Dungeon 2")) {
			if (psxMu32(0xbc090) == (0x0802f040))
			{
			 psxMemWrite32(0xbc090, 0);
			 psxMemWrite32(0xbc094, 0x0802f040);
			 psxMemWrite32(0xbc098, 0);
			}
		}
	}
    
	if(ret->stop==~0) ret->fade=0; // Infinity+anything is still infinity...or is it?
	setlength(ret->stop,ret->fade);
	ret->length=ret->stop+ret->fade;

        return(ret);
}
예제 #3
0
static void write_mem32()
{
	memprintf("ari64_write_mem32 %08x, %08x @%08x %u\n", address, word, psxRegs.pc, psxRegs.cycle);
	psxMemWrite32(address, word);
}
예제 #4
0
파일: Misc.c 프로젝트: mistydemeo/modizer
static PSFINFO *LoadPSF(char *path, int level, int type,const char *pathDir) // Type==1 for just info load.
{
    FILE *fp;
    u8 *in,*out=0;
	u8 head[4];
    u32 reserved;
    u32 complen;
    u32 crc32;
    uLongf outlen;
	PSFINFO *psfi=NULL;
	PSFINFO *tmpi=NULL;

    u32 offset, plength;
	
	sexypsf_missing_psflib=0;

#ifdef DEBUG
	fprintf(stderr, "Searching (%s)\n", path);
#endif

	fp=fopen(path,"rb");
    if(!fp) return 0;

	fread(head,1,4,fp);
	if(memcmp(head,"PSF\x01",4)) return(0);

	psfi=malloc(sizeof(PSFINFO));
	if( psfi == NULL ) return(0);
	memset(psfi,0,sizeof(PSFINFO));
    psfi->stop=~0;
    psfi->fade=0;

    fread(&reserved,1,4,fp);
    fread(&complen,1,4,fp);
	complen=BFLIP32(complen);

    fread(&crc32,1,4,fp);
	crc32=BFLIP32(crc32);

#ifdef DEBUG
	fprintf(stderr, "CRC32 = 0x%x\n", crc32);
#endif

    fseek(fp,reserved,SEEK_CUR);

    if(type)
		fseek(fp,complen,SEEK_CUR);
    else {
        in=malloc(complen);
		if( !in ) return(0);
        out=malloc(1024*1024*2+0x800);
		if( !out ) {
			free(in);
			return(0);
		}
        fread(in,1,complen,fp);
        outlen=1024*1024*2;
        uncompress(out,&outlen,in,complen);
        free(in);

		psxRegs->pc = out[0x10] | out[0x11]<<8 | out[0x12]<<16 | out[0x13]<<24;
		psxRegs->GPR.n.gp = out[0x14] | out[0x15]<<8 | out[0x16]<<16 | out[0x17]<<24;
		psxRegs->GPR.n.sp = out[0x30] | out[0x31]<<8 | out[0x32]<<16 | out[0x33]<<24;

        if (psxRegs->GPR.n.sp == 0) psxRegs->GPR.n.sp = 0x801fff00;

#ifdef DEBUG
		fprintf(stderr, "%d Level: PC %x GP %x SP %x\n",
			level, psxRegs->pc, psxRegs->GPR.n.gp, psxRegs->GPR.n.sp);
#endif

 		if(level) {
			offset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24;
			offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
			plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24;

#ifdef DEBUG
			fprintf(stderr, "%d Level: offset %x plength: %d [%d]\n", level, offset, plength, plength);
#endif

			LoadPSXMem(offset,plength,(char*)out+0x800);
			free(out);

			// I don't really know how does this
			// work, but apparently it breaks the
			// loop that makes ff6 and ct to take
			// several seconds to start ...
			if( crc32 == 0xEFDE8EEE || crc32 == 0x545D9F65 )
				psxMemWrite32(0x5A66C, 0);

			// Same as above for Popolocrois
			if( crc32 == 0xF535726 )
				psxMemWrite32(0x5A990, 0);
		}
	}

    {
		u8 tagdata[5];
        if(fread(tagdata,1,5,fp)==5) {
			if(!memcmp(tagdata,"[TAG]",5)) {
				char linebuf[1024];
				while(fgets(linebuf,1024,fp)>0) {
					int x;
					char *key=0,*value=0;

					if(!GetKeyVal(linebuf,&key,&value)) {
						if(key) free(key);
						if(value) free(value);
						continue;
					}

					AddKV(&psfi->tags,key,value);

					if(!level) {
       					static char *yoinks[8]={"title","artist","game","year","genre",
                                  "copyright","psfby","comment"};
						char **yoinks2[8]={&psfi->title,&psfi->artist,&psfi->game,&psfi->year,&psfi->genre,
                                    &psfi->copyright,&psfi->psfby,&psfi->comment};
						for(x=0;x<8;x++)
							if(!strcasecmp(key,yoinks[x]))
								*yoinks2[x]=value;
						if(!strcasecmp(key,"length"))
							psfi->stop=TimeToMS(value);
						else if(!strcasecmp(key,"fade"))
							psfi->fade=TimeToMS(value);
					}

					if(!strcasecmp(key,"_lib") && !type) {
						char *tmpfn;
						/* Load file name "value" from the directory specified in
						   the full path(directory + file name) "path"
						*/
                        //printf("yo %s\nya %s\nyu%s\n",path,value,pathDir);
						tmpfn=GetFileWithBase(path,value,pathDir);
                        //printf("ru: %s\n",tmpfn);
						if(!(tmpi=LoadPSF(tmpfn,level+1,0,pathDir))) {
							//free(key);
							//free(value);
							sexypsf_missing_psflib=1;
							strcpy(sexypsf_psflib_str,value);
							free(tmpfn);
 							if(!level) free(out);
							fclose(fp);
							FreeTags(psfi->tags);
							free(psfi);
							return(0);
						}
						FreeTags(tmpi->tags);
						free(tmpi);
						free(tmpfn);
					}
				}
			}
		}
	}

    fclose(fp);

	/* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff */
    if(!level && !type) {
		offset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24;
		offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
		plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24;

		// TODO - investigate: should i just make
		//        plength = outlen-0x800?

		// Philosoma has an illegal "plength".  *sigh*
		if (plength > (outlen-0x800))
		{
			plength = outlen-0x800;
		}

		if( psfi->game ) {
			// Suikoden Tenmei has an illegal "plength". *sigh sigh*
			if( !strncmp(psfi->game, "Suikoden: Tenmei no Chikai", 26) ) {
				plength = outlen-0x800;
			}

			// Einhänder has an illegal "plength". *sigh sigh sigh*
			if( !strncmp(psfi->game, "Einhänder", 9) ) {
				plength = outlen-0x800;
			}
		}

#ifdef DEBUG
		fprintf(stderr, "%d Level: offset %x plength: %d [%d]\n", level, offset, plength, outlen-2048);
#endif

		LoadPSXMem(offset,plength,(char*)out+0x800);
		free(out);
    }

	if(!type)	/* Load libN */{
		LIBNCACHE *cache;
		PSFTAG *tag;
		unsigned int libncount=0;
		unsigned int cur=0;

		tag=psfi->tags;
		while(tag) {
			if(!strncasecmp(tag->key,"_lib",4) && tag->key[4])
			libncount++;
			tag=tag->next;
		}

		if(libncount) {
			cache=malloc(sizeof(LIBNCACHE)*libncount);

			tag=psfi->tags;
			while(tag) {
				if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) {
					cache[cur].num=atoi(&tag->key[4]);
					cache[cur].value=tag->value;
					cur++;
				}
				tag=tag->next;
			}
			qsort(cache, libncount, sizeof(LIBNCACHE), ccomp);
			for(cur=0;cur<libncount;cur++) {
				u32 ba[3];
				char *tmpfn;

 				if(cache[cur].num < 2) continue;

				ba[0]=psxRegs->pc;
				ba[1]=psxRegs->GPR.n.gp;
				ba[2]=psxRegs->GPR.n.sp;

				/* Load file name "value" from the directory specified in
				the full path(directory + file name) "path"
				*/
				tmpfn=GetFileWithBase(path,cache[cur].value,pathDir);
				if(!(tmpi=LoadPSF(tmpfn,level+1,0,pathDir))) {
					//free(key);
					//free(value);
					//free(tmpfn);
					//fclose(fp);
			        //return(0);
				} else {
                    FreeTags(tmpi->tags);
                    free(tmpi);
                }
                free(tmpfn);


				psxRegs->pc=ba[0];
       			psxRegs->GPR.n.gp=ba[1];
				psxRegs->GPR.n.sp=ba[2];
			}
			free(cache);
		}	// if(libncount)

	}	// if(!type)

	return(psfi);
}
예제 #5
0
파일: Misc.c 프로젝트: mistydemeo/modizer
// LoadPSF for Memory
static PSFINFO *memLoadPSF(char *addr, long size, int level, int type) // Type==1 for just info load.
{
    u8 *in,*out=0;
	u8 head[4];

    u32 reserved;
    u32 complen;
    u32 crc32;
    uLongf outlen;
	PSFINFO *psfi=NULL;
	PSFINFO *tmpi=NULL;
	u32 poffset, plength;
	u32 offset = 0;

	if( addr == NULL || size == 0 ) return(0);

	memread((void*)(head), 4, addr, size, &offset);
	if(memcmp(head,"PSF\x01",4)) return(0);

	psfi=malloc(sizeof(PSFINFO));
	memset(psfi,0,sizeof(PSFINFO));
    psfi->stop=~0;
    psfi->fade=0;

	memread((void*)(&reserved), 4, addr, size, &offset);
	memread((void*)(&complen), 4, addr, size, &offset);
	complen=BFLIP32(complen);

	memread((void*)(&crc32), 4, addr, size, &offset);
	crc32=BFLIP32(crc32);

	memseek(reserved, size, &offset);

	if(type) {
		memseek(complen, size, &offset);
	}
    else {
        in=malloc(complen);
        out=malloc(1024*1024*2+0x800);
		if( !in || !out ) { free(psfi); return (0); }
		memread((void*)(in), complen, addr, size, &offset);

        outlen=1024*1024*2;
        uncompress(out,&outlen,in,complen);
        free(in);

        psxRegs->pc = out[0x10] | out[0x11]<<8 | out[0x12]<<16 | out[0x13]<<24;
		psxRegs->GPR.n.gp = out[0x14] | out[0x15]<<8 | out[0x16]<<16 | out[0x17]<<24;
		psxRegs->GPR.n.sp = out[0x30] | out[0x31]<<8 | out[0x32]<<16 | out[0x33]<<24;

        if (psxRegs->GPR.n.sp == 0) psxRegs->GPR.n.sp = 0x801fff00;

#ifdef DEBUG
		fprintf(stderr, "%d Level: PC %x GP %x SP %x\n",
			level, psxRegs->pc, psxRegs->GPR.n.gp, psxRegs->GPR.n.sp);
#endif

 		if(level) {
			poffset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24;
			poffset &= 0x3fffffff;	// kill any MIPS cache segment indicators
			plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24;

#ifdef DEBUG
			fprintf(stderr, "%d Level: offset %x plength: %d\n", level, poffset, plength);
#endif

			LoadPSXMem(poffset,plength,out+0x800);
			free(out);

			// I don't really know how does this
			// work, but apparently it breaks the
			// loop that makes ff6 and ct to take
			// several seconds to start ...
			if( crc32 == 0xEFDE8EEE || crc32 == 0x545D9F65 )
				psxMemWrite32(0x5A66C, 0);

			// Same as above for Popolocrois and Einhänder
			if( crc32 == 0xF535726 )
				psxMemWrite32(0x5A990, 0);
		}
	}

    {
		u8 tagdata[5];
		if( memread((void*)(tagdata), 5, addr, size, &offset) == 5 ) {
			if(!memcmp(tagdata,"[TAG]",5)) {
				char linebuf[1024];

				while( memfgets(linebuf, 1024, addr, size, &offset)>0 ) {
					int x;
					char *key=0,*value=0;

					if(!GetKeyVal(linebuf,&key,&value)) {
						if(key) free(key);
						if(value) free(value);
						continue;
					}

					AddKV(&psfi->tags,key,value);

					if(!level) {
       					static char *yoinks[8]={"title","artist","game","year","genre",
                                  "copyright","psfby","comment"};
						char **yoinks2[8]={&psfi->title,&psfi->artist,&psfi->game,&psfi->year,&psfi->genre,
                                    &psfi->copyright,&psfi->psfby,&psfi->comment};
						for(x=0;x<8;x++)
							if(!strcasecmp(key,yoinks[x]))
								*yoinks2[x]=value;
						if(!strcasecmp(key,"length"))
							psfi->stop=TimeToMS(value);
						else if(!strcasecmp(key,"fade"))
							psfi->fade=TimeToMS(value);
					}

					if(!strcasecmp(key,"_lib") && !type && __psflibs) {

						/* Search file name "value" from the __psflibs array */
						int n, found = 0;
						for(n=0;n<__psflibs->count;n++)
							if( !strcasecmp(value, __psflibs->libn[n].name) ) {
								found = 1;
								break;
							}

						if(!found || !(tmpi=memLoadPSF(__psflibs->libn[n].addr, __psflibs->libn[n].size, level+1,0))) {
							free(key);
							free(value);
							if(!level) free(out);

							FreeTags(psfi->tags);
							free(psfi);
							return(0);
						}

						FreeTags(tmpi->tags);
						free(tmpi);
					}
				}
			}
		}
	}

	/* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff*/
    if(!level && !type) {
    	poffset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24;
		poffset &= 0x3fffffff;	// kill any MIPS cache segment indicators
		plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24;

		// TODO - investigate: should i just make
		//        plength = outlen-0x800?

		// Philosoma has an illegal "plength".  *sigh*
		if (plength > (outlen-0x800))
		{
			plength = outlen-0x800;
		}

		if( psfi->game ) {
			// Suikoden Tenmei has an illegal "plength". *sigh sigh*
			if( !strncmp(psfi->game, "Suikoden: Tenmei no Chikai", 26) ) {
				plength = outlen-0x800;
			}

			// Einhänder has an illegal "plength". *sigh sigh sigh*
			if( !strncmp(psfi->game, "Einhänder", 9) ) {
				plength = outlen-0x800;
			}
		}

#ifdef DEBUG
		fprintf(stderr, "%d Level: offset %x plength: %d\n", level, poffset, plength);
#endif

		LoadPSXMem(poffset,plength,out+0x800);
		free(out);
    }

	if(!type && __psflibs)	/* Load libN */ {
		LIBNCACHE *cache;
		PSFTAG *tag;
		unsigned int libncount=0;
		unsigned int cur=0;

		tag=psfi->tags;
		while(tag) {
			if(!strncasecmp(tag->key,"_lib",4) && tag->key[4])
			libncount++;
			tag=tag->next;
		}

		if(libncount) {
			cache=malloc(sizeof(LIBNCACHE)*libncount);

			tag=psfi->tags;
			while(tag) {
				if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) {
					cache[cur].num=atoi(&tag->key[4]);
					cache[cur].value=tag->value;
					cur++;
				}
				tag=tag->next;
			}
			qsort(cache, libncount, sizeof(LIBNCACHE), ccomp);
			for(cur=0;cur<libncount;cur++) {
				u32 ba[3];

 				if(cache[cur].num < 2) continue;

				ba[0]=psxRegs->pc;
				ba[1]=psxRegs->GPR.n.gp;
				ba[2]=psxRegs->GPR.n.sp;

				/* Search file name "value" from the __psflibs array */
				int n, found = 0;
				for(n=0;n<__psflibs->count;n++)
					if( !strcasecmp(cache[cur].value, __psflibs->libn[n].name) ) {
						found = 1;
						break;
					}

				if(!found || !(tmpi=memLoadPSF(__psflibs->libn[n].addr,__psflibs->libn[n].size,level+1,0))) {
					//free(key);
					//free(value);
					//free(tmpfn);
					//fclose(fp);
					//return(0);
				}
				FreeTags(tmpi->tags);
				free(tmpi);

				psxRegs->pc=ba[0];
       			psxRegs->GPR.n.gp=ba[1];
				psxRegs->GPR.n.sp=ba[2];
			}
			free(cache);
		}	// if(libncount)

	}	// if(!type)

	return(psfi);
}