diff --git a/modules/MsgSkip/MsgSkip.c b/modules/MsgSkip/MsgSkip.c index 9353bd4..4358a82 100644 --- a/modules/MsgSkip/MsgSkip.c +++ b/modules/MsgSkip/MsgSkip.c @@ -1,6 +1,5 @@ #include "config.h" -#include #include #include #include @@ -8,48 +7,14 @@ #include "portab.h" #include "system.h" #include "filecheck.h" -#include "mmap.h" #include "xsystem35.h" #include "modules.h" #include "nact.h" -#include "message.h" #include "msgskip.h" #include "utfsjis.h" -typedef struct { - uint32_t msgnum; - uint8_t seen[]; -} MsgSkipData; - -static struct { - mmap_t *map; - MsgSkipData *data; - int action; - boolean valid; -} msgskip; - -static void msg_callback(int msgid) { - if (!msgskip.valid || !msgskip.data || (unsigned)msgid >= nact->ain.msgnum) - return; - uint8_t bit = 1 << (msgid & 7); - boolean unseen = !(msgskip.data->seen[msgid >> 3] & bit); - msgskip.data->seen[msgid >> 3] |= bit; - msgskip_action(unseen); -} - -static int open_msgskip_file(const char *fname_utf8) { - char *path = fc_get_path(fname_utf8); - size_t length = ((nact->ain.msgnum + 7) >> 3) + 4; - mmap_t *m = map_file_readwrite(path, length); - free(path); - if (!m) - return 1; - - msgskip.map = m; - msgskip.data = m->addr; - msgskip.data->msgnum = nact->ain.msgnum; - return 0; -} +static boolean valid; +static int action; static void Init() { int *p1 = getCaliVariable(); @@ -57,9 +22,8 @@ static void Init() { int p3 = getCaliValue(); int p4 = getCaliValue(); - msgskip.action = p3; - msgskip.valid = true; - nact->msgskip_callback = &msg_callback; + action = p3; + valid = true; *p1 = 0; DEBUG_COMMAND("MsgSkip.Init %p,%d,%d,%d:\n", p1, p2, p3, p4); @@ -69,9 +33,11 @@ static void Start() { int *p1 = getCaliVariable(); int p2 = getCaliValue(); - char *file = sjis2utf(svar_get(p2)); - *p1 = open_msgskip_file(file); - free(file); + char *fname_utf8 = sjis2utf(svar_get(p2)); + char *path = fc_get_path(fname_utf8); + msgskip_init(path); + free(path); + free(fname_utf8); DEBUG_COMMAND("MsgSkip.Start %p,%d:\n", p1, p2); } @@ -79,7 +45,8 @@ static void Start() { static void SetValid() { int p1 = getCaliValue(); - msgskip.valid = p1; + valid = p1; + msgskip_pause(!valid); DEBUG_COMMAND("MsgSkip.SetValid %d:\n", p1); } @@ -87,7 +54,7 @@ static void SetValid() { static void GetValid() { int *p1 = getCaliVariable(); - *p1 = msgskip.valid; + *p1 = valid; DEBUG_COMMAND("MsgSkip.GetValid %p:\n", p1); } @@ -95,7 +62,7 @@ static void GetValid() { static void SetAction() { int p1 = getCaliValue(); - msgskip.action = p1; + action = p1; DEBUG_COMMAND("MsgSkip.SetAcion %d:\n", p1); } @@ -103,7 +70,7 @@ static void SetAction() { static void GetAction() { int *p1 = getCaliVariable(); - *p1 = msgskip.action; + *p1 = action; DEBUG_COMMAND("MsgSkip.GetAcion %p:\n", p1); } diff --git a/src/cmd2F.c b/src/cmd2F.c index e68fdba..16d98f0 100644 --- a/src/cmd2F.c +++ b/src/cmd2F.c @@ -30,6 +30,7 @@ #include "savedata.h" #include "menu.h" #include "input.h" +#include "msgskip.h" #include "selection.h" #include "message.h" #include "music.h" @@ -1331,8 +1332,7 @@ void commands2F7C() { int index = sys_getdw(); sys_addMsg(nact->ain.msg[index]); - if (nact->msgskip_callback) - nact->msgskip_callback(index); + msgskip_onAinMessage(index); DEBUG_COMMAND("2F7C %d:\n", index); } @@ -1341,8 +1341,7 @@ void commands2F7D() { int index = sys_getdw(); commandH(); - if (nact->msgskip_callback) - nact->msgskip_callback(index); + msgskip_onAinMessage(index); DEBUG_COMMAND("2F7D %d:\n", index); } @@ -1351,8 +1350,7 @@ void commands2F7E() { int index = sys_getdw(); commandHH(); - if (nact->msgskip_callback) - nact->msgskip_callback(index); + msgskip_onAinMessage(index); DEBUG_COMMAND("2F7E %d:\n", index); } @@ -1362,8 +1360,7 @@ void commands2F7F() { int p1 = sys_getCaliValue(); sys_addMsg(svar_get(p1)); - if (nact->msgskip_callback) - nact->msgskip_callback(index); + msgskip_onAinMessage(index); DEBUG_COMMAND("2F7F %d, %d(%s,%s):\n", index, p1, nact->ain.msg[index], svar_get(p1)); } diff --git a/src/msgskip.c b/src/msgskip.c index 44a6d8a..23f5551 100644 --- a/src/msgskip.c +++ b/src/msgskip.c @@ -22,6 +22,7 @@ #include #include "portab.h" #include "mmap.h" +#include "nact.h" #include "input.h" #include "scenario.h" #ifdef __EMSCRIPTEN__ @@ -36,14 +37,16 @@ typedef struct { uint32_t size; - uint8_t bloom[]; + uint8_t seen[]; } MsgSkipData; static struct { mmap_t *map; MsgSkipData *data; unsigned flags; + boolean for_ain_message; boolean dirty; + boolean paused; // used by MsgSkip module } msgskip = { .flags = MSGSKIP_STOP_ON_UNSEEN | MSGSKIP_STOP_ON_MENU | MSGSKIP_STOP_ON_CLICK, }; @@ -53,20 +56,47 @@ static uint32_t hash(uint32_t x, int s) { return (x * 2654435761ULL) >> s; } +static void msgskip_action(boolean unseen) { + if (unseen && !(msgskip.flags & MSGSKIP_SKIP_UNSEEN)) { + if (msgskip.flags & MSGSKIP_STOP_ON_UNSEEN) + set_skipMode(FALSE); + enable_msgSkip(FALSE); + } else { + enable_msgSkip(TRUE); + } +} + void msgskip_init(const char *msgskip_file) { if (!msgskip_file) return; - size_t length = ((BLOOM_FILTER_SIZE + 7) >> 3) + 4; + if (msgskip.data) { + // Called from MsgSkip.Start but we've already initialized with the + // MsgSkip file specified in the gameresource file. Do nothing. + return; + } + + size_t size; + if (nact->ain.msg) { + msgskip.for_ain_message = true; + size = nact->ain.msgnum; + } else { + msgskip.for_ain_message = false; + size = BLOOM_FILTER_SIZE; + } + + size_t length = ((size + 7) >> 3) + 4; mmap_t *m = map_file_readwrite(msgskip_file, length); if (!m) return; + msgskip.map = m; msgskip.data = m->addr; msgskip.dirty = false; + msgskip.paused = false; - if (msgskip.data->size != BLOOM_FILTER_SIZE) { - msgskip.data->size = BLOOM_FILTER_SIZE; - memset(msgskip.data->bloom, 0, length - 4); + if (msgskip.data->size != size) { + msgskip.data->size = size; + memset(msgskip.data->seen, 0, length - 4); } #ifdef __EMSCRIPTEN__ @@ -75,7 +105,7 @@ void msgskip_init(const char *msgskip_file) { } void msgskip_onMessage(void) { - if (!msgskip.data) + if (!msgskip.data || msgskip.for_ain_message) return; uint32_t h1 = hash(sl_getPage(), 7); uint32_t h2 = hash(sl_getIndex(), 15); @@ -83,22 +113,28 @@ void msgskip_onMessage(void) { for (int i = 0; i < BLOOM_FILTER_HASHES; i++) { uint32_t h = (h1 + i * h2) % BLOOM_FILTER_SIZE; uint8_t bit = 1 << (h & 7); - unseen |= (msgskip.data->bloom[h >> 3] & bit) ^ bit; - msgskip.data->bloom[h >> 3] |= bit; + unseen |= (msgskip.data->seen[h >> 3] & bit) ^ bit; + msgskip.data->seen[h >> 3] |= bit; } if (unseen) msgskip.dirty = true; msgskip_action(unseen); } -void msgskip_action(boolean unseen) { - if (unseen && !(msgskip.flags & MSGSKIP_SKIP_UNSEEN)) { - if (msgskip.flags & MSGSKIP_STOP_ON_UNSEEN) - set_skipMode(FALSE); - enable_msgSkip(FALSE); - } else { - enable_msgSkip(TRUE); - } +void msgskip_onAinMessage(int msgid) { + if (msgskip.paused || !msgskip.data || !msgskip.for_ain_message + || (unsigned)msgid >= msgskip.data->size) + return; + uint8_t bit = 1 << (msgid & 7); + boolean unseen = !(msgskip.data->seen[msgid >> 3] & bit); + msgskip.data->seen[msgid >> 3] |= bit; + if (unseen) + msgskip.dirty = true; + msgskip_action(unseen); +} + +void msgskip_pause(boolean pause) { + msgskip.paused = pause; } unsigned msgskip_getFlags() { diff --git a/src/msgskip.h b/src/msgskip.h index e062dc7..0cd2ddb 100644 --- a/src/msgskip.h +++ b/src/msgskip.h @@ -29,8 +29,9 @@ extern void msgskip_init(const char *msgskip_file); extern void msgskip_onMessage(void); +extern void msgskip_onAinMessage(int msgid); extern unsigned msgskip_getFlags(); extern void msgskip_setFlags(unsigned flags, unsigned mask); -extern void msgskip_action(boolean unseen); +extern void msgskip_pause(boolean pause); #endif // __MSGSKIP_H__ diff --git a/src/nact.h b/src/nact.h index 7f7dc0f..a1d04c1 100644 --- a/src/nact.h +++ b/src/nact.h @@ -112,7 +112,6 @@ typedef struct { msg_t msg; boolean is_msg_out; /* 通常メッセージを表示するか */ void (*msgout)(const char *msg); // 通常以外(DLL等)のメッセージ表示関数 - void (*msgskip_callback)(int msgid); /* 選択肢関連 */ sel_t sel; diff --git a/src/xsystem35.c b/src/xsystem35.c index 659762d..8e7df7b 100644 --- a/src/xsystem35.c +++ b/src/xsystem35.c @@ -234,12 +234,12 @@ static void sys35_init() { msg_init(); sel_init(); - msgskip_init(nact->files.msgskip); s39ain_init(); #ifdef ENABLE_GTK s39ini_init(); #endif + msgskip_init(nact->files.msgskip); } static void sys35_remove() {