Introducing CPU register lists
This commit is contained in:
parent
2e38c1fa49
commit
7d8d33158f
|
@ -10,6 +10,7 @@ app {
|
||||||
debug {
|
debug {
|
||||||
(menu) Debug
|
(menu) Debug
|
||||||
console Console
|
console Console
|
||||||
|
cpu CPU
|
||||||
memory Memory
|
memory Memory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +37,16 @@ console {
|
||||||
title Console
|
title Console
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# CPU window
|
||||||
|
cpu {
|
||||||
|
float Float
|
||||||
|
hex Hex
|
||||||
|
last_pc Last PC
|
||||||
|
signed Signed
|
||||||
|
title CPU
|
||||||
|
unsigned Unsigned
|
||||||
|
}
|
||||||
|
|
||||||
# Memory window
|
# Memory window
|
||||||
memory {
|
memory {
|
||||||
title Memory
|
title Memory
|
||||||
|
|
18
makefile
18
makefile
|
@ -69,7 +69,7 @@ core:
|
||||||
desktop: clean_desktop
|
desktop: clean_desktop
|
||||||
@echo " Compiling Java desktop application"
|
@echo " Compiling Java desktop application"
|
||||||
@javac -sourcepath src/desktop --release 10 -Xlint:unchecked \
|
@javac -sourcepath src/desktop --release 10 -Xlint:unchecked \
|
||||||
-h src/desktop/native -d . src/desktop/Main.java
|
-h src/desktop/vue -d . src/desktop/Main.java
|
||||||
|
|
||||||
# Build all native modules
|
# Build all native modules
|
||||||
.PHONY: native
|
.PHONY: native
|
||||||
|
@ -103,7 +103,7 @@ clean_desktop:
|
||||||
# Delete everything but the .jar
|
# Delete everything but the .jar
|
||||||
.PHONY: clean_most
|
.PHONY: clean_most
|
||||||
clean_most: clean_desktop
|
clean_most: clean_desktop
|
||||||
@rm -f src/desktop/native/vue_NativeVUE.h native/*.dll native/*.so
|
@rm -f src/desktop/vue/vue_NativeVUE.h native/*.dll native/*.so
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,14 +112,14 @@ clean_most: clean_desktop
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# JNI header file
|
# JNI header file
|
||||||
src/desktop/native/vue_NativeVUE.h: src/desktop/vue/NativeVUE.java
|
src/desktop/vue/vue_NativeVUE.h: src/desktop/vue/NativeVUE.java
|
||||||
@javac -h src/desktop/native -sourcepath src/desktop -d . \
|
@javac -h src/desktop/vue -sourcepath src/desktop -d . \
|
||||||
src/desktop/vue/NativeVUE.java
|
src/desktop/vue/NativeVUE.java
|
||||||
@sleep 3
|
@sleep 3
|
||||||
|
|
||||||
# linux_x86
|
# linux_x86
|
||||||
.PHONY: lin32_pre
|
.PHONY: lin32_pre
|
||||||
lin32_pre: src/desktop/native/vue_NativeVUE.h
|
lin32_pre: src/desktop/vue/vue_NativeVUE.h
|
||||||
$(eval name = linux_x86)
|
$(eval name = linux_x86)
|
||||||
$(eval prefix = `uname -m`-linux-gnu-)
|
$(eval prefix = `uname -m`-linux-gnu-)
|
||||||
$(eval include = -I$(include_linux) -I$(include_linux)/linux)
|
$(eval include = -I$(include_linux) -I$(include_linux)/linux)
|
||||||
|
@ -130,7 +130,7 @@ lin32: lin32_pre native_common
|
||||||
|
|
||||||
# linux_x86-64
|
# linux_x86-64
|
||||||
.PHONY: lin64_pre
|
.PHONY: lin64_pre
|
||||||
lin64_pre: src/desktop/native/vue_NativeVUE.h
|
lin64_pre: src/desktop/vue/vue_NativeVUE.h
|
||||||
$(eval name = linux_x86-64)
|
$(eval name = linux_x86-64)
|
||||||
$(eval prefix = `uname -m`-linux-gnu-)
|
$(eval prefix = `uname -m`-linux-gnu-)
|
||||||
$(eval include = -I$(include_linux) -I$(include_linux)/linux)
|
$(eval include = -I$(include_linux) -I$(include_linux)/linux)
|
||||||
|
@ -141,7 +141,7 @@ lin64: lin64_pre native_common
|
||||||
|
|
||||||
# windows_x86
|
# windows_x86
|
||||||
.PHONY: win32_pre
|
.PHONY: win32_pre
|
||||||
win32_pre: src/desktop/native/vue_NativeVUE.h
|
win32_pre: src/desktop/vue/vue_NativeVUE.h
|
||||||
$(eval name = windows_x86)
|
$(eval name = windows_x86)
|
||||||
$(eval prefix = i686-w64-mingw32-)
|
$(eval prefix = i686-w64-mingw32-)
|
||||||
$(eval include = -I$(include_windows) -I$(include_windows)/win32)
|
$(eval include = -I$(include_windows) -I$(include_windows)/win32)
|
||||||
|
@ -151,7 +151,7 @@ win32: win32_pre native_common
|
||||||
|
|
||||||
# windows_x86-64
|
# windows_x86-64
|
||||||
.PHONY: win64_pre
|
.PHONY: win64_pre
|
||||||
win64_pre: src/desktop/native/vue_NativeVUE.h
|
win64_pre: src/desktop/vue/vue_NativeVUE.h
|
||||||
$(eval name = windows_x86-64)
|
$(eval name = windows_x86-64)
|
||||||
$(eval prefix = x86_64-w64-mingw32-)
|
$(eval prefix = x86_64-w64-mingw32-)
|
||||||
$(eval include = -I$(include_windows) -I$(include_windows)/win32)
|
$(eval include = -I$(include_windows) -I$(include_windows)/win32)
|
||||||
|
@ -165,4 +165,4 @@ native_common:
|
||||||
@echo " Building native module $(name)"
|
@echo " Building native module $(name)"
|
||||||
@$(prefix)gcc $(include) -Isrc/core/include $(gccargs) -s -shared -O2 \
|
@$(prefix)gcc $(include) -Isrc/core/include $(gccargs) -s -shared -O2 \
|
||||||
-fno-strict-aliasing -Werror \
|
-fno-strict-aliasing -Werror \
|
||||||
-o native/$(name)$(ext) src/desktop/native/native.c src/core/vue.c
|
-o native/$(name)$(ext) src/desktop/vue/NativeVUE.c src/core/vue.c
|
||||||
|
|
|
@ -69,6 +69,13 @@ static int32_t busReadValue(VUE *vue, uint32_t address, int type) {
|
||||||
return 0; /* Unreachable */
|
return 0; /* Unreachable */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Perform a system reset */
|
||||||
|
static void busReset(VUE *vue) {
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < 0x10000; x++)
|
||||||
|
vue->bus.wram[x] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write bytes to host memory */
|
/* Write bytes to host memory */
|
||||||
static void busWriteBytes(uint8_t *dest, uint8_t *src, uint32_t address,
|
static void busWriteBytes(uint8_t *dest, uint8_t *src, uint32_t address,
|
||||||
uint32_t size, uint32_t length) {
|
uint32_t size, uint32_t length) {
|
||||||
|
|
|
@ -90,6 +90,13 @@ static int32_t cpuSetSystemRegister(VUE *vue, int index, int32_t value,
|
||||||
|
|
||||||
return vue->cpu.chcw_ice << 1;
|
return vue->cpu.chcw_ice << 1;
|
||||||
|
|
||||||
|
case VUE_ECR:
|
||||||
|
if (debug) {
|
||||||
|
vue->cpu.ecr_fecc = value >> 16 & 0xFFFF;
|
||||||
|
vue->cpu.ecr_eicc = value & 0xFFFF;
|
||||||
|
}
|
||||||
|
return vue->cpu.ecr_fecc << 16 | vue->cpu.ecr_eicc;
|
||||||
|
|
||||||
case VUE_PSW :
|
case VUE_PSW :
|
||||||
vue->cpu.psw_i = value >> 16 & 15;
|
vue->cpu.psw_i = value >> 16 & 15;
|
||||||
vue->cpu.psw_np = value >> 15 & 1;
|
vue->cpu.psw_np = value >> 15 & 1;
|
||||||
|
@ -109,16 +116,16 @@ static int32_t cpuSetSystemRegister(VUE *vue, int index, int32_t value,
|
||||||
return value & 0x000FF3FF;
|
return value & 0x000FF3FF;
|
||||||
|
|
||||||
/* Remaining cases to encourage tableswitch */
|
/* Remaining cases to encourage tableswitch */
|
||||||
case 4: case 6: case 7: case 8: case 9: case 10: case 11:
|
case 6: case 7: case 8: case 9: case 10: case 11: case 12:
|
||||||
case 12: case 13: case 14: case 15: case 16: case 17: case 18:
|
case 13: case 14: case 15: case 16: case 17: case 18: case 19:
|
||||||
case 19: case 20: case 21: case 22: case 23: case 26: case 27:
|
case 20: case 21: case 22: case 23: case 26: case 27: case 28:
|
||||||
case 28: case 30:
|
case 30:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1; /* Unreachable */
|
return 1; /* Unreachable */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* System reset */
|
/* Perform a system reset */
|
||||||
static void cpuReset(VUE *vue) {
|
static void cpuReset(VUE *vue) {
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
|
@ -127,15 +134,17 @@ static void cpuReset(VUE *vue) {
|
||||||
vue->cpu.fetch = 0;
|
vue->cpu.fetch = 0;
|
||||||
vue->cpu.stage = CPU_FETCH;
|
vue->cpu.stage = CPU_FETCH;
|
||||||
|
|
||||||
/* Reset program counter */
|
|
||||||
vue->cpu.pc = 0xFFFFFFF0;
|
|
||||||
|
|
||||||
/* Clear all registers (hardware only sets ECR, PC and PSW) */
|
/* Clear all registers (hardware only sets ECR, PC and PSW) */
|
||||||
for (x = 0; x < 32; x++) {
|
for (x = 0; x < 32; x++) {
|
||||||
vue->cpu.program[x] = 0;
|
vue->cpu.program[x] = 0;
|
||||||
cpuSetSystemRegister(vue, x, 0, VUE_TRUE);
|
cpuSetSystemRegister(vue, x, 0, VUE_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Configure registers */
|
||||||
|
vue->cpu.ecr_eicc = 0xFFF0;
|
||||||
|
vue->cpu.lastPC = 0xFFFFFFF0;
|
||||||
|
vue->cpu.pc = 0xFFFFFFF0;
|
||||||
|
vue->cpu.psw_np = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test a condition */
|
/* Test a condition */
|
||||||
|
|
|
@ -43,6 +43,13 @@ extern "C" {
|
||||||
#define VUE_PSW 5
|
#define VUE_PSW 5
|
||||||
#define VUE_TKCW 7
|
#define VUE_TKCW 7
|
||||||
|
|
||||||
|
/* Program register indexes */
|
||||||
|
#define VUE_GP 4
|
||||||
|
#define VUE_HP 2
|
||||||
|
#define VUE_LP 31
|
||||||
|
#define VUE_SP 3
|
||||||
|
#define VUE_TP 5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -68,6 +75,7 @@ typedef struct {
|
||||||
struct {
|
struct {
|
||||||
uint32_t cycles; /* Cycles until next stage */
|
uint32_t cycles; /* Cycles until next stage */
|
||||||
int fetch; /* Fetch unit index */
|
int fetch; /* Fetch unit index */
|
||||||
|
int32_t lastPC; /* Previous value of PC */
|
||||||
int stage; /* Current processing stage */
|
int stage; /* Current processing stage */
|
||||||
|
|
||||||
/* Program registers */
|
/* Program registers */
|
||||||
|
@ -101,17 +109,17 @@ typedef struct {
|
||||||
int8_t psw_z; /* Zero */
|
int8_t psw_z; /* Zero */
|
||||||
|
|
||||||
/* Cache Control Word */
|
/* Cache Control Word */
|
||||||
int32_t chcw_cec; /* Clear Entry Count */
|
uint16_t chcw_cec; /* Clear Entry Count */
|
||||||
int32_t chcw_cen; /* Clear Entry Number */
|
uint16_t chcw_cen; /* Clear Entry Number */
|
||||||
int8_t chcw_icc; /* Instruction Cache Clear */
|
int8_t chcw_icc; /* Instruction Cache Clear */
|
||||||
int8_t chcw_icd; /* Instruction Cache Dump */
|
int8_t chcw_icd; /* Instruction Cache Dump */
|
||||||
int8_t chcw_ice; /* Instruction Cache Enable */
|
int8_t chcw_ice; /* Instruction Cache Enable */
|
||||||
int8_t chcw_icr; /* Instruction Cache Restore */
|
int8_t chcw_icr; /* Instruction Cache Restore */
|
||||||
int32_t chcw_sa; /* Spill-Out Base Address */
|
int32_t chcw_sa; /* Spill-Out Base Address */
|
||||||
|
|
||||||
/* Exception Cause Register */
|
/* Exception Cause Register */
|
||||||
int8_t ecr_eicc; /* Exception/Interrupt Cause Code */
|
uint16_t ecr_eicc; /* Exception/Interrupt Cause Code */
|
||||||
int8_t ecr_fecc; /* Fatal Error Cause Code */
|
uint16_t ecr_fecc; /* Fatal Error Cause Code */
|
||||||
} cpu;
|
} cpu;
|
||||||
|
|
||||||
} VUE;
|
} VUE;
|
||||||
|
@ -125,6 +133,7 @@ typedef struct {
|
||||||
VUEAPI int32_t vueGetRegister(VUE *vue, int index, vbool system);
|
VUEAPI int32_t vueGetRegister(VUE *vue, int index, vbool system);
|
||||||
VUEAPI void vueInitialize (VUE *vue);
|
VUEAPI void vueInitialize (VUE *vue);
|
||||||
VUEAPI vbool vueRead (VUE *vue, uint32_t address, uint8_t *dest, uint32_t length);
|
VUEAPI vbool vueRead (VUE *vue, uint32_t address, uint8_t *dest, uint32_t length);
|
||||||
|
VUEAPI void vueReset (VUE *vue);
|
||||||
VUEAPI int32_t vueSetRegister(VUE *vue, int index, vbool system, int32_t value);
|
VUEAPI int32_t vueSetRegister(VUE *vue, int index, vbool system, int32_t value);
|
||||||
VUEAPI vbool vueSetROM (VUE *vue, uint8_t *rom, uint32_t size);
|
VUEAPI vbool vueSetROM (VUE *vue, uint8_t *rom, uint32_t size);
|
||||||
VUEAPI vbool vueWrite (VUE *vue, uint32_t address, uint8_t *src, uint32_t length);
|
VUEAPI vbool vueWrite (VUE *vue, uint32_t address, uint8_t *src, uint32_t length);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include <vue.h>
|
#include <vue.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Constants *
|
* Constants *
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -27,7 +26,7 @@ static const int TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
|
||||||
|
|
||||||
/* Retrieve the value of a register */
|
/* Retrieve the value of a register */
|
||||||
int32_t vueGetRegister(VUE *vue, int index, vbool system) {
|
int32_t vueGetRegister(VUE *vue, int index, vbool system) {
|
||||||
return
|
return vue == NULL ? 0 :
|
||||||
index == VUE_PC && system ? vue->cpu.pc :
|
index == VUE_PC && system ? vue->cpu.pc :
|
||||||
index < 0 || index > 31 ? 0 :
|
index < 0 || index > 31 ? 0 :
|
||||||
system ? cpuGetSystemRegister(vue, index) :
|
system ? cpuGetSystemRegister(vue, index) :
|
||||||
|
@ -37,6 +36,8 @@ int32_t vueGetRegister(VUE *vue, int index, vbool system) {
|
||||||
|
|
||||||
/* Prepare an emulation state context for use */
|
/* Prepare an emulation state context for use */
|
||||||
void vueInitialize(VUE *vue) {
|
void vueInitialize(VUE *vue) {
|
||||||
|
if (vue == NULL)
|
||||||
|
return;
|
||||||
vue->bus.rom = NULL;
|
vue->bus.rom = NULL;
|
||||||
vue->bus.sram = NULL;
|
vue->bus.sram = NULL;
|
||||||
}
|
}
|
||||||
|
@ -79,13 +80,21 @@ vbool vueRead(VUE *vue, uint32_t address, uint8_t *dest, uint32_t length) {
|
||||||
return VUE_TRUE;
|
return VUE_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize all system components */
|
||||||
|
void vueReset(VUE *vue) {
|
||||||
|
if (vue == NULL)
|
||||||
|
return;
|
||||||
|
busReset(vue);
|
||||||
|
cpuReset(vue);
|
||||||
|
}
|
||||||
|
|
||||||
/* Specify a value for a register */
|
/* Specify a value for a register */
|
||||||
int32_t vueSetRegister(VUE *vue, int index, vbool system, int32_t value) {
|
int32_t vueSetRegister(VUE *vue, int index, vbool system, int32_t value) {
|
||||||
return
|
return vue == NULL ? 0 :
|
||||||
index == VUE_PC && system ? vue->cpu.pc = value & 0xFFFFFFFE :
|
index == VUE_PC && system ? vue->cpu.pc = value & 0xFFFFFFFE :
|
||||||
index < 0 || index > 31 ? 0 :
|
index < 0 || index > 31 ? 0 :
|
||||||
system ? cpuSetSystemRegister(vue, index, value, VUE_TRUE) :
|
system ? cpuSetSystemRegister(vue, index, value, VUE_TRUE) :
|
||||||
index == 0 ? 0 : vue->cpu.program[index]
|
index == 0 ? 0 : (vue->cpu.program[index] = value)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,255 @@
|
||||||
|
package app;
|
||||||
|
|
||||||
|
// Java imports
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
// Project imports
|
||||||
|
import util.*;
|
||||||
|
import vue.*;
|
||||||
|
|
||||||
|
// CPU window
|
||||||
|
class CPU extends ChildWindow {
|
||||||
|
|
||||||
|
// Instance fields
|
||||||
|
private int expandWidth; // Width of expand buttons
|
||||||
|
private Font font; // Display font
|
||||||
|
private int fontHeight; // Font line height
|
||||||
|
private int fontWidth; // Font maximum character width
|
||||||
|
private boolean shown; // Window has been shown
|
||||||
|
private int systemHeight; // Initial height of system register list
|
||||||
|
|
||||||
|
// UI components
|
||||||
|
private JPanel dasm; // Disassembler
|
||||||
|
private JPanel system; // System registers
|
||||||
|
private JPanel program; // Program registers
|
||||||
|
private ArrayList<Register> registers; // Register controls
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructors //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Default constructor
|
||||||
|
CPU(MainWindow parent) {
|
||||||
|
super(parent, "cpu.title");
|
||||||
|
var client = getContentPane();
|
||||||
|
|
||||||
|
// Configure instance fields
|
||||||
|
font = new Font(Util.fontFamily(new String[]
|
||||||
|
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14);
|
||||||
|
registers = new ArrayList<Register>();
|
||||||
|
|
||||||
|
dasm = new JPanel(null);
|
||||||
|
dasm.setBackground(SystemColor.window);
|
||||||
|
dasm.setFocusable(true);
|
||||||
|
|
||||||
|
var inner = initRegisters();
|
||||||
|
var outer = Util.splitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||||
|
outer.setLeftComponent(new JScrollPane(dasm,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
|
||||||
|
outer.setRightComponent(inner);
|
||||||
|
outer.setResizeWeight(1);
|
||||||
|
|
||||||
|
client.add(outer);
|
||||||
|
client.setPreferredSize(new Dimension(640, 480));
|
||||||
|
setFont2(font);
|
||||||
|
pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Register Constructors //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize program register list
|
||||||
|
private void initProgram() {
|
||||||
|
Dimension target = null;
|
||||||
|
|
||||||
|
// Program register container
|
||||||
|
var lst = program = new JPanel(new GridBagLayout()) {
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
var ret = super.getPreferredSize();
|
||||||
|
if (!shown)
|
||||||
|
ret.height = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
if (shown)
|
||||||
|
return;
|
||||||
|
shown = true;
|
||||||
|
system.revalidate();
|
||||||
|
program.revalidate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
lst.setBackground(SystemColor.window);
|
||||||
|
lst.setFocusable(true);
|
||||||
|
lst.addMouseListener(Util.onMouse(e->lst.requestFocus(),null));
|
||||||
|
|
||||||
|
// Produce the list of program registers
|
||||||
|
for (int x = 0; x < 32; x++) {
|
||||||
|
String name = "r" + x;
|
||||||
|
switch (x) {
|
||||||
|
case VUE.GP: name = "gp"; break;
|
||||||
|
case VUE.HP: name = "hp"; break;
|
||||||
|
case VUE.LP: name = "lp"; break;
|
||||||
|
case VUE.SP: name = "sp"; break;
|
||||||
|
case VUE.TP: name = "tp"; break;
|
||||||
|
}
|
||||||
|
registers.add(new Register(parent,lst,name,x,Register.PROGRAM));
|
||||||
|
}
|
||||||
|
endList(lst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize register lists
|
||||||
|
private JSplitPane initRegisters() {
|
||||||
|
initSystem();
|
||||||
|
initProgram();
|
||||||
|
|
||||||
|
var ret = Util.splitPane(JSplitPane.VERTICAL_SPLIT);
|
||||||
|
ret.setTopComponent(new JScrollPane(system,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
|
||||||
|
));
|
||||||
|
ret.setBottomComponent(new JScrollPane(program,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
|
||||||
|
));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize system register list
|
||||||
|
private void initSystem() {
|
||||||
|
|
||||||
|
// System register container
|
||||||
|
var lst = system = new JPanel(new GridBagLayout()) {
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
var ret = super.getPreferredSize();
|
||||||
|
if (!shown)
|
||||||
|
ret.height = systemHeight;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
system.setBackground(SystemColor.window);
|
||||||
|
system.setFocusable(true);
|
||||||
|
system.addMouseListener(Util.onMouse(e->system.requestFocus(), null));
|
||||||
|
system.putClientProperty("shown", true);
|
||||||
|
|
||||||
|
// Add the first two system registers and expand PSW
|
||||||
|
registers.add(new Register(parent, lst, "PC" , VUE.PC , VUE.PC ));
|
||||||
|
Register psw =new Register(parent, lst, "PSW" , VUE.PSW , VUE.PSW );
|
||||||
|
psw.setExpanded(true);
|
||||||
|
registers.add(psw);
|
||||||
|
shown = true;
|
||||||
|
systemHeight = system.getPreferredSize().height + 6;
|
||||||
|
shown = false;
|
||||||
|
|
||||||
|
// Add the remaining system registers
|
||||||
|
registers.add(new Register(parent, lst, "EIPC" , VUE.EIPC , VUE.PC ));
|
||||||
|
registers.add(new Register(parent, lst, "EIPSW", VUE.EIPSW, VUE.PSW ));
|
||||||
|
registers.add(new Register(parent, lst, "FEPC" , VUE.FEPC , VUE.PC ));
|
||||||
|
registers.add(new Register(parent, lst, "FEPSW", VUE.FEPSW, VUE.PSW ));
|
||||||
|
registers.add(new Register(parent, lst, "ECR" , VUE.ECR , VUE.ECR ));
|
||||||
|
registers.add(new Register(parent, lst, "ADTRE", VUE.ADTRE, VUE.PC ));
|
||||||
|
registers.add(new Register(parent, lst, "CHCW" , VUE.CHCW , VUE.CHCW));
|
||||||
|
registers.add(new Register(parent, lst, "PIR" , VUE.PIR , VUE.PIR ));
|
||||||
|
registers.add(new Register(parent, lst, "TKCW" , VUE.TKCW , VUE.TKCW));
|
||||||
|
registers.add(new Register(parent, lst, "29" , 29, VUE.PC ));
|
||||||
|
registers.add(new Register(parent, lst, "30" , 30, VUE.PC ));
|
||||||
|
registers.add(new Register(parent, lst, "31" , 31, VUE.PC ));
|
||||||
|
endList(lst);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Event Handlers //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Client resize
|
||||||
|
private void onResize() {
|
||||||
|
//refreshDasm();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Package Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Update the display
|
||||||
|
void refresh() {
|
||||||
|
|
||||||
|
// The element is not ready
|
||||||
|
if (registers == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Refresh registers
|
||||||
|
for (var reg : registers)
|
||||||
|
reg.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify a new font
|
||||||
|
void setFont2(Font font) {
|
||||||
|
this.font = font;
|
||||||
|
|
||||||
|
// Configure the maximum font dimensions
|
||||||
|
var fontMax = new JLabel("!");
|
||||||
|
fontMax.setFont(font);
|
||||||
|
fontHeight = Math.max(1, fontMax.getPreferredSize().height);
|
||||||
|
fontWidth = -1;
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
fontMax.setText(Integer.toString(x, 16).toUpperCase());
|
||||||
|
fontWidth = Math.max(fontWidth, fontMax.getPreferredSize().width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure register list scrolling
|
||||||
|
for (int x = 0; x < 2; x++) {
|
||||||
|
Component ctrl = x == 0 ? system : program;
|
||||||
|
while (!(ctrl instanceof JScrollPane))
|
||||||
|
ctrl = ctrl.getParent();
|
||||||
|
((JScrollPane) ctrl).getVerticalScrollBar()
|
||||||
|
.setUnitIncrement(fontHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the width of the register expand buttons
|
||||||
|
var expand = new JLabel("+");
|
||||||
|
int width = expand.getPreferredSize().width;
|
||||||
|
expand.setText("-");
|
||||||
|
width = Math.max(width, expand.getPreferredSize().width) + 4;
|
||||||
|
|
||||||
|
// Configure registers
|
||||||
|
for (var reg : registers) {
|
||||||
|
reg.setExpandWidth(width);
|
||||||
|
reg.setFont(font, fontWidth, fontHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
onResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Terminate a register list
|
||||||
|
private JPanel endList(JPanel list) {
|
||||||
|
var spacer = new JPanel(null);
|
||||||
|
spacer.setOpaque(false);
|
||||||
|
spacer.setPreferredSize(new Dimension(1, 1));
|
||||||
|
var gbc = new GridBagConstraints();
|
||||||
|
gbc.gridheight = GridBagConstraints.REMAINDER;
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
gbc.weighty = 1;
|
||||||
|
list.add(spacer, gbc);
|
||||||
|
return spacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ class MainWindow extends JFrame {
|
||||||
// UI components
|
// UI components
|
||||||
private JPanel client; // Common client container
|
private JPanel client; // Common client container
|
||||||
private Console console; // Console window
|
private Console console; // Console window
|
||||||
|
private CPU cpu; // CPU window
|
||||||
private JDesktopPane desktop; // Container for child windows
|
private JDesktopPane desktop; // Container for child windows
|
||||||
private Memory memory; // Memory window
|
private Memory memory; // Memory window
|
||||||
private JPanel video; // Video output
|
private JPanel video; // Video output
|
||||||
|
@ -92,9 +93,11 @@ class MainWindow extends JFrame {
|
||||||
desktop = new JDesktopPane();
|
desktop = new JDesktopPane();
|
||||||
desktop.setBackground(SystemColor.controlShadow);
|
desktop.setBackground(SystemColor.controlShadow);
|
||||||
desktop.add(console = new Console(this));
|
desktop.add(console = new Console(this));
|
||||||
|
desktop.add(cpu = new CPU (this));
|
||||||
desktop.add(memory = new Memory (this));
|
desktop.add(memory = new Memory (this));
|
||||||
|
|
||||||
// Display window
|
// Display window
|
||||||
|
refreshDebug();
|
||||||
pack();
|
pack();
|
||||||
setLocationRelativeTo(null);
|
setLocationRelativeTo(null);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
@ -131,6 +134,11 @@ class MainWindow extends JFrame {
|
||||||
mnuDebugMemory.addActionListener(e->memory.setVisible(true));
|
mnuDebugMemory.addActionListener(e->memory.setVisible(true));
|
||||||
mnuDebug.add(mnuDebugMemory);
|
mnuDebug.add(mnuDebugMemory);
|
||||||
|
|
||||||
|
var mnuDebugCPU = new JMenuItem();
|
||||||
|
loc.add(mnuDebugCPU, "app.debug.cpu");
|
||||||
|
mnuDebugCPU.addActionListener(e->cpu.setVisible(true));
|
||||||
|
mnuDebug.add(mnuDebugCPU);
|
||||||
|
|
||||||
return mnuDebug;
|
return mnuDebug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +186,7 @@ class MainWindow extends JFrame {
|
||||||
|
|
||||||
// Refresh all debug views
|
// Refresh all debug views
|
||||||
void refreshDebug() {
|
void refreshDebug() {
|
||||||
|
cpu .refresh();
|
||||||
memory.refresh();
|
memory.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,6 +292,7 @@ class MainWindow extends JFrame {
|
||||||
var bytes = rom.toByteArray();
|
var bytes = rom.toByteArray();
|
||||||
// Pause emulation
|
// Pause emulation
|
||||||
vue.setROM(bytes, 0, bytes.length);
|
vue.setROM(bytes, 0, bytes.length);
|
||||||
|
vue.reset();
|
||||||
refreshDebug();
|
refreshDebug();
|
||||||
// Resume emulation
|
// Resume emulation
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,13 @@ import util.*;
|
||||||
class Memory extends ChildWindow {
|
class Memory extends ChildWindow {
|
||||||
|
|
||||||
// Private fields
|
// Private fields
|
||||||
private int address; // Address of top row
|
private int address; // Address of top row
|
||||||
private Font font; // Display font
|
private Font font; // Display font
|
||||||
|
private int fontHeight; // Font line height
|
||||||
|
private int fontWidth; // Font maximum character width
|
||||||
|
|
||||||
// UI components
|
// UI components
|
||||||
private JPanel client; // Client area
|
private JPanel client; // Client area
|
||||||
private JLabel fontHeight; // Font height proxy
|
|
||||||
private ArrayList<Row> rows; // Rows of text
|
private ArrayList<Row> rows; // Rows of text
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,23 +45,25 @@ class Memory extends ChildWindow {
|
||||||
super(parent, "memory.title");
|
super(parent, "memory.title");
|
||||||
|
|
||||||
// Configure instance fields
|
// Configure instance fields
|
||||||
address = 0x00000000;
|
address = 0x00000000;
|
||||||
font = new Font(Util.fontFamily(new String[]
|
font = new Font(Util.fontFamily(new String[]
|
||||||
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14);
|
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14);
|
||||||
fontHeight = new JLabel(".");
|
rows = new ArrayList<Row>();
|
||||||
rows = new ArrayList<Row>();
|
|
||||||
|
|
||||||
// Configure client area
|
// Configure client area
|
||||||
client = new JPanel(null);
|
client = new JPanel(null);
|
||||||
client.addComponentListener(Util.onResize(e->onResize()));
|
client.addComponentListener(Util.onResize(e->onResize()));
|
||||||
client.addKeyListener(Util.onKey(e->onKeyDown(e), null));
|
client.addKeyListener(Util.onKey(e->onKeyDown(e), null));
|
||||||
client.addMouseWheelListener(e->onWheel(e));
|
client.addMouseWheelListener(e->onWheel(e));
|
||||||
|
client.setBackground(SystemColor.window);
|
||||||
client.setFocusable(true);
|
client.setFocusable(true);
|
||||||
client.setPreferredSize(new Dimension(640, 480));
|
client.setPreferredSize(new Dimension(640, 480));
|
||||||
client.setBackground(SystemColor.window);
|
|
||||||
|
|
||||||
// Configure component
|
// Configure component
|
||||||
setContentPane(client);
|
var content = new JPanel(new BorderLayout());
|
||||||
|
content.setBorder(new JScrollPane().getBorder());
|
||||||
|
content.add(client, BorderLayout.CENTER);
|
||||||
|
setContentPane(content);
|
||||||
setFont2(font);
|
setFont2(font);
|
||||||
pack();
|
pack();
|
||||||
}
|
}
|
||||||
|
@ -79,11 +82,9 @@ class Memory extends ChildWindow {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Configure working variables
|
// Configure working variables
|
||||||
int height = client.getHeight();
|
int height = client.getHeight();
|
||||||
int lineHeight = fontHeight.getPreferredSize().height;
|
int count = (height + fontHeight - 1) / fontHeight;
|
||||||
int count = (height + lineHeight - 1) / lineHeight;
|
var data = new byte[count * 16];
|
||||||
var data = new byte[count * 16];
|
|
||||||
var widths = new int[2];
|
|
||||||
|
|
||||||
// Retrieve all visible bytes from the emulation context
|
// Retrieve all visible bytes from the emulation context
|
||||||
parent.vue.read(address, data, 0, data.length);
|
parent.vue.read(address, data, 0, data.length);
|
||||||
|
@ -91,26 +92,17 @@ class Memory extends ChildWindow {
|
||||||
// Update visible rows
|
// Update visible rows
|
||||||
for (int x = 0; x < count; x++) {
|
for (int x = 0; x < count; x++) {
|
||||||
Row row;
|
Row row;
|
||||||
|
|
||||||
// Retrieve the row if it exists, make a new one otherwise
|
|
||||||
if (x < rows.size())
|
if (x < rows.size())
|
||||||
row = rows.get(x);
|
row = rows.get(x); // Retrieve row from collection
|
||||||
else row = createRow();
|
else row = createRow(); // Produce a new row
|
||||||
|
update(row, x * fontHeight, address + x * 16, data, x * 16);
|
||||||
// Configure the row
|
|
||||||
update(row, address + x * 16, data, x * 16);
|
|
||||||
setVisible(row, true);
|
setVisible(row, true);
|
||||||
measure(row, widths);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide any rows that are not visible
|
// Hide any rows that are not visible
|
||||||
for (int x = count; x < rows.size(); x++)
|
for (int x = count; x < rows.size(); x++)
|
||||||
setVisible(rows.get(x), false);
|
setVisible(rows.get(x), false);
|
||||||
|
|
||||||
// Position components
|
|
||||||
for (int x = 0; x < rows.size(); x++)
|
|
||||||
arrange(rows.get(x), x * lineHeight, widths, lineHeight);
|
|
||||||
|
|
||||||
// Finalize layout
|
// Finalize layout
|
||||||
client.revalidate();
|
client.revalidate();
|
||||||
client.repaint();
|
client.repaint();
|
||||||
|
@ -119,12 +111,24 @@ class Memory extends ChildWindow {
|
||||||
// Specify a new font
|
// Specify a new font
|
||||||
void setFont2(Font font) {
|
void setFont2(Font font) {
|
||||||
this.font = font;
|
this.font = font;
|
||||||
fontHeight.setFont(font);
|
|
||||||
|
// Configure the maximum font dimensions
|
||||||
|
var fontMax = new JLabel("!");
|
||||||
|
fontMax.setFont(font);
|
||||||
|
fontHeight = Math.max(1, fontMax.getPreferredSize().height);
|
||||||
|
fontWidth = -1;
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
fontMax.setText(Integer.toString(x, 16).toUpperCase());
|
||||||
|
fontWidth = Math.max(fontWidth, fontMax.getPreferredSize().width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure rows
|
||||||
for (var row : rows) {
|
for (var row : rows) {
|
||||||
row.address.setFont(font);
|
row.address.setFont(font);
|
||||||
for (var label : row.bytes)
|
for (var label : row.bytes)
|
||||||
label.setFont(font);
|
label.setFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
onResize();
|
onResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,27 +196,9 @@ class Memory extends ChildWindow {
|
||||||
// Private Methods //
|
// Private Methods //
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Position the elements of a row
|
|
||||||
private void arrange(Row row, int y, int[] widths, int height) {
|
|
||||||
int spacing = (height + 1) / 2;
|
|
||||||
|
|
||||||
// Size and position the address header
|
|
||||||
row.address.setSize(row.address.getPreferredSize());
|
|
||||||
row.address.setLocation(0, y);
|
|
||||||
|
|
||||||
// Size and position the byte labels
|
|
||||||
for (int z = 0, x = widths[0] + height; z < 16; z++) {
|
|
||||||
var label = row.bytes[z];
|
|
||||||
label.setBounds(x, y, widths[1], height);
|
|
||||||
x += widths[1] + (z == 7 ? height : spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a new row of output
|
// Add a new row of output
|
||||||
private Row createRow() {
|
private Row createRow() {
|
||||||
var row = new Row();
|
var row = new Row();
|
||||||
row.address =
|
|
||||||
|
|
||||||
// Address label
|
// Address label
|
||||||
row.address = new JLabel();
|
row.address = new JLabel();
|
||||||
|
@ -260,16 +246,24 @@ class Memory extends ChildWindow {
|
||||||
|
|
||||||
// Determine how many rows of output are visible
|
// Determine how many rows of output are visible
|
||||||
private int tall(boolean partial) {
|
private int tall(boolean partial) {
|
||||||
int lineHeight = fontHeight.getPreferredSize().height;
|
return (client.getHeight() + (partial?fontHeight-1:0)) / fontHeight;
|
||||||
return lineHeight == 0 ? 0 :
|
|
||||||
(client.getHeight() + (partial ? lineHeight + 1 : 0)) / lineHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the text of a row
|
// Update the text of a row
|
||||||
private void update(Row row, int address, byte[] data, int offset) {
|
private void update(Row row, int y, int address, byte[] data, int offset) {
|
||||||
|
|
||||||
|
// Update address
|
||||||
|
row.address.setBounds(0, y, 8 * fontWidth, fontHeight);
|
||||||
row.address.setText(String.format("%08X", address));
|
row.address.setText(String.format("%08X", address));
|
||||||
for (var label : row.bytes)
|
|
||||||
|
// Update bytes
|
||||||
|
for (int z = 0, x = 10 * fontWidth; z < 16; z++) {
|
||||||
|
var label = row.bytes[z];
|
||||||
|
label.setBounds(x, y, 2 * fontWidth, fontHeight);
|
||||||
label.setText(String.format("%02X", data[offset++] & 0xFF));
|
label.setText(String.format("%02X", data[offset++] & 0xFF));
|
||||||
|
x += fontWidth * (z == 7 ? 4 : 3);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,419 @@
|
||||||
|
package app;
|
||||||
|
|
||||||
|
// Java imports
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
// Project imports
|
||||||
|
import util.*;
|
||||||
|
import vue.*;
|
||||||
|
|
||||||
|
// Register list item
|
||||||
|
class Register {
|
||||||
|
|
||||||
|
// Instance fields
|
||||||
|
boolean expanded; // The expanded area is being shown
|
||||||
|
Font font; // Hexadecimal font
|
||||||
|
int index; // Register index
|
||||||
|
int mode; // Display mode for program registers
|
||||||
|
MainWindow parent; // Containing window
|
||||||
|
int type; // Expansion controls type
|
||||||
|
int value; // Current register value
|
||||||
|
|
||||||
|
// UI components
|
||||||
|
private JPanel expansion; // Expansion area
|
||||||
|
private JLabel btnExpand; // Expand button
|
||||||
|
private JLabel lblName; // Register name
|
||||||
|
private JPanel list; // Containing element
|
||||||
|
private JPanel spacer; // Expansion area spacer
|
||||||
|
private JTextField txtValue; // Register value
|
||||||
|
private ArrayList<JComponent> controls; // Expansion controls
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constants //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Modes
|
||||||
|
static final int FLOAT = 3;
|
||||||
|
static final int HEX = 0;
|
||||||
|
static final int SIGNED = 1;
|
||||||
|
static final int UNSIGNED = 2;
|
||||||
|
|
||||||
|
// Types
|
||||||
|
static final int PROGRAM = -2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructors //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Default constructor
|
||||||
|
Register(MainWindow parent, JPanel list, String name, int index, int type){
|
||||||
|
|
||||||
|
// Configure instance fields
|
||||||
|
controls = new ArrayList<JComponent>();
|
||||||
|
this.index = index;
|
||||||
|
this.list = list;
|
||||||
|
this.mode = HEX;
|
||||||
|
this.parent = parent;
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
|
// Click handler for expand and name controls
|
||||||
|
MouseListener expand = type == VUE.PC ? null : Util.onMouse(
|
||||||
|
e->{ if (e.getButton() == 1) setExpanded(!expanded); }, null);
|
||||||
|
|
||||||
|
// Expand button
|
||||||
|
btnExpand = new JLabel(expand != null ? "+" : " ");
|
||||||
|
btnExpand.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
if (expand != null)
|
||||||
|
btnExpand.addMouseListener(expand);
|
||||||
|
var gbc = new GridBagConstraints();
|
||||||
|
gbc.anchor = GridBagConstraints.NORTH;
|
||||||
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
list.add(btnExpand, gbc);
|
||||||
|
|
||||||
|
// Name label
|
||||||
|
lblName = new JLabel(name);
|
||||||
|
if (expand != null)
|
||||||
|
lblName.addMouseListener(expand);
|
||||||
|
gbc = new GridBagConstraints();
|
||||||
|
gbc.anchor = GridBagConstraints.NORTH;
|
||||||
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
gbc.weightx = 1;
|
||||||
|
list.add(lblName, gbc);
|
||||||
|
|
||||||
|
// Value text box
|
||||||
|
txtValue = new JTextField();
|
||||||
|
txtValue.setBorder(null);
|
||||||
|
txtValue.setOpaque(false);
|
||||||
|
txtValue.setText("00000000");
|
||||||
|
gbc = new GridBagConstraints();
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
gbc.insets = new Insets(0, 4, 0, 0);
|
||||||
|
list.add(txtValue, gbc);
|
||||||
|
|
||||||
|
// Value changed
|
||||||
|
txtValue.addActionListener(e->{
|
||||||
|
String text = txtValue.getText();
|
||||||
|
int val = value;
|
||||||
|
try { switch (mode) {
|
||||||
|
case HEX : val = (int) Long.parseLong(text, 16); break;
|
||||||
|
case SIGNED : // Fallthrough
|
||||||
|
case UNSIGNED: val = (int) Long.parseLong(text, 10); break;
|
||||||
|
case FLOAT : val =
|
||||||
|
Float.floatToIntBits(Float.parseFloat(text) ); break;
|
||||||
|
}} catch (Exception x) { }
|
||||||
|
setValue(val);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Expansion controls
|
||||||
|
switch (type) {
|
||||||
|
case PROGRAM : initProgram(); break;
|
||||||
|
case VUE.CHCW: initCHCW (); break;
|
||||||
|
case VUE.ECR : initECR (); break;
|
||||||
|
case VUE.PIR : initPIR (); break;
|
||||||
|
case VUE.PSW : initPSW (); break;
|
||||||
|
case VUE.TKCW: initTKCW (); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expansion spacer
|
||||||
|
spacer = new JPanel(null);
|
||||||
|
spacer.setOpaque(false);
|
||||||
|
spacer.setPreferredSize(new Dimension(0, 0));
|
||||||
|
spacer.setVisible(false);
|
||||||
|
list.add(spacer, new GridBagConstraints());
|
||||||
|
|
||||||
|
// Expansion area
|
||||||
|
expansion.setOpaque(false);
|
||||||
|
expansion.setVisible(false);
|
||||||
|
gbc = new GridBagConstraints();
|
||||||
|
gbc.anchor = GridBagConstraints.WEST;
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
gbc.insets = new Insets(0, 4, 0, 0);
|
||||||
|
list.add(expansion, gbc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Expansion Constructors //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Expansion controls for CHCW
|
||||||
|
private void initCHCW() {
|
||||||
|
expansion = new JPanel(new GridBagLayout());
|
||||||
|
addCheckBox("ICE", 1, false); endRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expansion controls for ECR
|
||||||
|
private void initECR() {
|
||||||
|
expansion = new JPanel(new GridBagLayout());
|
||||||
|
addTextBox("EICC", 0, 16, false, true); endRow();
|
||||||
|
addTextBox("FECC", 16, 16, false, true); endRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expansion controls for program registers
|
||||||
|
private void initProgram() {
|
||||||
|
expansion = new JPanel(new GridBagLayout());
|
||||||
|
var group = new ButtonGroup();
|
||||||
|
group.add(addRadioButton("cpu.hex" , HEX ));
|
||||||
|
group.add(addRadioButton("cpu.signed" , SIGNED ));
|
||||||
|
group.add(addRadioButton("cpu.unsigned", UNSIGNED));
|
||||||
|
group.add(addRadioButton("cpu.float" , FLOAT ));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expansion controls for PSW
|
||||||
|
private void initPSW() {
|
||||||
|
expansion = new JPanel(new GridBagLayout());
|
||||||
|
addCheckBox("Z" , 0, false);
|
||||||
|
addCheckBox("FRO", 9, false); endRow();
|
||||||
|
addCheckBox("S" , 1, false);
|
||||||
|
addCheckBox("FIV", 8, false); endRow();
|
||||||
|
addCheckBox("OV" , 2, false);
|
||||||
|
addCheckBox("FZD", 7, false); endRow();
|
||||||
|
addCheckBox("CY" , 3, false);
|
||||||
|
addCheckBox("FOV", 6, false); endRow();
|
||||||
|
addCheckBox("EP" , 14, false);
|
||||||
|
addCheckBox("FUD", 5, false); endRow();
|
||||||
|
addCheckBox("NP" , 15, false);
|
||||||
|
addCheckBox("FPR", 4, false); endRow();
|
||||||
|
addCheckBox("AE" , 13, false); endRow();
|
||||||
|
addCheckBox("ID" , 12, false);
|
||||||
|
addTextBox ("I" , 16, 4, false, false); endRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expansion controls for PIR
|
||||||
|
private void initPIR() {
|
||||||
|
expansion = new JPanel(new GridBagLayout());
|
||||||
|
addTextBox("PT", 0, 16, true, true); endRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expansion controls for TKCW
|
||||||
|
private void initTKCW() {
|
||||||
|
expansion = new JPanel(new GridBagLayout());
|
||||||
|
addCheckBox("OTM", 8, true);
|
||||||
|
addCheckBox("FVT", 5, true); endRow();
|
||||||
|
addCheckBox("FIT", 7, true);
|
||||||
|
addCheckBox("FUT", 4, true); endRow();
|
||||||
|
addCheckBox("FZT", 6, true);
|
||||||
|
addCheckBox("FPT", 3, true); endRow();
|
||||||
|
addCheckBox("RDI", 2, true);
|
||||||
|
addTextBox ("RD", 0, 2, true, false); endRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Package Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Refresh controls
|
||||||
|
void refresh() {
|
||||||
|
|
||||||
|
// Value text box
|
||||||
|
value = parent.vue.getRegister(index, type != PROGRAM);
|
||||||
|
txtValue.setText(
|
||||||
|
type != PROGRAM || mode == HEX ?
|
||||||
|
String.format("%08X", value) :
|
||||||
|
mode == SIGNED ? Integer.toString(value) :
|
||||||
|
mode == UNSIGNED ? Long.toString(value & 0xFFFFFFFFL) :
|
||||||
|
Float.toString(Float.intBitsToFloat(value))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Expansion controls
|
||||||
|
for (var control : controls) {
|
||||||
|
|
||||||
|
// Check box
|
||||||
|
if (control instanceof JCheckBox) {
|
||||||
|
var ctrl = (JCheckBox) control;
|
||||||
|
int bit = (Integer) ctrl.getClientProperty("bit");
|
||||||
|
ctrl.setSelected((value & 1 << bit) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text box
|
||||||
|
if (control instanceof JTextField) {
|
||||||
|
var ctrl = (JTextField) control;
|
||||||
|
int bit = (Integer) ctrl.getClientProperty("bit" );
|
||||||
|
int digits = (Integer) ctrl.getClientProperty("digits");
|
||||||
|
boolean hex = (Boolean) ctrl.getClientProperty("hex");
|
||||||
|
int width = (Integer) ctrl.getClientProperty("width");
|
||||||
|
int val = value >> bit & (1 << width) - 1;
|
||||||
|
ctrl.setText(!hex ? Integer.toString(val) :
|
||||||
|
String.format("%0" + digits + "X", val));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify whether the expansion area is expanded
|
||||||
|
void setExpanded(boolean expanded) {
|
||||||
|
|
||||||
|
// Error checking
|
||||||
|
if (type == VUE.PC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Update controls
|
||||||
|
this.expanded = expanded;
|
||||||
|
btnExpand.setText (expanded ? "-" : "+");
|
||||||
|
expansion.setVisible(expanded);
|
||||||
|
spacer .setVisible(expanded);
|
||||||
|
list.revalidate();
|
||||||
|
list.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify the width of the expand button
|
||||||
|
void setExpandWidth(int width) {
|
||||||
|
var size = btnExpand.getPreferredSize();
|
||||||
|
size.width = width;
|
||||||
|
btnExpand.setPreferredSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify a new font
|
||||||
|
void setFont(Font font, int fontWidth, int fontHeight) {
|
||||||
|
this.font = font;
|
||||||
|
|
||||||
|
// Value text box
|
||||||
|
txtValue.setFont(font);
|
||||||
|
txtValue.setPreferredSize(
|
||||||
|
new Dimension(8 * fontWidth + 4, fontHeight));
|
||||||
|
|
||||||
|
// Expansion controls
|
||||||
|
for (var ctrl : controls) {
|
||||||
|
if (!(ctrl instanceof JTextField))
|
||||||
|
continue;
|
||||||
|
if ((Boolean) ctrl.getClientProperty("hex"))
|
||||||
|
((JTextField) ctrl).setFont(font);
|
||||||
|
int digits = (Integer) ctrl.getClientProperty("digits");
|
||||||
|
var size = ctrl.getPreferredSize();
|
||||||
|
size.width = digits * fontWidth + 4;
|
||||||
|
ctrl.setPreferredSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the display mode of a program register
|
||||||
|
void setMode(int mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
txtValue.setFont(mode == HEX ? font : null);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Add a check box to the expansion area
|
||||||
|
private void addCheckBox(String name, int bit, boolean readOnly) {
|
||||||
|
int mask = 1 << bit;
|
||||||
|
|
||||||
|
// Configure control
|
||||||
|
var ctrl = new JCheckBox(name);
|
||||||
|
ctrl.putClientProperty("bit", bit);
|
||||||
|
ctrl.setBorder(null);
|
||||||
|
ctrl.setEnabled(!readOnly);
|
||||||
|
ctrl.setFocusable(false);
|
||||||
|
ctrl.setOpaque(false);
|
||||||
|
controls.add(ctrl);
|
||||||
|
|
||||||
|
// Event handler
|
||||||
|
ctrl.addItemListener(e->setValue(
|
||||||
|
e.getStateChange() == ItemEvent.SELECTED ?
|
||||||
|
value | mask : value & ~mask
|
||||||
|
));
|
||||||
|
|
||||||
|
// Configure expansion area
|
||||||
|
var gbc = new GridBagConstraints();
|
||||||
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
gbc.insets = new Insets(0, 4, 0, 0);
|
||||||
|
expansion.add(ctrl, gbc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a radio button to the expansion area
|
||||||
|
private JRadioButton addRadioButton(String key, int mode) {
|
||||||
|
|
||||||
|
// Configure control
|
||||||
|
var ctrl = new JRadioButton();
|
||||||
|
parent.app.getLocalizer().add(ctrl, key);
|
||||||
|
ctrl.setBorder(null);
|
||||||
|
ctrl.setFocusable(false);
|
||||||
|
ctrl.setOpaque(false);
|
||||||
|
ctrl.setSelected(mode == HEX);
|
||||||
|
controls.add(ctrl);
|
||||||
|
|
||||||
|
// Event handler
|
||||||
|
ctrl.addItemListener(e->{
|
||||||
|
if (e.getStateChange() == ItemEvent.SELECTED) setMode(mode); });
|
||||||
|
|
||||||
|
// Configure expansion area
|
||||||
|
var gbc = new GridBagConstraints();
|
||||||
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
gbc.insets = new Insets(0, 4, 0, 0);
|
||||||
|
expansion.add(ctrl, gbc);
|
||||||
|
|
||||||
|
return ctrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a text box to the expansion area
|
||||||
|
private void addTextBox(String name, int bit, int width, boolean readOnly,
|
||||||
|
boolean hex) {
|
||||||
|
int mask = (1 << width) - 1;
|
||||||
|
|
||||||
|
// Configure control
|
||||||
|
var ctrl = new JTextField();
|
||||||
|
ctrl.putClientProperty("bit", bit);
|
||||||
|
ctrl.putClientProperty("digits",
|
||||||
|
Integer.toString(mask, hex ? 16 : 10).length());
|
||||||
|
ctrl.putClientProperty("hex", hex);
|
||||||
|
ctrl.putClientProperty("width", width);
|
||||||
|
ctrl.setBorder(null);
|
||||||
|
ctrl.setEnabled(!readOnly);
|
||||||
|
ctrl.setOpaque(false);
|
||||||
|
controls.add(ctrl);
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
|
ctrl.addActionListener(e->{
|
||||||
|
int val = value >> bit & mask;
|
||||||
|
try { val = Integer.parseInt(ctrl.getText(), hex ? 16 : 10); }
|
||||||
|
catch (Exception x) { }
|
||||||
|
setValue(value & ~(mask << bit) | (val & mask) << bit);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Configure expansion area
|
||||||
|
var label = new JLabel(name);
|
||||||
|
label.setEnabled(!readOnly);
|
||||||
|
var gbc = new GridBagConstraints();
|
||||||
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
||||||
|
gbc.insets = new Insets(0, 4, 0, 4);
|
||||||
|
expansion.add(label, gbc);
|
||||||
|
expansion.add(ctrl , gbc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate a row of expansion controls
|
||||||
|
private void endRow() {
|
||||||
|
var spacer = new JPanel(null);
|
||||||
|
spacer.setOpaque(false);
|
||||||
|
spacer.setPreferredSize(new Dimension(0, 0));
|
||||||
|
var gbc = new GridBagConstraints();
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
expansion.add(spacer, gbc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the register value
|
||||||
|
private void setValue(int value) {
|
||||||
|
list.requestFocus();
|
||||||
|
parent.vue.setRegister(index, type != PROGRAM, value);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,12 +28,13 @@ public final class Util {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Event listener interfaces
|
// Event listener interfaces
|
||||||
public interface OnClose { void call(WindowEvent e); }
|
public interface OnClose { void call(WindowEvent e); }
|
||||||
public interface OnClose2 { void call(InternalFrameEvent e); }
|
public interface OnClose2 { void call(InternalFrameEvent e); }
|
||||||
public interface OnFocus { void call(FocusEvent e); }
|
public interface OnFocus { void call(FocusEvent e); }
|
||||||
public interface OnKey { void call(KeyEvent e); }
|
public interface OnKey { void call(KeyEvent e); }
|
||||||
public interface OnMouse { void call(MouseEvent e); }
|
public interface OnMouse { void call(MouseEvent e); }
|
||||||
public interface OnResize { void call(ComponentEvent e); }
|
public interface OnResize { void call(ComponentEvent e); }
|
||||||
|
public interface OnVisible { void call(AncestorEvent e); }
|
||||||
|
|
||||||
// Data class for byte-order marks
|
// Data class for byte-order marks
|
||||||
private static class BOM {
|
private static class BOM {
|
||||||
|
@ -310,6 +311,17 @@ public final class Util {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Produce an AncestorListener using functional interfaces
|
||||||
|
public static AncestorListener onVisible(OnVisible show, OnVisible hide) {
|
||||||
|
return new AncestorListener() {
|
||||||
|
public void ancestorMoved (AncestorEvent e) { }
|
||||||
|
public void ancestorAdded (AncestorEvent e)
|
||||||
|
{ if (show != null) show.call(e); }
|
||||||
|
public void ancestorRemoved(AncestorEvent e)
|
||||||
|
{ if (hide != null) hide.call(e); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Configure the Swing look-and-feel with the system theme
|
// Configure the Swing look-and-feel with the system theme
|
||||||
public static boolean setSystemLAF() {
|
public static boolean setSystemLAF() {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -87,6 +87,11 @@ class Bus {
|
||||||
return 0; // Unreachable
|
return 0; // Unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform a system reset
|
||||||
|
public void reset() {
|
||||||
|
Arrays.fill(wram, 0, 0x10000, (byte) 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Write bytes to host memory
|
// Write bytes to host memory
|
||||||
void writeBytes(byte[] dest,byte[] src,int address,int offset,int length) {
|
void writeBytes(byte[] dest,byte[] src,int address,int offset,int length) {
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ class CPU {
|
||||||
// Package fields
|
// Package fields
|
||||||
int cycles; // Cycles until next stage
|
int cycles; // Cycles until next stage
|
||||||
int fetch; // Fetch unit index
|
int fetch; // Fetch unit index
|
||||||
|
int lastPC; // Previous value of PC
|
||||||
int stage; // Current processing stage
|
int stage; // Current processing stage
|
||||||
|
|
||||||
// Program registers
|
// Program registers
|
||||||
|
@ -113,7 +114,19 @@ class CPU {
|
||||||
|
|
||||||
// Remaining cases to encourage tableswitch
|
// Remaining cases to encourage tableswitch
|
||||||
case 8: case 9: case 10: case 11: case 12: case 13: case 14:
|
case 8: case 9: case 10: case 11: case 12: case 13: case 14:
|
||||||
case 15: case 16: case 17: case 18: case 19: case 20: case 21:
|
case 15: case 16: case 17: case 18: case 19: case 20: case 21: // Configure instance fields
|
||||||
|
cycles = 0;
|
||||||
|
fetch = 0;
|
||||||
|
stage = FETCH;
|
||||||
|
|
||||||
|
// Reset program counter
|
||||||
|
pc = 0xFFFFFFF0;
|
||||||
|
|
||||||
|
// Clear all registers (hardware only sets ECR, PC and PSW)
|
||||||
|
for (int x = 0; x < 32; x++) {
|
||||||
|
program[x] = 0;
|
||||||
|
setSystemRegister(x, 0, true);
|
||||||
|
}
|
||||||
case 22: case 23: case 26: case 27: case 28:
|
case 22: case 23: case 26: case 27: case 28:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -128,15 +141,17 @@ class CPU {
|
||||||
fetch = 0;
|
fetch = 0;
|
||||||
stage = FETCH;
|
stage = FETCH;
|
||||||
|
|
||||||
// Reset program counter
|
|
||||||
pc = 0xFFFFFFF0;
|
|
||||||
|
|
||||||
// Clear all registers (hardware only sets ECR, PC and PSW)
|
// Clear all registers (hardware only sets ECR, PC and PSW)
|
||||||
for (int x = 0; x < 32; x++) {
|
for (int x = 0; x < 32; x++) {
|
||||||
program[x] = 0;
|
program[x] = 0;
|
||||||
setSystemRegister(x, 0, true);
|
setSystemRegister(x, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure registers
|
||||||
|
ecr_eicc = 0xFFF0;
|
||||||
|
lastPC = 0xFFFFFFF0;
|
||||||
|
pc = 0xFFFFFFF0;
|
||||||
|
psw_np = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a system register
|
// Write a system register
|
||||||
|
@ -150,6 +165,13 @@ class CPU {
|
||||||
case 29 : return sr29 = value;
|
case 29 : return sr29 = value;
|
||||||
case 31 : return sr31 = debug || value >= 0 ? value : -value;
|
case 31 : return sr31 = debug || value >= 0 ? value : -value;
|
||||||
|
|
||||||
|
case VUE.ECR:
|
||||||
|
if (debug) {
|
||||||
|
ecr_fecc = value >> 16 & 0xFFFF;
|
||||||
|
ecr_eicc = value & 0xFFFF;
|
||||||
|
}
|
||||||
|
return ecr_fecc << 16 | ecr_eicc;
|
||||||
|
|
||||||
case VUE.CHCW :
|
case VUE.CHCW :
|
||||||
chcw_cen = value >> 20 & 0x00000FFF;
|
chcw_cen = value >> 20 & 0x00000FFF;
|
||||||
chcw_cec = value >> 8 & 0x00000FFF;
|
chcw_cec = value >> 8 & 0x00000FFF;
|
||||||
|
@ -181,10 +203,10 @@ class CPU {
|
||||||
return value & 0x000FF3FF;
|
return value & 0x000FF3FF;
|
||||||
|
|
||||||
// Remaining cases to encourage tableswitch
|
// Remaining cases to encourage tableswitch
|
||||||
case 4: case 6: case 7: case 8: case 9: case 10: case 11:
|
case 6: case 7: case 8: case 9: case 10: case 11: case 12:
|
||||||
case 12: case 13: case 14: case 15: case 16: case 17: case 18:
|
case 13: case 14: case 15: case 16: case 17: case 18: case 19:
|
||||||
case 19: case 20: case 21: case 22: case 23: case 26: case 27:
|
case 20: case 21: case 22: case 23: case 26: case 27: case 28:
|
||||||
case 28: case 30:
|
case 30:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1; // Unreachable
|
return 1; // Unreachable
|
||||||
|
|
|
@ -26,6 +26,7 @@ class JavaVUE extends VUE {
|
||||||
JavaVUE() {
|
JavaVUE() {
|
||||||
bus = new Bus(this);
|
bus = new Bus(this);
|
||||||
cpu = new CPU(this);
|
cpu = new CPU(this);
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,13 +109,19 @@ class JavaVUE extends VUE {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize all system components
|
||||||
|
public void reset() {
|
||||||
|
bus.reset();
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
// Specify a register value
|
// Specify a register value
|
||||||
public int setRegister(int index, boolean system, int value) {
|
public int setRegister(int index, boolean system, int value) {
|
||||||
return
|
return
|
||||||
index == VUE.PC && system ? cpu.pc = value & 0xFFFFFFFE :
|
index == VUE.PC && system ? cpu.pc = value & 0xFFFFFFFE :
|
||||||
index < 0 || index > 31 ? 0 :
|
index < 0 || index > 31 ? 0 :
|
||||||
system ? cpu.setSystemRegister(index, value, true) :
|
system ? cpu.setSystemRegister(index, value, true) :
|
||||||
index == 0 ? 0 : cpu.program[index]
|
index == 0 ? 0 : (cpu.program[index] = value)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// Native-backed emulation core implementation
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
@ -21,7 +23,7 @@ static const int TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
|
||||||
|
|
||||||
// Core context state type
|
// Core context state type
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VUE vue;
|
VUE vue; /* Context into the generic C library */
|
||||||
} CORE;
|
} CORE;
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +61,7 @@ JNIEXPORT void JNICALL Java_vue_NativeVUE_construct
|
||||||
// Produce and initialize s new core context
|
// Produce and initialize s new core context
|
||||||
CORE *core = calloc(sizeof (CORE), 1);
|
CORE *core = calloc(sizeof (CORE), 1);
|
||||||
vueInitialize(&core->vue);
|
vueInitialize(&core->vue);
|
||||||
|
vueReset(&core->vue);
|
||||||
|
|
||||||
// Encode the context handle into a byte array
|
// Encode the context handle into a byte array
|
||||||
jbyteArray pointer = (*env)->NewByteArray(env, sizeof (void *));
|
jbyteArray pointer = (*env)->NewByteArray(env, sizeof (void *));
|
||||||
|
@ -83,7 +86,7 @@ JNIEXPORT void JNICALL Java_vue_NativeVUE_dispose
|
||||||
JNIEXPORT jint JNICALL Java_vue_NativeVUE_getRegister
|
JNIEXPORT jint JNICALL Java_vue_NativeVUE_getRegister
|
||||||
(JNIEnv *env, jobject vue, jint index, jboolean system) {
|
(JNIEnv *env, jobject vue, jint index, jboolean system) {
|
||||||
CORE *core = GetCore(env, vue);
|
CORE *core = GetCore(env, vue);
|
||||||
return vueGetRegister(&core->vue, index, system);
|
return vueGetRegister(&core->vue, index, system);;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve a copy of the ROM data
|
// Retrieve a copy of the ROM data
|
||||||
|
@ -130,6 +133,13 @@ JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_read
|
||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize all system components
|
||||||
|
JNIEXPORT void JNICALL Java_vue_NativeVUE_reset
|
||||||
|
(JNIEnv *env, jobject vue) {
|
||||||
|
CORE *core = GetCore(env, vue);
|
||||||
|
vueReset(&core->vue);
|
||||||
|
}
|
||||||
|
|
||||||
// Specify a register value
|
// Specify a register value
|
||||||
JNIEXPORT jint JNICALL Java_vue_NativeVUE_setRegister
|
JNIEXPORT jint JNICALL Java_vue_NativeVUE_setRegister
|
||||||
(JNIEnv *env, jobject vue, jint index, jboolean system, jint value) {
|
(JNIEnv *env, jobject vue, jint index, jboolean system, jint value) {
|
|
@ -39,6 +39,9 @@ class NativeVUE extends VUE {
|
||||||
public native boolean read(int address, byte[] dest, int offset,
|
public native boolean read(int address, byte[] dest, int offset,
|
||||||
int length);
|
int length);
|
||||||
|
|
||||||
|
// Initialize all system components
|
||||||
|
public native void reset();
|
||||||
|
|
||||||
// Specify a register value
|
// Specify a register value
|
||||||
public native int setRegister(int index, boolean system, int value);
|
public native int setRegister(int index, boolean system, int value);
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,13 @@ public abstract class VUE {
|
||||||
public static final int PSW = 5;
|
public static final int PSW = 5;
|
||||||
public static final int TKCW = 7;
|
public static final int TKCW = 7;
|
||||||
|
|
||||||
|
// Program register indexes
|
||||||
|
public static final int GP = 4;
|
||||||
|
public static final int HP = 2;
|
||||||
|
public static final int LP = 31;
|
||||||
|
public static final int SP = 3;
|
||||||
|
public static final int TP = 5;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -81,6 +88,9 @@ public abstract class VUE {
|
||||||
public abstract boolean read(int address, byte[] dest, int offset,
|
public abstract boolean read(int address, byte[] dest, int offset,
|
||||||
int length);
|
int length);
|
||||||
|
|
||||||
|
// Initialize all system components
|
||||||
|
public abstract void reset();
|
||||||
|
|
||||||
// Specify a register value
|
// Specify a register value
|
||||||
public abstract int setRegister(int index, boolean system, int value);
|
public abstract int setRegister(int index, boolean system, int value);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue