Revamp NightDemonDemo

- Fix off-by-one bug in demo number
- Use the jpeg extraction function in src/
- Improve alk archive interface
This commit is contained in:
kichikuou
2022-04-02 22:12:16 +09:00
parent f1b80d7086
commit 901a3bb28c
9 changed files with 81 additions and 266 deletions
+2 -8
View File
@@ -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()
+58 -5
View File
@@ -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);
-97
View File
@@ -1,97 +0,0 @@
/*
* jpeg2surface.c:
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* 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 <stdio.h>
#include <jpeglib.h>
#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;
}
-110
View File
@@ -1,110 +0,0 @@
/*
* ndd.c:
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* 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 <stdio.h>
#include <stdlib.h>
#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);
}
+9 -22
View File
@@ -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];
}
+9 -16
View File
@@ -25,27 +25,20 @@
#ifndef __ALK_H__
#define __ALK_H__
#include <unistd.h>
#include <sys/types.h>
#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__ */
+1 -6
View File
@@ -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;
}
+1 -2
View File
@@ -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);
+1
View File
@@ -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;