/* ALICE SOFT SYSTEM 3 for Win32 [ NACT ] */ #include #include "nact.h" #include "ags.h" #include "mako.h" #include "dri.h" #include "../fileio.h" #include "crc32.h" extern SDL_Window* g_window; // 初期化 NACT::NACT(int sys_ver, uint32 crc32, const char* font_file, const char* playlist) : sys_ver(sys_ver), crc32(crc32) { // デバッグコンソール起動 initialize_console(); // AG00.DAT読み込み FILEIO* fio = new FILEIO(); if(fio->Fopen("AG00.DAT", FILEIO_READ_BINARY)) { int d0, d1, d2, d3; char string[MAX_CAPTION]; fio->Fgets(string); sscanf_s(string, "%d,%d,%d,%d", &d0, &d1, &d2, &d3); for(int i = 0; i < d1; i++) { // 動詞の読み込み fio->Fgets(string); memcpy(caption_verb[i], string, sizeof(string)); } for(int i = 0; i < d2; i++) { // 目的語の読み込み fio->Fgets(string); memcpy(caption_obj[i], string, sizeof(string)); } fio->Fclose(); } delete fio; // ADISK.DAT #if defined(_PROG_OMAKE) strcpy_s(adisk, 16, "AGAME.DAT"); #else strcpy_s(adisk, 16, "ADISK.DAT"); #endif // シナリオ管理 scenario_data = NULL; load_scenario(0); scenario_page = 0; scenario_addr = 2; label_depth = page_depth = 0; // 変数初期化 memset(var, 0, sizeof(var)); memset(var_stack, 0, sizeof(var_stack)); memset(tvar, 0, sizeof(tvar)); memset(tvar_stack, 0, sizeof(tvar_stack)); // コマンド初期化 column = true; // 座標モード wait_keydown = true; // ウェイト時のキー受付 seed = SDL_GetTicks(); // 乱数の種 text_wait_time = 100; // メッセージ表示のウェイト text_wait_enb = false; text_skip_enb = false; mouse_sence = 16; // マウス移動感知 menu_window = text_window = 1; menu_index = 0; show_push = true; clear_text = true; verb_obj = false; set_palette = false; tvar_index = 0; pcm_index = 0; memset(pcm, 0, sizeof(pcm)); if (sys_ver == 1) { // SYETEM1 初期化 menu_max = 6; switch (crc32) { case CRC32_DPS: text_refresh = false; strcpy_s(tvar[0], 22, "カスタム"); strcpy_s(tvar[1], 22, "リーナス"); strcpy_s(tvar[2], 22, "かつみ"); strcpy_s(tvar[3], 22, "由美子"); strcpy_s(tvar[4], 22, "いつみ"); strcpy_s(tvar[5], 22, "ひとみ"); strcpy_s(tvar[6], 22, "真理子"); break; case CRC32_INTRUDER: menu_max = 11; paint_x = paint_y = map_page = 0; break; } } // 各種クラス生成 ags = new AGS(this, font_file); mako = new MAKO(this, playlist); #ifdef USE_JOY // 入力初期化 joy_num = joyGetNumDevs(); if(joy_num) { joyGetDevCaps(JOYSTICKID1, &joycaps, sizeof(JOYCAPS)); } #endif terminate = false; } NACT::~NACT() { // 各種クラス開放 if(ags) { delete ags; } if(mako) { delete mako; } // シナリオ開放 if(scenario_data) { free(scenario_data); } // デバッグコンソール開放 release_console(); } void NACT::mainloop() { int sleep_cnt = 0; while(!terminate) { execute(); // 512コマンド実行毎にSleep(10) if(!(sleep_cnt = (sleep_cnt + 1) & 0x1ff)) { SDL_Delay(10); } } } // コマンドパーサ void NACT::execute() { // アドレスの確認 if(scenario_addr < 2 || scenario_addr >= scenario_size) { fatal("Scenario error"); } // 致命的なエラー発生 or 正常終了 if(fatal_error) { if(!post_quit) { terminate = true; } post_quit = true; return; } if(sys_ver == 1 && scenario_page == 0 && scenario_addr == 2) { opening(); } // 1コマンド実行 uint8 cmd = getd(); if(set_palette && cmd != 'P') { // パレット設定が終わった ags->flush_screen(true); set_palette = false; } if(verb_obj && cmd != '[' && cmd != ':') { // 動詞-目的語メニューの表示 scenario_addr--; cmd_open_verb(); return; } switch(cmd) { case '!': cmd_calc(); break; case '{': cmd_branch(); break; case '}': break; case '@': cmd_label_jump(); break; case '\\': cmd_label_call(); break; case '&': cmd_page_jump(); break; case '%': cmd_page_call(); break; case '$': cmd_set_menu(); break; case '[': cmd_set_verbobj(); break; case ':': cmd_set_verbobj2(); break; case ']': cmd_open_menu(); break; case 'A': cmd_a(); break; case 'B': cmd_b(); break; case 'D': cmd_d(); break; case 'E': cmd_e(); break; case 'F': cmd_f(); break; case 'G': cmd_g(); break; case 'H': cmd_h(); break; case 'I': cmd_i(); break; case 'J': cmd_j(); break; case 'K': cmd_k(); break; case 'L': cmd_l(); break; case 'M': cmd_m(); break; case 'N': cmd_n(); break; case 'O': cmd_o(); break; case 'P': cmd_p(); break; case 'Q': cmd_q(); break; case 'R': cmd_r(); break; case 'S': cmd_s(); break; case 'T': cmd_t(); break; case 'U': cmd_u(); break; case 'V': cmd_v(); break; case 'W': cmd_w(); break; case 'X': cmd_x(); break; case 'Y': cmd_y(); break; case 'Z': cmd_z(); break; default: if(cmd == 0x20 || (0xa1 <= cmd && cmd <= 0xdd)) { // message (1 byte) char string[2]; string[0] = cmd; string[1] = '\0'; ags->draw_text(string); if(crc32 == CRC32_DPS && !ags->draw_menu) { text_refresh = false; } if(!ags->draw_menu && text_wait_enb && cmd != 0x20) { Uint32 dwTime = SDL_GetTicks() + text_wait_time; for(;;) { if(terminate) { return; } RND = get_key(); if(RND && wait_keydown) { break; } if(dwTime <= SDL_GetTicks()) { break; } SDL_Delay(16); } } #if defined(_DEBUG_CONSOLE) output_console(string); #endif } else if((0x81 <= cmd && cmd <= 0x9f) || 0xe0 <= cmd) { // message (2 bytes) char string[3]; string[0] = cmd; string[1] = getd(); string[2] = '\0'; ags->draw_text(string); if(crc32 == CRC32_DPS && !ags->draw_menu) { text_refresh = false; } if(!ags->draw_menu && text_wait_enb) { Uint32 dwTime = SDL_GetTicks() + text_wait_time; for(;;) { if(terminate) { return; } RND = get_key(); if(RND && wait_keydown) { break; } if(dwTime <= SDL_GetTicks()) { break; } SDL_Delay(16); } } #if defined(_DEBUG_CONSOLE) output_console(string); #endif } else { fatal("Unknown command %2x at %d", cmd, scenario_addr); } break; } } void NACT::load_scenario(int page) { if(scenario_data) { free(scenario_data); } DRI* dri = new DRI(); if((scenario_data = dri->load(adisk, page + 1, &scenario_size)) == NULL) { fatal("Cannot load scenario %d", page); } delete dri; } // 下位関数 uint16 NACT::random(uint16 range) { // xorhift32 seed = seed ^ (seed << 13); seed = seed ^ (seed >> 17); seed = seed ^ (seed << 15); return (uint16)(((uint32)range * (seed & 0xffff)) >> 16) + 1; } // WinMainとのインターフェース int NACT::get_screen_height() { return ags->screen_height; } void NACT::select_cursor() { ags->select_cursor(); } void NACT::select_sound(int dev) { // 強制的に音源を変更する int page = mako->current_music; int old_dev = (1 <= page && page <= 99 && mako->cd_track[page]) ? 1 : 0; for(int i = 1; i <= 99; i++) { mako->cd_track[i] = dev ? i : 0; } // デバイスが変更された場合は再演奏する if(dev != old_dev && page) { mako->stop_music(); mako->play_music(page); } } void NACT::fatal(const char* format, ...) { char buf[512]; va_list args; va_start(args, format); vsnprintf(buf, sizeof buf, format, args); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "system3", buf, g_window); fatal_error = true; } NACT* NACT::create(const char* game_id, const char* font_file, const char* playlist) { uint32 crc32 = NACT::calc_crc32(game_id); int sys_ver = NACT::get_sys_ver(crc32); switch (sys_ver) { case 1: return new NACT_Sys1(crc32, font_file, playlist); case 2: return new NACT_Sys2(crc32, font_file, playlist); default: return new NACT_Sys3(crc32, font_file, playlist); } }