For script performance:
* call data.GetGameCode() less often, using a cached value for the ScriptParser
* use a 4-byte game code instead of string parsing for the game code
For map previews in the table tool performance
* Don't use dispatcher foreground/background thread swapping, it's safe to add the previews to the collection from the background thread.
* Check the exit condition more often
For drawing performance:
* Use Array.Copy when we don't need to worry about Transparency, since it's much faster.
* Make `Darken` faster, we call it a lot
* Reuse DarkenRect utility in HighlightCollision
Other performance changes
* Protototype for ObserableList<T> for a more configurable version of ObservableCollection
Situation:
* Script A refers to B and C. B and C occur right after eachother.
* Scirpt B does not refer to script C, so C doesn't get included in the same body.
-> when editing B, B needs to know that its length does not include C. So the script-length-cache that B uses shouldn't know about C, since B doesn't refer to C.
-> Therefore, B can't use the same cache as A.
* track length caches based on the code body start, not based on the entire model. This lets each code body have its own cache.
doing <??????> auto-included a new {} block, which is cool. But that block needs to not be included when calculating the new cursor position, because the cursor position should remain _before_ the new {}, so it's still on the same line in case you're writing `trainerbattle` or something with multiple pointers in the line.
* when jumping to a script from a map, format the script. This gets us things like text/marts immediately, instead of needing to load, then edit, to see runs that the script points to.
* When editing a script, keep better track of the cursor, so it doesn't jump around when the script address changes or a pointer within the script changes.
* submit failing tests
* Grab failing trainer test from remote branch (#121)
* Updated flash constants
* Fixed flash constant locations
I originally supplied anchor references, not locations of the constants themselves. That's been fixed. Also, I changed the field name for flash.radius, so it's hopefully clearer.
* Fixed some other pointer issues with RAM addresses in script commands
RAM addresses can't be encased in <> nicely. Some commands still needed their RAM-address pointers to have the ::|h formatting instead.
* Fixing some parameter formats in the script reference file.
There were a few other commands that needed RAM-address parameters set to their correct format so that typing "2024284" doesn't auto format to 0xA024284, etc.
* update script reference (again)
* Added a failing test for duplicating trainer data
Bug report in query: https://discord.com/channels/538022037718040588/538022038376415234/1083215729177931877
---------
Co-authored-by: ShinyTillDawn <80070404+ShinyTillDawn@users.noreply.github.com>
* Fix test
ExportTilesetWithPalette2_EditTileset_ImportTilesetWithPalette2_DataMatches
-> fix formatting in LzSpriteRun
-> fix overflow error in SpriteRun
-> fix default palette detection in SpriteTool
-> improve test so it gives better failure info
* fix trainer duplication assert
fix test name / remove unneeded comments
handle Trainer team runs specially
update assertion error message
* Improve pointer error logic
Pointers are allowed to point into the middle of an existing run. Such a pointer is an error, but is not a metadata inconsistency. Update metadata checking for new logic. Update pointer logic to display pointer as an error.
* improve handling of `auto`
allow <auto> to be used if there's a one-byte gap
* improve interruptingSourceRun logic
an interrupting table is not always valid.
It's only valid if the source is at an index that would make it a pointer.
* don't clear bytes, clear anchors
If you have a custom anchor name in the middle of a script and then edit the script, that custom anchor name will be lost. But anything pointing to it will still point to it.
---------
Co-authored-by: ShinyTillDawn <80070404+ShinyTillDawn@users.noreply.github.com>
When scripts get merged together, some inner-scripts no longer appear to be real scripts. These were showing up as orphans when the scripts get formatted, since that causes scripts to get merged. But the pointers are still there, so they're not actually orphans.
Fix the orphan-naming logic so that it won't name things as orphans if they're inner scripts that still have pointers
ai script children should appear as ai scripts
editing an AI script shouldn't make a bunch of orphans
introduce a light caching system for noticing when scripts don't need to be loaded again.
script edits that don't change any compiled bytes should be capable of skipping the metadata update in situations where the metadata is already correct
* Selecting brock's script should select the _whole_ script
* Get correct number of code sections when scripts point to freespace
* Make sure script concatenation works correctly for `goto` followed by `end` (vanilla games do this a lot)
* multiple if statements / gotos all get compiled into one script, so long as it's all contiginous script data
* make sure `trainerbattle 01` works correctly with labels
* include blank line separators between labels when decompiling scripts
add enum types for fanfare / bufferitem
allow script constants to contain underscores
allow autocomplete for constants that are the last argument
allow 'find usages -> scripts' to find usages from macros (and fix crash)
instead of calculating their length each time, an edited script can be passed its previous length. This lets you have multiple ends within the same script without issue.
Previously, trying to edit a script with gotos/calls inline would cause trouble, because the destination is likely contained within the same script. But HMA parses the anchor and puts the script in a separate textbox, which is confusing. Worse, it prevents you from making your script longer, because it thinks it would overwrite itself because of the anchor.
Add logic to handle this case.
- If a script is completely contained within the script that's currently under edit, don't give the script its own textbox.
- If the script would overwrite some bytes, but those bytes are a script that (1) is totally contained within the script you're editing, and (2) is only referenced by the script you're editing; then allow the overwrite to occur.
* Don't clear an anchor to the start of the code we're writing, it may be important. We may later care about keeping pointers that point one byte into the thumb code as well, since the low bit is set to 1 for branch-exchange.
* Have ldr instructions write word aligned values even when starting from a 4N+2 offset.
* When given 4 instructions, that's enough space to replace it with a load, a branch, and an address.
* If the 4 instructions are such that they don't have any external dependencies (they don't contain a branch or a load), they can be safely moved to a new address.
These two points together mean that we can arbitrarily (and safely) expand almost any function. This should be very useful for both users and prototyping.
sometimes scripts are created at locations that have NoInfo anchors. In this case, do allow repoints, and do interpret the data as a script even though the anchor is wrong.
in order for clearing a pointer to clear itself from any anchors that use it, the pointer must still point to that anchor... so we need to clear the data before we change it.
When editing XSE scripts, it's possible to have a script that used to be called, but now isn't. If we don't track those orphans, they just become dead data.
Put orphans in a subfolder so that the intent is more clear.
Replace the existing method with a pair of methods.
One method requires a token, so that it can make metadata changes.
The other returns a set of runs along with its set of compiled bytes, so that pointers can be adjusted.
Animation scripts can use the same engine as map scripts and battle scripts... except that they include a new type of parameter.
With animation scripts, the last parameter of some lines is allowed to include arbitrarily many arguments. This is represented by putting the last argument in brackets `[]`.