Precursor to VIP introduction

This commit is contained in:
Guy Perfect 2020-12-23 12:26:02 -06:00
parent d636719775
commit 9f5a5233ea
19 changed files with 636 additions and 348 deletions

View File

@ -135,7 +135,7 @@
border-width: 0 1px 1px 0;
}
.bordered tr > :first-child {
.bordered tr > :first-child, .op1 {
padding: 1px 12px 1px 12px;
text-align: center;
}
@ -245,12 +245,12 @@
</p>
<p>
Floats, like words, are represented as sequences of character digits. They
are differentiated from words by the presence of a dot <code>.</code>
are distinguished from words by the presence of a dot <code>.</code>
character somewhere within the sequence. Only one dot may be present in a
float literal, and dots cannot be used in hexadecimal literals. If the given
value cannot be represented in the float data type, a parsing error occurs.
Float values in the expression evaluator are subjected to the same
restrictions as on the Virtual Boy's CPU: if the result of any float
Float values in the expression evaluator are subjected to the following
restrictions: if the value of any float literal or the result of any float
operation is NaN, an infinity, a denormal number or negative zero, it will be
changed to positive zero.
</p>
@ -259,7 +259,7 @@
slightly different. When used in a numeric operation, a boolean will use the
value <code>0</code> if false or the value <code>1</code> if true. Boolean
literals are specified with the named values <code>true</code> and
<code>false</code> within the expression. In a boolean operation, any result
<code>false</code> within the expression. In a boolean operation, any value
that is zero is considered false, and any non-zero value is considered true.
</p>
<p>
@ -298,13 +298,13 @@
<td class="mono">disp</td>
<td>Displacement offset for jumps and memory accesses.</td>
</tr>
<tr>
<!--tr>
<td class="mono">fetch</td>
<td>
Data unit index during a fetch operation, or <code>-1</code> if the read
operation is not a fetch.
</td>
</tr>
</tr-->
<tr>
<td class="mono">format</td>
<td>Current instruction's encoding format.</td>
@ -354,7 +354,7 @@
</tr>
<tr>
<td class="mono">value</td>
<td>Value read by the current memory access.</td>
<td>Value read or to be written by the current memory access.</td>
</tr>
<tr>
<td class="mono">vector</td>
@ -434,15 +434,14 @@
<p>
Operators may apply to one (unary) or two (binary) values. All unary
operators appear to the left of the value they modify (or another unary
operator). Binary operators appear between the values they modify. Each
operator considers the types of its operands in order to produce a new value
of the appropriate type.
operator). Binary operators appear between the values they modify.
</p>
<p>
If the operands of a binary operator have different types, one of the values
will be converted to the other type before performing the operation. The
conversion depends on the "greater" of the two types, in the following order
(higher is "greater"):
Each operator considers the types of its operands in order to produce a new
value of the appropriate type. If the operands of a binary operator have
different types, one of the values will be converted to the other type before
performing the operation. The conversion selects the "greater" of the two
types, in the following order (higher is "greater"):
</p>
<table class="indent">
<tr><td class="center narrow">&uarr;</td><td>Float</td></tr>
@ -452,7 +451,7 @@
</table>
<p>
For example, if an operation contains both a signed word and a float, the
signed word value is first converted to float.
signed word value is converted to float before performing the operation.
</p>
<p>
Operators have assigned precedence that specifies the order of operations.
@ -467,12 +466,14 @@
<p>
The following operators may be used in expressions. Groups listed higher have
higher precedence and happen before groups listed lower. Operators within
groups have the same precedence and are processed in the order they appear in
the expression from left to right.
groups have the same precedence and are processed according to the order in
which they appear in the expression: right-to-left for unary operators,
left-to-right for binary operators.
</p>
<table class="indent bordered">
<tr>
<td class="mono open">~</td>
<td rowSpan="18" class="middle">Unary</td>
<td class="mono open op1">~</td>
<td class="open">Not Bitwise</td>
<td class="open">Cannot be used with a float value.</td>
</tr>
@ -562,7 +563,8 @@
<td>The binary value is not modified.</td>
</tr>
<tr>
<td class="mono open">/</td>
<td rowSpan="20" class="middle">Binary</td>
<td class="mono open op1">/</td>
<td class="open">Divide</td>
<td class="open">Zero divisor yields zero as result.</td>
</tr>
@ -589,17 +591,17 @@
<tr>
<td class="mono open">&lt;&lt;</td>
<td class="open">Shift Left</td>
<td class="open">Cannot be used with a float value.</td>
<td class="open">Cannot be used with float values.</td>
</tr>
<tr>
<td class="mono open">&gt;&gt;</td>
<td class="open">Shift Right Arithmetic</td>
<td class="open">Cannot be used with a float value.</td>
<td class="open">Cannot be used with float values.</td>
</tr>
<tr>
<td class="mono">&gt;&gt;&gt;</td>
<td>Shift Right Logical</td>
<td>Cannot be used with a float value.</td>
<td>Cannot be used with float values.</td>
</tr>
<tr>
<td class="mono open">&gt;</td>
@ -634,17 +636,17 @@
<tr>
<td class="mono">&amp;</td>
<td>And Bitwise</td>
<td>Cannot be used with a float value.</td>
<td>Cannot be used with float values.</td>
</tr>
<tr>
<td class="mono">^</td>
<td>Exclusive Or Bitwise</td>
<td>Cannot be used with a float value.</td>
<td>Cannot be used with float values.</td>
</tr>
<tr>
<td class="mono">|</td>
<td>Or Bitwise</td>
<td>Cannot be used with a float value.</td>
<td>Cannot be used with float values.</td>
</tr>
<tr>
<td class="mono">&amp;&amp;</td>
@ -691,6 +693,13 @@
<td>Performs a halfword read of the specified signedness.</td>
</tr>
</table>
<p>
Reads are subjected to the alginment restrictions of the Virtual Boy's CPU:
the lowest bit of the address is ignored for halfword reads, and the lowest
two bits of the address are ignored for word reads.
</p>
<h1>&nbsp;</h1>
</body>
</html>

View File

@ -68,11 +68,33 @@ breakpoints {
}
# Characters window
characters {
address Address
grid Grid
index Index
mirror Mirror
Palette Palette
scale Scale
title Characters
wide Wide
}
# Console window
console {
title Console
}
# Emulation core
core {
java Java
linux-x86 Linux (32-bit)
linux-x86_64 Linux (64-bit)
native Native
windows-x86 Windows (32-bit)
windows-x86_64 Windows (64-bit)
}
# CPU window
cpu {
float Float
@ -84,21 +106,6 @@ cpu {
unsigned Unsigned
}
# Memory window
memory {
title Memory
}
# Emulation core
core {
java Java
linux-x86 Linux (32-bit)
linux-x86_64 Linux (64-bit)
native Native
windows-x86 Windows (32-bit)
windows-x86_64 Windows (64-bit)
}
# File dialog
dialog {
ext_isx ISX modules (*.isx)
@ -108,3 +115,21 @@ dialog {
load_rom_error Unable to load the selected ROM file.
load_rom_notvb The selected file does not appear to be a Virtual Boy ROM.
}
# Memory window
memory {
title Memory
}
# Palettes
palette {
Generic Generic
gplt0 BG 0
gplt1 BG 1
gplt2 BG 2
gplt3 BG 3
jplt0 OBJ 0
jplt1 OBJ 1
jplt2 OBJ 2
jplt3 OBJ 3
}

View File

@ -1164,7 +1164,7 @@ static vbool cpuFetch(Vue *vue) {
/* First unit */
if (vue->cpu.fetch == 0) {
vue->cpu.inst.bits = vue->cpu.access.value << 16;
if (cpuSize(vue->cpu.access.value >> 10 & 0x3F) == 4) {
if (cpuSize(vue->cpu.access.value >> 10) == 4) {
vue->cpu.fetch = 1;
return VUE_FALSE;
}
@ -1172,7 +1172,7 @@ static vbool cpuFetch(Vue *vue) {
/* Second unit */
else {
vue->cpu.inst.bits |= vue->cpu.access.value & 0xFFFF;
vue->cpu.inst.bits |= vue->cpu.access.value;
vue->cpu.fetch = -1;
}

View File

@ -1,7 +1,9 @@
package app;
// Java imports
import java.awt.*;
import java.util.*;
import javax.swing.*;
// Project imports
import util.*;
@ -16,7 +18,28 @@ public class App {
private ArrayList<MainWindow> windows; // Application windows
// Configuration fields
Util.Font fntDialog; // Dialog font
Util.Font fntMono; // Monospaced font
int hexDigitWidth; // Width in pixels of one hex digit
Localizer localizer; // UI localization manager
int[][] rgbBase; // Base anaglyph filter colors
///////////////////////////////////////////////////////////////////////////
// Constants //
///////////////////////////////////////////////////////////////////////////
// Anaglyph presets
static final int[] RED = { 0xFF, 0x00, 0x00 };
static final int[] CYAN = { 0x00, 0xC6, 0xF0 };
static final int[] GREEN = { 0x00, 0xB4, 0x00 };
static final int[] MAGENTA = { 0xC8, 0x00, 0xFF };
// Eyes
static final int LEFT = 0;
static final int RIGHT = 1;
static final int CHR = 2;
@ -27,10 +50,17 @@ public class App {
// Default constructor
public App(boolean useNative) {
// Instance fields
// Configure instance fields
localizer = new Localizer();
windows = new ArrayList<MainWindow>();
// Configure config fields
fntDialog = new Util.Font(new JLabel().getFont());
fntMono = new Util.Font(new Font(Util.fontFamily(new String[]
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14));
hexDigitWidth = hexDigitWidth();
rgbBase = new int[][] { GREEN, MAGENTA, RED };
// Additional processing
setUseNative(useNative);
initLocales();
@ -83,6 +113,14 @@ public class App {
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Calculate the maximum hexadecimal digit width
private int hexDigitWidth() {
int width = 0;
for (var digit : "0123456789ABCDEFabcdef".toCharArray())
width = Math.max(width, fntMono.metrics.charWidth(digit));
return width;
}
// Load and parse all locale translations
private void initLocales() {

View File

@ -14,7 +14,6 @@ import vue.*;
class BreakpointsWindow extends ChildWindow {
// Private fields
private Font font; // Display font
private ArrayList<Item> items; // List items
private int selectedIndex; // Selected list item
@ -133,7 +132,7 @@ class BreakpointsWindow extends ChildWindow {
else if (breakpoint.any() && breakpoint.evaluate(inst, acc))
lblStatus.setText("\u2605"); // Star
else lblStatus.setText(" ");
int lineHeight = lblStatus.getPreferredSize().height;
int lineHeight = parent.app.fntDialog.metrics.getHeight();
lblStatus.setPreferredSize(new Dimension(lineHeight, lineHeight));
}
@ -158,8 +157,6 @@ class BreakpointsWindow extends ChildWindow {
super(parent, "breakpoints.title");
// Configure instance fields
font = new Font(Util.fontFamily(new String[]
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14);
items = new ArrayList<Item>();
selectedIndex = -1;
@ -183,7 +180,7 @@ class BreakpointsWindow extends ChildWindow {
lstBreakpoints.addMouseListener(Util.onMouse(e->onMouseDown(e), null));
var scr = new JScrollPane(lstBreakpoints);
client.add(scr, BorderLayout.CENTER);
spacer = new JPanel(null);
spacer = new JPanel();
spacer.setOpaque(false);
lstBreakpoints.add(spacer, SPACER);
@ -223,7 +220,7 @@ class BreakpointsWindow extends ChildWindow {
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
props.add(buttons, gbc);
var fill = new JPanel(null);
var fill = new JPanel();
fill.setOpaque(false);
fill.addMouseListener(Util.onMouse(e->onDebug(e), null));
gbc = new GridBagConstraints();
@ -602,7 +599,7 @@ class BreakpointsWindow extends ChildWindow {
var txt = new JTextField();
txt.setEnabled(false);
if (mono)
txt.setFont(font);
txt.setFont(parent.app.fntMono);
txt.addActionListener(e->client.requestFocus());
txt.addFocusListener (Util.onFocus(null, e->handler.run()));
var gbc = new GridBagConstraints();

View File

@ -13,7 +13,7 @@ import vue.*;
// CPU window
class CPUWindow extends ChildWindow {
// Package fields
// Instance fields
MainWindow parent; // Containing window
// UI components
@ -23,70 +23,6 @@ class CPUWindow extends ChildWindow {
///////////////////////////////////////////////////////////////////////////
// Global Settings //
///////////////////////////////////////////////////////////////////////////
static Font dasmFont; // Disassembler font
static int dasmFontHeight; // Disassembler font line height
static int regExpandWidth; // Width of register list expand button
static Font regHexFont; // Register list hex font
static Dimension regHexFontSize; // Max dimensions
static HashSet<CPUWindow> instances; // Spawned instances
// Static initializer
static {
setDefaults();
instances = new HashSet<CPUWindow>();
}
///////////////////////////////////////////////////////////////////////////
// Static Methods //
///////////////////////////////////////////////////////////////////////////
// Apply configuration settings to all instances
static void configureAll() {
for (var inst : instances)
inst.configure();
}
// Reset all settings to their default values
static void setDefaults() {
// Register list hex font
setRegHexFont(new Font(Util.fontFamily(new String[]
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14));
// Width of register list expand button
var label = new JLabel("+");
regExpandWidth = label.getPreferredSize().width;
label.setText("-");
regExpandWidth = Math.max(regExpandWidth,
label.getPreferredSize().width) + 4;
// Disassembler font
setDasmFont(new Font(Util.fontFamily(new String[]
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14));
}
// Specify a font to use as the disassembler font
static void setDasmFont(Font font) {
dasmFont = font;
var label = new JLabel("!");
label.setFont(font);
dasmFontHeight = label.getPreferredSize().height;
}
// Specify a font to use as the register list hex font
static void setRegHexFont(Font font) {
regHexFont = font;
regHexFontSize = measureHex(font);
}
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
@ -94,7 +30,6 @@ class CPUWindow extends ChildWindow {
// Default constructor
CPUWindow(MainWindow parent) {
super(parent, "cpu.title");
instances.add(this);
// Configure instance fields
this.parent = parent;
@ -117,34 +52,15 @@ class CPUWindow extends ChildWindow {
var client = getContentPane();
client.add(outer);
client.setPreferredSize(new Dimension(480, 300));
configure();
pack();
}
///////////////////////////////////////////////////////////////////////////
// Public Methods //
///////////////////////////////////////////////////////////////////////////
// The window is closing
public void dispose() {
instances.remove(this);
super.dispose();
}
///////////////////////////////////////////////////////////////////////////
// Package Methods //
///////////////////////////////////////////////////////////////////////////
// Apply configuration settings
void configure() {
panDasm .configure();
lstProgram.configure();
lstSystem .configure();
}
// Update the display
void refresh(boolean seekToPC) {
panDasm .refresh(seekToPC);
@ -152,42 +68,4 @@ class CPUWindow extends ChildWindow {
lstProgram.refresh();
}
///////////////////////////////////////////////////////////////////////////
// Event Handlers //
///////////////////////////////////////////////////////////////////////////
// Client resize
private void onResize() {
//refreshDasm();
}
///////////////////////////////////////////////////////////////////////////
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Determine the maximum width of a hex character in a font
private static Dimension measureHex(Font font) {
int ret = 0;
Dimension size = null;
// Process all digits
var label = new JLabel();
label.setFont(font);
for (int x = 0; x < 16; x++) {
label.setText(String.format(
"%" + (Disassembler.hexCaps ? "X" : "x"
), x));
size = label.getPreferredSize();
ret = Math.max(ret, size.width);
}
return new Dimension(ret, size.height);
}
}

View File

@ -0,0 +1,317 @@
package app;
// Java imports
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
// Project imports
import util.*;
// VIP characters window
class CharactersWindow extends ChildWindow {
// Instance fields
private int color; // Selected color index
// UI components
private JPanel client; // Client area
private JPanel panCharacters; // Characters panel
private JPanel panPalette; // Palette panel
private JPanel panPattern; // Pattern panel
private JScrollPane scrControls; // Controls panel
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
// Default constructor
CharactersWindow(MainWindow parent) {
super(parent, "characters.title");
// Configure instance fields
color = 0;
// Configure client area
client = new JPanel(new BorderLayout());
client.setBackground(SystemColor.control);
client.setFocusable(true);
client.setPreferredSize(new Dimension(480, 360));
client.addComponentListener(Util.onResize(e->onResize()));
// Configure controls panel
var ctrls = new JPanel(new GridBagLayout());
ctrls.setBackground(SystemColor.control);
ctrls.addMouseListener(
Util.onMouse(e->client.requestFocus(), null));
scrControls = new JScrollPane(ctrls,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrControls.setBorder(null);
scrControls.getVerticalScrollBar().setUnitIncrement(20);
client.add(scrControls, BorderLayout.WEST);
label(ctrls, "characters.index", true);
spinner(ctrls, 0, 2047, 0, true);
label(ctrls, "characters.address", false);
textBox(ctrls);
label(ctrls, "characters.mirror", false);
textBox(ctrls);
// Pattern panel
var panPattern = new JPanel();
panPattern.setBackground(Color.black);
panPattern.setPreferredSize(new Dimension(96, 96));
var gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(4, 2, 2, 2);
ctrls.add(panPattern, gbc);
// Palette panel
panPalette = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
onPaintPalette((Graphics2D) g, getWidth(), getHeight());
}
};
panPalette.setOpaque(false);
panPalette.setPreferredSize(new Dimension(0, 20 + 6));
panPalette.addMouseListener(
Util.onMouse(e->onMouseDownPalette(e), null));
gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 2, 4, 2);
ctrls.add(panPalette, gbc);
// Fill the extra space above the view controls
var spacer = new JPanel();
spacer.setOpaque(false);
gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weighty = 1;
ctrls.add(spacer, gbc);
label(ctrls, "characters.grid", false);
checkBox(ctrls).setSelected(true);
label(ctrls, "characters.wide", false);
spinner(ctrls, 0, 2048, 0, false);
label(ctrls, "characters.palette", false);
select(ctrls, new String[] { "palette.generic",
"palette.gplt0", "palette.gplt1", "palette.gplt2", "palette.gplt3",
"palette.jplt0", "palette.jplt1", "palette.jplt2", "palette.jplt3"
});
label(ctrls, "characters.scale", false);
slider(ctrls, 1, 10, 1);
// Terminate the list of controls
spacer = new JPanel();
spacer.setOpaque(false);
spacer.setPreferredSize(new Dimension(0, 0));
gbc = new GridBagConstraints();
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
ctrls.add(spacer, gbc);
// Configure characters panel
panCharacters = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
onPaintCharacters((Graphics2D) g, getWidth(), getHeight());
}
};
panCharacters.setBackground(SystemColor.control);
panCharacters.addMouseListener(
Util.onMouse(e->client.requestFocus(), null));
var scr = new JScrollPane(panCharacters);
client.add(scr, BorderLayout.CENTER);
// Configure component
setContentPane(client);
pack();
}
///////////////////////////////////////////////////////////////////////////
// Package Methods //
///////////////////////////////////////////////////////////////////////////
// Update the display
void refresh() {
repaint();
}
///////////////////////////////////////////////////////////////////////////
// Event Handlers //
///////////////////////////////////////////////////////////////////////////
// Palette mouse button press
private void onMouseDownPalette(MouseEvent e) {
// Common processing
client.requestFocus();
// Only consider left clicks
if (e.getButton() != MouseEvent.BUTTON1)
return;
// Working variables
int height = panPalette.getHeight();
int width = panPalette.getWidth();
int size = Math.max(1, Math.min((width - 18) / 4, height - 6));
int left = (width - size * 4 - 18) / 2;
int top = (height - size - 6) / 2;
int x = e.getX() - left - 3;
int y = e.getY() - top - 3;
// The click was not on top of a color
if (
x < 0 || x >= (size + 4) * 4 ||
x % (size + 4) >= size ||
y < 0 || y >= size
) return;
// Select the clicked color
color = x / (size + 4);
panPalette.repaint();
}
// Characters paint
private void onPaintCharacters(Graphics2D g, int width, int height) {
g.setColor(new Color(0x001830));
g.fillRect(0, 0, 256, 512);
}
// Palette paint
private void onPaintPalette(Graphics2D g, int width, int height) {
int size = Math.max(1, Math.min((width - 18) / 4, height - 6));
int left = (width - size * 4 - 18) / 2;
int top = (height - size - 6) / 2;
// Draw the color picker
for (int x = 0; x < 4; x++, left += size + 4) {
// The current color is selected
if (x == color) {
g.setColor(SystemColor.textHighlight);
g.fillRect(left , top , size + 6, size + 6);
g.setColor(SystemColor.control);
g.fillRect(left + 2, top + 2, size + 2, size + 2);
}
// Draw the color area
g.setColor(Color.black);
g.fillRect(left + 3, top + 3, size , size );
}
}
// Window resize
private void onResize() {
var viewport = scrControls.getViewport();
int inner = viewport.getView().getPreferredSize().width;
int outer = viewport.getExtentSize().width;
// The controls container does not need to be resized
if (inner == outer)
return;
// Size the controls container to match the inner component
scrControls.setPreferredSize(new Dimension(
scrControls.getPreferredSize().width + inner - outer, 0));
scrControls.revalidate();
scrControls.repaint();
}
///////////////////////////////////////////////////////////////////////////
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Add a check box to the controls panel
private JCheckBox checkBox(JPanel panel) {
var chk = new JCheckBox();
chk.setBorder(null);
chk.setFocusable(false);
var gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 0, 2, 2);
panel.add(chk, gbc);
return chk;
}
// Add a label to the controls panel
private void label(JPanel panel, String key, boolean top) {
var lbl = new JLabel();
parent.app.localizer.add(lbl, key);
var gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(top ? 2 : 0, 2, 2, 2);
panel.add(lbl, gbc);
}
// Add a combo box to the controls panel
private JComboBox<String> select(JPanel panel, String[] options) {
var cmb = new JComboBox<String>();
parent.app.localizer.add(cmb, options);
cmb.setSelectedIndex(0);
var gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 0, 1, 2);
panel.add(cmb, gbc);
return cmb;
}
// Add a slider to the controls panel
private JSlider slider(JPanel panel, int min, int max, int value) {
var sld = new JSlider(min, max, value);
sld.setFocusable(false);
sld.setPreferredSize(new Dimension(0, sld.getPreferredSize().height));
var gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 0, 1, 2);
panel.add(sld, gbc);
return sld;
}
// Add a spinner to the controls panel
private JSpinner spinner(JPanel panel, int min, int max, int value,
boolean top) {
var spn = new JSpinner(new SpinnerNumberModel(value, min, max, 1));
spn.setEditor(new JSpinner.NumberEditor(spn, "#"));
var gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(top ? 2 : 0, 0, 2, 2);
gbc.weightx = 1;
panel.add(spn, gbc);
return spn;
}
// Add a text box to the controls panel
private JTextField textBox(JPanel panel) {
var txt = new JTextField();
txt.setFont(parent.app.fntMono);
var size = txt.getPreferredSize();
txt.setPreferredSize(new Dimension(
parent.app.hexDigitWidth * 8 + 2 + size.width, size.height));
var gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 0, 2, 2);
panel.add(txt, gbc);
return txt;
}
}

View File

@ -53,23 +53,22 @@ class DisassemblerPane extends JScrollPane {
widths = new int[5];
// Configure client area
client = new JPanel(null) {
client = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
onPaint((Graphics2D) g, getWidth(), getHeight());
}
};
client.setBackground(SystemColor.window);
client.setFocusable(true);
client.addFocusListener(
Util.onFocus(e->client.repaint(), e->client.repaint()));
client.addKeyListener(Util.onKey(e->onKeyDown(e), null));
client.addMouseListener(Util.onMouse(e->client.requestFocus(), null));
client.addMouseWheelListener(e->onMouseWheel(e));
client.setBackground(SystemColor.window);
client.setFocusable(true);
// Configure component
setViewportView(client);
configure();
}
@ -78,18 +77,15 @@ class DisassemblerPane extends JScrollPane {
// Package Methods //
///////////////////////////////////////////////////////////////////////////
// Apply configuration settings
void configure() {
client.repaint();
}
// Update the display
void refresh(boolean seekToPC) {
client.repaint();
if (seekToPC) {
int pc = parent.parent.vue.getRegister(Vue.PC, true);
if (!isVisible(pc))
seek(pc, tall(false) / 3);
}
client.repaint();
}
@ -179,6 +175,7 @@ class DisassemblerPane extends JScrollPane {
int address = this.address;
int count = tall(true);
var data = new byte[count * 4];
int lineHeight = parent.parent.app.fntMono.metrics.getHeight();
int offset = 0;
// Disassemble from the current address
@ -202,8 +199,8 @@ class DisassemblerPane extends JScrollPane {
}
g.setColor(bg);
g.fillRect(
0, y * CPUWindow.dasmFontHeight,
width, CPUWindow.dasmFontHeight
0, y * lineHeight,
width, lineHeight
);
}
@ -220,7 +217,7 @@ class DisassemblerPane extends JScrollPane {
// Configure all rows
for (int y = 0; y < rows.size(); y++) {
var row = rows.get(y);
int top = y * CPUWindow.dasmFontHeight;
int top = y * lineHeight;
// Configure all labels
for (int z = 0, x = 0; z < 5; z++) {
@ -235,17 +232,17 @@ class DisassemblerPane extends JScrollPane {
// Configure the label
label.setLocation(x, top);
label.setSize(label.getPreferredSize());
x += widths[z] + CPUWindow.dasmFontHeight;
x += widths[z] + lineHeight;
}
}
// Update the client's size
var size = client.getPreferredSize();
width = -CPUWindow.dasmFontHeight + 1;
width = -lineHeight + 1;
for (int x = 0; x < 5; x++)
if (widths[x] != 0 && (x != 2 || showBytes))
width += CPUWindow.dasmFontHeight + widths[x];
width += lineHeight + widths[x];
if (width == size.width)
return;
client.setPreferredSize(new Dimension(width, 0));
@ -268,7 +265,7 @@ class DisassemblerPane extends JScrollPane {
for (int x = 0; x < 5; x++) {
var label = row.labels[x] = new JLabel();
if (x != 4)
label.setFont(CPUWindow.dasmFont);
label.setFont(parent.parent.app.fntMono);
client.add(label);
}
@ -380,9 +377,10 @@ class DisassemblerPane extends JScrollPane {
// Determine how many rows of output are visible
private int tall(boolean partial) {
int lineHeight = parent.parent.app.fntMono.metrics.getHeight();
return Math.max(1, (client.getHeight() +
(partial ? CPUWindow.dasmFontHeight - 1 : 0)
) / CPUWindow.dasmFontHeight);
(partial ? lineHeight - 1 : 0)
) / lineHeight);
}
// Update a row with its text and measure the column widths

View File

@ -17,6 +17,8 @@ class MainWindow extends JFrame {
// Instance fields
App app; // Containing application
Breakpoint brkStep; // Single step internal breakpoint
int[][][] palettes; // Raster palettes
byte[] vram; // Snapshot of VIP memory
Vue vue; // Emulation core context
// Private fields
@ -28,23 +30,40 @@ class MainWindow extends JFrame {
private File romFile; // Currently loaded ROM file
// UI components
private BreakpointsWindow breakpoints; // Breakpoints window
private JPanel client; // Common client container
private ConsoleWindow console; // Console window
private CPUWindow cpu; // CPU window
private JDesktopPane desktop; // Container for child windows
private MemoryWindow memory; // Memory window
private JMenu mnuDebug; // Debug menu
private JPanel video; // Video output
private JMenuItem mnuFileDebugMode; // File -> Debug mode
private JMenuItem mnuFileGameMode; // File -> Game mode
// Child windows
private BreakpointsWindow breakpoints;
private CharactersWindow characters;
private ConsoleWindow console;
private CPUWindow cpu;
private MemoryWindow memory;
///////////////////////////////////////////////////////////////////////////
// Constants //
///////////////////////////////////////////////////////////////////////////
// Palette indexes
static final int GENERIC = 0;
static final int GPLT0 = 1;
static final int GPLT1 = 2;
static final int GPLT2 = 3;
static final int GPLT3 = 4;
static final int JPLT0 = 5;
static final int JPLT1 = 6;
static final int JPLT2 = 7;
static final int JPLT3 = 8;
static final int LEFT = 0;
static final int RIGHT = 1;
static final int RED = 2;
// Application icon
private static final BufferedImage APPICON;
@ -55,6 +74,17 @@ class MainWindow extends JFrame {
///////////////////////////////////////////////////////////////////////////
// Static Methods //
///////////////////////////////////////////////////////////////////////////
// Calculate the address of a character by index
static int chrAddress(int index) {
return index >> 9 << 15 | (index & 511) << 4;
}
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
@ -65,13 +95,16 @@ class MainWindow extends JFrame {
// Configure instance fields
this.app = app;
palettes = new int[9][3][4];
pwd = Util.PWD;
vram = new byte[0x40000];
vue = Vue.create(app.getUseNative());
System.out.println("Native: " +
(vue.isNative() ? Vue.getNativeID() : "No"));
//vue.write(0x00078000, Vue.S32, -1);
// Configure video pane
video = new JPanel(null) {
video = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
onPaintVideo((Graphics2D) g, getWidth(), getHeight());
@ -96,6 +129,7 @@ class MainWindow extends JFrame {
desktop = new JDesktopPane();
desktop.setBackground(SystemColor.controlShadow);
desktop.add(breakpoints = new BreakpointsWindow(this));
desktop.add(characters = new CharactersWindow (this));
desktop.add(console = new ConsoleWindow (this));
desktop.add(cpu = new CPUWindow (this));
desktop.add(memory = new MemoryWindow (this));
@ -160,8 +194,8 @@ class MainWindow extends JFrame {
mnuDebug.add(mnuDebugBackgrounds);
var mnuDebugCharacters = new JMenuItem();
mnuDebugCharacters.setEnabled(false);
loc.add(mnuDebugCharacters, "app.debug.characters");
mnuDebugCharacters.addActionListener(e->characters.setVisible(true));
mnuDebug.add(mnuDebugCharacters);
var mnuDebugFrameBuffers = new JMenuItem();
@ -226,7 +260,12 @@ class MainWindow extends JFrame {
// Refresh all debug views
void refreshDebug(boolean seekToPC) {
vue.readBytes(0x00000000, vram, 0, vram.length);
refreshPalettes();
breakpoints.refresh();
characters .refresh();
cpu .refresh(seekToPC);
memory .refresh();
}
@ -364,6 +403,58 @@ class MainWindow extends JFrame {
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Update the palette composites
private void refreshPalettes() {
// Process brightness levels
int[] brt = { 0,
vue.read(0x0005F824, Vue.U8),
vue.read(0x0005F826, Vue.U8),
vue.read(0x0005F828, Vue.U8)
};
brt[3] += brt[0] + brt[1];
for (int x = 1; x < 4; x++)
brt[x] = (Math.min(127, brt[x]) * 510 + 127) / 254 << 1;
// Process all palettes
var pal = new int[4];
for (int x = 0; x < 9; x++) {
// Generic palette
if (x == GENERIC) {
pal[1] = 0x55 << 1;
pal[2] = 0xAA << 1;
pal[3] = 0xFF << 1;
}
// Palette from emulation state
else {
int bits = vue.read(0x0005F860 + (x - 1 << 1), Vue.U8);
pal[1] = brt[bits >> 2 & 3];
pal[2] = brt[bits >> 4 & 3];
pal[3] = brt[bits >> 6 ];
}
// Process colors
for (int y = 0; y < 3; y++) {
var base = app.rgbBase[y];
var dest = palettes[x][y];
for (int z = 1; z < 4; z++) {
dest[z] = 0xFF000000;
for (int w = 0, bits = 16; w < 3; w++, bits -= 8)
dest[z] |= (pal[z] * base[w] + 255) / 510 << bits;
}
}
}
}
// Separate the RGB components of a color
private static int[] split(int rgb) {
return new int[] { rgb >> 16 & 0xFF, rgb >> 8 & 0xFF, rgb & 0xFF };
}
// Update the window title
private void updateTitle() {
app.localizer.add(this,

View File

@ -14,9 +14,6 @@ class MemoryWindow extends ChildWindow {
// Private fields
private int address; // Address of top row
private Font font; // Display font
private int fontHeight; // Font line height
private int fontWidth; // Font maximum character width
// UI components
private JPanel client; // Client area
@ -46,8 +43,6 @@ class MemoryWindow extends ChildWindow {
// Configure instance fields
address = 0x00000000;
font = new Font(Util.fontFamily(new String[]
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14);
rows = new ArrayList<Row>();
// Configure client area
@ -64,7 +59,6 @@ class MemoryWindow extends ChildWindow {
content.setBorder(new JScrollPane().getBorder());
content.add(client, BorderLayout.CENTER);
setContentPane(content);
setFont2(font);
pack();
}
@ -83,7 +77,8 @@ class MemoryWindow extends ChildWindow {
// Configure working variables
int height = client.getHeight();
int count = (height + fontHeight - 1) / fontHeight;
int lineHeight = parent.app.fntMono.metrics.getHeight();
int count = (height + lineHeight - 1) / lineHeight;
var data = new byte[count * 16];
// Retrieve all visible bytes from the emulation context
@ -95,7 +90,7 @@ class MemoryWindow extends ChildWindow {
if (x < rows.size())
row = rows.get(x); // Retrieve row from collection
else row = createRow(); // Produce a new row
update(row, x * fontHeight, address + x * 16, data, x * 16);
update(row, x * lineHeight, address + x * 16, data, x * 16);
setVisible(row, true);
}
@ -108,30 +103,6 @@ class MemoryWindow extends ChildWindow {
client.repaint();
}
// 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 rows
for (var row : rows) {
row.address.setFont(font);
for (var label : row.bytes)
label.setFont(font);
}
onResize();
}
///////////////////////////////////////////////////////////////////////////
@ -202,6 +173,7 @@ class MemoryWindow extends ChildWindow {
// Add a new row of output
private Row createRow() {
var font = parent.app.fntMono;
var row = new Row();
// Address label
@ -250,22 +222,25 @@ class MemoryWindow extends ChildWindow {
// Determine how many rows of output are visible
private int tall(boolean partial) {
return (client.getHeight() + (partial?fontHeight-1:0)) / fontHeight;
int lineHeight = parent.app.fntMono.metrics.getHeight();
return (client.getHeight() + (partial?lineHeight-1:0)) / lineHeight;
}
// Update the text of a row
private void update(Row row, int y, int address, byte[] data, int offset) {
int hexDigitWidth = parent.app.hexDigitWidth;
int lineHeight = parent.app.fntMono.metrics.getHeight();
// Update address
row.address.setBounds(0, y, 8 * fontWidth, fontHeight);
row.address.setBounds(0, y, 8 * hexDigitWidth, lineHeight);
row.address.setText(String.format("%08X", address));
// Update bytes
for (int z = 0, x = 10 * fontWidth; z < 16; z++) {
for (int z = 0, x = 10 * hexDigitWidth; z < 16; z++) {
var label = row.bytes[z];
label.setBounds(x, y, 2 * fontWidth, fontHeight);
label.setBounds(x, y, 2 * hexDigitWidth, lineHeight);
label.setText(String.format("%02X", data[offset++] & 0xFF));
x += fontWidth * (z == 7 ? 4 : 3);
x += hexDigitWidth * (z == 7 ? 4 : 3);
}
}

View File

@ -47,6 +47,10 @@ class Register {
static final int PLAIN = -2;
static final int PROGRAM = -3;
// Expand button labels
static final String COLLAPSE = "-";
static final String EXPAND = "+";
///////////////////////////////////////////////////////////////////////////
@ -71,7 +75,7 @@ class Register {
if (e.getButton() == 1) setExpanded(!expanded); }, null);
// Expand button
btnExpand = new JLabel(expandable ? "+" : " ");
btnExpand = new JLabel(expandable ? EXPAND : "");
btnExpand.setHorizontalAlignment(SwingConstants.CENTER);
if (expandable)
btnExpand.addMouseListener(expand);
@ -124,12 +128,12 @@ class Register {
case Vue.PIR : initPIR (); break;
case Vue.PSW : initPSW (); break;
case Vue.TKCW: initTKCW (); break;
default: return;
default: configure(); return;
}
// Expansion indentation
if (index != Vue.PC) {
indent = new JPanel(null);
indent = new JPanel();
indent.setOpaque(false);
indent.setPreferredSize(new Dimension(0, 0));
indent.setVisible(false);
@ -152,6 +156,9 @@ class Register {
// Handling for PSW
if (index == Vue.PSW && type == Vue.PSW)
setExpanded(true);
// Apply application settings
configure();
}
@ -191,7 +198,7 @@ class Register {
for (int x = 0; x < 2; x++) {
// Indentation
indent = new JPanel(null);
indent = new JPanel();
indent.setOpaque(false);
indent.setPreferredSize(new Dimension(0, 0));
var gbc = new GridBagConstraints();
@ -296,25 +303,28 @@ class Register {
// Expand button
var size = btnExpand.getPreferredSize();
size.width = CPUWindow.regExpandWidth;
var metrics = parent.parent.parent.app.fntDialog.metrics;
size.width = 4 + Math.max(
metrics.stringWidth(EXPAND), metrics.stringWidth(COLLAPSE));
btnExpand.setPreferredSize(size);
// Value text box
var fontSize = CPUWindow.regHexFontSize;
size = new Dimension(8 * fontSize.width + 4, fontSize.height);
txtValue.setFont(CPUWindow.regHexFont);
txtValue.setPreferredSize(size);
var fntMono = parent.parent.parent.app.fntMono;
int hexDigitWidth = parent.parent.parent.app.hexDigitWidth;
txtValue.setFont(fntMono);
txtValue.setPreferredSize(new Dimension(
hexDigitWidth * 8 + 4, fntMono.metrics.getHeight()));
// Expansion controls
for (var ctrl : controls) {
if (!(ctrl instanceof JTextField))
continue;
if (type == Vue.PC || (Boolean) ctrl.getClientProperty("hex"))
((JTextField) ctrl).setFont(CPUWindow.regHexFont);
((JTextField) ctrl).setFont(fntMono);
int digits = type == Vue.PC ? 8 :
(Integer) ctrl.getClientProperty("digits");
size = ctrl.getPreferredSize();
size.width = digits * fontSize.width + 4;
size.width = digits * hexDigitWidth + 4;
ctrl.setPreferredSize(size);
}
}
@ -397,7 +407,7 @@ class Register {
// Change the display mode of a program register
void setMode(int mode) {
this.mode = mode;
txtValue.setFont(mode == HEX ? CPUWindow.regHexFont : null);
txtValue.setFont(mode!=HEX ? null : parent.parent.parent.app.fntMono);
refresh();
}

View File

@ -85,7 +85,7 @@ class RegisterList extends JScrollPane {
}
// List terminator
var spacer = new JPanel(null);
var spacer = new JPanel();
spacer.setOpaque(false);
spacer.setPreferredSize(new Dimension(0, 0));
var gbc = new GridBagConstraints();
@ -144,7 +144,7 @@ class RegisterList extends JScrollPane {
}
// Apply configuration settings
void configure() {
void configure2() {
// Configure registers
for (var reg : registers.values())
@ -152,7 +152,7 @@ class RegisterList extends JScrollPane {
// Configure component
getVerticalScrollBar().setUnitIncrement(
CPUWindow.regHexFontSize.height);
parent.parent.app.fntMono.metrics.getHeight());
}
// Update the display

View File

@ -24,7 +24,7 @@ public final class Util {
///////////////////////////////////////////////////////////////////////////
// Types //
// Classes //
///////////////////////////////////////////////////////////////////////////
// Event listener interfaces
@ -43,6 +43,16 @@ public final class Util {
BOM(byte[] m, Charset s) { mark = m; set = s; }
}
// Font metrics wrapper
public static class Font extends java.awt.Font {
public final FontMetrics metrics;
public Font(java.awt.Font font) {
super(font);
metrics = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)
.getGraphics().getFontMetrics(this);
}
}
///////////////////////////////////////////////////////////////////////////

View File

@ -1537,7 +1537,7 @@ public class Breakpoint {
case CODE : sym = vue.getExceptionCode(); break;
case COND : sym = inst.cond ; break;
case DISP : sym = inst.disp ; break;
case FETCH : sym = vue.getFetch (); break;
case FETCH : sym = acc.fetch ; break;
case FORMAT : sym = inst.format ; break;
case ID : sym = inst.id ; break;
case OPCODE : sym = inst.opcode ; break;

View File

@ -443,8 +443,8 @@ class CPU {
// First unit
if (fetch == 0) {
inst.bits = access.value & 0xFFFF;
if (Instruction.size(access.value >> 10 & 0x3F) == 4) {
inst.bits = access.value;
if (Instruction.size(access.value >> 10) == 4) {
fetch = 1;
return false;
}

View File

@ -114,6 +114,7 @@ public class Instruction {
boolean read = false;
var ret = new Access();
ret.address = vue.getRegister(reg1, false) + disp;
ret.fetch = vue.getFetch();
ret.type = Vue.S32;
// Configure descriptor by ID
@ -139,10 +140,17 @@ public class Instruction {
if (read)
ret.value = vue.read(ret.address, ret.type);
// Select the value to write to the bus
else ret.value = vue.getRegister(id == Vue.CAXI &&
vue.getRegister(reg2, false) == vue.read(ret.address, Vue.S32) ?
30 : reg2, false);
// Write a register to the bus
else if (id != Vue.CAXI)
vue.getRegister(reg2, false);
// CAXI processing
else {
int value = vue.read(ret.address, Vue.S32);
int compare = vue.getRegister(reg2, false);
int exchange = vue.getRegister( 30, false);
ret.value = value == compare ? value : exchange;
}
return ret;
}

View File

@ -76,11 +76,6 @@ class JavaVue extends Vue {
return maxCycles;
}
// Retrieve a snapshot of the current state's memory access
public Access getAccess() {
return cpu.access;
}
// Retrieve the most recent applicaiton break code
public int getBreakCode() {
return breakCode;
@ -91,11 +86,6 @@ class JavaVue extends Vue {
return cpu.exception;
}
// Retrieve a snapshot of the current state's instruction
public Instruction getInstruction() {
return cpu.inst;
}
// Retrieve a register value
public int getRegister(int index, boolean system) {

View File

@ -141,22 +141,6 @@ JNIEXPORT jint JNICALL Java_vue_NativeVue_emulate
return vueEmulate(&core->vue, maxCycles);
}
// Retrieve a snapshot of the current state's memory access
JNIEXPORT jobject JNICALL Java_vue_NativeVue_getAccess
(JNIEnv *env, jobject vue, jlong handle, jobject acc) {
Core *core = *(Core **)&handle;
jclass cls = (*env)->GetObjectClass(env, acc);
(*env)->SetIntField(env, acc, (*env)->GetFieldID(env, cls, "address", "I"),
core->vue.cpu.access.address);
(*env)->SetIntField(env, acc, (*env)->GetFieldID(env, cls, "fetch", "I"),
core->vue.cpu.fetch);
(*env)->SetIntField(env, acc, (*env)->GetFieldID(env, cls, "type", "I"),
core->vue.cpu.access.type);
(*env)->SetIntField(env, acc, (*env)->GetFieldID(env, cls, "value", "I"),
core->vue.cpu.access.value);
return acc;
}
// Retrieve the most recent exception code
JNIEXPORT jint JNICALL Java_vue_NativeVue_getBreakCode
(JNIEnv *env, jobject vue, jlong handle) {
@ -171,36 +155,6 @@ JNIEXPORT jint JNICALL Java_vue_NativeVue_getExceptionCode
return vueGetExceptionCode(&core->vue);
}
// Retrieve a snapshot of the current state's instruction
JNIEXPORT jobject JNICALL Java_vue_NativeVue_getInstruction
(JNIEnv *env, jobject vue, jlong handle, jobject inst) {
Core *core = *(Core **)&handle;
jclass cls = (*env)->GetObjectClass(env, inst);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "bits", "I"),
core->vue.cpu.inst.bits);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "cond", "I"),
core->vue.cpu.inst.cond);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "disp", "I"),
core->vue.cpu.inst.disp);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "format", "I"),
core->vue.cpu.inst.format);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "id", "I"),
core->vue.cpu.inst.id);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "imm", "I"),
core->vue.cpu.inst.imm);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "opcode", "I"),
core->vue.cpu.inst.opcode);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "reg1", "I"),
core->vue.cpu.inst.reg1);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "reg2", "I"),
core->vue.cpu.inst.reg2);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env, cls, "size", "I"),
core->vue.cpu.inst.size);
(*env)->SetIntField(env, inst, (*env)->GetFieldID(env,cls,"subopcode","I"),
core->vue.cpu.inst.subopcode);
return inst;
}
// Retrieve a register value
JNIEXPORT jint JNICALL Java_vue_NativeVue_getRegister
(JNIEnv *env, jobject vue, jlong handle, jint index, jboolean system) {

View File

@ -42,12 +42,6 @@ class NativeVue extends Vue {
public int emulate(int maxCycles)
{ return emulate(handle, maxCycles); }
// Retrieve a snapshot of the current state's memory access
private native Access getAccess(long handle, Access access);
public Access getAccess() {
return getAccess(handle, new Access());
}
// Retrieve the most recent application break code
private native int getBreakCode(long handle);
public int getBreakCode() { return getBreakCode(handle); }
@ -58,12 +52,6 @@ class NativeVue extends Vue {
return getExceptionCode(handle);
}
// Retrieve a snapshot of the current state's instruction
private native Instruction getInstruction(long handle, Instruction inst);
public Instruction getInstruction() {
return getInstruction(handle, new Instruction());
}
// Retrieve a register value
private native int getRegister(long handle, int index, boolean system);
public int getRegister(int index, boolean system)