Cleaner simulator startup and run-loop exiting

- If a default ROM image ("rom.bin") isn't available at startup, the
  simulator will now create and load a 16KB R/W memory at the ROM
  location, so resets will work even without a ROM loaded.

- Cleaned up the way simulator UI state is updated when the run loop
  exits.
This commit is contained in:
Seth Morabito committed 2012-12-10 21:53:01 -08:00
1 parent 504f7291b3
commit 0215e2e3d8
3 files changed
+47 -48

No files matched your search

+39 -46
View File
@@ -49,12 +49,11 @@ import java.util.logging.Logger;
/** /**
* Symon Simulator Interface and Control. * Symon Simulator Interface and Control.
* * <p/>
* This class provides a control and I/O system for the simulated 6502 system. * This class provides a control and I/O system for the simulated 6502 system.
* It includes the simulated CPU itself, as well as 32KB of RAM, 16KB of ROM, * It includes the simulated CPU itself, as well as 32KB of RAM, 16KB of ROM,
* and a simulated ACIA for serial I/O. The ACIA is attached to a dumb terminal * and a simulated ACIA for serial I/O. The ACIA is attached to a dumb terminal
* with a basic 80x25 character display. * with a basic 80x25 character display.
*
*/ */
public class Simulator implements Observer { public class Simulator implements Observer {
@@ -156,8 +155,12 @@ public class Simulator implements Observer {
if (romImage.canRead()) { if (romImage.canRead()) {
logger.info("Loading ROM image from file " + romImage); logger.info("Loading ROM image from file " + romImage);
this.rom = Memory.makeROM(ROM_BASE, ROM_SIZE, romImage); this.rom = Memory.makeROM(ROM_BASE, ROM_SIZE, romImage);
bus.addDevice(rom); } else {
logger.info("Default ROM file " + romImage +
" not found, loading empty R/W memory image.");
this.rom = Memory.makeRAM(ROM_BASE, ROM_SIZE);
} }
bus.addDevice(rom);
} }
/** /**
@@ -254,26 +257,6 @@ public class Simulator implements Observer {
runLoop.requestStop(); runLoop.requestStop();
runLoop.interrupt(); runLoop.interrupt();
runLoop = null; runLoop = null;
simulatorDidStop();
}
/*
* Handle post-stop actions.
*/
private void simulatorDidStop() {
// The simulator is lazy about updating the UI for performance reasons, so always request an
// immediate update after stopping.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Now update the state
statusPane.updateState(cpu);
}
});
traceLog.simulatorDidStop();
if (traceLog.isVisible()) {
traceLog.refresh();
}
// TODO: Update memory window, if frame is visible.
} }
/* /*
@@ -313,7 +296,9 @@ public class Simulator implements Observer {
private void handleStep() { private void handleStep() {
try { try {
step(); step();
simulatorDidStop(); if (traceLog.isVisible()) {
traceLog.refresh();
}
} catch (SymonException ex) { } catch (SymonException ex) {
logger.log(Level.SEVERE, "Exception during simulator step: " + ex.getMessage()); logger.log(Level.SEVERE, "Exception during simulator step: " + ex.getMessage());
ex.printStackTrace(); ex.printStackTrace();
@@ -389,22 +374,6 @@ public class Simulator implements Observer {
}); });
} }
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
// Create the main UI window
Simulator simulator = new Simulator();
simulator.createAndShowUi();
// Reset the simulator.
simulator.handleReset();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/** /**
* The configuration has changed. Re-load. * The configuration has changed. Re-load.
* *
@@ -423,6 +392,28 @@ public class Simulator implements Observer {
} }
} }
/**
* Main entry point to the simulator. Creates a simulator and shows the main
* window.
*
* @param args
*/
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
// Create the main UI window
Simulator simulator = new Simulator();
simulator.createAndShowUi();
// Reset the simulator.
simulator.handleReset();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/** /**
* The main run thread. * The main run thread.
*/ */
@@ -464,13 +455,15 @@ public class Simulator implements Observer {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
public void run() { public void run() {
console.stopListening();
// Allow step while the simulator is stopped
stepButton.setEnabled(true);
menuBar.simulatorDidStop();
runStopButton.setText("Run");
// Now update the state
statusPane.updateState(cpu); statusPane.updateState(cpu);
runStopButton.setText("Run");
stepButton.setEnabled(true);
if (traceLog.isVisible()) {
traceLog.refresh();
}
menuBar.simulatorDidStop();
traceLog.simulatorDidStop();
// TODO: Update memory window, if frame is visible.
} }
}); });
@@ -14,8 +14,8 @@ package com.loomcom.symon.util;
* The most convenient way to get a formatted hex value from an integer is with the <code>String.format</code> * The most convenient way to get a formatted hex value from an integer is with the <code>String.format</code>
* method, but this turns out to be extremely inefficient. Formatting a million integers * method, but this turns out to be extremely inefficient. Formatting a million integers
* with <code>String.format</code> takes something like 1600ms. Formatting the same number of integers * with <code>String.format</code> takes something like 1600ms. Formatting the same number of integers
* with <code>HexUtil</code> takes only 160ms. This is on part with <code>Integer.toHexString</code>, * with <code>HexUtil</code> takes only 160ms. This is on par with <code>Integer.toHexString</code>,
* but also allows the desired padding. * but also gives the desired padding.
* *
*/ */
public class HexUtil { public class HexUtil {
@@ -33,4 +33,10 @@ public class HexUtilTest extends TestCase {
assertEquals("FFFE", HexUtil.wordToHex(0xfffffe)); assertEquals("FFFE", HexUtil.wordToHex(0xfffffe));
assertEquals("FF00", HexUtil.wordToHex(0xffff00)); assertEquals("FF00", HexUtil.wordToHex(0xffff00));
} }
public void testAllBytesAreCorrect() {
for (int i = 0; i <= 0xff; i++) {
assertEquals(String.format("%02X", i), HexUtil.byteToHex(i));
}
}
} }