mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-10-04 12:48:00 +03:00
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:
+141
-12
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user