Compare commits

..
20 Commits
Author SHA1 Message Date
kichikuou 70a940b216 Version 2.8.0 2023-02-12 09:33:29 +09:00
kichikuou db2bb03fdd Add -help description for -game option 2023-02-12 09:12:09 +09:00
kichikuou 5ef949ae14 Refactor ags_setWindowTitle() 2023-02-11 21:40:14 +09:00
kichikuou 043028cf7d Update game_compatibility.md 2023-02-11 16:18:09 +09:00
kichikuou eace5d1dbd Refactor game-specific hacks, add -game option
It's now possible to enable certain game-specific hacks by using the
`-game` command line option or the `game` property in the .xsys35rc
file.
2023-02-11 15:27:38 +09:00
kichikuou 878bea69d6 Add a test for stack commands 2023-02-10 21:30:02 +09:00
kichikuou ae8becc4a3 Fix menuReturnGoto when stack top is not a return address 2023-02-10 21:24:13 +09:00
kichikuou 1d863cfb2e Implement UR command 2023-02-10 20:56:53 +09:00
kichikuou 7bb2bee693 Label return should pop TPx 2023-02-10 20:56:53 +09:00
kichikuou 47e7f5542e Remove sl_retFar2
In System39.exe `%0` drops stack frames for label calls (Rance4 v2
relies on this behavior), so it's the same as `UD 1`.
2023-02-10 20:56:53 +09:00
kichikuou 8087d11b2b Fix UC command
* UC0 should restore values pushed by US/TPx
* UC1 should stop when the stack top is a page call
* UC1/2 should restore status pushes by TPx
* UC1/2 should not consume the count for non-call stack frames
* Add support for UC3 command
2023-02-10 20:56:53 +09:00
kichikuou 4f1521ac90 TOx commands are no-op if the stack top is of an unexpected type 2023-02-10 20:56:53 +09:00
kichikuou 99632397da Enable the hack in Rance4v2 recompiled with System3.9
The System3.9 compiler compiles `MT` command to `0x2F28`, so the hack
must be enabled in commands2F28().

Fixes https://github.com/kichikuou/xsystem35-sdl2/issues/36.
2023-02-10 20:50:12 +09:00
kichikuou 59283815d8 Properly implement Y 1900 command
It is the same as patchEC, but can be used in SCO files less than
version 390.
2023-02-08 10:43:06 +09:00
kichikuou a32c901eb8 Tweak the Rance4v2 hack
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/35.
2023-02-08 10:15:06 +09:00
kichikuou 03b84b8ba7 Make UR command safer
It's still unimplemented, but clears the output variables for safety.
2023-02-07 22:12:35 +09:00
kichikuou 720da4e42c Fix UC1 command 2023-02-07 22:05:00 +09:00
kichikuou c4dc799c94 Change the condition for applying Rance4v2 hack
Now it's determined by the MT command argument.
2023-02-07 21:31:03 +09:00
kichikuou ce271ae5eb Fix CG positioning issue in Rance 4.x (TOTO port)
G command should reset the effect of J0/J1, even if pixel extraction is
disabled by PC command.
2023-02-05 18:37:50 +09:00
kichikuou 526e5f8709 Fix VSP palette issue
This fixes a palette problem when drawing a VSP image on a non-8-bit
surface after executing `ZC 0` command.

cg->vsp_bank can be overridden by the `ZC 0` command.
2023-02-05 18:08:41 +09:00
33 changed files with 373 additions and 260 deletions
+2 -2
View File
@@ -16,8 +16,8 @@ android {
}
minSdkVersion 19
targetSdkVersion 31
versionCode 12
versionName "2.7.0" + gitRevision()
versionCode 13
versionName "2.8.0" + gitRevision()
externalNativeBuild {
cmake {
arguments "-DANDROID_APP_PLATFORM=android-16", "-DANDROID_STL=c++_static"
+1 -1
View File
@@ -1,5 +1,5 @@
#cmakedefine PACKAGE "@PACKAGE@"
#define VERSION "2.7.0"
#define VERSION "2.8.0"
#cmakedefine CMAKE_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@"
+3 -1
View File
@@ -5,9 +5,11 @@ Game Compatibility
| ------------------------------------------- | ----------- | ----- |
| 鬼畜王ランス | Supported | |
| Kichikuou Rance (EN) | Supported | |
| RanceIV -教団の遺産- | Supported | Win95 edition, [Win10 edition](https://hannylaboratory.blogspot.com/2023/01/blog-post_26.html) |
| RanceIV -教団の遺産- | Supported | Win95 edition, [Ver2.05](https://hannylaboratory.blogspot.com/2023/01/blog-post_26.html) |
| Rance4 -Legacy of the Sect- (EN) | Supported | |
| 兰斯IV -教团的遗产- (CN) | Supported | |
| ランス4.1 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html) |
| ランス4.2 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html) |
| いけないかつみ先生 | Supported | Emojis are not supported |
| 闘神都市II | Supported | Win95 edition |
| かえるにょ・ぱにょ~ん | Supported | Normal / Low-priced edition |
-1
View File
@@ -32,7 +32,6 @@
#include "input.h"
#include "msgskip.h"
#include "xsystem35.h"
#include "gametitle.h"
#include "message.h"
#include "modules.h"
#include "music.h"
+3 -1
View File
@@ -89,7 +89,9 @@ static void SetWindowTitle(void) { /* 6 */
int strno = getCaliValue();
int p2 = getCaliValue(); /* ISys3xSystem */
ags_setWindowTitle(svar_get(strno));
char *title_utf8 = toUTF8(svar_get(strno));
ags_setWindowTitle(title_utf8);
free(title_utf8);
DEBUG_COMMAND("ShString.SetWindowTitle: %d,%d:", strno, p2);
}
+1 -1
View File
@@ -53,7 +53,7 @@ target_sources(xsystem35 PRIVATE
# Misc
target_sources(xsystem35 PRIVATE
input.c profile.c mt19937-1.c filecheck.c mmap.c)
input.c profile.c mt19937-1.c filecheck.c mmap.c hacks.c)
# Scenario
target_sources(xsystem35 PRIVATE
+4 -13
View File
@@ -162,19 +162,10 @@ void ags_setViewArea(int x, int y, int width, int height) {
sdl_setWindowSize(width, height);
}
void ags_setWindowTitle(const char *src) {
#define TITLEHEAD "XSystem35 Version "VERSION":"
uint8_t *utf, *d;
utf = toUTF8(src);
if (NULL == (d = malloc(strlen(utf) + strlen(TITLEHEAD) + 1))) {
NOMEMERR();
}
strcpy(d, TITLEHEAD);
strcat(d, utf);
sdl_setWindowTitle(d);
free(utf);
free(d);
void ags_setWindowTitle(const char *title_utf8) {
char buf[256];
snprintf(buf, sizeof(buf), "XSystem35 Version %s: %s", VERSION, title_utf8);
sdl_setWindowTitle(buf);
}
void ags_getDIBInfo(DispInfo *info) {
+1 -1
View File
@@ -133,7 +133,7 @@ void ags_reset(void);
/* ウィンド関係 */
extern void ags_setWorldSize(int width, int height, int depth);
extern void ags_setViewArea(int x, int y, int width, int height);
extern void ags_setWindowTitle(const char *str);
extern void ags_setWindowTitle(const char *title_utf8);
extern void ags_getDIBInfo(DispInfo *info);
extern void ags_getWindowInfo(DispInfo *info);
extern void ags_getViewAreaInfo(DispInfo *info);
+2 -2
View File
@@ -346,9 +346,9 @@ void cg_load(int no, int flg) {
}
/* draw cg pixel */
display_cg(cg, p.x, p.y, flg, flg != -1);
/* clear display offset */
clear_display_loc();
}
/* clear display offset */
clear_display_loc();
}
/*
+12 -57
View File
@@ -41,14 +41,11 @@
#include "sdl_core.h"
#include "ald_manager.h"
#include "LittleEndian.h"
#include "gametitle.h"
#include "hacks.h"
#if HAVE_UNAME
#include <sys/utsname.h>
#endif
/* defined by cmdm.c */
extern boolean have_eng_mp_patch;
/* 選択 Window OPEN 時 callback */
static int cb_sel_init_page = 0;
static int cb_sel_init_address = 0;
@@ -68,82 +65,43 @@ static fncall_table fnctbl[FCTBL_MAX];
void commands2F00() {
/* テキストカラーをスタックからポップして設定する */
int data[3];
sl_popData(data, 3);
if (data[0] == TxxTEXTCOLOR) {
if (data[1] == 0) {
nact->msg.MsgFontColor = data[2];
} else {
nact->sel.MsgFontColor = data[2];
}
}
sl_popState(TxxTEXTCOLOR);
DEBUG_COMMAND("TOC:");
}
void commands2F01() {
/* テキストフォントサイズをスタックからポップして設定する */
int data[3];
sl_popData(data, 3);
if (data[0] == TxxTEXTSIZE) {
if (data[1] == 0) {
nact->msg.MsgFontSize = data[2];
} else {
nact->sel.MsgFontSize = data[2];
}
}
sl_popState(TxxTEXTSIZE);
DEBUG_COMMAND("TOS:");
}
void commands2F02() {
/* 現在のテキストカラーをスタックにプッシュする */
int exp = getCaliValue();
int data[] = {TxxTEXTCOLOR,0,0};
data[1] = exp;
data[2] = (exp == 0 ? nact->msg.MsgFontColor : nact->sel.MsgFontColor);
sl_pushData(data, 3);
int val = exp == 0 ? nact->msg.MsgFontColor : nact->sel.MsgFontColor;
sl_pushState(TxxTEXTCOLOR, exp, val);
DEBUG_COMMAND("TPC %d", exp);
}
void commands2F03() {
/* 現在のテキストフォントサイズをスタックにプッシュする */
int exp = getCaliValue();
int data[] = {TxxTEXTSIZE, 0, 0};
data[1] = exp;
data[2] = (exp == 0 ? nact->msg.MsgFontSize : nact->sel.MsgFontSize);
sl_pushData(data, 3);
DEBUG_COMMAND("TPS %d:%s", exp, "");
int val = exp == 0 ? nact->msg.MsgFontSize : nact->sel.MsgFontSize;
sl_pushState(TxxTEXTSIZE, exp, val);
DEBUG_COMMAND("TPS %d", exp);
}
void commands2F04() {
/* テキスト表示位置をスタックからポップして設定する */
int data[3];
sl_popData(data, 3);
if (data[0] == TxxTEXTLOC) {
msg_setMessageLocation(data[1], data[2]);
}
sl_popState(TxxTEXTLOC);
DEBUG_COMMAND("TOP:");
}
void commands2F05() {
/* 現在のテキスト表示位置をスタックにプッシュする */
int data[] = {TxxTEXTLOC, 0, 0};
MyPoint loc;
msg_getMessageLocation(&loc);
data[1] = loc.x;
data[2] = loc.y;
sl_pushData(data, 3);
sl_pushState(TxxTEXTLOC, loc.x, loc.y);
DEBUG_COMMAND("TPP:");
}
@@ -461,12 +419,9 @@ void commands2F28() {
free(nact->game_title_utf8);
nact->game_title_utf8 = toUTF8(title);
ags_setWindowTitle(title);
ags_setWindowTitle(nact->game_title_utf8);
if (0 == strcmp(nact->game_title_utf8, GT_RANCE3_ENG) ||
0 == strcmp(nact->game_title_utf8, GT_RANCE4_ENG)) {
have_eng_mp_patch = TRUE;
}
enable_hack_by_title(nact->game_title_utf8);
DEBUG_COMMAND("MT(new) %s:",title);
}
+3 -20
View File
@@ -31,22 +31,13 @@
#include "utfsjis.h"
#include "menu.h"
#include "ags.h"
#include "input.h"
#include "message.h"
#include "gametitle.h"
#include "hankaku.h"
/* defined by cmds.c */
extern boolean dummy_pcm_su_flag;
/* defined by cmdy.c */
extern boolean Y3waitFlags;
/* MI 用パラメータ */
INPUTSTRING_PARAM mi_param;
boolean have_eng_mp_patch = FALSE;
void commandMS() {
/* Xコマンドで表示される文字列領域に文字列を入れる */
int num = getCaliValue();
@@ -69,7 +60,7 @@ void commandMP() {
char *str;
/* Patched English executable appends num2 spaces instead of truncating */
if (have_eng_mp_patch) {
if (nact->game == GAME_RANCE3_ENG || nact->game == GAME_RANCE4_ENG) {
str = calloc(strlen(src) + num2 * strlen(fullwidth_blank[nact->encoding]) + 1, 1);
if (NULL == str) {
NOMEMERR();
@@ -163,17 +154,9 @@ void commandMT() {
if (nact->game_title_utf8)
free(nact->game_title_utf8);
nact->game_title_utf8 = toUTF8(str);
ags_setWindowTitle(str);
ags_setWindowTitle(nact->game_title_utf8);
/* 闘神都市II 対策 */
if (0 == strcmp(nact->game_title_utf8, GT_TOSHIN2)) {
dummy_pcm_su_flag = TRUE;
}
/* Rance4 対策? */
if (0 == strcmp(nact->game_title_utf8, GT_RANCE4)) {
Y3waitFlags = KEYWAIT_NONCANCELABLE;
}
enable_hack_by_title(nact->game_title_utf8);
DEBUG_COMMAND("MT %s:",str);
}
+2 -3
View File
@@ -29,8 +29,6 @@
/* ぱにょ〜ん 異常シナリオ対策 */
static boolean dummy_pcm_in_play = FALSE;
/* 闘神都市II 異常シナリオ対策 */
boolean dummy_pcm_su_flag = FALSE;
/* 次の cdrom の loop 回数 */
static int next_cdrom_loopcnt = 0;
@@ -273,7 +271,8 @@ void commandSU() {
dummy_pcm_in_play = dummy_pcm_in_play ? FALSE : TRUE;
}
}
if (dummy_pcm_su_flag) {
/* 闘神都市II 異常シナリオ対策 */
if (nact->game == GAME_TT2) {
*var1 = *var2 = 0;
}
+19 -6
View File
@@ -33,12 +33,16 @@ void commandUC() { /* 王道勇者 */
switch(mode) {
case 0:
sl_stackClear_allCall(); break;
sl_clearStack(true);
break;
case 1:
sl_stackClear_labelCall(num); break;
sl_dropLabelCalls(num);
break;
case 2:
sl_stackClear_pageCall(num); break;
default:
sl_dropPageCalls(num);
break;
case 3:
sl_clearStack(false);
break;
}
DEBUG_COMMAND("UC %d,%d:",mode,num);
@@ -51,7 +55,7 @@ void commandUD() {
case 0:
sl_reinit(); break;
case 1:
sl_retFar2(); break;
sl_retFar(); break;
default:
WARNING("UnKnown UD command %d", mode);
}
@@ -62,8 +66,17 @@ void commandUD() {
void commandUR() {
/* 最後に積まれたスタックの属性をリード */
int *var = getCaliVariable();
struct stack_info info;
sl_getStackInfo(&info);
var[0] = info.top_attr;
var[1] = info.page_calls;
var[2] = info.label_calls;
var[3] = info.var_pushes;
var[4] = info.label_calls_after_page_call;
var[5] = info.var_pushes_after_call;
DEBUG_COMMAND_YET("UR %p:",var);
DEBUG_COMMAND("UR %p:",var);
}
void commandUS() {
+4 -4
View File
@@ -126,7 +126,7 @@ void commandY() {
default:
if (p1 == 1003) {
sys_key_releasewait(SYS35KEY_RET, FALSE);
} else if (nact->game_rance4v2) {
} else if (nact->game == GAME_RANCE4_V2 && p2 == 1) {
// Return immediately if any key is pressed.
sysVar[0] = sys_getInputInfo();
if (sysVar[0])
@@ -145,9 +145,9 @@ void commandY() {
}
break;
case 1900:
// The effect of Y1900 is unknown, but since it is only used by Rance4
// ver2 as the very first command, do some initialization here.
nact->game_rance4v2 = true;
nact->patch_ec = p2;
// We're sure this game was built for System3.9 v5.50, which by default
// routes CD-DA commands to DRIFILE_WAVE.
muscd_init_bgm(DRIFILE_WAVE, 999);
break;
default:
+2 -2
View File
@@ -390,7 +390,7 @@ static void set_stack_frame(StackFrame *frame, int page, int addr, boolean is_re
StackTrace *dbg_stack_trace(void) {
int stack_size;
const int *stack_base = sl_getStackInfo(&stack_size);
const int *stack_base = sl_getStack(&stack_size);
int page = nact->current_page;
@@ -440,7 +440,7 @@ static boolean should_continue_step(void) {
void dbg_stepout(void) {
// Set an internal breakpoint at the return address of current frame.
int stack_size;
const int *stack_base = sl_getStackInfo(&stack_size);
const int *stack_base = sl_getStack(&stack_size);
const int *p = stack_base + stack_size - 1;
while (p >= stack_base) {
int page, addr = -1;
-4
View File
@@ -1,4 +0,0 @@
#define GT_TOSHIN2 "闘神都市Ⅱ for Win95 "
#define GT_RANCE4 "Rance4 -教団の遺産- For Win95 "
#define GT_RANCE3_ENG "Rance3"
#define GT_RANCE4_ENG "Rance4 -Legacy of the Sect- For Win95 "
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2023 kichikuou <KichikuouChrome@gmail.com>
*
* 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
*
*/
#include <string.h>
#include "hacks.h"
#include "system.h"
#include "nact.h"
#include "input.h"
// Game titles.
#define GT_TOSHIN2 "闘神都市Ⅱ for Win95 "
#define GT_RANCE4 "Rance4 -教団の遺産- For Win95 "
#define GT_RANCE4_V2 "RanceⅣ -教団の遺産- for Windows "
#define GT_RANCE3_ENG "Rance3"
#define GT_RANCE4_ENG "Rance4 -Legacy of the Sect- For Win95 "
/* defined by cmdy.c */
extern boolean Y3waitFlags;
void enable_hack_by_gameid(const char *gameid) {
if (!strcmp(gameid, "toushin2"))
nact->game = GAME_TT2;
else if (!strcmp(gameid, "rance3_eng"))
nact->game = GAME_RANCE3_ENG;
else if (!strcmp(gameid, "rance4_eng"))
nact->game = GAME_RANCE4_ENG;
else if (!strcmp(gameid, "rance4_v2"))
nact->game = GAME_RANCE4_V2;
else
sys_error("Unknown game id \"%s\"", gameid);
}
void enable_hack_by_title(const char *title_utf8) {
if (!strcmp(title_utf8, GT_RANCE4))
Y3waitFlags = KEYWAIT_NONCANCELABLE;
if (nact->game != GAME_UNKNOWN)
return;
if (!strcmp(title_utf8, GT_TOSHIN2))
nact->game = GAME_TT2;
else if (!strcmp(title_utf8, GT_RANCE4_V2))
nact->game = GAME_RANCE4_V2;
else if (!strcmp(title_utf8, GT_RANCE3_ENG))
nact->game = GAME_RANCE3_ENG;
else if (!strcmp(title_utf8, GT_RANCE4_ENG))
nact->game = GAME_RANCE4_ENG;
}
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2023 kichikuou <KichikuouChrome@gmail.com>
*
* 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
*
*/
#ifndef __HACKS_H_
#define __HACKS_H_
enum gameId {
GAME_UNKNOWN = 0,
GAME_TT2,
GAME_RANCE3_ENG,
GAME_RANCE4_ENG,
GAME_RANCE4_V2,
};
void enable_hack_by_gameid(const char *gameid);
void enable_hack_by_title(const char *game_title_utf8);
#endif // __HACKS_H_
+2 -1
View File
@@ -32,6 +32,7 @@
#include "message.h"
#include "ags.h"
#include "utfsjis.h"
#include "hacks.h"
#define toUTF8(s) codeconv(UTF8, nact->encoding, s)
#define toSJIS(s) codeconv(SHIFT_JIS, nact->encoding, s)
@@ -110,7 +111,7 @@ typedef struct {
int patch_g0; /* see patch g0 command */
// For game-specific hacks.
bool game_rance4v2;
enum gameId game;
/* ain 関連 */
S39AIN ain;
+2 -2
View File
@@ -525,7 +525,7 @@ int save_saveAll(int no) {
/* スタック情報のセーブ */
static void *saveStackInfo(Ald_stackHdr *head) {
int count;
int *info = sl_getStackInfo(&count);
int *info = sl_getStack(&count);
head->size = count * sizeof(int);
return (void *)info;
@@ -535,7 +535,7 @@ static void *saveStackInfo(Ald_stackHdr *head) {
static void loadStackInfo(char *buf) {
Ald_stackHdr *head = (Ald_stackHdr *)buf;
char *data = buf + sizeof(Ald_stackHdr);
sl_putStackInfo((int *)data, head->size / sizeof(int));
sl_putStack((int *)data, head->size / sizeof(int));
}
/* 文字列変数のセーブ */
+100 -116
View File
@@ -38,7 +38,7 @@ int sl_index;
/* static mathods */
static void popVars(int *tmp);
static void popDatas(int *tmp);
static void popState(int *tmp);
static void sl_push(int type, int *val, int cnt);
static int* sl_pop(void);
@@ -47,11 +47,6 @@ static int *stack_buf;
static int *stack_top;
static int stack_size = 1024;
static int labelCallCnt = 0;
static int pageCallCnt = 0;
static int labelCallCnt_afterPageCall = 0;
static int dataPushCnt = 0;
static char strbuf[512];
static dridata *dfile; // dri object for current page
@@ -66,10 +61,6 @@ boolean sl_init(void) {
stack_top = stack_buf;
sl_jmpFar(0);
labelCallCnt = 0;
pageCallCnt = 0;
labelCallCnt_afterPageCall = 0;
dataPushCnt = 0;
return TRUE;
}
@@ -225,9 +216,6 @@ void sl_callNear(int address) {
val[0] = sl_index;
sl_push(STACK_NEARJMP, val, 1);
sl_jmpNear(address);
labelCallCnt++;
labelCallCnt_afterPageCall++;
}
void sl_retNear(void) {
@@ -237,6 +225,8 @@ void sl_retNear(void) {
while (*tmp != STACK_NEARJMP) {
if (*tmp == STACK_FARJMP) {
SYSERROR("Stack buffer is illegal");
} else if (*tmp == STACK_TXXSTATE) {
popState(tmp);
} else if (*tmp == STACK_VARIABLE) {
popVars(tmp);
} else {
@@ -248,17 +238,12 @@ void sl_retNear(void) {
index = *(tmp + 2);
free(tmp);
sl_jmpNear(index);
labelCallCnt--;
labelCallCnt_afterPageCall--;
}
void sl_callFar(int page) {
int val[2] = { sl_page, sl_index };
sl_push(STACK_FARJMP, val, 2);
boolean ok = sl_jmpFar(page);
pageCallCnt++;
labelCallCnt_afterPageCall = 0;
if (!ok)
sl_retFar();
}
@@ -267,8 +252,6 @@ void sl_callFar2(int page, int address) {
int val[2] = { sl_page, sl_index };
sl_push(STACK_FARJMP, val, 2);
boolean ok = sl_jmpFar2(page, address);
labelCallCnt_afterPageCall = 0;
pageCallCnt++;
if (!ok)
sl_retFar();
}
@@ -279,9 +262,9 @@ void sl_retFar(void) {
while (*tmp != STACK_FARJMP) {
if (*tmp == STACK_NEARJMP) {
WARNING("Stack buffer is illegal");
} else if (*tmp == STACK_DATA) {
popDatas(tmp);
// do nothing
} else if (*tmp == STACK_TXXSTATE) {
popState(tmp);
} else if (*tmp == STACK_VARIABLE) {
popVars(tmp);
} else {
@@ -294,88 +277,76 @@ void sl_retFar(void) {
index = *(tmp + 3);
free(tmp);
sl_jmpFar2(page, index);
labelCallCnt_afterPageCall = 0;
pageCallCnt--;
}
/* UD 1 */
void sl_retFar2(void) {
int *tmp = sl_pop();
int page, index;
while (*tmp != STACK_FARJMP) {
if (*tmp == STACK_NEARJMP) {
labelCallCnt--;
} else if (*tmp == STACK_DATA) {
popDatas(tmp);
} else if (*tmp == STACK_VARIABLE) {
popVars(tmp);
} else {
SYSERROR("Stack buffer is illegal");
}
free(tmp);
tmp = sl_pop();
}
page = *(tmp + 2);
index = *(tmp + 3);
free(tmp);
sl_jmpFar2(page, index);
pageCallCnt--;
labelCallCnt_afterPageCall = 0;
}
/* UC0 */
void sl_stackClear_allCall(void) {
free(stack_buf);
stack_buf = calloc(stack_size, sizeof(int));
if (stack_buf == NULL)
NOMEMERR();
void sl_clearStack(bool restore) {
if (!restore) {
stack_top = stack_buf;
return;
}
while (stack_top > stack_buf) {
int *tmp = sl_pop();
switch (*tmp) {
case STACK_NEARJMP:
case STACK_FARJMP:
break;
case STACK_VARIABLE:
popVars(tmp);
break;
case STACK_TXXSTATE:
popState(tmp);
break;
default:
SYSERROR("broken stack");
}
free(tmp);
}
stack_top = stack_buf;
}
/* UC 2 */
void sl_stackClear_pageCall(int cnt) {
int *tmp;
while(cnt--) {
tmp = sl_pop();
if (*tmp == STACK_NEARJMP) {
labelCallCnt--;
} else if (*tmp == STACK_FARJMP) {
pageCallCnt--;
} else if (*tmp == STACK_VARIABLE) {
void sl_dropPageCalls(int cnt) {
while (cnt > 0 && stack_top > stack_buf) {
int *tmp = sl_pop();
switch (*tmp) {
case STACK_NEARJMP:
break;
case STACK_FARJMP:
cnt--;
break;
case STACK_VARIABLE:
popVars(tmp);
} else {
SYSERROR("Stack buffer is illegal");
break;
case STACK_TXXSTATE:
popState(tmp);
break;
default:
SYSERROR("broken stack");
}
free(tmp);
}
labelCallCnt_afterPageCall = 0;
}
/* UC 1 */
void sl_stackClear_labelCall(int cnt) {
int *tmp;
if (labelCallCnt_afterPageCall == 0) return;
tmp = sl_pop();
while(cnt--) {
if (*tmp == STACK_NEARJMP) {
labelCallCnt--;
labelCallCnt_afterPageCall--;
} else if (*tmp == STACK_VARIABLE) {
void sl_dropLabelCalls(int cnt) {
while (cnt > 0 && stack_top > stack_buf && stack_top[-1] != STACK_FARJMP) {
int *tmp = sl_pop();
switch (*tmp) {
case STACK_NEARJMP:
cnt--;
break;
case STACK_VARIABLE:
popVars(tmp);
} else {
SYSERROR("Stack buffer is illegal");
break;
case STACK_TXXSTATE:
popState(tmp);
break;
default:
SYSERROR("broken stack");
}
free(tmp);
if (labelCallCnt_afterPageCall == 0) break;
tmp = sl_pop();
}
}
@@ -431,12 +402,12 @@ static void popVars(int *tmp) {
memcpy(topVar, tmp + 4, sizeof(int) * cnt);
}
int *sl_getStackInfo(int *size) {
int *sl_getStack(int *size) {
*size = stack_top - stack_buf;
return stack_buf;
}
void sl_putStackInfo(int *data, int size) {
void sl_putStack(int *data, int size) {
if (size > stack_size) {
stack_size = size << 1;
stack_buf = calloc(stack_size, sizeof(int));
@@ -447,31 +418,51 @@ void sl_putStackInfo(int *data, int size) {
stack_top = stack_buf + size;
}
void sl_getStackInfo(struct stack_info *info) {
memset(info, 0, sizeof(struct stack_info));
for (int *p = stack_top; p > stack_buf; p -= p[-2] + 2) {
switch (p[-1]) {
case STACK_NEARJMP:
info->label_calls++;
if (!info->page_calls)
info->label_calls_after_page_call++;
break;
case STACK_FARJMP:
info->page_calls++;
break;
case STACK_VARIABLE:
info->var_pushes += p[-2] - 2;
if (info->page_calls + info->label_calls == 0)
info->var_pushes_after_call += p[-2] - 2;
break;
case STACK_TXXSTATE:
break;
}
}
}
/* TPx */
void sl_pushData(int *data, int cnt) {
dataPushCnt++;
sl_push(STACK_DATA, data, cnt);
void sl_pushState(enum txx_type type, int val1, int val2) {
int data[] = {type, val1, val2};
sl_push(STACK_TXXSTATE, data, 3);
}
/* TOx */
void sl_popData(int *data, int cnt) {
int *tmp;
if (dataPushCnt == 0) return;
tmp = sl_pop();
dataPushCnt--;
if (*tmp != STACK_DATA)
SYSERROR("Stack buffer is illegal");
if (*(tmp + 1) != cnt)
WARNING("Variable count is not match with stacked variable");
memcpy(data, tmp + 2, sizeof(int) * cnt);
void sl_popState(enum txx_type expected_type) {
// No-op if the stack top is of an unexpected type.
if (stack_top <= stack_buf ||
stack_top[-1] != STACK_TXXSTATE ||
stack_top[-3] != expected_type) {
WARNING("unexpected stack top type");
return;
}
int *tmp = sl_pop();
popState(tmp);
free(tmp);
}
static void popDatas(int *tmp) {
static void popState(int *tmp) {
int d1 = *(tmp + 2);
int d2 = *(tmp + 3);
int d3 = *(tmp + 4);
@@ -498,7 +489,6 @@ static void popDatas(int *tmp) {
msg_setMessageLocation(d2, d3);
break;
}
dataPushCnt--;
}
void *sl_setDataTable(int page, int index) {
@@ -513,10 +503,9 @@ void sl_returnGoto(int address) {
int *tmp = sl_pop();
int page;
while (TRUE) {
if (*tmp != STACK_FARJMP || *tmp != STACK_NEARJMP) break;
if (*tmp == STACK_DATA) {
popDatas(tmp);
while (*tmp != STACK_FARJMP && *tmp != STACK_NEARJMP) {
if (*tmp == STACK_TXXSTATE) {
popState(tmp);
} else if (*tmp == STACK_VARIABLE) {
popVars(tmp);
} else {
@@ -531,14 +520,9 @@ void sl_returnGoto(int address) {
// index = *(tmp + 3);
free(tmp);
sl_jmpFar2(page, address);
labelCallCnt_afterPageCall = 0;
pageCallCnt--;
} else {
// index = *(tmp + 2);
free(tmp);
sl_jmpNear(address);
labelCallCnt--;
labelCallCnt_afterPageCall--;
}
}
+18 -9
View File
@@ -34,7 +34,7 @@ enum stack_frame_type {
STACK_NEARJMP = 1,
STACK_FARJMP = 2,
STACK_VARIABLE = 3,
STACK_DATA = 4
STACK_TXXSTATE = 4
};
enum txx_type {
@@ -43,6 +43,15 @@ enum txx_type {
TxxTEXTLOC = 3
};
struct stack_info {
int top_attr; // always zero?
int page_calls;
int label_calls;
int var_pushes;
int label_calls_after_page_call;
int var_pushes_after_call;
};
// Use functions below instead of accessing these variables directly.
extern const uint8_t *sl_sco; // scenario page buffer
extern int sl_page; // current scenario page (0-based)
@@ -68,16 +77,16 @@ void sl_retNear(void);
void sl_callFar(int page);
void sl_callFar2(int page, int address);
void sl_retFar(void);
void sl_retFar2(void);
void sl_stackClear_allCall(void);
void sl_stackClear_labelCall(int cnt);
void sl_stackClear_pageCall(int cnt);
void sl_clearStack(bool restore);
void sl_dropLabelCalls(int cnt);
void sl_dropPageCalls(int cnt);
void sl_pushVar(struct VarRef *vref, int cnt);
void sl_popVar(struct VarRef *vref, int cnt);
int *sl_getStackInfo(int *size);
void sl_putStackInfo(int *data, int size);
void sl_pushData(int *data, int cnt);
void sl_popData(int *data, int cnt);
int *sl_getStack(int *size);
void sl_putStack(int *data, int size);
void sl_getStackInfo(struct stack_info *info);
void sl_pushState(enum txx_type type, int val1, int val2);
void sl_popState(enum txx_type expected_type);
void *sl_setDataTable(int page, int index);
void sl_returnGoto(int address);
+4 -9
View File
@@ -233,16 +233,11 @@ void sdl_drawImage8_fromData(cgdata *cg, int dx, int dy, int sprite_color) {
sdl_pal_check();
if (sdl_dib->format->BitsPerPixel > 8 && cg->pal) {
int i, i_st = 0, i_end = 256;
SDL_Color *c = s->format->palette->colors;
uint8_t *r = cg->pal->red, *g = cg->pal->green, *b = cg->pal->blue;
if (cg->type == ALCG_VSP) {
i_st = (cg->vsp_bank << 4);
i_end = i_st + 16;
c += i_st;
}
for (i = i_st; i < i_end; i++) {
uint8_t *r = cg->pal->red;
uint8_t *g = cg->pal->green;
uint8_t *b = cg->pal->blue;
for (int i = 0; i < 256; i++) {
c->r = *(r++);
c->g = *(g++);
c->b = *(b++);
+1 -1
View File
@@ -272,7 +272,7 @@ static void sdl_getEvent(void) {
cmd_count_of_prev_input = nact->cmd_count;
} else if (nact->cmd_count != cmd_count_of_prev_input) {
nact->wait_vsync = TRUE;
if (nact->game_rance4v2)
if (nact->game == GAME_RANCE4_V2)
rance4v2_hack();
}
+1 -1
View File
@@ -148,7 +148,7 @@ static void window_init(const char *render_driver) {
#else
Uint32 flags = SDL_WINDOW_RESIZABLE;
#endif
sdl_window = SDL_CreateWindow("XSystem3.5 Version "VERSION,
sdl_window = SDL_CreateWindow("XSystem35 Version "VERSION,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SYS35_DEFAULT_WIDTH, SYS35_DEFAULT_HEIGHT,
flags);
+11 -1
View File
@@ -110,6 +110,7 @@ static void sys35_usage(boolean verbose) {
puts("Usage: xsystem35 [OPTIONS]\n");
puts("OPTIONS");
puts(" -gamefile file : set game resource file to 'file'");
puts(" -game game : enable game-specific hacks");
puts(" -renderer name : set rendering driver name to 'name'");
puts(" -devcd device : set cdrom device name to 'device'");
puts(" -devmidi device: set midi device name to 'device'");
@@ -308,8 +309,12 @@ static void sys35_ParseOption(int *argc, char **argv) {
} else if (0 == strcmp(argv[i], "-version")) {
puts(VERSION);
exit(0);
} else if (0 == strcmp(argv[i], "-integerscale")) {
} else if (0 == strcmp(argv[i], "-integerscale")) {
sdl_setIntegerScaling(TRUE);
} else if (0 == strcmp(argv[i], "-game")) {
if (argv[i + 1] != NULL) {
enable_hack_by_gameid(argv[i + 1]);
}
}
}
}
@@ -394,6 +399,11 @@ static void check_profile() {
sdl_setIntegerScaling(TRUE);
}
}
/* enable game-specific hacks */
param = get_profile("game");
if (param) {
enable_hack_by_gameid(param);
}
}
#ifdef HAVE_SIGACTION
BIN
View File
Binary file not shown.
+58
View File
@@ -0,0 +1,58 @@
MS FILE,"stack.adv":
const word STACK_TOP_ATTR = 0:
const word NUM_PAGE_CALLS = 1:
const word NUM_LABEL_CALLS = 2:
const word NUM_VAR_PUSHES = 3:
const word NUM_LABEL_CALLS_AFTER_PAGE_CALL = 4:
const word NUM_VAR_PUSHES_AFTER_CALL = 5:
UR D01:
~AssertEquals D01[STACK_TOP_ATTR], 0, __LINE__:
~AssertEquals D01[NUM_PAGE_CALLS], 1, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS], 0, __LINE__:
~AssertEquals D01[NUM_VAR_PUSHES], 0, __LINE__:
~TestGlobalReturnFromLocalFunc:
%0:
**TestGlobalReturnFromLocalFunc:
UR D01:
~AssertEquals D01[STACK_TOP_ATTR], 0, __LINE__:
~AssertEquals D01[NUM_PAGE_CALLS], 2, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS], 0, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS_AFTER_PAGE_CALL], 0, __LINE__:
\LocalFunc:
; Unreachable
~Fail __LINE__:
%0:
*LocalFunc:
UR D01:
~AssertEquals D01[STACK_TOP_ATTR], 0, __LINE__:
~AssertEquals D01[NUM_PAGE_CALLS], 2, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS], 1, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS_AFTER_PAGE_CALL], 1, __LINE__:
~NestedGlobalFunc:
%0: ; This returns from TestGlobalReturnFromLocalFunc!
**NestedGlobalFunc:
US D01, 20:
UR D01:
~AssertEquals D01[STACK_TOP_ATTR], 0, __LINE__:
~AssertEquals D01[NUM_PAGE_CALLS], 3, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS], 1, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS_AFTER_PAGE_CALL], 0, __LINE__:
~AssertEquals D01[NUM_VAR_PUSHES], 20, __LINE__:
~AssertEquals D01[NUM_VAR_PUSHES_AFTER_CALL], 20, __LINE__:
\NestedLocalFunc:
%0:
*NestedLocalFunc:
UR D01:
~AssertEquals D01[STACK_TOP_ATTR], 0, __LINE__:
~AssertEquals D01[NUM_PAGE_CALLS], 3, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS], 2, __LINE__:
~AssertEquals D01[NUM_LABEL_CALLS_AFTER_PAGE_CALL], 1, __LINE__:
~AssertEquals D01[NUM_VAR_PUSHES], 20, __LINE__:
~AssertEquals D01[NUM_VAR_PUSHES_AFTER_CALL], 0, __LINE__:
\0:
+1
View File
@@ -11,6 +11,7 @@
%#array.adv:
%#strvar.adv:
%#stack.adv:
HH0,tests_passed: ' tests passed' R
HH0,tests_failed: ' tests failed' R
+1
View File
@@ -3,6 +3,7 @@ test.adv
util.adv
array.adv
strvar.adv
stack.adv
#DLLHeader
ShString.HEL
BIN
View File
Binary file not shown.
+6
View File
@@ -27,3 +27,9 @@ const word FILE = 1:
' actual: "' X actual: '"'
R
%0:
**Fail line:
inc tests_failed:
'[FAIL] ' X FILE: ':' HH0,line:
R
%0:
+11 -1
View File
@@ -18,7 +18,17 @@
# フォントのアンチエイリアスを無効にする
#antialias: No
# ----------------------------------------------------------
# ------------------------------------------------------------
# ------------------------------------------------------------
# Enables game-specific hacks. Usually auto-detected, but must be
# specified for games with modified / translated titles.
#
# Possible values are: toushin2, rance3_eng, rance4_eng, rance4_v2.
#game: rance4_v2
# ------------------------------------------------------------
# ------------------------------------------------------------
# CD-ROM のデバイス名