当你运行了模拟器,通过模拟器菜单选择并加载一个umd镜像,模拟器就用这个umd镜像实例化一个UmdIsoReader(见上一篇,源码解读5)。
通过这个UmdIsoReader,从光盘提取的第一个文件是:PSP_GAME/param.sfo
这个文件在模拟器源码中用类PSF表示。
文件中存放的是一些关于游戏的参数信息,这些信息被组织成表格。这些信息包括:对系统固件的版本要求,游戏的标题(名字),游戏的类型,游戏分级,语言,游戏版本,本游戏总共的光盘数,本光盘的盘片号 等。
文件的组织方式:最前面是文件头,紧接着放索引,然后是键表,值表。
文件头:
PSF文件标识符,是一个常量0x46535000
PSF格式版本号,常量0x0101
键表起始位置相对于文件起始位置的偏移
值表起始位置相对于文件起始位置的偏移
索引项总数
每一个索引的格式:
键名在键表中的偏移(上述文件头中有键表起始位置,加上这个偏移就可以得到这个索引所指的键)
常量4(可能表示4字节边界对齐)
键值的数据类型(有三种可能的值,分别是 PSF_DATA_TYPE_BINARY = 0,PSF_DATA_TYPE_STRING = 2,PSF_DATA_TYPE_INT32 = 4)
键值有效数据的字节数
键值有效数据加上pad部分,总共的字节数。因为要4字节对齐,所以不对齐时会有pad填充到对齐
键值在值表中的偏移(上述文件头中有值表起始位置,加上这个偏移就可以得到这个索引所指键的值)
回到源码:
UmdIsoReader iso = new UmdIsoReader(file.getPath()); //打开光盘镜像
UmdIsoFile psfFile = iso.getFile("PSP_GAME/param.sfo"); //从光盘镜像中提取一个参数文件
PSF psf = new PSF(); //实例一个PSF文件对象
byte[] data = new byte[(int) psfFile.length()]; //申请一个字节缓冲区,要容纳下整个psf文件
psfFile.read(data); //将psf文件内容读取到缓冲区数组中
psf.read(ByteBuffer.wrap(data)); //从缓冲区数组中提取psf文件的内容
可以看到,这里是先从光盘中得到param.sfo文件,然后将这个文件读取到一个缓冲数组中,PSF从这个缓冲数组中提取了所有参数信息。
文件格式上文已经说明的很清楚了,PSF类中解析提取数据的实现此处不再赘述。
关于这种文件的组织格式,参考自网址:http://hitmen.c02.at/files/yapspd/psp_doc/chap26.html#sec26.4,基本就是翻译了一下。不过在模拟器的源码中确认了网页中的内容。两处细节似乎稍有差异。