From 901a3bb28c5d8d8faaeee5b9ae84414a195ee145 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sat, 2 Apr 2022 09:50:16 +0900 Subject: [PATCH] Revamp NightDemonDemo - Fix off-by-one bug in demo number - Use the jpeg extraction function in src/ - Improve alk archive interface --- modules/CMakeLists.txt | 10 +-- modules/NightDemonDemo/NightDemonDemo.c | 63 ++++++++++++-- modules/NightDemonDemo/jpeg2surface.c | 97 --------------------- modules/NightDemonDemo/ndd.c | 110 ------------------------ modules/lib/alk.c | 31 ++----- modules/lib/alk.h | 25 ++---- modules/lib/cg.c | 7 +- src/cg.c | 3 +- src/cg.h | 1 + 9 files changed, 81 insertions(+), 266 deletions(-) delete mode 100644 modules/NightDemonDemo/jpeg2surface.c delete mode 100644 modules/NightDemonDemo/ndd.c diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index f249492..20dfea6 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -118,12 +118,6 @@ else() endif() endif() -if (HAVE_JPEG) - target_sources(modules PRIVATE - NightDemonDemo/ndd.c - NightDemonDemo/jpeg2surface.c - ) - if (NOT EMSCRIPTEN) - target_link_libraries(modules PRIVATE JPEG::JPEG) - endif() +if (HAVE_JPEG AND NOT EMSCRIPTEN) + target_link_libraries(modules PRIVATE JPEG::JPEG) endif() diff --git a/modules/NightDemonDemo/NightDemonDemo.c b/modules/NightDemonDemo/NightDemonDemo.c index 33d6cd7..175ab83 100644 --- a/modules/NightDemonDemo/NightDemonDemo.c +++ b/modules/NightDemonDemo/NightDemonDemo.c @@ -30,9 +30,65 @@ #include "xsystem35.h" #include "modules.h" #include "nact.h" +#include "alk.h" +#include "music.h" +#include "sdl_core.h" +#include "input.h" +#include "ngraph.h" +#include "cg.h" +#ifdef HAVE_JPEG +#include "jpeg.h" +#endif -extern void ndd_init(const char *files[], int n); -extern void ndd_run(int demonum); +#ifdef HAVE_JPEG + +#define FPS 30 + +static const int ndemo_mus[3] = {0, 1, 85}; + +static void ndd_run(int demonum) { + const char *alk_path = nact->files.alk[demonum + 1]; + alk_t *alk = alk_new(alk_path); + if (alk == NULL) return; + + while (sys_getInputInfo()); // wait for key up + + int mus = ndemo_mus[demonum]; + if (mus) + mus_bgm_play(mus, 0, 100); + + uint32_t start = sdl_getTicks(); + while (!nact->is_quit) { + int i = (sdl_getTicks() - start) / (1000 / FPS); + if (i >= alk->datanum) + break; + + cgdata *cg = jpeg_extract(alk->entries[i].data, alk->entries[i].size); + if (cg) { + gr_drawimage16(sf0, cg, 0, 0); + ags_updateFull(); + cgdata_free(cg); + } else { + WARNING("Cannot decode CG %d in %s\n", i, alk_path); + } + + int wait_ms = (i + 1) * (1000 / FPS) - (sdl_getTicks() - start); + if (wait_ms > 0) { + if (sys_keywait(wait_ms, KEYWAIT_CANCELABLE)) + break; + } else { + if (sys_getInputInfo()) + break; + } + } + + if (mus) + mus_bgm_stop(ndemo_mus[demonum], 0); + + alk_free(alk); +} + +#endif static void Init() { int p1 = getCaliValue(); /* ISys3x */ @@ -40,9 +96,6 @@ static void Init() { int p3 = getCaliValue(); /* ITimer */ int *var = getCaliVariable(); -#ifdef HAVE_JPEG - ndd_init(nact->files.alk, 4); -#endif *var = 1; DEBUG_COMMAND("NightDemonDemo.Init %d,%d,%d,%p:\n", p1, p2, p3, var); diff --git a/modules/NightDemonDemo/jpeg2surface.c b/modules/NightDemonDemo/jpeg2surface.c deleted file mode 100644 index 51d834a..0000000 --- a/modules/NightDemonDemo/jpeg2surface.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * jpeg2surface.c: - * - * Copyright (C) 1997-1998 Masaki Chikama (Wren) - * 1998- - * - * 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 - * -*/ -/* $Id: jpeg2surface.c,v 1.2 2003/11/09 15:06:12 chikama Exp $ */ - -#include -#include -#undef max -#undef min - -#include "config.h" - -#include "portab.h" -#include "ags.h" -#include "surface.h" -#include "ngraph.h" - -static void ppm2surface(surface_t *sf, int curscanline, unsigned char *src, int width) { - BYTE *dp = GETOFFSET_PIXEL(sf, 0, curscanline); - - switch (sf->depth) { - case 16: - { - WORD *dst = (WORD *)dp; - while (width--) { - *dst = PIX16(*src, *(src +1), *(src +2)); - dst++; src+= 3; - } - break; - } - case 24: - case 32: - { - DWORD *dst = (DWORD *)dp; - while (width--) { - *dst = PIX24(*src, *(src +1), *(src +2)); - dst++; src+= 3; - } - break; - }} -} - -// sf0 に直接描く(それでも遅いけど) -surface_t *jpeg2surface(FILE *fp, int offset) { - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - int row_stride; - surface_t *sf; - JSAMPARRAY buffer; - - fseek(fp, offset, SEEK_SET); - - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_decompress(&cinfo); - - jpeg_stdio_src(&cinfo, fp); - jpeg_read_header(&cinfo, TRUE); - - cinfo.do_fancy_upsampling = FALSE; - cinfo.do_block_smoothing = FALSE; - - jpeg_start_decompress(&cinfo); - //fprintf(stderr, "width = %d, height = %d\n", cinfo.output_width, cinfo.output_height); - - //sf = sf_create_pixel(cinfo.output_width, cinfo.output_height, sf0->depth); - sf = sf0; - - row_stride = cinfo.output_width * cinfo.output_components; - buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - - while (cinfo.output_scanline < cinfo.output_height) { - jpeg_read_scanlines(&cinfo, buffer, 1); - ppm2surface(sf, cinfo.output_scanline -1, buffer[0], cinfo.output_width); - } - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - - return sf; -} diff --git a/modules/NightDemonDemo/ndd.c b/modules/NightDemonDemo/ndd.c deleted file mode 100644 index a6ea76d..0000000 --- a/modules/NightDemonDemo/ndd.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * ndd.c: - * - * Copyright (C) 1997-1998 Masaki Chikama (Wren) - * 1998- - * - * 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 - * -*/ -/* $Id: ndd.c,v 1.2 2003/11/09 15:06:12 chikama Exp $ */ - -#include -#include - -#include "portab.h" -#include "ags.h" -#include "alk.h" -#include "system.h" -#include "surface.h" -#include "music.h" -#include "sdl_core.h" -#include "ngraph.h" -#include "input.h" - -// 0: AliceSoft -// 1: Opening -// 2: Meteo - -struct nddemo { - const char **fn; - alk_t *alk; - surface_t *sf[10]; -}; - -static struct nddemo ndd; -static int ndemo_alk[3] = {2, 3, 4}; -static int ndemo_mus[3] = {0, 1, 85}; -static int ndemo_nums[3] = {150, 603, 467}; - -extern surface_t *jpeg2surface(FILE *fp, int offset); - -// ALKファイルの登録 -void ndd_init(const char *files[], int n) { - int i; - ndd.fn = malloc(sizeof(char *) * n); - - for (i = 1; i <= n; i++) { - ndd.fn[i] = files[i]; - } -} - -// デモ本体 -void ndd_run(int demonum) { - FILE *fp; - alk_t *alk; - int i, start, ct; - - // ファイルオフセットだけ alk からもらう - alk = alk_new(ndd.fn[ndemo_alk[demonum]]); - if (alk == NULL) return; - - // libjpeg には FILE* を渡す - if (NULL == (fp = fopen(ndd.fn[ndemo_alk[demonum]], "rb"))) { - WARNING("%s not found\n", ndd.fn[ndemo_alk[demonum]]); - return; - } - - // wait keyup - while (sys_getInputInfo()); - - mus_bgm_play(ndemo_mus[demonum], 0, 100); - start = sdl_getTicks(); - ct = 0; - for (i = 0; i <= ndemo_nums[demonum];) { - int offset; - int cur1, cur = sdl_getTicks(); - - offset = alk->offset[i]; - - jpeg2surface(fp, offset); ct++; - ags_updateFull(); - - cur1 = sdl_getTicks(); - if (cur1 - cur < 33) { - if (sys_keywait(33 - (cur1 - cur), KEYWAIT_CANCELABLE)) break; - } else { - if (sys_getInputInfo()) break; - } - - i = (cur - start) / 33; - } - - NOTICE("%d/%d processed\n", ct, ndemo_nums[demonum]); - mus_bgm_stop(ndemo_mus[demonum], 0); - - fclose(fp); - alk_free(alk); -} diff --git a/modules/lib/alk.c b/modules/lib/alk.c index e182212..5dee0e1 100644 --- a/modules/lib/alk.c +++ b/modules/lib/alk.c @@ -34,9 +34,6 @@ #include "alk.h" alk_t *alk_new(const char *path) { - alk_t *alk; - int i; - mmap_t *m = map_file(path); if (0 != strncmp(m->addr, "ALK0", 4)) { @@ -45,30 +42,20 @@ alk_t *alk_new(const char *path) { return NULL; } - alk = calloc(1, sizeof(alk_t)); + int nr_entries = LittleEndian_getDW(m->addr, 4); + + alk_t *alk = malloc(sizeof(alk_t) + sizeof(struct alk_entry) * nr_entries); alk->mmap = m; - alk->datanum = LittleEndian_getDW(m->addr, 4); - alk->offset = malloc(sizeof(int) * alk->datanum); - - for (i = 0; i < alk->datanum; i++) { - alk->offset[i] = LittleEndian_getDW(m->addr, 8 + i * 8); + alk->datanum = nr_entries; + + for (int i = 0; i < nr_entries; i++) { + alk->entries[i].data = (uint8_t *)m->addr + LittleEndian_getDW(m->addr, 8 + i * 8); + alk->entries[i].size = LittleEndian_getDW(m->addr, 8 + i * 8 + 4); } - return alk; } -int alk_free(alk_t *alk) { - if (alk == NULL) return OK; - +void alk_free(alk_t *alk) { unmap_file(alk->mmap); - free(alk->offset); free(alk); - - return OK; -} - -char *alk_get(alk_t *alk, int no) { - if (no >= alk->datanum) return NULL; - - return (char *)alk->mmap->addr + alk->offset[no]; } diff --git a/modules/lib/alk.h b/modules/lib/alk.h index 08ea5b6..97ce7c6 100644 --- a/modules/lib/alk.h +++ b/modules/lib/alk.h @@ -25,27 +25,20 @@ #ifndef __ALK_H__ #define __ALK_H__ -#include -#include #include "mmap.h" -/* - .ALK データ構造 - - char[4] sig = "ALK0"; シグネチャ - int32 num = ファイル数 - int32 offset; 個々のファイルのファイルの先頭からのオフセット - int32 size; 個々のファイルの大きさ(in bytes) -*/ +struct alk_entry { + void *data; + uint32_t size; +}; typedef struct { - mmap_t *mmap; /* mmap したファイル */ - int datanum; /* .alk ファイル中のファイル数 */ - int *offset; /* 各ファイルへのオフセット */ + mmap_t *mmap; + int datanum; + struct alk_entry entries[]; } alk_t; -extern alk_t *alk_new(const char *path); -extern int alk_free(alk_t *alk); -extern char *alk_get(alk_t *alk, int no); +alk_t *alk_new(const char *path); +void alk_free(alk_t *alk); #endif /* __ALK_H__ */ diff --git a/modules/lib/cg.c b/modules/lib/cg.c index 49ec0c8..6f45fe5 100644 --- a/modules/lib/cg.c +++ b/modules/lib/cg.c @@ -127,12 +127,7 @@ surface_t *sf_getcg(void *b, size_t size) { } break; } - - if (cg->pic) free(cg->pic); - if (cg->pal) free(cg->pal); - if (cg->alpha) free(cg->alpha); - free(cg); - + cgdata_free(cg); return sf; } diff --git a/src/cg.c b/src/cg.c index 3233dc4..756d162 100644 --- a/src/cg.c +++ b/src/cg.c @@ -63,7 +63,6 @@ static cacher *cacheid; /* static methods */ static CG_TYPE check_cgformat(BYTE *data); static void set_vspbank(BYTE *pic, int bank, int width, int height); -static void cgdata_free(cgdata *cg); static MyPoint set_display_loc(cgdata *cg); static void clear_display_loc(); static void display_cg(cgdata *cg, int x, int y); @@ -116,7 +115,7 @@ static void set_vspbank(BYTE *pic, int bank, int width, int height) { * Free data * cg: freeing data object */ -static void cgdata_free(cgdata *cg) { +void cgdata_free(cgdata *cg) { if (cg->pic) free(cg->pic); if (cg->pal) free(cg->pal); if (cg->alpha) free(cg->alpha); diff --git a/src/cg.h b/src/cg.h index 8680dea..21d7543 100644 --- a/src/cg.h +++ b/src/cg.h @@ -83,6 +83,7 @@ extern void cg_load_with_alpha(int cgno, int shadowno); extern int cg_load_with_filename(char *fname_utf8, int x, int y); extern void cg_get_info(int no, MyRectangle *info); extern void cg_clear_display_loc(); +extern void cgdata_free(cgdata *cg); extern int cg_vspPB; extern int cg_fflg;