Make JavaScript core work like the API
This commit is contained in:
		
							parent
							
								
									1cc268e5d0
								
							
						
					
					
						commit
						386f4a904f
					
				
							
								
								
									
										2
									
								
								makefile
								
								
								
								
							
							
						
						
									
										2
									
								
								makefile
								
								
								
								
							| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
.PHONY: help
 | 
			
		||||
help:
 | 
			
		||||
	@echo
 | 
			
		||||
	@echo "Virtual Boy Emulator - March 11, 2023"
 | 
			
		||||
	@echo "Virtual Boy Emulator - March 12, 2023"
 | 
			
		||||
	@echo
 | 
			
		||||
	@echo "Target build environment is any Debian with the following packages:"
 | 
			
		||||
	@echo "  emscripten"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,30 @@
 | 
			
		|||
// Interface between application and WebAssembly worker thread
 | 
			
		||||
class Core {
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////// Constants ////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    /* Register types */
 | 
			
		||||
    static VB_PROGRAM = 0;
 | 
			
		||||
    static VB_SYSTEM  = 1;
 | 
			
		||||
    static VB_OTHER   = 2;
 | 
			
		||||
 | 
			
		||||
    /* System registers */
 | 
			
		||||
    static VB_ADTRE = 25;
 | 
			
		||||
    static VB_CHCW  = 24;
 | 
			
		||||
    static VB_ECR   =  4;
 | 
			
		||||
    static VB_EIPC  =  0;
 | 
			
		||||
    static VB_EIPSW =  1;
 | 
			
		||||
    static VB_FEPC  =  2;
 | 
			
		||||
    static VB_FEPSW =  3;
 | 
			
		||||
    static VB_PIR   =  6;
 | 
			
		||||
    static VB_PSW   =  5;
 | 
			
		||||
    static VB_TKCW  =  7;
 | 
			
		||||
 | 
			
		||||
    /* Other registers */
 | 
			
		||||
    static VB_PC = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    ///////////////////////// Initialization Methods //////////////////////////
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,29 +162,13 @@ class Core {
 | 
			
		|||
        }, [], options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Retrieve the value of PC
 | 
			
		||||
    getProgramCounter(sim, options) {
 | 
			
		||||
    // Retrieve the value of a register
 | 
			
		||||
    getRegister(sim, type, id, options) {
 | 
			
		||||
        return this.message({
 | 
			
		||||
            command: "getProgramCounter",
 | 
			
		||||
            sim    : sim.pointer
 | 
			
		||||
        }, [], options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Retrieve the value of a program register
 | 
			
		||||
    getProgramRegister(sim, id, options) {
 | 
			
		||||
        return this.message({
 | 
			
		||||
            command: "getProgramRegister",
 | 
			
		||||
            command: "getRegister",
 | 
			
		||||
            id     : id,
 | 
			
		||||
            sim    : sim.pointer
 | 
			
		||||
        }, [], options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Retrieve the value of a system register
 | 
			
		||||
    getSystemRegister(sim, id, options) {
 | 
			
		||||
        return this.message({
 | 
			
		||||
            command: "getSystemRegister",
 | 
			
		||||
            id     : id,
 | 
			
		||||
            sim    : sim.pointer
 | 
			
		||||
            sim    : sim.pointer,
 | 
			
		||||
            type   : type
 | 
			
		||||
        }, [], options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -199,21 +207,13 @@ class Core {
 | 
			
		|||
        }, [], options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specify a value for the program counter
 | 
			
		||||
    setProgramCounter(sim, value, options) {
 | 
			
		||||
    // Specify a value for a register
 | 
			
		||||
    setRegister(sim, type, id, value, options) {
 | 
			
		||||
        return this.message({
 | 
			
		||||
            command: "setProgramCounter",
 | 
			
		||||
            sim    : sim.pointer,
 | 
			
		||||
            value  : value
 | 
			
		||||
        }, [], options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specify a value for a program register
 | 
			
		||||
    setProgramRegister(sim, id, value, options) {
 | 
			
		||||
        return this.message({
 | 
			
		||||
            command: "setProgramRegister",
 | 
			
		||||
            command: "setRegister",
 | 
			
		||||
            id     : id,
 | 
			
		||||
            sim    : sim.pointer,
 | 
			
		||||
            type   : type,
 | 
			
		||||
            value  : value
 | 
			
		||||
        }, [], options);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -229,16 +229,6 @@ class Core {
 | 
			
		|||
        }, [data.buffer], options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specify a value for a system register
 | 
			
		||||
    setSystemRegister(sim, id, value, options) {
 | 
			
		||||
        return this.message({
 | 
			
		||||
            command: "setSystemRegister",
 | 
			
		||||
            id     : id,
 | 
			
		||||
            sim    : sim.pointer,
 | 
			
		||||
            value  : value
 | 
			
		||||
        }, [], options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Execute the current instruction
 | 
			
		||||
    singleStep(sims, options) {
 | 
			
		||||
        return this.message({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,25 @@
 | 
			
		|||
"use strict";
 | 
			
		||||
 | 
			
		||||
/* Register types */
 | 
			
		||||
const VB_PROGRAM = 0;
 | 
			
		||||
const VB_SYSTEM  = 1;
 | 
			
		||||
const VB_OTHER   = 2;
 | 
			
		||||
 | 
			
		||||
/* System registers */
 | 
			
		||||
const VB_ADTRE = 25;
 | 
			
		||||
const VB_CHCW  = 24;
 | 
			
		||||
const VB_ECR   =  4;
 | 
			
		||||
const VB_EIPC  =  0;
 | 
			
		||||
const VB_EIPSW =  1;
 | 
			
		||||
const VB_FEPC  =  2;
 | 
			
		||||
const VB_FEPSW =  3;
 | 
			
		||||
const VB_PIR   =  6;
 | 
			
		||||
const VB_PSW   =  5;
 | 
			
		||||
const VB_TKCW  =  7;
 | 
			
		||||
 | 
			
		||||
/* Other registers */
 | 
			
		||||
const VB_PC = 0;
 | 
			
		||||
 | 
			
		||||
// Dedicated emulation thread
 | 
			
		||||
class CoreThread {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -130,19 +150,12 @@ class CoreThread {
 | 
			
		|||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Retrieve the value of PC
 | 
			
		||||
    getProgramCounter(msg) {
 | 
			
		||||
        return { value: this.vbGetRegister(msg.sim, 2, 0) >>> 0 };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Retrieve the value of a program register
 | 
			
		||||
    getProgramRegister(msg) {
 | 
			
		||||
        return { value: this.vbGetRegister(msg.sim, 0, msg.id) };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Retrieve the value of a system register
 | 
			
		||||
    getSystemRegister(msg) {
 | 
			
		||||
        return { value: this.vbGetRegister(msg.sim, 1, msg.id) >>> 0 };
 | 
			
		||||
    // Retrieve the value of a register
 | 
			
		||||
    getRegister(msg) {
 | 
			
		||||
        let value = this.vbGetRegister(msg.sim, msg.type, msg.id);
 | 
			
		||||
        if (msg.type != VB_PROGRAM)
 | 
			
		||||
            value >>>= 0;
 | 
			
		||||
        return { value: value };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Read multiple bytes from memory
 | 
			
		||||
| 
						 | 
				
			
			@ -193,13 +206,10 @@ class CoreThread {
 | 
			
		|||
            delete rep.transfers;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Do not send a reply
 | 
			
		||||
        if (subscriptions.length == 0 && !msg.reply)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // Send the response to the main thread
 | 
			
		||||
        if (subscriptions.length == 0)
 | 
			
		||||
            return;
 | 
			
		||||
        this.main.postMessage({
 | 
			
		||||
            isReply      : !!msg.reply,
 | 
			
		||||
            subscriptions: subscriptions.sort(CoreThread.REFRESH_ORDER)
 | 
			
		||||
        }, transfers);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -224,14 +234,12 @@ class CoreThread {
 | 
			
		|||
        return { pcs: pcs };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specify a value for the program counter
 | 
			
		||||
    setProgramCounter(msg) {
 | 
			
		||||
        return { value: this.vbSetRegister(msg.sim, 2, 0, msg.value) >>> 0 };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specify a value for a program register
 | 
			
		||||
    setProgramRegister(msg) {
 | 
			
		||||
        return { value: this.vbSetRegister(msg.sim, 0, msg.id, msg.value) };
 | 
			
		||||
    // Specify a value for a register
 | 
			
		||||
    setRegister(msg) {
 | 
			
		||||
        let value = this.vbSetRegister(msg.sim, msg.type, msg.id, msg.value);
 | 
			
		||||
        if (msg.type != VB_PROGRAM)
 | 
			
		||||
            value >>>= 0;
 | 
			
		||||
        return { value: value };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specify a cartridge ROM buffer
 | 
			
		||||
| 
						 | 
				
			
			@ -261,11 +269,6 @@ class CoreThread {
 | 
			
		|||
        return { success: success };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specify a value for a system register
 | 
			
		||||
    setSystemRegister(msg) {
 | 
			
		||||
        return {value:this.vbSetRegister(msg.sim, 1, msg.id, msg.value)>>>0};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Execute the current instruction
 | 
			
		||||
    singleStep(msg) {
 | 
			
		||||
        let sims = this.malloc(msg.sims.length, true);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
import { Core         } from /**/"../core/Core.js";
 | 
			
		||||
import { Disassembler } from /**/"../core/Disassembler.js";
 | 
			
		||||
import { Toolkit      } from /**/"../toolkit/Toolkit.js";
 | 
			
		||||
let register = Debugger => {
 | 
			
		||||
| 
						 | 
				
			
			@ -657,10 +658,12 @@ class Register {
 | 
			
		|||
 | 
			
		||||
    ///////////////////////// Initialization Methods //////////////////////////
 | 
			
		||||
 | 
			
		||||
    constructor(registers, key, type) {
 | 
			
		||||
    constructor(registers, key, type, apiType, apiId) {
 | 
			
		||||
        let app = registers.cpu.debug.app;
 | 
			
		||||
 | 
			
		||||
        // Configure instance fields
 | 
			
		||||
        this.apiId     = apiId;
 | 
			
		||||
        this.apiType   = apiType;
 | 
			
		||||
        this.controls  = [];
 | 
			
		||||
        this.dasm      = registers.cpu.debug.app.dasm;
 | 
			
		||||
        this.debug     = registers.cpu.debug;
 | 
			
		||||
| 
						 | 
				
			
			@ -1159,17 +1162,11 @@ class Register {
 | 
			
		|||
    async setValue(value) {
 | 
			
		||||
 | 
			
		||||
        // Update the value in the simulation state
 | 
			
		||||
        let sim = this.debug.sim;
 | 
			
		||||
        let result = await (
 | 
			
		||||
            this.key == "pc" ? this.debug.core
 | 
			
		||||
                .setProgramCounter(sim, value, {
 | 
			
		||||
                    refresh: [ this.registers.cpu.disassembler.subscription ]
 | 
			
		||||
                }) :
 | 
			
		||||
            this.type != Register.PROGRAM ? this.debug.core
 | 
			
		||||
                .setSystemRegister(sim, this.key, value) :
 | 
			
		||||
            this.debug.core
 | 
			
		||||
                .setProgramRegister(sim, this.key, value)
 | 
			
		||||
        );
 | 
			
		||||
        let options = {};
 | 
			
		||||
        if (this.key == "pc")
 | 
			
		||||
            options.refresh = [ this.registers.cpu.disassembler.subscription ];
 | 
			
		||||
        let result = await this.debug.core.setRegister(
 | 
			
		||||
            this.debug.sim, this.apiType, this.apiId, value, options);
 | 
			
		||||
 | 
			
		||||
        // Update the value in the debugger window
 | 
			
		||||
        this.target[this.key] = result.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -1194,20 +1191,20 @@ class RegisterPane extends Toolkit.SplitPane {
 | 
			
		|||
 | 
			
		||||
    // System register templates
 | 
			
		||||
    static SYSTEMS = [
 | 
			
		||||
        [ [ "pc"         ], Register.PLAIN ],
 | 
			
		||||
        [ [ "system",  5 ], Register.PSW   ],
 | 
			
		||||
        [ [ "system", 25 ], Register.PLAIN ],
 | 
			
		||||
        [ [ "system", 24 ], Register.CHCW  ],
 | 
			
		||||
        [ [ "system",  4 ], Register.ECR   ],
 | 
			
		||||
        [ [ "system",  0 ], Register.PLAIN ],
 | 
			
		||||
        [ [ "system",  1 ], Register.PSW   ],
 | 
			
		||||
        [ [ "system",  2 ], Register.PLAIN ],
 | 
			
		||||
        [ [ "system",  3 ], Register.PSW   ],
 | 
			
		||||
        [ [ "system",  6 ], Register.PIR   ],
 | 
			
		||||
        [ [ "system",  7 ], Register.TKCW  ],
 | 
			
		||||
        [ [ "system", 29 ], Register.PLAIN ],
 | 
			
		||||
        [ [ "system", 30 ], Register.PLAIN ],
 | 
			
		||||
        [ [ "system", 31 ], Register.PLAIN ]
 | 
			
		||||
        [["pc"                  ],Register.PLAIN,Core.VB_OTHER ,Core.VB_PC   ],
 | 
			
		||||
        [["system",Core.VB_PSW  ],Register.PSW  ,Core.VB_SYSTEM,Core.VB_PSW  ],
 | 
			
		||||
        [["system",Core.VB_ADTRE],Register.PLAIN,Core.VB_SYSTEM,Core.VB_ADTRE],
 | 
			
		||||
        [["system",Core.VB_CHCW ],Register.CHCW ,Core.VB_SYSTEM,Core.VB_CHCW ],
 | 
			
		||||
        [["system",Core.VB_ECR  ],Register.ECR  ,Core.VB_SYSTEM,Core.VB_ECR  ],
 | 
			
		||||
        [["system",Core.VB_EIPC ],Register.PLAIN,Core.VB_SYSTEM,Core.VB_EIPC ],
 | 
			
		||||
        [["system",Core.VB_EIPSW],Register.PSW  ,Core.VB_SYSTEM,Core.VB_EIPSW],
 | 
			
		||||
        [["system",Core.VB_FEPC ],Register.PLAIN,Core.VB_SYSTEM,Core.VB_FEPC ],
 | 
			
		||||
        [["system",Core.VB_FEPSW],Register.PSW  ,Core.VB_SYSTEM,Core.VB_FEPSW],
 | 
			
		||||
        [["system",Core.VB_PIR  ],Register.PIR  ,Core.VB_SYSTEM,Core.VB_PIR  ],
 | 
			
		||||
        [["system",Core.VB_TKCW ],Register.TKCW ,Core.VB_SYSTEM,Core.VB_TKCW ],
 | 
			
		||||
        [["system",29           ],Register.PLAIN,Core.VB_SYSTEM,29           ],
 | 
			
		||||
        [["system",30           ],Register.PLAIN,Core.VB_SYSTEM,30           ],
 | 
			
		||||
        [["system",31           ],Register.PLAIN,Core.VB_SYSTEM,31           ]
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1278,10 +1275,10 @@ class RegisterPane extends Toolkit.SplitPane {
 | 
			
		|||
 | 
			
		||||
        // Configure register lists
 | 
			
		||||
        for (let sys of RegisterPane.SYSTEMS)
 | 
			
		||||
            this.addRegister(new Register(this, sys[0], sys[1]));
 | 
			
		||||
            this.addRegister(new Register(this, ... sys));
 | 
			
		||||
        for (let x = 0; x < 32; x++) {
 | 
			
		||||
            this.addRegister(new Register(this,
 | 
			
		||||
                [ "program", x ], Register.PROGRAM));
 | 
			
		||||
                [ "program", x ], Register.PROGRAM, Core.VB_PROGRAM, x));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Value text box measurer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,13 +4,6 @@ let register = Debugger => Debugger.Memory =
 | 
			
		|||
// Debugger memory window
 | 
			
		||||
class Memory extends Toolkit.Window {
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////// Constants ////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    // Bus indexes
 | 
			
		||||
    static MEMORY = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    ///////////////////////// Initialization Methods //////////////////////////
 | 
			
		||||
 | 
			
		||||
    constructor(debug, index) {
 | 
			
		||||
| 
						 | 
				
			
			@ -35,12 +28,11 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
        // Available buses
 | 
			
		||||
        this.buses = [
 | 
			
		||||
            {
 | 
			
		||||
                index      : Memory.MEMORY,
 | 
			
		||||
                editAddress: 0x05000000,
 | 
			
		||||
                viewAddress: 0x05000000
 | 
			
		||||
            }
 | 
			
		||||
        ];
 | 
			
		||||
        this.bus = this.buses[Memory.MEMORY];
 | 
			
		||||
        this.bus = this.buses[0];
 | 
			
		||||
 | 
			
		||||
        // Window
 | 
			
		||||
        this.setTitle("{debug.memory._}", true);
 | 
			
		||||
| 
						 | 
				
			
			@ -60,8 +52,7 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
        this.drpBus = new Toolkit.DropDown(debug.app);
 | 
			
		||||
        this.drpBus.setLabel("{debug.memory.bus}", true);
 | 
			
		||||
        this.drpBus.setTitle("{debug.memory.bus}", true);
 | 
			
		||||
        this.drpBus.add("{debug.memory.busMemory}", true,
 | 
			
		||||
            this.buses[Memory.MEMORY]);
 | 
			
		||||
        this.drpBus.add("{debug.memory.busMemory}", true, this.buses[0]);
 | 
			
		||||
        this.drpBus.addEventListener("input", e=>this.busInput());
 | 
			
		||||
        this.add(this.drpBus);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +77,8 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
        };
 | 
			
		||||
        this.hexEditor.setLabel("{debug.memory.hexEditor}", true);
 | 
			
		||||
        this.hexEditor.setRoleDescription("{debug.memory.hexEditor}", true);
 | 
			
		||||
        this.hexEditor.addEventListener("keydown", e=>this.hexKeyDown(e));
 | 
			
		||||
        this.hexEditor.addEventListener("focusout", e=>this.commit    ( ));
 | 
			
		||||
        this.hexEditor.addEventListener("keydown" , e=>this.hexKeyDown(e));
 | 
			
		||||
        this.hexEditor.addEventListener("resize"  , e=>this.hexResize ( ));
 | 
			
		||||
        this.hexEditor.addEventListener("wheel"   , e=>this.hexWheel  (e));
 | 
			
		||||
        this.hexEditor.addEventListener(
 | 
			
		||||
| 
						 | 
				
			
			@ -187,7 +179,7 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
        // Processing by key, scroll lock on
 | 
			
		||||
        else switch (e.key) {
 | 
			
		||||
            case "ArrowDown":
 | 
			
		||||
                this.bus.viewAddress += 16;
 | 
			
		||||
                this.setViewAddress(this.bus.viewAddress + 16);
 | 
			
		||||
                this.fetch();
 | 
			
		||||
                Toolkit.handle(e);
 | 
			
		||||
                return;
 | 
			
		||||
| 
						 | 
				
			
			@ -200,17 +192,17 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
                Toolkit.handle(e);
 | 
			
		||||
                return;
 | 
			
		||||
            case "ArrowUp":
 | 
			
		||||
                this.bus.viewAddress -= 16;
 | 
			
		||||
                this.setViewAddress(this.bus.viewAddress - 16);
 | 
			
		||||
                this.fetch();
 | 
			
		||||
                Toolkit.handle(e);
 | 
			
		||||
                return;
 | 
			
		||||
            case "PageDown":
 | 
			
		||||
                this.bus.viewAddress += this.tall(true) * 16;
 | 
			
		||||
                this.setViewAddress(this.bus.viewAddress + this.tall(true)*16);
 | 
			
		||||
                this.fetch();
 | 
			
		||||
                Toolkit.handle(e);
 | 
			
		||||
                return;
 | 
			
		||||
            case "PageUp":
 | 
			
		||||
                this.bus.viewAddress -= this.tall(true) * 16;
 | 
			
		||||
                this.setViewAddress(this.bus.viewAddress - this.tall(true)*16);
 | 
			
		||||
                this.fetch();
 | 
			
		||||
                Toolkit.handle(e);
 | 
			
		||||
                return;
 | 
			
		||||
| 
						 | 
				
			
			@ -280,7 +272,7 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // Update the selection address
 | 
			
		||||
        let address = this.bus.viewAddress + y * 16 + x >>> 0;
 | 
			
		||||
        let address = this.toAddress(this.bus.viewAddress + y * 16 + x);
 | 
			
		||||
        if (this.editDigit !== null && address != this.bus.editAddress)
 | 
			
		||||
            this.commit();
 | 
			
		||||
        this.setEditAddress(address);
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +348,7 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
            return;
 | 
			
		||||
 | 
			
		||||
        // Scroll the view
 | 
			
		||||
        this.bus.viewAddress = this.bus.viewAddress + scr.lines * 16 >>> 0;
 | 
			
		||||
        this.setViewAddress(this.bus.viewAddress + scr.lines * 16);
 | 
			
		||||
        this.fetch();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -407,7 +399,7 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
 | 
			
		||||
        // The edited value is in the bus's data buffer
 | 
			
		||||
        if (this.data != null) {
 | 
			
		||||
            let offset = this.bus.editAddress - this.dataAddress >>> 0;
 | 
			
		||||
            let offset = this.toAddress(this.bus.editAddress-this.dataAddress);
 | 
			
		||||
            if (offset < this.data.length)
 | 
			
		||||
                this.data[offset] = this.editDigit;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -425,7 +417,7 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
 | 
			
		||||
        // Select the parameters for the simulation fetch
 | 
			
		||||
        let params = {
 | 
			
		||||
            address: this.bus.viewAddress - 10 * 16,
 | 
			
		||||
            address: this.toAddress(this.bus.viewAddress - 10 * 16),
 | 
			
		||||
            length : (this.tall(false) + 20) * 16
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -478,7 +470,7 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
 | 
			
		||||
        // Process all lines
 | 
			
		||||
        for (let y = 0; y < this.lines.length; y++) {
 | 
			
		||||
            let address = this.bus.viewAddress + y * 16 >>> 0;
 | 
			
		||||
            let address = this.toAddress(this.bus.viewAddress + y * 16);
 | 
			
		||||
            let line    = this.lines[y];
 | 
			
		||||
 | 
			
		||||
            // Address label
 | 
			
		||||
| 
						 | 
				
			
			@ -496,7 +488,7 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
 | 
			
		||||
                // Bus data exists
 | 
			
		||||
                else if (this.data != null) {
 | 
			
		||||
                    let offset = address - this.dataAddress + x >>> 0;
 | 
			
		||||
                    let offset = this.toAddress(address-this.dataAddress+x);
 | 
			
		||||
 | 
			
		||||
                    // The byte is contained in the bus data buffer
 | 
			
		||||
                    if (offset >= 0 && offset < this.data.length)
 | 
			
		||||
| 
						 | 
				
			
			@ -515,18 +507,18 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
    setEditAddress(address, auto = false) {
 | 
			
		||||
        let col  = this.lines[0].lblBytes[address&15].getBoundingClientRect();
 | 
			
		||||
        let port = this.scrHex.viewport.element.getBoundingClientRect();
 | 
			
		||||
        let row  = (address & ~15) >>> 0;
 | 
			
		||||
        let row  = this.toAddress(address & ~15);
 | 
			
		||||
        let scr  = this.scrHex.scrollLeft;
 | 
			
		||||
        let tall = this.tall(true, 0);
 | 
			
		||||
 | 
			
		||||
        // Ensure the data row is fully visible
 | 
			
		||||
        if (row - this.bus.viewAddress >>> 0 >= tall * 16) {
 | 
			
		||||
        if (this.toAddress(row - this.bus.viewAddress) >= tall * 16) {
 | 
			
		||||
            if (!auto) {
 | 
			
		||||
                this.bus.viewAddress =
 | 
			
		||||
                    this.bus.viewAddress - row >>> 0 <=
 | 
			
		||||
                    row - (this.bus.viewAddress + tall * 16) >>> 0
 | 
			
		||||
                ? row : row - (tall - 1) * 16;
 | 
			
		||||
            } else this.bus.viewAddress = row - Math.floor(tall * auto) * 16;
 | 
			
		||||
                this.setViewAddress(
 | 
			
		||||
                    this.toAddress(this.bus.viewAddress - row) <=
 | 
			
		||||
                    this.toAddress(row - (this.bus.viewAddress + tall * 16))
 | 
			
		||||
                ? row : this.toAddress(row - (tall - 1) * 16));
 | 
			
		||||
            } else this.setViewAddress(row - Math.floor(tall * auto) * 16);
 | 
			
		||||
            this.fetch();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -542,10 +534,15 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
        ;
 | 
			
		||||
 | 
			
		||||
        // Refresh the display;
 | 
			
		||||
        this.bus.editAddress = address;
 | 
			
		||||
        this.bus.editAddress = this.toAddress(address);
 | 
			
		||||
        this.refresh();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specify the address of the hex editor's view
 | 
			
		||||
    setViewAddress(address) {
 | 
			
		||||
        this.bus.viewAddress = this.toAddress(address);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Measure the number of lines visible in the view
 | 
			
		||||
    tall(fully = null, plus = 1) {
 | 
			
		||||
        return Math.max(1, Math[fully===null ? "abs" : fully?"floor":"ceil"](
 | 
			
		||||
| 
						 | 
				
			
			@ -554,6 +551,11 @@ class Memory extends Toolkit.Window {
 | 
			
		|||
        )) + plus;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Ensure an address is in the proper range
 | 
			
		||||
    toAddress(address) {
 | 
			
		||||
        return address >>> 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export { register };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue