Dealing with a circular pattern in the computed mark address.

This commit is contained in:
Rob Greene 2018-07-14 16:47:16 -05:00
parent 87c5930b0c
commit fde074ccdc
1 changed files with 21 additions and 0 deletions

View File

@ -1,5 +1,7 @@
package io.github.applecommander.bastools.api.code;
import java.util.HashMap;
/**
* A {@code CodeMark} marks a dynamic address within the output stream. When referenced, it will report the
* most recent address is knows, forcing the generation to run multiple times until it "settles".
@ -16,6 +18,8 @@ package io.github.applecommander.bastools.api.code;
* @author rob
*/
public class CodeMark {
private static final int LOOP_MAX = 10;
private HashMap<Integer,Integer> loopCounter = new HashMap<>();
private int address;
public int getAddress() {
@ -28,6 +32,23 @@ public class CodeMark {
*/
public boolean update(GeneratorState state) {
int currentAddress = state.currentAddress();
loopCounter.merge(currentAddress, 1, (a,b) -> a+b);
if (loopCounter.get(currentAddress) > LOOP_MAX) {
StringBuilder sb = new StringBuilder();
sb.append("A circular pattern in a dynamic address was discovered!\n");
sb.append("This usually indicates that an address was computed to be just below a page boundary.\n");
sb.append("For example, the 0x1000 mark. However, code using that address then pushed the\n");
sb.append("address over the 0x1000 mark, but that triggered the address to be recomputed below\n");
sb.append("the 0x1000 mark. Rinse and repeat.\n");
sb.append("\n");
sb.append("For example, shape tables have a POKE 232,255 when the shape table is at 0xFFF, but the\n");
sb.append("address gets recomputed (due to the 3 digit low address) to be 0x1001, which changes the\n");
sb.append("low address byte to be a single digit. This starts the cascade.\n");
sb.append("\n");
sb.append("Generally, stick a little bit of extra code into the program bypasses this issue.\n");
sb.append("(Sorry, there is no elegant solution at this time. Pull requests are welcome!).\n");
throw new IllegalStateException(sb.toString());
}
try {
return currentAddress != address;
} finally {