vita-toolchain

git clone https://git.neptards.moe/neptards/vita-toolchain.git
Log | Files | Refs | README | LICENSE

vita-mksfoex.c (6658B)


      1 /*
      2 # _____	 ___ ____	 ___ ____
      3 #  ____|   |	____|   |		| |____|
      4 # |	 ___|   |	 ___|	____| |	\	PSPDEV Open Source Project.
      5 #-----------------------------------------------------------------------
      6 # Review pspsdk README & LICENSE files for further details.
      7 #
      8 # New and improved mksfo
      9 # $Id$
     10 */
     11 #include <stdio.h>
     12 #include <stdint.h>
     13 #include <string.h>
     14 #include <stdlib.h>
     15 #include "getopt.h"
     16 #include "types.h"
     17 
     18 #define PSF_MAGIC	0x46535000
     19 #define PSF_VERSION  0x00000101
     20 
     21 struct SfoHeader 
     22 {
     23 	uint32_t magic;
     24 	uint32_t version;
     25 	uint32_t keyofs;
     26 	uint32_t valofs;
     27 	uint32_t count;
     28 };
     29 
     30 struct SfoEntry
     31 {
     32 	uint16_t nameofs;
     33 	uint8_t  alignment;
     34 	uint8_t  type;
     35 	uint32_t valsize;
     36 	uint32_t totalsize;
     37 	uint32_t dataofs;
     38 };
     39 
     40 #define PSF_TYPE_BIN  0
     41 #define PSF_TYPE_STR  2
     42 #define PSF_TYPE_VAL  4
     43 
     44 struct EntryContainer
     45 {
     46 	const char *name;
     47 	int type;
     48 	uint32_t value;
     49 	const char *data;
     50 };
     51 
     52 struct EntryContainer g_defaults[] = {
     53 	{ "APP_VER", PSF_TYPE_STR, 0, "00.00" },
     54 	{ "ATTRIBUTE", PSF_TYPE_VAL, 0x8000, NULL },
     55 	{ "ATTRIBUTE2", PSF_TYPE_VAL, 0, NULL },
     56 	{ "ATTRIBUTE_MINOR", PSF_TYPE_VAL, 0x10, NULL },
     57 	{ "BOOT_FILE", PSF_TYPE_STR, 32, "" },
     58 	{ "CATEGORY", PSF_TYPE_STR, 0, "gd" },
     59 	{ "CONTENT_ID", PSF_TYPE_STR, 48, "" },
     60 	{ "EBOOT_APP_MEMSIZE", PSF_TYPE_VAL, 0, NULL },
     61 	{ "EBOOT_ATTRIBUTE", PSF_TYPE_VAL, 0, NULL },
     62 	{ "EBOOT_PHY_MEMSIZE", PSF_TYPE_VAL, 0, NULL },
     63 	{ "LAREA_TYPE", PSF_TYPE_VAL, 0, NULL },
     64 	{ "NP_COMMUNICATION_ID", PSF_TYPE_STR, 16, "" },
     65 	{ "PARENTAL_LEVEL", PSF_TYPE_VAL, 0, NULL },
     66 	{ "PSP2_DISP_VER", PSF_TYPE_STR, 0, "00.000" },
     67 	{ "PSP2_SYSTEM_VER", PSF_TYPE_VAL, 0, NULL },
     68 	{ "STITLE", PSF_TYPE_STR, 52, "Homebrew" },
     69 	{ "TITLE", PSF_TYPE_STR, 0x80, "Homebrew" },
     70 	{ "TITLE_ID", PSF_TYPE_STR, 0, "ABCD99999" },
     71 	{ "VERSION", PSF_TYPE_STR, 0, "00.00" },
     72 };
     73 
     74 #define MAX_OPTIONS (256)
     75 
     76 static const char *g_title = NULL;
     77 static const char *g_filename = NULL;
     78 static int g_empty = 0;
     79 static struct EntryContainer g_vals[MAX_OPTIONS];
     80 
     81 static struct option arg_opts[] = 
     82 {
     83 	{"dword", required_argument, NULL, 'd'},
     84 	{"string", required_argument, NULL, 's'},
     85 	{"empty", no_argument, NULL, 'e'},
     86 	{ NULL, 0, NULL, 0 }
     87 };
     88 
     89 struct EntryContainer *find_free()
     90 {
     91 	int i;
     92 
     93 	for(i = 0; i < MAX_OPTIONS; i++)
     94 	{
     95 		if(g_vals[i].name == NULL)
     96 		{
     97 			return &g_vals[i];
     98 		}
     99 	}
    100 
    101 	return NULL;
    102 }
    103 
    104 struct EntryContainer *find_name(const char *name)
    105 {
    106 	int i;
    107 
    108 	for(i = 0; i < MAX_OPTIONS; i++)
    109 	{
    110 		if((g_vals[i].name != NULL) && (strcmp(g_vals[i].name, name) == 0))
    111 		{
    112 			return &g_vals[i];
    113 		}
    114 	}
    115 
    116 	return NULL;
    117 }
    118 
    119 int add_string(char *str)
    120 {
    121 	char *equals = NULL;
    122 	struct EntryContainer *entry;
    123 
    124 	equals = strchr(str, '=');
    125 	if(equals == NULL)
    126 	{
    127 		fprintf(stderr, "Invalid option (no =)\n");
    128 		return 0;
    129 	}
    130 
    131 	*equals++ = 0;
    132 	
    133 	if ((entry = find_name(str)))
    134 	{
    135 		entry->data = equals;
    136 	}
    137 	else
    138 	{
    139 		entry = find_free();
    140 		if(entry == NULL)
    141 		{
    142 			fprintf(stderr, "Maximum options reached\n");
    143 			return 0;
    144 		}
    145 
    146 		memset(entry, 0, sizeof(struct EntryContainer));
    147 		entry->name = str;
    148 		entry->type = PSF_TYPE_STR;
    149 		entry->data = equals;
    150 	}
    151 	
    152 	return 1;
    153 }
    154 
    155 int add_dword(char *str)
    156 {
    157 	char *equals = NULL;
    158 	struct EntryContainer *entry;
    159 
    160 	equals = strchr(str, '=');
    161 	if(equals == NULL)
    162 	{
    163 		fprintf(stderr, "Invalid option (no =)\n");
    164 		return 0;
    165 	}
    166 
    167 	*equals++ = 0;
    168 
    169 	if ((entry = find_name(str)))
    170 	{
    171 		entry->value = strtoul(equals, NULL, 0);
    172 	}
    173 	else
    174 	{
    175 		entry = find_free();
    176 		if(entry == NULL)
    177 		{
    178 			fprintf(stderr, "Maximum options reached\n");
    179 			return 0;
    180 		}
    181 
    182 		memset(entry, 0, sizeof(struct EntryContainer));
    183 		entry->name = str;
    184 		entry->type = PSF_TYPE_VAL;
    185 		entry->value = strtoul(equals, NULL, 0);		
    186 	}
    187 
    188 	return 1;
    189 }
    190 
    191 /* Process the arguments */
    192 int process_args(int argc, char **argv)
    193 {
    194 	int ch;
    195 
    196 	g_title = NULL;
    197 	g_filename = NULL;
    198 	g_empty = 0;
    199 
    200 	ch = getopt_long(argc, argv, "ed:s:", arg_opts, NULL);
    201 	while(ch != -1)
    202 	{
    203 		switch(ch)
    204 		{
    205 			case 'd' : if(!add_dword(optarg))
    206 					   {
    207 						   return 0;
    208 					   }
    209 				break;
    210 			case 's' : if(!add_string(optarg))
    211 					   {
    212 					   }
    213 				break;
    214 			default  : break;
    215 		};
    216 
    217 		ch = getopt_long(argc, argv, "ed:s:", arg_opts, NULL);
    218 	}
    219 
    220 	argc -= optind;
    221 	argv += optind;
    222 
    223 	if(argc < 1)
    224 	{
    225 		return 0;
    226 	}
    227 
    228 	if(!g_empty)
    229 	{
    230 		g_title = argv[0];
    231 		argc--;
    232 		argv++;
    233 	}
    234 
    235 	if(argc < 1)
    236 	{
    237 		return 0;
    238 	}
    239 
    240 	g_filename = argv[0];
    241 
    242 	return 1;
    243 }
    244 
    245 int main(int argc, char **argv)
    246 {
    247 	FILE *fp;
    248 	int i;
    249 	char head[8192];
    250 	char keys[8192];
    251 	char data[8192];
    252 	struct SfoHeader *h;
    253 	struct SfoEntry  *e;
    254 	char *k;
    255 	char *d;
    256 	unsigned int align;
    257 	unsigned int keyofs;
    258 	unsigned int count;
    259 	
    260 	for(i = 0; i < (sizeof(g_defaults) / sizeof(struct EntryContainer)); i++)
    261 	{
    262 		struct EntryContainer *entry = find_free();
    263 		if(entry == NULL)
    264 		{
    265 			fprintf(stderr, "Maximum options reached\n");
    266 			return 0;
    267 		}
    268 		*entry = g_defaults[i];
    269 	}
    270 	
    271 	if(!process_args(argc, argv)) 
    272 	{
    273 		fprintf(stderr, "usage: mksfoex [options] TITLE output.sfo\n");
    274 		fprintf(stderr, "\t-d NAME=VALUE   Add a new DWORD value\n");
    275 		fprintf(stderr, "\t-s NAME=STR     Add a new string value\n");
    276 
    277 		return 1;
    278 	}
    279 	
    280 	if (g_title)
    281 	{
    282 		struct EntryContainer *entry = find_name("TITLE");
    283 		entry->data = g_title;
    284 		
    285 		entry = find_name("STITLE");
    286 		entry->data = g_title;
    287 	}
    288 
    289 	memset(head, 0, sizeof(head));
    290 	memset(keys, 0, sizeof(keys));
    291 	memset(data, 0, sizeof(data));
    292 	h = (struct SfoHeader*) head;
    293 	e = (struct SfoEntry*)  (head+sizeof(struct SfoHeader));
    294 	k = keys;
    295 	d = data;
    296 	SW(&h->magic, PSF_MAGIC);
    297 	SW(&h->version, PSF_VERSION);
    298 	count = 0;
    299 
    300 	for(i = 0; g_vals[i].name; i++)
    301 	{
    302 		SW(&h->count, ++count);
    303 		SW(&e->nameofs, k-keys);
    304 		SW(&e->dataofs, d-data);
    305 		SW(&e->alignment, 4);
    306 		SW(&e->type, g_vals[i].type);
    307 
    308 		strcpy(k, g_vals[i].name);
    309 		k += strlen(k)+1;
    310 		if(e->type == PSF_TYPE_VAL)
    311 		{
    312 			SW(&e->valsize, 4);
    313 			SW(&e->totalsize, 4);
    314 			SW((uint32_t*) d, g_vals[i].value);
    315 			d += 4;
    316 		}
    317 		else
    318 		{
    319 			int totalsize;
    320 			int valsize = 0;
    321 
    322 			if (g_vals[i].data)
    323 				valsize = strlen(g_vals[i].data)+1;
    324 			totalsize = (g_vals[i].value) ? (g_vals[i].value) : ((valsize + 3) & ~3);
    325 			SW(&e->valsize, valsize);
    326 			SW(&e->totalsize, totalsize);
    327 			memset(d, 0, totalsize);
    328 			
    329 			if (g_vals[i].data)
    330 				memcpy(d, g_vals[i].data, valsize);
    331 			d += totalsize;
    332 		}
    333 		e++;
    334 	}
    335 
    336 
    337 	keyofs = (char*)e - head;
    338 	SW(&h->keyofs, keyofs);
    339 	align = 3 - ((unsigned int) (k-keys) & 3);
    340 	while(align < 3)
    341 	{
    342 		k++;
    343 		align--;
    344 	}
    345 	
    346 	SW(&h->valofs, keyofs + (k-keys));
    347 
    348 	fp = fopen(g_filename, "wb");
    349 	if(fp == NULL)
    350 	{
    351 		fprintf(stderr, "Cannot open filename %s\n", g_filename);
    352 		return 0;
    353 	}
    354 
    355 	fwrite(head, 1, (char*)e-head, fp);
    356 	fwrite(keys, 1, k-keys, fp);
    357 	fwrite(data, 1, d-data, fp);
    358 	fclose(fp);
    359 
    360 	return 0;
    361 }