From 80266d6454743452917092b6ecb82fa360be9751 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 14 Jun 2020 10:33:12 +0900 Subject: [PATCH] Support JPEG image format JPEG images are not used in AliceSoft games, but supported since System3.6 version 3.23 and used in some third-party games (e.g. Graymerca). --- .github/workflows/windows.yml | 2 +- CMakeLists.txt | 5 +++ README.md | 4 +- config.h.in | 1 + modules/CMakeLists.txt | 4 +- src/CMakeLists.txt | 4 ++ src/cg.c | 23 +++++++++++- src/cg.h | 3 +- src/jpeg.c | 70 +++++++++++++++++++++++++++++++++++ src/jpeg.h | 28 ++++++++++++++ src/savedata.c | 13 +++---- src/savedata.h | 2 +- 12 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 src/jpeg.c create mode 100644 src/jpeg.h diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ab73d01..2826769 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -31,7 +31,7 @@ jobs: echo PATH: $PATH - name: Install Deps - run: pacman -S --noconfirm ${{ matrix.package }}-SDL2 ${{ matrix.package }}-SDL2_ttf ${{ matrix.package }}-SDL2_mixer + run: pacman -S --noconfirm ${{ matrix.package }}-SDL2 ${{ matrix.package }}-SDL2_ttf ${{ matrix.package }}-SDL2_mixer ${{ matrix.package }}-libjpeg-turbo - name: Checkout uses: actions/checkout@v2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 16d5fc0..a45f0c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,11 @@ else() optional_pkg_check_modules(SDL2MIXER IMPORTED_TARGET SDL2_mixer) optional_pkg_check_modules(SDL2TTF IMPORTED_TARGET SDL2_ttf) + include(FindJPEG) + if (JPEG_FOUND) + set(HAVE_JPEG 1) + endif() + set(DEFAULT_FONT_PATH ${CMAKE_INSTALL_PREFIX}/share/xsystem35/fonts/) endif() diff --git a/README.md b/README.md index fa91541..a10f8ab 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ cmake の実行でエラーになる場合は必要なライブラリをイン [Homebrew](https://brew.sh/index_ja) が必要です。 - $ brew install cmake pkg-config sdl2 sdl2_mixer freetype + $ brew install cmake pkg-config sdl2 sdl2_mixer freetype libjpeg $ mkdir -p out/debug $ cd out/debug $ cmake -DCMAKE_BUILD_TYPE=Debug ../../ @@ -30,7 +30,7 @@ cmake の実行でエラーになる場合は必要なライブラリをイン [MSYS2](https://www.msys2.org) が必要です。 - $ pacman -S cmake mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_ttf mingw-w64-x86_64-SDL2_mixer + $ pacman -S cmake mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_ttf mingw-w64-x86_64-SDL2_mixer mingw-w64-x86_64-libjpeg-turbo $ mkdir -p out/debug $ cd out/debug $ cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug ../../ diff --git a/config.h.in b/config.h.in index b7bc127..0b0bcf4 100644 --- a/config.h.in +++ b/config.h.in @@ -33,6 +33,7 @@ #cmakedefine QUIET_MIDI @QUIET_MIDI@ #cmakedefine HAVE_GETLOGIN @HAVE_GETLOGIN@ +#cmakedefine HAVE_JPEG @HAVE_JPEG@ #cmakedefine HAVE_MMAP @HAVE_MMAP@ #cmakedefine HAVE_SDLJOY @HAVE_SDLJOY@ #cmakedefine HAVE_SIGACTION @HAVE_SIGACTION@ diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 377901c..09a0ce4 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -81,9 +81,7 @@ if (SDL2MIXER_FOUND) endif() endif() -include(FindJPEG) -if (JPEG_FOUND) - target_compile_definitions(modules PRIVATE HAVE_JPEG) +if (HAVE_JPEG) target_sources(modules PRIVATE NightDemonDemo/ndd.c NightDemonDemo/jpeg2surface.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1d40225..3925751 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,10 @@ target_sources(xsystem35 PRIVATE # CG target_sources(xsystem35 PRIVATE pms.c vsp.c bmp.c qnt.c) +if (HAVE_JPEG) + target_sources(xsystem35 PRIVATE jpeg.c) + target_link_libraries(xsystem35 PRIVATE JPEG::JPEG) +endif() # Music target_sources(xsystem35 PRIVATE diff --git a/src/cg.c b/src/cg.c index e7adc07..5a4579c 100644 --- a/src/cg.c +++ b/src/cg.c @@ -33,6 +33,9 @@ #include "pms.h" #include "bmp.h" #include "qnt.h" +#ifdef HAVE_JPEG +#include "jpeg.h" +#endif #include "ald_manager.h" #include "savedata.h" #include "cache.h" @@ -85,6 +88,10 @@ static CG_TYPE check_cgformat(BYTE *data) { return ALCG_BMP8; } else if (vsp_checkfmt(data)) { return ALCG_VSP; +#ifdef HAVE_JPEG + } else if (jpeg_checkfmt(data) && nact->sys_world_depth >= 15) { + return ALCG_JPEG; +#endif } WARNING("Unknown Cg Type\n"); return ALCG_UNKNOWN; @@ -182,6 +189,7 @@ static void display_cg(cgdata *cg, int x, int y) { ags_drawCg8bit(cg, x, y); break; case ALCG_PMS16: case ALCG_BMP24: + case ALCG_JPEG: ags_drawCg16bit(cg, x, y); break; default: break; @@ -243,6 +251,12 @@ static cgdata *loader(int no) { cg = qnt_extract(dfile->data); size = (cg->width * cg->height) * 3; break; +#ifdef HAVE_JPEG + case ALCG_JPEG: + cg = jpeg_extract(dfile->data, dfile->size); + size = (cg->width * cg->height) * sizeof(WORD); + break; +#endif default: break; } @@ -395,6 +409,7 @@ void cg_load(int no, int flg) { break; case ALCG_PMS16: case ALCG_BMP24: + case ALCG_JPEG: if (GCMD_EXTRACTCG(cg_fflg)) { /* set display offset */ p = set_display_loc(cg); @@ -463,11 +478,12 @@ void cg_load_with_alpha(int cgno, int shadowno) { */ int cg_load_with_filename(char *name, int x, int y) { int status, type; + long filesize; BYTE *data; cgdata *cg = NULL; MyPoint p; - data = load_cg_with_file(name, &status); + data = load_cg_with_file(name, &status, &filesize); if (data == NULL) return status; cg_set_display_location(x, y, OFFSET_ABSOLUTE_GC); @@ -480,6 +496,11 @@ int cg_load_with_filename(char *name, int x, int y) { case ALCG_BMP24: cg = bmp16m_extract(data); break; +#ifdef HAVE_JPEG + case ALCG_JPEG: + cg = jpeg_extract(data, filesize); + break; +#endif default: return status; } diff --git a/src/cg.h b/src/cg.h index f8a2435..2888bc6 100644 --- a/src/cg.h +++ b/src/cg.h @@ -37,7 +37,8 @@ typedef enum { ALCG_PMS16 = 4, ALCG_BMP8 = 5, ALCG_BMP24 = 6, - ALCG_QNT = 7 + ALCG_QNT = 7, + ALCG_JPEG = 8, } CG_TYPE; /* diff --git a/src/jpeg.c b/src/jpeg.c new file mode 100644 index 0000000..f64851a --- /dev/null +++ b/src/jpeg.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include "config.h" + +#include +#include +#include + +#include "system.h" +#include "ags.h" +#include "jpeg.h" + +boolean jpeg_checkfmt(BYTE *data) { + return data[0] == 0xff && data[1] == 0xd8; +} + +cgdata *jpeg_extract(BYTE *data, size_t size) { + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + + // TODO: Error handling + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + + jpeg_mem_src(&cinfo, data, size); + if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) { + WARNING("jpeg_read_header failed\n"); + jpeg_destroy_decompress(&cinfo); + return NULL; + } + + jpeg_start_decompress(&cinfo); + + cgdata *cg = calloc(1, sizeof(cgdata)); + cg->type = ALCG_JPEG; + cg->width = cinfo.output_width; + cg->height = cinfo.output_height; + cg->pic = malloc(sizeof(WORD) * cg->width * cg->height); + + int row_stride = cinfo.output_width * cinfo.output_components; + JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + + WORD *dst = (WORD *)cg->pic; + while (cinfo.output_scanline < cinfo.output_height) { + jpeg_read_scanlines(&cinfo, buffer, 1); + for (int x = 0; x < cinfo.output_width; x++) + *dst++ = PIX16(buffer[0][x * 3], buffer[0][x * 3 + 1], buffer[0][x * 3 + 2]); + } + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + return cg; +} diff --git a/src/jpeg.h b/src/jpeg.h new file mode 100644 index 0000000..ccd211b --- /dev/null +++ b/src/jpeg.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#ifndef __JPEG_H__ +#define __JPEG_H__ + +#include "cg.h" + +extern boolean jpeg_checkfmt(BYTE *data); +extern cgdata *jpeg_extract(BYTE *data, size_t size); + +#endif // __JPEG_H__ diff --git a/src/savedata.c b/src/savedata.c index f9293ea..e3f88e9 100644 --- a/src/savedata.c +++ b/src/savedata.c @@ -755,11 +755,10 @@ static int saveGameData(int no, char *buf, int size) { } /* 指定ファイルからの画像の読み込み thanx tajiru@wizard */ -BYTE* load_cg_with_file(char *filename, int *status){ +BYTE* load_cg_with_file(char *filename, int *status, long *filesize){ int size; FILE *fp; static BYTE *tmp; - long filesize; *status = 0; @@ -768,20 +767,20 @@ BYTE* load_cg_with_file(char *filename, int *status){ } fseek(fp, 0L, SEEK_END); - filesize = ftell(fp); - if (filesize == 0) { + *filesize = ftell(fp); + if (*filesize == 0) { *status = SAVE_LOADERR; return NULL; } - tmp = (char *)malloc(filesize); + tmp = (char *)malloc(*filesize); if (tmp == NULL) { WARNING("Out of memory\n"); *status = SAVE_LOADERR; return NULL; } fseek(fp, 0L, SEEK_SET); - size = fread(tmp, 1, filesize,fp); + size = fread(tmp, 1, *filesize,fp); - if (size != filesize) { + if (size != *filesize) { *status = SAVE_LOADSHORTAGE; } else { *status = SAVE_LOADOK; diff --git a/src/savedata.h b/src/savedata.h index 9310c67..7ece830 100644 --- a/src/savedata.h +++ b/src/savedata.h @@ -124,7 +124,7 @@ extern int save_save_var_with_file(char *filename, int *start, int cnt); extern int save_load_var_with_file(char *filename, int *start, int cnt); extern int save_save_str_with_file(char *filename, int start, int cnt); extern int save_load_str_with_file(char *filename, int start, int cnt); -extern BYTE* load_cg_with_file(char *file,int *status); +extern BYTE* load_cg_with_file(char *file, int *status, long *filesize); extern void save_set_path(char *path); extern void save_register_file(char *name, int index); extern char* save_get_file(int index);