Support message skip in System3.9 games without MsgSkip.DLL

This commit is contained in:
kichikuou
2020-12-29 11:27:14 +09:00
parent 6da3dfef55
commit 9878f5ca74
6 changed files with 74 additions and 74 deletions
+14 -47
View File
@@ -1,6 +1,5 @@
#include "config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -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);
}
+5 -8
View File
@@ -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));
}
+52 -16
View File
@@ -22,6 +22,7 @@
#include <string.h>
#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() {
+2 -1
View File
@@ -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__
-1
View File
@@ -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;
+1 -1
View File
@@ -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() {