Merge branch 'master' of github.com:badvision/lawless-legends

This commit is contained in:
Martin Haye 2018-05-31 10:37:47 -07:00
commit f35739aec9
7 changed files with 65 additions and 46 deletions

View File

@ -131,12 +131,12 @@ public class LawlessLegends extends Application {
observe(RAMEvent.TYPE.EXECUTE, 0x0c700, (e) -> {
romStarted = true;
});
Emulator.computer.coldStart();
Emulator.computer.invokeColdStart();
try {
Thread.sleep(10000);
Thread.sleep(7500);
if (!romStarted) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Boot not detected, performing a cold start");
Emulator.computer.coldStart();
Emulator.computer.invokeColdStart();
}
} catch (InterruptedException ex) {
Logger.getLogger(LawlessLegends.class.getName()).log(Level.SEVERE, null, ex);

View File

@ -151,8 +151,10 @@ public class Configuration implements Reconfigurable {
settings = (Map) in.readObject();
hotkeys = (Map) in.readObject();
Object[] nodeArray = (Object[]) in.readObject();
for (Object child : nodeArray) {
children.add((ConfigNode) child);
synchronized (children) {
for (Object child : nodeArray) {
children.add((ConfigNode) child);
}
}
}
@ -222,13 +224,17 @@ public class Configuration implements Reconfigurable {
private boolean removeChild(String childName) {
ConfigNode child = findChild(childName);
return children.remove(child);
synchronized (children) {
return children.remove(child);
}
}
private ConfigNode findChild(String id) {
for (ConfigNode node : children) {
if (id.equalsIgnoreCase(node.id)) {
return node;
synchronized (children) {
for (ConfigNode node : children) {
if (id.equalsIgnoreCase(node.id)) {
return node;
}
}
}
return null;
@ -245,7 +251,9 @@ public class Configuration implements Reconfigurable {
index++;
}
}
children.add(index, newChild);
synchronized (children) {
children.add(index, newChild);
}
}
private void setChanged(boolean b) {
@ -258,9 +266,11 @@ public class Configuration implements Reconfigurable {
}
public Stream<ConfigNode> getTreeAsStream() {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(ConfigNode::getTreeAsStream));
synchronized (children) {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(ConfigNode::getTreeAsStream));
}
}
}
public static ConfigNode BASE;
@ -346,11 +356,13 @@ public class Configuration implements Reconfigurable {
continue;
}
for (Optional<Reconfigurable> child : (Optional<Reconfigurable>[]) o) {
if (child.isPresent()) {
children.add(child.get());
} else {
children.add(null);
synchronized (children) {
for (Optional<Reconfigurable> child : (Optional<Reconfigurable>[]) o) {
if (child.isPresent()) {
children.add(child.get());
} else {
children.add(null);
}
}
}
}
@ -615,9 +627,11 @@ public class Configuration implements Reconfigurable {
private static void buildNodeMap(ConfigNode n, Map<String, ConfigNode> shortNames) {
// System.out.println("Encountered " + n.subject.getShortName().toLowerCase());
shortNames.put(n.subject.getShortName().toLowerCase(), n);
n.getChildren().stream().forEach((c) -> {
buildNodeMap(c, shortNames);
});
synchronized (n.getChildren()) {
n.getChildren().stream().forEach((c) -> {
buildNodeMap(c, shortNames);
});
}
}
private static void printTree(ConfigNode n, String prefix, int i) {

View File

@ -24,6 +24,7 @@ import jace.config.Reconfigurable;
import jace.state.StateManager;
import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
@ -44,7 +45,7 @@ public abstract class Computer implements Reconfigurable {
public Keyboard keyboard;
public StateManager stateManager;
public Motherboard motherboard;
public boolean romLoaded;
public AtomicBoolean romLoaded = new AtomicBoolean(false);
@ConfigurableField(category = "advanced", name = "State management", shortName = "rewind", description = "This enables rewind support, but consumes a lot of memory when active.")
public boolean enableStateManager;
public final SoundMixer mixer;
@ -56,7 +57,7 @@ public abstract class Computer implements Reconfigurable {
public Computer() {
keyboard = new Keyboard(this);
mixer = new SoundMixer(this);
romLoaded = false;
romLoaded.set(false);
}
public RAM getMemory() {
@ -124,7 +125,7 @@ public abstract class Computer implements Reconfigurable {
public void loadRom(String path) throws IOException {
memory.loadRom(path);
romLoaded = true;
romLoaded.set(true);
}
public void deactivate() {
@ -150,9 +151,9 @@ public abstract class Computer implements Reconfigurable {
consumeKeyEvent = true,
defaultKeyMapping = {"Ctrl+Shift+Backspace", "Ctrl+Shift+Delete"})
public void invokeColdStart() {
if (!romLoaded) {
if (!romLoaded.get()) {
Thread delayedStart = new Thread(() -> {
while (!romLoaded) {
while (!romLoaded.get()) {
Thread.yield();
}
coldStart();

View File

@ -40,7 +40,7 @@ import java.util.logging.Logger;
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class Motherboard extends TimedDevice {
final public Set<Device> miscDevices = Collections.synchronizedSet(new LinkedHashSet<>());
@ConfigurableField(name = "Enable Speaker", shortName = "speaker", defaultValue = "true")
public static boolean enableSpeaker = true;
@ -97,11 +97,9 @@ public class Motherboard extends TimedDevice {
clockCounter = cpuPerClock;
computer.getVideo().doTick();
for (Optional<Card> card : cards) {
card.ifPresent(c -> c.doTick());
card.ifPresent(Card::doTick);
}
miscDevices.stream().forEach((m) -> {
m.doTick();
});
miscDevices.forEach(Device::doTick);
} catch (Throwable t) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, t);
}

View File

@ -58,10 +58,11 @@ public abstract class TimedDevice extends Device {
public boolean suspend() {
disableTempMaxSpeed();
boolean result = super.suspend();
if (worker != null && worker.isAlive()) {
Thread w = worker;
if (w != null && w.isAlive()) {
try {
worker.interrupt();
worker.join(1000);
w.interrupt();
w.join(1000);
} catch (InterruptedException ex) {
}
}
@ -118,22 +119,22 @@ public abstract class TimedDevice extends Device {
public final int getSpeedRatio() {
return speedRatio;
}
public final void setMaxSpeed(boolean enabled) {
maxspeed = enabled;
if (!enabled) {
disableTempMaxSpeed();
}
}
public final boolean isMaxSpeed() {
return maxspeed;
}
public final long getSpeedInHz() {
return cyclesPerInterval * 100L;
}
public final void setSpeedInHz(long cyclesPerSecond) {
// System.out.println("Raw set speed for " + getName() + " to " + cyclesPerSecond + "hz");
speedRatio = (int) Math.round(cyclesPerSecond * 100.0 / defaultCyclesPerSecond());
@ -143,16 +144,16 @@ public abstract class TimedDevice extends Device {
cycleTimer = 0;
resetSyncTimer();
}
public final void setSpeedInPercentage(int ratio) {
// System.out.println("Setting " + getName() + " speed ratio to " + speedRatio);
cyclesPerSecond = defaultCyclesPerSecond() * ratio / 100;
if (cyclesPerSecond == 0) {
cyclesPerSecond = defaultCyclesPerSecond();
}
setSpeedInHz(cyclesPerSecond);
setSpeedInHz(cyclesPerSecond);
}
long skip = 0;
long wait = 0;

View File

@ -209,6 +209,10 @@ public class CardMockingboard extends Card implements Runnable {
}
}
public boolean isRunning() {
return super.isRunning() && playbackThread != null && playbackThread.isAlive();
}
private void doSoundTick() {
if (isRunning() && !pause) {
// buildMixerTable();
@ -356,11 +360,11 @@ public class CardMockingboard extends Card implements Runnable {
int zeroSamples = 0;
setRun(true);
LockSupport.parkNanos(5000);
while (isRunning()) {
while (isRunning() && !Thread.interrupted()) {
while (isRunning() && !computer.isRunning()) {
Thread.currentThread().yield();
Thread.sleep(1000);
}
if (isRunning()) {
if (isRunning() && !Thread.interrupted()) {
playSound(leftBuffer, rightBuffer);
int p = 0;
for (int idx = 0; idx < BUFFER_LENGTH; idx++) {
@ -425,6 +429,8 @@ public class CardMockingboard extends Card implements Runnable {
} catch (LineUnavailableException ex) {
Logger.getLogger(CardMockingboard.class
.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(CardMockingboard.class.getName()).log(Level.SEVERE, null, ex);
} finally {
computer.getMotherboard().cancelSpeedRequest(this);
System.out.println("Mockingboard playback stopped");

View File

@ -169,9 +169,8 @@ public class LawlessComputer extends Apple2e {
try {
for (Optional<Card> c : getMemory().getAllCards()) {
c.ifPresent(Card::reset);
waitForVBL();
}
getCpu().resume();
waitForVBL();
reboot();
} catch (InterruptedException ex) {
Logger.getLogger(LawlessComputer.class.getName()).log(Level.SEVERE, null, ex);