Rework string variables

- strVar is now allocated as a vector of indefinite length buffers
  rather than a single contiguous buffer.
- Strings can be any length, but truncated to (strvar_len * 2) bytes
  when saved to a file, for backward compatibility.
- Now string commands treat 1-byte characters in the same way as System
  3.9. This potentially fixes bugs in English translated games.
This commit is contained in:
kichikuou
2020-06-20 22:29:22 +09:00
parent a23ce19433
commit 86470e543a
5 changed files with 177 additions and 50 deletions
+3 -5
View File
@@ -749,14 +749,12 @@ void commands2F44() {
char s[256];
if (fig) {
char *ss="%%%dd";
char sss[256];
sprintf(sss, ss, fig);
sprintf(s, sss, num2);
sprintf(s, "%*d", fig, num2);
v_strcpy(num1 - 1, s + strlen(s) - fig);
} else {
sprintf(s, "%d", num2);
v_strcpy(num1 - 1, s);
}
v_strcpy(num1 - 1, s);
DEBUG_COMMAND("MHH %d, %d, %d:\n", num1, fig, num2);
}
+18 -24
View File
@@ -135,8 +135,14 @@ void commandMA() {
/* num1 の文字列の後ろに num2 をつなげる */
int num1 = getCaliValue();
int num2 = getCaliValue();
v_strcat(num1 - 1, v_str(num2 - 1));
if (num1 == num2) {
char *buf = strdup(v_str(num2 - 1));
v_strcat(num1 - 1, buf);
free(buf);
} else {
v_strcat(num1 - 1, v_str(num2 - 1));
}
DEBUG_COMMAND("MA %d,%d:\n",num1,num2);
}
@@ -176,7 +182,8 @@ void commandMM() {
int num1 = getCaliValue();
int num2 = getCaliValue();
v_strcpy(num1 - 1, v_str(num2 - 1));
if (num1 != num2)
v_strcpy(num1 - 1, v_str(num2 - 1));
DEBUG_COMMAND("MM %d,%d:\n",num1, num2);
}
@@ -236,8 +243,7 @@ void commandMD() {
int src_str_no = getCaliValue();
int len = getCaliValue();
strncpy(v_str(dst_str_no - 1), v_str(src_str_no - 1), len * 2);
*(v_str(dst_str_no - 1) + len*2) = '\0';
v_strncpy(dst_str_no - 1, 0, src_str_no - 1, 0, len);
DEBUG_COMMAND("MD %d,%d,%d:\n",dst_str_no, src_str_no, len);
}
@@ -250,8 +256,7 @@ void commandME() {
int src_pos = getCaliValue();
int len = getCaliValue();
strncpy(v_str(dst_str_no - 1) + dst_pos * 2, v_str(src_str_no - 1) + src_pos * 2, len*2);
*(v_str(dst_str_no - 1) + dst_pos * 2 + len*2) = '\0';
v_strncpy(dst_str_no - 1, dst_pos, src_str_no - 1, src_pos, len);
DEBUG_COMMAND("ME %d,%d,%d,%d,%d:\n",dst_str_no, dst_pos, src_str_no, src_pos, len);
}
@@ -262,14 +267,13 @@ void commandMF() {
int dst_no = getCaliValue();
int key_no = getCaliValue();
int start_pos = getCaliValue();
char *start = v_str(dst_no - 1) + start_pos * 2;
char *pos = strstr(start, v_str(key_no - 1));
int pos = v_strstr(dst_no - 1, start_pos, v_str(key_no - 1));
if (pos == NULL) {
if (pos < 0) {
sysVar[0] = 255;
} else {
*var = (pos - start) / 2;
*var = pos;
sysVar[0] = 0;
}
@@ -376,26 +380,16 @@ void commandMN() {
int num = getCaliValue();
int *var = getCaliVariable();
int i, len;
char *b;
const char *b;
switch(no) {
case 0:
/* 文字列を配列に変換する */
len = v_strlen(num -1);
b = v_str(num -1);
for (i = 0; i < len; i++) {
*var = *b;
var++; b++;
}
*var = 0;
sysVar[0] = v_strToVars(num - 1, var);
break;
case 1:
/* 配列を文字列に変換する */
b = v_str(num -1);
while(*var) {
*b = *var; b++; var++;
}
*b = '\0';
v_strFromVars(num - 1, var);
break;
default:
WARNING("UnKnown MN command(%d)\n", no);
+8 -6
View File
@@ -185,7 +185,8 @@ int save_save_str_with_file(char *filename, int start, int cnt) {
*tmp = 0;
for (i = 0; i < cnt; i++) {
strncpy(tmp, v_str(start + i - 1), strvar_len - 1);
tmp += v_strlen(start + i - 1) + 1;
tmp[strvar_len - 1] = '\0';
tmp += strlen(tmp) + 1;
}
@@ -241,8 +242,8 @@ int save_load_str_with_file(char *filename, int start, int cnt) {
status = SAVE_LOADOK;
}
for (i = 0; i < cnt; i++) {
strncpy(v_str(start + i - 1), tmp, strvar_len);
tmp += v_strlen(start + i - 1) + 1;
v_strcpy(start + i - 1, tmp);
tmp += strlen(tmp) + 1;
}
fclose(fp);
free(_tmp);
@@ -599,7 +600,8 @@ static void *saveStrVar(Ald_strVarHdr *head) {
*tmp = 0;
for (i = 0; i < strvar_cnt; i++) {
strncpy(tmp, v_str(i), strvar_len - 1);
tmp += v_strlen(i) + 1;
tmp[strvar_len - 1] = '\0';
tmp += strlen(tmp) + 1;
}
head->size = tmp - _tmp;
head->count = strvar_cnt;
@@ -618,8 +620,8 @@ static void loadStrVar(char *buf) {
v_initStringVars(cnt, max);
buf += sizeof(Ald_strVarHdr);
for (i = 0; i < cnt; i++) {
strncpy(v_str(i), buf, max - 1);
buf += v_strlen(i) + 1;
v_strcpy(i, buf);
buf += strlen(buf) + 1;
}
}
+141 -12
View File
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <string.h>
#include "portab.h"
#include "utfsjis.h"
#include "variable.h"
#include "xsystem35.h"
@@ -37,11 +38,18 @@ arrayVarBufferStruct arrayVarBuffer[ARRAYVAR_PAGEMAX];
/* 64bit変数 */
double longVar[SYSVARLONG_MAX];
/* 文字列変数 */
static char *strVar;
static char **strVar;
/* 文字列変数の属性(最大,1つあたりの大きさ) */
int strvar_cnt = STRVAR_MAX;
int strvar_len = STRVAR_LEN;
static char *advance(const char *s, int n) {
while (*s && n > 0) {
s += CHECKSJIS1BYTE(*s) ? 2 : 1;
n--;
}
return (char *)s;
}
/* 配列バッファの確保 DC ,page = 1~ */
extern boolean v_allocateArrayBuffer(int page, int size, boolean flg) {
@@ -96,43 +104,164 @@ extern boolean v_getArrayBufferStatus(int page) {
/* 文字列変数の再初期化 */
extern void v_initStringVars(int cnt,int len) {
strVar = realloc(strVar, cnt * len);
for (int i = cnt + 1; i < strvar_cnt; i++) {
if (strVar[i])
free(strVar[i]);
}
strVar = realloc(strVar, cnt * sizeof(char *));
if (strVar == NULL) {
NOMEMERR();
}
for (int i = strvar_cnt + 1; i < cnt; i++)
strVar[i] = NULL;
strvar_cnt = cnt;
strvar_len = len;
}
/* 変数の初期化 */
extern boolean v_initVars() {
strVar = calloc(STRVAR_MAX, STRVAR_LEN);
strVar = calloc(STRVAR_MAX, sizeof(char *));
if (strVar == NULL) {
NOMEMERR();
}
return true;
}
/* 文字変数への代入 */
char *v_strcpy(int no, const char *str) {
return strncpy(strVar + no * strvar_len, str, strvar_len - 1);
void v_strcpy(int no, const char *str) {
if (no < 0 || no >= strvar_cnt) {
WARNING("string index out of range: %d", no);
return;
}
if (strVar[no])
free(strVar[no]);
strVar[no] = strdup(str);
}
void v_strncpy(int dstno, int dstpos, int srcno, int srcpos, int len) {
if (dstno < 0 || dstno >= strvar_cnt) {
WARNING("string index out of range: %d", dstno);
return;
}
if (!strVar[dstno])
strVar[dstno] = strdup("");
char *buf = NULL;
const char *src;
if (srcno == dstno)
src = buf = strdup(strVar[srcno]);
else
src = v_str(srcno);
dstpos = advance(strVar[dstno], dstpos) - strVar[dstno]; // #chars -> #bytes
src = advance(src, srcpos);
len = advance(src, len) - src; // #chars -> #bytes
strVar[dstno] = realloc(strVar[dstno], dstpos + len + 1);
strncpy(strVar[dstno] + dstpos, src, len);
strVar[dstno][dstpos + len] = '\0';
if (buf)
free(buf);
}
/* 文字変数への接続 */
char *v_strcat(int no, const char *str) {
return strncat(strVar + no * strvar_len, str, strvar_len - 1);
void v_strcat(int no, const char *str) {
if (no < 0 || no >= strvar_cnt) {
WARNING("string index out of range: %d", no);
return;
}
if (!strVar[no]) {
strVar[no] = strdup(str);
return;
}
int len1 = strlen(strVar[no]);
int len2 = strlen(str);
strVar[no] = realloc(strVar[no], len1 + len2 + 1);
strcpy(strVar[no] + len1, str);
}
/* 文字変数の長さ */
size_t v_strlen(int no) {
return strlen(strVar + no * strvar_len);
if (no < 0 || no >= strvar_cnt) {
WARNING("string index out of range: %d", no);
return 0;
}
return strVar[no] ? sjis_count_char(strVar[no]) : 0;
}
/* 文字変数そのもの */
char *v_str(int no) {
return strVar + no * strvar_len;
const char *v_str(int no) {
if (no < 0 || no >= strvar_cnt) {
WARNING("string index out of range: %d", no);
return "";
}
return strVar[no] ? strVar[no] : "";
}
int v_strstr(int no, int start, const char *str) {
if (no < 0 || no >= strvar_cnt) {
WARNING("string index out of range: %d", no);
return -1;
}
if (!*str)
return 0;
if (!strVar[no])
return -1;
const char *p = advance(strVar[no], start);
const char *found = strstr(p, str);
if (!found)
return -1;
int n = start;
while (p < found) {
p += CHECKSJIS1BYTE(*p) ? 2 : 1;
n++;
}
return n;
}
void v_strFromVars(int no, const int *vars) {
if (no < 0 || no >= strvar_cnt) {
WARNING("string index out of range: %d", no);
return;
}
int len = 0;
for (const int *c = vars; *c; c++)
len += (*c < 256) ? 1 : 2;
if (strVar[no])
free(strVar[no]);
char *p = strVar[no] = malloc(len + 1);
for (const int *v = vars; *v; v++) {
if (*v < 256) {
*p++ = *v;
} else {
*p++ = *v & 0xff;
*p++ = *v >> 8;
}
}
*p = '\0';
}
int v_strToVars(int no, int *vars) {
if (no < 0 || no >= strvar_cnt) {
WARNING("string index out of range: %d", no);
return 0;
}
if (!strVar[no]) {
*vars = 0;
return 1;
}
int count = 0;
for (const char *p = strVar[no]; *p; count++) {
vars[count] = *p++ & 0xff;
if (CHECKSJIS1BYTE(vars[count]))
vars[count] |= (*p++ & 0xff) << 8;
}
vars[count++] = 0;
return count;
}
#ifdef DEBUG
+7 -3
View File
@@ -60,9 +60,13 @@ extern int v_getArrayBufferCnt(int page);
extern boolean v_getArrayBufferStatus(int page);
extern void v_initStringVars(int ,int );
extern boolean v_initVars();
extern char *v_strcpy(int no, const char *str);
extern char *v_strcat(int no, const char *str);
extern void v_strcpy(int no, const char *str);
extern void v_strncpy(int dstno, int dstpos, int srcno, int srcpos, int len);
extern void v_strcat(int no, const char *str);
extern size_t v_strlen(int no);
extern char *v_str(int no);
extern int v_strstr(int no, int start, const char *str);
extern void v_strFromVars(int no, const int *vars);
extern int v_strToVars(int no, int *vars);
extern const char *v_str(int no);
#endif /* !__VARIABLE__ */