int he_init (DB_fileinfo_t *_info, const char * uri) { he_info_t *info = (he_info_t *)_info; info->path = strdup( uri ); // int psf_version = psf_load( uri, &psf_file_system, 0, 0, 0, 0, 0, 0 ); requiredLib[0]= 0; int psf_version = psf_load( uri, &psf_file_system, 0, 0, 0, psf_lib_meta, 0, 0 ); if (psf_version < 0) { trace ("he: failed to open %s\n", uri); return -1; } if (strlen(requiredLib)) { // lib must be loaded here or else the psf loading will fail.. // (enter "retry-mode" if something is missing) // make sure the file will be available in the FS when the song asks for it later.. char tmpFileName[PATH_MAX]; char *p= strrchr(uri, '/'); int pathlen= p?(p-uri+1):0; memcpy(tmpFileName, uri, pathlen); snprintf(tmpFileName+pathlen, PATH_MAX-pathlen, "%s", requiredLib); int r= psx_request_file(tmpFileName); // trigger load & check if ready if (r <0) { return -1; // file not ready } } char he_bios_path[PATH_MAX]; memset(he_bios_path, 0, PATH_MAX); // set specific BIOS here if needed he_install_bios(he_bios_path); psx_init(); struct psf_load_state state; memset( &state, 0, sizeof(state) ); state.first = 1; state.emu= set_emu(info, malloc( psx_get_state_size( psf_version ) )); if ( !state.emu ) { trace( "he: out of memory\n" ); return -1; } psx_clear_state( state.emu, psf_version ); if ( psf_version == 1 ) { if ( psf_load( uri, &psf_file_system, 1, psf1_load, &state, psf_info_meta, &state, 0 ) <= 0 ) { trace( "he: invalid PSF file\n" ); return -1; } } else if ( psf_version == 2 ) { info->psf2fs = psf2fs_create(); if ( !info->psf2fs ) { trace( "he: out of memory\n" ); return -1; } if ( psf_load( uri, &psf_file_system, 2, psf2fs_load_callback, info->psf2fs, psf_info_meta, &state, 0 ) <= 0 ) { trace( "he: invalid PSF file\n" ); return -1; } psx_set_readfile( info->emu, virtual_readfile, info->psf2fs ); } if ( state.refresh ) psx_set_refresh( info->emu, state.refresh ); int tag_song_ms = state.tag_song_ms; int tag_fade_ms = state.tag_fade_ms; if (!tag_song_ms) { tag_song_ms = ( 2 * 60 + 50 ) * 1000; tag_fade_ms = 10 * 1000; } const int srate = psf_version == 2 ? 48000 : 44100; info->samples_played = 0; info->samples_to_play = (uint64_t)tag_song_ms * (uint64_t)srate / 1000; info->samples_to_fade = (uint64_t)tag_fade_ms * (uint64_t)srate / 1000; _info->fmt.channels = 2; _info->fmt.bps = 16; _info->fmt.samplerate = srate; _info->readpos = 0; free_tags(state.tags); return 0; }
void AopsfWrapper::open() { if (this->psfHandle != nullptr) { return; } this->psfVersion = psf_load(this->Filename.c_str(), &stdio_callbacks, 0, // psf files might have version 1 or 2, we dont know, so probe for version with 0 nullptr, nullptr, nullptr, nullptr, 0); if (this->psfVersion <= 0) { THROW_RUNTIME_ERROR("psf_load failed on file \"" << this->Filename << ")\""); } if (this->psfVersion != 1 && this->psfVersion != 2) { THROW_RUNTIME_ERROR("this is neither a PSF1 nor a PSF2 file \"" << this->Filename << ")\""); } else { CLOG(LogLevel_t::Debug, "'" << this->Filename << "' seems to be a PSF" << this->psfVersion); } this->psfHandle = reinterpret_cast<PSX_STATE *>(new unsigned char[psx_get_state_size(this->psfVersion)]); memset(this->psfHandle, 0, psx_get_state_size(this->psfVersion)); this->Format.SampleRate = this->psfVersion == 2 ? 48000 : 44100; psx_register_console_callback(this->psfHandle, &AopsfWrapper::console_log, this); if (this->psfVersion == 1) { // we ask psflib to load that file using OUR loader method int ret = psf_load(this->Filename.c_str(), &stdio_callbacks, this->psfVersion, &AopsfWrapper::psf_loader, // callback function to call on loading this psf file this, // context, i.e. pointer to the struct we place the psf file in &AopsfWrapper::psf_info, // callback function to call for info on this psf file this, // info context 1 // yes we want nested info tags ); if (ret != this->psfVersion) { THROW_RUNTIME_ERROR("Invalid PSF1 file \"" << this->Filename << ")\""); } psf_start(this->psfHandle); } else { // we are creating some psf2fs that handles loading and fiddling around with that psf2 file this->psf2fs = ::psf2fs_create(); if (this->psf2fs == nullptr) { throw std::bad_alloc(); } int ret = psf_load(this->Filename.c_str(), &stdio_callbacks, this->psfVersion, ::psf2fs_load_callback, // callback function provided by psf2fs this->psf2fs, // context &AopsfWrapper::psf_info, // callback function to call for info on this psf file this, // info context 1 // yes we want nested info tag ); if (ret != this->psfVersion) { THROW_RUNTIME_ERROR("Invalid PSF2 file \"" << this->Filename << ")\""); } psf2_register_readfile(this->psfHandle, ::psf2fs_virtual_readfile, this->psf2fs); psf2_start(this->psfHandle); } }