mirror of
https://github.com/sethm/symon.git
synced 2025-02-15 09:34:00 +00:00
Fixes and enhancements.
- Added ability to change inner border width of console window. - Fixed a nasty bug that prevented key press handling. - Reset now clears the accumulator and index registers.
This commit is contained in:
parent
e012d97bb3
commit
c214cc9b43
2
pom.xml
2
pom.xml
@ -44,7 +44,7 @@
|
||||
<dependency>
|
||||
<groupId>com.grahamedgecombe.jterminal</groupId>
|
||||
<artifactId>jterminal</artifactId>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
<version>1.0.2-loomcom</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -118,6 +118,11 @@ public class Cpu implements InstructionTable {
|
||||
|
||||
// Reset step counter
|
||||
stepCounter = 0L;
|
||||
|
||||
// Reset registers.
|
||||
a = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
public void step(int num) throws MemoryAccessException {
|
||||
|
@ -8,11 +8,15 @@ public interface Preferences {
|
||||
|
||||
public static final int DEFAULT_ACIA_ADDRESS = 0xc000;
|
||||
|
||||
public static final int DEFAULT_BORDER_WIDTH = 10;
|
||||
|
||||
public JDialog getDialog();
|
||||
|
||||
public int getProgramStartAddress();
|
||||
|
||||
public int getAciaAddress();
|
||||
|
||||
public int getBorderWidth();
|
||||
|
||||
public void updateUi();
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public class Simulator implements ActionListener, Observer {
|
||||
private JMenuItem loadMenuItem;
|
||||
|
||||
private JFileChooser fileChooser;
|
||||
private Preferences preferences;
|
||||
private PreferencesDialog preferences;
|
||||
|
||||
public Simulator() throws MemoryRangeException {
|
||||
this.acia = new Acia(ACIA_BASE);
|
||||
@ -109,6 +109,7 @@ public class Simulator implements ActionListener, Observer {
|
||||
// File Chooser
|
||||
fileChooser = new JFileChooser();
|
||||
preferences = new PreferencesDialog(mainWindow, true);
|
||||
preferences.addObserver(this);
|
||||
|
||||
// Panel for Console and Buttons
|
||||
JPanel controlsContainer = new JPanel();
|
||||
@ -203,6 +204,8 @@ public class Simulator implements ActionListener, Observer {
|
||||
} else if (actionEvent.getSource() == stepButton) {
|
||||
handleStep();
|
||||
} else if (actionEvent.getSource() == runStopButton) {
|
||||
// Shift focus to the console.
|
||||
console.requestFocus();
|
||||
if (runLoop != null && runLoop.isRunning()) {
|
||||
runLoop.requestStop();
|
||||
runLoop.interrupt();
|
||||
@ -327,18 +330,9 @@ public class Simulator implements ActionListener, Observer {
|
||||
// Read from the ACIA and immediately update the console if there's
|
||||
// output ready.
|
||||
if (acia.hasTxChar()) {
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
console.print(Character.toString((char)acia.txRead()));
|
||||
console.repaint();
|
||||
}
|
||||
});
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// This is thread-safe
|
||||
console.print(Character.toString((char)acia.txRead()));
|
||||
console.repaint();
|
||||
}
|
||||
|
||||
// If a key has been pressed, fill the ACIA.
|
||||
@ -414,8 +408,14 @@ public class Simulator implements ActionListener, Observer {
|
||||
public void update(Observable observable, Object o) {
|
||||
// Instance equality should work here, there is only one instance.
|
||||
if (observable == preferences) {
|
||||
// TODO: Update system based on state. (i.e., update ACIA address, and raise a dialog if it
|
||||
// overlaps with anything)
|
||||
// TODO: Update ACIA base address if it has changed.
|
||||
|
||||
int oldBorderWidth = console.getBorderWidth();
|
||||
if (oldBorderWidth != preferences.getBorderWidth()) {
|
||||
// Resize the main window if the border width has changed.
|
||||
console.setBorderWidth(preferences.getBorderWidth());
|
||||
mainWindow.pack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
import com.grahamedgecombe.jterminal.JTerminal;
|
||||
import com.grahamedgecombe.jterminal.vt100.Vt100TerminalModel;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.BevelBorder;
|
||||
@ -18,11 +19,20 @@ import javax.swing.border.Border;
|
||||
|
||||
public class Console extends JTerminal implements KeyListener, MouseListener {
|
||||
|
||||
private static final int DEFAULT_COLUMNS = 80;
|
||||
private static final int DEFAULT_ROWS = 24;
|
||||
private static final int DEFAULT_BORDER_WIDTH = 10;
|
||||
|
||||
private boolean hasInput = false;
|
||||
private char keyBuffer;
|
||||
|
||||
public Console() {
|
||||
super();
|
||||
public Console() {
|
||||
this(DEFAULT_COLUMNS, DEFAULT_ROWS);
|
||||
}
|
||||
|
||||
public Console(int columns, int rows) {
|
||||
super(new Vt100TerminalModel(columns, rows));
|
||||
setBorderWidth(DEFAULT_BORDER_WIDTH);
|
||||
addKeyListener(this);
|
||||
addMouseListener(this);
|
||||
Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 0);
|
||||
@ -31,6 +41,11 @@ public class Console extends JTerminal implements KeyListener, MouseListener {
|
||||
this.setBorder(compoundBorder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the console. This will cause the console to be cleared and the cursor returned to the
|
||||
* home position.
|
||||
*
|
||||
*/
|
||||
public void reset() {
|
||||
getModel().clear();
|
||||
getModel().setCursorColumn(0);
|
||||
@ -39,28 +54,50 @@ public class Console extends JTerminal implements KeyListener, MouseListener {
|
||||
this.hasInput = false;
|
||||
}
|
||||
|
||||
public void keyTyped(KeyEvent keyEvent) {
|
||||
keyEvent.consume();
|
||||
}
|
||||
|
||||
public void keyPressed(KeyEvent keyEvent) {
|
||||
keyBuffer = keyEvent.getKeyChar();
|
||||
hasInput = true;
|
||||
|
||||
System.out.println("Key Pressed (0x" + Integer.toString((int)keyBuffer, 16) + ") : " + keyBuffer);
|
||||
|
||||
keyEvent.consume();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a key has been pressed since the last time input was read.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean hasInput() {
|
||||
return hasInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a Key Typed event.
|
||||
*
|
||||
* @param keyEvent The key event.
|
||||
*/
|
||||
public void keyTyped(KeyEvent keyEvent) {
|
||||
keyEvent.consume();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a Key Press event.
|
||||
*
|
||||
* @param keyEvent The key event.
|
||||
*/
|
||||
public void keyPressed(KeyEvent keyEvent) {
|
||||
keyBuffer = keyEvent.getKeyChar();
|
||||
hasInput = true;
|
||||
keyEvent.consume();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the most recently typed key from the single-char input buffer.
|
||||
*
|
||||
* @return The character typed.
|
||||
*/
|
||||
public char readInputChar() {
|
||||
hasInput = false;
|
||||
return this.keyBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a key release event.
|
||||
*
|
||||
* @param keyEvent The key event.
|
||||
*/
|
||||
public void keyReleased(KeyEvent keyEvent) {
|
||||
keyEvent.consume();
|
||||
}
|
||||
|
@ -14,9 +14,11 @@ public class PreferencesDialog extends Observable implements Preferences {
|
||||
|
||||
private JTextField aciaAddressField;
|
||||
private JTextField programLoadAddressField;
|
||||
private JTextField borderWidthField;
|
||||
|
||||
private int programLoadAddress = DEFAULT_PROGRAM_LOAD_ADDRESS;
|
||||
private int aciaAddress = DEFAULT_ACIA_ADDRESS;
|
||||
private int borderWidth = DEFAULT_BORDER_WIDTH;
|
||||
|
||||
public PreferencesDialog(Frame parent, boolean modal) {
|
||||
this.dialog = new JDialog(parent, modal);
|
||||
@ -28,6 +30,9 @@ public class PreferencesDialog extends Observable implements Preferences {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Validation of input.
|
||||
*/
|
||||
private void initComponents() {
|
||||
dialog.setTitle("Preferences");
|
||||
Container contents = dialog.getContentPane();
|
||||
@ -40,12 +45,15 @@ public class PreferencesDialog extends Observable implements Preferences {
|
||||
|
||||
final JLabel aciaAddressLabel = new JLabel("ACIA Address");
|
||||
final JLabel programLoadAddressLabel = new JLabel("Program Load Address");
|
||||
final JLabel borderWidthLabel = new JLabel("Console Border Width");
|
||||
|
||||
aciaAddressField = new JTextField(8);
|
||||
programLoadAddressField = new JTextField(8);
|
||||
borderWidthField = new JTextField(8);
|
||||
|
||||
aciaAddressLabel.setLabelFor(aciaAddressField);
|
||||
programLoadAddressLabel.setLabelFor(programLoadAddressField);
|
||||
borderWidthLabel.setLabelFor(borderWidthField);
|
||||
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
|
||||
@ -66,6 +74,13 @@ public class PreferencesDialog extends Observable implements Preferences {
|
||||
constraints.gridx = 1;
|
||||
settingsContainer.add(programLoadAddressField, constraints);
|
||||
|
||||
constraints.gridy = 2;
|
||||
constraints.gridx = 0;
|
||||
settingsContainer.add(borderWidthLabel, constraints);
|
||||
|
||||
constraints.gridx = 1;
|
||||
settingsContainer.add(borderWidthField, constraints);
|
||||
|
||||
JButton applyButton = new JButton("Apply");
|
||||
JButton cancelButton = new JButton("Cancel");
|
||||
|
||||
@ -81,8 +96,11 @@ public class PreferencesDialog extends Observable implements Preferences {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
programLoadAddress = hexToInt(programLoadAddressField.getText());
|
||||
aciaAddress = hexToInt(aciaAddressField.getText());
|
||||
borderWidth = Integer.parseInt(borderWidthField.getText());
|
||||
updateUi();
|
||||
notifyObservers();
|
||||
// TODO: Actually check to see if values have changed, don't assume.
|
||||
setChanged();
|
||||
PreferencesDialog.this.notifyObservers();
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
});
|
||||
@ -96,6 +114,27 @@ public class PreferencesDialog extends Observable implements Preferences {
|
||||
dialog.pack();
|
||||
}
|
||||
|
||||
public int getProgramStartAddress() {
|
||||
return programLoadAddress;
|
||||
}
|
||||
|
||||
public int getAciaAddress() {
|
||||
return aciaAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The width of the console border, in pixels.
|
||||
*/
|
||||
public int getBorderWidth() {
|
||||
return borderWidth;
|
||||
}
|
||||
|
||||
public void updateUi() {
|
||||
aciaAddressField.setText(intToHex(aciaAddress));
|
||||
programLoadAddressField.setText(intToHex(programLoadAddress));
|
||||
borderWidthField.setText(Integer.toString(borderWidth));
|
||||
}
|
||||
|
||||
private String intToHex(int i) {
|
||||
return String.format("%04x", i);
|
||||
}
|
||||
@ -109,16 +148,4 @@ public class PreferencesDialog extends Observable implements Preferences {
|
||||
}
|
||||
}
|
||||
|
||||
public int getProgramStartAddress() {
|
||||
return programLoadAddress;
|
||||
}
|
||||
|
||||
public int getAciaAddress() {
|
||||
return aciaAddress;
|
||||
}
|
||||
|
||||
public void updateUi() {
|
||||
aciaAddressField.setText(intToHex(aciaAddress));
|
||||
programLoadAddressField.setText(intToHex(programLoadAddress));
|
||||
}
|
||||
}
|
||||
|
@ -401,6 +401,8 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
|
||||
bus.loadProgram(0xa9, 0x7f, // LDA #$7f
|
||||
0x7d, 0x10, 0xab); // ADC $ab10,X
|
||||
cpu.step(2);
|
||||
@ -411,6 +413,8 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
|
||||
bus.loadProgram(0xa9, 0x80, // LDA #$80
|
||||
0x7d, 0x10, 0xab); // ADC $ab10,X
|
||||
cpu.step(2);
|
||||
@ -421,6 +425,8 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
|
||||
bus.loadProgram(0xa9, 0xff, // LDA #$ff
|
||||
0x7d, 0x10, 0xab); // ADC $ab10,X
|
||||
cpu.step(2);
|
||||
@ -431,6 +437,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertTrue(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xa9, 0x00, // LDA #$00
|
||||
0x7d, 0x11, 0xab); // ADC $ab11,X
|
||||
cpu.step(2);
|
||||
@ -441,6 +448,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xa9, 0x7f, // LDA #$7f
|
||||
0x7d, 0x11, 0xab); // ADC $ab11,X
|
||||
cpu.step(2);
|
||||
@ -451,6 +459,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertTrue(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xa9, 0x80, // LDA #$80
|
||||
0x7d, 0x11, 0xab); // ADC $ab11,X
|
||||
cpu.step(2);
|
||||
@ -461,6 +470,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertTrue(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xa9, 0xff, // LDA #$ff
|
||||
0x7d, 0x11, 0xab); // ADC $ab11,X
|
||||
cpu.step(2);
|
||||
@ -506,6 +516,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xf8, // SED
|
||||
0xa9, 0x49, // LDA #$49
|
||||
0x7d, 0x10, 0xab); // ADC $ab10,X
|
||||
@ -517,6 +528,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xf8, // SED
|
||||
0xa9, 0x50, // LDA #$50
|
||||
0x7d, 0x10, 0xab); // ADC $ab10,X
|
||||
@ -528,6 +540,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xf8, // SED
|
||||
0xa9, 0x99, // LDA #$99
|
||||
0x7d, 0x10, 0xab); // ADC $ab10,X
|
||||
@ -539,6 +552,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertTrue(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xf8, // SED
|
||||
0xa9, 0x00, // LDA #$00
|
||||
0x7d, 0x11, 0xab); // ADC $ab10,X
|
||||
@ -550,6 +564,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xf8, // SED
|
||||
0xa9, 0x49, // LDA #$49
|
||||
0x7d, 0x11, 0xab); // ADC $ab11,X
|
||||
@ -561,6 +576,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertTrue(cpu.getCarryFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
bus.loadProgram(0xf8, // SED
|
||||
0xa9, 0x50, // LDA #$59
|
||||
0x7d, 0x11, 0xab); // ADC $ab11,X
|
||||
@ -666,6 +682,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
|
||||
cpu.setAccumulator(0x0f);
|
||||
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
||||
@ -675,6 +692,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setXRegister(0x30);
|
||||
|
||||
cpu.setAccumulator(0x80);
|
||||
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user