Jump to content


  • Content count

  • Joined

  • Last visited

  • Days Won

  • Feedback


MasterToma last won the day on October 14 2017

MasterToma had the most liked content!

Community Reputation

10 Good


About MasterToma

  • Rank

Profile Information

  • Current Mood
  • Gender
    Not Telling
  • Country

Recent Profile Visitors

497 profile views
  1. I would like to request minor (is it?) improvement. There are a lot of cases, where strings are present inside decompiled NAS file. E.g. TelPosList Position = { {"古鲁丁城镇"; -80749; 149834; -3043; 18000; 0} }; But actually, there should be ID from fstring.txt file. Originally, NAS Lexer translates ID from fstring.txt for TelPosList, and Code-Generator inserts string in ai.obj So, this should be like this TelPosList Position = { {1000003; -80749; 149834; -3043; 18000; 0} }; It allowed NCSoft to do script language-agnostic. Similar for AddChoise, but case is more complicated there, since it requires QuestDataChecker.exe
  2. Great! 1. I've decompiled C1 ai.obj from leaked CHN server using @verbrannt's decompiler (branch c1-support) 2. Compiled back ai.nasc without any changes, using my C1 AI compiler 3. Splited compiled AI classes from original ai.obj and recompiled ai_decompiled.obj in separate files 4. Compared 2 directories (with ignore L\d* and fetch_i\s*//\s*(npc_)class_id Here is result https://ibb.co/jSNsBy Original obj code 1. extra jump is present in 10 files. This jump jumps to next line, so it's completely useless. Don't know, why compiler generates it 2. empty parameters in 4 classes (selected ones on picture) are present in original obj and missed after recompilation. This also could be ignored class party_leader_ag_casting_curse : party_leader_casting_curse parameter_define_begin parameter_define_end ... So, I could say, it's first decompiler for ai.obj, which works (I mean it) at least for C1. But in general, code syntax wasn't changed much in NAS language (I've checked compiler from C4 - only diagnostics were improved and few minor generator changes, but lexer/parser are the same).
  3. Some of them are not crucial (like empty parameters), some - might be, deeper check is needed. But there is not "only jump" :)
  4. Const pushing looks like in wrong place (tor) tutorial_quest_npc original: push_const 4194304 push_const 2097152 bit_or push_const 8388608 bit_or not bit_and assign recompiled push_const 4194304 not bit_and push_const 2097152 bit_or push_const 8388608 bit_or assign
  5. I think there is no point to be so pathetic. I'm trying to help you to complete this big work finally, since you've made it public, and probably you want it to be as much usable as it could be. Have to remove your smile mod, since it's done for all cases, instead of doing it properly, where it's needed. But let's skip it finally. I don't know which diff you are using, and don't want to know, but it's obvious that this diff is not right. Ors are missed in about 20 classes (corpse_of_kurtz 1 of them) More complicated case fairy_mymyu Empty parameers here and in quest_0503_imperial_gravekeeper , rodd class party_leader_ag_casting_curse : party_leader_casting_curse parameter_define_begin parameter_define_end
  6. Well I think it's not so hard to do proper (), if this info present in ai.obj. But I understand your sarcasm. Why should I replace labels If I ignore them during diff? I have 35 files with differences (labels are ignored, and few more filters are ignored), but you don't want to hear :) And it's not "only jump" Okay I will fix it manually, not a big deal. Tnx for your work, this decompiler at least somehow usefull
  7. Looks like we lost and talking about different things. I really understand, that if there are only &&, no point in extra bracers... belive me, because I've decompiled most of L2, and it works (including NASC itself). But this info about extra scope () is present in ai.obj. I posted examples, where you can see the difference. I posted the difference in pastebin. NASC generates DIFFERENT code for (a && (b && c)) and for (a && b && c). But decompiler restores them in SAME way - no bracers. I don't know how to be more clear. I have two concerns about it. First - messed diff. I can't compare original and recompiled objs due to much more trash. Second - there is might be some weird context, which might lead to bug. OK, never-mind, you did great job anyway. I have at least two more bugs apart this: 1. some jump is just missed. Have no idea, but in original class's obj there is just 1 more jump instruction. I can't say nothing concrete, because diff produces too much mismatches due to my previous point. Could you just add those bracers? Or point me the function and I'll fix it by my own maybe :) 2. in some classes (e.g. pet_manager_martin) push_event // i5 push_const 212 add instead of push_reg_sp fetch_i
  8. I sent you ai.obj from C1. Being decompiled (bracers are missed) and compiled back, ai.obj with mixed and/or is produced. I pasted in my recent posts. I have about 35 classes with such case. You can check drunkard_treaf for instance
  9. I've compiled your code with C1 NASC. Left - no bracers, right - with bracers.
  10. I think, I've provided it in recent post. Both, script code and 2 obj. results (links to pastebin)
  11. Okay then... so as I told, nested bracers change resulted ai.obj Try this one (output https://pastebin.com/6Su1S470) EventHandler TALK_SELECTED(talker) { if ( HaveMemo(talker, @trial_of_scholar)==1 && OwnItemCount(talker, @dieters_diary) >= 1 || OwnItemCount(talker, @scripture_chapter_1) >= 1 || OwnItemCount(talker, @strong_liquor) >= 1) { AddChoice(0,"Mention what Raut said"); } } and with additional bracers EventHandler TALK_SELECTED(talker) { if ( HaveMemo(talker, @trial_of_scholar)==1 && (OwnItemCount(talker, @dieters_diary) >= 1 || OwnItemCount(talker, @scripture_chapter_1) >= 1 || OwnItemCount(talker, @strong_liquor) >= 1)) { AddChoice(0,"Mention what Raut said"); } } https://pastebin.com/JL3sWgyz (output) Scroll to the end in pastebin, to see the difference The same in complex cases with + and * Take into account, that NASC is actually simple stream translator, so it doesn't have (almost) context like AST. It translates line by line (with special handling of loops and if/else)
  12. I never used shitty NASC decompilers :D No, Scripts from C0 were leaked. Real one with comments, etc. You should know it. Okay, I will find good example, where OBJ code differs. Or if you don't want to hear about bugs, just say it clearly ;) I'm comparing two obj's with diff, so code differs... And Im trying to find good example, like with modulo
  13. I understand it. But some of cases might like like with modulo. I wouldn't noticed difference in if (a && c || d) if NASC would generated same code. Could you please also add bracers for all nested expressions? According to leaked code, all nested expressions have (). I'm not sure about such thing as precedence in script-engine, I could show you their VM code, where arguments only taken from stack in such and order in which compiler pasted them. And NASC pasted them in opposite order :) (as I wrote in recent post)
  14. I've noticed the same with nested &&. Original pseudo-code if (a && (c && d)) after decompilation will be if (a && c && d) Which is OK. But some times not: if (a && (c || d)) goes into if (a && c || d) Trying to find some nice example...
  15. Ok, now it works. Another bug with operator precedence. For instance, look at blacksmith_duning (code is too large). Here is how it should look like: fetch_i push_const 10 mod mul greater_equal else if(reply == 6) { if (OwnItemCount(talker, @q_gold_wyvern) >= (4*(talker.param2 % 10))) { DeleteItem1(talker, @q_gold_wyvern, 4*(talker.param2 % 10)); talker.param1 = talker.param1+((Rand(3)+1)*16); } else ShowPage(talker, "blacksmith_duning_q0336_10.htm"); } Note about two points 1. (4*(talker.param2 % 10)) 2. ((Rand(3)+1)*4) Decompiler generates } else if (reply == 6) { if (OwnItemCount(talker, @q_gold_wyvern) >= 4 * talker.param2 % 10) { if (GetCurrentTick() - talker.quest_last_reward_time > 1) { DeleteItem1(talker, @q_gold_wyvern, 4 * talker.param2 % 10); talker.param1 = talker.param1 + (Rand(3) + 1) * 4; talker.param1 = talker.param1 + (Rand(3) + 1) * 16; } } else { ShowPage(talker, "blacksmith_duning_q0336_10.htm"); } 1. 4 * talker.param2 % 10 2. (Rand(3) + 1) * 4 While point #2 in THIS case is not crucial (but in other cases it might be crucial), point #1 is for sure wrongly decompiled - extra () are missed and cause wrong calculation, which will be fetch_i mul push_const 10 mod greater_equal