Example #1
0
int cmdline_for_sprite(const char **argv, int argc)
{
	if (argc == 0)
		return -1;

	if (_strcmpi(argv[0], "details") == 0) {
		if (argc < 2) {
			fprintf(stderr, "usage: sprite details <spritefile> [idx]\n");
			return -1;
		} else if (argc == 2) {
			const char *spriteFilePath = argv[1];

			if (!sprite_file_open(spriteFilePath)) {
				fprintf(stderr, "Unable to open input sprite file.\n");
				return -1;
			}

			printf("sprites: %d\n", spriteFileHeader.num_entries);
			printf("data size: %d\n", spriteFileHeader.total_size);

			sprite_file_close();
			return 1;
		} else {
			const char *spriteFilePath = argv[1];
			int spriteIndex = atoi(argv[2]);

			if (!sprite_file_open(spriteFilePath)) {
				fprintf(stderr, "Unable to open input sprite file.\n");
				return -1;
			}

			if (spriteIndex < 0 || spriteIndex >= (int)spriteFileHeader.num_entries) {
				sprite_file_close();
				fprintf(stderr, "Sprite #%d does not exist in sprite file.\n", spriteIndex);
				return -1;
			}

			rct_g1_element *g1 = &spriteFileEntries[spriteIndex];
			printf("width: %d\n", g1->width);
			printf("height: %d\n", g1->height);
			printf("x offset: %d\n", g1->x_offset);
			printf("y offset: %d\n", g1->y_offset);
			printf("data offset: 0x%X\n", g1->offset);

			sprite_file_close();
			return 1;
		}
	} else if (_strcmpi(argv[0], "export") == 0) {
		if (argc < 4) {
			fprintf(stderr, "usage: sprite export <spritefile> <idx> <output>\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];
		int spriteIndex = atoi(argv[2]);
		const char *outputPath = argv[3];

		if (!sprite_file_open(spriteFilePath)) {
			fprintf(stderr, "Unable to open input sprite file.\n");
			return -1;
		}

		if (spriteIndex < 0 || spriteIndex >= (int)spriteFileHeader.num_entries) {
			fprintf(stderr, "Sprite #%d does not exist in sprite file.\n", spriteIndex);
			return -1;
		}

		if (!sprite_file_export(spriteIndex, outputPath)) {
			fprintf(stderr, "Could not export\n");
			sprite_file_close();
			return -1;
		}

		sprite_file_close();
		return 1;
	} else if (_strcmpi(argv[0], "exportall") == 0) {
		if (argc < 3) {
			fprintf(stderr, "usage: sprite exportall <spritefile> <output directory>\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];
		char outputPath[_MAX_PATH];

		if (!sprite_file_open(spriteFilePath)) {
			fprintf(stderr, "Unable to open input sprite file.\n");
			return -1;
		}

		if (!platform_ensure_directory_exists(argv[2])){
			fprintf(stderr, "Unable to create directory.\n");
			return -1;
		}


		int maxIndex = (int)spriteFileHeader.num_entries;
		int numbers = (int)floor(log(maxIndex));
		
		strncpy(outputPath, argv[2], _MAX_PATH);
		int pathLen = strlen(outputPath);

		if (pathLen >= _MAX_PATH - numbers - 5){
			fprintf(stderr, "Path too long.\n");
			return -1;
		}

		for (int x = 0; x < numbers; x++){
			outputPath[pathLen + x] = '0';
		}
		strncpy(outputPath + pathLen + numbers, ".png", _MAX_PATH);

		for (int spriteIndex = 0; spriteIndex < maxIndex; spriteIndex++){

			if (spriteIndex % 100 == 99){
				// Status indicator
				printf("\r%d / %d, %d%%", spriteIndex, maxIndex, spriteIndex / maxIndex);
			}

			// Add to the index at the end of the file name
			char *counter = outputPath + pathLen + numbers - 1;
			(*counter)++;
			while (*counter > '9'){
				*counter = '0';
				counter--;
				(*counter)++;
			}

			if (!sprite_file_export(spriteIndex, outputPath)) {
				fprintf(stderr, "Could not export\n");
				sprite_file_close();
				return -1;
			}
		}

		sprite_file_close();
		return 1;

	} else if (_strcmpi(argv[0], "create") == 0) {
		if (argc < 2) {
			fprintf(stderr, "usage: sprite create <spritefile>\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];

		spriteFileHeader.num_entries = 0;
		spriteFileHeader.total_size = 0;
		sprite_file_save(spriteFilePath);

		sprite_file_close();
		return 1;
	} else if (_strcmpi(argv[0], "append") == 0) {
		if (argc < 3) {
			fprintf(stderr, "usage: sprite append <spritefile> <input>\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];
		const char *imagePath = argv[2];

		rct_g1_element spriteElement;
		uint8 *buffer;
		int bufferLength;
		if (!sprite_file_import(imagePath, &spriteElement, &buffer, &bufferLength, sprite_mode))
			return -1;

		if (!sprite_file_open(spriteFilePath)) {
			fprintf(stderr, "Unable to open input sprite file.\n");
			return -1;
		}
		
		spriteFileHeader.num_entries++;
		spriteFileHeader.total_size += bufferLength;
		spriteFileEntries = realloc(spriteFileEntries, spriteFileHeader.num_entries * sizeof(rct_g1_element));

		sprite_entries_make_relative();
		spriteFileData = realloc(spriteFileData, spriteFileHeader.total_size);
		sprite_entries_make_absolute();

		spriteFileEntries[spriteFileHeader.num_entries - 1] = spriteElement;
		memcpy(spriteFileData + (spriteFileHeader.total_size - bufferLength), buffer, bufferLength);
		spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData + (spriteFileHeader.total_size - bufferLength);
		
		free(buffer);
		if (!sprite_file_save(spriteFilePath))
			return -1;

		return 1;
	} else if (_strcmpi(argv[0], "build") == 0) {
		if (argc < 3) {
			fprintf(stderr, "usage: sprite build <spritefile> <resourcedir> [silent]\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];
		const char *resourcePath = argv[2];
		char imagePath[MAX_PATH];
		int resourceLength = strlen(resourcePath);

		bool silent = (argc >= 4 && strcmp(argv[3], "silent") == 0);
		bool fileExists = true;
		FILE *file;

		spriteFileHeader.num_entries = 0;
		spriteFileHeader.total_size = 0;
		sprite_file_save(spriteFilePath);

		fprintf(stderr, "Building: %s\n", spriteFilePath);
		int i = 0;
		do {
			// Create image path
			strcpy(imagePath, resourcePath);
			if (resourcePath[resourceLength - 1] == '/' || resourcePath[resourceLength - 1] == '\\')
				imagePath[resourceLength - 1] = 0;
			sprintf(imagePath, "%s%c%d.png", imagePath, platform_get_path_separator(), i);

			file = fopen(imagePath, "r");
			if (file != NULL) {
				fclose(file);
				rct_g1_element spriteElement;
				uint8 *buffer;
				int bufferLength;
				if (!sprite_file_import(imagePath, &spriteElement, &buffer, &bufferLength, sprite_mode)) {
					fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath);
					return -1;
				}

				if (!sprite_file_open(spriteFilePath)) {
					fprintf(stderr, "Unable to open sprite file: %s\nCanceling\n", spriteFilePath);
					return -1;
				}

				spriteFileHeader.num_entries++;
				spriteFileHeader.total_size += bufferLength;
				spriteFileEntries = realloc(spriteFileEntries, spriteFileHeader.num_entries * sizeof(rct_g1_element));

				sprite_entries_make_relative();
				spriteFileData = realloc(spriteFileData, spriteFileHeader.total_size);
				sprite_entries_make_absolute();

				spriteFileEntries[spriteFileHeader.num_entries - 1] = spriteElement;
				memcpy(spriteFileData + (spriteFileHeader.total_size - bufferLength), buffer, bufferLength);
				spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData + (spriteFileHeader.total_size - bufferLength);

				free(buffer);

				if (!sprite_file_save(spriteFilePath)) {
					fprintf(stderr, "Could not save sprite file: %s\nCanceling\n", imagePath);
					return -1;
				}
				if (!silent)
					fprintf(stderr, "Added: %s\n", imagePath);
			}
			i++;
		} while (file != NULL);


		fprintf(stderr, "Finished\n", imagePath);
		return 1;
	} else {
		fprintf(stderr, "Unknown sprite command.");
		return 1;
	}
}
Example #2
0
sint32 cmdline_for_sprite(const char **argv, sint32 argc)
{
    gOpenRCT2Headless = true;
    if (argc == 0)
        return -1;

    if (_strcmpi(argv[0], "details") == 0) {
        if (argc < 2) {
            fprintf(stdout, "usage: sprite details <spritefile> [idx]\n");
            return -1;
        } else if (argc == 2) {
            const char *spriteFilePath = argv[1];

            if (!sprite_file_open(spriteFilePath)) {
                fprintf(stderr, "Unable to open input sprite file.\n");
                return -1;
            }

            printf("sprites: %u\n", spriteFileHeader.num_entries);
            printf("data size: %u\n", spriteFileHeader.total_size);

            sprite_file_close();
            return 1;
        } else {
            const char *spriteFilePath = argv[1];
            sint32 spriteIndex = atoi(argv[2]);

            if (!sprite_file_open(spriteFilePath)) {
                fprintf(stderr, "Unable to open input sprite file.\n");
                return -1;
            }

            if (spriteIndex < 0 || spriteIndex >= (sint32)spriteFileHeader.num_entries) {
                sprite_file_close();
                fprintf(stderr, "Sprite #%d does not exist in sprite file.\n", spriteIndex);
                return -1;
            }

            rct_g1_element *g1 = &spriteFileEntries[spriteIndex];
            printf("width: %d\n", g1->width);
            printf("height: %d\n", g1->height);
            printf("x offset: %d\n", g1->x_offset);
            printf("y offset: %d\n", g1->y_offset);
            printf("data offset: %p\n", g1->offset);

            sprite_file_close();
            return 1;
        }
    } else if (_strcmpi(argv[0], "export") == 0) {
        if (argc < 4) {
            fprintf(stdout, "usage: sprite export <spritefile> <idx> <output>\n");
            return -1;
        }

        const char *spriteFilePath = argv[1];
        sint32 spriteIndex = atoi(argv[2]);
        const char *outputPath = argv[3];

        if (!sprite_file_open(spriteFilePath)) {
            fprintf(stderr, "Unable to open input sprite file.\n");
            return -1;
        }

        if (spriteIndex < 0 || spriteIndex >= (sint32)spriteFileHeader.num_entries) {
            fprintf(stderr, "Sprite #%d does not exist in sprite file.\n", spriteIndex);
            return -1;
        }

        if (!sprite_file_export(spriteIndex, outputPath)) {
            fprintf(stderr, "Could not export\n");
            sprite_file_close();
            return -1;
        }

        sprite_file_close();
        return 1;
    } else if (_strcmpi(argv[0], "exportall") == 0) {
        if (argc < 3) {
            fprintf(stdout, "usage: sprite exportall <spritefile> <output directory>\n");
            return -1;
        }

        const char *spriteFilePath = argv[1];
        char outputPath[MAX_PATH];

        if (!sprite_file_open(spriteFilePath)) {
            fprintf(stderr, "Unable to open input sprite file.\n");
            return -1;
        }

        safe_strcpy(outputPath, argv[2], MAX_PATH);
        path_end_with_separator(outputPath, MAX_PATH);

        if (!platform_ensure_directory_exists(outputPath)){
            fprintf(stderr, "Unable to create directory.\n");
            return -1;
        }

        sint32 maxIndex = (sint32)spriteFileHeader.num_entries;
        sint32 numbers = (sint32)floor(log(maxIndex));
        size_t pathLen = strlen(outputPath);

        if (pathLen >= (size_t)(MAX_PATH - numbers - 5)) {
            fprintf(stderr, "Path too long.\n");
            return -1;
        }

        for (sint32 x = 0; x < numbers; x++){
            outputPath[pathLen + x] = '0';
        }
        safe_strcpy(outputPath + pathLen + numbers, ".png", MAX_PATH - pathLen - numbers);

        for (sint32 spriteIndex = 0; spriteIndex < maxIndex; spriteIndex++){

            if (spriteIndex % 100 == 99){
                // Status indicator
                printf("\r%d / %d, %d%%", spriteIndex, maxIndex, spriteIndex / maxIndex);
            }

            // Add to the index at the end of the file name
            char *counter = outputPath + pathLen + numbers - 1;
            (*counter)++;
            while (*counter > '9'){
                *counter = '0';
                counter--;
                (*counter)++;
            }

            if (!sprite_file_export(spriteIndex, outputPath)) {
                fprintf(stderr, "Could not export\n");
                sprite_file_close();
                return -1;
            }
        }

        sprite_file_close();
        return 1;

    } else if (_strcmpi(argv[0], "create") == 0) {
        if (argc < 2) {
            fprintf(stderr, "usage: sprite create <spritefile>\n");
            return -1;
        }

        const char *spriteFilePath = argv[1];

        spriteFileHeader.num_entries = 0;
        spriteFileHeader.total_size = 0;
        sprite_file_save(spriteFilePath);

        sprite_file_close();
        return 1;
    } else if (_strcmpi(argv[0], "append") == 0) {
        if (argc != 3 && argc != 5) {
            fprintf(stderr, "usage: sprite append <spritefile> <input> [<x offset> <y offset>]\n");
            return -1;
        }


        const char *spriteFilePath = argv[1];
        const char *imagePath = argv[2];
        sint16 x_offset = 0;
        sint16 y_offset = 0;

        if (argc == 5)
        {
            char *endptr;

            x_offset = strtol(argv[3], &endptr, 0);
            if (*endptr != 0)
            {
                fprintf(stderr, "X offset must be an integer\n");
                return -1;
            }

            y_offset = strtol(argv[4], &endptr, 0);
            if (*endptr != 0)
            {
                fprintf(stderr, "Y offset must be an integer\n");
                return -1;
            }
        }

        rct_g1_element spriteElement;
        uint8 *buffer;

        sint32 bufferLength;
        if (!sprite_file_import(imagePath, x_offset, y_offset, &spriteElement, &buffer, &bufferLength, gSpriteMode))

            return -1;

        if (!sprite_file_open(spriteFilePath)) {
            fprintf(stderr, "Unable to open input sprite file.\n");
            return -1;
        }

        spriteFileHeader.num_entries++;
        spriteFileHeader.total_size += bufferLength;
        spriteFileEntries = realloc(spriteFileEntries, spriteFileHeader.num_entries * sizeof(rct_g1_element));

        sprite_entries_make_relative();
        spriteFileData = realloc(spriteFileData, spriteFileHeader.total_size);
        sprite_entries_make_absolute();

        spriteFileEntries[spriteFileHeader.num_entries - 1] = spriteElement;
        memcpy(spriteFileData + (spriteFileHeader.total_size - bufferLength), buffer, bufferLength);
        spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData + (spriteFileHeader.total_size - bufferLength);

        free(buffer);
        if (!sprite_file_save(spriteFilePath))
            return -1;

        return 1;
    } else if (_strcmpi(argv[0], "build") == 0) {
        if (argc < 3) {
            fprintf(stdout, "usage: sprite build <spritefile> <sprite description file> [silent]\n");
            return -1;
        }

        const char *spriteFilePath = argv[1];
        const char *spriteDescriptionPath = argv[2];
        char* directoryPath = path_get_directory(spriteDescriptionPath);

        json_error_t error;
        json_t* sprite_list=json_load_file(spriteDescriptionPath, JSON_REJECT_DUPLICATES, &error);

        if (sprite_list == NULL)
        {
            fprintf(stderr, "Error parsing sprite description file: %s at line %d column %d\n", error.text, error.line, error.column);
            return -1;
        }

        if (!json_is_array(sprite_list))
        {
            fprintf(stderr, "Error: expected array\n");
            json_decref(sprite_list);
            return -1;
        }

        bool silent = (argc >= 4 && strcmp(argv[3], "silent") == 0);

        spriteFileHeader.num_entries = 0;
        spriteFileHeader.total_size = 0;
        sprite_file_save(spriteFilePath);

        fprintf(stdout, "Building: %s\n", spriteFilePath);

        size_t i;
        json_t* sprite_description;

        json_array_foreach(sprite_list, i, sprite_description)
        {
            if(!json_is_object(sprite_description))
            {
                fprintf(stderr, "Error: expected object for sprite %lu\n", (unsigned long)i);
                json_decref(sprite_list);
                return -1;
            }

            json_t* path = json_object_get(sprite_description,"path");
            if(!path || !json_is_string(path))
            {
                fprintf(stderr, "Error: no path provided for sprite %lu\n", (unsigned long)i);
                json_decref(sprite_list);
                return -1;
            }
            // Get x and y offsets, if present
            json_t* x_offset = json_object_get(sprite_description, "x_offset");
            json_t* y_offset = json_object_get(sprite_description, "y_offset");


            // Resolve absolute sprite path
            char *imagePath = platform_get_absolute_path(json_string_value(path), directoryPath);

            rct_g1_element spriteElement;
            uint8 *buffer;
            int bufferLength;

            if (!sprite_file_import(imagePath, x_offset==NULL ? 0 : json_integer_value(x_offset), y_offset==NULL ? 0 : json_integer_value(y_offset), &spriteElement, &buffer, &bufferLength, gSpriteMode))
            {
                fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath);
                json_decref(sprite_list);
                free(imagePath);
                return -1;
            }

            if (!sprite_file_open(spriteFilePath))
            {
                fprintf(stderr, "Unable to open sprite file: %s\nCanceling\n", spriteFilePath);
                json_decref(sprite_list);
                free(imagePath);
                return -1;
            }

            spriteFileHeader.num_entries++;
            spriteFileHeader.total_size += bufferLength;
            spriteFileEntries = realloc(spriteFileEntries, spriteFileHeader.num_entries * sizeof(rct_g1_element));

            sprite_entries_make_relative();
            spriteFileData = realloc(spriteFileData, spriteFileHeader.total_size);
            sprite_entries_make_absolute();

            spriteFileEntries[spriteFileHeader.num_entries - 1] = spriteElement;
            memcpy(spriteFileData + (spriteFileHeader.total_size - bufferLength), buffer, bufferLength);
            spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData + (spriteFileHeader.total_size - bufferLength);

            free(buffer);

            if (!sprite_file_save(spriteFilePath))
            {
                fprintf(stderr, "Could not save sprite file: %s\nCanceling\n", imagePath);
                json_decref(sprite_list);
                free(imagePath);
                return -1;
            }

            if (!silent)
                fprintf(stdout, "Added: %s\n", imagePath);

            free(imagePath);
            sprite_file_close();

        }

        json_decref(sprite_list);
        free(directoryPath);

        fprintf(stdout, "Finished\n");
        return 1;
    } else {