diff --git a/data/g2.dat b/data/g2.dat new file mode 100644 index 0000000000..727bc37f26 Binary files /dev/null and b/data/g2.dat differ 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); }