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