///////////////////////////////////////////////////////////////////////////// // // Upload PS-X EXE - must INCLUDE the header. // If the header includes the strings "North America", "Japan", or "Europe", // the appropriate refresh rate is set. // Returns nonzero on error. // Will return error for PS2. // sint32 EMU_CALL psx_upload_psxexe(void *state, void *program, uint32 size) { uint32 init_pc; uint32 init_sp; uint32 text_start; uint32 text_size; if(PSXSTATE->version != 1) return -1; if(size < 0x801) return -1; if(memcmp(program, "PS-X EXE", 8)) return -1; text_start = get32lsb(((uint8*)program) + 0x18); text_size = get32lsb(((uint8*)program) + 0x1C); init_pc = get32lsb(((uint8*)program) + 0x10); init_sp = get32lsb(((uint8*)program) + 0x30); // Try to determine the region, or leave it at the default if it's not found if(string_exists(program, 0x800, "North America")) { psx_set_refresh(state, 60); } else if(string_exists(program, 0x800, "Japan" )) { psx_set_refresh(state, 60); } else if(string_exists(program, 0x800, "Europe" )) { psx_set_refresh(state, 50); } if(text_size > (size - 0x800)) { text_size = (size - 0x800); } iop_upload_to_ram(IOPSTATE, text_start, ((uint8*)program) + 0x800, text_size); r3000_setreg(iop_get_r3000_state(IOPSTATE), R3000_REG_PC , init_pc); r3000_setreg(iop_get_r3000_state(IOPSTATE), R3000_REG_GEN+29, init_sp); return 0; }
int he_seek_sample (DB_fileinfo_t *_info, int sample) { he_info_t *info = (he_info_t *)_info; unsigned long int s = sample; if (s < info->samples_played) { struct psf_load_state state; memset( &state, 0, sizeof(state) ); state.emu = info->emu; if ( !info->psf2fs ) { psx_clear_state( info->emu, 1 ); if ( psf_load( info->path, &psf_file_system, 1, psf1_load, &state, psf_info_meta, &state, 0 ) <= 0 ) { trace( "he: invalid PSF file\n" ); return -1; } } else { psx_clear_state( info->emu, 2 ); if ( psf_load( info->path, &psf_file_system, 2, 0, 0, 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 ); info->samples_played = 0; free_tags(state.tags); } while ( info->samples_played < s ) { int to_skip = s - info->samples_played; if ( to_skip > 32768 ) to_skip = 1024; if ( he_read( _info, NULL, to_skip * 2 * sizeof(short) ) < 0 ) { return -1; } } _info->readpos = s/(float)_info->fmt.samplerate; return 0; }
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; }