• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

loading jass functions at runtime

Status
Not open for further replies.
Level 5
Joined
Jun 16, 2004
Messages
108
Recently I have thought about going back and working on some things that I only conceptualized in the past. This post sort of refers to one of those things. (Also some of the byte code stuff I have been seeing lately has motivated me)

I wrote a basic jass parser for fun, though a basic syntax checking parser is not anything new (probably not useful either, due to existing solutions). I decided to have it compile scripts to byte code. That is not very useful either, because the byte code would not be usable. So I also coded the functionality to load such byte code into a tool I already had available.

And here I am presenting the proof of concept: loading new fully functional jass byte code while the game is running.

To me, in its current form it does not feel very useful for map makers, but perhaps eventually it can reach that point. The project was just for fun really, but I am curious if people can find good use cases for this sort of thing. It does set an apparent path forward to another idea I had.

... Anyway, in short, you can compile jass and get it in executable form in the game, provided things go well (the compiler probably has a lot of bugs in it still, as it has had fairly minimal testing).

If you are interested, you can download the attachment and try it out yourself.

First I will note some important things:
- this will only work on game version 1.28.0
- you should not play online with this tool running, as it modifies memory and can get you banned
- the tool will try to disconnect you if you are in a multiplayer game, which further cements the above point


Something resembling instructions:
- download and extract the archive
- verify you can run jasstool.exe in the /jasstool directory, either just run it (and look for errors) or maybe run it through a dependency walker; if you are missing dependencies you may need whatever runtime matches VS 2017
- copy your common.j and Blizzard.j files into the /bytecode directory.
- make sure you are not online (ideally be at the main menu screen)
- run EMS.exe as an admin
- in the ems console that pops up, type in "start" (without quotation marks) and then press enter
- if it all works out, the ems console should start spitting out a bunch of text and wc3 should still be running properly; if things do not work out, wc3 will probably crash - and you may need to kill the process (war3.exe) in your task manager (try running the game again if it fails - and kill the War3.exe task if it says it cannot initialize).
- now that ems is running, try starting a game in single player or in LAN (alone)

Next we can actually try compiling a simple script:
- while in game, type the following as a chat slash command: /jvm bal common.j Blizzard.j createfootman.txt
- the createfootman.txt file is one that should already be present in the /bytecode directory
- assuming all goes well, a cmd prompt should pop up briefly, and then the ems console should say it has inserted a function; if things have gone wrong, there will be error messages instead (verify you copied common.j and Blizzard.j into the /bytecode directory, and that you can run jasstool.exe)
- next, try typing: /jvm ib createfootman
- if it all worked, then you should now have a footman at position 0, 0

And those two slash commands are the basic functionality:
/jvm bal common.j Blizzard.j [customscript.j] - will load the byte code into the game
/jvm ib [function name] - will run a function

Some limitations:
- it is not easy to declare new globals with the current compiler, though you could do it if you really wanted to via using the assembler functionality and some other commands
- you probably will only want to run a "takes nothing returns nothing" function when using the "/jvm ib" command
- the "/jvm bal" command is able to replace functions that already exist, provided the function's parameter count/types and return type does not change; if any of those things change it will throw an error instead
- the compiler is limited to vanilla jass only - if you use some other flavor, you would have to precompile to vanilla jass before the compiler could function on the script


There are a few other slash commands that might be interesting:
/ripbc [function name] <- this will take the byte code from the specified function and write it in the /bytecode directory
/scanstr [hex number] <- looks up the specified string id in the scan string table
/scanstri [string] <- adds a new string to the scan string table (limited to one word, though you could fix it if you wanted by looking at /lua/slash_scanstr.lua)
/scanstrf [string] <- finds the string id of the given string (limited to one word)
/jfunc [function name] <- prints in the ems console the address of the data about the function (which holds things such as the byte code address, return type, name string, and other stuff)
/load, /reload, /unload [script name] <- handles loading/reloading/unloading of a lua script

Some known issues (plan ahead):
- ems can crash the game while it is attaching
- ems causes the game to crash when the game is closed (alt+f4/etc)
- ems will crash the game if you close ems after it already attached to the game
- ems has in the past managed to crash the world editor, not sure if this still happens since I changed the attach logic



Anyway, I am curious if anyone is interested in this sort of tool.
 

Attachments

  • 17.0426-publicems.zip
    2.1 MB · Views: 100
Last edited:
Level 3
Joined
May 19, 2010
Messages
35
That's a pretty cool tool. Good job! I played around with it a bit and had no issues.
Can your tool also read already compiled bytecode and insert it? Cause I'm currently writing an assembler (here) and that would be a pretty handy feature to test it.
Also do you plan to release the sourcecode?
 
Level 5
Joined
Jun 16, 2004
Messages
108
That's a pretty cool tool. Good job! I played around with it a bit and had no issues.
Can your tool also read already compiled bytecode and insert it? Cause I'm currently writing an assembler (here) and that would be a pretty handy feature to test it.
Also do you plan to release the sourcecode?

It can read in existing byte code, the command for that is: /jvm dec [bytecodefile]
Actually building the byte code is a two step process for jasstool, the first converts to an assembly-like language, and the second is running the assembler portion of the tool on that assembly.
A note on this though, is that the compiled byte code format is not just byte code. You can read the compiledformat.txt in the /jasstool directory for information about that. Basically two things need to be done for injected byte code: inserting any new strings necessary to the scan string table (or looking up the existing strings) and inserting any new jumps into the jump table. So the format used basically just makes that stuff easy to read through.

For jasstool, when it creates byte code, it actually leaves the value/data portion of the op empty for ops that have a jump index or string index. The tables at the beginning of the byte code file list all ops using a string/jump index, so those ops are given real indices to use just before going into game memory ("link" process).

There are some other steps, like actually registering any new functions so the game knows about them, or replacing the existing functions with the new ones, but generally the byte code does not have to change from its compiled form for these.

One last point is that the linker (jvm bal command) expects the function begin op (0x03 op) to have the return type put into the third byte (so it looks like 0x00 0x00 [ret type] 0x03 [string id]).

For the jasstool I would not mind releasing source. It does not rely on EMS for anything so that would be easy. For EMS I probably will not release source. This thread has a somewhat stripped down EMS release to it, and I think I would rather not have an open source EMS rolling out in the wild at this time. For the vmutility module that actually does the byte code insertions and such, maybe. I will have to think about it. There are some things I might have to roll into the module from EMS for it to be any use to a third party.

Can write for wc3 older versions?

I could, but I would rather not. Adding new functionality would become a pain because I would have to do the work specifically to add to each prior version supported as well. So I have no plans to support older versions, sorry.

This also applies going forward. If there is a patch 1.28.1 and I update the tool to support it, I will not update for 1.28.0 anymore.
 
Last edited:
Status
Not open for further replies.
Top