upse_psf_t *upse_load(char *path, upse_iofuncs_t * iofuncs) { upse_psf_t *ret; _ENTER; psxInit(); psxReset(); SPUinit(); SPUopen(); if (!(ret = _upse_load(path, 0, 0, iofuncs))) { psxShutdown(); return NULL; } if (ret->stop == (u32) ~ 0) ret->fade = 0; SPUsetlength(ret->stop, ret->fade); ret->length = ret->stop + ret->fade; _LEAVE; return ret; }
int32 psf_command(int32 command, int32 parameter) { union cpuinfo mipsinfo; uint32 lengthMS, fadeMS; switch (command) { case COMMAND_RESTART: SPUclose(); memcpy(psx_ram, initial_ram, 2*1024*1024); memcpy(psx_scratch, initial_scratch, 0x400); mips_init(); mips_reset(NULL); psx_hw_init(); SPUinit(); SPUopen(); lengthMS = psfTimeToMS(c->inf_length); fadeMS = psfTimeToMS(c->inf_fade); if (lengthMS == 0) { lengthMS = ~0; } setlength(lengthMS, fadeMS); mipsinfo.i = initialPC; mips_set_info(CPUINFO_INT_PC, &mipsinfo); mipsinfo.i = initialSP; mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo); mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo); mipsinfo.i = initialGP; mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo); mips_execute(5000); return AO_SUCCESS; } return AO_FAIL; }
PSFINFO *sexy_load(char *path) { PSFINFO *ret; psxInit(); psxReset(); SPUinit(); SPUopen(); if(!(ret=LoadPSF(path,0,0))) { psxShutdown(); return(0); } if(ret->stop==~0) ret->fade=0; // Infinity+anything is still infinity...or is it? SPUsetlength(ret->stop,ret->fade); ret->length=ret->stop+ret->fade; return(ret); }
long ZN_SPUopen(void) { iZincEmu=1; SPUinit(); return SPUopen(); }
long CALLBACK ZN_SPUopen(HWND hW) { iZincEmu=1; SPUinit(); return SPUopen(hW); }
int32_t spx_start(uint8_t *buffer, uint32_t length) { int i; uint16_t reg; if (strncmp((char *)buffer, "SPU", 3) && strncmp((char *)buffer, "SPX", 3)) { return AO_FAIL; } start_of_file = buffer; SPUinit(); SPUopen(); setlength(~0, 0); // upload the SPU RAM image SPUinjectRAMImage((unsigned short *)&buffer[0]); // apply the register image for (i = 0; i < 512; i += 2) { reg = buffer[0x80000+i] | buffer[0x80000+i+1]<<8; SPUwriteRegister((i/2)+0x1f801c00, reg); } old_fmt = 1; if ((buffer[0x80200] != 0x44) || (buffer[0x80201] != 0xac) || (buffer[0x80202] != 0x00) || (buffer[0x80203] != 0x00)) { old_fmt = 0; } if (old_fmt) { num_events = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24; if (((num_events * 12) + 0x80208) > length) { old_fmt = 0; } else { cur_tick = 0; } } if (!old_fmt) { end_tick = buffer[0x80200] | buffer[0x80201]<<8 | buffer[0x80202]<<16 | buffer[0x80203]<<24; cur_tick = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24; next_tick = cur_tick; } song_ptr = &buffer[0x80208]; cur_event = 0; strncpy((char *)&buffer[4], name, 128); strncpy((char *)&buffer[0x44], song, 128); strncpy((char *)&buffer[0x84], company, 128); return AO_SUCCESS; }
int32 psf_start(uint8 *buffer, uint32 length) { uint8 *file, *lib_decoded, *lib_raw_file, *alib_decoded; uint32 offset, plength, PC, SP, GP, lengthMS, fadeMS; uint64 file_len, lib_len, lib_raw_length, alib_len; corlett_t *lib; int i; union cpuinfo mipsinfo; // clear PSX work RAM before we start scribbling in it memset(psx_ram, 0, 2*1024*1024); // printf("Length = %d\n", length); // Decode the current GSF if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS) { return AO_FAIL; } // printf("file_len %d reserve %d\n", file_len, c->res_size); // check for PSX EXE signature if (strncmp((char *)file, "PS-X EXE", 8)) { return AO_FAIL; } #if DEBUG_LOADER offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24; printf("Text section start: %x\n", offset); offset = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24; printf("Text section size: %x\n", offset); printf("Region: [%s]\n", &file[0x4c]); printf("refresh: [%s]\n", c->inf_refresh); #endif if (c->inf_refresh[0] == '5') { psf_refresh = 50; } if (c->inf_refresh[0] == '6') { psf_refresh = 60; } PC = file[0x10] | file[0x11]<<8 | file[0x12]<<16 | file[0x13]<<24; GP = file[0x14] | file[0x15]<<8 | file[0x16]<<16 | file[0x17]<<24; SP = file[0x30] | file[0x31]<<8 | file[0x32]<<16 | file[0x33]<<24; #if DEBUG_LOADER printf("Top level: PC %x GP %x SP %x\n", PC, GP, SP); #endif // Get the library file, if any if (c->lib[0] != 0) { uint64 tmp_length; #if DEBUG_LOADER printf("Loading library: %s\n", c->lib); #endif if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS) { return AO_FAIL; } lib_raw_length = tmp_length; if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS) { free(lib_raw_file); return AO_FAIL; } // Free up raw file free(lib_raw_file); if (strncmp((char *)lib_decoded, "PS-X EXE", 8)) { printf("Major error! PSF was OK, but referenced library is not!\n"); free(lib); return AO_FAIL; } #if DEBUG_LOADER offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24; printf("Text section start: %x\n", offset); offset = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24; printf("Text section size: %x\n", offset); printf("Region: [%s]\n", &lib_decoded[0x4c]); printf("refresh: [%s]\n", lib->inf_refresh); #endif // if the original file had no refresh tag, give the lib a shot if (psf_refresh == -1) { if (lib->inf_refresh[0] == '5') { psf_refresh = 50; } if (lib->inf_refresh[0] == '6') { psf_refresh = 60; } } PC = lib_decoded[0x10] | lib_decoded[0x11]<<8 | lib_decoded[0x12]<<16 | lib_decoded[0x13]<<24; GP = lib_decoded[0x14] | lib_decoded[0x15]<<8 | lib_decoded[0x16]<<16 | lib_decoded[0x17]<<24; SP = lib_decoded[0x30] | lib_decoded[0x31]<<8 | lib_decoded[0x32]<<16 | lib_decoded[0x33]<<24; #if DEBUG_LOADER printf("Library: PC %x GP %x SP %x\n", PC, GP, SP); #endif // now patch the file into RAM offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24; offset &= 0x3fffffff; // kill any MIPS cache segment indicators plength = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24; #if DEBUG_LOADER printf("library offset: %x plength: %d\n", offset, plength); #endif memcpy(&psx_ram[offset/4], lib_decoded+2048, plength); // Dispose the corlett structure for the lib - we don't use it free(lib); } // now patch the main file into RAM OVER the libraries (but not the aux lib) offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24; offset &= 0x3fffffff; // kill any MIPS cache segment indicators plength = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24; // Philosoma has an illegal "plength". *sigh* if (plength > (file_len-2048)) { plength = file_len-2048; } memcpy(&psx_ram[offset/4], file+2048, plength); // load any auxiliary libraries now for (i = 0; i < 8; i++) { if (c->libaux[i][0] != 0) { uint64 tmp_length; #if DEBUG_LOADER printf("Loading aux library: %s\n", c->libaux[i]); #endif if (ao_get_lib(c->libaux[i], &lib_raw_file, &tmp_length) != AO_SUCCESS) { return AO_FAIL; } lib_raw_length = tmp_length; if (corlett_decode(lib_raw_file, lib_raw_length, &alib_decoded, &alib_len, &lib) != AO_SUCCESS) { free(lib_raw_file); return AO_FAIL; } // Free up raw file free(lib_raw_file); if (strncmp((char *)alib_decoded, "PS-X EXE", 8)) { printf("Major error! PSF was OK, but referenced library is not!\n"); free(lib); return AO_FAIL; } #if DEBUG_LOADER offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24; printf("Text section start: %x\n", offset); offset = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24; printf("Text section size: %x\n", offset); printf("Region: [%s]\n", &alib_decoded[0x4c]); #endif // now patch the file into RAM offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24; offset &= 0x3fffffff; // kill any MIPS cache segment indicators plength = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24; memcpy(&psx_ram[offset/4], alib_decoded+2048, plength); // Dispose the corlett structure for the lib - we don't use it free(lib); } } free(file); // free(lib_decoded); // Finally, set psfby tag strcpy(psfby, "n/a"); if (c) { int i; for (i = 0; i < MAX_UNKNOWN_TAGS; i++) { if (!strcasecmp(c->tag_name[i], "psfby")) strcpy(psfby, c->tag_data[i]); } } mips_init(); mips_reset(NULL); // set the initial PC, SP, GP #if DEBUG_LOADER printf("Initial PC %x, GP %x, SP %x\n", PC, GP, SP); printf("Refresh = %d\n", psf_refresh); #endif mipsinfo.i = PC; mips_set_info(CPUINFO_INT_PC, &mipsinfo); // set some reasonable default for the stack if (SP == 0) { SP = 0x801fff00; } mipsinfo.i = SP; mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo); mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo); mipsinfo.i = GP; mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo); #if DEBUG_LOADER && 1 { FILE *f; f = fopen("psxram.bin", "wb"); fwrite(psx_ram, 2*1024*1024, 1, f); fclose(f); } #endif psx_hw_init(); SPUinit(); SPUopen(); lengthMS = psfTimeToMS(c->inf_length); fadeMS = psfTimeToMS(c->inf_fade); #if DEBUG_LOADER printf("length %d fade %d\n", lengthMS, fadeMS); #endif if (lengthMS == 0) { lengthMS = ~0; } setlength(lengthMS, fadeMS); // 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 (c->inf_game) { if (!strcmp(c->inf_game, "Chocobo Dungeon 2")) { if (psx_ram[0xbc090/4] == LE32(0x0802f040)) { psx_ram[0xbc090/4] = LE32(0); psx_ram[0xbc094/4] = LE32(0x0802f040); psx_ram[0xbc098/4] = LE32(0); } } } // psx_ram[0x118b8/4] = LE32(0); // crash 2 hack // backup the initial state for restart memcpy(initial_ram, psx_ram, 2*1024*1024); memcpy(initial_scratch, psx_scratch, 0x400); initialPC = PC; initialGP = GP; initialSP = SP; mips_execute(5000); return AO_SUCCESS; }