Files
kichikuou_system3-sdl2/src/sys/nact_sys1.cpp
T
kichikuou 131707f9d8 Merge upstream changes: Improve error messages for unknown commands
Unlike the upstream, we use fatal() because it generates a message box
even if DEBUG_CONSOLE is disabled.
2020-05-22 09:32:04 +09:00

1527 lines
32 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
ALICE SOFT SYSTEM1 for Win32
D.P.S. - Dream Program System
Intruder -桜屋敷の探索-
Little Vampire
あぶないてんぐ伝説
クレセントムーンがぁる
婦警さん物語VX
[ NACT - command ]
*/
#include "nact.h"
#include "ags.h"
#include "mako.h"
#include "crc32.h"
#include "../fileio.h"
#define WAIT(tm) \
{ \
Uint32 dwTime = SDL_GetTicks() + (tm); \
for(;;) { \
if(terminate) { \
return; \
} \
if(dwTime <= SDL_GetTicks()) { \
break; \
} \
SDL_Delay(10); \
} \
}
#define WAIT_KEYQUIT(tm) \
{ \
Uint32 dwTime = SDL_GetTicks() + (tm); \
for(;;) { \
if(terminate) { \
return; \
} \
if(get_key()) { \
for(;;) { \
if(terminate) { \
return; \
} \
if(!get_key()) { \
break; \
} \
if(dwTime <= SDL_GetTicks()) { \
break; \
} \
SDL_Delay(10); \
} \
break; \
} \
if(dwTime <= SDL_GetTicks()) { \
break; \
} \
SDL_Delay(10); \
} \
}
NACT_Sys1::NACT_Sys1(uint32 crc32, const char* font_file, const char* playlist)
: NACT(1, crc32, font_file, playlist)
{
menu_max = 6;
switch (crc32) {
case CRC32_DPS:
text_refresh = false;
strcpy_s(tvar[0], 22, "\x83\x4A\x83\x58\x83\x5E\x83\x80"); // "カスタム" in SJIS
strcpy_s(tvar[1], 22, "\x83\x8A\x81\x5B\x83\x69\x83\x58"); // "リーナス" in SJIS
strcpy_s(tvar[2], 22, "\x82\xA9\x82\xC2\x82\xDD"); // "かつみ" in SJIS
strcpy_s(tvar[3], 22, "\x97\x52\x94\xFC\x8E\x71"); // "由美子" in SJIS
strcpy_s(tvar[4], 22, "\x82\xA2\x82\xC2\x82\xDD"); // "いつみ" in SJIS
strcpy_s(tvar[5], 22, "\x82\xD0\x82\xC6\x82\xDD"); // "ひとみ" in SJIS
strcpy_s(tvar[6], 22, "\x90\x5E\x97\x9D\x8E\x71"); // "真理子" in SJIS
break;
case CRC32_INTRUDER:
menu_max = 11;
paint_x = paint_y = map_page = 0;
break;
}
}
void NACT_Sys1::opening()
{
switch (crc32) {
case CRC32_CRESCENT:
mako->play_music(2);
ags->load_cg(1, -1);
WAIT(3000);
ags->load_cg(81, -1);
break;
case CRC32_INTRUDER:
ags->load_cg(77, -1);
WAIT(1667);
ags->load_cg(74, -1);
break;
case CRC32_VAMPIRE:
mako->play_music(4);
ags->load_cg(3, -1);
WAIT(2000);
ags->load_cg(38, -1);
cmd_a();
ags->draw_box(0);
break;
}
}
void NACT_Sys1::cmd_calc()
{
int index = getd();
if(0x80 <= index && index <= 0xbf) {
index &= 0x3f;
} else {
index = ((index & 0x3f) << 8) | getd();
}
var[index] = cali();
output_console("\n!var[%d]:%d!", index, var[index]);
}
void NACT_Sys1::cmd_branch()
{
int condition = cali();
int nest = 0;
bool set_menu = false;
if(!condition) {
// 次の'}'命令までスキップする(ネストも考慮する)
for(;;) {
prev_addr = scenario_addr;
uint8 cmd = getd();
if(cmd == '!') {
int index = getd();
if(!(0x80 <= index && index <= 0xbf)) {
getd();
}
cali();
} else if(cmd == '{') {
cali();
nest++;
} else if(cmd == '}') {
if(nest) {
nest--;
} else {
break;
}
} else if(cmd == '@') {
getd();
getd();
} else if(cmd == '\\') {
getd();
getd();
} else if(cmd == '&') {
cali();
} else if(cmd == '%') {
cali();
} else if(cmd == '$') {
if(!set_menu) {
getd();
getd();
set_menu = true;
} else {
set_menu = false;
}
} else if(cmd == '[') {
getd();
getd();
getd();
getd();
} else if(cmd == ':') {
cali();
getd();
getd();
getd();
getd();
} else if(cmd == ']') {
} else if(cmd == 'A') {
} else if(cmd == 'F') {
} else if(cmd == 'G') {
getd();
} else if(cmd == 'L') {
getd();
} else if(cmd == 'P') {
getd();
} else if(cmd == 'Q') {
getd();
} else if(cmd == 'R') {
} else if(cmd == 'S') {
getd();
} else if(cmd == 'U') {
getd();
getd();
} else if(cmd == 'X') {
getd();
} else if(cmd == 'Y') {
cali();
cali();
} else if(cmd == 'Z') {
cali();
cali();
} else if(cmd == 0x20 || (0xa1 <= cmd && cmd <= 0xdd)) {
// message (1 byte)
} else if((0x81 <= cmd && cmd <= 0x9f) || 0xe0 <= cmd) {
// message (2 bytes)
getd();
} else {
if(cmd >= 0x20 && cmd < 0x7f) {
fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr);
} else {
fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr);
}
break;
}
}
}
output_console("\n{%d:", condition);
}
void NACT_Sys1::cmd_label_jump()
{
int next_addr = getw();
scenario_addr = next_addr;
output_console("\n@%x:", next_addr);
}
void NACT_Sys1::cmd_label_call()
{
int next_addr = getw();
output_console("\n\\%x:", next_addr);
if(next_addr == 0) {
// リターン
if(label_depth == 0) {
// fatal_error = true;
return;
}
scenario_addr = label_stack[--label_depth];
} else {
label_stack[label_depth++] = scenario_addr;
scenario_addr = next_addr;
}
}
void NACT_Sys1::cmd_page_jump()
{
int next_page = cali();
load_scenario(next_page);
scenario_page = next_page;
scenario_addr = 2;
output_console("\n&%d:", next_page);
}
void NACT_Sys1::cmd_page_call()
{
int next_page = cali(), next_addr;
output_console("\n%%%d:", next_page);
if(next_page == 0) {
// リターン
if(page_depth == 0) {
// fatal_error = true;
return;
}
next_page = page_stack[--page_depth];
next_addr = addr_stack[page_depth];
} else {
page_stack[page_depth] = scenario_page;
addr_stack[page_depth++] = scenario_addr;
next_addr = 2;
}
load_scenario(next_page);
scenario_page = next_page;
scenario_addr = next_addr;
}
void NACT_Sys1::cmd_set_menu()
{
if(ags->draw_menu) {
ags->menu_dest_x = 2;
ags->menu_dest_y += ags->menu_font_size + 2;
ags->draw_menu = false;
output_console("$");
} else {
if(!menu_index) {
ags->clear_menu_window();
ags->menu_dest_y = 0;
}
menu_addr[menu_index++] = getw();
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_menu = true;
output_console("\n$%x,", menu_addr[menu_index - 1]);
}
}
void NACT_Sys1::cmd_open_menu()
{
output_console("\n]");
if(!menu_index) {
scenario_addr = scenario_data[0] | (scenario_data[1] << 8);
return;
}
if(crc32 == CRC32_DPS && !text_refresh) {
cmd_a();
}
// クリック中の間は待機
for(;;) {
if(terminate) {
return;
}
// if(get_key() != 32) {
if(!get_key()) {
break;
}
SDL_Delay(10);
}
// メニュー表示
ags->open_menu_window(menu_window);
int current_index = 0;
// マウス移動
int sx = ags->menu_w[menu_window - 1].sx;
int sy = ags->menu_w[menu_window - 1].sy;
int ex = ags->menu_w[menu_window - 1].ex;
int mx = ex - 16;
int my = sy + 10;
int height = ags->menu_font_size + 4;
set_cursor(mx, my);
// メニュー選択
for(;;) {
// 入力待機
int val = 0, current_mx = mx, current_my = my;
for(;;) {
if(terminate) {
return;
}
if((val = get_key())) {
SDL_Delay(100);
break;
}
get_cursor(&current_mx, &current_my);
if(abs(my - current_my) > 3) {
break;
}
SDL_Delay(10);
}
if(val) {
for(;;) {
if(terminate) {
return;
}
if(!get_key()) {
break;
}
SDL_Delay(10);
}
}
if(val == 0) {
// マウス操作
mx = current_mx; my = current_my;
int index = (my - sy) / height;
if(sx <= mx && mx <= ex && 0 <= index && index < menu_index) {
current_index = index;
ags->redraw_menu_window(menu_window, current_index);
}
} else if(val == 1 || val == 2 || val == 4 || val == 8) {
if(val == 1) {
current_index = current_index ? current_index - 1 : menu_index - 1;
} else if(val == 2) {
current_index = (current_index < menu_index - 1) ? current_index + 1 : 0;
} else if(val == 4) {
current_index = 0;
} else if(val == 8) {
current_index = menu_index - 1;
}
ags->redraw_menu_window(menu_window, current_index);
} else if(val == 16) {
break;
} else if(val == 32) {
current_index = -1;
break;
}
}
// 画面更新
ags->close_menu_window(menu_window);
if(clear_text) {
ags->clear_text_window(text_window, true);
}
if(current_index != -1) {
scenario_addr = menu_addr[current_index];
}
menu_index = 0;
}
void NACT_Sys1::cmd_set_verbobj()
{
int verb = getd();
int obj = getd();
int addr = getw();
menu_addr[menu_index] = addr;
menu_verb[menu_index] = verb;
menu_obj[menu_index++] = obj;
verb_obj = true;
output_console("\n[%x,%s,%s:", addr, caption_verb[verb], caption_obj[obj]);
}
void NACT_Sys1::cmd_set_verbobj2()
{
int condition = cali();
int verb = getd();
int obj = getd();
int addr = getw();
if(condition) {
menu_addr[menu_index] = addr;
menu_verb[menu_index] = verb;
menu_obj[menu_index++] = obj;
}
verb_obj = true;
output_console("\n:%d,%x,%s,%s:", condition, addr, caption_verb[verb], caption_obj[obj]);
}
void NACT_Sys1::cmd_open_verb()
{
// 動詞メニューの表示
output_console("\nopen verb-obj menu");
verb_obj = false;
// 表示する動詞のチェック
int chk[MAX_VERB], page = 0, cnt = 0;
memset(chk, 0, sizeof(chk));
for(int i = 0; i < menu_index; i++) {
chk[menu_verb[i]] = 1;
}
for(int i = 0; i < MAX_VERB; i++) {
if(chk[i]) {
cnt++;
}
}
top:
// メニュー項目の準備
int id[32], index = 0;
ags->clear_menu_window();
ags->menu_dest_y = 0;
ags->draw_menu = true;
if(cnt <= menu_max) {
// 1ページ内に全て表示できる
for(int i = 0; i < MAX_VERB; i++) {
if(chk[i]) {
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_text(caption_verb[i]);
id[index++] = i;
ags->menu_dest_y += ags->menu_font_size + 2;
}
}
} else {
top2:
for(int i = page; i < MAX_VERB; i++) {
if(chk[i]) {
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_text(caption_verb[i]);
id[index++] = i;
ags->menu_dest_y += ags->menu_font_size + 2;
}
page = i + 1;
if(index == menu_max - 1) {
break;
}
}
if(index == 0) {
// 最初のページに戻る
page = 0;
goto top2;
}
// 次のページを追加
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_text(SJIS_NEXT_PAGE);
id[index++] = -1;
ags->menu_dest_y += ags->menu_font_size + 2;
}
ags->draw_menu = false;
// クリック中の間は待機
for(;;) {
if(terminate) {
return;
}
// if(get_key() != 32) {
if(!get_key()) {
break;
}
SDL_Delay(10);
}
// メニュー表示
ags->open_menu_window(menu_window);
int current_index = 0;
// マウス移動
int sx = ags->menu_w[menu_window - 1].sx;
int sy = ags->menu_w[menu_window - 1].sy;
int ex = ags->menu_w[menu_window - 1].ex;
int mx = ex - 16;
int my = sy + 10;
int height = ags->menu_font_size + 4;
set_cursor(mx, my);
// メニュー選択
for(;;) {
// 入力待機
int val = 0, current_mx = mx, current_my = my;
for(;;) {
if(terminate) {
return;
}
if((val = get_key())) {
SDL_Delay(100);
break;
}
get_cursor(&current_mx, &current_my);
if(abs(my - current_my) > 3) {
break;
}
SDL_Delay(10);
}
if(val) {
for(;;) {
if(terminate) {
return;
}
if(!get_key()) {
break;
}
SDL_Delay(10);
}
}
if(val == 0) {
// マウス操作
mx = current_mx; my = current_my;
int mindex = (my - sy) / height;
if(sx <= mx && mx <= ex && 0 <= mindex && mindex < index) {
current_index = mindex;
ags->redraw_menu_window(menu_window, current_index);
}
} else if(val == 1 || val == 2 || val == 4 || val == 8) {
if(val == 1) {
current_index = current_index ? current_index - 1 : index - 1;
} else if(val == 2) {
current_index = (current_index < index - 1) ? current_index + 1 : 0;
} else if(val == 4) {
current_index = 0;
} else if(val == 8) {
current_index = index - 1;
}
ags->redraw_menu_window(menu_window, current_index);
} else if(val == 16) {
break;
} else if(val == 32) {
current_index = -1;
break;
}
}
// 画面更新
ags->close_menu_window(menu_window);
if(clear_text) {
ags->clear_text_window(text_window, true);
}
if(current_index == -1) {
scenario_addr = scenario_data[0] | (scenario_data[1] << 8);
} else if(id[current_index] == -1) {
goto top;
} else {
cmd_open_obj(id[current_index]);
}
menu_index = 0;
}
void NACT_Sys1::cmd_open_obj(int verb)
{
// 目的語メニューの表示
verb_obj = false;
// 表示する目的語のチェック
int chk[MAX_OBJ], addr[MAX_OBJ], page = 0, cnt = 0;
memset(chk, 0, sizeof(chk));
for(int i = 0; i < menu_index; i++) {
if(menu_verb[i] == verb) {
chk[menu_obj[i]] = 1;
addr[menu_obj[i]] = menu_addr[i];
}
}
for(int i = 0; i < MAX_OBJ; i++) {
if(chk[i]) {
cnt++;
}
}
// 目的語がない場合
if(chk[0] && cnt == 1) {
scenario_addr = addr[0];
return;
}
// 以後、obj=0は戻るとして扱う
chk[0] = 0;
addr[0] = scenario_data[0] | (scenario_data[1] << 8);
top:
// メニュー項目の準備
int id[32], index = 0;
ags->clear_menu_window();
ags->menu_dest_y = 0;
ags->draw_menu = true;
if(cnt <= menu_max - 1) {
// 1ページ内に全て表示できる
for(int i = 0; i < MAX_OBJ; i++) {
if(chk[i]) {
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_text(caption_obj[i]);
id[index++] = i;
ags->menu_dest_y += ags->menu_font_size + 2;
}
}
// 戻るを追加
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_text(SJIS_BACK);
id[index++] = 0;
ags->menu_dest_y += ags->menu_font_size + 2;
} else {
top2:
for(int i = page; i < MAX_OBJ; i++) {
if(chk[i]) {
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_text(caption_obj[i]);
id[index++] = i;
ags->menu_dest_y += ags->menu_font_size + 2;
}
page = i + 1;
if(index == menu_max - 2) {
break;
}
}
if(index == 0) {
// 最初のページに戻る
page = 0;
goto top2;
}
// 戻るを追加
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_text(SJIS_BACK);
id[index++] = 0;
ags->menu_dest_y += ags->menu_font_size + 2;
// 次のページを追加
ags->menu_dest_x = 2;
ags->menu_dest_y += 2;
ags->draw_text(SJIS_NEXT_PAGE);
id[index++] = -1;
ags->menu_dest_y += ags->menu_font_size + 2;
}
ags->draw_menu = false;
// クリック中の間は待機
for(;;) {
if(terminate) {
return;
}
// if(get_key() != 32) {
if(!get_key()) {
break;
}
SDL_Delay(10);
}
// メニュー表示
ags->open_menu_window(menu_window);
int current_index = 0;
// マウス移動
int sx = ags->menu_w[menu_window - 1].sx;
int sy = ags->menu_w[menu_window - 1].sy;
int ex = ags->menu_w[menu_window - 1].ex;
int mx = ex - 16;
int my = sy + 10;
int height = ags->menu_font_size + 4;
set_cursor(mx, my);
// メニュー選択
for(;;) {
// 入力待機
int val = 0, current_mx = mx, current_my = my;
for(;;) {
if(terminate) {
return;
}
if((val = get_key())) {
SDL_Delay(100);
break;
}
get_cursor(&current_mx, &current_my);
if(abs(my - current_my) > 3) {
break;
}
SDL_Delay(10);
}
if(val) {
for(;;) {
if(terminate) {
return;
}
if(!get_key()) {
break;
}
SDL_Delay(10);
}
}
if(val == 0) {
// マウス操作
mx = current_mx; my = current_my;
int mindex = (my - sy) / height;
if(sx <= mx && mx <= ex && 0 <= mindex && mindex < index) {
current_index = mindex;
ags->redraw_menu_window(menu_window, current_index);
}
} else if(val == 1 || val == 2 || val == 4 || val == 8) {
if(val == 1) {
current_index = current_index ? current_index - 1 : index - 1;
} else if(val == 2) {
current_index = (current_index < index - 1) ? current_index + 1 : 0;
} else if(val == 4) {
current_index = 0;
} else if(val == 8) {
current_index = index - 1;
}
ags->redraw_menu_window(menu_window, current_index);
} else if(val == 16) {
break;
} else if(val == 32) {
current_index = -1;
break;
}
}
// 画面更新
ags->close_menu_window(menu_window);
if(clear_text) {
ags->clear_text_window(text_window, true);
}
if(current_index == -1) {
scenario_addr = scenario_data[0] | (scenario_data[1] << 8);
} else if(id[current_index] == -1) {
goto top;
} else {
scenario_addr = addr[id[current_index]];
}
}
void NACT_Sys1::cmd_a()
{
output_console("A\n");
if(!text_skip_enb) {
// Pushマークの表示
if(show_push) {
ags->draw_push(text_window);
}
// キーが押されて離されるまで待機
for(;;) {
if(terminate) {
return;
}
if(get_key()) {
break;
}
SDL_Delay(10);
}
SDL_Delay(100);
for(;;) {
if(terminate) {
return;
}
if(!(get_key() & 0x18)) {
break;
}
SDL_Delay(10);
}
}
// ウィンドウ更新
ags->clear_text_window(text_window, true);
if (crc32 == CRC32_DPS)
text_refresh = true;
}
void NACT_Sys1::cmd_b()
{
// 未使用
fatal("Unknown Command: 'B' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_d()
{
// 未使用
fatal("Unknown Command: 'D' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_e()
{
// 未使用
fatal("Unknown Command: 'E' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_f()
{
output_console("\nF");
scenario_addr = 2;
}
void NACT_Sys1::cmd_g()
{
int page = getd();
output_console("\nG %d:", page);
if (crc32 == CRC32_INTRUDER) {
page = (page == 97) ? 96 : (page == 98) ? 97 : page;
}
ags->load_cg(page, -1);
if (crc32 == CRC32_INTRUDER) {
if(page == 94) {
WAIT(400);
}
if(page == 81 || page == 82) {
map_page = page;
}
}
}
void NACT_Sys1::cmd_h()
{
// 未使用
fatal("Unknown Command: 'H' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_i()
{
// 未使用
fatal("Unknown Command: 'I' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_j()
{
// 未使用
fatal("Unknown Command: 'J' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_k()
{
// 未使用
fatal("Unknown Command: 'K' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_l()
{
int index = getd();
output_console("\nL %d:", index);
if(1 <= index && index <= 26) {
// ASLEEP_A.DAT - ASLEEP_Z.DAT
char path[_MAX_PATH];
strcpy_s(path, _MAX_PATH, "ASLEEP_A.DAT");
path[7] = 'A' + index - 1;
FILEIO* fio = new FILEIO();
if(fio->Fopen(path, FILEIO_READ_BINARY)) {
fio->Fseek(112, FILEIO_SEEK_SET);
int next_page = fio->Fgetw() - 1;
fio->Fgetw();
fio->Fgetw(); // cg no?
fio->Fgetw();
int next_music = fio->Fgetw();
fio->Fgetw();
int next_addr = fio->Fgetw();
fio->Fgetw();
for(int i = 0; i < 512; i++) {
var[i] = fio->Fgetw();
}
ags->menu_font_size = fio->Fgetw();
ags->text_font_size = fio->Fgetw();
ags->palette_bank = fio->Fgetw();
if(!ags->palette_bank) {
ags->palette_bank = -1;
}
ags->text_font_color = fio->Fgetw();
ags->menu_font_color = fio->Fgetw();
ags->menu_frame_color = fio->Fgetw();
ags->menu_back_color = fio->Fgetw();
ags->text_frame_color = fio->Fgetw();
ags->text_back_color = fio->Fgetw();
for(int i = 0; i < 10; i++) {
ags->menu_w[i].sx = fio->Fgetw();
ags->menu_w[i].sy = fio->Fgetw();
ags->menu_w[i].ex = fio->Fgetw();
ags->menu_w[i].ey = fio->Fgetw();
ags->menu_w[i].push = fio->Fgetw() ? true : false;
ags->menu_w[i].frame = fio->Fgetw() ? true : false;
fio->Fgetw();
fio->Fgetw();
if(ags->menu_w[i].screen) {
free(ags->menu_w[i].screen);
}
ags->menu_w[i].screen = NULL;
if(ags->menu_w[i].window) {
free(ags->menu_w[i].window);
}
ags->menu_w[i].window = NULL;
}
for(int i = 0; i < 10; i++) {
ags->text_w[i].sx = fio->Fgetw();
ags->text_w[i].sy = fio->Fgetw();
ags->text_w[i].ex = fio->Fgetw();
ags->text_w[i].ey = fio->Fgetw();
ags->text_w[i].push = fio->Fgetw() ? true : false;
ags->text_w[i].frame = fio->Fgetw() ? true : false;
fio->Fgetw();
fio->Fgetw();
if(ags->text_w[i].screen) {
free(ags->text_w[i].screen);
}
ags->text_w[i].screen = NULL;
if(ags->text_w[i].window) {
free(ags->text_w[i].window);
}
ags->text_w[i].window = NULL;
}
for(int i = 0; i < 10; i++) {
fio->Fread(tvar[i], 22, 1);
}
for(int i = 0; i < 30; i++) {
for(int j = 0; j < 10; j++) {
fio->Fread(tvar_stack[i][j], 22, 1);
}
}
for(int i = 0; i < 30; i++) {
for(int j = 0; j < 20; j++) {
var_stack[i][j] = fio->Fgetw();
}
}
fio->Fclose();
load_scenario(next_page);
scenario_page = next_page;
scenario_addr = next_addr;
mako->play_music(next_music);
}
delete fio;
}
}
void NACT_Sys1::cmd_m()
{
// 未使用
fatal("Unknown Command: 'M' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_n()
{
// 未使用
fatal("Unknown Command: 'N' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_o()
{
// 未使用
fatal("Unknown Command: 'O' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_p()
{
int param = getd();
ags->text_font_color = (uint8)((param & 0x7) + 16);
output_console("\nP %d:", param);
}
#define FWRITE(data, size) { \
memcpy(&buffer[p], data, size); \
p += size; \
}
#define FPUTW(data) { \
uint16 tmp = (data); \
buffer[p++] = tmp & 0xff; \
buffer[p++] = (tmp >> 8) & 0xff; \
}
void NACT_Sys1::cmd_q()
{
static char header[112] = {
'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 'a', 'v', 'e', ' ', 'd', 'a', 't',
'a', ' ', 'f', 'o', 'r', ' ', 'S', 'y', 's', 't', 'e', 'm', '1', ' ', ' ', 'U',
'n', 'i', 'o', 'n', ' ', '[', 'W', 'i', 'n', '9', 'x', '/', 'N', 'T', '4', '0',
'/', '2', '0', '0', '0', '/', 'X', 'P', '/', 'C', 'E', ']', ' ', 'F', 'o', 'r',
' ', 'N', 'A', 'C', 'T', '/', 'A', 'D', 'V', ' ', 's', 'y', 's', 't', 'e', 'm',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '(', 'C', ')', '2', '0', '0',
'4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' '
};
int index = getd();
output_console("\nQ %d:", index);
if(1 <= index && index <= 26) {
// ASLEEP_A.DAT - ASLEEP_Z.DAT
char path[_MAX_PATH];
strcpy_s(path, _MAX_PATH, "ASLEEP_A.DAT");
path[7] = 'A' + index - 1;
FILEIO* fio = new FILEIO();
if(fio->Fopen(path, FILEIO_WRITE_BINARY)) {
uint8 buffer[9510];
int p = 0;
FWRITE(header, 112);
FPUTW(scenario_page + 1);
FPUTW(0);
FPUTW(0); // cg no?
FPUTW(0);
FPUTW(mako->current_music);
FPUTW(0);
FPUTW(scenario_addr);
FPUTW(0);
for(int i = 0; i < 512; i++) {
FPUTW(var[i]);
}
FPUTW(ags->menu_font_size);
FPUTW(ags->text_font_size);
FPUTW(ags->palette_bank == -1 ? 0 : ags->palette_bank);
FPUTW(ags->text_font_color);
FPUTW(ags->menu_font_color);
FPUTW(ags->menu_frame_color);
FPUTW(ags->menu_back_color);
FPUTW(ags->text_frame_color);
FPUTW(ags->text_back_color);
for(int i = 0; i < 10; i++) {
FPUTW(ags->menu_w[i].sx);
FPUTW(ags->menu_w[i].sy);
FPUTW(ags->menu_w[i].ex);
FPUTW(ags->menu_w[i].ey);
FPUTW(ags->menu_w[i].push ? 1 : 0);
FPUTW(ags->menu_w[i].frame ? 1 : 0);
FPUTW(0);
FPUTW(0);
}
for(int i = 0; i < 10; i++) {
FPUTW(ags->text_w[i].sx);
FPUTW(ags->text_w[i].sy);
FPUTW(ags->text_w[i].ex);
FPUTW(ags->text_w[i].ey);
FPUTW(ags->text_w[i].push ? 1 : 0);
FPUTW(ags->text_w[i].frame ? 1 : 0);
FPUTW(0);
FPUTW(0);
}
for(int i = 0; i < 10; i++) {
FWRITE(tvar[i], 22);
}
for(int i = 0; i < 30; i++) {
for(int j = 0; j < 10; j++) {
FWRITE(tvar_stack[i][j], 22);
}
}
for(int i = 0; i < 30; i++) {
for(int j = 0; j < 20; j++) {
FPUTW(var_stack[i][j]);
}
}
fio->Fwrite(buffer, 9510, 1);
fio->Fclose();
}
delete fio;
}
}
void NACT_Sys1::cmd_r()
{
output_console("R\n");
// ウィンドウの表示範囲外の場合は改ページ
if(ags->return_text_line(text_window)) {
cmd_a();
}
}
void NACT_Sys1::cmd_s()
{
int page = getd();
output_console("\nS %d:", page);
if(page) {
mako->play_music(page);
} else {
mako->stop_music();
}
}
void NACT_Sys1::cmd_t()
{
// 未使用
fatal("Unknown Command: 'T' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_u()
{
int page = getd();
int transparent = getd();
output_console("\nU %d,%d:", page, transparent);
if (crc32 == CRC32_INTRUDER) {
ags->load_cg(page, 11);
if(page == 5) {
WAIT(400);
}
} else {
ags->load_cg(page, transparent);
}
}
void NACT_Sys1::cmd_v()
{
// 未使用
fatal("Unknown Command: 'V' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_w()
{
// 未使用
fatal("Unknown Command: 'W' at page = %d, addr = %d", scenario_page, prev_addr);
}
void NACT_Sys1::cmd_x()
{
int index = getd();
output_console("\nX %d:", index);
if(1 <= index && index <= 10) {
ags->draw_text(tvar[index - 1]);
}
}
void NACT_Sys1::cmd_y()
{
int cmd = cali();
int param = cali();
output_console("\nY %d,%d:", cmd, param);
switch (crc32) {
case CRC32_BUNKASAI:
case CRC32_CRESCENT:
case CRC32_DPS:
case CRC32_FUKEI:
case CRC32_TENGU:
switch(cmd) {
case 0:
ags->clear_text_window(text_window, true);
break;
case 1:
{
char buf[16];
buf[0] = '0' + (int)(param / 10000);
param %= 10000;
buf[1] = '0' + (int)(param / 1000);
param %= 1000;
buf[2] = '0' + (int)(param / 100);
param %= 100;
buf[3] = '0' + (int)(param / 10);
buf[4] = '0' + (param % 10);
buf[5] = '\0';
int p = 0;
for(;;) {
if(buf[p] != '0') {
break;
}
p++;
}
ags->draw_text(&buf[p < 4 ? p : 4]);
}
break;
case 2:
switch (crc32) {
case CRC32_CRESCENT:
for(int i = 39; i <= 48; i++)
var[i] = 0;
break;
case CRC32_DPS:
for(int i = 0; i <= 20; i++)
var[i] = 0;
break;
default:
for(int i = 0; i <= 16; i++)
var[i] = 0;
break;
}
break;
case 3:
WAIT(param * 1000 / 60)
break;
case 4:
RND = (param == 0 || param == 1) ? 0 : random(param);
break;
case 7:
if(crc32 == CRC32_DPS && param == 1) {
ags->box_fill(0, 40, 8, 598, 270, 0);
}
break;
case 130:
if (crc32 == CRC32_TENGU) {
WAIT(2000)
ags->load_cg(180, -1);
WAIT(2000)
ags->draw_box(0);
ags->dest_screen = 1;
ags->load_cg(173, -1);
ags->dest_screen = 0;
ags->gcopy(0x1ecd, 0x3a2a, 8, 60, 3);
WAIT(667);
ags->gcopy(0x1b65, 0x262e, 8, 60, 3);
ags->gcopy(0x2e25, 0x38ee, 7, 9, 3);
WAIT(667);
ags->gcopy(0x1914, 0x1914, 8, 63, 3);
WAIT(667);
ags->gcopy(0x182c, 0x182c, 7, 50, 3);
WAIT(667);
ags->gcopy(0x0000, 0x1ecd, 32, 60, 1);
WAIT(667);
for(int i = 12; i <= 57; i++) {
ags->gcopy(i + 0x2306, i + 0x2306, 1, 165, 3);
}
WAIT_KEYQUIT(6000)
ags->draw_box(param);
}
break;
case 253:
post_quit = false;
fatal_error = true;
break;
case 254:
RND = 0;
break;
case 255:
if (crc32 == CRC32_DPS)
post_quit = false;
else
post_quit = true;
fatal_error = true;
break;
}
break;
case CRC32_INTRUDER:
switch(cmd) {
case 0:
ags->clear_text_window(text_window, true);
break;
case 1:
if(show_push) {
ags->draw_push(text_window);
}
for(;;) {
if(terminate) {
return;
}
if(get_key()) {
break;
}
SDL_Delay(10);
}
SDL_Delay(100);
for(;;) {
if(terminate) {
return;
}
if(!(get_key() & 0x18)) {
break;
}
SDL_Delay(10);
}
ags->clear_text_window(text_window, true);
break;
case 2:
if(param == 0) {
post_quit = true;
fatal_error = true;
} else {
WAIT(100)
}
break;
case 3:
WAIT(param * 1000)
break;
case 255:
post_quit = true;
fatal_error = true;
break;
}
break;
}
}
void NACT_Sys1::cmd_z()
{
if (crc32 == CRC32_CRESCENT) {
cmd_y();
return;
}
int cmd = cali();
int param = cali();
output_console("\nZ %d,%d:", cmd, param);
switch (crc32) {
case CRC32_INTRUDER:
if(cmd == 1 && 1 <= param && param <= 4) {
const char* buf[4] = {
"\x81\x83", // "<" in SJIS
"\x81\xC8", // "∧" in SJIS
"\x81\x84", // ">" in SJIS
"\x81\xC9", // "∨" in SJIS
};
// 矢印を消去する
if(map_page) {
ags->load_cg(map_page, -1);
if(paint_x) {
ags->paint(paint_x, paint_y * 2, 2 + 16);
}
}
// 矢印を表示する
int x = ags->text_dest_x;
int y = ags->text_dest_y;
int color = ags->text_font_color;
ags->text_font_size = 24;
ags->text_font_color = 16;
ags->text_dest_x = 456;
ags->text_dest_y = 103;
ags->draw_text(buf[param - 1]);
ags->text_dest_x = x;
ags->text_dest_y = y;
ags->text_font_size = 16;
ags->text_font_color = color;
} else if(cmd == 2) {
ags->load_cg(74, -1);
ags->load_cg(81, -1);
map_page = 81;
} else if(cmd == 3) {
RND = (param == 0 || param == 1) ? 0 : random(param);
} else if(460 <= cmd && cmd <= 625 && 20 <= param && param <= 55) {
if(paint_x) {
ags->paint(paint_x, paint_y * 2, 5 + 16);
}
ags->paint(cmd, param * 2, 2 + 16);
paint_x = cmd;
paint_y = param;
} else {
paint_x = 0;
}
break;
case CRC32_TENGU:
if(cmd == 10) {
// nop
} else if(cmd == 20) {
if(param == 20) {
ags->gcopy(8, 8, 46, 144, 2);
} else if(param == 21) {
ags->gcopy(8, 8, 46, 144, 3);
}
}
break;
}
}
// 下位関数
uint16 NACT_Sys1::cali()
{
uint32 cali[256];
int p = 1;
bool ok = false;
while(p > 0) {
uint8 dat = getd();
// 除算はサポートしない?
if(0x80 <= dat && dat <= 0xbf) {
cali[p++] = var[dat & 0x3f];
} else if(0xc0 <= dat && dat <= 0xff) {
cali[p++] = var[((dat & 0x3f) << 8) | getd()];
} else if(0x00 <= dat && dat <= 0x3f) {
cali[p++] = ((dat & 0x3f) << 8) | getd();
} else if(0x40 <= dat && dat <= 0x77) {
cali[p++] = dat & 0x3f;
} else if(dat == 0x78) {
cali[p - 2] = cali[p - 2] * cali[p - 1];
if (cali[p - 2] > 65535) {
cali[p - 2] = 65535;
}
p--;
} else if(dat == 0x79) {
cali[p - 2] = cali[p - 2] + cali[p - 1];
if (cali[p - 2] > 65535) {
cali[p - 2] = 65535;
}
p--;
} else if(dat == 0x7a) {
if(cali[p - 2] > cali[p - 1]) {
cali[p - 2] = cali[p - 2] - cali[p - 1];
} else {
cali[p - 2] = 0;
}
p--;
} else if(dat == 0x7b) {
cali[p - 2] = (cali[p - 2] == cali[p - 1]) ? 1 : 0;
p--;
} else if(dat == 0x7c) {
cali[p - 2] = (cali[p - 2] < cali[p - 1]) ? 1 : 0;
p--;
} else if(dat == 0x7d) {
cali[p - 2] = (cali[p - 2] > cali[p - 1]) ? 1 : 0;
p--;
} else if(dat == 0x7e) {
cali[p - 2] = (cali[p - 2] != cali[p - 1]) ? 1 : 0;
p--;
} else if(dat == 0x7f) {
if(p == 2) {
ok = true;
}
p = 0;
}
}
if (!ok) {
fatal("cali: invalid expression");
}
return (uint16)(cali[1] & 0xffff);
}
uint16 NACT_Sys1::cali2()
{
uint16 val = 0;
uint16 dat = getd();
if(0x80 <= dat && dat <= 0xbf) {
val = dat & 0x3f;
} else if(0xc0 <= dat && dat <= 0xff) {
val = ((dat & 0x3f) << 8) | getd();
} else {
fatal("cali2: invalid expression");
}
if(getd() != 0x7f) {
fatal("cali2: invalid expression");
}
return val;
}