From af8e3f881851fd505fafeeab47becebfdc1a8d3c Mon Sep 17 00:00:00 2001 From: brliron Date: Sun, 5 Nov 2017 00:06:53 +0100 Subject: [PATCH] thcrap_tasofro: add png->bmp conversion --- thcrap_tasofro/src/nsml.cpp | 76 ++++++++++++++++++++++++++++- thcrap_tasofro/src/thcrap_tasofro.h | 5 +- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/thcrap_tasofro/src/nsml.cpp b/thcrap_tasofro/src/nsml.cpp index da073b28..268bd200 100644 --- a/thcrap_tasofro/src/nsml.cpp +++ b/thcrap_tasofro/src/nsml.cpp @@ -12,10 +12,16 @@ #include "thcrap_tasofro.h" int patch_cv2(void *file_inout, size_t size_out, size_t size_in, const char *fn, json_t*); +int patch_bmp(void *file_inout, size_t size_out, size_t size_in, const char *fn, json_t*); int nsml_init() { - patchhook_register("*.cv2", patch_cv2); + if (game_id == TH_MEGAMARI) { + patchhook_register("*.bmp", patch_bmp); + } + if (game_id == TH_NSML) { + patchhook_register("*.cv2", patch_cv2); + } return 0; } @@ -65,6 +71,74 @@ int patch_cv2(void *file_inout, size_t size_out, size_t size_in, const char *fn, return 1; } +int patch_bmp(void *file_inout, size_t size_out, size_t size_in, const char *fn, json_t*) +{ + VLA(char, fn_png, strlen(fn) + 1); + strcpy(fn_png, fn); + strcpy(PathFindExtensionA(fn_png), ".png"); + + uint32_t width, height, rowbytes; + uint8_t bpp; + BYTE** row_pointers = png_image_read(fn_png, &width, &height, &bpp); + VLA_FREE(fn_png); + + if (!row_pointers) { + return 0; + } + + rowbytes = width * bpp / 8; + if (rowbytes % 4 != 0) { + rowbytes += 4 - (rowbytes % 4); + } + if (size_out < sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + rowbytes * height) { + log_print("Destination buffer too small!\n"); + free(row_pointers); + return -1; + } + + BITMAPFILEHEADER *bpFile = (BITMAPFILEHEADER*)file_inout; + BITMAPINFOHEADER *bpInfo = (BITMAPINFOHEADER*)(bpFile + 1); + BYTE *bpData = (BYTE*)(bpInfo + 1); + bpFile->bfType = 0x4D42; + bpFile->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + rowbytes * height; + bpFile->bfReserved1 = 0; + bpFile->bfReserved2 = 0; + bpFile->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + + bpInfo->biSize = sizeof(BITMAPINFOHEADER); + bpInfo->biWidth = width; + bpInfo->biHeight = height; + bpInfo->biPlanes = 1; + bpInfo->biBitCount = bpp; + bpInfo->biCompression = (bpp == 32 ? BI_BITFIELDS : BI_RGB); + bpInfo->biSizeImage = rowbytes * height; + bpInfo->biXPelsPerMeter = 65535; + bpInfo->biYPelsPerMeter = 65535; + bpInfo->biClrUsed = 0; + bpInfo->biClrImportant = 0; + + for (unsigned int h = 0; h < height; h++) { + unsigned int pos = 0; + for (unsigned int w = 0; w < width; w++) { + bpData[h * rowbytes + pos + 0] = row_pointers[height - h - 1][w * bpp / 8 + 2]; + bpData[h * rowbytes + pos + 1] = row_pointers[height - h - 1][w * bpp / 8 + 1]; + bpData[h * rowbytes + pos + 2] = row_pointers[height - h - 1][w * bpp / 8 + 0]; + if (bpp == 32) { + bpData[h * rowbytes + pos + 3] = row_pointers[height - h - 1][w * bpp / 8 + 3]; + } + pos += bpp / 8; + } + // Padding + while (pos % 4) { + bpData[h * rowbytes + pos] = 0; + pos++; + } + } + + free(row_pointers); + return 1; +} + int BP_nsml_file_header(x86_reg_t *regs, json_t *bp_info) { // Parameters diff --git a/thcrap_tasofro/src/thcrap_tasofro.h b/thcrap_tasofro/src/thcrap_tasofro.h index eefeb172..ed69d9e5 100644 --- a/thcrap_tasofro/src/thcrap_tasofro.h +++ b/thcrap_tasofro/src/thcrap_tasofro.h @@ -14,10 +14,13 @@ typedef enum { TH_NONE, - // • Doesn't share any code with the other formats + // • nsml engine TH_MEGAMARI, + + // • Use a slightly different XORing TH_NSML, + // • th135 engine // • filename hash: uses hash = ch ^ 0x1000193 * hash // • spells: using data/csv/Item*.csv // • spells: data/csv/story/*/*.csv has columns for popularity