Added speed monitor and fixed a lot of timing problems. 10x speed now possible.

This commit is contained in:
Brendan Robert 2022-03-03 20:10:20 -06:00
parent 261bd7f7d8
commit 639110e639
11 changed files with 58 additions and 18 deletions

View File

@ -259,9 +259,10 @@ public class JaceUIController {
}
if (speedRatio >= 100.0) {
Emulator.getComputer().getMotherboard().setMaxSpeed(true);
Motherboard.cpuPerClock = 10;
Emulator.getComputer().getMotherboard().setSpeedInPercentage(20000);
// Motherboard.cpuPerClock = 10;
} else {
if (speedRatio > 25) {
if (speedRatio > 1000) {
Motherboard.cpuPerClock = 2;
} else {
Motherboard.cpuPerClock = 1;
@ -391,11 +392,11 @@ public class JaceUIController {
Map<Label, Long> iconTTL = new ConcurrentHashMap<>();
void addIndicator(Label icon) {
public void addIndicator(Label icon) {
addIndicator(icon, 250);
}
void addIndicator(Label icon, long TTL) {
public void addIndicator(Label icon, long TTL) {
if (!iconTTL.containsKey(icon)) {
Application.invokeLater(() -> {
if (!notificationBox.getChildren().contains(icon)) {
@ -406,7 +407,7 @@ public class JaceUIController {
trackTTL(icon, TTL);
}
void removeIndicator(Label icon) {
public void removeIndicator(Label icon) {
Application.invokeLater(() -> {
notificationBox.getChildren().remove(icon);
iconTTL.remove(icon);

View File

@ -26,6 +26,7 @@ import jace.config.ConfigurableField;
import jace.core.*;
import jace.hardware.*;
import jace.hardware.massStorage.CardMassStorage;
import jace.lawless.FPSMonitorDevice;
import jace.lawless.LawlessVideo;
import jace.state.Stateful;
@ -95,12 +96,16 @@ public class Apple2e extends Computer {
public Cheats activeCheatEngine = null;
public NoSlotClock clock;
public ZipWarpAccelerator accelerator;
FPSMonitorDevice fpsCounters;
@ConfigurableField(name = "Show speed monitors", shortName = "showFps")
public boolean showSpeedMonitors = false;
/**
* Creates a new instance of Apple2e
*/
public Apple2e() {
super();
fpsCounters = new FPSMonitorDevice(this);
try {
setCpu(new MOS65C02(this));
setMotherboard(new Motherboard(this, null));
@ -353,6 +358,10 @@ public class Apple2e extends Computer {
for (Optional<Card> c : getMemory().getAllCards()) {
c.ifPresent(newDeviceSet::add);
}
if (showSpeedMonitors) {
newDeviceSet.add(fpsCounters);
}
motherboard.attach();
motherboard.setAllDevices(newDeviceSet);
motherboard.reconfigure();
});

View File

@ -74,6 +74,8 @@ public class VideoDHGR extends Video {
initHgrDhgrTables();
initVideoWriters();
registerDirtyFlagChecks();
currentTextWriter = textPage1;
currentGraphicsWriter = loresPage1;
}
// Take two consecutive bytes and double them, taking hi-bit into account

View File

@ -21,6 +21,7 @@ package jace.core;
import jace.config.ConfigurableField;
import jace.config.InvokableAction;
import jace.config.Reconfigurable;
import jace.lawless.FPSMonitorDevice;
import jace.state.StateManager;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;

View File

@ -42,6 +42,7 @@ public abstract class Device implements Reconfigurable {
protected Computer computer;
private final MutableSet<Device> children;
private Device[] childrenArray = new Device[0];
private Device() {
children = Sets.mutable.empty();
@ -70,6 +71,7 @@ public abstract class Device implements Reconfigurable {
if (isAttached) {
d.attach();
}
childrenArray = children.toArray(new Device[0]);
}
public void removeChildDevice(Device d) {
@ -81,6 +83,7 @@ public abstract class Device implements Reconfigurable {
if (isAttached) {
d.detach();
}
childrenArray = children.toArray(new Device[0]);
}
public void addAllDevices(Iterable<Device> devices) {
@ -110,7 +113,9 @@ public abstract class Device implements Reconfigurable {
public void doTick() {
if (isRunning()) {
children.forEach(Device::doTick);
for (Device d : childrenArray) {
d.doTick();
}
if (waitCycles > 0) {
waitCycles--;
return;

View File

@ -23,9 +23,6 @@ import jace.apple2e.Speaker;
import jace.config.ConfigurableField;
import java.util.HashSet;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Motherboard is the heart of the computer. It can have a list of cards
@ -79,11 +76,16 @@ public class Motherboard extends TimedDevice {
return "mb";
}
@ConfigurableField(category = "advanced", shortName = "cpuPerClock", name = "CPU per clock", defaultValue = "1", description = "Number of CPU cycles per clock cycle (normal = 1)")
public static int cpuPerClock = 4;
public static int cpuPerClock = 1;
public int clockCounter = 1;
@Override
public void tick() {
// Extra CPU cycles requested, other devices are called by the TimedDevice abstraction
for (int i=1; i < cpuPerClock; i++) {
computer.getCpu().doTick();
}
/*
try {
clockCounter--;
computer.getCpu().doTick();
@ -100,6 +102,7 @@ public class Motherboard extends TimedDevice {
System.out.print("!");
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, t);
}
*/
}
// From the holy word of Sather 3:5 (Table 3.1) :-)
// This average speed averages in the "long" cycles
@ -137,6 +140,7 @@ public class Motherboard extends TimedDevice {
System.out.println("Speaker not enabled, leaving it off.");
}
});
adjustRelativeSpeeds();
}
HashSet<Object> accelorationRequestors = new HashSet<>();
@ -151,4 +155,14 @@ public class Motherboard extends TimedDevice {
disableTempMaxSpeed();
}
}
void adjustRelativeSpeeds() {
if (isMaxSpeed()) {
computer.getVideo().setWaitPerCycle(8);
} else if (getSpeedInHz() > SPEED) {
computer.getVideo().setWaitPerCycle(getSpeedInHz()/SPEED);
} else {
computer.getVideo().setWaitPerCycle(0);
}
}
}

View File

@ -100,7 +100,9 @@ public abstract class TimedDevice extends Device {
hasStopped = true;
LockSupport.parkNanos(1000);
}
resync();
if (!maxspeed) {
resync();
}
}
hasStopped = true;
System.out.println("Worker thread for " + getDeviceName() + " stopped");
@ -171,10 +173,8 @@ public abstract class TimedDevice extends Device {
protected void resync() {
if (++cycleTimer >= cyclesPerInterval) {
if (maxspeed || tempSpeedDuration > 0) {
if (tempSpeedDuration > 0) {
tempSpeedDuration -= cyclesPerInterval;
}
if (tempSpeedDuration > 0) {
tempSpeedDuration -= cyclesPerInterval;
resetSyncTimer();
return;
}

View File

@ -156,6 +156,8 @@ public abstract class Video extends Device {
@Override
public void tick() {
addWaitCycles(waitsPerCycle);
addWaitCycles((int) motherboardAdjustedWaitsPerCycle);
setScannerLocation(currentWriter.getYOffset(y));
setFloatingBus(computer.getMemory().readRaw(scannerAddress + x));
if (hPeriod > 0) {
@ -232,7 +234,6 @@ public abstract class Video extends Device {
lineDirty = true;
currentWriter.displayByte(video, x, y, textOffset[y], hiresOffset[y]);
}
setWaitCycles(waitsPerCycle);
doPostDraw();
}
@ -294,4 +295,10 @@ public abstract class Video extends Device {
public Image getFrameBuffer() {
return visible;
}
long motherboardAdjustedWaitsPerCycle = 0;
public void setWaitPerCycle(long l) {
motherboardAdjustedWaitsPerCycle = Math.max(0,l);
System.out.println("Adjusting video rendering speed to 1/"+(l+1));
}
}

View File

@ -33,7 +33,7 @@ public class LawlessComputer extends Apple2e {
super();
motherboard.whileSuspended(this::initLawlessLegendsConfiguration);
}
private void initLawlessLegendsConfiguration() {
reconfigure(); // Required before anything so that memory is initialized
this.cheatEngine.setValue(LawlessHacks.class);

View File

@ -78,6 +78,7 @@ public class LawlessVideo extends VideoNTSC {
public LawlessVideo(Computer computer) {
super(computer);
this.vblankStart();
}
public void setEngine(RenderEngine e) {

View File

@ -11,7 +11,7 @@
<StackPane fx:id="stackPane" prefHeight="384.0" prefWidth="560.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<ImageView fx:id="appleScreen" fitHeight="384.0" fitWidth="560.0" pickOnBounds="true" style="-fx-background-color: BLACK;" />
<HBox fx:id="notificationBox" alignment="BOTTOM_RIGHT" blendMode="SCREEN" fillHeight="false" maxHeight="45.0" mouseTransparent="true" prefHeight="45.0" prefWidth="560.0" StackPane.alignment="BOTTOM_CENTER" />
<HBox fx:id="notificationBox" alignment="BOTTOM_RIGHT" fillHeight="false" minHeight="45.0" maxHeight="45.0" mouseTransparent="true" prefHeight="45.0" prefWidth="560.0" StackPane.alignment="BOTTOM_CENTER" />
<AnchorPane fx:id="menuButtonPane" prefHeight="200.0" prefWidth="200.0">
<children>
<Button fx:id="menuButton" layoutX="494.0" layoutY="14.0" mnemonicParsing="false" styleClass="menuButton" text="☰" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0" />