From 9646ece341e1d9f8f1e1f98b33a5b6ee3ee3c9ab Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 08:39:51 -0400 Subject: [PATCH 01/11] Adds documentation for Remember and Recall --- docs/.vitepress/config/en.ts | 8 ++ docs/developer-docs/flags/remember.md | 186 ++++++++++++++++++++++++++ docs/developer-docs/recall.md | 19 +++ 3 files changed, 213 insertions(+) create mode 100644 docs/developer-docs/flags/remember.md create mode 100644 docs/developer-docs/recall.md diff --git a/docs/.vitepress/config/en.ts b/docs/.vitepress/config/en.ts index 6fbf0c3f..af988456 100644 --- a/docs/.vitepress/config/en.ts +++ b/docs/.vitepress/config/en.ts @@ -365,6 +365,10 @@ function sidebarDeveloperDocs(): DefaultTheme.SidebarItem[] { text: "Trigger", link: "/developer-docs/flags/trigger", }, + { + text: "Remember", + link: "/developer-docs/flags/remember", + }, ], }, { @@ -391,6 +395,10 @@ function sidebarDeveloperDocs(): DefaultTheme.SidebarItem[] { text: "Prior Values", link: "/developer-docs/prior-values", }, + { + text: "Recall", + link: "/developer-docs/recall", + }, { text: "Value Definition", link: "/developer-docs/value-definition", diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md new file mode 100644 index 00000000..b20c9282 --- /dev/null +++ b/docs/developer-docs/flags/remember.md @@ -0,0 +1,186 @@ +# `Remember` + +*This feature will be available at the RA_Integration version 1.4 milestone for developers. with support to be added for rcheevos version 11.4 milestone.* + +The `Remember` condition is chosen in the Flag column of the Asset Editor. Since many of the use cases tend to be fairly complex, it is recommended you be familiar with the rest of the tool kit before studying some of the more complicated examples below. + +When a condition has the `Remember Flag`, the value of the condition is stored in the `Recall` accumulator. This value may be used in later logic by using the `Recall` operand found in the Type column of either side. + +There is one remembered value per *group* (Core, Alt1, Alt2, etc). This value is initialized as a unsigned integer with value 0. If you Remember a new value, it will overwrite the previously remembered value. If you remember a Float value, the remembered value will be a floating point value instead of an unsigned integer. Using `Recall` before a value is remembered using the `Remember` condition will generate a warning in the asset editor. + +The `Remember` condition is a combining condition and does not break any chain it is in. Conditions that follow it are considered part of the chain. + +## Basic Usage + +### Simple Example + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | --------- | ----- | ------ | ------ | --- | ----- | ------ | ------- | ----- | +| 1 | SubSource | Delta | 16-bit | 0x1234 | | | | | | +| 2 | Remember | Mem | 16-bit | 0x1234 | | | | | | + +In this example, the `Delta` value of `0x1234`, the value from the previous frame, is subtracted from the `Mem` value of `0x1234` and Remembered. + +### Simple Example - With Operators + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | --------- | ----- | ------ | ------ | --- | ----- | ------ | ------- | ----- | +| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | + +The Remember condition can optionally take two operand and process a value based on an operator such as multiplication, division, addition, subtraction, and others. In this example, we used the subtraction operator to store the equivalent value as in the first example, but we do it in a single line. + +### Using the Stored Value + +To use the stored value, specify the `Recall` operator as the Type of operand: + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | +| 2 | | Recall | | | = | Value | | 0x05 | | + +In this example it uses the stored value and compares it to a constant value of 5. However, using the stored value once does not show off the main usefulness of `Remember`. + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | +| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | +| 2 | And Next | Recall | | | = | Value | | 0x05 | | +| 3 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 4 | And Next | Recall | | | = | Value | | 0x14 | | +| 5 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 6 | And Next | Recall | | | = | Value | | 0x14 | | +| 7 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 8 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | + +In this example, we are using the stored value in multiple chains within an Add Hits chain without having to recalculate the value each time. Here we are looking for specific increases of `0x1234` to occur while the value of `0x1000` is equal to 3. Perhaps `0x1234` is money, `0x1000` is the current level, and you want to make sure the player collects a gem worth 5 units of money, one worth 20, and one worth 100 in level 3. `Recall` is used here to check all these values of the difference between Mem and Delta without having to recalculate it each time. See the [`Add Hits`](/developer-docs/flags/addhits-and-subhits) document for more information about how that condition works. + +## Interaction with Pause If + +Because `Pause If` logic is processed before other logic, `Pause If` logic can only recall values that have been remembered by pause logic. Values remembered during `Pause If` logic continue to me remembered during the remaining logic processing. + +See the [`Pause If`](/developer-docs/flags/pauseif) document for more information about how that condition works. + +### Example of Use with Pause If + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ---------- | ----- | +| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | +| 2 | Pause If | Recall | | | >= | Value | | 0x8000000 | 1 (0) | +| 3 | And Next | Recall | | | = | Value | | 0x05 | | +| 4 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 5 | And Next | Recall | | | = | Value | | 0x14 | | +| 6 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 7 | And Next | Recall | | | = | Value | | 0x14 | | +| 8 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 9 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | + +This example extends the previous [Using the Stored Value](#using-the-stored-value) example by adding a `Pause If` lock if the player loses money\*. Because `Remember` is a combining condition, it links with the following `Pause If` to form a chain and is processed as part of the pause processing, allowing the value to be used by the `Pause If`. The remembered value is available to the remaining logic and can therefore be used by the Add Hits chain. + +Notes: +- \* Due to the way unsigned math works, the subtraction will underflow back to 0xfffffff at negative one, so any value greater or equal to 0x80000000 is treated as negative). +- Because pause processing happens first, you *could* put conditions 1-2 at the end of the logic and it will still work! The value remembered by the pause logic will still be available to the Add Hits chain. However because this may be a confusing effect, we recommend putting your pause logic at the beginning when using it with `Remember` and `Recall`. + +### Example of Incorrect Usage with Pause If + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ---------- | ----- | +| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | +| 2 | And Next | Recall | | | = | Value | | 0x05 | | +| 3 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 4 | And Next | Recall | | | = | Value | | 0x14 | | +| 5 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 6 | And Next | Recall | | | = | Value | | 0x14 | | +| 7 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 8 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | +| 9 | Pause If | Recall | | | >= | Value | | 0x8000000 | 1 (0) | + +In this example, the `Remember` condition is not chained with the `Pause If`. Because of this, the `Pause If` condition will read a value of 0 from the `Recall` operand and never be paused, as a consequence of the pause logic being processed first. Fear not though, as the validation is smart enough to recognize this and will generate a warning on condition 9 that `Recall` is being used in a `Pause If` without a value being remembered in a `Pause If`. + +## Using `Recall` within a `Remember` Condition + +You can perform math on a remembered value and remember the result: + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | +| 1 | Remember | Mem | 16-bit | 0x1002 | + | Mem | 16-Bit | 0x1004 | | +| 2 | Remember | Recall | | | \* | Value | | 0x03 | | +| 3 | Remember | Recall | | | + | Mem | 16-Bit | 0x1000 | | +| 4 | Remember | Recall | | | % | Value | | 0x05 | | +| 5 | | Recall | | | = | Value | | 0x00 | | + +In this example, let's say you need to calculate the value of `0x1000` + (`0x1002` + `0x1004`) \* 3 and check to see if that is a multiple of 5. You can use `Recall` in a `Remember` condition it keep operating on the remembered value and store the new result. + +Notes: +- If the value of the modulus (`%`) operation is 0, that means there is no remainder from the division by 5, meaning the value is a multiple of 5) + +## Using `Remember` for Calculated Pointer Offsets + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | ---------- | ------ | ------ | ------ | --- | ------ | ------ | ------- | ----- | +| 1 | Remember | Mem | 8-bit | 0x0789 | \* | Value | | 0x60 | | +| 2 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 3 | | Mem | 16-bit | 0x08 | > | Value | | 0x00 | | + +In this example, let's say you have an address that points to a table of data, but in order to know where in the table you want to go, you have to calculate the offset from another source. `0x1234` will be used as the pointer to the table of data. `0x0789` will be the index in the table. The size of data for table entries is `0x60` bytes. And finally, the data we care about is `0x08` bytes into the data's structure Perhaps this is "Player Health" and the index we are calculating is the index in the table where the "Player Data" exists and we need to check if this value is greater than 0. + +See the [`Add Address`](/developer-docs/flags/addaddress) document for more information about how that condition works. + +Breakdown of Conditions: +1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table. +2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" +3. Offsets from the Address by `0x08`, the and reads the current memory value for the Player's Health with 16-bit size, then uses a comparison to check if it is greater than zero. + +## Deeper Chaining of `Remember` Conditions + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | ---------- | ------ | ------ | ------ | --- | ------ | ------ | ------- | ----- | +| 1 | Remember | Mem | 8-bit | 0x0789 | \* | Value | | 0x60 | | +| 2 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 3 | And Next | Mem | 16-bit | 0x08 | < | Delta | | 0x08 | 0 (0) | +| 4 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 5 | And Next | Mem | 8-bit | 0x24 | != | Value | | 0xff | 0 (0) | +| 6 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 7 | Remember | Mem | 16-bit | 0x24 | \* | Value | | 0x60 | | +| 8 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 9 | Reset If | Mem | 8-bit | 0x00 | = | Value | | 0xA7 | 0 (0) | + +This example shows how using `Remember` continues the chain of And Next conditions and how you can remember new values during the chain without affecting earlier parts of the chain or breaking the chain. + +In this example, we build on the previous `Add Address` example by chaining it with other conditions. Pretend this is a challenge that fails if the player loses health while holding a certain object. Suppose the player data stores the index of the object at offset `0x24` (the value of which is `0xff` if no object is held). Suppose that index is an index into the same table that holds the player data. This example shows the reset chain that accomplishes this. Suppose that offset `0x00` of object data holds the 8-bit ID of the object. + +Breakdown of Conditions: +1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table. +2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" +3. Checks if the player lost health, using the offset for health established in the previous example. +4. Re-uses the address for the start of the player data +5. Checks the offset of the held object and makes sure it's not 0xff. +6. Re-uses the address for the start of the player data +7. Stores the index of the helf object times the size of the object data and now the stored value is the location of the table where the object is located. +8. Uses the object table pointer + location in table of object +9. Reads the ID of the object and resets if holding the specific object while the other two core conditions in the chain are true (Player lost health and an object is held. + +## Other Considerations + +### Interaction With Floats + +A remembered value will match the type of data being remembered. If operations are being performed, the first operand usually determines the type, except in the case of division (where the second operand determines the type). If you need to force an integer value to be stored as a float, you can do either of the following: + + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | -------- | ----- | ------ | ------ | --- | ------ | ------ | ------- | ---- | +| 1 | Remember | Float | | 0.0 | + | Mem | 16-Bit | 0x1234 | | + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | -------- | ----- | ------ | ------ | --- | ------ | ------ | ------- | ---- | +| 1 | Remember | Mem | 16-Bit | 0x1234 | / | Float | | 1.0 | | + + +### Integer Overflow + +When the stored value is an integer, all logic being performed is limited to 32-bits. If the total value exceeds 0xFFFFFFFF, there will be an overflow and only the 32 least significant bits will be used in the comparison. + + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | -------- | ------ | ------ | ------ | --- | ------ | ------ | ---------- | ----- | +| 1 | Remember | Mem | 32-bit | 0x8010 | + | Mem | 32-Bit | 0x8020 | | +| 2 | | Recall | > | Value | | 0x30000000 | 0 (0) | + +If 0x8010 is 0xC0000000 and 0x8020 is 0x54321ABC, then the total will be 0x114321ABC, which is more than 32-bits and will be truncated to 0x14321ABC, which is not more then 0x30000000, so the logic will evaluate false. \ No newline at end of file diff --git a/docs/developer-docs/recall.md b/docs/developer-docs/recall.md new file mode 100644 index 00000000..3c5177eb --- /dev/null +++ b/docs/developer-docs/recall.md @@ -0,0 +1,19 @@ +# `Recall` + +*This feature will be available at the RA_Integration version 1.4 milestone for developers. with support to be added for rcheevos version 11.4 milestone.* + +A `Recall` value is the the last value stored by the [`Remember` Flag](/developer-docs/flags/remember) + +Examples of how it can be used: + +- Recall a calculated value for multiple uses in logic. +- Continuous operation on remembered values to perform maore complicated math than `Add Source` and `Sub Source` can accomplish. +- Recall a calculated address+offset for use in `Add Address` + +To use a remembered value, specify the `Recall` operator as the Type of operand: + +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | +| 2 | | Recall | | | = | Value | | 0x05 | | + +In this snippet, the recalled value is compared for equality with a constant value of 5. \ No newline at end of file From cd2b78f8e16c538d7497c3da5bca0b0bc12748a4 Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 08:53:30 -0400 Subject: [PATCH 02/11] Fixes bad link. --- docs/developer-docs/flags/remember.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md index b20c9282..cd22f88f 100644 --- a/docs/developer-docs/flags/remember.md +++ b/docs/developer-docs/flags/remember.md @@ -50,7 +50,7 @@ In this example it uses the stored value and compares it to a constant value of | 7 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | | 8 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | -In this example, we are using the stored value in multiple chains within an Add Hits chain without having to recalculate the value each time. Here we are looking for specific increases of `0x1234` to occur while the value of `0x1000` is equal to 3. Perhaps `0x1234` is money, `0x1000` is the current level, and you want to make sure the player collects a gem worth 5 units of money, one worth 20, and one worth 100 in level 3. `Recall` is used here to check all these values of the difference between Mem and Delta without having to recalculate it each time. See the [`Add Hits`](/developer-docs/flags/addhits-and-subhits) document for more information about how that condition works. +In this example, we are using the stored value in multiple chains within an Add Hits chain without having to recalculate the value each time. Here we are looking for specific increases of `0x1234` to occur while the value of `0x1000` is equal to 3. Perhaps `0x1234` is money, `0x1000` is the current level, and you want to make sure the player collects a gem worth 5 units of money, one worth 20, and one worth 100 in level 3. `Recall` is used here to check all these values of the difference between Mem and Delta without having to recalculate it each time. See the [`Add Hits`](/developer-docs/flags/addhits-subhits) document for more information about how that condition works. ## Interaction with Pause If From 834ab3a231294059834a18dea5fe435e4ecc79cd Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 09:44:45 -0400 Subject: [PATCH 03/11] Adds title and description metadata. --- docs/developer-docs/flags/remember.md | 4 ++++ docs/developer-docs/recall.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md index cd22f88f..36be0ac0 100644 --- a/docs/developer-docs/flags/remember.md +++ b/docs/developer-docs/flags/remember.md @@ -1,3 +1,7 @@ +--- +title: Understanding and Using Remember +description: Learn how to effectively use the Remember flag to store values for use later in logic, along with several use cases where this is particularly helpful. +--- # `Remember` *This feature will be available at the RA_Integration version 1.4 milestone for developers. with support to be added for rcheevos version 11.4 milestone.* diff --git a/docs/developer-docs/recall.md b/docs/developer-docs/recall.md index 3c5177eb..963ce913 100644 --- a/docs/developer-docs/recall.md +++ b/docs/developer-docs/recall.md @@ -1,3 +1,7 @@ +--- +title: Understanding and Using Recall +description: Learn how to use the Recall operand type to represent a previously remembered value. +--- # `Recall` *This feature will be available at the RA_Integration version 1.4 milestone for developers. with support to be added for rcheevos version 11.4 milestone.* From e6a594bc721c2f464382add3f08584ae61b62c80 Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 10:16:31 -0400 Subject: [PATCH 04/11] Addresses typographical errors identified by Jamiras's PR review. --- docs/developer-docs/flags/remember.md | 6 +++--- docs/developer-docs/recall.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md index 36be0ac0..7f9ba992 100644 --- a/docs/developer-docs/flags/remember.md +++ b/docs/developer-docs/flags/remember.md @@ -31,7 +31,7 @@ In this example, the `Delta` value of `0x1234`, the value from the previous fram | -- | --------- | ----- | ------ | ------ | --- | ----- | ------ | ------- | ----- | | 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | -The Remember condition can optionally take two operand and process a value based on an operator such as multiplication, division, addition, subtraction, and others. In this example, we used the subtraction operator to store the equivalent value as in the first example, but we do it in a single line. +The Remember condition can optionally take two operands and process a value based on an operator such as multiplication, division, addition, subtraction, and others. In this example, we used the subtraction operator to store the equivalent value as in the first example, but we do it in a single line. ### Using the Stored Value @@ -67,7 +67,7 @@ See the [`Pause If`](/developer-docs/flags/pauseif) document for more informatio | ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | | -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ---------- | ----- | | 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | -| 2 | Pause If | Recall | | | >= | Value | | 0x8000000 | 1 (0) | +| 2 | Pause If | Recall | | | >= | Value | | 0x80000000 | 1 (0) | | 3 | And Next | Recall | | | = | Value | | 0x05 | | | 4 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | | 5 | And Next | Recall | | | = | Value | | 0x14 | | @@ -123,7 +123,7 @@ Notes: | 2 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | | 3 | | Mem | 16-bit | 0x08 | > | Value | | 0x00 | | -In this example, let's say you have an address that points to a table of data, but in order to know where in the table you want to go, you have to calculate the offset from another source. `0x1234` will be used as the pointer to the table of data. `0x0789` will be the index in the table. The size of data for table entries is `0x60` bytes. And finally, the data we care about is `0x08` bytes into the data's structure Perhaps this is "Player Health" and the index we are calculating is the index in the table where the "Player Data" exists and we need to check if this value is greater than 0. +In this example, let's say you have an address that points to a table of data, but in order to know where in the table you want to go, you have to calculate the offset from another source. `0x1234` will be used as the pointer to the table of data. `0x0789` will be the index in the table. The size of data for table entries is `0x60` bytes. And finally, the data we care about is `0x08` bytes into the data's structure. Perhaps this is "Player Health" and the index we are calculating is the index in the table where the "Player Data" exists and we need to check if this value is greater than 0. See the [`Add Address`](/developer-docs/flags/addaddress) document for more information about how that condition works. diff --git a/docs/developer-docs/recall.md b/docs/developer-docs/recall.md index 963ce913..0a6a2f21 100644 --- a/docs/developer-docs/recall.md +++ b/docs/developer-docs/recall.md @@ -11,7 +11,7 @@ A `Recall` value is the the last value stored by the [`Remember` Flag](/develope Examples of how it can be used: - Recall a calculated value for multiple uses in logic. -- Continuous operation on remembered values to perform maore complicated math than `Add Source` and `Sub Source` can accomplish. +- Continuous operation on remembered values to perform more complicated math than `Add Source` and `Sub Source` can accomplish. - Recall a calculated address+offset for use in `Add Address` To use a remembered value, specify the `Recall` operator as the Type of operand: From 16d364154cce5a5a23810e0adac27136abc45218 Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 12:54:15 -0400 Subject: [PATCH 05/11] Fixes minor typo in version availability comments. (period->comma) --- docs/developer-docs/flags/remember.md | 2 +- docs/developer-docs/recall.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md index 7f9ba992..c98bb03e 100644 --- a/docs/developer-docs/flags/remember.md +++ b/docs/developer-docs/flags/remember.md @@ -4,7 +4,7 @@ description: Learn how to effectively use the Remember flag to store values for --- # `Remember` -*This feature will be available at the RA_Integration version 1.4 milestone for developers. with support to be added for rcheevos version 11.4 milestone.* +*This feature will be available at the RA_Integration version 1.4 milestone for developers, with support to be added for rcheevos version 11.4 milestone.* The `Remember` condition is chosen in the Flag column of the Asset Editor. Since many of the use cases tend to be fairly complex, it is recommended you be familiar with the rest of the tool kit before studying some of the more complicated examples below. diff --git a/docs/developer-docs/recall.md b/docs/developer-docs/recall.md index 0a6a2f21..c8448532 100644 --- a/docs/developer-docs/recall.md +++ b/docs/developer-docs/recall.md @@ -4,7 +4,7 @@ description: Learn how to use the Recall operand type to represent a previously --- # `Recall` -*This feature will be available at the RA_Integration version 1.4 milestone for developers. with support to be added for rcheevos version 11.4 milestone.* +*This feature will be available at the RA_Integration version 1.4 milestone for developers, with support to be added for rcheevos version 11.4 milestone.* A `Recall` value is the the last value stored by the [`Remember` Flag](/developer-docs/flags/remember) From 86f3ec0b92d6a61ae21ddaab7fdb464b43bee3bf Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 13:02:18 -0400 Subject: [PATCH 06/11] Adds some additional clarification to the lifetime of a remembered value. --- docs/developer-docs/flags/remember.md | 2 +- docs/developer-docs/recall.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md index c98bb03e..6273011f 100644 --- a/docs/developer-docs/flags/remember.md +++ b/docs/developer-docs/flags/remember.md @@ -10,7 +10,7 @@ The `Remember` condition is chosen in the Flag column of the Asset Editor. Since When a condition has the `Remember Flag`, the value of the condition is stored in the `Recall` accumulator. This value may be used in later logic by using the `Recall` operand found in the Type column of either side. -There is one remembered value per *group* (Core, Alt1, Alt2, etc). This value is initialized as a unsigned integer with value 0. If you Remember a new value, it will overwrite the previously remembered value. If you remember a Float value, the remembered value will be a floating point value instead of an unsigned integer. Using `Recall` before a value is remembered using the `Remember` condition will generate a warning in the asset editor. +There is one remembered value per *group* (Core, Alt1, Alt2, etc). This value is initialized at the beginning of an evaluation as a unsigned integer with value 0. If you Remember a new value, it will overwrite the previously remembered value. If you remember a Float value, the remembered value will be a floating point value instead of an unsigned integer. Using `Recall` before a value is remembered using the `Remember` condition will generate a warning in the asset editor. The `Remember` condition is a combining condition and does not break any chain it is in. Conditions that follow it are considered part of the chain. diff --git a/docs/developer-docs/recall.md b/docs/developer-docs/recall.md index c8448532..c4c31502 100644 --- a/docs/developer-docs/recall.md +++ b/docs/developer-docs/recall.md @@ -8,6 +8,8 @@ description: Learn how to use the Recall operand type to represent a previously A `Recall` value is the the last value stored by the [`Remember` Flag](/developer-docs/flags/remember) +The `Recall` accumulator's value is for the current frame's evaluation of logic. It does not persist between evaluations and does not maintain its value for use in a later evaluation. Each group (Core, Alt1, Alt2, etc) has its own separate `Recall` accumulator; a value remembered in one group therefore cannot be recalled in another group. Using `Recall` before a value is remembered in using the `Remember` condition will generate a warning in the asset editor. + Examples of how it can be used: - Recall a calculated value for multiple uses in logic. From ca74461071988ddfb2739f062f5b340b98ed2c87 Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 13:04:54 -0400 Subject: [PATCH 07/11] Adds link to Recall operand document. --- docs/developer-docs/flags/remember.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md index 6273011f..aa54aa7f 100644 --- a/docs/developer-docs/flags/remember.md +++ b/docs/developer-docs/flags/remember.md @@ -8,7 +8,7 @@ description: Learn how to effectively use the Remember flag to store values for The `Remember` condition is chosen in the Flag column of the Asset Editor. Since many of the use cases tend to be fairly complex, it is recommended you be familiar with the rest of the tool kit before studying some of the more complicated examples below. -When a condition has the `Remember Flag`, the value of the condition is stored in the `Recall` accumulator. This value may be used in later logic by using the `Recall` operand found in the Type column of either side. +When a condition has the `Remember Flag`, the value of the condition is stored in the `Recall` accumulator. This value may be used in later logic by using the [`Recall`](/developer-docs/recall) operand found in the Type column of either side. There is one remembered value per *group* (Core, Alt1, Alt2, etc). This value is initialized at the beginning of an evaluation as a unsigned integer with value 0. If you Remember a new value, it will overwrite the previously remembered value. If you remember a Float value, the remembered value will be a floating point value instead of an unsigned integer. Using `Recall` before a value is remembered using the `Remember` condition will generate a warning in the asset editor. From d825529d630bd5c2e1d646a46eb771fd309097d4 Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 13:16:30 -0400 Subject: [PATCH 08/11] Cleans up some additional typos and awkward wording. --- docs/developer-docs/flags/remember.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md index aa54aa7f..9f39380c 100644 --- a/docs/developer-docs/flags/remember.md +++ b/docs/developer-docs/flags/remember.md @@ -58,7 +58,7 @@ In this example, we are using the stored value in multiple chains within an Add ## Interaction with Pause If -Because `Pause If` logic is processed before other logic, `Pause If` logic can only recall values that have been remembered by pause logic. Values remembered during `Pause If` logic continue to me remembered during the remaining logic processing. +Because `Pause If` logic is processed before other logic, `Pause If` logic can only recall values that have been remembered by pause logic. Values remembered during `Pause If` logic continue to be remembered during the remaining logic processing. See the [`Pause If`](/developer-docs/flags/pauseif) document for more information about how that condition works. @@ -110,10 +110,10 @@ You can perform math on a remembered value and remember the result: | 4 | Remember | Recall | | | % | Value | | 0x05 | | | 5 | | Recall | | | = | Value | | 0x00 | | -In this example, let's say you need to calculate the value of `0x1000` + (`0x1002` + `0x1004`) \* 3 and check to see if that is a multiple of 5. You can use `Recall` in a `Remember` condition it keep operating on the remembered value and store the new result. +In this example, let's say you need to calculate the value of `0x1000` + (`0x1002` + `0x1004`) \* 3 and check to see if that is a multiple of 5. You can use `Recall` in a `Remember` condition to operate on the last remembered value and store the new result. Notes: -- If the value of the modulus (`%`) operation is 0, that means there is no remainder from the division by 5, meaning the value is a multiple of 5) +- If the value of the modulus (`%`) operation is 0, that means there is no remainder from the division by 5, meaning the value is a multiple of 5. ## Using `Remember` for Calculated Pointer Offsets @@ -128,9 +128,9 @@ In this example, let's say you have an address that points to a table of data, b See the [`Add Address`](/developer-docs/flags/addaddress) document for more information about how that condition works. Breakdown of Conditions: -1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table. -2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" -3. Offsets from the Address by `0x08`, the and reads the current memory value for the Player's Health with 16-bit size, then uses a comparison to check if it is greater than zero. +1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table the data is located. +2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" in the table. +3. Offsets from the Address by `0x08`, where it reads the current memory value for the Player's Health with 16-bit size, then uses a comparison to check if it is greater than zero. ## Deeper Chaining of `Remember` Conditions @@ -151,13 +151,13 @@ This example shows how using `Remember` continues the chain of And Next conditio In this example, we build on the previous `Add Address` example by chaining it with other conditions. Pretend this is a challenge that fails if the player loses health while holding a certain object. Suppose the player data stores the index of the object at offset `0x24` (the value of which is `0xff` if no object is held). Suppose that index is an index into the same table that holds the player data. This example shows the reset chain that accomplishes this. Suppose that offset `0x00` of object data holds the 8-bit ID of the object. Breakdown of Conditions: -1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table. -2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" +1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table the data is located. +2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" in the table. 3. Checks if the player lost health, using the offset for health established in the previous example. 4. Re-uses the address for the start of the player data 5. Checks the offset of the held object and makes sure it's not 0xff. 6. Re-uses the address for the start of the player data -7. Stores the index of the helf object times the size of the object data and now the stored value is the location of the table where the object is located. +7. Stores the index of the held object times the size of the object data and now the stored value is the location in the table where the object's data is located. 8. Uses the object table pointer + location in table of object 9. Reads the ID of the object and resets if holding the specific object while the other two core conditions in the chain are true (Player lost health and an object is held. From c0c9656e8e27b40ff5914d4fd171f604ba42dfc3 Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 13:56:12 -0400 Subject: [PATCH 09/11] Add in the condition syntax for Remember/Recall --- docs/developer-docs/condition-syntax.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/developer-docs/condition-syntax.md b/docs/developer-docs/condition-syntax.md index 89507e4c..f1580d85 100644 --- a/docs/developer-docs/condition-syntax.md +++ b/docs/developer-docs/condition-syntax.md @@ -43,6 +43,11 @@ description: Comprehensive guide to understanding and using condition syntax in | [BCD](/developer-docs/value-definition#binary-coded-decimal) | `b` | `b0xH1234` | | [Invert](/developer-docs/value-definition#binary-inversion) | `~` | `~0xH1234` | +### Special Operands +| Modifier | Representation | Example | +| :----------------------------------------------------------: | :------------: | :--------: | +| [Recall](/developer-docs/recall) | `{recall}` | `{recall}` | + ### Logical Flags | Flag | Prefix | Example | @@ -61,3 +66,4 @@ description: Comprehensive guide to understanding and using condition syntax in | [`Measured`%](/developer-docs/flags/measured) | `G:` | `G:0xH1234=1` | | [`MeasuredIf`](/developer-docs/flags/measured) | `Q:` | `Q:0xH1234=1` | | [`Trigger`](/developer-docs/flags/trigger) | `T:` | `T:0xH1234=1` | +| [`Remember`](/developer-docs/flags/remember) | `K:` | `K:0xH1234=1` | From cfd1119c53d33e900f23ba3426bd10fb696f383e Mon Sep 17 00:00:00 2001 From: Matt Buchwald Date: Mon, 3 Jun 2024 14:54:07 -0400 Subject: [PATCH 10/11] Changed the =1 to *2 in the Remember example so that it'd actually be valid example. --- docs/developer-docs/condition-syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-docs/condition-syntax.md b/docs/developer-docs/condition-syntax.md index f1580d85..28879a35 100644 --- a/docs/developer-docs/condition-syntax.md +++ b/docs/developer-docs/condition-syntax.md @@ -66,4 +66,4 @@ description: Comprehensive guide to understanding and using condition syntax in | [`Measured`%](/developer-docs/flags/measured) | `G:` | `G:0xH1234=1` | | [`MeasuredIf`](/developer-docs/flags/measured) | `Q:` | `Q:0xH1234=1` | | [`Trigger`](/developer-docs/flags/trigger) | `T:` | `T:0xH1234=1` | -| [`Remember`](/developer-docs/flags/remember) | `K:` | `K:0xH1234=1` | +| [`Remember`](/developer-docs/flags/remember) | `K:` | `K:0xH1234*2` | From c450124f08b4e8c78efc0402319f37d003d92b56 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Mon, 3 Jun 2024 17:30:15 -0400 Subject: [PATCH 11/11] chore: run prettier and add i18n links --- docs/.vitepress/config/es.ts | 8 + docs/.vitepress/config/pt.ts | 8 + docs/developer-docs/condition-syntax.md | 7 +- docs/developer-docs/flags/remember.md | 186 ++++++++++++------------ docs/developer-docs/recall.md | 13 +- 5 files changed, 121 insertions(+), 101 deletions(-) diff --git a/docs/.vitepress/config/es.ts b/docs/.vitepress/config/es.ts index 6d0b906b..bd50f131 100644 --- a/docs/.vitepress/config/es.ts +++ b/docs/.vitepress/config/es.ts @@ -380,6 +380,10 @@ function sidebarDeveloperDocs(): DefaultTheme.SidebarItem[] { // text: "Trigger", // link: "/es/developer-docs/flags/trigger", // }, + // { + // text: "Remember", + // link: "/developer-docs/flags/remember", + // }, ], }, { @@ -407,6 +411,10 @@ function sidebarDeveloperDocs(): DefaultTheme.SidebarItem[] { // link: "/es/developer-docs/prior-values", // }, // { + // text: "Recall", + // link: "/developer-docs/recall", + // }, + // { // text: "Definición de Valor", // link: "/es/developer-docs/value-definition", // }, diff --git a/docs/.vitepress/config/pt.ts b/docs/.vitepress/config/pt.ts index 5f050a3a..afc9fd84 100644 --- a/docs/.vitepress/config/pt.ts +++ b/docs/.vitepress/config/pt.ts @@ -380,6 +380,10 @@ function sidebarDeveloperDocs(): DefaultTheme.SidebarItem[] { // text: "Trigger", // link: "/pt/developer-docs/flags/trigger", // }, + // { + // text: "Remember", + // link: "/developer-docs/flags/remember", + // }, // ], // }, // { @@ -407,6 +411,10 @@ function sidebarDeveloperDocs(): DefaultTheme.SidebarItem[] { // link: "/pt/developer-docs/prior-values", // }, // { + // text: "Recall", + // link: "/developer-docs/recall", + // }, + // { // text: "Definição de Valores", // link: "/pt/developer-docs/value-definition", // }, diff --git a/docs/developer-docs/condition-syntax.md b/docs/developer-docs/condition-syntax.md index 28879a35..761cd036 100644 --- a/docs/developer-docs/condition-syntax.md +++ b/docs/developer-docs/condition-syntax.md @@ -44,9 +44,10 @@ description: Comprehensive guide to understanding and using condition syntax in | [Invert](/developer-docs/value-definition#binary-inversion) | `~` | `~0xH1234` | ### Special Operands -| Modifier | Representation | Example | -| :----------------------------------------------------------: | :------------: | :--------: | -| [Recall](/developer-docs/recall) | `{recall}` | `{recall}` | + +| Modifier | Representation | Example | +| :------------------------------: | :------------: | :--------: | +| [Recall](/developer-docs/recall) | `{recall}` | `{recall}` | ### Logical Flags diff --git a/docs/developer-docs/flags/remember.md b/docs/developer-docs/flags/remember.md index 9f39380c..37951a00 100644 --- a/docs/developer-docs/flags/remember.md +++ b/docs/developer-docs/flags/remember.md @@ -2,15 +2,16 @@ title: Understanding and Using Remember description: Learn how to effectively use the Remember flag to store values for use later in logic, along with several use cases where this is particularly helpful. --- + # `Remember` -*This feature will be available at the RA_Integration version 1.4 milestone for developers, with support to be added for rcheevos version 11.4 milestone.* +_This feature will be available at the RA_Integration version 1.4 milestone for developers, with support to be added for rcheevos version 11.4 milestone._ The `Remember` condition is chosen in the Flag column of the Asset Editor. Since many of the use cases tend to be fairly complex, it is recommended you be familiar with the rest of the tool kit before studying some of the more complicated examples below. When a condition has the `Remember Flag`, the value of the condition is stored in the `Recall` accumulator. This value may be used in later logic by using the [`Recall`](/developer-docs/recall) operand found in the Type column of either side. -There is one remembered value per *group* (Core, Alt1, Alt2, etc). This value is initialized at the beginning of an evaluation as a unsigned integer with value 0. If you Remember a new value, it will overwrite the previously remembered value. If you remember a Float value, the remembered value will be a floating point value instead of an unsigned integer. Using `Recall` before a value is remembered using the `Remember` condition will generate a warning in the asset editor. +There is one remembered value per _group_ (Core, Alt1, Alt2, etc). This value is initialized at the beginning of an evaluation as a unsigned integer with value 0. If you Remember a new value, it will overwrite the previously remembered value. If you remember a Float value, the remembered value will be a floating point value instead of an unsigned integer. Using `Recall` before a value is remembered using the `Remember` condition will generate a warning in the asset editor. The `Remember` condition is a combining condition and does not break any chain it is in. Conditions that follow it are considered part of the chain. @@ -18,18 +19,18 @@ The `Remember` condition is a combining condition and does not break any chain i ### Simple Example -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | --------- | ----- | ------ | ------ | --- | ----- | ------ | ------- | ----- | -| 1 | SubSource | Delta | 16-bit | 0x1234 | | | | | | -| 2 | Remember | Mem | 16-bit | 0x1234 | | | | | | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | --------- | ----- | ------ | ------ | --- | ---- | ---- | ------- | ---- | +| 1 | SubSource | Delta | 16-bit | 0x1234 | | | | | | +| 2 | Remember | Mem | 16-bit | 0x1234 | | | | | | In this example, the `Delta` value of `0x1234`, the value from the previous frame, is subtracted from the `Mem` value of `0x1234` and Remembered. ### Simple Example - With Operators -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | --------- | ----- | ------ | ------ | --- | ----- | ------ | ------- | ----- | -| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | -------- | ---- | ------ | ------ | --- | ----- | ------ | ------- | ---- | +| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | The Remember condition can optionally take two operands and process a value based on an operator such as multiplication, division, addition, subtraction, and others. In this example, we used the subtraction operator to store the equivalent value as in the first example, but we do it in a single line. @@ -37,122 +38,126 @@ The Remember condition can optionally take two operands and process a value base To use the stored value, specify the `Recall` operator as the Type of operand: -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | -| 2 | | Recall | | | = | Value | | 0x05 | | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | ---- | ------ | ---- | ------ | --- | ----- | ---- | ------- | ---- | +| 2 | | Recall | | | = | Value | | 0x05 | | -In this example it uses the stored value and compares it to a constant value of 5. However, using the stored value once does not show off the main usefulness of `Remember`. +In this example it uses the stored value and compares it to a constant value of 5. However, using the stored value once does not show off the main usefulness of `Remember`. -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | -| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | -| 2 | And Next | Recall | | | = | Value | | 0x05 | | -| 3 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 4 | And Next | Recall | | | = | Value | | 0x14 | | -| 5 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 6 | And Next | Recall | | | = | Value | | 0x14 | | -| 7 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 8 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | -------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | +| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | +| 2 | And Next | Recall | | | = | Value | | 0x05 | | +| 3 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 4 | And Next | Recall | | | = | Value | | 0x14 | | +| 5 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 6 | And Next | Recall | | | = | Value | | 0x14 | | +| 7 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 8 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | -In this example, we are using the stored value in multiple chains within an Add Hits chain without having to recalculate the value each time. Here we are looking for specific increases of `0x1234` to occur while the value of `0x1000` is equal to 3. Perhaps `0x1234` is money, `0x1000` is the current level, and you want to make sure the player collects a gem worth 5 units of money, one worth 20, and one worth 100 in level 3. `Recall` is used here to check all these values of the difference between Mem and Delta without having to recalculate it each time. See the [`Add Hits`](/developer-docs/flags/addhits-subhits) document for more information about how that condition works. +In this example, we are using the stored value in multiple chains within an Add Hits chain without having to recalculate the value each time. Here we are looking for specific increases of `0x1234` to occur while the value of `0x1000` is equal to 3. Perhaps `0x1234` is money, `0x1000` is the current level, and you want to make sure the player collects a gem worth 5 units of money, one worth 20, and one worth 100 in level 3. `Recall` is used here to check all these values of the difference between Mem and Delta without having to recalculate it each time. See the [`Add Hits`](/developer-docs/flags/addhits-subhits) document for more information about how that condition works. ## Interaction with Pause If -Because `Pause If` logic is processed before other logic, `Pause If` logic can only recall values that have been remembered by pause logic. Values remembered during `Pause If` logic continue to be remembered during the remaining logic processing. +Because `Pause If` logic is processed before other logic, `Pause If` logic can only recall values that have been remembered by pause logic. Values remembered during `Pause If` logic continue to be remembered during the remaining logic processing. See the [`Pause If`](/developer-docs/flags/pauseif) document for more information about how that condition works. ### Example of Use with Pause If -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ---------- | ----- | -| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | -| 2 | Pause If | Recall | | | >= | Value | | 0x80000000 | 1 (0) | -| 3 | And Next | Recall | | | = | Value | | 0x05 | | -| 4 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 5 | And Next | Recall | | | = | Value | | 0x14 | | -| 6 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 7 | And Next | Recall | | | = | Value | | 0x14 | | -| 8 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 9 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | -------- | ------ | ------ | ------ | --- | ----- | ------ | ---------- | ----- | +| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | +| 2 | Pause If | Recall | | | >= | Value | | 0x80000000 | 1 (0) | +| 3 | And Next | Recall | | | = | Value | | 0x05 | | +| 4 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 5 | And Next | Recall | | | = | Value | | 0x14 | | +| 6 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 7 | And Next | Recall | | | = | Value | | 0x14 | | +| 8 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 9 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | This example extends the previous [Using the Stored Value](#using-the-stored-value) example by adding a `Pause If` lock if the player loses money\*. Because `Remember` is a combining condition, it links with the following `Pause If` to form a chain and is processed as part of the pause processing, allowing the value to be used by the `Pause If`. The remembered value is available to the remaining logic and can therefore be used by the Add Hits chain. Notes: + - \* Due to the way unsigned math works, the subtraction will underflow back to 0xfffffff at negative one, so any value greater or equal to 0x80000000 is treated as negative). -- Because pause processing happens first, you *could* put conditions 1-2 at the end of the logic and it will still work! The value remembered by the pause logic will still be available to the Add Hits chain. However because this may be a confusing effect, we recommend putting your pause logic at the beginning when using it with `Remember` and `Recall`. +- Because pause processing happens first, you _could_ put conditions 1-2 at the end of the logic and it will still work! The value remembered by the pause logic will still be available to the Add Hits chain. However because this may be a confusing effect, we recommend putting your pause logic at the beginning when using it with `Remember` and `Recall`. ### Example of Incorrect Usage with Pause If -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ---------- | ----- | -| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | -| 2 | And Next | Recall | | | = | Value | | 0x05 | | -| 3 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 4 | And Next | Recall | | | = | Value | | 0x14 | | -| 5 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 6 | And Next | Recall | | | = | Value | | 0x14 | | -| 7 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | -| 8 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | -| 9 | Pause If | Recall | | | >= | Value | | 0x8000000 | 1 (0) | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | -------- | ------ | ------ | ------ | --- | ----- | ------ | --------- | ----- | +| 1 | Remember | Mem | 16-bit | 0x1234 | - | Delta | 16-Bit | 0x1224 | | +| 2 | And Next | Recall | | | = | Value | | 0x05 | | +| 3 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 4 | And Next | Recall | | | = | Value | | 0x14 | | +| 5 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 6 | And Next | Recall | | | = | Value | | 0x14 | | +| 7 | Add Hits | Mem | 8-Bit | 0x1000 | = | Value | | 0x03 | 1 (0) | +| 8 | Measured | Value | | 0x00 | = | Value | | 0x00 | 3 (0) | +| 9 | Pause If | Recall | | | >= | Value | | 0x8000000 | 1 (0) | -In this example, the `Remember` condition is not chained with the `Pause If`. Because of this, the `Pause If` condition will read a value of 0 from the `Recall` operand and never be paused, as a consequence of the pause logic being processed first. Fear not though, as the validation is smart enough to recognize this and will generate a warning on condition 9 that `Recall` is being used in a `Pause If` without a value being remembered in a `Pause If`. +In this example, the `Remember` condition is not chained with the `Pause If`. Because of this, the `Pause If` condition will read a value of 0 from the `Recall` operand and never be paused, as a consequence of the pause logic being processed first. Fear not though, as the validation is smart enough to recognize this and will generate a warning on condition 9 that `Recall` is being used in a `Pause If` without a value being remembered in a `Pause If`. ## Using `Recall` within a `Remember` Condition You can perform math on a remembered value and remember the result: -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | -| 1 | Remember | Mem | 16-bit | 0x1002 | + | Mem | 16-Bit | 0x1004 | | -| 2 | Remember | Recall | | | \* | Value | | 0x03 | | -| 3 | Remember | Recall | | | + | Mem | 16-Bit | 0x1000 | | -| 4 | Remember | Recall | | | % | Value | | 0x05 | | -| 5 | | Recall | | | = | Value | | 0x00 | | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | -------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ---- | +| 1 | Remember | Mem | 16-bit | 0x1002 | + | Mem | 16-Bit | 0x1004 | | +| 2 | Remember | Recall | | | \* | Value | | 0x03 | | +| 3 | Remember | Recall | | | + | Mem | 16-Bit | 0x1000 | | +| 4 | Remember | Recall | | | % | Value | | 0x05 | | +| 5 | | Recall | | | = | Value | | 0x00 | | In this example, let's say you need to calculate the value of `0x1000` + (`0x1002` + `0x1004`) \* 3 and check to see if that is a multiple of 5. You can use `Recall` in a `Remember` condition to operate on the last remembered value and store the new result. Notes: + - If the value of the modulus (`%`) operation is 0, that means there is no remainder from the division by 5, meaning the value is a multiple of 5. ## Using `Remember` for Calculated Pointer Offsets -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | ---------- | ------ | ------ | ------ | --- | ------ | ------ | ------- | ----- | -| 1 | Remember | Mem | 8-bit | 0x0789 | \* | Value | | 0x60 | | -| 2 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | -| 3 | | Mem | 16-bit | 0x08 | > | Value | | 0x00 | | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | ---------- | ---- | ------ | ------ | --- | ------ | ---- | ------- | ---- | +| 1 | Remember | Mem | 8-bit | 0x0789 | \* | Value | | 0x60 | | +| 2 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 3 | | Mem | 16-bit | 0x08 | > | Value | | 0x00 | | -In this example, let's say you have an address that points to a table of data, but in order to know where in the table you want to go, you have to calculate the offset from another source. `0x1234` will be used as the pointer to the table of data. `0x0789` will be the index in the table. The size of data for table entries is `0x60` bytes. And finally, the data we care about is `0x08` bytes into the data's structure. Perhaps this is "Player Health" and the index we are calculating is the index in the table where the "Player Data" exists and we need to check if this value is greater than 0. +In this example, let's say you have an address that points to a table of data, but in order to know where in the table you want to go, you have to calculate the offset from another source. `0x1234` will be used as the pointer to the table of data. `0x0789` will be the index in the table. The size of data for table entries is `0x60` bytes. And finally, the data we care about is `0x08` bytes into the data's structure. Perhaps this is "Player Health" and the index we are calculating is the index in the table where the "Player Data" exists and we need to check if this value is greater than 0. See the [`Add Address`](/developer-docs/flags/addaddress) document for more information about how that condition works. Breakdown of Conditions: -1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table the data is located. -2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" in the table. + +1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table the data is located. +2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" in the table. 3. Offsets from the Address by `0x08`, where it reads the current memory value for the Player's Health with 16-bit size, then uses a comparison to check if it is greater than zero. ## Deeper Chaining of `Remember` Conditions -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | ---------- | ------ | ------ | ------ | --- | ------ | ------ | ------- | ----- | -| 1 | Remember | Mem | 8-bit | 0x0789 | \* | Value | | 0x60 | | -| 2 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | -| 3 | And Next | Mem | 16-bit | 0x08 | < | Delta | | 0x08 | 0 (0) | -| 4 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | -| 5 | And Next | Mem | 8-bit | 0x24 | != | Value | | 0xff | 0 (0) | -| 6 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | -| 7 | Remember | Mem | 16-bit | 0x24 | \* | Value | | 0x60 | | -| 8 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | -| 9 | Reset If | Mem | 8-bit | 0x00 | = | Value | | 0xA7 | 0 (0) | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | ---------- | ---- | ------ | ------ | --- | ------ | ---- | ------- | ----- | +| 1 | Remember | Mem | 8-bit | 0x0789 | \* | Value | | 0x60 | | +| 2 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 3 | And Next | Mem | 16-bit | 0x08 | < | Delta | | 0x08 | 0 (0) | +| 4 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 5 | And Next | Mem | 8-bit | 0x24 | != | Value | | 0xff | 0 (0) | +| 6 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 7 | Remember | Mem | 16-bit | 0x24 | \* | Value | | 0x60 | | +| 8 | AddAddress | Mem | 32-bit | 0x1234 | + | Recall | | | | +| 9 | Reset If | Mem | 8-bit | 0x00 | = | Value | | 0xA7 | 0 (0) | This example shows how using `Remember` continues the chain of And Next conditions and how you can remember new values during the chain without affecting earlier parts of the chain or breaking the chain. In this example, we build on the previous `Add Address` example by chaining it with other conditions. Pretend this is a challenge that fails if the player loses health while holding a certain object. Suppose the player data stores the index of the object at offset `0x24` (the value of which is `0xff` if no object is held). Suppose that index is an index into the same table that holds the player data. This example shows the reset chain that accomplishes this. Suppose that offset `0x00` of object data holds the 8-bit ID of the object. Breakdown of Conditions: -1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table the data is located. -2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" in the table. + +1. Scales the index by the size of the data structure. Now it represents how far from the beginning of the table the data is located. +2. Uses the address for the start of the table and adds to it the stored value. Now this Add Address points to the start of the "Player Data" in the table. 3. Checks if the player lost health, using the offset for health established in the previous example. 4. Re-uses the address for the start of the player data 5. Checks the offset of the held object and makes sure it's not 0xff. @@ -165,26 +170,23 @@ Breakdown of Conditions: ### Interaction With Floats -A remembered value will match the type of data being remembered. If operations are being performed, the first operand usually determines the type, except in the case of division (where the second operand determines the type). If you need to force an integer value to be stored as a float, you can do either of the following: - +A remembered value will match the type of data being remembered. If operations are being performed, the first operand usually determines the type, except in the case of division (where the second operand determines the type). If you need to force an integer value to be stored as a float, you can do either of the following: -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | -------- | ----- | ------ | ------ | --- | ------ | ------ | ------- | ---- | -| 1 | Remember | Float | | 0.0 | + | Mem | 16-Bit | 0x1234 | | - -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | -------- | ----- | ------ | ------ | --- | ------ | ------ | ------- | ---- | -| 1 | Remember | Mem | 16-Bit | 0x1234 | / | Float | | 1.0 | | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | -------- | ----- | ---- | ------ | --- | ---- | ------ | ------- | ---- | +| 1 | Remember | Float | | 0.0 | + | Mem | 16-Bit | 0x1234 | | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | -------- | ---- | ------ | ------ | --- | ----- | ---- | ------- | ---- | +| 1 | Remember | Mem | 16-Bit | 0x1234 | / | Float | | 1.0 | | ### Integer Overflow When the stored value is an integer, all logic being performed is limited to 32-bits. If the total value exceeds 0xFFFFFFFF, there will be an overflow and only the 32 least significant bits will be used in the comparison. +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | -------- | ------ | ------ | ------ | --- | ---------- | ------ | ------- | ---- | +| 1 | Remember | Mem | 32-bit | 0x8010 | + | Mem | 32-Bit | 0x8020 | | +| 2 | | Recall | > | Value | | 0x30000000 | 0 (0) | -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | -------- | ------ | ------ | ------ | --- | ------ | ------ | ---------- | ----- | -| 1 | Remember | Mem | 32-bit | 0x8010 | + | Mem | 32-Bit | 0x8020 | | -| 2 | | Recall | > | Value | | 0x30000000 | 0 (0) | - -If 0x8010 is 0xC0000000 and 0x8020 is 0x54321ABC, then the total will be 0x114321ABC, which is more than 32-bits and will be truncated to 0x14321ABC, which is not more then 0x30000000, so the logic will evaluate false. \ No newline at end of file +If 0x8010 is 0xC0000000 and 0x8020 is 0x54321ABC, then the total will be 0x114321ABC, which is more than 32-bits and will be truncated to 0x14321ABC, which is not more then 0x30000000, so the logic will evaluate false. diff --git a/docs/developer-docs/recall.md b/docs/developer-docs/recall.md index c4c31502..6b7f13ff 100644 --- a/docs/developer-docs/recall.md +++ b/docs/developer-docs/recall.md @@ -2,13 +2,14 @@ title: Understanding and Using Recall description: Learn how to use the Recall operand type to represent a previously remembered value. --- + # `Recall` -*This feature will be available at the RA_Integration version 1.4 milestone for developers, with support to be added for rcheevos version 11.4 milestone.* +_This feature will be available at the RA_Integration version 1.4 milestone for developers, with support to be added for rcheevos version 11.4 milestone._ A `Recall` value is the the last value stored by the [`Remember` Flag](/developer-docs/flags/remember) -The `Recall` accumulator's value is for the current frame's evaluation of logic. It does not persist between evaluations and does not maintain its value for use in a later evaluation. Each group (Core, Alt1, Alt2, etc) has its own separate `Recall` accumulator; a value remembered in one group therefore cannot be recalled in another group. Using `Recall` before a value is remembered in using the `Remember` condition will generate a warning in the asset editor. +The `Recall` accumulator's value is for the current frame's evaluation of logic. It does not persist between evaluations and does not maintain its value for use in a later evaluation. Each group (Core, Alt1, Alt2, etc) has its own separate `Recall` accumulator; a value remembered in one group therefore cannot be recalled in another group. Using `Recall` before a value is remembered in using the `Remember` condition will generate a warning in the asset editor. Examples of how it can be used: @@ -18,8 +19,8 @@ Examples of how it can be used: To use a remembered value, specify the `Recall` operator as the Type of operand: -| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | -| -- | --------- | ------ | ------ | ------ | --- | ----- | ------ | ------- | ----- | -| 2 | | Recall | | | = | Value | | 0x05 | | +| ID | Flag | Type | Size | Memory | Cmp | Type | Size | Mem/Val | Hits | +| --- | ---- | ------ | ---- | ------ | --- | ----- | ---- | ------- | ---- | +| 2 | | Recall | | | = | Value | | 0x05 | | -In this snippet, the recalled value is compared for equality with a constant value of 5. \ No newline at end of file +In this snippet, the recalled value is compared for equality with a constant value of 5.