?? bbx2.6.txt
字號:
我最近正好也做了個相關的,我把VB的程序給你參考下吧,希望對你有幫助,就是用VB的MSCOMM來控制的,注釋我都寫上了,你應該能看懂,根據你自己的需要改下就可以了,我調試過的,沒問題
MSCOMM1.COMMPORT1=1 '設置端口號為1
MSCOMM1.SETTINGS="19200,N,8,1" '設置波特率等通信協議
MSCOMM1.INPUTLEN=6 '設置一次從串口讀取6個字節
MSCOMM1.PORTOPEN=TRUE '打開串行口
MSCOMM1.INPUTMODE=COMINPUTMODEBINARY '從串行口讀取二進制數據
MSCOMM1.OUTPUT=SENDDAT '發送數據
DO UNTIL MSCOMM1.INBUFFERCOUNT>=6 '查詢方式,等待收到6個字節
DOEVENTS
LOOP
DATTEMP=MSCOMM1.INPUT '從串口讀取數據至變體變量
RCVDAT=DATTEMP '數據送至接收二進制數組
TXTRCV.TEXT=""
FOR I=0 TO 5 '接收數據送至接收文本框TXTRCV顯示
TXTRCV.TEXT=TXTRCV.TEXT&RIGHT("0"&HEX(RCVDAT(I)),2)
NEXT I
MSCOMM1.PORTOPEN=FALSE '關閉串行口
CMDCOMM.ENABLED=TRUE '使能CMDCOMM按鈕
END SUB
傳奇3的加解密核心就兩個函數,一個加密一個解密,這兩個函數在做封包分析的過程中起很重要的作用:
Function Decode(source: string): string;
Var
Source_Len,Len : integer;
Count,c1,c2 : integer;
code : array[0..7] of byte;
a1,a2 : byte;
ind : dword;
Decode_Str : string;
label L1,L2;
Begin
Result := '';
Decode_Str := '';
code[2] := ;
code[4] := ;
code[6] := ;
Len := 0;
a1 := 0;
a2 := 0;
c1 := 2;
c2 := 0;
ind := 0;
Count := 0;
Source_Len := Length(source);
while (Count < Source_Len) do
begin
if(ord(Source[Count+1]) - $3c) < 0 then
begin
Decode_Str := Decode_Str + Source[Count+1];
inc(Len);
inc(Count);
a1 := 0;
a2 := 0;
c1 := 2;
c2 := 0;
ind := 0;
Continue;
//break;
end;
a1 := ord(Source[Count+1]) - $3c;
if Len >= Source_Len then
begin
break;
end;
if (c2 + 6) < 8 then
begin
goto L2;
end;
ind := a1 and $3f;
ind := ind shr (6-c1);
Decode_Str := Decode_Str + chr(ind or a2);
Inc(Len);
c2 := 0;
if c1 >= 6 then
begin
c1 := 2;
goto L1;
end;
inc(c1,2);
L2 :a2 := a1 shl c1;
a2 := a2 and code[c1];
c2 := c2 + (8 - c1);
L1 :inc(count);
end;
SetLength(Decode_Str,Len);
Result := Decode_Str;
end;
function Encode(source: string): string;
var
Source_Len,Len : integer;
Count,c : integer;
a1,a2 : byte;
ind : dword;
Encode_Str : string;
begin
Result := '';
Encode_Str := '';
Len := 0;
a1 := 0;
a2 := 0;
c := 0;
ind := 0;
Count := 0;
Source_Len := Length(source);
while Count < Source_Len do
begin
if Len >= $2710 then
break;
ind := ord(source[Count+1]);
ind := ind shr (c+2);
a1 := ind or a2;
a1 := a1 and $3f;
ind := ord(source[Count+1]);
ind := ind shl (8-(c+2));
ind := ind shr 2;
a2 := ind and $3f;
inc(c,2);
if c >= 6 then
begin
if Len >= $270f then
begin
Encode_Str := Encode_Str + chr(a1 + $3c);
inc(Len);
end
else
begin
Encode_Str := Encode_Str + chr(a1 + $3c);
Encode_Str := Encode_Str + chr(a2 + $3c);
Inc(Len,2);
end;
c := 0;
a2 := 0;
end
else
begin
Encode_Str := Encode_Str + chr(a1 + $3c);
Inc(Len);
end;
inc(Count);
end;
if c > 0 then
begin
Encode_Str := Encode_Str + chr(a2 + $3c);
Inc(Len);
end;
SetLength(Encode_Str,Len);
Result := Encode_Str;
end;
新地圖的制做方法,還有些ACI的東西
半年多了還沒有人找出加新地圖的方法,我說說我以前用的方法,不過我當時自己寫的程序和ACI代碼被我當年一氣之下全刪了,所以也沒有什么現成的可以用的東西,只是憑記憶寫寫大概的過程
先把傳奇三的地圖提取出來,傳奇三MAP文件的格式應該很多人都知道,前幾個DW是字圖長和寬,后面全是一個單元一個單元的數據,每單元數據里第幾位不記的了是個能不能行走的標記。全提取出來,形成一個 ACI里叫BUFFER
大概是這么個意思
int x_len=**;
int y_len=**;
byte map_data=new byte[x_len * y_len+8]; //加8還是+4我記不太清了。DW加8 WORD 加4。自己找個解開看看就行了
map_data 前面的兩個DW還是W我記不太清了。多試試吧,好象是DW
還有一個重要的區別 ACI的地圖文件里的 高低位有些是反著的。可能是ACI天生帶來的,把一個DW填為10時,有時要寫 10 00 00 00 有時要寫成 00 00 00 10 ,這個自己多試試吧,相信很多人已經做到這一步了。 最關鍵的一步就是把這個 BUFFER 用ACI自己的壓縮方式壓縮一下,再寫到文件里,這樣的一個一個文件就是組成 mir3_map.fs 的部件。不是有人已經把這個文件給分解開來了么,看看分解后的一個個文件,那就是經過壓縮過的。 ACI里壓縮和解壓縮的函數是 compress() 和 decompress 函數原型我記不太清了,好象是 buffer compress(buffer) 自己多試試吧。
還有更簡單的方式 load_map(string mir3_map_file) 可以直接把傳奇三地圖文件提取到ACI里,用這個函數可以讓百寶箱直接使用傳奇三的地圖文件,我沒試過,剛寫的時候突然想到這個問題,有興趣的可以試一下
對應的函數 save_map() 這個函數把已經load_map()的地圖數據寫到硬盤里,是壓縮過的還是沒有壓縮過的我記不太清了
呵呵,說到這里,還有最后的一步,讀寫文件。這個我不知道有沒有人能實現 read_file() 讀二進制 read_file_ex() 讀文本文件和 write_file() . 函數原型參考ANSI C。實在不行自己猜也就猜出來的,當時我也是猜出來的。
要想讀寫文件,必須要有255的權限,用正常的ACI是不行的。要用到另一個函數,可以越過 權限直接運行最高權限的腳本,run_script_from_server( (buffer) string) 好象是這樣的,時間太久我也記不太清了
這樣一路下來,應該沒有什么問題了吧。至于加密的那些ZD文件,只不過是有一個文件頭,用二UE 打開一看就知道了。有特殊文件頭的。讀入后面的數據然后 decompress() 就得到文本文件了。沒有特殊文件頭的,就當做明文處理。
如果是自己研究摸索出來的,拿去賺錢無可厚非,如果是看了上面我寫的東西才搞出來的,那就不要拿去賣錢了,做好了拿出來共享一下吧。實在覺的虧,那就少少收一點吧。
就是這樣子了,沒啥好說的了,上面都說的很清楚了,有不明白的地方自己再研究吧,就不要再來問我了。
ACI是可以編譯的,不管你信不信。
BBX 采用的是 C/S 模式 看到的那個只是一個界面,不過是空殼罷了。界面的東西全在 gamebbx.dl 里 函數入口我記不太清了。自己找找就行了。能在內存里看到的那些明碼的ACI 全是 gamebbx.dll里帶的。
百寶箱運行時 先把 artifact.dll 載入內存 這就是虛擬機的內核。 artifact.dll 監聽兩個端口,一個是 等待gamebbx.dll連接的。一個是TELNET 端口。注意BBX3.0之前 TELNET端口是不自動打開的。要用函數才能打開,打開后 telnet ip port 就可以連接上了。TELNET 密碼是 什么我不記的了。是三個字母,好象可以在打開TELNET的時候設定密碼,具體我也記不太清了 函數可能是 telnet_on(int port , string tlnet_password) ? 我也記不太清了。 通過TELNET 界面不受權限255的限制。 還有一個函數可以打開一個控制臺 可惜太久我不記的了。同樣,BBX還提供了訪問系統注冊表的功能。還有一系列的WINDOWS下的函數 比如 msg_box 還有一個可以輸入的界面。BBX2.6下打開控制界面的是 宏 win 要求255權限 一樣,這個界面也不受權限影響。而且這是一個調試信息輸出的界面。ACI里 所有的調試信息都是輸出到這個界面的。
想起什么再來寫。
在BBX 2。6版本 artifact.dll中帶著兩個個文件,名字我忘記了。虛擬機一運行就執行這兩個個編譯過的ACI腳本,這兩個文件才是內核,平常所用到的函數也全在里面,用UE打開就能找到所有的函數名了。因為編譯過的ACI里函數名是不加密的。這兩個文件名可以在內存中找到。直接 read_file(file_name) 再write_file()就可以把這兩個文件保存下來了。
總的來說 BBX是個不錯的開發外掛的平臺,可惜就是沒有一個好的調試器,所以寫代碼容易,寫正確的代碼就難了。因為用的虛擬機,所以要想用調試的方法來破這個平臺,幾乎是不可能的。要想破,只能用ACI來破。
接口
那些什么on什么on什么的接口函數就不用說了,定時調用就是了。哈哈。ACI里也有C#的反射?可以判定變量和函數的類型等等。指針是不提供的,只可以傳址。不過應該有函數指針,我也不會用
線程同步
寫ACI如果搞不好線程同步,基本上是廢的。呵呵,沒記錯的話是用 create_event() 和 wait_event() 好象還有信號燈的函數 create_semphore()?
網絡庫
ACI里也有標準的SOCKET實現。 socket() listen() bind() receive() send() send_to()? 可以支持TCP 和UDP
有興趣可以用ACI來寫外掛,除了調試的因素。呵呵。
試試這樣能不能去掉試用版本的時間限制
http://bbs.bbx8.com/viewthread.php?tid=69105&extra=page%3D1 里提供的是我很久以前發的一個試用版本,因為很久不做了,所以源程序我手上也沒有,當時怎么寫的也是一點印象沒有了。用上提供的補丁以后,試著在ACI里加載
run_script_from_server(compress("delete_thread(\"tmain2\");"));
看能不能把時間限制去掉,行不行請跟貼說明一下
不過就是能去掉時間限制,這個種方法的免驗證版本也不是完美的,還是一樣會有停止練功的BUG,最好自己寫ACI修正一下。這個問題我是解決不了的。
發一個最簡單最穩定的持續凝血離魂+陰陽法環+ 破血狂殺aci
//適合掛變態號或者不能穩定使用的情況
//持續凝血離魂 陰陽法環 破血狂殺
void my_cast_thread();
void create_my_cast();
create_my_cast();
void my_cast_thread()
{
if(strsrch(get_status_desc(me()), "凝血離魂") < 0 && me()["magic"][get_magic_no("凝血離魂")] )
{
cast(me(),"凝血離魂");
}
if(strsrch(get_status_desc(me()), "陰陽法環") < 0 && me()["magic"][get_magic_no("陰陽法環")] )
{
cast(me(),"陰陽法環");
}
if(strsrch(get_status_desc(me()), "破血狂殺") < 0 && me()["magic"][get_magic_no("破血狂殺")] )
{
cast(me(),"破血狂殺");
}
}
void create_my_cast()
{
delete_thread("t_my_cast_thread");
create_thread("t_my_cast_thread","my_cast_thread");
delete_timer("tm_create_my_cast");
set_timer(4, "tm_create_my_cast", "create_my_cast");
}
void on_enter_world()
{
delete_timer("tm_create_my_cast");
set_timer(4, "tm_create_my_cast", "create_my_cast");
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -