A Community discussion forum for Halo Custom Edition, Halo 2 Vista, Portal and Halo Machinima

Home  Search Register  Login Member ListRecent Posts
»Forums Index »Halo Custom Edition (Bungie/Gearbox) »Halo CE General Discussion »How to bypass script limit

Author Topic: How to bypass script limit (6 messages, Page 1 of 1)
Moderators: Dennis

Joined: Dec 18, 2018


Posted: Mar 11, 2019 11:36 AM    Msg. 1 of 6       
03.11.19 23:28:52  sapien pc ----------------------------------------------
03.11.19 23:28:52 reference function: _write_to_error_file
03.11.19 23:28:52 reference address: 401b13
03.11.19 23:28:52 CreateDevice succeeded with refresh rate = 0
03.11.19 23:28:55 Sound card doesn't meet minimum hardware requirements. Disabling hardware option.
03.11.19 23:28:58 Increasing sound decompression buffer size to 1048576 bytes
03.11.19 23:29:04 units must have models and animation graphs
03.11.19 23:30:23 tried to add more elements for a hs_globals_block @0C52D1A0 #128 than allowed
03.11.19 23:30:23 [player_addons line 1] i couldn't allocate space for this global.: (global boolean visr false)

03.11.19 23:30:23 recompiling scripts after scenarios were merged.

Joined: Jun 8, 2014


Posted: Mar 11, 2019 11:49 AM    Msg. 2 of 6       
Quote: ;*

There are three limits in the Halo scripting system that the CMT scripts come up against regularly. You must understand them if you want to do anything big.

If you do not understand these concepts, insanely bad things may happen and you may not know where to start fixing them.

Limit 1 - syntax nodes

The first is the concept of "syntax nodes".

These are sections of memory that the game allocates to handle the structure of scripts when it compiles them. There is a maximum number of syntax nodes that the game can allocate when compiling scripts. If you exceed this limit, scripts will not compile.

Syntax data is stuff like parentheses, function names, variable names... anything that has syntactic meaning for the script system.

This limit is enforced across both individual scenarios and child scenarios. So, even if the main scenario compiles, it might not work once you add its children (if its children have scripts of their own).

If you hit this limit, your only choice is to remove some syntax data. It can come from anywhere, but something has to go. This can sometimes be a long and painful process.

Limit 2 - source file size

The second is the maximum size of a source file.

The game will not compile scripts for a source file above a given size. Many of our ready-to-compile output files approach this limit.

To combat this limit, we omit comments from preprocessor output. We also have a quick-and-dirty tool to strip extraneous whitespace characters from output files.

If you hit this limit, your only choice is to move stuff from one source file into another source file. (The component system, which you'll read more about later, is designed to make these movements reasonably easy by setting components' filter types so they appear in different output files).

Limit 3 - script stack overflows

The third is the concept of the maximum stack size allocated to a script. This one is scary and technical, and its potential consequences are the most severe.

If you've never heard of a stack in the context of computer programming before, skim through this: http://en.wikipedia.org/wiki/Call_stack

Halo allocates a certain amount of memory for each scripting thread in a scenario. (A "thread" is either a startup script, a dormant script, or a continuous script). This memory is used to hold results of invoking functions, parameters for script functions, and so on.

Unfortunately, this memory is not very big. It is very, very easy to exceed the limits of this memory if you have enough nested statements. The maximum number of nested statements is somewhere between 10 and 16 levels deep, depending on if you're invoking static scripts, if you're invoking methods with parameters, and other things.

(Nested statements are statements like these, where many things happen that are "nested" within one another:
(if ;; some condition
(if ;; some condition
;; ... do something
;; ... do something else
If you exceed this maximum amount of memory allocated for a script's call stack -- for example by having too many statements nested within one another -- the game is not very smart about what it does. It will allow scripts to *overflow* into the memory allocated to other scripts. (See: http://en.wikipedia.org/wiki/Buffer_overflow)

This means that one script can ***COMPLETELY*** fugg up another script if it nests too deeply. If another script's memory is clobbered, it can end up doing arbitrary things. It might wake up when it's supposed to be asleep. It might switch to a new BSP for no reason. It might crash the game. It might make objects flicker randomly.

To combat this, we created a basic static-analysis tool that sniffs for obvious stack overflow conditions in scripts. It's not perfect -- it's really just a rough approximation using heuristics from trial-and-error experiments. However, it'll catch obvious problems and it kept us safe for most of TSC:E's development.

;; --------------------------------------------------------

;; Sidenote: if you're the programming type, you might want to expand that tool to correctly model the HS stack. I've included a chatlog from the immeasurably talented KM00, in which he describes the basic machinery of the stack and some of the size values involved. It's basically a standard call stack. A few of the game's intrinsic functions behave oddly, but the rest follow standard conventions. Most of its behavior is known, and the real challenge is just implementing a correct model of it.

;; Sadly, we didn't have time to implement such a model, and our ballpark estimates were generally okay. But I think it would be a really interesting project for anyone interested in the implementation of programming languages.

Joined: Dec 18, 2018


Posted: Mar 12, 2019 08:00 AM    Msg. 3 of 6       
Not working and it's not the script size but the global blocks I've hit is there a special OS HEK that could bypass all of this shiht.

Joined: Jun 8, 2014


Posted: Mar 12, 2019 02:05 PM    Msg. 4 of 6       
Quote: --- Original message by: Pabeung
Not working and it's not the script size but the global blocks I've hit is there a special OS HEK that could bypass all of this shiht.

Well the OS_HEK only lets you bypass limits that OS extended. There were some hacked versions that let you extend other data that users found out was arbitrarily bound by the toolset, even though it was under the actual engine cap.

This is the OS_2 toolset

But again, I don't know that the limits your hitting are arbitrary, and if you re-read that script document you'll see how badly scripts can get screw things up even if the game does allow it to run.

Either way, there you go. There is an OS_Tool4.exe out there somewhere. Don't know what caps it unbounds.

Joined: Dec 18, 2018


Posted: Mar 12, 2019 09:49 PM    Msg. 5 of 6       
Thanks this came in handy but still doesn't bypass the global limit of only 128 and what I'm trying to do is add more player addon scripts to a50 but they manage to do it in SPV3.

Joined: Jun 8, 2014


Posted: Mar 13, 2019 12:42 AM    Msg. 6 of 6       
IDK, from what I understand that's the hacked toolkit.

As a fix outside of looking for tools that may or may not actually exist, I'd recommend using bit operators;

;; To save on valuable global variables, TSC:E makes use of Open Sauce enabling bit operations
;; on variables.
(global long bit_field 0)

;; Each variable is comprised of a set number of bits. OS bit operations all work on a long
;; integer, which in hsc has 32 bits. Each bit in the long can only be 0 or 1; certain combinations
;; of 0 and 1 lead to a huge number of different values, but we can also use it as if it were
;; essentially a sequence of 32 true/false flags.

(bit_test bit_field 3)
;; this will test if the third bit (bit 3) in the variable is 0 or 1. If it's 0, it will return false;
;; if it's 1, it will return true.

(set bit_field (bit_toggle bit_field 3 1))
;; this will set bit 3 in the bit_field variable to 1, or, for our purposes, true.
;; We have a BIT_SET macro defined in shared\shared_macros.hsh that simplifies this slightly.

;; to make life easier, we always use preprocessor macros with our bit fields.
#define GRUNTS_BIT 0
#define JACKALS_BIT 1
#define BRUTES_BIT 2
#define ELITES_BIT 3
#define HUNTERS_BIT 4

;; If the elites are dead, set the elites bit to false
(if (< (ai_living_count encounter/elites) 0)
BIT_SET(bit_field ELITES_BIT 0)

;; If the elites bit is on, elites attack; if not, it means they're dead, so have everyone defend
(if (bit_test bit_field ELITES_BIT)
(ai_attack encounter/elites)
(ai_defend encounter)

;; You shouldn't need to use these unless you're really really hurting for globals, but if you're
;; just trying to poke some things in TSC:E's scripts, this should give you enough to know what's
;; going on.


Previous Older Thread    Next newer Thread

Time: Wed October 16, 2019 9:39 AM 171 ms.
A Halo Maps Website