/* * cmdz.c SYSTEM35 Z command * * Copyright (C) 1997-1998 Masaki Chikama (Wren) * 1998- * * 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 * */ /* $Id: cmdz.c,v 1.35 2003/01/12 10:48:50 chikama Exp $ */ #include #include #include #include "portab.h" #include "xsystem35.h" #include "gfx.h" #include "scheduler.h" #include "ags.h" #include "scenario.h" #include "randMT.h" #include "selection.h" #include "message.h" #include "input.h" #include "nact.h" #include "font.h" static struct { uint32_t base; int divisor; } counters[257]; // [0] for ZT 1-5, [1..256] for ZT 10-11 static void reset_counter(int num, int divisor, int offset) { counters[num].base = sys_get_ticks() - offset; counters[num].divisor = divisor; } static uint32_t get_counter(int num) { scheduler_on_event(SCHEDULER_EVENT_TIMER_CHECK); return sys_get_ticks() - counters[num].base; } void commandZC() { /* システムの使用環境を変更する */ int m = getCaliValue(); int n = getCaliValue(); switch(m) { case 0: cg_vspPB = n; break; case 1: nact->msg.MsgFontColor = n; break; case 2: nact->sel.MsgFontColor = n; break; case 3: nact->sel.WinFrameColor = n; break; case 4: nact->sel.WinBackgroundColor = n; break; case 5: nact->msg.WinFrameColor = n; break; case 6: nact->msg.WinBackgroundColor = n; break; case 7: nact->msg.HitAnyKeyMsgColor = n; break; case 10: nact->sel.EncloseType = n; break; case 11: nact->sel.SelectedElementColor = n; break; case 13: nact->msg.WinBackgroundTransparent = n; break; case 14: nact->sel.WinBackgroundTransparent = n; break; case 15: sel_setDefaultElement(n); break; default: WARNING("commandZC(): Unknown Command (%d)", m); break; } TRACE("ZC %d,%d:",m,n); } void commandZM() { /* シナリオメッセージのフォントサイズを指定する。*/ int size = getCaliValue(); if (size > 100) { WARNING("msg font size force to 100 from %d", size); size = 100; } nact->msg.MsgFontSize = size; TRACE("ZM %d:",size); } void commandZS() { /* 選択肢のフォントサイズを指定する */ int size = getCaliValue(); nact->sel.MsgFontSize = size; TRACE("ZS %d:",size); } void commandZB() { /* メッセージ文字を太さを設定 */ int weight = getCaliValue(); if (nact->ags.enable_zb) nact->ags.font_weight = weight > 5 ? FONT_WEIGHT_BOLD : FONT_WEIGHT_NORMAL; TRACE("ZB %d:", weight); } void commandZH() { /* 全角半角切替え */ int sw = getCaliValue(); sys_setHankakuMode(sw); TRACE("ZH %d:",sw); } void commandZW() { /* CAPS 状態の内部的制御を変更する。 */ int sw = getCaliValue(); if (sw < 256) { // System 3.5 has a bug in which ZW 1 does not disable message waiting, // and Rance 2 depends on it. if (game_id == GAME_RANCE2) sw = 2; nact->messagewait_enable = ((sw & 0xff) > 1); nact->messagewait_cancelled = false; } else { nact->messagewait_time = sw & 0xff; nact->messagewait_cancel = !!(sw & 0x200); } TRACE("ZW %d:", sw); } void commandZL() { /* メッセージ領域の文字の縦方向行間ドット数を指定する。*/ int line = getCaliValue(); nact->msg.LineIncrement = line; TRACE("ZL %d:",line); } void commandZE() { /* 選択肢を選んだらメッセージ領域を初期化するかどうかを指定する */ int sw = getCaliValue(); nact->sel.ClearMsgWindow = sw != 0; TRACE("ZE %d:", sw); } void commandZF() { /* 選択肢枠サイズを可変にするか固定にするかを指定 */ int sw = getCaliValue(); switch(sw) { case 0: nact->sel.WinResizeHeight = true; break; case 1: nact->sel.WinResizeHeight = false; break; case 2: nact->sel.WinResizeWidth = false; break; case 3: nact->sel.WinResizeWidth = true; break; } TRACE("ZF %d:", sw); } void commandZD() { int c0 = sl_getc(); int sw = 0, *var; char *msg; switch(c0) { case 0: case 1: sw = getCaliValue(); break; case 2: sw = getCaliValue(); msg = toUTF8(svar_get(sw)); sys_message(2, "[DEBUG] %s\n", msg); free(msg); break; case 3: sw = getCaliValue(); sys_message(2, "[DEBUG] %d\n", sw); break; case 4: var = getCaliVariable(); *var = 0; break; } TRACE("ZD %d,%d:", c0, sw); } void commandZT0() { /* 現在の日時を var0〜var6 の変数列に返す。*/ time_t time_now = time(NULL); struct tm *lc; int sv = sl_getIndex(); int c1, c2; int *var; /* ZT 0,1対策 for DALK */ c1 = sl_getc(); c2 = sl_getc(); if (c1 == 0x41 && c2 == 0x7f) { reset_counter(0, 1, 0); return; } else { sl_jmpNear(sv); var = getCaliVariable(); } lc = localtime(&time_now); *var = 1900 + lc->tm_year; *(var + 1) = 1 + lc->tm_mon; *(var + 2) = lc->tm_mday; *(var + 3) = lc->tm_hour; *(var + 4) = lc->tm_min; *(var + 5) = lc->tm_sec; *(var + 6) = 1 + lc->tm_wday; TRACE("ZT0 %p:", var); } void commandZT1() { /* タイマーを n の数値でクリアする */ int n = getCaliValue(); reset_counter(0, 1, n); TRACE("ZT1 %d:", n); } void commandZT2() { /* タイマーを var に取得する 1/10 sec */ int *var = getCaliVariable(); int val = get_counter(0) / 100; *var = val & 0xffff; TRACE("ZT2 %p:", var); } void commandZT3() { /* タイマーを var に取得する 1/30 sec */ int *var = getCaliVariable(); int val = get_counter(0) * 3 / 100; *var = val & 0xffff; TRACE("ZT3 %p:", var); } void commandZT4() { /* タイマーを var に取得する 1/60 sec */ int *var = getCaliVariable(); int val = get_counter(0) * 3 / 50; *var = val & 0xffff; TRACE("ZT4 %p:", var); } void commandZT5() { /* タイマーを var に取得する */ int *var = getCaliVariable(); int val = get_counter(0) / 10; *var = val & 0xffff; TRACE("ZT5 %d:", val); } void commandZT10() { /* 高精度タイマー 設定 */ int num = getCaliValue(); int base = getCaliValue(); int count = getCaliValue(); if (num > 256) { WARNING("invalid timer id %d", num); } else if (num == 0) { for (int i = 1; i <= 256; i++) reset_counter(i, base, count); } else { reset_counter(num, base, count); } TRACE("ZT10 %d,%d,%d:", num, base, count); } void commandZT11() { /* 高精度タイマー取得 */ int num = getCaliValue(); int *var = getCaliVariable(); int divisor = counters[num].divisor ? counters[num].divisor : 1; if (num > 256) WARNING("invalid timer id %d", num); else *var = (get_counter(num) / divisor) & 0xffff; TRACE("ZT11 %d,%d:", num, *var); } void commandZT20() { /* ??? wait? */ int p1 = getCaliValue(); sysVar[0] = sys_keywait(p1, KEYWAIT_NONCANCELABLE); TRACE("ZT20 %d:",p1); } void commandZT21() { /* ??? wait? */ int p1 = getCaliValue(); sysVar[0] = sys_keywait(p1, KEYWAIT_CANCELABLE); TRACE("ZT21 %d:",p1); } void commandZZ0() { /* SYSTEM3.5を終了する */ int sw = getCaliValue(); TRACE("ZZ0 %d:",sw); if (sw == 0) { #ifdef __EMSCRIPTEN__ nact_quit(true); #else sys_exit(sysVar[0]); #endif } else if (sw == 1) { while (!nact->is_quit) sys_keywait(1000, 0); } } void commandZZ1() { /* 現在の動作機種コードを var に返す */ int *var = getCaliVariable(); #if 1 *var = 1; #else #if defined(linux) *var = 5; #elif defined(__FreeBSD__) *var = 6; #endif #endif TRACE("ZZ1 %p:",var); } void commandZZ2() { /* 機種文字列を文字列領域 num に返す(MAX12文字)*/ int num = getCaliValue(); #if defined(linux) static uint8_t str[] = {0x82, 0x6B, 0x82, 0x89, 0x82, 0x8E, 0x82, 0x95, 0x82, 0x98, 0}; #elif defined(__FreeBSD__) static uint8_t str[] = {0x82, 0x65, 0x82, 0x92, 0x82, 0x85, 0x82, 0x85, 0x82, 0x61, 0x82, 0x72, 0x82, 0x63, 0}; #elif defined(__OpenBSD__) static uint8_t str[] = {0x82, 0x6E, 0x82, 0x90, 0x82, 0x85, 0x82, 0x8E, 0x82, 0x61, 0x82, 0x72, 0x82, 0x63, 0}; #elif defined(__NetBSD__) static uint8_t str[] = {0x82, 0x6D, 0x82, 0x85, 0x82, 0x94, 0x82, 0x61, 0x82, 0x72, 0x82, 0x63, 0}; #elif defined(sun) static uint8_t str[] = {0x82, 0x72, 0x82, 0x95, 0x82, 0x8E, 0x82, 0x6E, 0x82, 0x72, 0}; #elif defined(__osf__) static uint8_t str[] = {0x82, 0x63, 0x82, 0x89, 0x82, 0x87, 0x82, 0x89, 0x82, 0x94, 0x82, 0x81, 0x82, 0x8C, 0x82, 0x74, 0x82, 0x6D, 0x82, 0x68, 0x82, 0x77, 0}; #elif defined(sgi) static uint8_t str[] = {0x82, 0x68, 0x82, 0x71, 0x82, 0x68, 0x82, 0x77, 0}; #else static uint8_t str[] = {0x82, 0x74, 0x82, 0x8e, 0x82, 0x8b, 0x82, 0x8e, 0x82, 0x8f, 0x82, 0x97, 0x82, 0x8e, 0}; #endif svar_set(num, str); TRACE("ZZ2 %d:",num); } void commandZZ3() { /* WINDOWSの全画面サイズや表示色数を変数列に返す */ int *var = getCaliVariable(); DispInfo info; ags_getWindowInfo(&info); *var = info.width; *(var + 1) = info.height; *(var + 2) = info.depth; TRACE("ZZ3 %p:",var); } void commandZZ4() { /* DIB の全画面 サイズや色数を変数列に返す */ int *var = getCaliVariable(); DispInfo info; ags_getDIBInfo(&info); *var = info.width; *(var + 1) = info.height; *(var + 2) = info.depth; TRACE("ZZ4 %p:",var); } void commandZZ5() { /* SYSTEM3.5用表示画面 の サイズや色数を変数列に返す */ int *var = getCaliVariable(); DispInfo info; ags_getViewAreaInfo(&info); *var = info.width; *(var + 1) = info.height; *(var + 2) = info.depth; TRACE("ZZ5 %p:",var); } void commandZZ7() { // セーブドライブの残りディスク容量を得る int *var = getCaliVariable(); *var = 65535; TRACE("ZZ7 %p:",var); } void commandZZ8() { // メモリオンバッファの残り容量を得る int *var = getCaliVariable(); TRACE_UNIMPLEMENTED("ZZ8 %p:",var); } void commandZZ9() { /* 起動時のスクリーンサイズを取得する */ int *var = getCaliVariable(); DispInfo info; ags_getWindowInfo(&info); *var = info.width; *(var + 1) = info.height; *(var + 2) = info.depth; TRACE("ZZ9 %p:",var); } void commandZZ10() { /* スクリーンモードを取得する */ int *var = getCaliVariable(); *var = gfx_isFullscreen() ? 1 : 0; TRACE("ZZ10 %d:",*var); } void commandZZ13() { /* 表示フォントを設定する */ int num = getCaliValue(); #ifdef __EMSCRIPTEN__ if (num == FONT_MINCHO) { if (!load_mincho_font()) num = FONT_GOTHIC; } #endif if (num < FONTTYPEMAX) nact->ags.font_type = num; TRACE("ZZ13 %d:",num); } void commandZZ14() { int no = getCaliValue(); char *s = "xsys35_user"; #ifdef HAVE_GETLOGIN char *lname=getlogin(); if (lname) s = lname; #endif if (no <= 0) return; svar_set(no, s); TRACE("ZZ14 %d:", no); } void commandZG() { /* CGのロードした回数をリンク番号毎に配列に書き込む配列を設定 */ int *var = getCaliVariable(); cg_loadCountVar = var; TRACE("ZG %p:",var); } void commandZI() { /* T2 */ /* Aコマンドのキー入力待ち時の各キーの動作の指定 */ int key = getCaliValue(); int mode = getCaliValue(); set_hak_keymode(key, mode); TRACE("ZI %d,%d:", key, mode); } void commandZA() { /* T2 */ /* 文字飾りの種類を指定する */ int p1 = sl_getc(); int p2 = getCaliValue(); switch(p1) { case 0: ags_setTextDecorationType(p2); break; case 1: ags_setTextDecorationColor(p2); break; case 2: case 3: nact->msg.AutoPageChange = p2 != 0; break; default: WARNING("Unknown ZA comannd %d, %d", p1, p2); } TRACE("ZA %d,%d:", p1, p2); } void commandZK() { // ディスクの入れ替えを促す int p1 = getCaliValue(); int p2 = getCaliValue(); const char *str = sl_getString(':'); TRACE("ZK %d,%d,%s:", p1, p2, str); } void commandZR() { /* 1 〜 num までの乱数を発生して変数に返す。 */ int num = getCaliValue(); int *var = getCaliVariable(); if (num == 0 || num == 1) { *var = num; } else { *var = (int)(genrand() * num) +1; } TRACE("ZR %d,%d:", num, *var); } void commandZU() { /* xsystem35 extension: sets unicode mode */ int sw = getCaliValue(); if (sw <= CHARACTER_ENCODING_MAX) sys_setCharacterEncoding(sw); TRACE("ZU %d:",sw); } void cmdz_reset(void) { memset(counters, 0, sizeof(counters)); }