mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-08-15 06:27:24 +00:00
Partial attempt at getting Mockingboard to run more correctly, start of rewrite of music playback routines
This commit is contained in:
@@ -198,7 +198,6 @@ public class SoundMixer extends Device {
|
|||||||
Logger.getLogger(SoundMixer.class.getName()).warning("Playback attempted on stopped buffer!");
|
Logger.getLogger(SoundMixer.class.getName()).warning("Playback attempted on stopped buffer!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentBuffer.put(sample);
|
|
||||||
if (!currentBuffer.hasRemaining()) {
|
if (!currentBuffer.hasRemaining()) {
|
||||||
buffersGenerated++;
|
buffersGenerated++;
|
||||||
currentBuffer.flip();
|
currentBuffer.flip();
|
||||||
@@ -232,6 +231,7 @@ public class SoundMixer extends Device {
|
|||||||
currentBuffer = alternateBuffer;
|
currentBuffer = alternateBuffer;
|
||||||
alternateBuffer = tempBuffer;
|
alternateBuffer = tempBuffer;
|
||||||
}
|
}
|
||||||
|
currentBuffer.put(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() throws InterruptedException, ExecutionException {
|
public void shutdown() throws InterruptedException, ExecutionException {
|
||||||
|
@@ -108,7 +108,7 @@ public abstract class TimedDevice extends Device {
|
|||||||
if (worker != null && worker.isAlive()) {
|
if (worker != null && worker.isAlive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
worker = new Thread(() -> {
|
Thread newWorker = new Thread(() -> {
|
||||||
// System.out.println("Worker thread for " + getDeviceName() + " starting");
|
// System.out.println("Worker thread for " + getDeviceName() + " starting");
|
||||||
while (isRunning()) {
|
while (isRunning()) {
|
||||||
hasStopped = false;
|
hasStopped = false;
|
||||||
@@ -124,10 +124,11 @@ public abstract class TimedDevice extends Device {
|
|||||||
hasStopped = true;
|
hasStopped = true;
|
||||||
// System.out.println("Worker thread for " + getDeviceName() + " stopped");
|
// System.out.println("Worker thread for " + getDeviceName() + " stopped");
|
||||||
});
|
});
|
||||||
worker.setDaemon(false);
|
this.worker = newWorker;
|
||||||
worker.setPriority(Thread.MAX_PRIORITY);
|
newWorker.setDaemon(false);
|
||||||
worker.start();
|
newWorker.setPriority(Thread.MAX_PRIORITY);
|
||||||
worker.setName("Timed device " + getDeviceName() + " worker");
|
newWorker.setName("Timed device " + getDeviceName() + " worker");
|
||||||
|
newWorker.start();
|
||||||
}
|
}
|
||||||
long nanosPerInterval; // How long to wait between pauses
|
long nanosPerInterval; // How long to wait between pauses
|
||||||
long cyclesPerInterval; // How many cycles to wait until a pause interval
|
long cyclesPerInterval; // How many cycles to wait until a pause interval
|
||||||
|
@@ -324,14 +324,13 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean suspendSound() {
|
public boolean suspendSound() {
|
||||||
|
setRun(false);
|
||||||
if (playbackThread == null || !playbackThread.isAlive()) {
|
if (playbackThread == null || !playbackThread.isAlive()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (playbackThread != null) {
|
if (playbackThread != null) {
|
||||||
playbackThread.interrupt();
|
|
||||||
try {
|
try {
|
||||||
// Wait for thread to die
|
playbackThread.join(500);
|
||||||
playbackThread.join();
|
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -160,6 +160,9 @@ public class LawlessComputer extends Apple2e {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void waitForVBL(int count) throws InterruptedException {
|
public void waitForVBL(int count) throws InterruptedException {
|
||||||
|
if (!isRunning()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Semaphore s = new Semaphore(0);
|
Semaphore s = new Semaphore(0);
|
||||||
onNextVBL(s::release);
|
onNextVBL(s::release);
|
||||||
s.acquire();
|
s.acquire();
|
||||||
|
@@ -18,9 +18,6 @@ import jace.cheat.Cheats;
|
|||||||
import jace.core.Computer;
|
import jace.core.Computer;
|
||||||
import jace.core.RAMEvent;
|
import jace.core.RAMEvent;
|
||||||
import jace.lawless.LawlessVideo.RenderEngine;
|
import jace.lawless.LawlessVideo.RenderEngine;
|
||||||
import javafx.beans.property.DoubleProperty;
|
|
||||||
import javafx.scene.media.Media;
|
|
||||||
import javafx.scene.media.MediaPlayer;
|
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,12 +47,10 @@ public class LawlessHacks extends Cheats {
|
|||||||
addCheat("Lawless Legends Graphics Modes", RAMEvent.TYPE.ANY, (e) -> {
|
addCheat("Lawless Legends Graphics Modes", RAMEvent.TYPE.ANY, (e) -> {
|
||||||
int addr = e.getAddress();
|
int addr = e.getAddress();
|
||||||
if (addr >= MODE_SOFTSWITCH_MIN && e.getAddress() <= MODE_SOFTSWITCH_MAX) {
|
if (addr >= MODE_SOFTSWITCH_MIN && e.getAddress() <= MODE_SOFTSWITCH_MAX) {
|
||||||
// System.out.println("Trapped " + e.getType().toString() + " to $" + Integer.toHexString(e.getAddress()));
|
|
||||||
setEngineByOrdinal(e.getAddress() - MODE_SOFTSWITCH_MIN);
|
setEngineByOrdinal(e.getAddress() - MODE_SOFTSWITCH_MIN);
|
||||||
}
|
}
|
||||||
}, MODE_SOFTSWITCH_MIN, MODE_SOFTSWITCH_MAX);
|
}, MODE_SOFTSWITCH_MIN, MODE_SOFTSWITCH_MAX);
|
||||||
addCheat("Lawless Legends Music Commands", RAMEvent.TYPE.WRITE, (e) -> {
|
addCheat("Lawless Legends Music Commands", RAMEvent.TYPE.WRITE, (e) -> {
|
||||||
// System.out.println(Integer.toHexString(e.getAddress()) + " => " + Integer.toHexString(e.getNewValue() & 0x0ff));
|
|
||||||
playSound(e.getNewValue());
|
playSound(e.getNewValue());
|
||||||
}, SFX_TRIGGER);
|
}, SFX_TRIGGER);
|
||||||
}
|
}
|
||||||
@@ -165,7 +160,7 @@ public class LawlessHacks extends Cheats {
|
|||||||
playbackEffect = null;
|
playbackEffect = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<Double> getCurrentTime() {
|
private Optional<Long> getCurrentTime() {
|
||||||
if (currentSongPlayer == null) {
|
if (currentSongPlayer == null) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
} else if (currentSongPlayer.getCurrentTime() == null) {
|
} else if (currentSongPlayer.getCurrentTime() == null) {
|
||||||
@@ -181,9 +176,8 @@ public class LawlessHacks extends Cheats {
|
|||||||
if (player != null) {
|
if (player != null) {
|
||||||
getCurrentTime().ifPresent(val -> lastTime.put(currentSong, val + 1500));
|
getCurrentTime().ifPresent(val -> lastTime.put(currentSong, val + 1500));
|
||||||
playbackEffect = new Thread(() -> {
|
playbackEffect = new Thread(() -> {
|
||||||
DoubleProperty volume = player.volumeProperty();
|
while (playbackEffect == Thread.currentThread() && player.getVolume() > 0.0) {
|
||||||
while (playbackEffect == Thread.currentThread() && volume.get() > 0.0) {
|
player.setVolume(player.getVolume() - FADE_AMT);
|
||||||
volume.set(volume.get() - FADE_AMT);
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(FADE_SPEED);
|
Thread.sleep(FADE_SPEED);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@@ -208,14 +202,13 @@ public class LawlessHacks extends Cheats {
|
|||||||
private void fadeInSong(MediaPlayer player) {
|
private void fadeInSong(MediaPlayer player) {
|
||||||
stopSongEffect();
|
stopSongEffect();
|
||||||
currentSongPlayer = player;
|
currentSongPlayer = player;
|
||||||
DoubleProperty volume = player.volumeProperty();
|
if (player.getVolume() >= 1.0) {
|
||||||
if (volume.get() >= 1.0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackEffect = new Thread(() -> {
|
playbackEffect = new Thread(() -> {
|
||||||
while (playbackEffect == Thread.currentThread() && volume.get() < 1.0) {
|
while (playbackEffect == Thread.currentThread() && player.getVolume() < 1.0) {
|
||||||
volume.set(volume.get() + FADE_AMT);
|
player.setVolume(player.getVolume() + FADE_AMT);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(FADE_SPEED);
|
Thread.sleep(FADE_SPEED);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@@ -250,7 +243,7 @@ public class LawlessHacks extends Cheats {
|
|||||||
player.setCycleCount(repeatSong ? MediaPlayer.INDEFINITE : 1);
|
player.setCycleCount(repeatSong ? MediaPlayer.INDEFINITE : 1);
|
||||||
player.setVolume(0.0);
|
player.setVolume(0.0);
|
||||||
if (playingFightSong || autoResume.contains(track) || switchScores) {
|
if (playingFightSong || autoResume.contains(track) || switchScores) {
|
||||||
double time = lastTime.getOrDefault(track, 0.0);
|
long time = lastTime.getOrDefault(track, 0L);
|
||||||
System.out.println("Auto-resume from time " + time);
|
System.out.println("Auto-resume from time " + time);
|
||||||
player.setStartTime(Duration.millis(time));
|
player.setStartTime(Duration.millis(time));
|
||||||
}
|
}
|
||||||
@@ -316,7 +309,7 @@ public class LawlessHacks extends Cheats {
|
|||||||
Pattern ENTRY = Pattern.compile("([0-9]+)\\s+(.*)");
|
Pattern ENTRY = Pattern.compile("([0-9]+)\\s+(.*)");
|
||||||
private final Map<String, Map<Integer, String>> scores = new HashMap<>();
|
private final Map<String, Map<Integer, String>> scores = new HashMap<>();
|
||||||
private final Set<Integer> autoResume = new HashSet<>();
|
private final Set<Integer> autoResume = new HashSet<>();
|
||||||
private final Map<Integer, Double> lastTime = new HashMap<>();
|
private final Map<Integer, Long> lastTime = new HashMap<>();
|
||||||
private void readScores() {
|
private void readScores() {
|
||||||
InputStream data = getClass().getResourceAsStream("/jace/data/sound/scores.txt");
|
InputStream data = getClass().getResourceAsStream("/jace/data/sound/scores.txt");
|
||||||
readScores(data);
|
readScores(data);
|
||||||
|
@@ -0,0 +1,8 @@
|
|||||||
|
package jace.lawless;
|
||||||
|
|
||||||
|
public class Media {
|
||||||
|
|
||||||
|
public Media(String resourcePath) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,55 @@
|
|||||||
|
package jace.lawless;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
public class MediaPlayer {
|
||||||
|
|
||||||
|
double vol = 1.0;
|
||||||
|
int repeats = 0;
|
||||||
|
int maxRepetitions = 1;
|
||||||
|
Status status = Status.STOPPED;
|
||||||
|
|
||||||
|
public static enum Status {
|
||||||
|
PLAYING, PAUSED, STOPPED
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int INDEFINITE = -1;
|
||||||
|
|
||||||
|
public MediaPlayer(Media song) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Duration getCurrentTime() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getVolume() {
|
||||||
|
return vol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
status = Status.STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCycleCount(int i) {
|
||||||
|
maxRepetitions = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVolume(double d) {
|
||||||
|
vol = Math.max(0.0, Math.min(1.0, d));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartTime(javafx.util.Duration millis) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void play() {
|
||||||
|
repeats = 0;
|
||||||
|
status = Status.PLAYING;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -14,6 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
module lawlesslegends {
|
module lawlesslegends {
|
||||||
requires nestedvm;
|
requires nestedvm;
|
||||||
requires java.base;
|
requires java.base;
|
||||||
|
Reference in New Issue
Block a user