Implementing native breakpoint interface
This commit is contained in:
		
							parent
							
								
									2d048a74c0
								
							
						
					
					
						commit
						826e921dac
					
				
							
								
								
									
										2
									
								
								makefile
								
								
								
								
							
							
						
						
									
										2
									
								
								makefile
								
								
								
								
							| 
						 | 
					@ -10,7 +10,7 @@ default:
 | 
				
			||||||
	@echo $(include_linux)
 | 
						@echo $(include_linux)
 | 
				
			||||||
	@echo "Planet Virtual Boy Emulator"
 | 
						@echo "Planet Virtual Boy Emulator"
 | 
				
			||||||
	@echo "  https://www.planetvb.com/"
 | 
						@echo "  https://www.planetvb.com/"
 | 
				
			||||||
	@echo "  October 13, 2020"
 | 
						@echo "  October 16, 2020"
 | 
				
			||||||
	@echo
 | 
						@echo
 | 
				
			||||||
	@echo "Intended build environment: Debian i386 or amd64"
 | 
						@echo "Intended build environment: Debian i386 or amd64"
 | 
				
			||||||
	@echo "  gcc-multilib"
 | 
						@echo "  gcc-multilib"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,7 +51,7 @@ public class Main {
 | 
				
			||||||
        // Begin application operations
 | 
					        // Begin application operations
 | 
				
			||||||
        new App(useNative);
 | 
					        new App(useNative);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
        var brk = new Breakpoint(null);
 | 
					        var brk = new Breakpoint(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String exp =
 | 
					        String exp =
 | 
				
			||||||
| 
						 | 
					@ -74,6 +74,7 @@ public class Main {
 | 
				
			||||||
            brk.getErrorPosition(Breakpoint.ADDRESS) + ":"  +
 | 
					            brk.getErrorPosition(Breakpoint.ADDRESS) + ":"  +
 | 
				
			||||||
            brk.getErrorText    (Breakpoint.ADDRESS)
 | 
					            brk.getErrorText    (Breakpoint.ADDRESS)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -612,13 +612,13 @@ static void evalUnary(Vue *vue, int32_t id, int32_t *stack, int32_t size) {
 | 
				
			||||||
int32_t evaluate(Vue *vue, Breakpoint *brk, int32_t *stack) {
 | 
					int32_t evaluate(Vue *vue, Breakpoint *brk, int32_t *stack) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The condition is empty
 | 
					    // The condition is empty
 | 
				
			||||||
    if (brk->numCondition == 0)
 | 
					    if (brk->numTokens == 0)
 | 
				
			||||||
        return brk->enabled;
 | 
					        return brk->enabled;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Process tokens
 | 
					    // Process tokens
 | 
				
			||||||
    int size = 0;
 | 
					    int size = 0;
 | 
				
			||||||
    for (int x = 0; x < brk->numCondition; x++) {
 | 
					    for (int x = 0; x < brk->numTokens; x++) {
 | 
				
			||||||
        Token *tok = &brk->condition[x];
 | 
					        Token *tok = &brk->tokens[x];
 | 
				
			||||||
        switch (tok->type) {
 | 
					        switch (tok->type) {
 | 
				
			||||||
            case BINARY: size =
 | 
					            case BINARY: size =
 | 
				
			||||||
                evalBinary(     tok->value, stack, size); continue;
 | 
					                evalBinary(     tok->value, stack, size); continue;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,15 +7,16 @@ import java.util.*;
 | 
				
			||||||
public class Breakpoint {
 | 
					public class Breakpoint {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Instance fields
 | 
					    // Instance fields
 | 
				
			||||||
    private int[][]  addresses;   // Applicable address ranges
 | 
					    private String   addresses;   // Un-processed address ranges
 | 
				
			||||||
    private String   addressText; // Un-processed address ranges
 | 
					 | 
				
			||||||
    private String   condition;   // Un-processed condition
 | 
					    private String   condition;   // Un-processed condition
 | 
				
			||||||
    private int[]    errCode;     // Error codes
 | 
					    private int[]    errCode;     // Error codes
 | 
				
			||||||
    private int[]    errPosition; // Character position of errors
 | 
					    private int[]    errPosition; // Character position of errors
 | 
				
			||||||
    private String[] errText;     // Offending error text
 | 
					    private String[] errText;     // Offending error text
 | 
				
			||||||
 | 
					    private int      hooks;       // Applied breakpoint types
 | 
				
			||||||
    private boolean  isEnabled;   // Breakpoint is active
 | 
					    private boolean  isEnabled;   // Breakpoint is active
 | 
				
			||||||
    private String   name;        // Display name
 | 
					    private String   name;        // Display name
 | 
				
			||||||
    private Token[]  tokens;      // Evaluation tokens
 | 
					    private int[][]  ranges;      // Applicable address ranges
 | 
				
			||||||
 | 
					    private Token[]  tokens;      // Condition tokens
 | 
				
			||||||
    private Vue      vue;         // Containing emulation context
 | 
					    private Vue      vue;         // Containing emulation context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +40,12 @@ public class Breakpoint {
 | 
				
			||||||
    public static final int ADDRESS   = 0;
 | 
					    public static final int ADDRESS   = 0;
 | 
				
			||||||
    public static final int CONDITION = 1;
 | 
					    public static final int CONDITION = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Breakpoint hooks
 | 
				
			||||||
 | 
					    private static final int EXCEPTION = 0x00000001;
 | 
				
			||||||
 | 
					    private static final int EXECUTE   = 0x00000002;
 | 
				
			||||||
 | 
					    private static final int READ      = 0x00000004;
 | 
				
			||||||
 | 
					    private static final int WRITE     = 0x00000008;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Token types
 | 
					    // Token types
 | 
				
			||||||
    private static final int BINARY  = 4;
 | 
					    private static final int BINARY  = 4;
 | 
				
			||||||
    private static final int CLOSE   = 6;
 | 
					    private static final int CLOSE   = 6;
 | 
				
			||||||
| 
						 | 
					@ -296,6 +303,11 @@ public class Breakpoint {
 | 
				
			||||||
            this.type  = type;
 | 
					            this.type  = type;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Retrieve the applicable serialized "value"
 | 
				
			||||||
 | 
					        int flatten() {
 | 
				
			||||||
 | 
					            return type == FLOAT || type == WORD ? value : id;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -306,13 +318,13 @@ public class Breakpoint {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Default constructor
 | 
					    // Default constructor
 | 
				
			||||||
    public Breakpoint(Vue vue) {
 | 
					    public Breakpoint(Vue vue) {
 | 
				
			||||||
        addresses   = new int[0][];
 | 
					        addresses   = "";
 | 
				
			||||||
        addressText = "";
 | 
					 | 
				
			||||||
        condition   = "";
 | 
					        condition   = "";
 | 
				
			||||||
        errCode     = new int   [] { NONE, NONE };
 | 
					        errCode     = new int   [] { NONE, NONE };
 | 
				
			||||||
        errPosition = new int   [] {    0,    0 };
 | 
					        errPosition = new int   [] {    0,    0 };
 | 
				
			||||||
        errText     = new String[] {   "",   "" };
 | 
					        errText     = new String[] {   "",   "" };
 | 
				
			||||||
        name        = "";
 | 
					        name        = "";
 | 
				
			||||||
 | 
					        ranges      = new int[0][];
 | 
				
			||||||
        tokens      = new Token[0];
 | 
					        tokens      = new Token[0];
 | 
				
			||||||
        this.vue    = vue;
 | 
					        this.vue    = vue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -378,8 +390,8 @@ public class Breakpoint {
 | 
				
			||||||
    // Produce a string representation of the internal address ranges
 | 
					    // Produce a string representation of the internal address ranges
 | 
				
			||||||
    public String test() {
 | 
					    public String test() {
 | 
				
			||||||
        var ret = new StringBuilder();
 | 
					        var ret = new StringBuilder();
 | 
				
			||||||
        for (int x = 0; x < addresses.length; x++) {
 | 
					        for (int x = 0; x < ranges.length; x++) {
 | 
				
			||||||
            var range = addresses[x];
 | 
					            var range = ranges[x];
 | 
				
			||||||
            if (x > 0)
 | 
					            if (x > 0)
 | 
				
			||||||
                ret.append("\n");
 | 
					                ret.append("\n");
 | 
				
			||||||
            ret.append(String.format("%08X", range[0]));
 | 
					            ret.append(String.format("%08X", range[0]));
 | 
				
			||||||
| 
						 | 
					@ -396,7 +408,7 @@ public class Breakpoint {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Retrieve the most recent input addresses
 | 
					    // Retrieve the most recent input addresses
 | 
				
			||||||
    public String getAddresses() {
 | 
					    public String getAddresses() {
 | 
				
			||||||
        return addressText;
 | 
					        return addresses;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Retrieve the most recent input condition
 | 
					    // Retrieve the most recent input condition
 | 
				
			||||||
| 
						 | 
					@ -419,6 +431,26 @@ public class Breakpoint {
 | 
				
			||||||
        return type < 0 || type > 1 ? null : errText[type];
 | 
					        return type < 0 || type > 1 ? null : errText[type];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve whether the breakpoint hooks exceptions
 | 
				
			||||||
 | 
					    public boolean getException() {
 | 
				
			||||||
 | 
					        return (hooks & EXCEPTION) != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve whether the breakpoint hooks executions
 | 
				
			||||||
 | 
					    public boolean getExecute() {
 | 
				
			||||||
 | 
					        return (hooks & EXECUTE) != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve whether the breakpoint hooks reads
 | 
				
			||||||
 | 
					    public boolean getRead() {
 | 
				
			||||||
 | 
					        return (hooks & READ) != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve whether the breakpoint hooks writes
 | 
				
			||||||
 | 
					    public boolean getWrite() {
 | 
				
			||||||
 | 
					        return (hooks & WRITE) != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Retrieve the display name
 | 
					    // Retrieve the display name
 | 
				
			||||||
    public String getName() {
 | 
					    public String getName() {
 | 
				
			||||||
        return name;
 | 
					        return name;
 | 
				
			||||||
| 
						 | 
					@ -438,7 +470,7 @@ public class Breakpoint {
 | 
				
			||||||
        int     x      = 0;    // Input position
 | 
					        int     x      = 0;    // Input position
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Configure instance fields
 | 
					        // Configure instance fields
 | 
				
			||||||
        addressText = addresses == null ? addresses = "" : addresses;
 | 
					        this.addresses = addresses == null ? addresses = "" : addresses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Parse the input
 | 
					        // Parse the input
 | 
				
			||||||
        var chars = (addresses + " ").toCharArray();
 | 
					        var chars = (addresses + " ").toCharArray();
 | 
				
			||||||
| 
						 | 
					@ -485,7 +517,7 @@ public class Breakpoint {
 | 
				
			||||||
                    errPosition[ADDRESS] = start + 1;
 | 
					                    errPosition[ADDRESS] = start + 1;
 | 
				
			||||||
                    errText    [ADDRESS] = text;
 | 
					                    errText    [ADDRESS] = text;
 | 
				
			||||||
                    if (vue != null)
 | 
					                    if (vue != null)
 | 
				
			||||||
                        vue.update(this);
 | 
					                        vue.updateRanges(this);
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -535,7 +567,7 @@ public class Breakpoint {
 | 
				
			||||||
            errPosition[ADDRESS] = x + 1;
 | 
					            errPosition[ADDRESS] = x + 1;
 | 
				
			||||||
            errText    [ADDRESS] = Character.toString(c);
 | 
					            errText    [ADDRESS] = Character.toString(c);
 | 
				
			||||||
            if (vue != null)
 | 
					            if (vue != null)
 | 
				
			||||||
                vue.update(this);
 | 
					                vue.updateRanges(this);
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        } // x
 | 
					        } // x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -545,7 +577,7 @@ public class Breakpoint {
 | 
				
			||||||
            errPosition[ADDRESS] = x + 1;
 | 
					            errPosition[ADDRESS] = x + 1;
 | 
				
			||||||
            errText    [ADDRESS] = "";
 | 
					            errText    [ADDRESS] = "";
 | 
				
			||||||
            if (vue != null)
 | 
					            if (vue != null)
 | 
				
			||||||
                vue.update(this);
 | 
					                vue.updateRanges(this);
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -554,13 +586,12 @@ public class Breakpoint {
 | 
				
			||||||
            ranges.add(new int[] { first, first });
 | 
					            ranges.add(new int[] { first, first });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Parsing was successful
 | 
					        // Parsing was successful
 | 
				
			||||||
        this.addresses   = ranges.toArray(new int[ranges.size()][]);
 | 
					        this.ranges = ranges.toArray(new int[ranges.size()][]);
 | 
				
			||||||
        this.addressText = addresses;
 | 
					 | 
				
			||||||
        errCode    [ADDRESS] = NONE;
 | 
					        errCode    [ADDRESS] = NONE;
 | 
				
			||||||
        errPosition[ADDRESS] = 0;
 | 
					        errPosition[ADDRESS] = 0;
 | 
				
			||||||
        errText    [ADDRESS] = "";
 | 
					        errText    [ADDRESS] = "";
 | 
				
			||||||
        if (vue != null)
 | 
					        if (vue != null)
 | 
				
			||||||
            vue.update(this);
 | 
					            vue.updateRanges(this);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -578,7 +609,7 @@ public class Breakpoint {
 | 
				
			||||||
        var tokens = parse();
 | 
					        var tokens = parse();
 | 
				
			||||||
        if (tokens == null || !validate(tokens)) {
 | 
					        if (tokens == null || !validate(tokens)) {
 | 
				
			||||||
            if (vue != null)
 | 
					            if (vue != null)
 | 
				
			||||||
                vue.update(this);
 | 
					                vue.updateTokens(this);
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        tree(tokens);
 | 
					        tree(tokens);
 | 
				
			||||||
| 
						 | 
					@ -586,7 +617,7 @@ public class Breakpoint {
 | 
				
			||||||
        // The expression is empty
 | 
					        // The expression is empty
 | 
				
			||||||
        if (tokens.size() == 0) {
 | 
					        if (tokens.size() == 0) {
 | 
				
			||||||
            if (vue != null)
 | 
					            if (vue != null)
 | 
				
			||||||
                vue.update(this);
 | 
					                vue.updateTokens(this);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -616,15 +647,48 @@ public class Breakpoint {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The expression was successfully parsed
 | 
					        // The expression was successfully parsed
 | 
				
			||||||
        if (vue != null)
 | 
					        if (vue != null)
 | 
				
			||||||
            vue.update(this);
 | 
					            vue.updateTokens(this);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Specify whether the breakpoint is enabled
 | 
				
			||||||
 | 
					    public void setEnabled(boolean enabled) {
 | 
				
			||||||
 | 
					        isEnabled = enabled;
 | 
				
			||||||
 | 
					        if (vue != null)
 | 
				
			||||||
 | 
					            vue.updateState(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Specify whether the breakpoint hooks exceptions
 | 
				
			||||||
 | 
					    public void setException(boolean hook) {
 | 
				
			||||||
 | 
					        hooks = hook ? hooks | EXCEPTION : hooks & ~EXCEPTION;
 | 
				
			||||||
 | 
					        if (vue != null)
 | 
				
			||||||
 | 
					            vue.updateState(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Specify whether the breakpoint hooks executions
 | 
				
			||||||
 | 
					    public void setExecute(boolean hook) {
 | 
				
			||||||
 | 
					        hooks = hook ? hooks | EXECUTE : hooks & ~EXECUTE;
 | 
				
			||||||
 | 
					        if (vue != null)
 | 
				
			||||||
 | 
					            vue.updateState(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Specify the display name
 | 
					    // Specify the display name
 | 
				
			||||||
    public void setName(String name) {
 | 
					    public void setName(String name) {
 | 
				
			||||||
        this.name = name == null ? "" : name;
 | 
					        this.name = name == null ? "" : name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Specify whether the breakpoint hooks reads
 | 
				
			||||||
 | 
					    public void setRead(boolean hook) {
 | 
				
			||||||
 | 
					        hooks = hook ? hooks | READ : hooks & ~READ;
 | 
				
			||||||
        if (vue != null)
 | 
					        if (vue != null)
 | 
				
			||||||
            vue.update(this);
 | 
					            vue.updateState(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Specify whether the breakpoint hooks reads
 | 
				
			||||||
 | 
					    public void setWrite(boolean hook) {
 | 
				
			||||||
 | 
					        hooks = hook ? hooks | WRITE : hooks & ~WRITE;
 | 
				
			||||||
 | 
					        if (vue != null)
 | 
				
			||||||
 | 
					            vue.updateState(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -634,7 +698,7 @@ public class Breakpoint {
 | 
				
			||||||
    ///////////////////////////////////////////////////////////////////////////
 | 
					    ///////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate the condition for a Java emulation context
 | 
					    // Evaluate the condition for a Java emulation context
 | 
				
			||||||
    boolean evaluate(JavaVue vue, int[] stack) {
 | 
					    boolean evaluate(int[] stack) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The condition is empty
 | 
					        // The condition is empty
 | 
				
			||||||
        if (tokens.length == 0)
 | 
					        if (tokens.length == 0)
 | 
				
			||||||
| 
						 | 
					@ -645,11 +709,11 @@ public class Breakpoint {
 | 
				
			||||||
        for (var tok : tokens) {
 | 
					        for (var tok : tokens) {
 | 
				
			||||||
            switch (tok.type) {
 | 
					            switch (tok.type) {
 | 
				
			||||||
                case BINARY: size =
 | 
					                case BINARY: size =
 | 
				
			||||||
                    evalBinary(     tok.id, stack, size); continue;
 | 
					                    evalBinary(tok.id, stack, size); continue;
 | 
				
			||||||
                case SYMBOL: size =
 | 
					                case SYMBOL: size =
 | 
				
			||||||
                    evalSymbol(vue, tok.id, stack, size); continue;
 | 
					                    evalSymbol(tok.id, stack, size); continue;
 | 
				
			||||||
                case UNARY :
 | 
					                case UNARY :
 | 
				
			||||||
                    evalUnary (vue, tok.id, stack, size); continue;
 | 
					                    evalUnary (tok.id, stack, size); continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            stack[size++] = tok.type;
 | 
					            stack[size++] = tok.type;
 | 
				
			||||||
            stack[size++] = tok.value;
 | 
					            stack[size++] = tok.value;
 | 
				
			||||||
| 
						 | 
					@ -676,6 +740,43 @@ public class Breakpoint {
 | 
				
			||||||
        return max;
 | 
					        return max;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Produce a one-dimensional array from the address ranges
 | 
				
			||||||
 | 
					    int[] flattenRanges() {
 | 
				
			||||||
 | 
					        var ret = new int[ranges.length * 2];
 | 
				
			||||||
 | 
					        for (int x = 0; x < ranges.length; x++) {
 | 
				
			||||||
 | 
					            var range = ranges[x];
 | 
				
			||||||
 | 
					            ret[x / 2    ] = range[0];
 | 
				
			||||||
 | 
					            ret[x / 2 + 1] = range[1];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Produce a one-dimensional array from the condition tokens
 | 
				
			||||||
 | 
					    int[] flattenTokens() {
 | 
				
			||||||
 | 
					        var ret = new int[tokens.length * 2];
 | 
				
			||||||
 | 
					        for (int x = 0; x < tokens.length; x++) {
 | 
				
			||||||
 | 
					            var token = tokens[x];
 | 
				
			||||||
 | 
					            ret[x / 2    ] = token.type;
 | 
				
			||||||
 | 
					            ret[x / 2 + 1] = token.flatten();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve the bit mask for enabled hooks
 | 
				
			||||||
 | 
					    int getHooks() {
 | 
				
			||||||
 | 
					        return hooks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve the list of address ranges
 | 
				
			||||||
 | 
					    int[][] getRanges() {
 | 
				
			||||||
 | 
					        return ranges;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve the list of condition tokens
 | 
				
			||||||
 | 
					    Token[] getTokens() {
 | 
				
			||||||
 | 
					        return tokens;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The breakpoint is being removed from its emulation context
 | 
					    // The breakpoint is being removed from its emulation context
 | 
				
			||||||
    void remove() {
 | 
					    void remove() {
 | 
				
			||||||
        vue = null;
 | 
					        vue = null;
 | 
				
			||||||
| 
						 | 
					@ -1155,8 +1256,9 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate a functional symbol
 | 
					    // Evaluate a functional symbol
 | 
				
			||||||
    private static int evalSymbol(JavaVue vue, int id, int[] stack, int size) {
 | 
					    private int evalSymbol(int id, int[] stack, int size) {
 | 
				
			||||||
        int ret = 0;
 | 
					        int ret = 0;
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        if (id == Vue.PC)
 | 
					        if (id == Vue.PC)
 | 
				
			||||||
            ret = vue.cpu.pc;
 | 
					            ret = vue.cpu.pc;
 | 
				
			||||||
        else if (id >= 200)
 | 
					        else if (id >= 200)
 | 
				
			||||||
| 
						 | 
					@ -1166,20 +1268,20 @@ public class Breakpoint {
 | 
				
			||||||
        else if (vue.cpu.stage == CPU.EXCEPTION && id == CODE)
 | 
					        else if (vue.cpu.stage == CPU.EXCEPTION && id == CODE)
 | 
				
			||||||
            ret = vue.cpu.exception.code;
 | 
					            ret = vue.cpu.exception.code;
 | 
				
			||||||
        else if (vue.cpu.stage == CPU.EXECUTE) switch (id) {
 | 
					        else if (vue.cpu.stage == CPU.EXECUTE) switch (id) {
 | 
				
			||||||
            case ADDRESS  : ret = evalAddress   (vue); break;
 | 
					            case ADDRESS  : ret = evalAddress      (); break;
 | 
				
			||||||
            case COND     : ret = evalCond      (vue); break;
 | 
					            case COND     : ret = evalCond         (); break;
 | 
				
			||||||
            case DISP     : ret = evalDisp      (vue); break;
 | 
					            case DISP     : ret = evalDisp         (); break;
 | 
				
			||||||
            case FORMAT   : ret = vue.cpu.inst.format; break;
 | 
					            case FORMAT   : ret = vue.cpu.inst.format; break;
 | 
				
			||||||
            case ID       : ret = vue.cpu.inst.id    ; break;
 | 
					            case ID       : ret = vue.cpu.inst.id    ; break;
 | 
				
			||||||
            case IMM      : ret = evalImm       (vue); break;
 | 
					            case IMM      : ret = evalImm          (); break;
 | 
				
			||||||
            case OPCODE   : ret = vue.cpu.inst.opcode; break;
 | 
					            case OPCODE   : ret = vue.cpu.inst.opcode; break;
 | 
				
			||||||
            case REG1     : ret = evalReg1      (vue); break;
 | 
					            case REG1     : ret = evalReg1         (); break;
 | 
				
			||||||
            case REG2     : ret = evalReg2      (vue); break;
 | 
					            case REG2     : ret = evalReg2         (); break;
 | 
				
			||||||
            case REGID    : ret = evalRegId     (vue); break;
 | 
					            case REGID    : ret = evalRegId        (); break;
 | 
				
			||||||
            case SIZE     : ret = vue.cpu.inst.size  ; break;
 | 
					            case SIZE     : ret = vue.cpu.inst.size  ; break;
 | 
				
			||||||
            case SUBOPCODE: ret = evalSubopcode (vue); break;
 | 
					            case SUBOPCODE: ret = evalSubopcode    (); break;
 | 
				
			||||||
            case VALUE    : ret = evalValue     (vue); break;
 | 
					            case VALUE    : ret = evalValue        (); break;
 | 
				
			||||||
            case VECTOR   : ret = evalVector    (vue); break;
 | 
					            case VECTOR   : ret = evalVector       (); break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        stack[size++] = WORD;
 | 
					        stack[size++] = WORD;
 | 
				
			||||||
        stack[size++] = ret;
 | 
					        stack[size++] = ret;
 | 
				
			||||||
| 
						 | 
					@ -1187,7 +1289,7 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate a unary operator
 | 
					    // Evaluate a unary operator
 | 
				
			||||||
    private static void evalUnary(JavaVue vue, int id, int[] stack, int size) {
 | 
					    private void evalUnary(int id, int[] stack, int size) {
 | 
				
			||||||
        int     type   = stack[size - 2];
 | 
					        int     type   = stack[size - 2];
 | 
				
			||||||
        int     value  = stack[size - 1];
 | 
					        int     value  = stack[size - 1];
 | 
				
			||||||
        boolean isWord = type == WORD;
 | 
					        boolean isWord = type == WORD;
 | 
				
			||||||
| 
						 | 
					@ -1201,7 +1303,7 @@ public class Breakpoint {
 | 
				
			||||||
            case FLOAT      : value = evalFloat     (isWord, value);
 | 
					            case FLOAT      : value = evalFloat     (isWord, value);
 | 
				
			||||||
                type = FLOAT; break;
 | 
					                type = FLOAT; break;
 | 
				
			||||||
            case FLOOR      : value = evalFloor     (isWord, value); break;
 | 
					            case FLOOR      : value = evalFloor     (isWord, value); break;
 | 
				
			||||||
            case READ_WORD  : value = evalReadWord  (isWord, value, vue);
 | 
					            case READ_WORD  : value = evalReadWord  (isWord, value);
 | 
				
			||||||
                type = WORD ; break;
 | 
					                type = WORD ; break;
 | 
				
			||||||
            case ROUND      : value = evalRound     (isWord, value); break;
 | 
					            case ROUND      : value = evalRound     (isWord, value); break;
 | 
				
			||||||
            case TRUNC      : value = evalTrunc     (isWord, value); break;
 | 
					            case TRUNC      : value = evalTrunc     (isWord, value); break;
 | 
				
			||||||
| 
						 | 
					@ -1414,7 +1516,8 @@ public class Breakpoint {
 | 
				
			||||||
    ///////////////////////////////////////////////////////////////////////////
 | 
					    ///////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate address
 | 
					    // Evaluate address
 | 
				
			||||||
    private static int evalAddress(JavaVue vue) {
 | 
					    private int evalAddress() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        if (vue.cpu.inst.format == 6)
 | 
					        if (vue.cpu.inst.format == 6)
 | 
				
			||||||
            return vue.cpu.program[vue.cpu.inst.reg1] + vue.cpu.inst.disp;
 | 
					            return vue.cpu.program[vue.cpu.inst.reg1] + vue.cpu.inst.disp;
 | 
				
			||||||
        switch (vue.cpu.inst.id) {
 | 
					        switch (vue.cpu.inst.id) {
 | 
				
			||||||
| 
						 | 
					@ -1429,7 +1532,8 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate cond
 | 
					    // Evaluate cond
 | 
				
			||||||
    private static int evalCond(JavaVue vue) {
 | 
					    private int evalCond() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        switch (vue.cpu.inst.id) {
 | 
					        switch (vue.cpu.inst.id) {
 | 
				
			||||||
            case Vue.BCOND: return vue.cpu.inst.cond;
 | 
					            case Vue.BCOND: return vue.cpu.inst.cond;
 | 
				
			||||||
            case Vue.SETF : return vue.cpu.inst.imm;
 | 
					            case Vue.SETF : return vue.cpu.inst.imm;
 | 
				
			||||||
| 
						 | 
					@ -1438,7 +1542,8 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate disp
 | 
					    // Evaluate disp
 | 
				
			||||||
    private static int evalDisp(JavaVue vue) {
 | 
					    private int evalDisp() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        switch (vue.cpu.inst.format) {
 | 
					        switch (vue.cpu.inst.format) {
 | 
				
			||||||
            case 3: case 4: case 6: return vue.cpu.inst.disp;
 | 
					            case 3: case 4: case 6: return vue.cpu.inst.disp;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1446,7 +1551,8 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate imm
 | 
					    // Evaluate imm
 | 
				
			||||||
    private static int evalImm(JavaVue vue) {
 | 
					    private int evalImm() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        switch (vue.cpu.inst.format) {
 | 
					        switch (vue.cpu.inst.format) {
 | 
				
			||||||
            case 2: case 5: return vue.cpu.inst.imm;
 | 
					            case 2: case 5: return vue.cpu.inst.imm;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1454,7 +1560,8 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate reg1
 | 
					    // Evaluate reg1
 | 
				
			||||||
    private static int evalReg1(JavaVue vue) {
 | 
					    private int evalReg1() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        switch (vue.cpu.inst.format) {
 | 
					        switch (vue.cpu.inst.format) {
 | 
				
			||||||
            case 1: case 5: case 6: case 7: return vue.cpu.inst.reg1;
 | 
					            case 1: case 5: case 6: case 7: return vue.cpu.inst.reg1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1462,7 +1569,8 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate reg2
 | 
					    // Evaluate reg2
 | 
				
			||||||
    private static int evalReg2(JavaVue vue) {
 | 
					    private int evalReg2() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        switch (vue.cpu.inst.format) {
 | 
					        switch (vue.cpu.inst.format) {
 | 
				
			||||||
            case 1: case 2: case 5: case 6: case 7: return vue.cpu.inst.reg2;
 | 
					            case 1: case 2: case 5: case 6: case 7: return vue.cpu.inst.reg2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1470,7 +1578,8 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate regid
 | 
					    // Evaluate regid
 | 
				
			||||||
    private static int evalRegId(JavaVue vue) {
 | 
					    private int evalRegId() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        switch (vue.cpu.inst.id) {
 | 
					        switch (vue.cpu.inst.id) {
 | 
				
			||||||
            case Vue.LDSR: case Vue.STSR: return vue.cpu.inst.imm;
 | 
					            case Vue.LDSR: case Vue.STSR: return vue.cpu.inst.imm;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1478,7 +1587,8 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate subopcode
 | 
					    // Evaluate subopcode
 | 
				
			||||||
    private static int evalSubopcode(JavaVue vue) {
 | 
					    private int evalSubopcode() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        switch (vue.cpu.inst.opcode) {
 | 
					        switch (vue.cpu.inst.opcode) {
 | 
				
			||||||
            case 0x1F: return vue.cpu.inst.imm;
 | 
					            case 0x1F: return vue.cpu.inst.imm;
 | 
				
			||||||
            case 0x3E: return vue.cpu.inst.subopcode;
 | 
					            case 0x3E: return vue.cpu.inst.subopcode;
 | 
				
			||||||
| 
						 | 
					@ -1487,12 +1597,14 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate value
 | 
					    // Evaluate value
 | 
				
			||||||
    private static int evalValue(JavaVue vue) {
 | 
					    private int evalValue() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        return vue.cpu.inst.format == 6 ? vue.cpu.access.value : 0;
 | 
					        return vue.cpu.inst.format == 6 ? vue.cpu.access.value : 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate vector
 | 
					    // Evaluate vector
 | 
				
			||||||
    private static int evalVector(JavaVue vue) {
 | 
					    private int evalVector() {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        return vue.cpu.inst.id == Vue.TRAP ? vue.cpu.inst.imm : 0;
 | 
					        return vue.cpu.inst.id == Vue.TRAP ? vue.cpu.inst.imm : 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1533,7 +1645,8 @@ public class Breakpoint {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Evaluate []
 | 
					    // Evaluate []
 | 
				
			||||||
    private static int evalReadWord(boolean isWord, int value, JavaVue vue) {
 | 
					    private int evalReadWord(boolean isWord, int value) {
 | 
				
			||||||
 | 
					        var vue = (JavaVue) this.vue;
 | 
				
			||||||
        return vue.read(isWord ? value : toWord(asFloat(value)), Vue.S32);
 | 
					        return vue.read(isWord ? value : toWord(asFloat(value)), Vue.S32);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,19 +22,27 @@ static const int TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
 | 
				
			||||||
//                                   Types                                   //
 | 
					//                                   Types                                   //
 | 
				
			||||||
///////////////////////////////////////////////////////////////////////////////
 | 
					///////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Breakpoint token
 | 
					// Breakpoint address range
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    int32_t type;
 | 
					    int32_t start; // First address, inclusive
 | 
				
			||||||
    int32_t value;
 | 
					    int32_t end;   // Last address, inclusive
 | 
				
			||||||
 | 
					} Range;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Breakpoint condition token
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    int32_t type;  // Token category
 | 
				
			||||||
 | 
					    int32_t value; // Operator or symbol ID, or literal value
 | 
				
			||||||
} Token;
 | 
					} Token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Precompiled breakpoint
 | 
					// Precompiled breakpoint
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    int32_t  enabled;      // The breakpoint is enabled
 | 
					    int32_t  depth;     // Maximum number of stack entries
 | 
				
			||||||
    int32_t  numAddresses; // Number of address ranges
 | 
					    int32_t  enabled;   // The breakpoint is enabled
 | 
				
			||||||
    int32_t  numCondition; // Number of tokens in condition
 | 
					    int32_t  hooks;     // Events hooked by the breakpoint
 | 
				
			||||||
    int32_t *addresses;    // Address ranges
 | 
					    int32_t  numRanges; // Number of address ranges
 | 
				
			||||||
    Token   *condition;    // Condition tokens in RPN order
 | 
					    int32_t  numTokens; // Number of condition tokens
 | 
				
			||||||
 | 
					    Range   *ranges;    // Address ranges
 | 
				
			||||||
 | 
					    Token   *tokens;    // Condition tokens in RPN order
 | 
				
			||||||
} Breakpoint;
 | 
					} Breakpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Core context state type
 | 
					// Core context state type
 | 
				
			||||||
| 
						 | 
					@ -67,7 +75,7 @@ typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
///////////////////////////////////////////////////////////////////////////////
 | 
					///////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
//                             Method Functions                              //
 | 
					//                              Public Methods                               //
 | 
				
			||||||
///////////////////////////////////////////////////////////////////////////////
 | 
					///////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Native constructor
 | 
					// Native constructor
 | 
				
			||||||
| 
						 | 
					@ -83,7 +91,18 @@ JNIEXPORT jlong JNICALL Java_vue_NativeVue_construct
 | 
				
			||||||
// Release any used resources
 | 
					// Release any used resources
 | 
				
			||||||
JNIEXPORT void JNICALL Java_vue_NativeVue_dispose
 | 
					JNIEXPORT void JNICALL Java_vue_NativeVue_dispose
 | 
				
			||||||
  (JNIEnv *env, jobject vue, jlong handle) {
 | 
					  (JNIEnv *env, jobject vue, jlong handle) {
 | 
				
			||||||
    Core *core = *(Core **)&handle;
 | 
					    Core       *core = *(Core **)&handle;
 | 
				
			||||||
 | 
					    Breakpoint *brk; // Handle to breakpoint
 | 
				
			||||||
 | 
					    int        x;    // Iterator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Delete breakpoints
 | 
				
			||||||
 | 
					    for (x = 0; x < core->numBreakpoints; x++) {
 | 
				
			||||||
 | 
					        brk = &core->breakpoints[x];
 | 
				
			||||||
 | 
					        if (brk->ranges != NULL) free(brk->ranges);
 | 
				
			||||||
 | 
					        if (brk->tokens != NULL) free(brk->tokens);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Delete core
 | 
				
			||||||
    if (core->breakpoints != NULL) free(core->breakpoints);
 | 
					    if (core->breakpoints != NULL) free(core->breakpoints);
 | 
				
			||||||
    if (core->stack       != NULL) free(core->stack      );
 | 
					    if (core->stack       != NULL) free(core->stack      );
 | 
				
			||||||
    if (core->vue.pak.rom != NULL) free(core->vue.pak.rom);
 | 
					    if (core->vue.pak.rom != NULL) free(core->vue.pak.rom);
 | 
				
			||||||
| 
						 | 
					@ -234,3 +253,108 @@ JNIEXPORT jboolean JNICALL Java_vue_NativeVue_writeBytes
 | 
				
			||||||
    (*env)->ReleaseByteArrayElements(env, data, elems, 0);
 | 
					    (*env)->ReleaseByteArrayElements(env, data, elems, 0);
 | 
				
			||||||
    return JNI_TRUE;
 | 
					    return JNI_TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					//                              Private Methods                              //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Produce a new breakpoint and add it to the collection
 | 
				
			||||||
 | 
					JNIEXPORT void JNICALL Java_vue_NativeVue_breakpoint
 | 
				
			||||||
 | 
					  (JNIEnv *env, jobject vue, jlong handle) {
 | 
				
			||||||
 | 
					    Core   *core = *(Core **)&handle;
 | 
				
			||||||
 | 
					    int32_t size; // Number of bytes to allocate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Allocate memory for the breakpoint
 | 
				
			||||||
 | 
					    core->numBreakpoints++;
 | 
				
			||||||
 | 
					    size = core->numBreakpoints * sizeof (Breakpoint);
 | 
				
			||||||
 | 
					    core->breakpoints = core->breakpoints == NULL ?
 | 
				
			||||||
 | 
					        malloc(size) : realloc(core->breakpoints, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Initialize the breakpoint
 | 
				
			||||||
 | 
					    memset(&core->breakpoints[core->numBreakpoints-1], 0, sizeof (Breakpoint));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Remove a breakpoint from the collection
 | 
				
			||||||
 | 
					JNIEXPORT void JNICALL Java_vue_NativeVue_remove
 | 
				
			||||||
 | 
					  (JNIEnv *env, jobject vue, jlong handle, jint index) {
 | 
				
			||||||
 | 
					    Core       *core = *(Core **)&handle;
 | 
				
			||||||
 | 
					    Breakpoint *brk  = &core->breakpoints[index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Delete the breakpoint
 | 
				
			||||||
 | 
					    if (brk->ranges != NULL) free(brk->ranges);
 | 
				
			||||||
 | 
					    if (brk->tokens != NULL) free(brk->tokens);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Move all subsequent breakpoints forward
 | 
				
			||||||
 | 
					    if (index != core->numBreakpoints - 1)
 | 
				
			||||||
 | 
					        memmove(brk, &brk[1],
 | 
				
			||||||
 | 
					            (core->numBreakpoints - index) * sizeof (Breakpoint));
 | 
				
			||||||
 | 
					    core->numBreakpoints--;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A breakpoint's address ranges have changed
 | 
				
			||||||
 | 
					JNIEXPORT void JNICALL Java_vue_NativeVue_updateRanges
 | 
				
			||||||
 | 
					  (JNIEnv *env, jobject vue, jlong handle, jint index, jintArray ranges) {
 | 
				
			||||||
 | 
					    Core       *core = *(Core **)&handle;
 | 
				
			||||||
 | 
					    Breakpoint *brk  = &core->breakpoints[index];
 | 
				
			||||||
 | 
					    jint       *elems; // Array elements
 | 
				
			||||||
 | 
					    int32_t     size;  // Number of bytes to allocate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Determine the number of address ranges
 | 
				
			||||||
 | 
					    brk->numRanges = (*env)->GetArrayLength(env, ranges) / 2;
 | 
				
			||||||
 | 
					    if (brk->numRanges == 0) {
 | 
				
			||||||
 | 
					        if (brk->ranges != NULL)
 | 
				
			||||||
 | 
					            free(brk->ranges);
 | 
				
			||||||
 | 
					        brk->ranges = NULL;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Allocate memory for the address ranges
 | 
				
			||||||
 | 
					    size        = brk->numRanges * sizeof (Range);
 | 
				
			||||||
 | 
					    brk->ranges = brk->ranges == NULL ?
 | 
				
			||||||
 | 
					        malloc(size) : realloc(brk->ranges, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Initialize address ranges
 | 
				
			||||||
 | 
					    elems = (*env)->GetIntArrayElements(env, ranges, NULL);
 | 
				
			||||||
 | 
					    memcpy(brk->ranges, elems, size);
 | 
				
			||||||
 | 
					    (*env)->ReleaseIntArrayElements(env, ranges, elems, JNI_ABORT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A breakpoint's enabled/hook state has changed
 | 
				
			||||||
 | 
					JNIEXPORT void JNICALL Java_vue_NativeVue_updateState
 | 
				
			||||||
 | 
					  (JNIEnv *env, jobject vue, jlong handle, jint index, jboolean enabled,
 | 
				
			||||||
 | 
					  jint hooks) {
 | 
				
			||||||
 | 
					    Core       *core = *(Core **)&handle;
 | 
				
			||||||
 | 
					    Breakpoint *brk  = &core->breakpoints[index];
 | 
				
			||||||
 | 
					    brk->enabled     = enabled;
 | 
				
			||||||
 | 
					    brk->hooks       = hooks;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A breakpoint's condition tokens have changed
 | 
				
			||||||
 | 
					JNIEXPORT void JNICALL Java_vue_NativeVue_updateTokens
 | 
				
			||||||
 | 
					  (JNIEnv *env, jobject vue, jlong handle, jint index, jintArray tokens) {
 | 
				
			||||||
 | 
					    Core       *core = *(Core **)&handle;
 | 
				
			||||||
 | 
					    Breakpoint *brk  = &core->breakpoints[index];
 | 
				
			||||||
 | 
					    jint       *elems; // Array elements
 | 
				
			||||||
 | 
					    int32_t     size;  // Number of bytes to allocate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Determine the number of condition tokens
 | 
				
			||||||
 | 
					    brk->numTokens = (*env)->GetArrayLength(env, tokens) / 2;
 | 
				
			||||||
 | 
					    if (brk->numTokens == 0) {
 | 
				
			||||||
 | 
					        if (brk->tokens != NULL)
 | 
				
			||||||
 | 
					            free(brk->tokens);
 | 
				
			||||||
 | 
					        brk->tokens = NULL;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Allocate memory for the condition tokens
 | 
				
			||||||
 | 
					    size           = brk->numTokens * sizeof (Token);
 | 
				
			||||||
 | 
					    brk->tokens    = brk->tokens == NULL ?
 | 
				
			||||||
 | 
					        malloc(size) : realloc(brk->tokens, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Initialize condition tokens
 | 
				
			||||||
 | 
					    elems = (*env)->GetIntArrayElements(env, tokens, NULL);
 | 
				
			||||||
 | 
					    memcpy(brk->tokens, elems, size);
 | 
				
			||||||
 | 
					    (*env)->ReleaseIntArrayElements(env, tokens, elems, JNI_ABORT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,13 @@ class NativeVue extends Vue {
 | 
				
			||||||
    //                            Public Methods                             //
 | 
					    //                            Public Methods                             //
 | 
				
			||||||
    ///////////////////////////////////////////////////////////////////////////
 | 
					    ///////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Produce a new breakpoint and add it to the collection
 | 
				
			||||||
 | 
					    public Breakpoint breakpoint() {
 | 
				
			||||||
 | 
					        var brk = super.breakpoint();
 | 
				
			||||||
 | 
					        breakpoint(handle);
 | 
				
			||||||
 | 
					        return brk;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Release any used resources
 | 
					    // Release any used resources
 | 
				
			||||||
    private native void dispose(long handle);
 | 
					    private native void dispose(long handle);
 | 
				
			||||||
    public void dispose()
 | 
					    public void dispose()
 | 
				
			||||||
| 
						 | 
					@ -61,6 +68,15 @@ class NativeVue extends Vue {
 | 
				
			||||||
    public boolean readBytes(int address, byte[] dest, int offset, int length)
 | 
					    public boolean readBytes(int address, byte[] dest, int offset, int length)
 | 
				
			||||||
        { return readBytes(handle, address, dest, offset, length); }
 | 
					        { return readBytes(handle, address, dest, offset, length); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Remove a breakpoint from the collection
 | 
				
			||||||
 | 
					    public boolean remove(Breakpoint brk) {
 | 
				
			||||||
 | 
					        int index = breakpoints.indexOf(brk);
 | 
				
			||||||
 | 
					        if (!super.remove(brk))
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        remove(handle, index);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Initialize all system components
 | 
					    // Initialize all system components
 | 
				
			||||||
    private native void reset(long handle);
 | 
					    private native void reset(long handle);
 | 
				
			||||||
    public void reset()
 | 
					    public void reset()
 | 
				
			||||||
| 
						 | 
					@ -100,4 +116,45 @@ class NativeVue extends Vue {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // A breakpoint's address ranges have changed
 | 
				
			||||||
 | 
					    void updateRanges(Breakpoint brk) {
 | 
				
			||||||
 | 
					        super.updateRanges(brk);
 | 
				
			||||||
 | 
					        updateRanges(handle, breakpoints.indexOf(brk), brk.flattenRanges());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // A breakpoint's enabled/hook state has changed
 | 
				
			||||||
 | 
					    void updateState(Breakpoint brk) {
 | 
				
			||||||
 | 
					        super.updateState(brk);
 | 
				
			||||||
 | 
					        updateState(handle, breakpoints.indexOf(brk),
 | 
				
			||||||
 | 
					            brk.isEnabled(), brk.getHooks());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // A breakpoint's condition tokens have changed
 | 
				
			||||||
 | 
					    void updateTokens(Breakpoint brk) {
 | 
				
			||||||
 | 
					        super.updateTokens(brk);
 | 
				
			||||||
 | 
					        updateTokens(handle, breakpoints.indexOf(brk), brk.flattenTokens());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ///////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					    //                            Private Methods                            //
 | 
				
			||||||
 | 
					    ///////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Produce a new breakpoint and add it to the collection
 | 
				
			||||||
 | 
					    private native void breakpoint(long handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Remove a breakpoint from the collection
 | 
				
			||||||
 | 
					    private native void remove(long handle, int index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // A breakpoint's address ranges have changed
 | 
				
			||||||
 | 
					    private native void updateRanges(long handle, int index, int[] ranges);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // A breakpoint's enabled/hook state has changed
 | 
				
			||||||
 | 
					    private native void updateState(long handle, int index, boolean enabled,
 | 
				
			||||||
 | 
					        int hooks);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // A breakpoint's condition tokens have changed
 | 
				
			||||||
 | 
					    private native void updateTokens(long handle, int index, int[] tokens);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -249,8 +249,13 @@ public abstract class Vue {
 | 
				
			||||||
    // Evaluate the condition in a breakpoint
 | 
					    // Evaluate the condition in a breakpoint
 | 
				
			||||||
    abstract boolean evaluate(Breakpoint brk);
 | 
					    abstract boolean evaluate(Breakpoint brk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // A breakpoint has been updated
 | 
					    // A breakpoint's address ranges have changed
 | 
				
			||||||
    void update(Breakpoint brk) {
 | 
					    void updateRanges(Breakpoint brk) { }
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
 | 
					    // A breakpoint's enabled/hook state has changed
 | 
				
			||||||
 | 
					    void updateState(Breakpoint brk) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // A breakpoint's condition tokens have changed
 | 
				
			||||||
 | 
					    void updateTokens(Breakpoint brk) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue