• Content Count

  • Joined

  • Last visited

  • Days Won


AmanoJyaku last won the day on April 22

AmanoJyaku had the most liked content!

Community Reputation

73 Jedi Master

1 Follower

About AmanoJyaku

  • Rank
    Jedi Padawan

Recent Profile Visitors

749 profile views
  1. More specifically, you can enter integers in multiple number systems: Binary - e.g. 0b10101010 (starts with 0b or 0B, valid digits are 0 and 1) Octal - e.g. 0252 (starts with 0, valid digits are 0-7) Decimal - e.g. 170 (starts with 1-9, valid digits are 0-9) Hexadecimal - e.g. 0xAA (starts with 0x or 0X, valid digits are 0-9,A-F,a-f) Remember, all values are 32-bit. Values are signed, with the exception of object types (they are unsigned pointers). I think DeNCS gave you hex output because that is the default value for the last parameter of void ExecuteScript(string sScript, object oTarget, int nScriptVar = -1).
  2. That's the goal, yes. I only started this because @DrMcCoymade an appeal on another site I frequent, and I got swept up in the 15th anniversary of KOTOR modding euphoria. 😄 One potential challenge is that xoreos-tools' changelog states a need to update to C++11. My code is written in C++17; xoreos-tools may need a drastic overhaul before it can be integrated with my project. I'll have to use first to see what it does and determine how I might use it. DLLs are a pain to deal with, I try to avoid them whenever possible.
  3. Welcome! It's great to meet a fellow victim programmer! I'm unfamiliar with NCSDIS, so I read a man page. As far as I can tell, it produces an assembly-like output, DOT output, stack information, and control structures? My binary does all of that, too. 🤣 Not sure how NCSDIS helps here or can be integrated, but I'm interested in looking at it to see what I might have missed. The documentation is accurate. It says the JSR instruction doesn't modify the stack. However, before you even get to the instruction description the section "Calling Subroutines and Engine Routines (ACTIONS)" states that "Invoking subroutines [Amano: that means JSR] or engine routines [Amano: that means ACTION] is done basically in the same manner. Arguments are placed on the stack in reverse order. The call is then made and the callee removes all the arguments from the stack prior to returning." So, somewhere inside the called function is where the arguments are popped. This makes sense given that NCS was patterned after machine code, and the most common calling convention at that time, stdcall, had the callee clean the stack. No worries, this is my thread to discuss the development of whatever this will be named. I'm not on Discord, but I will send you direct messages here if I run into any issues. You can also subscribe to this thread in case anyone else replies, particularly from DP, Salk, or DrMcCoy since they directly work with NCS files. 😊
  4. @DrMcCoy It looks like some of the issues are due to the use of ncsdis for analysis. The binary I'm writing does its own analysis, so these issues might not affect me the same way. I did anticipate these problems, and that's what I'm working on now. I also think I know why ncsdis is failing, but I'll reserve my opinion for when I produce a working solution. 😁
  5. @DarthParametric Thanks! This is an easy problem to solve. @DrMcCoy Thanks for letting me know, I'll reach out to them! It is written in C++, so that's done. Once I get a working binary I'll test it against all files in the K1, K2, K1R, and TSLRCM. If it passes, we can work on integration with Xoreos. Full disclosure: I am self-taught, so I cannot guarantee quality code. A few months ago I came across your site and passed on this because it was outside of my skill set!
  6. Thanks, I was unaware of this. I've tested exclusively against K2 scripts, and will have to add K1 once I'm done. I assume the differences are visible in the nwscript.nss files? If so, I may not even need a toggle... That's what I'm working on now. The following is from the script "a_other_set.ncs": void main() { string sParam = GetScriptStringParameter(); int nParam = GetScriptParameter( 1 ); int nParam2 = GetScriptParameter( 2 ); int nTRUE; if ( nParam2 == -1 ) nTRUE = FALSE; else nTRUE = TRUE; SetLocalBoolean( GetObjectByTag(sParam),nParam,nTRUE ); } You may recognize the code; the byte code in my previous post is the line "int nParam2 = GetScriptParameter( 2 );". I can decompile from the beginning to "if ( nParam2 == -1 )", stopping at the branch. Simply put, "int nTRUE;" is just a declaration since there is other code between the declaration statement and assignment statement: //Note the lack of semicolons! //These expressions are not yet merged into statements!!! RSADDI [int nTRUE] CPTOPSP -8 4 [<copy nParam2 to top of stack>] CONSTI 1 [<place constant value 1 on top of stack>] NEGI [<negate value on top of stack, 1 becomes -1>] EQUALII [nParam2 == -1] JZ 32 [if (true)] The jump-if-zero is what prevents nTRUE from becoming a definition. From now on, any value assigned to nTRUE is just assignment. Branching isn't a problem. That reminds me, if I ever get around to writing the compiler I'll have to create a programming language. NWScript isn't fully documented enough to be usable. Which declarations are valid, and why? int i; int I; int 0; int i0; int I0; int _i; int _I; int _0; int _i0; int _I0;
  7. It's been a while! I hope all is well. First, as you can tell I'm not dead. (But, I may be a zombie.) Most important, I am still working on the decompiler and have been since the last update! Back in May I was preparing a status update, but stopped because I didn't like the code. I couldn't say why, exactly. It worked, it was fast. But, for some reason I wasn't satisfied. So, I scrapped the code and started over. And I finally saw what the problem was: the original code wasn't written to be easily extended. Which was important, since it still needed features. (If I had to guess, I would say it was 5%-10% complete.) Since then, I've made significant progress: To do: Embedding NWScript function declarations into the binary Complete (Yes, all 877! No nwscript.nss needed!!!) Identifying simple expressions (e.g. addition, assignment, bitwise operations, and function calls) Complete Fixed handling of STORE_STATE op code Identifying statements Declarations Complete Assignment Complete Iteration, selection and jump statements Still working Operator associativity and precedence This is irrelevant at the byte code level Type conversions This does not appear to exist in NWScript Byte code conversion to source code Still working Source code conversion to byte code Not started GUI Not started Analysis of NCS file bugs Still working Given what I've learned over the last few months, I would say progress is now 30%. Here's an example of what the decompiler currently does: 02 03 [RSADDI, create a named variable of type int on the stack] 04 03 00000002 [CONSTI, Place a constant (i.e. temporary) value of type int onto the stack] 05 00 0300 01 [Action, Call the function 0x300, popping 1 argument off the stack] 01 01 FFFFFFF8 0004 [CPDOWNSP, Copy the result from the top of the stack to an existing variable] This series of four operations is represented by the following psuedo-NWScript: 02 03 int I0; 04 03 00000002 2; 05 00 0300 01 int GetScriptParameter(int nIndex); [Function 0x300 (768) returns an int onto the top of the stack!!!] 01 01 FFFFFFF8 0004 <some variable -8 bytes from the top of the stack> = <value at top of stack>; Continued evaluation: int I0; I0 = GetScriptParameter(2); We have a variable declaration, and then assignment of the function result to the declared variable. In C terminology, that's a variable definition: int I0 = GetScriptParameter(2); Some of the steps are omitted, but we see the following: Some NCS op codes translate directly to NWScript statements (e.g. RSADDx results in a named variable) Some NCS op codes translate directly to expressions (e.g. CONSTx places a constant, or literal, into the script, ADDxx places addition into the script) Multiple NCS op codes will need to be combined to make complex NWScript statements, as in the example above At the moment, I have partially decompiled scripts. And, the binary does not choke on global variables initialized by functions the way DeNCS does! @Salk and @DarthParametric should be happy, since this means the swoop race scripts from Manaan and Tatooine can finally be decompiled! I'm also tallying errors I've found in scripts. Here's one in pseudo-code: string S1 = "Blah"; string S2 = "Meh"; object(S1) == object(S2); NWScript does not have casts! Casts added to illustrate the problem! What's wrong with this? NWScript is based on C, and C is a strongly-typed language. This means an entity of type string is different from an entity of type object! So, when NWScript is told to test for equality, it needs to compare the entities using their type information. That means strings should be compared byte by byte, up to the length of the shortest string. But, we told NWScript that S1 and S2 are object types, which are pointers! The pointers are compared, but not the strings to which they point! Thus, they will likely never test correctly even when the strings have the same contents! This is a real bug I found, and while I don't think it breaks the script I found it in, it could explain weird issues I've had with the game over the years. (I once tried to leave Peragus, only to find the Ebon Hawk surrounded by 30-40 robots. There're supposed to be two or three!!!) That's all for now. Hopefully, I'll have more progress by next week.
  8. I don't have a problem with it. Gamorreans are supposed to be formidable fighters, and it can be assumed that a leader of the GenoHaradan would be one of the stronger ones. Besides, maybe he used mines like we did.
  9. @JediArchivist Like @Effix said, check the VDF to see if "PublishFileId" is present. If the value is "2075761409" and it's failing, then change it to "0" or remove the line entirely.
  10. Yes, try that. Also, you may need to wait. During my testing a few days ago I uploaded the VDF, but it failed because I deliberately didn't put any content in. Today, I logged into and saw a workshop item for the first time! So, even if it fails, if you get a PublishFileId (which I got despite the failure) then you have an item in the Workshop! You will find your mod at "Workshop Items" to the bottom-right. The direct link is<custom_id>/myworkshopfiles/, where <custom_id> is your custom URL ID. Custom URL IDs are set in the "Edit Profile" section. The direct link to your mod should be at
  11. @JediArchivist I don't believe there is moderation unless people complain about ToS violations. Setting "visibility" to "0" makes it visible to everyone. It's also a different field than the one you see in your screenshot. Yes, there are two visibility properties. Very weird. If you need to activate Steam Guard you will get an email with a Steam Guard code automatically. Various theories range from having to accept EULAs in the Steam website, to having to put $5 into your Steam Account (Steam says this limits fake mods).
  12. @JediArchivist Well, whatever it is, it's not the contents of the script. I just made a VDF and saved in the directory structure you created. It gives me a workshop item ID and everything. Steam>login hodgel Logging in user 'hodgel' to Steam Public ... Logged in OK Waiting for user info...OK Steam>workshop_build_item C:\Mods\VDF\MiraRomance.vdf Create new workshop item ( PublishFileID 2075413754). Preparing update... Preparing content...ERROR! Failed to update workshop item (Failure). The error is because I never created any of the mod's files. But, I was able to replicate your error: Steam>workshop_build_item C:\Mods\VDF\MiraRomancw.vdf ERROR! Failed to load build config file "C:\Mods\VDF\MiraRomancw.vdf". So... you have a problem with the path. Check the file name properties. Since you created it in Notepad, you may have saved it as a text file due to the way Notepad works. The filename may be "MiraRomance.vdf.txt"
  13. @Effix According to Steam's documentation, "publishedfileid" "0" tells Steam to create a new Workshop mod. After creation, "publishedfileid" in the VFD is modified with whatever value Steam gives your mod. Updates to the mod then use the modified "publishedfileid" value in order to find the mod to update. The documentation does say that "publishedfileid" can be left "unset" to create the mod, but I'm unclear as to what that means. For example, leave out "publishedfileid" entirely, or just write "publishedfileid" without a corresponding value? It can't hurt to try the full syntax, especially since everything else looks ok. @JediArchivist I would ensure this is being run with administrator rights since it modifies the VDF file. I would also check stderr.txt to see if it gives more information on the error.
  14. @JediArchivist I think you're missing a field. Try adding "publishedfileid" "0", e.g. "workshopitem" { "appid" "208580" "publishedfileid" "0" "contentfolder" "C:\\Mods\\Mira Romance 2.0" "previewfile" "C:\\Mods\\Previews\\1.jpg" "visibility" "0" "title" "Mira Romance Mod 2.0" "description" "This Mod enables the Male Exile to romance Mira! It adds new conversation lines, a new movie, and a new outfit for Mira" "changenote" "Version 2.0.0" }
  15. There is no quest associated with the Rakata genes, and once you talk to the Elder tribe the One and his tribe become hostile. Doesn't matter, because the researcher tells you they just need access to the computer in the temple.