USFPlayer(const std::string &fileName) { usf_state = new usf_loader_state; usf_state->emu_state = malloc( usf_get_state_size() ); usf_clear( usf_state->emu_state ); sample_rate = 0; char temp[fileName.length()+1]; strcpy(temp, fileName.c_str()); LOGD("Trying to load USF %s", string(temp)); if ( psf_load( temp, &psf_file_system, 0x21, usf_loader, usf_state, usf_info, usf_state, 1 ) < 0 ) throw player_exception(); usf_set_hle_audio(usf_state->emu_state, 1); PSFFile psf { fileName }; if(psf.valid()) { auto &tags = psf.tags(); int seconds = psf.songLength(); setMeta("composer", tags["artist"], "sub_title", tags["title"], "game", tags["game"], "format", "Nintendo 64", "length", seconds ); } usf_set_compare( usf_state->emu_state, usf_state->enable_compare ); usf_set_fifo_full( usf_state->emu_state, usf_state->enable_fifo_full ); const char *err = usf_render(usf_state->emu_state, 0, 0, &sample_rate); if(err) LOGD("ERROR %s", err); LOGD("######### RATE %d", sample_rate); resampler_init(); for(auto &r : resampler) { r = resampler_create(); resampler_set_quality(r, RESAMPLER_QUALITY_CUBIC); resampler_set_rate(r, (float)sample_rate / 44100.0); //resampler_set_rate(r, 44100.0 / (float)sample_rate); resampler_clear(r); } }
/* ** Read the EXE from a PSF file ** ** Returns the error message, or NULL on success */ const wchar_t* GSFLoader::psf_read_exe( RawFile* file, unsigned char*& exebuffer, size_t& exebuffersize ) { PSFFile psf; if (!psf.Load(file)) return psf.GetError(); // search exclusively for _lib tag, and if found, perform a recursive load const wchar_t* psflibError = load_psf_libs(psf, file, exebuffer, exebuffersize); if (psflibError != NULL) return psflibError; DataSeg* gsfExeHeadSeg; if (!psf.ReadExeDataSeg(gsfExeHeadSeg, 0x0c, 0)) return psf.GetError(); //uint32_t gsfEntryPoint = gsfExeHeadSeg->GetWord(0x00); uint32_t gsfRomStart = gsfExeHeadSeg->GetWord(0x04) & 0x01FFFFFF; uint32_t gsfRomRegion = gsfExeHeadSeg->GetWord(0x04) & 0xFE000000; uint32_t gsfRomSize = gsfExeHeadSeg->GetWord(0x08); delete gsfExeHeadSeg; if (gsfRomRegion != 0x08000000) return L"GSF ROM offset points to unsupported region. (multi-boot GSF is not supported yet)"; if (gsfRomStart + gsfRomSize > exebuffersize || (exebuffer == NULL && exebuffersize == 0)) return L"GSF ROM section start and/or size values are corrupt."; if (exebuffer == NULL) { exebuffersize = gsfRomStart + gsfRomSize; exebuffer = new uint8_t[exebuffersize]; if (exebuffer == NULL) { return L"GSF ROM memory allocation error."; } memset(exebuffer, 0, exebuffersize); } if (!psf.ReadExe(exebuffer + gsfRomStart, gsfRomSize, 0x0c)) return L"Decompression failed"; // set tags to RawFile if (psf.tags.count("title") != 0) { file->tag.title = string2wstring(psf.tags["title"]); } if (psf.tags.count("artist") != 0) { file->tag.artist = string2wstring(psf.tags["artist"]); } if (psf.tags.count("game") != 0) { file->tag.album = string2wstring(psf.tags["game"]); } if (psf.tags.count("comment") != 0) { file->tag.comment = string2wstring(psf.tags["comment"]); } return NULL; }
/* ** Read the EXE from a PSF file ** ** Returns the error message, or NULL on success */ const wchar_t* NCSFLoader::psf_read_exe( RawFile* file, unsigned char*& exebuffer, size_t& exebuffersize ) { PSFFile psf; if (!psf.Load(file)) return psf.GetError(); // search exclusively for _lib tag, and if found, perform a recursive load const wchar_t* psflibError = load_psf_libs(psf, file, exebuffer, exebuffersize); if (psflibError != NULL) return psflibError; DataSeg* ncsfExeHeadSeg; if (!psf.ReadExeDataSeg(ncsfExeHeadSeg, 0x0c, 0)) return psf.GetError(); uint32_t ncsfRomStart = 0; uint32_t ncsfRomSize = ncsfExeHeadSeg->GetWord(0x08); delete ncsfExeHeadSeg; if (ncsfRomStart + ncsfRomSize > exebuffersize || (exebuffer == NULL && exebuffersize == 0)) return L"NCSF ROM section start and/or size values are likely corrupt."; if (exebuffer == NULL) { exebuffersize = ncsfRomStart + ncsfRomSize; exebuffer = new uint8_t[exebuffersize]; if (exebuffer == NULL) { return L"NCSF ROM memory allocation error."; } memset(exebuffer, 0, exebuffersize); } if (!psf.ReadExe(exebuffer + ncsfRomStart, ncsfRomSize, 0)) return L"Decompression failed"; // set tags to RawFile if (psf.tags.count("title") != 0) { file->tag.title = string2wstring(psf.tags["title"]); } if (psf.tags.count("artist") != 0) { file->tag.artist = string2wstring(psf.tags["artist"]); } if (psf.tags.count("game") != 0) { file->tag.album = string2wstring(psf.tags["game"]); } if (psf.tags.count("comment") != 0) { file->tag.comment = string2wstring(psf.tags["comment"]); } return NULL; }
/* ** Read the EXE from a PSF file ** ** Returns the error message, or NULL on success */ const wchar_t* SNSFLoader::psf_read_exe( RawFile* file, unsigned char*& exebuffer, size_t& exebuffersize ) { PSFFile psf; if (!psf.Load(file)) return psf.GetError(); // search exclusively for _lib tag, and if found, perform a recursive load const wchar_t* psflibError = load_psf_libs(psf, file, exebuffer, exebuffersize); if (psflibError != NULL) return psflibError; DataSeg* snsfExeHeadSeg; if (!psf.ReadExeDataSeg(snsfExeHeadSeg, 0x08, 0)) return psf.GetError(); uint32_t snsfRomStart = snsfExeHeadSeg->GetWord(0x00); uint32_t snsfRomSize = snsfExeHeadSeg->GetWord(0x04); delete snsfExeHeadSeg; if (snsfRomStart + snsfRomSize > exebuffersize || (exebuffer == NULL && exebuffersize == 0)) return L"SNSF ROM section start and/or size values are likely corrupt."; if (exebuffer == NULL) { exebuffersize = snsfRomStart + snsfRomSize; exebuffer = new BYTE[exebuffersize]; if (exebuffer == NULL) { return L"SNSF ROM memory allocation error."; } memset(exebuffer, 0, exebuffersize); } if (!psf.ReadExe(exebuffer + snsfRomStart, snsfRomSize, 0x08)) return L"Decompression failed"; return NULL; }
/* ** Read the EXE from a PSF file ** ** Returns the error message, or NULL on success */ const wchar_t* PSF1Loader::psf_read_exe( RawFile* file, unsigned char *exebuffer, unsigned exebuffersize ) { UINT fileSize = file->size(); if (fileSize >= 0x10000000) return L"PSF too large - likely corrupt"; PSFFile psf; if (!psf.Load(file)) return psf.GetError(); // Now we get into the stuff related to recursive psflib loading. // the actual size of the header is 0x800, but we only need the first 0x20 for the text section offset/size DataSeg* psfExeHeadSeg; if (!psf.ReadExeDataSeg(psfExeHeadSeg, 0x20, 0)) return psf.GetError(); uint32_t textSectionStart = psfExeHeadSeg->GetWord(0x18) & 0x3FFFFF; uint32_t textSectionSize = psfExeHeadSeg->GetWord(0x1C); delete psfExeHeadSeg; if (textSectionStart + textSectionSize > 0x200000) return L"Text section start and/or size values are corrupt in PSX-EXE header."; // search exclusively for _lib tag, and if found, perform a recursive load const wchar_t* psflibError = load_psf_libs(psf, file, exebuffer, exebuffersize); if (psflibError != NULL) return psflibError; if (!psf.ReadExe(exebuffer + textSectionStart, textSectionSize, 0x800)) return L"Decompression failed"; return NULL; }