pvbemu/src/desktop/app/CPU.java

258 lines
8.8 KiB
Java

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(480, 300));
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
int plain = Register.PLAIN;
registers.add(new Register(parent, lst, "PC" , VUE.PC , plain ));
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 , plain ));
registers.add(new Register(parent, lst, "EIPSW", VUE.EIPSW, VUE.PSW ));
registers.add(new Register(parent, lst, "FEPC" , VUE.FEPC , plain ));
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, plain ));
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, plain ));
registers.add(new Register(parent, lst, "30" , 30, plain ));
registers.add(new Register(parent, lst, "31" , 31, plain ));
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;
}
}