示例#1
0
int main(int argc, char* argv[])
{
    toolcontext ctx;
    u8 magic[4];
    char infname[512];
    int c;
    u32 ncchoffset = ~0;
    char keysetfname[512] = "keys.xml";
    keyset tmpkeys;
    unsigned int checkkeysetfile = 0;

    memset(&ctx, 0, sizeof(toolcontext));
    ctx.actions = InfoFlag | ExtractFlag;
    ctx.filetype = FILETYPE_UNKNOWN;

    settings_init(&ctx.usersettings);
    keyset_init(&ctx.usersettings.keys);
    keyset_init(&tmpkeys);


    while (1)
    {
        int option_index;
        static struct option long_options[] =
        {
            {"extract", 0, NULL, 'x'},
            {"plain", 0, NULL, 'p'},
            {"info", 0, NULL, 'i'},
            {"exefs", 1, NULL, 0},
            {"romfs", 1, NULL, 1},
            {"exheader", 1, NULL, 2},
            {"certs", 1, NULL, 3},
            {"tik", 1, NULL, 4},
            {"tmd", 1, NULL, 5},
            {"contents", 1, NULL, 6},
            {"meta", 1, NULL, 7},
            {"exefsdir", 1, NULL, 8},
            {"keyset", 1, NULL, 'k'},
            {"ncch", 1, NULL, 'n'},
            {"verbose", 0, NULL, 'v'},
            {"verify", 0, NULL, 'y'},
            {"raw", 0, NULL, 'r'},
            {"unitsize", 1, NULL, 9},
            {"showkeys", 0, NULL, 10},
            {"commonkey", 1, NULL, 11},
            {"ncchkey", 1, NULL, 12},
            {"intype", 1, NULL, 't'},
            {"lzssout", 1, NULL, 13},
            {"firmdir", 1, NULL, 14},
            {"ncchsyskey", 1, NULL, 15},
            {"wav", 1, NULL, 16},
            {"romfsdir", 1, NULL, 17},
            {"listromfs", 0, NULL, 18},
            {"wavloops", 1, NULL, 19},
            {"logo", 1, NULL, 20},
            {NULL},
        };

        c = getopt_long(argc, argv, "ryxivpk:n:t:", long_options, &option_index);
        if (c == -1)
            break;

        switch (c)
        {
        case 'x':
            ctx.actions |= ExtractFlag;
            break;

        case 'v':
            ctx.actions |= VerboseFlag;
            break;

        case 'y':
            ctx.actions |= VerifyFlag;
            break;

        case 'p':
            ctx.actions |= PlainFlag;
            break;

        case 'r':
            ctx.actions |= RawFlag;
            break;

        case 'i':
            ctx.actions |= InfoFlag;
            break;

        case 'n':
            ncchoffset = strtoul(optarg, 0, 0);
            break;

        case 'k':
            strncpy(keysetfname, optarg, sizeof(keysetfname));
            checkkeysetfile = 1;
            break;

        case 't':
            if (!strcmp(optarg, "exheader"))
                ctx.filetype = FILETYPE_EXHEADER;
            else if (!strcmp(optarg, "ncch"))
                ctx.filetype = FILETYPE_CXI;
            else if (!strcmp(optarg, "ncsd"))
                ctx.filetype = FILETYPE_CCI;
            else if (!strcmp(optarg, "cia"))
                ctx.filetype = FILETYPE_CIA;
            else if (!strcmp(optarg, "tmd"))
                ctx.filetype = FILETYPE_TMD;
            else if (!strcmp(optarg, "lzss"))
                ctx.filetype = FILETYPE_LZSS;
            else if (!strcmp(optarg, "firm"))
                ctx.filetype = FILETYPE_FIRM;
            else if (!strcmp(optarg, "cwav"))
                ctx.filetype = FILETYPE_CWAV;
            else if (!strcmp(optarg, "romfs"))
                ctx.filetype = FILETYPE_ROMFS;
            break;

        case 0:
            settings_set_exefs_path(&ctx.usersettings, optarg);
            break;
        case 1:
            settings_set_romfs_path(&ctx.usersettings, optarg);
            break;
        case 2:
            settings_set_exheader_path(&ctx.usersettings, optarg);
            break;
        case 3:
            settings_set_certs_path(&ctx.usersettings, optarg);
            break;
        case 4:
            settings_set_tik_path(&ctx.usersettings, optarg);
            break;
        case 5:
            settings_set_tmd_path(&ctx.usersettings, optarg);
            break;
        case 6:
            settings_set_content_path(&ctx.usersettings, optarg);
            break;
        case 7:
            settings_set_content_path(&ctx.usersettings, optarg);
            break;
        case 8:
            settings_set_exefs_dir_path(&ctx.usersettings, optarg);
            break;
        case 9:
            settings_set_mediaunit_size(&ctx.usersettings, strtoul(optarg, 0, 0));
            break;
        case 10:
            ctx.actions |= ShowKeysFlag;
            break;
        case 11:
            keyset_parse_commonkey(&tmpkeys, optarg, strlen(optarg));
            break;
        case 12:
            keyset_parse_ncchkey(&tmpkeys, optarg, strlen(optarg));
            break;
        case 13:
            settings_set_lzss_path(&ctx.usersettings, optarg);
            break;
        case 14:
            settings_set_firm_dir_path(&ctx.usersettings, optarg);
            break;
        case 15:
            keyset_parse_ncchfixedsystemkey(&tmpkeys, optarg, strlen(optarg));
            break;
        case 16:
            settings_set_wav_path(&ctx.usersettings, optarg);
            break;
        case 17:
            settings_set_romfs_dir_path(&ctx.usersettings, optarg);
            break;
        case 18:
            settings_set_list_romfs_files(&ctx.usersettings, 1);
            break;
        case 19:
            settings_set_cwav_loopcount(&ctx.usersettings, strtoul(optarg, 0, 0));
            break;
        case 20:
            settings_set_logo_path(&ctx.usersettings, optarg);
            break;

        default:
            usage(argv[0]);
        }
    }

    if (optind == argc - 1)
    {
        // Exactly one extra argument - an input file
        strncpy(infname, argv[optind], sizeof(infname));
    }
    else if ( (optind < argc) || (argc == 1) )
    {
        // Too many extra args
        usage(argv[0]);
    }

    keyset_load(&ctx.usersettings.keys, keysetfname, (ctx.actions & VerboseFlag) | checkkeysetfile);
    keyset_merge(&ctx.usersettings.keys, &tmpkeys);
    if (ctx.actions & ShowKeysFlag)
        keyset_dump(&ctx.usersettings.keys);

    ctx.infile = fopen(infname, "rb");

    if (ctx.infile == 0)
    {
        fprintf(stderr, "error: could not open input file!\n");
        return -1;
    }

    fseek(ctx.infile, 0, SEEK_END);
    ctx.infilesize = ftell(ctx.infile);
    fseek(ctx.infile, 0, SEEK_SET);




    if (ctx.filetype == FILETYPE_UNKNOWN)
    {
        fseek(ctx.infile, 0x100, SEEK_SET);
        fread(&magic, 1, 4, ctx.infile);

        switch(getle32(magic))
        {
        case MAGIC_NCCH:
            ctx.filetype = FILETYPE_CXI;
            break;

        case MAGIC_NCSD:
            ctx.filetype = FILETYPE_CCI;
            break;

        default:
            break;
        }
    }

    if (ctx.filetype == FILETYPE_UNKNOWN)
    {
        fseek(ctx.infile, 0, SEEK_SET);
        fread(magic, 1, 4, ctx.infile);

        switch(getle32(magic))
        {
        case 0x2020:
            ctx.filetype = FILETYPE_CIA;
            break;

        case MAGIC_FIRM:
            ctx.filetype = FILETYPE_FIRM;
            break;

        case MAGIC_CWAV:
            ctx.filetype = FILETYPE_CWAV;
            break;

        case MAGIC_IVFC:
            ctx.filetype = FILETYPE_ROMFS; // TODO: need to determine more here.. savegames use IVFC too, but is not ROMFS.
            break;
        }
    }

    if (ctx.filetype == FILETYPE_UNKNOWN)
    {
        fprintf(stdout, "Unknown file\n");
        exit(1);
    }


    switch(ctx.filetype)
    {
    case FILETYPE_CCI:
    {
        ncsd_context ncsdctx;

        ncsd_init(&ncsdctx);
        ncsd_set_file(&ncsdctx, ctx.infile);
        ncsd_set_size(&ncsdctx, ctx.infilesize);
        ncsd_set_usersettings(&ncsdctx, &ctx.usersettings);
        ncsd_process(&ncsdctx, ctx.actions);

        break;
    }

    case FILETYPE_FIRM:
    {
        firm_context firmctx;

        firm_init(&firmctx);
        firm_set_file(&firmctx, ctx.infile);
        firm_set_size(&firmctx, ctx.infilesize);
        firm_set_usersettings(&firmctx, &ctx.usersettings);
        firm_process(&firmctx, ctx.actions);

        break;
    }

    case FILETYPE_CXI:
    {
        ncch_context ncchctx;

        ncch_init(&ncchctx);
        ncch_set_file(&ncchctx, ctx.infile);
        ncch_set_size(&ncchctx, ctx.infilesize);
        ncch_set_usersettings(&ncchctx, &ctx.usersettings);
        ncch_process(&ncchctx, ctx.actions);

        break;
    }


    case FILETYPE_CIA:
    {
        cia_context ciactx;

        cia_init(&ciactx);
        cia_set_file(&ciactx, ctx.infile);
        cia_set_size(&ciactx, ctx.infilesize);
        cia_set_usersettings(&ciactx, &ctx.usersettings);
        cia_process(&ciactx, ctx.actions);

        break;
    }

    case FILETYPE_EXHEADER:
    {
        exheader_context exheaderctx;

        exheader_init(&exheaderctx);
        exheader_set_file(&exheaderctx, ctx.infile);
        exheader_set_size(&exheaderctx, ctx.infilesize);
        settings_set_ignore_programid(&ctx.usersettings, 1);

        exheader_set_usersettings(&exheaderctx, &ctx.usersettings);
        exheader_process(&exheaderctx, ctx.actions);

        break;
    }

    case FILETYPE_TMD:
    {
        tmd_context tmdctx;

        tmd_init(&tmdctx);
        tmd_set_file(&tmdctx, ctx.infile);
        tmd_set_size(&tmdctx, ctx.infilesize);
        tmd_set_usersettings(&tmdctx, &ctx.usersettings);
        tmd_process(&tmdctx, ctx.actions);

        break;
    }

    case FILETYPE_LZSS:
    {
        lzss_context lzssctx;

        lzss_init(&lzssctx);
        lzss_set_file(&lzssctx, ctx.infile);
        lzss_set_size(&lzssctx, ctx.infilesize);
        lzss_set_usersettings(&lzssctx, &ctx.usersettings);
        lzss_process(&lzssctx, ctx.actions);

        break;
    }


    case FILETYPE_CWAV:
    {
        cwav_context cwavctx;

        cwav_init(&cwavctx);
        cwav_set_file(&cwavctx, ctx.infile);
        cwav_set_size(&cwavctx, ctx.infilesize);
        cwav_set_usersettings(&cwavctx, &ctx.usersettings);
        cwav_process(&cwavctx, ctx.actions);

        break;
    }

    case FILETYPE_ROMFS:
    {
        romfs_context romfsctx;

        romfs_init(&romfsctx);
        romfs_set_file(&romfsctx, ctx.infile);
        romfs_set_size(&romfsctx, ctx.infilesize);
        romfs_set_usersettings(&romfsctx, &ctx.usersettings);
        romfs_process(&romfsctx, ctx.actions);

        break;
    }
    }

    if (ctx.infile)
        fclose(ctx.infile);

    return 0;
}
示例#2
0
int main(int argc, char* argv[])
{
	toolcontext ctx;
	char fname[512];
	int c;
	u32 ncchoffset = ~0;
	char keysetfname[512] = "keys.xml";
	keyset tmpkeys;
	unsigned int checkkeysetfile = 0;
	
	memset(&ctx, 0, sizeof(toolcontext));
	ctx.actions = InfoFlag | ExtractFlag | ParseFlag;
	ctx.filetype = FILETYPE_UNKNOWN;

	settings_init(&ctx.usersettings);
	keyset_init(&ctx.usersettings.keys);
	keyset_init(&tmpkeys);


	while (1) 
	{
		int option_index;
		static struct option long_options[] = 
		{
			{"create", 0, NULL, 'c'},
			{"extract", 0, NULL, 'x'},
			{"plain", 0, NULL, 'p'},
			{"info", 0, NULL, 'i'},
			{"exefs", 1, NULL, 0},
			{"romfs", 1, NULL, 1},
			{"exheader", 1, NULL, 2},
			{"certs", 1, NULL, 3},
			{"tik", 1, NULL, 4},
			{"tmd", 1, NULL, 5},
			{"contents", 1, NULL, 6},
			{"meta", 1, NULL, 7},
			{"exefsdir", 1, NULL, 8},
			{"keyset", 1, NULL, 'k'},
			{"ncch", 1, NULL, 'n'},
			{"verbose", 0, NULL, 'v'},
			{"verify", 0, NULL, 'y'},
			{"raw", 0, NULL, 'r'},
			{"unitsize", 1, NULL, 9},
			{"showkeys", 0, NULL, 10},
			{"commonkey", 1, NULL, 11},
			{"ncchkey", 1, NULL, 12},
			{"intype", 1, NULL, 't'},
			{"lzssout", 1, NULL, 13},
			{"firmdir", 1, NULL, 14},
			{"ncchsyskey", 1, NULL, 15},
			{"wav", 1, NULL, 16},
			{"romfsdir", 1, NULL, 17},
			{"listromfs", 0, NULL, 18},
			{"wavloops", 1, NULL, 19},

			{"section0file", 1, NULL, SECTION_FILE_ARG_BASE+0},
			{"section1file", 1, NULL, SECTION_FILE_ARG_BASE+1},
			{"section2file", 1, NULL, SECTION_FILE_ARG_BASE+2},
			{"section3file", 1, NULL, SECTION_FILE_ARG_BASE+3},
			{"section4file", 1, NULL, SECTION_FILE_ARG_BASE+4},
			{"section5file", 1, NULL, SECTION_FILE_ARG_BASE+5},
			{"section6file", 1, NULL, SECTION_FILE_ARG_BASE+6},
			{"section7file", 1, NULL, SECTION_FILE_ARG_BASE+7},

			{"section0name", 1, NULL, SECTION_NAME_ARG_BASE+0},
			{"section1name", 1, NULL, SECTION_NAME_ARG_BASE+1},
			{"section2name", 1, NULL, SECTION_NAME_ARG_BASE+2},
			{"section3name", 1, NULL, SECTION_NAME_ARG_BASE+3},
			{"section4name", 1, NULL, SECTION_NAME_ARG_BASE+4},
			{"section5name", 1, NULL, SECTION_NAME_ARG_BASE+5},
			{"section6name", 1, NULL, SECTION_NAME_ARG_BASE+6},
			{"section7name", 1, NULL, SECTION_NAME_ARG_BASE+7},

			{"compresscode", 0, NULL, 40},
			{NULL},
		};

		c = getopt_long(argc, argv, "ryxcivpk:n:t:", long_options, &option_index);
		if (c == -1)
			break;

		switch (c) 
		{
			case 'c':
				ctx.actions |= CreateFlag;
				ctx.actions &= ~ParseFlag;
			break;

			case 'x':
				ctx.actions |= ExtractFlag;
			break;

			case 'v':
				ctx.actions |= VerboseFlag;
			break;

			case 'y':
				ctx.actions |= VerifyFlag;
			break;

			case 'p':
				ctx.actions |= PlainFlag;
			break;

			case 'r':
				ctx.actions |= RawFlag;
			break;

			case 'i':
				ctx.actions |= InfoFlag;
			break;

			case 'n':
				ncchoffset = strtoul(optarg, 0, 0);
			break;

			case 'k':
				strncpy(keysetfname, optarg, sizeof(keysetfname));
				checkkeysetfile = 1;
			break;

			case 't':
				if (!strcmp(optarg, "exheader"))
					ctx.filetype = FILETYPE_EXHEADER;
				else if (!strcmp(optarg, "ncch"))
					ctx.filetype = FILETYPE_CXI;
				else if (!strcmp(optarg, "ncsd"))
					ctx.filetype = FILETYPE_CCI;
				else if (!strcmp(optarg, "cia"))
					ctx.filetype = FILETYPE_CIA;
				else if (!strcmp(optarg, "tmd"))
					ctx.filetype = FILETYPE_TMD;
				else if (!strcmp(optarg, "lzss"))
					ctx.filetype = FILETYPE_LZSS;
				else if (!strcmp(optarg, "firm"))
					ctx.filetype = FILETYPE_FIRM;
				else if (!strcmp(optarg, "cwav"))
					ctx.filetype = FILETYPE_CWAV;
				else if (!strcmp(optarg, "exefs"))
					ctx.filetype = FILETYPE_EXEFS;
				else if (!strcmp(optarg, "romfs"))
					ctx.filetype = FILETYPE_ROMFS;
			break;

			case 0: settings_set_exefs_path(&ctx.usersettings, optarg); break;
			case 1: settings_set_romfs_path(&ctx.usersettings, optarg); break;
			case 2: settings_set_exheader_path(&ctx.usersettings, optarg); break;
			case 3: settings_set_certs_path(&ctx.usersettings, optarg); break;
			case 4: settings_set_tik_path(&ctx.usersettings, optarg); break;
			case 5: settings_set_tmd_path(&ctx.usersettings, optarg); break;
			case 6: settings_set_content_path(&ctx.usersettings, optarg); break;
			case 7: settings_set_content_path(&ctx.usersettings, optarg); break;
			case 8: settings_set_exefs_dir_path(&ctx.usersettings, optarg); break;
			case 9: settings_set_mediaunit_size(&ctx.usersettings, strtoul(optarg, 0, 0)); break;
			case 10: ctx.actions |= ShowKeysFlag; break;
			case 11: keyset_parse_commonkey(&tmpkeys, optarg, strlen(optarg)); break;
			case 12: keyset_parse_ncchkey(&tmpkeys, optarg, strlen(optarg)); break;
			case 13: settings_set_lzss_path(&ctx.usersettings, optarg); break;
			case 14: settings_set_firm_dir_path(&ctx.usersettings, optarg); break;
			case 15: keyset_parse_ncchfixedsystemkey(&tmpkeys, optarg, strlen(optarg)); break;
			case 16: settings_set_wav_path(&ctx.usersettings, optarg); break;
			case 17: settings_set_romfs_dir_path(&ctx.usersettings, optarg); break;
			case 18: settings_set_list_romfs_files(&ctx.usersettings, 1); break;
			case 19: settings_set_cwav_loopcount(&ctx.usersettings, strtoul(optarg, 0, 0)); break;
			case 40: ctx.actions |= CompressCodeFlag; break;

			case SECTION_FILE_ARG_BASE+0:
			case SECTION_FILE_ARG_BASE+1:
			case SECTION_FILE_ARG_BASE+2:
			case SECTION_FILE_ARG_BASE+3:
			case SECTION_FILE_ARG_BASE+4:
			case SECTION_FILE_ARG_BASE+5:
			case SECTION_FILE_ARG_BASE+6:
			case SECTION_FILE_ARG_BASE+7:
				settings_set_exefs_section_path(&ctx.usersettings, c-SECTION_FILE_ARG_BASE, optarg);
			break;

			case SECTION_NAME_ARG_BASE+0:
			case SECTION_NAME_ARG_BASE+1:
			case SECTION_NAME_ARG_BASE+2:
			case SECTION_NAME_ARG_BASE+3:
			case SECTION_NAME_ARG_BASE+4:
			case SECTION_NAME_ARG_BASE+5:
			case SECTION_NAME_ARG_BASE+6:
			case SECTION_NAME_ARG_BASE+7:
				settings_set_exefs_section_name(&ctx.usersettings, c-SECTION_NAME_ARG_BASE, optarg);
			break;


			default:
				usage(argv[0]);
		}
	}

	if (optind == argc - 1) 
	{
		// Exactly one extra argument - an input file
		strncpy(fname, argv[optind], sizeof(fname));
	} 
	else if ( (optind < argc) || (argc == 1) )
	{
		// Too many extra args
		usage(argv[0]);
	}

	keyset_load(&ctx.usersettings.keys, keysetfname, (ctx.actions & VerboseFlag) | checkkeysetfile);
	keyset_merge(&ctx.usersettings.keys, &tmpkeys);
	if (ctx.actions & ShowKeysFlag)
		keyset_dump(&ctx.usersettings.keys);

	if(ctx.actions & ParseFlag)return action_parse(&ctx, fname);
	else if(ctx.actions & CreateFlag)return action_create(&ctx, fname);

	return -1; //shouldn't happen ffs
}