mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-09-30 03:56:59 +00:00
Merge branch 'master' of github.com:badvision/lawless-legends
This commit is contained in:
commit
f35739aec9
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user