PSP Emulator: Difference between revisions
No edit summary |
|||
Line 590: | Line 590: | ||
checksum("ULUS01986") | checksum("ULUS01986") | ||
==Compatibility Flags Values== | ===Compatibility Flags Values=== | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- |
Revision as of 13:14, 5 November 2023
PSP Emulator
FLASH0
|-- codepage | `-- cptbl.dat |-- data | `-- cert | `-- CA_LIST.cer |-- font | |-- arib.pgf | |-- gb3s1518.bwfon | |-- imagefont.bin | |-- jpn0.pgf | |-- kr0.pgf | |-- ltn0.pgf | |-- ltn10.pgf | |-- ltn11.pgf | |-- ltn12.pgf | |-- ltn13.pgf | |-- ltn14.pgf | |-- ltn15.pgf | |-- ltn1.pgf | |-- ltn2.pgf | |-- ltn3.pgf | |-- ltn4.pgf | |-- ltn5.pgf | |-- ltn6.pgf | |-- ltn7.pgf | |-- ltn8.pgf | `-- ltn9.pgf |-- kd | |-- amctrl.prx | |-- audiocodec_260.prx | |-- avcodec.prx | |-- cert_loader.prx | |-- chkreg.prx | |-- chnnlsv.prx | |-- dmacman.prx | |-- exceptionman.prx | |-- exitgame.prx | |-- g729.prx | |-- ge_2.prx | |-- ge.prx | |-- http_storage.prx | |-- ifhandle.prx | |-- impose_kermit.prx | |-- init.prx | |-- interruptman.prx | |-- iofilemgr_dnas.prx | |-- iofilemgr.prx | |-- isofs.prx | |-- kermit_2.prx | |-- kermit_audio.prx | |-- kermit_ctrl.prx | |-- kermit_display.prx | |-- kermit_flashfs.prx | |-- kermit_hpremote.prx | |-- kermit_idstorage.prx | |-- kermit_lowio.prx | |-- kermit_me_wrapper.prx | |-- kermit_msemu.prx | |-- kermit_msfs.prx | |-- kermit_netconf_dialog.prx | |-- kermit_osk_plugin.prx | |-- kermit_peripheral.prx | |-- kermit_power.prx | |-- kermit.prx | |-- kermit_rtc.prx | |-- kermit_usb.prx | |-- kermit_utility.prx | |-- kermit_wlan_2.prx | |-- kermit_wlan.prx | |-- libaac.prx | |-- libasfparser.prx | |-- libatrac3plus.prx | |-- libaudiocodec2.prx | |-- libdnas_core.prx | |-- libdnas.prx | |-- libgameupdate.prx | |-- libhttp.prx | |-- libmp3.prx | |-- libmp4.prx | |-- libparse_http.prx | |-- libparse_uri.prx | |-- libssl.prx | |-- libupdown.prx | |-- loadcore.prx | |-- loadexec_01g.prx | |-- mcctrl.prx | |-- mediasync.prx | |-- memab.prx | |-- memlmd_01g_2.prx | |-- memlmd_01g.prx | |-- mesg_led_01g.prx | |-- mgvideo.prx | |-- modulemgr.prx | |-- mp4msv.prx | |-- mpegbase_260.prx | |-- mpeg.prx | |-- np9660.prx | |-- np_auth.prx | |-- np_commerce2.prx | |-- np_commerce2_regcam.prx | |-- np_commerce2_store.prx | |-- np_core.prx | |-- npdrm.prx | |-- np_inst.prx | |-- np_matching2.prx | |-- np.prx | |-- np_service.prx | |-- openpsid.prx | |-- psheet.prx | |-- pspnet_adhoc_auth.prx | |-- pspnet_adhocctl.prx | |-- pspnet_adhoc_discover.prx | |-- pspnet_adhoc_download.prx | |-- pspnet_adhoc_matching.prx | |-- pspnet_adhoc.prx | |-- pspnet_adhoc_transfer_int.prx | |-- pspnet_apctl_2.prx | |-- pspnet_apctl.prx | |-- pspnet_inet_2.prx | |-- pspnet_inet.prx | |-- pspnet.prx | |-- pspnet_resolver.prx | |-- pspnet_upnp.prx | |-- pspnet_wispr.prx | |-- registry.prx | |-- resource | | `-- impose_05g.rsc | |-- sc_sascore.prx | |-- sircs.prx | |-- sysmem.prx | |-- systimer.prx | |-- threadman.prx | |-- usbacc.prx | |-- usbcam.prx | |-- usbgps.prx | |-- usbmic.prx | |-- usbpspcm.prx | |-- usersystemlib.prx | |-- vaudio.prx | `-- videocodec_260.prx |-- pspbtcnf.bin |-- reboot.bin `-- vsh |-- etc | |-- index_01g.dat | `-- version.txt |-- module | |-- auth_plugin.prx | |-- auto_connect.prx | |-- common_gui.prx | |-- common_util.prx | |-- dd_helper.prx | |-- dd_helper_utility.prx | |-- dialogmain.prx | |-- dnas_plugin.prx | |-- file_parser_base.prx | |-- game_install_plugin.prx | |-- htmlviewer_ui.prx | |-- htmlviewer_utility.prx | |-- hvauth_r.prx | |-- libfont_hv.prx | |-- libslim.prx | |-- libwww.prx | |-- msgdialog_plugin.prx | |-- netconf_plugin.prx | |-- netfront.prx | |-- netplay_server2_utility.prx | |-- netplay_server_plus_utility.prx | |-- netplay_server_utility.prx | |-- npinstaller_plugin.prx | |-- npsignin_plugin.prx | |-- npsignup_plugin.prx | |-- pafmini.prx | |-- ps3scan_plugin.prx | |-- psn_utility.prx | |-- savedata_auto_dialog.prx | |-- savedata_utility.prx | |-- screenshot_plugin.prx | |-- store_browser_plugin.prx | |-- store_checkout_plugin.prx | `-- store_checkout_utility.prx `-- resource |-- auth_plugin.rco |-- dd_helper.rco |-- dnas_plugin.rco |-- game_install_plugin.rco |-- htmlviewer.res |-- msgdialog_plugin.rco |-- netconf_dialog.rco |-- netplay_plugin.rco |-- npinstaller_plugin.rco |-- npsignin_plugin.rco |-- npsignup_plugin.rco |-- ps3scan_plugin.rco |-- psn_plugin.rco |-- savedata_utility.rco |-- screenshot_plugin.rco |-- store_browser_plugin.rco |-- store_checkout_plugin.rco `-- system_plugin.rco
FLASH0 1.80 changes
|-- font | |-- arib.pgf removed |-- kd | |-- kermit_me_wrapper_2.prx added | |-- pops_01g.prx added | |-- popsman.prx added |-- vsh |-- module |-- libpspvmc.prx added
Flash0 Dump code
Please use responsibly. int kthread(SceSize args, void *argp) { // Find File Manager Module SceModule2 * iofilemgr = _sceKernelFindModuleByName("sceIOFileManager"); // Find required Functions KernelIOOpen = (void *)iofilemgr->text_addr + IOFILEMGR_IO_OPEN; KernelIOWrite = (void *)iofilemgr->text_addr + IOFILEMGR_IO_WRITE; KernelIOClose = (void *)iofilemgr->text_addr + IOFILEMGR_IO_CLOSE; flashVitaDump( GAME_SAVE_PATH "h.bin"/*"flashVitaDump.zip"*/ ); return 0; } void initKernelThread(void) { SceModule2 *threadman = _sceKernelFindModuleByName("sceThreadManager"); _sceKernelCreateThread = (void *)((u32)threadman->text_addr + THREADMAN_CREATE_THREAD); _sceKernelStartThread = (void *)((u32)threadman->text_addr + THREADMAN_START_THREAD); SceUID kthreadID = _sceKernelCreateThread( "Kernel thread", KERNELIFY(kthread), 25, 0x10000, 0, NULL ); if (kthreadID >= 0) _sceKernelStartThread(kthreadID, 0, NULL); else PRTSTR1("Error: sceKernelCreateThread -> 0x%08lX\n", kthreadID); } struct minZipHeader { char pk[2]; unsigned nb; char space[12]; unsigned fileSize; unsigned fileSizeClone; unsigned pathLen; /* path data */ }; typedef struct{ char *name; void *content; u32 size; }VitaFlashBufferFile; unsigned addWriteFile( SceUID packFileID, void *data, unsigned size, char *name, u8 found_nb ) { const char *root = "flash0"; char path[256]; strcpy(path, root); // If file name has no / at first, add it if ( name[0] != '/' ) path[strlen(path)+1] = 0, path[strlen(path)] = '/'; strcat(path, name); // If file was already dumped, add custom name suffix if ( found_nb > 1) strcat(path, ".bakX"), path[strlen(path)-1] = '0'+found_nb-2; // Write Data struct minZipHeader zHead; strcpy(zHead.pk, "PK"); zHead.nb = 0x000A0403; memset(zHead.space, 0, sizeof(zHead.space)); zHead.fileSize = size; zHead.fileSizeClone = size; zHead.pathLen = strlen(path); KernelIOWrite(packFileID, &(zHead.pk), 2); KernelIOWrite(packFileID, &(zHead.nb), sizeof(u32)); KernelIOWrite(packFileID, &(zHead.space), sizeof(zHead.space)); KernelIOWrite(packFileID, &(zHead.fileSize), sizeof(u32)); KernelIOWrite(packFileID, &(zHead.fileSizeClone), sizeof(u32)); KernelIOWrite(packFileID, &(zHead.pathLen), sizeof(u32)); KernelIOWrite(packFileID, path, zHead.pathLen); unsigned written = KernelIOWrite(packFileID, data, size); return written; } int findFlashIndex( const VitaFlashBufferFile *f0, void *origContent ) { int flash0_filecount = 0; while ( origContent != f0[flash0_filecount].content && f0[flash0_filecount].name != NULL ) ++flash0_filecount; if ( f0[flash0_filecount].name == NULL ) return -1; else return flash0_filecount; } void flashVitaDump( char *packName ) { uint32_t sonyF0 = 0x8B000000; uint32_t sonyF0Backup = 0x8BF00000; int flash0_fileindex = 0; uint32_t totalwrite = 0; int isValid, i; int dummy_count = 0; int backup_count = 0; char *name = NULL; u8 found_f0[512]; for ( i=0; i<sizeof(found_f0); ++i ) found_f0[i] = 0; const VitaFlashBufferFile * f0 = (VitaFlashBufferFile *)sonyF0; SceUID packFileID = KernelIOOpen(packName, PSP_O_WRONLY | PSP_O_CREAT, 0777); if (packFileID) { setPrintColorRGB(255, 0, 0); PRTSTR0(""); PRTSTR0("Dumping flash"); PRTSTR0(""); setPrintColorRGB(0, 255, 255); // Write all found flash files while ( f0[flash0_fileindex].name != NULL ) { name = f0[flash0_fileindex].name; isValid = 0; if ( name[strlen(name)-3] == 'p' && name[strlen(name)-2] == 'r' && name[strlen(name)-1] == 'x' ) { switch ( *((int*)f0[flash0_fileindex].content) ) { case 0x5053507E: isValid = 1; break; case 0: dummy_count++; break; default: PRTSTR0("Unknown prx : %08lX", name); isValid = 1; break; } } else isValid = 1; if ( isValid ) { found_f0[flash0_fileindex]++; PRTSTR0("Writing file ..."); totalwrite += addWriteFile( packFileID, f0[flash0_fileindex].content, f0[flash0_fileindex].size, name, found_f0[flash0_fileindex] ); PRTSTR0("File dumped"); } else { //PRTSTR0("Invalid flash file : %08lX", name); PRTSTR0("Dummied flash file"); } ++flash0_fileindex; } uint32_t *curf0Backup = sonyF0Backup; setPrintColorRGB(255, 0, 0); PRTSTR0(""); PRTSTR0("Dumping flash backup"); PRTSTR0(""); setPrintColorRGB(0, 255, 255); // Write all found flash backups while ( *curf0Backup != NULL ) { uint32_t origContent = *curf0Backup; flash0_fileindex = findFlashIndex(f0, origContent); unsigned size = *(curf0Backup+1); curf0Backup += 2; if ( flash0_fileindex >= 0 ) { found_f0[flash0_fileindex]++; name = f0[flash0_fileindex].name; PRTSTR0("Writing file ..."); totalwrite += addWriteFile( packFileID, curf0Backup, size, name, found_f0[flash0_fileindex] ); backup_count++; PRTSTR0("File dumped"); } else { PRTSTR0("%08lX not found", origContent); // Quit because usually means a general error break; } curf0Backup += size/4 + 1; } KernelIOClose(packFileID); //PRTSTR0("Dummy files: %08lX, backup files: %08lX ", dummy_count, backup_count); setPrintColorRGB(255, 0, 0); PRTSTR0(""); PRTSTR0("Flash successfully dumped"); PRTSTR0(""); setPrintColorRGB(0, 255, 255); } }
PSP Memory Layout
Address | Size | Comments |
---|---|---|
0x00010000 | 0x4000 | CPU Scratchpad |
0x04000000 | 2 MB/4 MB | VRAM/Framebuffer |
0x08000000 | 64 MB | Main Memory |
0xBFC00000 | 0x1000 | Shared SRAM |
SceGrab
Address | Size | Comments |
---|---|---|
0xE8300120 | 4 | Paddr of CDRAM base + 1, maps to 0x88000000? |
0xE8300124 | 4 | Paddr of CDRAM base + 0x1000000 + 1 |
0xE8300128 | 4 | Paddr of CDRAM base + 0x2000000 + 1 |
0xE830012C | 4 | Paddr of flash0 in CDRAM (base + 0x3000000) + 1, maps to 0x3000000? |
SceCompatLCDDMA
Address | Size | Comments |
---|---|---|
0xE5071004 | 4 | set 1 when done |
0xE5071024 | 4 | 0xFF0000 |
0xE5071028 | 4 | 0x0 |
0xE5071030 | 4 | some status |
0xE5071034 | 4 | Width pixels |
0xE5071038 | 4 | 0x0 |
0xE507103C | 4 | Hight pixels |
0xE5071040 | 4 | 0x0 |
0xE507104C | 4 | DMA Paddr |
0xE5071078 | 4 | 0x0 |
0xE5071084 | 4 | 0x0 |
0xE5071050 | 4 | 2048 |
0xE5071094 | 4 | 2 |
0xE5071098 | 4 | 1 |
0xE50710C0 | 4 | busy status? (set 0x1000000 when done) |
Compatibility Settings
Emulator file stores compatibility settings for 898 Title IDs (as of 3.65 firmware). Additionally, settings can be supplied by __sce_menuinfo or title_specific.bin files. Title IDs are hidden under simple hash, which Sony borrowed from PSP POPS. That's not only similarity between two compatibility systems. Same like on POPS single config entry have 4 bytes ID and 4 bytes value, also here Sony decided to start count from -1, so config ID are in range of -1 - 0x1F. Which gives 33 possible settings per game.
Warning! Current version of Vita Adrenaline seems to break internal table settings and use own values in ScePspemuInitTitleSpecificInfoPatched. This is probably reasoning why some games run better outside of Adrenaline (in ARK for example).
Title ID Hash generator
def checksum(string): x = string[0:4].encode('ascii').hex() x = int(x, 16) #print(hex(x)) y = string[4:] y = int(y, 16) y = y + (y << 12) #print(hex(y)) suma = x ^ y print(hex(suma)) checksum("ULUS01986")
Compatibility Flags Values
Command ID | Bitfield | Notes |
---|---|---|
0xFFFFFFFF | Yes | Multi command |
0x00 | Unk | |
0x01 | Unk | |
0x02 | Unk | |
0x03 | Unk | |
0x04 | Unk | |
0x05 | Unk | |
0x06 | Unk | |
0x07 | Unk | |
0x08 | Unk | |
0x09 | Unk | |
0x0A | Unk | |
0x0B | No |
Game patches (info taken from Adrenaline) 0x01: UCUS98687 Twisted Metal: Head-On 0x02: UCES00018 Twisted Metal: Head-On 0x03: NPJG00115 INFLUENCE 0x04: ULJM05500 Monster Hunter Portable 2nd G 0x05: ULJM05800 Monster Hunter Portable 3rd 0x06: ULES00851 Monster Hunter Freedom 2 0x07: ULES01213 Monster Hunter Freedom Unite 0x08: UCES01563 Geronimo Stilton: Return to the Kingdom of Fantasy 0x09: NPUG80850 Geronimo Stilton: Return to the Kingdom of Fantasy 0x0A: NPJH00039 Hatsune Miku: Project Diva - Tsuika Gakkyoku Shuu Deluxe Pack 1 - Miku Uta, Okawar 0x0B: NPJH00040 Hatsune Miku: Project Diva - Tsuika Gakkyoku Shuu Deluxe Pack 2 - Motto Okawari Rin, Len, Luka 0x0C: NPJH50594 Jikkyou Powerful Pro Yakyuu 2012 0x0D: NPJH50708 Jikkyou Powerful Pro Yakyuu 2012 Ketteiban 0x0E: ULES00981 Star Wars: The Force Unleashed 0x0F: ULUS10345 Star Wars: The Force Unleashed 0x10: ULUS10088 Field Commander 0x11: NPUH10091 Pool Hall Pro 0x12: ULES00821 World of Pool |
0x0C | Unk | |
0x0D | Unk | |
0x0E | Unk | |
0x0F | Unk | |
0x10 | Unk | |
0x11 | Unk | |
0x12 | Unk | |
0x13 | Unk | |
0x14 | Unk | |
0x15 | Unk | |
0x16 | Unk | |
0x17 | Unk | |
0x18 | Unk | |
0x19 | Unk | |
0x1A | Unk | |
0x1B | Unk | |
0x1C | Unk | |
0x1D | Unk | |
0x1E | Yes | |
0x1F | Unk |