/* --------------------------------------- 绘制文字 (实体/透明) --------------------------------------- */ static bool_t qst_crh_text ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { sRECT rect; bool_t rett; bool_t tran; ansi_t* temp; ansi_t* text; sIMAGE* draw; uint_t ww,hh; uint_t align; /* 参数解析 <X> <Y> <EscText> [Width Height Align] */ if (argc < 4) return (FALSE); if (s_font == NULL) return (FALSE); draw = ((sQstView2D*)parm)->paint; if (draw == NULL) return (FALSE); /* 必须使用转义字符串 */ temp = str_fmtA("\"%s\"", argv[3]); if (temp == NULL) return (FALSE); text = str_esc_dupU(temp); mem_free(temp); if (text == NULL) return (FALSE); /* 区分实体和透明, 两个命令合并起来了 */ if (str_cmpA(argv[0], "crh:texts") == 0) tran = FALSE; else tran = TRUE; rect.x1 = (sint_t)str2intxA(argv[1]); rect.y1 = (sint_t)str2intxA(argv[2]); if (argc > 6) { ww = str2intxA(argv[4]); hh = str2intxA(argv[5]); align = str2intxA(argv[6]); rect_set_wh(&rect, rect.x1, rect.y1, ww, hh); } else { align = 0; } rett = qst_crh_text_int(draw, tran, &rect, text, align); mem_free(text); return (rett); }
/* ======================================= 转义字符串发送 ======================================= */ CR_API void_t* qst_esc_tran ( __CR_IN__ const ansi_t* string, __CR_OT__ uint_t* ot_size ) { leng_t len; ansi_t* dat; ansi_t* str; str = str_fmtA("\"%s\"", string); if (str == NULL) return (NULL); dat = str_esc_dupU(str, &len); mem_free(str); *ot_size = len; return (dat); }
/* ======================================= 更新窗口标题 ======================================= */ CR_API void_t qst_update_title ( __CR_IN__ const sQstComm* parm ) { ansi_t* wntt; const ansi_t* type; if (parm->comm.title == NULL) type = ""; else type = parm->comm.title; wntt = str_fmtA(WIN_TITLE "%s {s:%s, r:%s}", type, parm->comm.stype, parm->comm.rtype); if (wntt != NULL) { SetWindowTextA(parm->hwnd, wntt); mem_free(wntt); } }
/* --------------------------------------- 打开 UDPv4 通讯接口 --------------------------------------- */ static bool_t qst_com_udpv4 ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { uint_t port; socket_t netw; /* 参数解析 <目标地址> <端口号> */ if (argc < 3) return (FALSE); port = str2intxA(argv[2]); if (port > 65535) return (FALSE); sQstComm* ctx = (sQstComm*)parm; /* 关闭当前接口并打开 UDPv4 连接 */ netw = client_udp_open(argv[1], (int16u)port); if (netw == NULL) return (FALSE); socket_set_timeout(netw, QCOM_SNDTOUT, QCOM_CUTDOWN); /* 设置工作参数 */ qst_com_close(parm, argc, argv); ctx->comm.obj.netw = netw; ctx->comm.send = qst_udpv4_send; /* 启动接收线程 */ ctx->comm.thrd = thread_new(0, qst_udpv4_main, parm, FALSE); if (ctx->comm.thrd == NULL) { socket_close(netw); return (FALSE); } TRY_FREE(ctx->comm.title); ctx->comm.title = str_fmtA(" - UDPv4 \"%s\", %u", argv[1], port); qst_update_title(ctx); return (TRUE); }
/* --------------------------------------- 设置通讯接收模式 --------------------------------------- */ static bool_t qst_com_rtype ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { static ansi_t* name = NULL; /* 参数解析 <接收模式/插件名称> [函数名称] */ if (argc < 2) return (FALSE); sQstComm* ctx = (sQstComm*)parm; CTextOper* opr = (CTextOper*)ctx->oper; _ENTER_COM_SINGLE_ if (str_cmpA(argv[1], "text") == 0) { ctx->comm.text = TRUE; ctx->comm.render = qst_txt_show; ctx->comm.rtype = "text"; } else if (str_cmpA(argv[1], "html") == 0) { ctx->comm.text = TRUE; ctx->comm.render = qst_htm_show; ctx->comm.rtype = "html"; } else if (str_cmpA(argv[1], "hex") == 0) { ctx->comm.text = FALSE; ctx->comm.render = qst_hex_show; ctx->comm.rtype = "hex"; } else if (str_cmpA(argv[1], "ansi") == 0) { qst_csi_clear(); ctx->comm.text = TRUE; ctx->comm.render = qst_csi_show; ctx->comm.rtype = "ansi"; } else { sbin_t sbin; plugin_render_t func; /* 使用外部插件 */ if (argc < 3) goto _failure; sbin = sbin_loadA(argv[1]); if (sbin == NULL) goto _failure; func = sbin_exportT(sbin, argv[2], plugin_render_t); if (func == NULL) { sbin_unload(sbin); goto _failure; } ctx->comm.text = FALSE; ctx->comm.render = func; TRY_FREE(name); name = str_fmtA("%s|%s", argv[1], argv[2]); ctx->comm.rtype = (name == NULL) ? "null" : name; } opr->clear(); _LEAVE_COM_SINGLE_ qst_update_title(ctx); return (TRUE); _failure: _LEAVE_COM_SINGLE_ return (FALSE); }
/* --------------------------------------- 设置通讯发送模式 --------------------------------------- */ static bool_t qst_com_stype ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { static ansi_t* name = NULL; /* 参数解析 <发送模式/插件名称> [函数名称] */ if (argc < 2) return (FALSE); sQstComm* ctx = (sQstComm*)parm; if (str_cmpA(argv[1], "text") == 0) { ctx->comm.tran = NULL; ctx->comm.stype = "text"; } else if (str_cmpA(argv[1], "hex") == 0) { ctx->comm.tran = qst_hex_tran; ctx->comm.stype = "hex"; } else if (str_cmpA(argv[1], "esc") == 0) { ctx->comm.tran = qst_esc_tran; ctx->comm.stype = "esc"; } else if (str_cmpA(argv[1], "dos") == 0) { ctx->comm.tran = qst_dos_tran; ctx->comm.stype = "dos"; } else if (str_cmpA(argv[1], "unix") == 0) { ctx->comm.tran = qst_unx_tran; ctx->comm.stype = "unix"; } else if (str_cmpA(argv[1], "mac") == 0) { ctx->comm.tran = qst_mac_tran; ctx->comm.stype = "mac"; } else { sbin_t sbin; plugin_tran_t func; /* 使用外部插件 */ if (argc < 3) return (FALSE); sbin = sbin_loadA(argv[1]); if (sbin == NULL) return (FALSE); func = sbin_exportT(sbin, argv[2], plugin_tran_t); if (func == NULL) { sbin_unload(sbin); return (FALSE); } ctx->comm.tran = func; TRY_FREE(name); name = str_fmtA("%s|%s", argv[1], argv[2]); ctx->comm.stype = (name == NULL) ? "null" : name; } qst_update_title(ctx); return (TRUE); }
/* --------------------------------------- 打开 RS232 通讯接口 --------------------------------------- */ static bool_t qst_com_rs232 ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { int32u baud; uint_t port, bits; uint_t stop, parity; /* --------------- */ const ansi_t* sstop; const ansi_t* sparity; /* 参数解析 <串口号> [波特率] [数据位] [校验位] [停止位] */ if (argc < 2) return (FALSE); bits = 8; baud = 115200UL; stop = CR_SIO_STOP10; parity = CR_SIO_NOP; sstop = "1"; sparity = "no"; port = str2intxA(argv[1]); if (argc > 2) { baud = str2intx32A(argv[2]); if (argc > 3) { bits = str2intxA(argv[3]); if (argc > 4) { sparity = argv[4]; if (str_cmpA(argv[4], "no") == 0) parity = CR_SIO_NOP; else if (str_cmpA(argv[4], "odd") == 0) parity = CR_SIO_ODD; else if (str_cmpA(argv[4], "even") == 0) parity = CR_SIO_EVEN; else if (str_cmpA(argv[4], "mark") == 0) parity = CR_SIO_MARK; else if (str_cmpA(argv[4], "space") == 0) parity = CR_SIO_SPCE; else sparity = "no"; if (argc > 5) { sstop = argv[5]; if (str_cmpA(argv[5], "1") == 0) stop = CR_SIO_STOP10; else if (str_cmpA(argv[5], "1.5") == 0) stop = CR_SIO_STOP15; else if (str_cmpA(argv[5], "2") == 0) stop = CR_SIO_STOP20; else sstop = "1"; } } } } sQstComm* ctx = (sQstComm*)parm; /* 关闭当前接口并打开串口 */ if (!sio_open(port)) return (FALSE); sio_setup(port, baud, bits, parity, stop); sio_set_buffer(port, 1024, 1024); sio_set_rd_timeout(port, 0, 0, QCOM_CUTDOWN); sio_set_wr_timeout(port, 0, QCOM_SNDTOUT); sio_clear_error(port); sio_flush(port, CR_SIO_FLU_RT); /* 设置工作参数 */ qst_com_close(parm, argc, argv); ctx->comm.obj.port = port; ctx->comm.send = qst_rs232_send; /* 启动接收线程 */ ctx->comm.thrd = thread_new(0, qst_rs232_main, parm, FALSE); if (ctx->comm.thrd == NULL) { sio_close(port); return (FALSE); } TRY_FREE(ctx->comm.title); ctx->comm.title = str_fmtA(" - COM%u, %u, %u, %s, %s", port, baud, bits, sparity, sstop); qst_update_title(ctx); return (TRUE); }
/* --------------------------------------- FMODEx 类型信息 --------------------------------------- */ static bool_t fmodex_info ( __CR_IO__ iXMM_FMOD* port ) { sint_t bits; sint_t chns; ansi_t* allx; const ansi_t* type; const ansi_t* fmts; FMOD_RESULT result; FMOD_SOUND_TYPE snd_type; FMOD_SOUND_FORMAT snd_fmts; /* 获取所有信息 */ result = FMOD_Sound_GetFormat(port->m_snd, &snd_type, &snd_fmts, &chns, &bits); if (result != FMOD_OK) return (FALSE); /* 音频格式类型 */ switch (snd_type) { default: type = "3rd party / unknown plugin format"; break; case FMOD_SOUND_TYPE_AIFF: type = "AIFF"; break; case FMOD_SOUND_TYPE_ASF: type = "Microsoft Advanced Systems Format (ie WMA/ASF/WMV)"; break; case FMOD_SOUND_TYPE_AT3: type = "Sony ATRAC 3 format"; break; case FMOD_SOUND_TYPE_CDDA: type = "Digital CD audio"; break; case FMOD_SOUND_TYPE_DLS: type = "Sound font / downloadable sound bank"; break; case FMOD_SOUND_TYPE_FLAC: type = "FLAC lossless codec"; break; case FMOD_SOUND_TYPE_FSB: type = "FMOD Sample Bank"; break; case FMOD_SOUND_TYPE_GCADPCM: type = "Nintendo GameCube/Wii ADPCM"; break; case FMOD_SOUND_TYPE_IT: type = "Impulse Tracker"; break; case FMOD_SOUND_TYPE_MIDI: type = "MIDI"; break; case FMOD_SOUND_TYPE_MOD: type = "Protracker / Fasttracker MOD"; break; case FMOD_SOUND_TYPE_MPEG: type = "MP2/MP3 MPEG"; break; case FMOD_SOUND_TYPE_OGGVORBIS: type = "Ogg vorbis"; break; case FMOD_SOUND_TYPE_PLAYLIST: type = "Information only from ASX/PLS/M3U/WAX playlists"; break; case FMOD_SOUND_TYPE_RAW: type = "Raw PCM data"; break; case FMOD_SOUND_TYPE_S3M: type = "ScreamTracker 3"; break; case FMOD_SOUND_TYPE_SF2: type = "Sound font 2 format"; break; case FMOD_SOUND_TYPE_USER: type = "User created sound"; break; case FMOD_SOUND_TYPE_WAV: type = "Microsoft WAV"; break; case FMOD_SOUND_TYPE_XM: type = "FastTracker 2 XM"; break; case FMOD_SOUND_TYPE_XMA: type = "Xbox360 XMA"; break; case FMOD_SOUND_TYPE_VAG: type = "PlayStation Portable ADPCM VAG format"; break; case FMOD_SOUND_TYPE_AUDIOQUEUE: type = "iPhone hardware decoder, supports AAC, ALAC and MP3"; break; case FMOD_SOUND_TYPE_XWMA: type = "Xbox360 XWMA"; break; case FMOD_SOUND_TYPE_BCWAV: type = "3DS BCWAV container format for DSP ADPCM and PCM"; break; case FMOD_SOUND_TYPE_AT9: type = "NGP ATRAC 9 format"; break; case FMOD_SOUND_TYPE_VORBIS: type = "Raw vorbis"; break; case FMOD_SOUND_TYPE_MEDIA_FOUNDATION: type = "Microsoft Media Foundation wrappers, supports ASF/WMA"; break; } /* 音频数据类型 */ switch (snd_fmts) { default: fmts = "Unitialized / unknown"; break; case FMOD_SOUND_FORMAT_PCM8: fmts = "8bit integer PCM data"; break; case FMOD_SOUND_FORMAT_PCM16: fmts = "16bit integer PCM data"; break; case FMOD_SOUND_FORMAT_PCM24: fmts = "24bit integer PCM data"; break; case FMOD_SOUND_FORMAT_PCM32: fmts = "32bit integer PCM data"; break; case FMOD_SOUND_FORMAT_PCMFLOAT: fmts = "32bit floating point PCM data"; break; case FMOD_SOUND_FORMAT_GCADPCM: fmts = "Compressed Nintendo 3DS/Wii DSP data"; break; case FMOD_SOUND_FORMAT_IMAADPCM: fmts = "Compressed IMA ADPCM data"; break; case FMOD_SOUND_FORMAT_VAG: fmts = "Compressed PlayStation Portable ADPCM data"; break; case FMOD_SOUND_FORMAT_HEVAG: fmts = "Compressed PSVita ADPCM data"; break; case FMOD_SOUND_FORMAT_XMA: fmts = "Compressed Xbox360 XMA data"; break; case FMOD_SOUND_FORMAT_MPEG: fmts = "Compressed MPEG layer 2 or 3 data"; break; case FMOD_SOUND_FORMAT_CELT: fmts = "Compressed CELT data"; break; case FMOD_SOUND_FORMAT_AT9: fmts = "Compressed PSVita ATRAC9 data"; break; case FMOD_SOUND_FORMAT_XWMA: fmts = "Compressed Xbox360 xWMA data"; break; case FMOD_SOUND_FORMAT_VORBIS: fmts = "Compressed Vorbis data"; break; } /* 合成说明字符串 */ allx = str_fmtA("%s (%s) - %uch / %ubits", type, fmts, chns, bits); if (allx == NULL) return (FALSE); str_cpyA(port->m_inf, allx); mem_free(allx); return (TRUE); }
/* --------------------------------------- 绘制文字 (使用外部定义) --------------------------------------- */ static bool_t qst_crh_text_ex ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { sRECT* rect; bool_t free; bool_t rett; bool_t tran; uint_t algn; ansi_t* temp; ansi_t* text; sIMAGE* draw; /* 参数解析 <EscText/TextName> <RectName> <Align> [IsTextName] */ if (argc < 4) return (FALSE); if (s_font == NULL) return (FALSE); if (s_resx == NULL) return (FALSE); draw = ((sQstView2D*)parm)->paint; if (draw == NULL) return (FALSE); /* 查找目标矩形对象 */ rect = egui_res_get_rct(s_resx, argv[2]); if (rect == NULL) return (FALSE); /* 找不到或不使用文本名称的时候使用转义字符串 */ if (argc > 4) text = egui_res_get_txt(s_resx, argv[1]); else text = NULL; if (text == NULL) { temp = str_fmtA("\"%s\"", argv[1]); if (temp == NULL) return (FALSE); text = str_esc_dupU(temp); mem_free(temp); if (text == NULL) return (FALSE); free = TRUE; } else { free = FALSE; } /* 区分实体和透明, 两个命令合并起来了 */ if (str_cmpA(argv[0], "crh:texts_ex") == 0) tran = FALSE; else tran = TRUE; algn = str2intxA(argv[3]); rett = qst_crh_text_int(draw, tran, rect, text, algn); if (free) mem_free(text); return (rett); }
/* ======================================= WinMain 程序入口 ======================================= */ int WINAPI WinMain ( __CR_IN__ HINSTANCE curt_app, __CR_IN__ HINSTANCE prev_app, __CR_IN__ LPSTR cmd_line, __CR_IN__ int cmd_show ) { uint_t argc; ansi_t** argv; CR_NOUSE(curt_app); CR_NOUSE(prev_app); CR_NOUSE(cmd_show); /* 建立 CrHack 系统 */ if (!set_app_type(CR_APP_GUI)) return (QST_ERROR); /* 获取命令行参数, 不包括进程文件名 */ argv = misc_get_param(cmd_line, &argc); /* 参数解析 <脚本文件> */ if (argc < 1) return (QST_ERROR); leng_t size; ansi_t* root; ansi_t* temp; ansi_t* exec; ansi_t path[MAX_PATHA]; /* 合成 LUA_PATH & LUA_CPATH 目录 */ exec = file_load_as_strA(QST_ROOT_START); if (exec == NULL) { size = GetCurrentDirectoryA(sizeof(path), path); if (size == 0 || size > sizeof(path)) return (QST_ERROR); if (path[size - 1] == '\\') path[size - 1] = 0x00; exec = str_dupA(path); if (exec == NULL) return (QST_ERROR); } temp = str_dupA(exec); if (temp == NULL) { mem_free(exec); return (QST_ERROR); } root = str_fmtA("%s\\lualib", exec); mem_free(exec); if (root == NULL) { mem_free(temp); return (QST_ERROR); } DWORD cf = 0; /* 根据扩展名选择用哪个启动 */ if (filext_checkA(argv[0], ".lua")) { exec = str_fmtA("%s\\lua.exe \"%s\"", temp, argv[0]); cf = CREATE_NEW_CONSOLE; } else if (filext_checkA(argv[0], ".wlua")) { exec = str_fmtA("%s\\wlua.exe \"%s\"", temp, argv[0]); cf = CREATE_NO_WINDOW; } else { exec = NULL; } mem_free(temp); if (exec == NULL) { mem_free(root); return (QST_ERROR); } STARTUPINFOA si; PROCESS_INFORMATION pi; /* 启动脚本 */ mem_zero(&si, sizeof(si)); si.cb = sizeof(STARTUPINFOA); SetEnvironmentVariableA("LUA_PATH", root); SetEnvironmentVariableA("LUA_CPATH", root); size = str_lenA(root); size -= str_lenA("\\lualib"); root[size] = 0x00; if (CreateProcessA(NULL, exec, NULL, NULL, FALSE, cf, NULL, root, &si, &pi)) { WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } mem_free(exec); mem_free(root); return (QST_OKAY); }