From c1260fc11f8a9133012f2f6b00d5869511f33c62 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Tue, 19 May 2015 00:26:31 +0100 Subject: [PATCH] add command line sprite editor and additional custom graphics (g2.dat) --- data/g2.dat | Bin 0 -> 34340 bytes projects/openrct2.vcxproj | 4 + projects/openrct2.vcxproj.filters | 3 + src/cmdline.c | 68 ++- src/cmdline.h | 1 + src/cmdline_sprite.c | 678 ++++++++++++++++++++++++++++++ src/drawing/drawing.h | 1 + src/drawing/sprite.c | 56 ++- src/rct2.c | 1 + src/sprites.h | 3 + src/windows/title_logo.c | 3 +- 11 files changed, 799 insertions(+), 19 deletions(-) create mode 100644 data/g2.dat create mode 100644 src/cmdline_sprite.c diff --git a/data/g2.dat b/data/g2.dat new file mode 100644 index 0000000000000000000000000000000000000000..727bc37f263a834465c8acffba054badd40a0330 GIT binary patch literal 34340 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 Jcc+8k{{sW5vq1m= literal 0 HcmV?d00001 diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 18c7dfc1dd..ca7c8e0c09 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -21,6 +21,7 @@ + @@ -300,6 +301,9 @@ true winmm.lib;sdl2.lib;Dsound.lib;%(AdditionalDependencies) + + xcopy /Y "$(SolutionDir)\..\Data\*.*" "$(TargetDir)\Data\" + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index 0d27fea1b5..0d112d516f 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -433,6 +433,9 @@ Source\Windows + + Source + Source\Windows diff --git a/src/cmdline.c b/src/cmdline.c index ad2a471211..62fc461592 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -24,14 +24,18 @@ #include "cmdline.h" #include "openrct2.h" #include "platform/platform.h" +#include "util/util.h" typedef struct tm tm_t; typedef struct argparse_option argparse_option_t; typedef struct argparse argparse_t; +typedef int (*cmdline_action)(const char **argv, int argc); + int gExitCode = 0; static void print_launch_information(); +static int cmdline_call_action(const char **argv, int argc); static const char *const usage[] = { "openrct2 [options] []", @@ -73,21 +77,8 @@ int cmdline_run(const char **argv, int argc) _log_levels[DIAGNOSTIC_LEVEL_VERBOSE] = 1; if (argc != 0) { - if (_stricmp(argv[0], "intro") == 0) { - gOpenRCT2StartupAction = STARTUP_ACTION_INTRO; - } else if (_stricmp(argv[0], "edit") == 0) { - gOpenRCT2StartupAction = STARTUP_ACTION_EDIT; - if (argc >= 2) - strcpy(gOpenRCT2StartupActionPath, argv[1]); - } else { - if (platform_file_exists(argv[0])) { - gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; - strcpy(gOpenRCT2StartupActionPath, argv[0]); - } else { - fprintf(stderr, "error: %s does not exist\n", argv[0]); - return 0; - } - } + gExitCode = cmdline_call_action(argv, argc); + return 0; } print_launch_information(); @@ -113,3 +104,50 @@ static void print_launch_information() // TODO Print other potential information (e.g. user, hardware) } + +static int cmdline_for_intro(const char **argv, int argc) +{ + gOpenRCT2StartupAction = STARTUP_ACTION_INTRO; + return 0; +} + +static int cmdline_for_edit(const char **argv, int argc) +{ + gOpenRCT2StartupAction = STARTUP_ACTION_EDIT; + if (argc >= 1) + strcpy(gOpenRCT2StartupActionPath, argv[1]); + + return 0; +} + +static int cmdline_for_none(const char **argv, int argc) +{ + assert(argc >= 1); + + if (platform_file_exists(argv[0])) { + gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; + strcpy(gOpenRCT2StartupActionPath, argv[0]); + return 0; + } else { + fprintf(stderr, "error: %s does not exist\n", argv[0]); + return -1; + } +} + +struct { const char *firstArg; cmdline_action action; } cmdline_table[] = { + { "intro", cmdline_for_intro }, + { "edit", cmdline_for_edit }, + { "sprite", cmdline_for_sprite } +}; + +static int cmdline_call_action(const char **argv, int argc) +{ + for (int i = 0; i < countof(cmdline_table); i++) { + if (_stricmp(cmdline_table[i].firstArg, argv[0]) != 0) + continue; + + return cmdline_table[i].action(argv + 1, argc - 1); + } + + return cmdline_for_none(argv, argc); +} \ No newline at end of file diff --git a/src/cmdline.h b/src/cmdline.h index bb046008a0..dfb1d86b40 100644 --- a/src/cmdline.h +++ b/src/cmdline.h @@ -27,5 +27,6 @@ extern int gExitCode; int cmdline_run(const char **argv, int argc); +int cmdline_for_sprite(const char **argv, int argc); #endif \ No newline at end of file diff --git a/src/cmdline_sprite.c b/src/cmdline_sprite.c new file mode 100644 index 0000000000..d98fb2eb1b --- /dev/null +++ b/src/cmdline_sprite.c @@ -0,0 +1,678 @@ +#include +#include "cmdline.h" +#include "drawing/drawing.h" +#include "util/util.h" + +typedef struct { + uint32 num_entries; + uint32 total_size; +} rct_sprite_file_header; + +typedef struct { uint8 b, g, r, a; } rct_sprite_file_palette_entry; + +rct_sprite_file_palette_entry spriteFilePalette[256]; +static rct_sprite_file_palette_entry _standardPalette[256]; + +rct_sprite_file_header spriteFileHeader; +rct_g1_element *spriteFileEntries; +uint8 *spriteFileData; + +void sprite_file_load_palette(int spriteIndex) +{ + rct_g1_element *g1 = &spriteFileEntries[spriteIndex]; + int numPaletteEntries = g1->width; + uint8* src = g1->offset; + rct_sprite_file_palette_entry *destPaletteEntry = &spriteFilePalette[g1->x_offset]; + for (; numPaletteEntries > 0; numPaletteEntries--) { + destPaletteEntry->b = src[0]; + destPaletteEntry->g = src[1]; + destPaletteEntry->r = src[2]; + src += 3; + destPaletteEntry++; + } +} + +void sprite_entries_make_absolute() +{ + for (uint32 i = 0; i < spriteFileHeader.num_entries; i++) + spriteFileEntries[i].offset += (int)spriteFileData; +} + +void sprite_entries_make_relative() +{ + for (uint32 i = 0; i < spriteFileHeader.num_entries; i++) + spriteFileEntries[i].offset -= (int)spriteFileData; +} + +bool sprite_file_open(const char *path) +{ + FILE *file; + + file = fopen(path, "rb"); + if (file == NULL) + return false; + + if (fread(&spriteFileHeader, sizeof(rct_sprite_file_header), 1, file) != 1) { + fclose(file); + return false; + } + + if (spriteFileHeader.num_entries > 0) { + int entryTableSize = spriteFileHeader.num_entries * sizeof(rct_g1_element); + + spriteFileEntries = malloc(entryTableSize); + if (fread(spriteFileEntries, entryTableSize, 1, file) != 1) { + fclose(file); + return false; + } + + spriteFileData = malloc(spriteFileHeader.total_size); + if (fread(spriteFileData, spriteFileHeader.total_size, 1, file) != 1) { + fclose(file); + return false; + } + + sprite_entries_make_absolute(); + } + + fclose(file); + return true; +} + +bool sprite_file_save(const char *path) +{ + FILE *file = fopen(path, "wb"); + if (file == NULL) + return false; + + if (fwrite(&spriteFileHeader, sizeof(rct_sprite_file_header), 1, file) != 1) { + fclose(file); + return false; + } + + if (spriteFileHeader.num_entries > 0) { + sprite_entries_make_relative(); + + int entryTableSize = spriteFileHeader.num_entries * sizeof(rct_g1_element); + + if (fwrite(spriteFileEntries, entryTableSize, 1, file) != 1) { + sprite_entries_make_absolute(); + fclose(file); + return false; + } else { + sprite_entries_make_absolute(); + } + + if (fwrite(spriteFileData, spriteFileHeader.total_size, 1, file) != 1) { + fclose(file); + return false; + } + } + + fclose(file); + return true; +} + +void sprite_file_close() +{ + free(spriteFileEntries); + free(spriteFileData); +} + +bool sprite_file_export(int spriteIndex, const char *outPath) +{ + rct_g1_element *spriteHeader; + rct_drawpixelinfo dpi; + uint8 *pixels; + int pixelBufferSize; + + spriteHeader = &spriteFileEntries[spriteIndex]; + pixelBufferSize = spriteHeader->width * spriteHeader->height; + pixels = malloc(pixelBufferSize); + memset(pixels, 0, pixelBufferSize); + + dpi.bits = pixels; + dpi.x = 0; + dpi.y = 0; + dpi.width = spriteHeader->width; + dpi.height = spriteHeader->height; + dpi.pitch = 0; + dpi.zoom_level = 0; + + memcpy(spriteFilePalette, _standardPalette, 256 * 4); + gfx_rle_sprite_to_buffer(spriteHeader->offset, pixels, (uint8*)spriteFilePalette, &dpi, IMAGE_TYPE_NO_BACKGROUND, 0, spriteHeader->height, 0, spriteHeader->width); + + LodePNGState pngState; + unsigned int pngError; + unsigned char* pngData; + size_t pngSize; + + lodepng_state_init(&pngState); + pngState.info_raw.colortype = LCT_PALETTE; + lodepng_palette_add(&pngState.info_raw, 0, 0, 0, 0); + for (int i = 1; i < 256; i++) { + lodepng_palette_add( + &pngState.info_raw, + spriteFilePalette[i].r, + spriteFilePalette[i].g, + spriteFilePalette[i].b, + 255 + ); + } + + pngError = lodepng_encode(&pngData, &pngSize, pixels, spriteHeader->width, spriteHeader->height, &pngState); + if (pngError != 0) { + fprintf(stderr, "Error creating PNG data, %u: %s", pngError, lodepng_error_text(pngError)); + return false; + } else { + lodepng_save_file(pngData, pngSize, outPath); + free(pngData); + return true; + } +} + +int get_palette_index(uint32 colour) +{ + uint8 *rgba = (uint8*)(&colour); + + if (rgba[3] < 128) + return -1; + + for (int i = 10; i < 246; i++) { + if (spriteFilePalette[i].r != rgba[0]) continue; + if (spriteFilePalette[i].g != rgba[1]) continue; + if (spriteFilePalette[i].b != rgba[2]) continue; + return i; + } + + return -1; +} + +typedef struct { + uint8 num_pixels; + uint8 offset_x; +} rle_code; + +bool sprite_file_import(const char *path, rct_g1_element *outElement, uint8 **outBuffer, int *outBufferLength) +{ + unsigned char *pixels; + unsigned int width, height; + unsigned int pngError; + + memcpy(spriteFilePalette, _standardPalette, 256 * 4); + + pngError = lodepng_decode_file(&pixels, &width, &height, path, LCT_RGBA, 8); + if (pngError != 0) { + fprintf(stderr, "Error creating PNG data, %u: %s", pngError, lodepng_error_text(pngError)); + return false; + } + + if (width > 256 || height > 256) { + fprintf(stderr, "Only images 256x256 or less are supported."); + free(pixels); + return false; + } + + uint8 *buffer = malloc((height * 2) + (width * height * 16)); + uint16 *yOffsets = (uint16*)buffer; + uint8 *src = pixels; + uint8 *dst = buffer + (height * 2); + + for (unsigned int y = 0; y < height; y++) { + rle_code *previousCode, *currentCode; + + yOffsets[y] = (dst - buffer); + + previousCode = NULL; + currentCode = (rle_code*)dst; + dst += 2; + int startX = 0; + int pixels = 0; + bool pushRun = false; + for (unsigned int x = 0; x < width; x++) { + int paletteIndex = get_palette_index(*((uint32*)src)); + src += 4; + if (paletteIndex == -1) { + if (pixels != 0) { + x--; + src -= 4; + pushRun = true; + } + } else { + if (pixels == 0) + startX = x; + pixels++; + *dst++ = (uint8)paletteIndex; + } + if (pixels == 127 || x == width - 1) + pushRun = true; + + if (pushRun) { + if (pixels > 0) { + previousCode = currentCode; + currentCode->num_pixels = pixels; + currentCode->offset_x = startX; + + if (x == width - 1) + currentCode->num_pixels |= 0x80; + + currentCode = (rle_code*)dst; + dst += 2; + } else { + if (previousCode == NULL) { + currentCode->num_pixels = 0x80; + currentCode->offset_x = 0; + } else { + previousCode->num_pixels |= 0x80; + dst -= 2; + } + } + startX = 0; + pixels = 0; + pushRun = false; + } + } + } + free(pixels); + + int bufferLength = (int)(dst - buffer); + buffer = realloc(buffer, bufferLength); + + outElement->offset = buffer; + outElement->width = width; + outElement->height = height; + outElement->flags = G1_FLAG_RLE_COMPRESSION; + outElement->x_offset = 0; + outElement->y_offset = 0; + outElement->zoomed_offset = 0; + + *outBuffer = buffer; + *outBufferLength = bufferLength; + return true; +} + +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 [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 \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)) { + 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 \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 \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)) + 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)); + spriteFileData = realloc(spriteFileData, spriteFileHeader.total_size); + 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 { + fprintf(stderr, "Unknown sprite command."); + return -1; + } +} + +static rct_sprite_file_palette_entry _standardPalette[256] = { + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 35, 35, 23, 255 }, + { 51, 51, 35, 255 }, + { 67, 67, 47, 255 }, + { 83, 83, 63, 255 }, + { 99, 99, 75, 255 }, + { 115, 115, 91, 255 }, + { 131, 131, 111, 255 }, + { 151, 151, 131, 255 }, + { 175, 175, 159, 255 }, + { 195, 195, 183, 255 }, + { 219, 219, 211, 255 }, + { 243, 243, 239, 255 }, + { 0, 47, 51, 255 }, + { 0, 59, 63, 255 }, + { 11, 75, 79, 255 }, + { 19, 91, 91, 255 }, + { 31, 107, 107, 255 }, + { 47, 123, 119, 255 }, + { 59, 139, 135, 255 }, + { 79, 155, 151, 255 }, + { 95, 175, 167, 255 }, + { 115, 191, 187, 255 }, + { 139, 207, 203, 255 }, + { 163, 227, 223, 255 }, + { 7, 43, 67, 255 }, + { 11, 59, 87, 255 }, + { 23, 75, 111, 255 }, + { 31, 87, 127, 255 }, + { 39, 99, 143, 255 }, + { 51, 115, 159, 255 }, + { 67, 131, 179, 255 }, + { 87, 151, 191, 255 }, + { 111, 175, 203, 255 }, + { 135, 199, 219, 255 }, + { 163, 219, 231, 255 }, + { 195, 239, 247, 255 }, + { 0, 27, 71, 255 }, + { 0, 43, 95, 255 }, + { 0, 63, 119, 255 }, + { 7, 83, 143, 255 }, + { 7, 111, 167, 255 }, + { 15, 139, 191, 255 }, + { 19, 167, 215, 255 }, + { 27, 203, 243, 255 }, + { 47, 231, 255, 255 }, + { 95, 243, 255, 255 }, + { 143, 251, 255, 255 }, + { 195, 255, 255, 255 }, + { 0, 0, 35, 255 }, + { 0, 0, 79, 255 }, + { 7, 7, 95, 255 }, + { 15, 15, 111, 255 }, + { 27, 27, 127, 255 }, + { 39, 39, 143, 255 }, + { 59, 59, 163, 255 }, + { 79, 79, 179, 255 }, + { 103, 103, 199, 255 }, + { 127, 127, 215, 255 }, + { 159, 159, 235, 255 }, + { 191, 191, 255, 255 }, + { 19, 51, 27, 255 }, + { 23, 63, 35, 255 }, + { 31, 79, 47, 255 }, + { 39, 95, 59, 255 }, + { 43, 111, 71, 255 }, + { 51, 127, 87, 255 }, + { 59, 143, 99, 255 }, + { 67, 155, 115, 255 }, + { 75, 171, 131, 255 }, + { 83, 187, 147, 255 }, + { 95, 203, 163, 255 }, + { 103, 219, 183, 255 }, + { 27, 55, 31, 255 }, + { 35, 71, 47, 255 }, + { 43, 83, 59, 255 }, + { 55, 99, 75, 255 }, + { 67, 111, 91, 255 }, + { 79, 135, 111, 255 }, + { 95, 159, 135, 255 }, + { 111, 183, 159, 255 }, + { 127, 207, 183, 255 }, + { 147, 219, 195, 255 }, + { 167, 231, 207, 255 }, + { 191, 247, 223, 255 }, + { 0, 63, 15, 255 }, + { 0, 83, 19, 255 }, + { 0, 103, 23, 255 }, + { 0, 123, 31, 255 }, + { 7, 143, 39, 255 }, + { 23, 159, 55, 255 }, + { 39, 175, 71, 255 }, + { 63, 191, 91, 255 }, + { 87, 207, 111, 255 }, + { 115, 223, 139, 255 }, + { 143, 239, 163, 255 }, + { 179, 255, 195, 255 }, + { 19, 43, 79, 255 }, + { 27, 55, 99, 255 }, + { 43, 71, 119, 255 }, + { 59, 87, 139, 255 }, + { 67, 99, 167, 255 }, + { 83, 115, 187, 255 }, + { 99, 131, 207, 255 }, + { 115, 151, 215, 255 }, + { 131, 171, 227, 255 }, + { 151, 191, 239, 255 }, + { 171, 207, 247, 255 }, + { 195, 227, 255, 255 }, + { 55, 19, 15, 255 }, + { 87, 43, 39, 255 }, + { 103, 55, 51, 255 }, + { 119, 67, 63, 255 }, + { 139, 83, 83, 255 }, + { 155, 99, 99, 255 }, + { 175, 119, 119, 255 }, + { 191, 139, 139, 255 }, + { 207, 159, 159, 255 }, + { 223, 183, 183, 255 }, + { 239, 211, 211, 255 }, + { 255, 239, 239, 255 }, + { 111, 27, 0, 255 }, + { 151, 39, 0, 255 }, + { 167, 51, 7, 255 }, + { 187, 67, 15, 255 }, + { 203, 83, 27, 255 }, + { 223, 103, 43, 255 }, + { 227, 135, 67, 255 }, + { 231, 163, 91, 255 }, + { 239, 187, 119, 255 }, + { 243, 211, 143, 255 }, + { 251, 231, 175, 255 }, + { 255, 247, 215, 255 }, + { 15, 43, 11, 255 }, + { 23, 55, 15, 255 }, + { 31, 71, 23, 255 }, + { 43, 83, 35, 255 }, + { 59, 99, 47, 255 }, + { 75, 115, 59, 255 }, + { 95, 135, 79, 255 }, + { 119, 155, 99, 255 }, + { 139, 175, 123, 255 }, + { 167, 199, 147, 255 }, + { 195, 219, 175, 255 }, + { 223, 243, 207, 255 }, + { 95, 0, 63, 255 }, + { 115, 7, 75, 255 }, + { 127, 15, 83, 255 }, + { 143, 31, 95, 255 }, + { 155, 43, 107, 255 }, + { 171, 63, 123, 255 }, + { 187, 83, 135, 255 }, + { 199, 103, 155, 255 }, + { 215, 127, 171, 255 }, + { 231, 155, 191, 255 }, + { 243, 195, 215, 255 }, + { 255, 235, 243, 255 }, + { 0, 0, 63, 255 }, + { 0, 0, 87, 255 }, + { 0, 0, 115, 255 }, + { 0, 0, 143, 255 }, + { 0, 0, 171, 255 }, + { 0, 0, 199, 255 }, + { 0, 7, 227, 255 }, + { 0, 7, 255, 255 }, + { 67, 79, 255, 255 }, + { 115, 123, 255, 255 }, + { 163, 171, 255, 255 }, + { 215, 219, 255, 255 }, + { 0, 39, 79, 255 }, + { 0, 51, 111, 255 }, + { 0, 63, 147, 255 }, + { 0, 71, 183, 255 }, + { 0, 79, 219, 255 }, + { 0, 83, 255, 255 }, + { 23, 111, 255, 255 }, + { 51, 139, 255, 255 }, + { 79, 163, 255, 255 }, + { 107, 183, 255, 255 }, + { 135, 203, 255, 255 }, + { 163, 219, 255, 255 }, + { 47, 51, 0, 255 }, + { 55, 63, 0, 255 }, + { 67, 75, 0, 255 }, + { 79, 87, 0, 255 }, + { 99, 107, 7, 255 }, + { 119, 127, 23, 255 }, + { 143, 147, 43, 255 }, + { 163, 167, 71, 255 }, + { 187, 187, 99, 255 }, + { 207, 207, 131, 255 }, + { 231, 231, 171, 255 }, + { 255, 255, 207, 255 }, + { 27, 0, 63, 255 }, + { 51, 0, 103, 255 }, + { 63, 11, 123, 255 }, + { 79, 23, 143, 255 }, + { 95, 31, 163, 255 }, + { 111, 39, 183, 255 }, + { 143, 59, 219, 255 }, + { 171, 91, 239, 255 }, + { 187, 119, 243, 255 }, + { 203, 151, 247, 255 }, + { 223, 183, 251, 255 }, + { 239, 215, 255, 255 }, + { 0, 19, 39, 255 }, + { 7, 31, 55, 255 }, + { 15, 47, 71, 255 }, + { 31, 63, 91, 255 }, + { 51, 83, 107, 255 }, + { 75, 103, 123, 255 }, + { 107, 127, 143, 255 }, + { 127, 147, 163, 255 }, + { 147, 171, 187, 255 }, + { 171, 195, 207, 255 }, + { 195, 219, 231, 255 }, + { 223, 243, 255, 255 }, + { 75, 75, 55, 255 }, + { 0, 183, 255, 255 }, + { 0, 219, 255, 255 }, + { 0, 255, 255, 255 }, + { 99, 107, 7, 255 }, + { 99, 107, 7, 255 }, + { 135, 143, 39, 255 }, + { 123, 131, 27, 255 }, + { 99, 107, 7, 255 }, + { 151, 155, 55, 255 }, + { 151, 155, 55, 255 }, + { 227, 227, 155, 255 }, + { 203, 203, 115, 255 }, + { 151, 155, 55, 255 }, + { 91, 91, 67, 255 }, + { 107, 107, 83, 255 }, + { 123, 123, 99, 255 }, + { 47, 47, 47, 255 }, + { 47, 47, 47, 255 }, + { 47, 71, 87, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 }, + { 0, 0, 0, 255 } +}; \ No newline at end of file diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 8b24d08386..e258f07654 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -90,6 +90,7 @@ void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, short left, short top, short ri // sprite int gfx_load_g1(); +int gfx_load_g2(); void gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unknown_pointer, uint8* source_pointer, uint8* dest_pointer, rct_g1_element* source_image, rct_drawpixelinfo *dest_dpi, int height, int width, int image_type); void gfx_rle_sprite_to_buffer(uint8* source_bits_pointer, uint8* dest_bits_pointer, uint8* palette_pointer, rct_drawpixelinfo *dpi, int image_type, int source_y_start, int height, int source_x_start, int width); void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour); diff --git a/src/drawing/sprite.c b/src/drawing/sprite.c index d2ee61e884..0f102dd57b 100644 --- a/src/drawing/sprite.c +++ b/src/drawing/sprite.c @@ -20,6 +20,7 @@ #include "../addresses.h" #include "../common.h" +#include "../sprites.h" #include "drawing.h" typedef struct { @@ -29,6 +30,14 @@ typedef struct { void *_g1Buffer = NULL; +typedef struct { + rct_g1_header header; + rct_g1_element *elements; + void *data; +} rct_gx; + +rct_gx g2; + /** * * rct2: 0x00678998 @@ -74,6 +83,41 @@ int gfx_load_g1() return 0; } +int gfx_load_g2() +{ + log_verbose("loading g2 graphics"); + + FILE *file; + unsigned int i; + + file = fopen("data/g2.dat", "rb"); + if (file != NULL) { + if (fread(&g2.header, 8, 1, file) == 1) { + // Read element headers + g2.elements = malloc(g2.header.num_entries * sizeof(rct_g1_element)); + fread(g2.elements, g2.header.num_entries * sizeof(rct_g1_element), 1, file); + + // Read element data + g2.data = malloc(g2.header.total_size); + fread(g2.data, g2.header.total_size, 1, file); + + fclose(file); + + // Fix entry data offsets + for (i = 0; i < g2.header.num_entries; i++) + g2.elements[i].offset += (int)g2.data; + + // Successful + return 1; + } + fclose(file); + } + + // Unsuccessful + log_fatal("Unable to load g2 graphics"); + return 0; +} + /** * Copies a sprite onto the buffer. There is no compression used on the sprite * image. @@ -418,11 +462,17 @@ void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 * x (cx) * y (dx) */ -void gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer){ - int image_element = 0x7FFFF&image_id; +void gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer) +{ + int image_element = image_id & 0x7FFFF; int image_type = (image_id & 0xE0000000) >> 28; - rct_g1_element* g1_source = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_element]); + rct_g1_element* g1_source; + if (image_element < SPR_G2_BEGIN) { + g1_source = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_element]); + } else { + g1_source = &g2.elements[image_element - SPR_G2_BEGIN]; + } //Zooming code has been integrated into main code. //if (dpi->zoom_level >= 1){ //These have not been tested diff --git a/src/rct2.c b/src/rct2.c index f70848a2a7..01fdc105b0 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -94,6 +94,7 @@ int rct2_init() track_load_list(item); gfx_load_g1(); + gfx_load_g2(); gfx_load_character_widths(); platform_init(); audio_init1(); diff --git a/src/sprites.h b/src/sprites.h index 5d8e4a49e3..1993c61202 100644 --- a/src/sprites.h +++ b/src/sprites.h @@ -345,6 +345,9 @@ enum { SPR_INTRO_INFOGRAMES_01 = SPR_INTRO_INFOGRAMES_00 + 2, SPR_INTRO_INFOGRAMES_11 = SPR_INTRO_INFOGRAMES_00 + 3, SPR_CREDITS_INFOGRAMES = 23230, + + SPR_G2_BEGIN = 324288, + SPR_G2_LOGO = SPR_G2_BEGIN + 0 }; #endif diff --git a/src/windows/title_logo.c b/src/windows/title_logo.c index ad42ae327a..7ec8660e9c 100644 --- a/src/windows/title_logo.c +++ b/src/windows/title_logo.c @@ -101,7 +101,8 @@ static void window_title_logo_paint() window_paint_get_registers(w, dpi); - gfx_draw_sprite(dpi, SPR_MENU_LOGO, w->x, w->y, 0); + // gfx_draw_sprite(dpi, SPR_MENU_LOGO, w->x, w->y, 0); + gfx_draw_sprite(dpi, SPR_G2_LOGO, w->x, w->y, 0); window_title_logo_draw_expansion_packs(dpi); }