Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * This code only supports Little endian machine.
- */
- #include <errno.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- #define PSF_MAGIC 0x46535000
- enum {
- SFO_DATATYPE_UTF8 = 0x0204,
- SFO_DATATYPE_INT32 = 0x0404
- };
- enum {
- SFO_ENT_ATTRIBUTE,
- SFO_ENT_BOOTABLE,
- SFO_ENT_CATEGORY,
- SFO_ENT_PARENTAL_LEVEL,
- SFO_ENT_TITLE,
- SFO_ENT_TITLE_ID,
- SFO_ENT_VERSION
- };
- struct sfoHdr {
- uint32_t magic;
- uint32_t ver;
- uint32_t keyOffset;
- uint32_t dataOffset;
- uint32_t num;
- };
- struct sfoEnt {
- uint16_t keyOffset;
- uint16_t dataType;
- uint32_t dataSize;
- uint32_t dataMaxSize;
- uint32_t dataOffset;
- };
- struct outKeys_t {
- char attr[sizeof("ATTRIBUTE")];
- char bootable[sizeof("BOOTABLE")];
- char category[sizeof("CATEGORY")];
- char pl[sizeof("PARENTAL_LEVEL")];
- char title[sizeof("TITLE")];
- char titleId[sizeof("TITLE_ID")];
- char ver[sizeof("VERSION")];
- char pad[2];
- };
- static const struct outKeys_t outKeys = {
- .attr = "ATTRIBUTE",
- .bootable = "BOOTABLE",
- .category = "CATEGORY",
- .pl = "PARENTAL_LEVEL",
- .title = "TITLE",
- .titleId = "TITLE_ID",
- .ver = "VERSION"
- };
- struct outData_t {
- int32_t attr;
- int32_t bootable;
- char category[4];
- int32_t pl;
- char title[128];
- char titleId[16];
- char ver[8];
- };
- static struct outData_t outData = {
- .attr = 3,
- .bootable = 1,
- .category = "PE"
- };
- static struct sfoEnt outEnt[] = {
- [SFO_ENT_ATTRIBUTE] = {
- .keyOffset = offsetof(struct outKeys_t, attr),
- .dataType = SFO_DATATYPE_INT32,
- .dataSize = sizeof(outData.attr),
- .dataMaxSize = sizeof(outData.attr),
- .dataOffset = offsetof(struct outData_t, attr)
- },
- [SFO_ENT_BOOTABLE] = {
- .keyOffset = offsetof(struct outKeys_t, bootable),
- .dataType = SFO_DATATYPE_INT32,
- .dataSize = sizeof(outData.bootable),
- .dataMaxSize = sizeof(outData.bootable),
- .dataOffset = offsetof(struct outData_t, bootable)
- },
- [SFO_ENT_CATEGORY] = {
- .keyOffset = offsetof(struct outKeys_t, category),
- .dataType = SFO_DATATYPE_UTF8,
- .dataSize = 3,
- .dataMaxSize = sizeof(outData.category),
- .dataOffset = offsetof(struct outData_t, category)
- },
- [SFO_ENT_PARENTAL_LEVEL] = {
- .keyOffset = offsetof(struct outKeys_t, pl),
- .dataType = SFO_DATATYPE_INT32,
- .dataSize = sizeof(outData.pl),
- .dataMaxSize = sizeof(outData.pl),
- .dataOffset = offsetof(struct outData_t, pl)
- },
- [SFO_ENT_TITLE] = {
- .keyOffset = offsetof(struct outKeys_t, title),
- .dataType = SFO_DATATYPE_UTF8,
- .dataMaxSize = sizeof(outData.title),
- .dataOffset = offsetof(struct outData_t, title)
- },
- [SFO_ENT_TITLE_ID] = {
- .keyOffset = offsetof(struct outKeys_t, titleId),
- .dataType = SFO_DATATYPE_UTF8,
- .dataMaxSize = sizeof(outData.titleId),
- .dataOffset = offsetof(struct outData_t, titleId)
- },
- [SFO_ENT_VERSION] = {
- .keyOffset = offsetof(struct outKeys_t, ver),
- .dataType = SFO_DATATYPE_UTF8,
- .dataMaxSize = sizeof(outData.ver),
- .dataOffset = offsetof(struct outData_t, ver)
- }
- };
- static const struct sfoHdr outHdr = {
- .magic = PSF_MAGIC,
- .ver = 0x0101,
- .keyOffset = sizeof(outHdr) + sizeof(outEnt),
- .dataOffset = sizeof(outHdr) + sizeof(outEnt) + sizeof(outKeys),
- .num = sizeof(outEnt) / sizeof(struct sfoEnt)
- };
- int main(int argc, char *argv[])
- {
- struct sfoHdr hdr;
- struct sfoEnt ent;
- uint32_t *dataSize;
- size_t size;
- FILE *fp;
- char key[15];
- long offset;
- void *p;
- if (argc != 3) {
- printf("Usage: %s <INPUT.SFO> <OUTPUT.SFO>\n", argv[0]);
- return EINVAL;
- }
- fp = fopen(argv[1], "rb");
- if (fp < 0) {
- perror(argv[1]);
- return errno;
- }
- if (fread(&hdr, sizeof(hdr), 1, fp) <= 0) {
- perror(argv[1]);
- return errno;
- }
- if (hdr.magic != PSF_MAGIC) {
- printf("%s: Invalid Magic\n", argv[1]);
- return EILSEQ;
- }
- for (offset = sizeof(hdr);
- offset < sizeof(hdr) + sizeof(ent) * hdr.num;
- offset += sizeof(ent))
- {
- if (fseek(fp, offset, SEEK_SET)) {
- perror(argv[1]);
- return errno;
- }
- if (fread(&ent, sizeof(ent), 1, fp) <= 0) {
- perror(argv[1]);
- return errno;
- }
- if (fseek(fp, hdr.keyOffset + ent.keyOffset, SEEK_SET)) {
- perror(argv[1]);
- return errno;
- }
- if (fread(key, sizeof(key), 1, fp) <= 0) {
- perror(argv[1]);
- return errno;
- }
- if (!strcmp(key, "DISC_ID")) {
- p = outData.titleId;
- size = sizeof(outData.titleId);
- dataSize = &outEnt[SFO_ENT_TITLE_ID].dataSize;
- } else if (!strcmp(key, "DISC_VERSION")) {
- p = outData.ver;
- size = sizeof(outData.ver);
- dataSize = &outEnt[SFO_ENT_VERSION].dataSize;
- } else if (!strcmp(key, "TITLE")) {
- p = outData.title;
- size = sizeof(outData.title);
- dataSize = &outEnt[SFO_ENT_TITLE].dataSize;
- } else
- continue;
- if (fseek(fp, hdr.dataOffset + ent.dataOffset, SEEK_SET)) {
- perror(argv[1]);
- return errno;
- }
- if (fread(p, size, 1, fp) <= 0) {
- perror(argv[1]);
- return errno;
- }
- *dataSize = strlen(p);
- if (*dataSize > size) {
- printf("%s: %s is too long\n", argv[1], key);
- return EILSEQ;
- }
- }
- if (fclose(fp))
- perror(argv[1]);
- fp = fopen(argv[2], "w");
- if (fp < 0) {
- perror(argv[2]);
- return errno;
- }
- if (fwrite(&outHdr, sizeof(outHdr), 1, fp) != 1) {
- perror(argv[2]);
- return errno;
- }
- if (fwrite(&outEnt, sizeof(outEnt), 1, fp) != 1) {
- perror(argv[2]);
- return errno;
- }
- if (fwrite(&outKeys, sizeof(outKeys), 1, fp) != 1) {
- perror(argv[2]);
- return errno;
- }
- if (fwrite(&outData, sizeof(outData), 1, fp) != 1) {
- perror(argv[2]);
- return errno;
- }
- if (fclose(fp)) {
- perror(argv[2]);
- return errno;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement