Removal of AWT and most uses of reflection

This commit is contained in:
Brendan Robert 2023-07-26 10:50:50 -05:00
parent aa04be5d90
commit 454fcaff36
58 changed files with 1275 additions and 2390 deletions

View File

@ -1 +1 @@
graalvm64-17.0.6
17.0.3

View File

@ -46,7 +46,7 @@
<version>0.0.8</version>
<configuration>
<mainClass>lawlesslegends/jace.LawlessLegends</mainClass>
<executions>
<executions>
<execution>
<!-- Default configuration for running -->
<!-- Usage: mvn clean javafx:run -->
@ -182,11 +182,5 @@
<version>18</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
<type>jar</type>
</dependency>
</dependencies>
</project>

View File

@ -1,31 +1,26 @@
package jace;
import java.awt.Taskbar;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import jace.apple2e.Apple2e;
import jace.apple2e.RAM128k;
import jace.apple2e.SoftSwitches;
import jace.apple2e.VideoNTSC;
import jace.cheat.Cheats.Cheat;
import jace.config.Configuration;
import jace.core.Computer;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import jace.core.Utility;
import jace.hardware.CardDiskII;
import jace.hardware.CardRamFactor;
import jace.hardware.CardRamworks;
import jace.hardware.massStorage.CardMassStorage;
import jace.hardware.Cards;
import jace.hardware.VideoImpls;
import jace.lawless.LawlessComputer;
import jace.lawless.LawlessHacks;
import jace.lawless.LawlessImageTool;
import jace.lawless.LawlessVideo;
import jace.ui.MetacheatUI;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
@ -63,14 +58,6 @@ public class LawlessLegends extends Application {
primaryStage.titleProperty().set("Lawless Legends");
Utility.loadIcon("game_icon.png").ifPresent(icon -> {
primaryStage.getIcons().add(icon);
try {
//set icon for mac os (and other systems which do support this method)
Taskbar.getTaskbar().setIconImage(SwingFXUtils.fromFXImage(icon, null));
} catch (final UnsupportedOperationException e) {
System.out.println("The os does not support: 'taskbar.setIconImage'");
} catch (final SecurityException e) {
System.out.println("There was a security exception for: 'taskbar.setIconImage'");
}
});
} catch (IOException exception) {
throw new RuntimeException(exception);
@ -195,17 +182,17 @@ public class LawlessLegends extends Application {
c.joy1enabled = false;
c.joy2enabled = false;
c.enableStateManager = false;
c.ramCard.setValue(CardRamworks.class);
c.videoRenderer.setValue(LawlessVideo.class);
c.ramCard.setValue(RAM128k.RamCards.CardRamworks);
c.videoRenderer.setValue(VideoImpls.Lawless);
if (c.PRODUCTION_MODE) {
c.card7.setValue(CardMassStorage.class);
c.card6.setValue(CardDiskII.class);
c.card5.setValue(CardRamFactor.class);
c.card7.setValue(Cards.MassStorage);
c.card6.setValue(Cards.DiskIIDrive);
c.card5.setValue(Cards.RamFactor);
c.card4.setValue(null);
c.card2.setValue(null);
c.getMemory().writeWord(0x03f0, 0x0c700, false, false);
}
c.cheatEngine.setValue(LawlessHacks.class);
c.cheatEngine.setValue(Cheat.LawlessHacks);
Configuration.buildTree();
c.reconfigure();
VideoNTSC.setVideoMode(VideoNTSC.VideoMode.TextFriendly, false);

View File

@ -19,7 +19,6 @@
package jace.apple2e;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@ -35,8 +34,8 @@ import java.util.logging.Logger;
import jace.LawlessLegends;
import jace.apple2e.softswitch.VideoSoftSwitch;
import jace.cheat.Cheats;
import jace.config.ClassSelection;
import jace.config.ConfigurableField;
import jace.config.DeviceSelection;
import jace.core.Card;
import jace.core.Computer;
import jace.core.Device;
@ -45,17 +44,12 @@ import jace.core.RAM;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import jace.core.Utility;
import jace.core.Video;
import jace.hardware.CardDiskII;
import jace.hardware.CardExt80Col;
import jace.hardware.CardRamworks;
import jace.hardware.ConsoleProbe;
import jace.hardware.Cards;
import jace.hardware.Joystick;
import jace.hardware.NoSlotClock;
import jace.hardware.VideoImpls;
import jace.hardware.ZipWarpAccelerator;
import jace.hardware.massStorage.CardMassStorage;
import jace.lawless.FPSMonitorDevice;
import jace.lawless.LawlessVideo;
import jace.state.Stateful;
/**
@ -72,30 +66,27 @@ public class Apple2e extends Computer {
static int IRQ_VECTOR = 0x003F2;
@ConfigurableField(name = "Slot 1", shortName = "s1card")
public ClassSelection<Card> card1 = new ClassSelection<>(Card.class, null);
public DeviceSelection<Cards> card1 = new DeviceSelection<>(Cards.class, null);
@ConfigurableField(name = "Slot 2", shortName = "s2card")
public ClassSelection<Card> card2 = new ClassSelection<>(Card.class, null);
public DeviceSelection<Cards> card2 = new DeviceSelection<>(Cards.class, null);
@ConfigurableField(name = "Slot 3", shortName = "s3card")
public ClassSelection<Card> card3 = new ClassSelection<>(Card.class, null);
public DeviceSelection<Cards> card3 = new DeviceSelection<>(Cards.class, null);
@ConfigurableField(name = "Slot 4", shortName = "s4card")
public ClassSelection<Card> card4 = new ClassSelection<>(Card.class, null);
public DeviceSelection<Cards> card4 = new DeviceSelection<>(Cards.class, null);
@ConfigurableField(name = "Slot 5", shortName = "s5card")
public ClassSelection<Card> card5 = new ClassSelection<>(Card.class, null);
public DeviceSelection<Cards> card5 = new DeviceSelection<>(Cards.class, null);
@ConfigurableField(name = "Slot 6", shortName = "s6card")
public ClassSelection<Card> card6 = new ClassSelection<>(Card.class, CardDiskII.class);
public DeviceSelection<Cards> card6 = new DeviceSelection<>(Cards.class, Cards.DiskIIDrive);
@ConfigurableField(name = "Slot 7", shortName = "s7card")
public ClassSelection<Card> card7 = new ClassSelection<>(Card.class, CardMassStorage.class);
public DeviceSelection<Cards> card7 = new DeviceSelection<>(Cards.class, Cards.MassStorage);
@ConfigurableField(name = "Debug rom", shortName = "debugRom", description = "Use debugger //e rom")
public boolean useDebugRom = false;
@ConfigurableField(name = "Console probe", description = "Enable console redirection (experimental!)")
public boolean useConsoleProbe = false;
private final ConsoleProbe probe = new ConsoleProbe();
@ConfigurableField(name = "Helpful hints", shortName = "hints")
public boolean enableHints = true;
@ConfigurableField(name = "Renderer", shortName = "video", description = "Video rendering implementation")
public ClassSelection<Video> videoRenderer = new ClassSelection<>(Video.class, LawlessVideo.class);
public DeviceSelection<VideoImpls> videoRenderer = new DeviceSelection<>(VideoImpls.class, VideoImpls.Lawless, false);
@ConfigurableField(name = "Aux Ram", shortName = "ram", description = "Aux ram card")
public ClassSelection<RAM128k> ramCard = new ClassSelection<>(RAM128k.class, CardRamworks.class);
public DeviceSelection<RAM128k.RamCards> ramCard = new DeviceSelection<>(RAM128k.RamCards.class, RAM128k.RamCards.CardRamworks, false);
@ConfigurableField(name = "Joystick 1 Enabled", shortName = "joy1", description = "If unchecked, then there is no joystick support.", enablesDevice = true)
public boolean joy1enabled = true;
@ConfigurableField(name = "Joystick 2 Enabled", shortName = "joy2", description = "If unchecked, then there is no joystick support.", enablesDevice = true)
@ -110,7 +101,7 @@ public class Apple2e extends Computer {
public Joystick joystick1;
public Joystick joystick2;
@ConfigurableField(name = "Activate Cheats", shortName = "cheat")
public ClassSelection<Cheats> cheatEngine = new ClassSelection<>(Cheats.class, null);
public DeviceSelection<Cheats.Cheat> cheatEngine = new DeviceSelection<>(Cheats.Cheat.class, null);
public Cheats activeCheatEngine = null;
public NoSlotClock clock;
public ZipWarpAccelerator accelerator;
@ -187,26 +178,22 @@ public class Apple2e extends Computer {
return activeCheatEngine;
}
private void insertCard(Class<? extends Card> type, int slot) throws NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
private void insertCard(DeviceSelection<Cards> type, int slot) {
if (getMemory().getCard(slot).isPresent()) {
if (getMemory().getCard(slot).get().getClass().equals(type)) {
if (type.getValue() != null && type.getValue().isInstance(getMemory().getCard(slot).get())) {
return;
}
getMemory().removeCard(slot);
}
if (type != null) {
try {
Card card = type.getConstructor(Computer.class).newInstance(this);
getMemory().addCard(card, slot);
} catch (InstantiationException | IllegalAccessException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
}
if (type != null && type.getValue() != null) {
Card card = type.getValue().create(this);
getMemory().addCard(card, slot);
}
}
private Class<? extends RAM128k> getDesiredMemoryConfiguration() {
private RAM128k.RamCards getDesiredMemoryConfiguration() {
if (ramCard.getValue() == null) {
return CardExt80Col.class;
return RAM128k.RamCards.CardExt80Col;
} else {
return ramCard.getValue();
}
@ -216,7 +203,7 @@ public class Apple2e extends Computer {
if (getMemory() == null) {
return false;
}
return getMemory().getClass().equals(getDesiredMemoryConfiguration());
return getDesiredMemoryConfiguration().isInstance((RAM128k) getMemory());
}
@Override
@ -233,21 +220,17 @@ public class Apple2e extends Computer {
}
motherboard.whileSuspended(()-> {
if (!isMemoryConfigurationCorrect()) {
try {
if (getVideo() != null) {
getVideo().suspend();
}
setVideo(null);
System.out.println("Creating new ram using " + getDesiredMemoryConfiguration().getName());
RAM128k newMemory = getDesiredMemoryConfiguration().getConstructor(Computer.class).newInstance(this);
if (getVideo() != null) {
getVideo().suspend();
}
setVideo(null);
System.out.println("Creating new ram using " + getDesiredMemoryConfiguration().getName());
RAM128k newMemory = getDesiredMemoryConfiguration().create(this);
if (getMemory() != null) {
newMemory.copyFrom((RAM128k) getMemory());
}
setMemory(newMemory);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
}
if (getMemory() != null) {
newMemory.copyFrom((RAM128k) getMemory());
}
setMemory(newMemory);
}
try {
@ -298,44 +281,30 @@ public class Apple2e extends Computer {
clock = null;
}
if (useConsoleProbe) {
probe.init(this);
} else {
probe.shutdown();
}
if (getVideo() == null || getVideo().getClass() != videoRenderer.getValue()) {
if (videoRenderer.getValue() != null && !videoRenderer.getValue().isInstance(getVideo())) {
boolean resumeVideo = false;
if (getVideo() != null) {
resumeVideo = getVideo().suspend();
}
try {
setVideo(videoRenderer.getValue().getConstructor(Computer.class).newInstance(this));
getVideo().configureVideoMode();
getVideo().reconfigure();
if (LawlessLegends.getApplication() != null) {
LawlessLegends.getApplication().reconnectUIHooks();
}
if (resumeVideo) {
getVideo().resume();
}
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
setVideo(videoRenderer.getValue().create(this));
getVideo().configureVideoMode();
getVideo().reconfigure();
if (LawlessLegends.getApplication() != null) {
LawlessLegends.getApplication().reconnectUIHooks();
}
if (resumeVideo) {
getVideo().resume();
}
}
try {
// Add all new cards
insertCard(card1.getValue(), 1);
insertCard(card2.getValue(), 2);
insertCard(card3.getValue(), 3);
insertCard(card4.getValue(), 4);
insertCard(card5.getValue(), 5);
insertCard(card6.getValue(), 6);
insertCard(card7.getValue(), 7);
} catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
}
// Add all new cards
insertCard(card1, 1);
insertCard(card2, 2);
insertCard(card3, 3);
insertCard(card4, 4);
insertCard(card5, 5);
insertCard(card6, 6);
insertCard(card7, 7);
if (enableHints) {
enableHints();
} else {
@ -351,7 +320,7 @@ public class Apple2e extends Computer {
} else {
boolean startCheats = true;
if (activeCheatEngine != null) {
if (activeCheatEngine.getClass().equals(cheatEngine.getValue())) {
if (cheatEngine.getValue().isInstance(activeCheatEngine)) {
startCheats = false;
newDeviceSet.add(activeCheatEngine);
} else {
@ -360,12 +329,8 @@ public class Apple2e extends Computer {
activeCheatEngine = null;
}
}
if (startCheats) {
try {
activeCheatEngine = cheatEngine.getValue().getConstructor(Computer.class).newInstance(this);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
}
if (startCheats && cheatEngine.getValue() != null) {
activeCheatEngine = cheatEngine.getValue().create(this);
newDeviceSet.add(activeCheatEngine);
}
}

View File

@ -18,18 +18,26 @@
*/
package jace.apple2e;
import jace.core.*;
import jace.state.Stateful;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import jace.config.DeviceEnum;
import jace.core.CPU;
import jace.core.Card;
import jace.core.Computer;
import jace.core.PagedMemory;
import jace.core.RAM;
import jace.hardware.CardExt80Col;
import jace.hardware.CardRamworks;
import jace.state.Stateful;
/**
* Implementation of a 128k memory space and the MMU found in an Apple //e. The
* MMU behavior is mimicked by configureActiveMemory.
@ -38,6 +46,36 @@ import java.util.stream.Stream;
*/
@Stateful
abstract public class RAM128k extends RAM {
// Memory card implementations
public static enum RamCards implements DeviceEnum<RAM128k> {
CardExt80Col("80-Column Card (128k)", CardExt80Col.class, CardExt80Col::new),
CardRamworks("Ramworks (4mb)", CardRamworks.class, CardRamworks::new);
Function<Computer, ? extends RAM128k> factory;
String name;
Class clazz;
RamCards(String name, Class clazz, Function<Computer, ? extends RAM128k> factory) {
this.factory = factory;
this.name = name;
this.clazz = clazz;
}
@Override
public RAM128k create(Computer c) {
return factory.apply(c);
}
@Override
public String getName() {
return name;
}
@Override
public boolean isInstance(RAM128k card) {
return card != null && clazz.isInstance(card);
}
}
static final Logger LOG = Logger.getLogger(RAM128k.class.getName());

View File

@ -63,7 +63,7 @@ public class VideoNTSC extends VideoDHGR {
protected boolean[] colorActive = new boolean[80];
int rowStart = 0;
public VideoNTSC(Computer computer) {
super(computer);
initDivideTables();

View File

@ -18,14 +18,18 @@
*/
package jace.cheat;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
import jace.apple2e.MOS65C02;
import jace.config.DeviceEnum;
import jace.config.InvokableAction;
import jace.core.Computer;
import jace.core.Device;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import java.util.HashSet;
import java.util.Set;
import jace.lawless.LawlessHacks;
/**
* Represents some combination of hacks that can be enabled or disabled through
@ -34,6 +38,38 @@ import java.util.Set;
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public abstract class Cheats extends Device {
public static enum Cheat implements DeviceEnum<Cheats> {
Metacheat("Metacheat", MetaCheat.class, MetaCheat::new),
MontezumasRevenge("Montezuma's Revenge", MontezumasRevengeCheats.class, MontezumasRevengeCheats::new),
PrinceOfPersia("Prince of Persia", PrinceOfPersiaCheats.class, PrinceOfPersiaCheats::new),
LawlessHacks("Lawless Legends Enhancements", LawlessHacks.class, LawlessHacks::new);
Function<Computer, Cheats> factory;
String name;
Class clazz;
Cheat(String name, Class clazz, Function<Computer, Cheats> factory) {
this.name = name;
this.clazz = clazz;
this.factory = factory;
}
@Override
public String getName() {
return name;
}
@Override
public Cheats create(Computer computer) {
return factory.apply(computer);
}
@Override
public boolean isInstance(Cheats cheat) {
return clazz.isInstance(cheat);
}
}
boolean cheatsActive = true;
Set<RAMListener> listeners = new HashSet<>();

View File

@ -20,7 +20,6 @@ package jace.cheat;
import jace.EmulatorUILogic;
import jace.apple2e.RAM128k;
import jace.apple2e.SoftSwitches;
import jace.config.ConfigurableField;
import jace.core.Computer;
import jace.core.PagedMemory;

View File

@ -1,136 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.config;
import jace.core.Utility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class ClassSelection<C> extends DynamicSelection<Class<? extends C>> {
Class<C> template;
public ClassSelection(Class<C> supertype, Class<? extends C> defaultValue) {
super(defaultValue);
template = supertype;
}
@Override
public LinkedHashMap<Class<C>, String> getSelections() {
LinkedHashMap<Class<C>, String> selections = new LinkedHashMap<>();
Set<Class<? extends C>> allClasses = Utility.findAllSubclasses(template);
allClasses.add(null);
List<Entry<Class<? extends C>, String>> values = new ArrayList<>();
if (allowNull()) {
values.add(new Entry<Class<? extends C>, String>() {
@Override
public Class<? extends C> getKey() {
return null;
}
@Override
public String getValue() {
return "***Empty***";
}
@Override
public String setValue(String v) {
throw new UnsupportedOperationException("Not supported yet.");
}
});
}
for (final Class<? extends C> c : allClasses) {
Entry<Class<? extends C>, String> entry = new Map.Entry<Class<? extends C>, String>() {
@Override
public Class<? extends C> getKey() {
return c;
}
@Override
public String getValue() {
if (c == null) {
return "**Empty**";
}
if (c.isAnnotationPresent(Name.class)) {
return c.getAnnotation(Name.class).value();
}
return c.getSimpleName();
}
@Override
public String setValue(String value) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String toString() {
return getValue();
}
@Override
public boolean equals(Object obj) {
return super.equals(obj) || obj == getKey() || getKey() != null && getKey().equals(obj);
}
};
values.add(entry);
}
Collections.sort(values, (Entry<? extends Class, String> o1, Entry<? extends Class, String> o2) -> {
if (o1.getKey() == null) {
return -1;
}
if (o2.getKey() == null) {
return 1;
} else {
return (o1.getValue().compareTo(o2.getValue()));
}
});
values.forEach((entry) -> {
Class key = entry.getKey();
selections.put(key, entry.getValue());
});
return selections;
}
@Override
public boolean allowNull() {
return false;
}
@Override
public void setValue(Class value) {
Object v = value;
if (v != null && v instanceof String) {
super.setValueByMatch((String) v);
return;
}
super.setValue(value);
}
}

View File

@ -52,6 +52,7 @@ import jace.EmulatorUILogic;
import jace.core.Computer;
import jace.core.Keyboard;
import jace.core.Utility;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TreeItem;
import javafx.scene.image.ImageView;
@ -126,7 +127,7 @@ public class Configuration implements Reconfigurable {
public transient ConfigNode root;
public transient ConfigNode parent;
private final transient ObservableList<ConfigNode> children;
private transient ObservableList<ConfigNode> children;
public transient Reconfigurable subject;
private transient boolean changed = true;
@ -146,7 +147,9 @@ public class Configuration implements Reconfigurable {
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
// Create children list if it doesn't exist
if (children == null) {
children = FXCollections.observableArrayList();
children.setAll(getChildren());
}
children.setAll(super.getChildren());
@ -441,8 +444,8 @@ public class Configuration implements Reconfigurable {
successful = true;
} catch (FileNotFoundException ex) {
// This just means there are no settings to be saved -- just ignore it.
} catch (InvalidClassException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.WARNING, "Unable to load settings, Jace version is newer and incompatible with old settings.");
} catch (InvalidClassException | NullPointerException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.WARNING, "Unable to load settings, Jace version is newer and incompatible with old settings.");
} catch (ClassNotFoundException | IOException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
} finally {

View File

@ -0,0 +1,9 @@
package jace.config;
import jace.core.Computer;
public interface DeviceEnum<T extends Reconfigurable> {
public String getName();
public T create(Computer computer);
public boolean isInstance(T t);
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
* @param <C> Enum class which implements DeviceEnum
*/
// C is an enum class which implements DeviceEnum
public class DeviceSelection<C extends Enum & DeviceEnum> extends DynamicSelection<C> {
Class<C> enumClass;
boolean nullAllowed = false;
public DeviceSelection(Class<C> enumClass, C defaultValue) {
super(defaultValue);
if (defaultValue == null) {
nullAllowed = true;
}
this.enumClass = enumClass;
}
public DeviceSelection(Class<C> enumClass, C defaultValue, boolean nullAllowed) {
this(enumClass, defaultValue);
this.nullAllowed = nullAllowed;
}
@Override
public LinkedHashMap<C, String> getSelections() {
LinkedHashMap<C, String> selections = new LinkedHashMap<>();
if (allowNull()) {
selections.put(null, "***Empty***");
}
// Sort enum constants by getName
List<C> sorted = new ArrayList<>();
sorted.addAll(Arrays.asList(enumClass.getEnumConstants()));
Collections.sort(sorted, (C o1, C o2) -> o1.getName().compareTo(o2.getName()));
for (C c : enumClass.getEnumConstants()) {
selections.put(c, c.getName());
}
return selections;
}
@Override
public boolean allowNull() {
return nullAllowed;
}
@Override
public void setValue(C value) {
Object v = value;
if (v != null && v instanceof String) {
super.setValueByMatch((String) v);
return;
}
super.setValue(value);
}
}

View File

@ -35,8 +35,8 @@ import jace.apple2e.SoftSwitches;
*/
public abstract class Card extends Device {
private final PagedMemory cxRom;
private final PagedMemory c8Rom;
private PagedMemory cxRom;
private PagedMemory c8Rom;
private int slot;
private RAMListener ioListener;
private RAMListener firmwareListener;

View File

@ -18,11 +18,13 @@
*/
package jace.core;
import jace.config.Reconfigurable;
import jace.state.Stateful;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Supplier;
import jace.config.Reconfigurable;
import jace.state.Stateful;
/**
* Device is a very simple abstraction of any emulation component. A device
@ -184,6 +186,18 @@ public abstract class Device implements Reconfigurable {
r.run();
}
}
public <T> T whileSuspended(Supplier<T> r, T defaultValue) {
if (isRunning()) {
suspend();
T result = r.get();
resume();
return result;
} else {
return defaultValue;
}
}
public boolean suspend() {
if (isRunning()) {

View File

@ -18,10 +18,6 @@
*/
package jace.core;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
@ -39,6 +35,7 @@ import jace.apple2e.SoftSwitches;
import jace.config.InvokableAction;
import jace.config.Reconfigurable;
import javafx.event.EventHandler;
import javafx.scene.input.Clipboard;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
@ -334,18 +331,10 @@ public class Keyboard implements Reconfigurable {
@InvokableAction(name = "Paste clipboard", alternatives = "paste", category = "Keyboard", notifyOnRelease = false, defaultKeyMapping = {"Ctrl+Shift+V","Shift+Insert"}, consumeKeyEvent = true)
public static void pasteFromClipboard() {
try {
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
String contents = (String) clip.getData(DataFlavor.stringFlavor);
if (contents != null && !"".equals(contents)) {
contents = contents.replaceAll("\\r?\\n|\\r", (char) 0x0d + "");
pasteBuffer = new StringReader(contents);
}
} catch (UnsupportedFlavorException | IOException ex) {
Logger.getLogger(Keyboard.class
.getName()).log(Level.SEVERE, null, ex);
Clipboard clipboard = Clipboard.getSystemClipboard();
if (clipboard.hasString()) {
pasteFromString(clipboard.getString());
}
}
static StringReader pasteBuffer = null;

View File

@ -18,14 +18,15 @@
*/
package jace.core;
import jace.apple2e.SoftSwitches;
import jace.config.Reconfigurable;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.function.Consumer;
import java.util.function.Supplier;
import jace.apple2e.SoftSwitches;
import jace.config.Reconfigurable;
/**
* RAM is a 64K address space of paged memory. It also manages sets of memory
@ -45,7 +46,10 @@ public abstract class RAM implements Reconfigurable {
public Optional<Card>[] cards;
// card 0 = 80 column card firmware / system rom
public int activeSlot = 0;
protected final Computer computer;
protected Computer computer;
public RAM() {
}
/**
* Creates a new instance of RAM
@ -54,7 +58,7 @@ public abstract class RAM implements Reconfigurable {
*/
public RAM(Computer computer) {
this.computer = computer;
listeners = new HashSet<>();
listeners = new ConcurrentSkipListSet<>();
cards = (Optional<Card>[]) new Optional[8];
for (int i = 0; i < 8; i++) {
cards[i] = Optional.empty();
@ -157,12 +161,12 @@ public abstract class RAM implements Reconfigurable {
return msb + lsb;
}
private void mapListener(RAMListener l, int address) {
private synchronized void mapListener(RAMListener l, int address) {
if ((address & 0x0FF00) == 0x0C000) {
int index = address & 0x0FF;
Set<RAMListener> ioListeners = ioListenerMap[index];
if (ioListeners == null) {
ioListeners = Collections.synchronizedSet(new HashSet<>());
ioListeners = new ConcurrentSkipListSet<>();
ioListenerMap[index] = ioListeners;
}
ioListeners.add(l);
@ -170,7 +174,7 @@ public abstract class RAM implements Reconfigurable {
int index = (address >> 8) & 0x0FF;
Set<RAMListener> otherListeners = listenerMap[index];
if (otherListeners == null) {
otherListeners = Collections.synchronizedSet(new HashSet<>());
otherListeners = new ConcurrentSkipListSet<>();
listenerMap[index] = otherListeners;
}
otherListeners.add(l);
@ -275,8 +279,8 @@ public abstract class RAM implements Reconfigurable {
if (listeners.contains(l)) {
return l;
}
listeners.add(l);
computer.cpu.whileSuspended(()->{
listeners.add(l);
addListenerRange(l);
});
return l;
@ -299,26 +303,20 @@ public abstract class RAM implements Reconfigurable {
}
public void removeListener(final RAMListener l) {
boolean restart = computer.pause();
listeners.remove(l);
refreshListenerMap();
if (restart) {
computer.resume();
if (!listeners.contains(l)) {
return;
}
listeners.remove(l);
computer.cpu.whileSuspended(()->{
refreshListenerMap();
});
}
public byte callListener(RAMEvent.TYPE t, int address, int oldValue, int newValue, boolean requireSyncronization) {
private byte _callListener(RAMEvent.TYPE t, int address, int oldValue, int newValue) {
Set<RAMListener> activeListeners;
boolean resume = false;
if (requireSyncronization) {
resume = computer.getCpu().suspend();
}
if ((address & 0x0FF00) == 0x0C000) {
activeListeners = ioListenerMap[address & 0x0FF];
if (activeListeners == null && t.isRead()) {
if (resume) {
computer.getCpu().resume();
}
return computer.getVideo().getFloatingBus();
}
} else {
@ -327,17 +325,19 @@ public abstract class RAM implements Reconfigurable {
if (activeListeners != null && !activeListeners.isEmpty()) {
RAMEvent e = new RAMEvent(t, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY, address, oldValue, newValue);
activeListeners.forEach((l) -> l.handleEvent(e));
if (resume) {
computer.getCpu().resume();
}
return (byte) e.getNewValue();
}
if (resume) {
computer.getCpu().resume();
}
return (byte) newValue;
}
public byte callListener(RAMEvent.TYPE t, int address, int oldValue, int newValue, boolean requireSyncronization) {
if (requireSyncronization) {
return computer.cpu.whileSuspended((Supplier<Byte>) () -> _callListener(t, address, oldValue, newValue), (byte) 0);
} else {
return _callListener(t, address, oldValue, newValue);
}
}
abstract protected void loadRom(String path) throws IOException;
abstract public void attach();

View File

@ -29,7 +29,7 @@ import jace.core.RAMEvent.TYPE;
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public abstract class RAMListener implements RAMEvent.RAMEventHandler {
public abstract class RAMListener implements RAMEvent.RAMEventHandler, Comparable<RAMListener> {
private RAMEvent.TYPE type;
private RAMEvent.SCOPE scope;
@ -158,4 +158,21 @@ public abstract class RAMListener implements RAMEvent.RAMEventHandler {
abstract protected void doConfig();
abstract protected void doEvent(RAMEvent e);
@Override
public int compareTo(RAMListener o) {
if (o.scopeStart == scopeStart) {
if (o.scopeEnd == scopeEnd) {
if (o.type == type) {
return Integer.compare(o.hashCode(), hashCode());
} else {
return Integer.compare(o.type.ordinal(), type.ordinal());
}
} else {
return Integer.compare(o.scopeEnd, scopeEnd);
}
} else {
return Integer.compare(o.scopeStart, scopeStart);
}
}
}

View File

@ -18,6 +18,9 @@
*/
package jace.core;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
@ -25,9 +28,6 @@ import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import jace.config.ConfigurableField;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.FloatControl;
/**
* Manages sound resources used by various audio devices (such as speaker and
@ -77,7 +77,7 @@ public class SoundMixer extends Device {
line.open(format);
line.start();
// Logger.getLogger(getClass().getName()).log(Level.INFO, "Obtained source data line: %s, buffer size %d".formatted(line.getFormat(), line.getBufferSize()));
} catch (LineUnavailableException e) {
} catch (IllegalArgumentException | LineUnavailableException e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Error getting sound line: {0}", e.getMessage());
}
return line;

View File

@ -20,7 +20,6 @@ package jace.core;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
@ -31,12 +30,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.reflections.Reflections;
import jace.config.Configuration;
import jace.config.InvokableAction;
import javafx.application.Platform;
@ -59,12 +56,6 @@ import javafx.scene.paint.Color;
*/
public class Utility {
static Reflections reflections = new Reflections("jace");
public static <T> Set<Class<? extends T>> findAllSubclasses(Class<T> clazz) {
return reflections.getSubTypesOf(clazz);
}
//------------------------------ String comparators
/**
* Rank two strings similarity in terms of distance The lower the number,
@ -233,27 +224,7 @@ public class Utility {
});
});
}
// public static void runModalProcess(String title, final Runnable runnable) {
//// final JDialog frame = new JDialog(Emulator.getFrame());
// final JProgressBar progressBar = new JProgressBar();
// progressBar.setIndeterminate(true);
// final JPanel contentPane = new JPanel();
// contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// contentPane.setLayout(new BorderLayout());
// contentPane.add(new JLabel(title), BorderLayout.NORTH);
// contentPane.add(progressBar, BorderLayout.CENTER);
// frame.setContentPane(contentPane);
// frame.pack();
// frame.setLocationRelativeTo(null);
// frame.setVisible(true);
//
// new Thread(() -> {
// runnable.run();
// frame.setVisible(false);
// frame.dispose();
// }).start();
// }
public static class RankingComparator implements Comparator<String> {
String match;
@ -374,68 +345,6 @@ public class Utility {
});
}
public static Object findChild(Object object, String fieldName) {
if (object instanceof Map map) {
for (Object key : map.keySet()) {
if (key.toString().equalsIgnoreCase(fieldName)) {
return map.get(key);
}
}
return null;
}
try {
Field f = object.getClass().getField(fieldName);
return f.get(object);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
for (Method m : object.getClass().getMethods()) {
if (m.getName().equalsIgnoreCase("get" + fieldName) && m.getParameterTypes().length == 0) {
try {
return m.invoke(object);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex1) {
}
}
}
}
return null;
}
public static Object setChild(Object object, String fieldName, String value, boolean hex) {
if (object instanceof Map map) {
for (Object key : map.entrySet()) {
if (key.toString().equalsIgnoreCase(fieldName)) {
map.put(key, value);
return null;
}
}
return null;
}
Field f;
try {
f = object.getClass().getField(fieldName);
} catch (NoSuchFieldException ex) {
System.out.println("Object type " + object.getClass().getName() + " has no field named " + fieldName);
Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (SecurityException ex) {
Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
Object useValue = deserializeString(value, f.getType(), hex);
try {
f.set(object, useValue);
return useValue;
} catch (IllegalArgumentException | IllegalAccessException ex) {
for (Method m : object.getClass().getMethods()) {
if (m.getName().equalsIgnoreCase("set" + fieldName) && m.getParameterTypes().length == 0) {
try {
m.invoke(object, useValue);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex1) {
}
}
}
}
return useValue;
}
static Map<Class, Map<String, Object>> enumCache = new HashMap<>();
public static Object findClosestEnumConstant(String value, Class type) {
@ -497,46 +406,25 @@ public class Utility {
return null;
}
public static Object getProperty(Object object, String path) {
String[] paths = path.split("\\.");
for (String path1 : paths) {
object = findChild(object, path1);
if (object == null) {
return null;
}
}
return object;
}
public static Object setProperty(Object object, String path, String value, boolean hex) {
String[] paths = path.split("\\.");
for (int i = 0; i < paths.length - 1; i++) {
object = findChild(object, paths[i]);
if (object == null) {
return null;
}
}
return setChild(object, paths[paths.length - 1], value, hex);
}
static Map<InvokableAction, Runnable> allActions = null;
static final Map<InvokableAction, Runnable> allActions = new ConcurrentHashMap<>();
public static Map<InvokableAction, Runnable> getAllInvokableActions() {
if (allActions == null) {
allActions = new HashMap<>();
Configuration.BASE.getTreeAsStream().forEach((Configuration.ConfigNode node) -> {
for (Method m : node.subject.getClass().getMethods()) {
if (m.isAnnotationPresent(InvokableAction.class)) {
allActions.put(m.getAnnotation(InvokableAction.class), () -> {
try {
m.invoke(node.subject);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex);
}
});
synchronized (allActions) {
if (allActions.isEmpty()) {
Configuration.BASE.getTreeAsStream().forEach((Configuration.ConfigNode node) -> {
for (Method m : node.subject.getClass().getMethods()) {
if (m.isAnnotationPresent(InvokableAction.class)) {
allActions.put(m.getAnnotation(InvokableAction.class), () -> {
try {
m.invoke(node.subject);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
}
}
});
});
}
}
return allActions;
}

View File

@ -175,33 +175,15 @@ public class CardAppleMouse extends Card {
if (type == RAMEvent.TYPE.EXECUTE) {
// This means the CPU is calling firmware at this location
switch (offset - 0x080) {
case 0:
setMouse();
break;
case 1:
serveMouse();
break;
case 2:
readMouse();
break;
case 3:
clearMouse();
break;
case 4:
posMouse();
break;
case 5:
clampMouse();
break;
case 6:
homeMouse();
break;
case 7:
initMouse();
break;
case 8:
getMouseClamp();
break;
case 0 -> setMouse();
case 1 -> serveMouse();
case 2 -> readMouse();
case 3 -> clearMouse();
case 4 -> posMouse();
case 5 -> clampMouse();
case 6 -> homeMouse();
case 7 -> initMouse();
case 8 -> getMouseClamp();
}
// Always pass back RTS
e.setNewValue(0x060);

View File

@ -18,6 +18,12 @@
*/
package jace.hardware;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import jace.EmulatorUILogic;
import jace.config.ConfigurableField;
import jace.config.Name;
@ -29,11 +35,6 @@ import jace.core.RAMEvent.TYPE;
import jace.core.Utility;
import jace.library.MediaConsumer;
import jace.library.MediaConsumerParent;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Apple Disk ][ interface implementation. This card represents the interface

View File

@ -45,7 +45,7 @@ public class CardExt80Col extends RAM128k {
public String getShortName() {
return "128kb";
}
public CardExt80Col(Computer computer) {
super(computer);
auxMemory = new PagedMemory(0xc000, PagedMemory.Type.RAM, computer);

View File

@ -18,13 +18,14 @@
*/
package jace.hardware;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import jace.config.Name;
import jace.core.Computer;
import jace.core.RAMEvent;
import jace.core.RAMEvent.TYPE;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Partial Hayes Micromodem II implementation, acting more as a bridge to

View File

@ -18,6 +18,16 @@
*/
package jace.hardware;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.SourceDataLine;
import jace.config.ConfigurableField;
import jace.config.Name;
import jace.core.Card;
@ -29,15 +39,6 @@ import jace.core.RAMListener;
import jace.core.SoundMixer;
import jace.hardware.mockingboard.PSG;
import jace.hardware.mockingboard.R6522;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
/**
* Mockingboard-C implementation (with partial Phasor support). This uses two

View File

@ -18,6 +18,13 @@
*/
package jace.hardware;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import jace.config.ConfigurableField;
import jace.config.Name;
import jace.core.Card;
@ -26,12 +33,6 @@ import jace.core.RAMEvent;
import jace.core.RAMEvent.TYPE;
import jace.core.Utility;
import jace.state.Stateful;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.scene.control.Label;
/**

View File

@ -18,6 +18,11 @@
*/
package jace.hardware;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import jace.apple2e.RAM128k;
import jace.config.ConfigurableField;
import jace.config.Name;
@ -26,10 +31,6 @@ import jace.core.PagedMemory;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import jace.state.Stateful;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
/**
* Emulates the Ramworks Basic and Ramworks III cards
@ -47,10 +48,10 @@ public class CardRamworks extends RAM128k {
public Map<BankType, PagedMemory> nullBank = generateBank();
@ConfigurableField(
category = "memory",
defaultValue = "3072",
defaultValue = "4096",
name = "Memory Size",
description = "Size in KB. Should be a multiple of 64 and not exceed 8192. The real card cannot support more than 3072k")
public int memorySize = 3072;
public int memorySize = 4096;
public int maxBank = memorySize / 64;
private Map<BankType, PagedMemory> generateBank() {
Map<BankType, PagedMemory> memoryBank = new EnumMap<>(BankType.class);

View File

@ -18,15 +18,6 @@
*/
package jace.hardware;
import jace.EmulatorUILogic;
import jace.config.ConfigurableField;
import jace.config.Name;
import jace.config.Reconfigurable;
import jace.core.Card;
import jace.core.Computer;
import jace.core.RAMEvent;
import jace.core.RAMEvent.TYPE;
import jace.core.Utility;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@ -36,6 +27,16 @@ import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import jace.EmulatorUILogic;
import jace.config.ConfigurableField;
import jace.config.Name;
import jace.config.Reconfigurable;
import jace.core.Card;
import jace.core.Computer;
import jace.core.RAMEvent;
import jace.core.RAMEvent.TYPE;
import jace.core.Utility;
import javafx.scene.control.Label;
/**

View File

@ -18,6 +18,14 @@
*/
package jace.hardware;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Optional;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import jace.EmulatorUILogic;
import jace.apple2e.MOS65C02;
import jace.config.ConfigurableField;
@ -29,13 +37,6 @@ import jace.core.PagedMemory;
import jace.core.RAMEvent;
import jace.core.RAMEvent.TYPE;
import jace.core.Utility;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Optional;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.scene.control.Label;
/**

View File

@ -0,0 +1,44 @@
package jace.hardware;
import java.util.function.Function;
import jace.config.DeviceEnum;
import jace.core.Card;
import jace.core.Computer;
import jace.hardware.massStorage.CardMassStorage;
public enum Cards implements DeviceEnum<Card> {
DiskIIDrive("Disk II Floppy Controller", CardDiskII.class, CardDiskII::new),
MassStorage("Mass Storage", CardMassStorage.class, CardMassStorage::new),
AppleMouse("Apple Mouse", CardAppleMouse.class, CardAppleMouse::new),
HayesMicroModem("Hayes MicroModem", CardHayesMicromodem.class, CardHayesMicromodem::new),
Mockingboard("Mockingboard", CardMockingboard.class, CardMockingboard::new),
SuperSerialCard("Super Serial Card", CardSSC.class, CardSSC::new),
RamFactor("RamFactor", CardRamFactor.class, CardRamFactor::new),
Thunderclock("Thunderclock", CardThunderclock.class, CardThunderclock::new);
Function<Computer, Card> factory;
String name;
Class clazz;
Cards(String name, Class clazz, Function<Computer, Card> factory) {
this.name = name;
this.factory = factory;
this.clazz = clazz;
}
@Override
public String getName() {
return name;
}
@Override
public Card create(Computer computer) {
return factory.apply(computer);
}
@Override
public boolean isInstance(Card card) {
return card != null && clazz.isInstance(card);
}
}

View File

@ -1,166 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.hardware;
import jace.apple2e.SoftSwitches;
import jace.core.Computer;
import jace.core.Keyboard;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Attempt at adding accessibility by redirecting screen/keyboard traffic to
* stdout/stdin of the console. Doesn't work well, unfortunately.
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class ConsoleProbe {
public static boolean enabled = true;
public String[] lastScreen = new String[24];
public List<Rectangle> regions = new ArrayList<Rectangle>();
private RAMListener textListener;
public static long lastChange;
public static long updateDelay = 100L;
public static boolean readerActive = false;
public Computer computer;
private Thread keyReaderThread;
public void init(final Computer c) {
computer = c;
enabled = true;
keyReaderThread = new Thread(new KeyReader());
keyReaderThread.setName("Console probe key reader");
keyReaderThread.start();
textListener = new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) {
@Override
protected void doConfig() {
setScopeStart(0x0400);
setScopeEnd(0x0BFF);
}
@Override
protected void doEvent(RAMEvent e) {
if (e.getAddress() < 0x0800 && SoftSwitches.PAGE2.isOn()) {
return;
}
if (SoftSwitches.TEXT.isOff()) {
if (SoftSwitches.MIXED.isOn()) {
handleMixedMode();
}
} else {
handleTextMode();
}
}
private void handleMixedMode() {
handleTextMode();
}
private void handleTextMode() {
lastChange = System.currentTimeMillis();
if (readerActive) {
return;
}
Thread t = new Thread(new ScreenReader());
t.start();
}
};
c.getMemory().addListener(textListener);
}
public static synchronized void performRead() {
}
public void shutdown() {
enabled = false;
if (textListener != null) {
computer.getMemory().removeListener(textListener);
}
if (keyReaderThread != null && keyReaderThread.isAlive()) {
try {
keyReaderThread.join();
} catch (InterruptedException ex) {
Logger.getLogger(ConsoleProbe.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static class ScreenReader implements Runnable {
public void run() {
readerActive = true;
try {
// Keep sleeping until there have been no more screen changes during the specified delay period
// It is possible that the lastChange will keep being updated while in this loop
// That is both expected and the reason this is a loop!
long delay = 0;
while (System.currentTimeMillis() - lastChange <= updateDelay) {
delay = updateDelay - System.currentTimeMillis() - lastChange;
if (delay > 0) {
Thread.sleep(delay);
}
}
} catch (InterruptedException ex) {
Logger.getLogger(ConsoleProbe.class.getName()).log(Level.SEVERE, null, ex);
}
// Signal that we're off to go read the screen (and any additional update will need to spawn the thread again)
readerActive = false;
performRead();
}
}
public static class KeyReader implements Runnable {
public Computer c;
public void run() {
while (true) {
try {
while (enabled && (System.in.available() == 0 || Keyboard.readState() < 0)) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
Logger.getLogger(ConsoleProbe.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (!enabled) {
return;
}
int ch = System.in.read();
if (ch == 10) {
ch = 13;
}
Keyboard.pressKey((byte) ch);
} catch (IOException ex) {
System.out.println(ex.getMessage());
Logger.getLogger(ConsoleProbe.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}

View File

@ -1,99 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.hardware;
import jace.apple2e.MOS65C02;
import jace.core.Computer;
import jace.core.Keyboard;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import java.awt.Toolkit;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Attempt to simplify what ConsoleProbe was attempting. Still not ready for any
* real use.
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class ConsoleProbeSimple {
RAMListener cout;
public static int COUT = 0xFDED;
public void init(final Computer c) {
Thread t = new Thread(new KeyReader());
t.start();
cout = new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
@Override
protected void doConfig() {
setScopeStart(COUT);
}
@Override
protected void doEvent(RAMEvent e) {
MOS65C02 cpu = (MOS65C02) c.getCpu();
int ch = cpu.A & 0x07f;
if (ch == 13) {
System.out.println();
} else if (ch < ' ') {
if (ch == 7) {
Toolkit.getDefaultToolkit().beep();
} else {
System.out.println("CHR" + ch);
}
} else {
System.out.print((char) ch);
}
}
};
c.getMemory().addListener(cout);
}
public static class KeyReader implements Runnable {
public Computer c;
public void run() {
while (true) {
try {
while (System.in.available() == 0 || Keyboard.readState() < 0) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
Logger.getLogger(ConsoleProbeSimple.class.getName()).log(Level.SEVERE, null, ex);
}
}
int ch = System.in.read();
if (ch == 10) {
ch = 13;
}
Keyboard.pressKey((byte) ch);
} catch (IOException ex) {
System.out.println(ex.getMessage());
Logger.getLogger(ConsoleProbeSimple.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}

View File

@ -18,6 +18,7 @@
*/
package jace.hardware;
import jace.LawlessLegends;
import jace.apple2e.SoftSwitches;
import jace.apple2e.softswitch.MemorySoftSwitch;
import jace.config.ConfigurableField;
@ -27,14 +28,8 @@ import jace.core.Device;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import jace.state.Stateful;
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
/**
* Simple implementation of joystick support that supports mouse or keyboard.
@ -61,14 +56,18 @@ public class Joystick extends Device {
private int joyY = 0;
MemorySoftSwitch xSwitch;
MemorySoftSwitch ySwitch;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Point lastMouseLocation;
Robot robot;
Point centerPoint;
public Joystick(int port, Computer computer) {
super(computer);
centerPoint = new Point(screenSize.width / 2, screenSize.height / 2);
Stage stage = LawlessLegends.getApplication().primaryStage;
// Register a mouse handler on the primary stage that tracks the
// mouse x/y position as a percentage of window width and height
stage.addEventHandler(MouseEvent.MOUSE_MOVED, event -> {
if (!useKeyboard) {
joyX = (int) (event.getX() / stage.getWidth() * 255);
joyY = (int) (event.getY() / stage.getHeight() * 255);
}
});
this.port = port;
if (port == 0) {
xSwitch = (MemorySoftSwitch) SoftSwitches.PDL0.getSwitch();
@ -77,12 +76,6 @@ public class Joystick extends Device {
xSwitch = (MemorySoftSwitch) SoftSwitches.PDL2.getSwitch();
ySwitch = (MemorySoftSwitch) SoftSwitches.PDL3.getSwitch();
}
lastMouseLocation = MouseInfo.getPointerInfo().getLocation();
try {
robot = new Robot();
} catch (AWTException ex) {
Logger.getLogger(Joystick.class.getName()).log(Level.SEVERE, null, ex);
}
}
public boolean leftPressed = false;
public boolean rightPressed = false;
@ -93,47 +86,6 @@ public class Joystick extends Device {
if (useKeyboard) {
joyX = (leftPressed ? -128 : 0) + (rightPressed ? 255 : 128);
joyY = (upPressed ? -128 : 0) + (downPressed ? 255 : 128);
} else {
Point l = MouseInfo.getPointerInfo().getLocation();
if (l.x < lastMouseLocation.x) {
joyX = 0;
} else if (l.x > lastMouseLocation.x) {
joyX = 255;
} else {
joyX = 128;
}
if (l.y < lastMouseLocation.y) {
joyY = 0;
} else if (l.y > lastMouseLocation.y) {
joyY = 255;
} else {
joyY = 128;
}
if (centerMouse) {
lastMouseLocation = centerPoint;
robot.mouseMove(centerPoint.x, centerPoint.y);
} else {
if (l.x <= 20) {
robot.mouseMove(20, l.y);
l = MouseInfo.getPointerInfo().getLocation();
}
if ((l.x + 21) == screenSize.getWidth()) {
robot.mouseMove((int) (screenSize.getWidth() - 20), l.y);
l = MouseInfo.getPointerInfo().getLocation();
}
if (l.y <= 20) {
robot.mouseMove(l.x, 20);
l = MouseInfo.getPointerInfo().getLocation();
}
if ((l.y + 21) == screenSize.getHeight()) {
robot.mouseMove(l.x, (int) (screenSize.getHeight() - 20));
l = MouseInfo.getPointerInfo().getLocation();
}
lastMouseLocation = l;
}
}
}

View File

@ -0,0 +1,41 @@
package jace.hardware;
import java.util.function.Function;
import jace.apple2e.VideoDHGR;
import jace.apple2e.VideoNTSC;
import jace.config.DeviceEnum;
import jace.core.Computer;
import jace.core.Video;
import jace.lawless.LawlessVideo;
public enum VideoImpls implements DeviceEnum<Video> {
DHGR("Double-Hires graphics", VideoDHGR.class, VideoDHGR::new),
NTSC("NTSC Emulation", VideoNTSC.class, VideoNTSC::new),
Lawless("Lawless enhanced video", LawlessVideo.class, LawlessVideo::new);
private final String name;
private final Class clazz;
private final Function<Computer, Video> factory;
VideoImpls(String name, Class clazz, Function<Computer, Video> factory) {
this.name = name;
this.clazz = clazz;
this.factory = factory;
}
@Override
public String getName() {
return name;
}
@Override
public Video create(Computer computer) {
return factory.apply(computer);
}
@Override
public boolean isInstance(Video video) {
return clazz.isInstance(video);
}
}

View File

@ -18,6 +18,11 @@
*/
package jace.hardware.massStorage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import jace.EmulatorUILogic;
import jace.apple2e.MOS65C02;
import jace.config.ConfigurableField;
@ -33,10 +38,6 @@ import jace.library.MediaCache;
import jace.library.MediaConsumer;
import jace.library.MediaConsumerParent;
import jace.library.MediaEntry;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Hard disk and 800k floppy (smartport) controller card. HDV and 2MG images are

View File

@ -13,6 +13,7 @@ import jace.apple2e.Apple2e;
import jace.apple2e.RAM128k;
import jace.apple2e.SoftSwitches;
import jace.apple2e.VideoNTSC;
import jace.cheat.Cheats;
import jace.config.ConfigurableField;
import jace.core.Video;
import jace.library.MediaConsumer;
@ -33,10 +34,10 @@ public class LawlessComputer extends Apple2e {
}
public void initLawlessLegendsConfiguration() {
this.cheatEngine.setValue(Cheats.Cheat.LawlessHacks);
reconfigure(); // Required before anything so that memory is initialized
this.cheatEngine.setValue(LawlessHacks.class);
this.activeCheatEngine = new LawlessHacks(this);
this.activeCheatEngine.attach();
// this.activeCheatEngine = new LawlessHacks(this);
// this.activeCheatEngine.attach();
blankTextPage1();
reconfigure();
}

View File

@ -106,7 +106,6 @@ public class LawlessHacks extends Cheats {
stopSfx();
}
} else if (isMusic) {
System.out.println("Play music "+track);
playMusic(track, false);
} else {
System.out.println("Play sfx "+track);
@ -150,7 +149,7 @@ public class LawlessHacks extends Cheats {
if (currentSong != track || switchScores) {
fadeOutSong(() -> startNewSong(track, switchScores));
} else {
new Thread(() -> startNewSong(track, false)).start();
// new Thread(() -> startNewSong(track, false)).start();
}
currentSong = track;
}
@ -240,6 +239,7 @@ public class LawlessHacks extends Cheats {
}
MediaPlayer player;
if (track != currentSong || !isPlayingMusic() || switchScores) {
System.out.println("Play music "+track);
// If the same song is already playing don't restart it
Media song = getAudioTrack(track);

View File

@ -91,8 +91,6 @@ public class LawlessVideo extends VideoNTSC {
Emulator.withComputer(c->c.onNextVBL(Video::forceRefresh));
System.out.println("Detected engine: " + e.name());
} else {
System.out.println("Detected engine same as before: " + e.name());
}
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (C) 2013 brobert.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.library;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/**
*
* @author brobert
*/
class TransferableMediaEntry implements Transferable {
MediaEntry entry;
public TransferableMediaEntry(MediaEntry entry) {
this.entry = entry;
}
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{DataFlavor.stringFlavor};
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.isFlavorTextType();
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return String.valueOf(entry.id);
}
}

View File

@ -18,7 +18,6 @@
*/
package jace.state;
import java.awt.image.BufferedImage;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
@ -65,7 +64,7 @@ public class StateManager implements Reconfigurable {
public int maxStates = 100;
@ConfigurableField(category = "Emulator", name = "Capture frequency", description = "How often states are captured, in relation to each VBL (1 = 60 states/second, 2 = 30 states/second, 3 = 15 states/second, etc", defaultValue = "3")
public int captureFrequency = 3;
private ObjectGraphNode<BufferedImage> imageGraphNode;
private ObjectGraphNode<Image> imageGraphNode;
Computer computer;
@ -166,7 +165,7 @@ public class StateManager implements Reconfigurable {
Class type = node.getCurrentValue().getClass();
if (PagedMemory.class.isAssignableFrom(type)) {
addMemoryPages(node, f);
} else if (BufferedImage.class.isAssignableFrom(type)) {
} else if (Image.class.isAssignableFrom(type)) {
addVideoFrame(node, f);
} else if (List.class.isAssignableFrom(type)) {
List l = (List) node.getCurrentValue();
@ -213,7 +212,7 @@ public class StateManager implements Reconfigurable {
* @param node
* @param f
*/
private void addVideoFrame(ObjectGraphNode<BufferedImage> node, Field f) {
private void addVideoFrame(ObjectGraphNode<Image> node, Field f) {
imageGraphNode = node;
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.tracker;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class Command {
public enum CommandScope {global, channel}
public enum CommandType {
Rest(0, 0, 0, false),
Ay1(1, 1, 17, false),
Ay2(2, 1, 17, false),
Ay1and2(3, 2, 34, true),
PitchSlide(4, 2, 2, true),
Vibrato(5, 2, 2, true),
VolumeSlide(6, 2, 2, true),
Tremolo(7, 2, 2, true),
GlobalDetune(8, 2, 2, true),
Reserved(9, 0, 0, false),
AllOff(0x0a, 1, 1, false),
Reset(0x0b, 1, 1, false),
Playback(0x0c, 1, 2, false),
TicksPerBeat(0x0d, 1, 1, true),
Clock(0x0e, 2, 2, false),
Macro(0x0f, 1, 1, true);
int number;
int maxParameters;
int minParameters;
boolean isChain;
CommandType(int num, int minParam, int maxParam, boolean chain) {
number = num;
isChain = chain;
maxParameters = maxParam;
minParameters = minParam;
}
}
Integer[] parameters = {};
}

View File

@ -1,274 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.tracker;
import jace.core.Utility;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.*;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class EditableLabel extends JPanel implements MouseListener, FocusListener {
public static EditableLabel FOCUS;
public static int DEFAULT_GAP = 4;
Component editComponent;
JLabel labelComponent;
CardLayout layout;
boolean isEditing = false;
int width = 4;
Object ownerObject;
String objectProperty;
private void showBlankValue() {
String s = "...................".substring(0, width);
labelComponent.setText(s);
}
public enum cards {
label, edit
}
public EditableLabel(JLabel label, Component edit, int width, Object owner, String property) {
this(label, edit, width, DEFAULT_GAP, DEFAULT_GAP, owner, property);
}
public EditableLabel(JLabel label, Component edit, int width, int horizontalPadding, int verticalPadding, Object owner, String property) {
ownerObject = owner;
this.width = width;
objectProperty = property;
addMouseListener(this);
edit.addFocusListener(this);
addFocusListener(this);
layout = new CardLayout(horizontalPadding, verticalPadding);
setLayout(layout);
add(label, cards.label.toString());
add(edit, cards.edit.toString());
labelComponent = label;
editComponent = edit;
deactivateEdit();
setBackground(UserInterface.Theme.background.color);
label.setForeground(UserInterface.Theme.foreground.color);
label.setOpaque(false);
edit.setBackground(UserInterface.Theme.backgroundEdit.color);
edit.setForeground(UserInterface.Theme.foregroundEdit.color);
edit.setFocusTraversalKeysEnabled(false);
edit.addKeyListener(NAV_LISTENER);
label.addKeyListener(NAV_LISTENER);
this.addKeyListener(NAV_LISTENER);
}
@Override
public void mouseClicked(MouseEvent e) {
mousePressed(e);
}
@Override
public void mousePressed(MouseEvent e) {
if (isEditing) {
return;
}
activateEdit();
// This next bit will generate a second mouse event and pass it on to the edit component so that
// the edit cursor appears under the mouse pointer, not a the start of the component.
final MouseEvent e2 = new MouseEvent(editComponent, e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
editComponent.dispatchEvent(e2);
}
});
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void focusGained(FocusEvent e) {
if (e.getComponent() == this || e.getComponent() == labelComponent || e.getComponent() == editComponent) {
activateEdit();
} else {
deactivateEdit();
}
}
@Override
public void focusLost(FocusEvent e) {
deactivateEdit();
}
private void activateEdit() {
FOCUS = this;
isEditing = true;
layout.show(this, cards.edit.toString());
editComponent.requestFocusInWindow();
}
private void deactivateEdit() {
isEditing = false;
if (editComponent instanceof JTextField) {
String value = ((JTextComponent) editComponent).getText();
if (value != null) {
value = value.trim();
if (value.length() > width) {
value = value.substring(0, width);
}
}
Object result = Utility.setProperty(ownerObject, objectProperty, value, true);
value = (result == null) ? null : (result instanceof Integer ? Integer.toString((Integer) result, 16) : result.toString());
if (value != null && value.length() < width) {
value = value.concat(" ".substring(0, width - value.length()));
}
if (value == null || value.equals("")) {
showBlankValue();
((JTextComponent) editComponent).setText(null);
} else {
labelComponent.setText(value);
((JTextComponent) editComponent).setText(value.trim());
}
} else if (editComponent instanceof JComboBox) {
ImageIcon selection = (ImageIcon) ((JComboBox) editComponent).getSelectedItem();
labelComponent.setText(selection.getDescription());
}
layout.show(this, cards.label.toString());
}
public static EditableLabel generateTextLabel(Object owner, String property, int width, KeyListener listener) {
EditableLabel label = generateTextLabel(owner, property, width);
label.editComponent.addKeyListener(listener);
return label;
}
public static EditableLabel generateTextLabel(Object owner, String property, int width) {
Object value = Utility.getProperty(owner, property);
JLabel label = new JLabel(value != null ? value.toString() : null);
JTextField editor = new JTextField("");
editor.setCaretColor(UserInterface.Theme.foregroundEdit.color);
editor.setBorder(new EmptyBorder(0, 0, 0, 0));
label.setFont(UserInterface.EDITOR_FONT);
editor.setFont(UserInterface.EDITOR_FONT);
EditableLabel output = new EditableLabel(label, editor, width, owner, property);
if (value == null || value.equals("")) {
output.showBlankValue();
}
return output;
}
static KeyListener NAV_LISTENER = new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_TAB:
if (e.isShiftDown()) {
moveLeft();
} else {
moveRight();
}
e.consume();
break;
case KeyEvent.VK_UP:
moveUp();
e.consume();
break;
case KeyEvent.VK_DOWN:
moveDown();
e.consume();
break;
default:
break;
}
}
public int getIndex(Component c) {
System.out.println("Looking for " + c.getClass().getName() + " in parent " + c.getParent().getClass().getName());
for (int i = 0; i < c.getParent().getComponentCount(); i++) {
if (c == c.getParent().getComponent(i)) {
return i;
}
}
return -1;
}
public void focus(final Component c) {
Runnable r = () -> {
if (c instanceof EditableLabel) {
((EditableLabel) c).activateEdit();
} else {
c.requestFocusInWindow();
}
};
EventQueue.invokeLater(r);
}
public void moveDown() {
Component c = FOCUS;
int col = getIndex(c);
int row = getIndex(c.getParent()) + 1;
if (row < c.getParent().getParent().getComponentCount()) {
System.out.println("Trying to focus on col " + col + " row " + row);
focus(((Container) c.getParent().getParent().getComponent(row)).getComponent(col));
}
}
public void moveUp() {
Component c = FOCUS;
int col = getIndex(c);
int row = getIndex(c.getParent()) - 1;
if (row >= 0) {
System.out.println("Trying to focus on col " + col + " row " + row);
focus(((Container) c.getParent().getParent().getComponent(row)).getComponent(col));
}
}
public void moveLeft() {
Component c = FOCUS;
int col = getIndex(c) - 1;
System.out.println("Trying to focus on col " + col);
if (col >= 0) {
focus(c.getParent().getComponent(col));
}
}
public void moveRight() {
Component c = FOCUS;
int col = getIndex(c) + 1;
System.out.println("Trying to focus on col " + col);
if (col < c.getParent().getComponentCount()) {
focus(c.getParent().getComponent(col));
}
}
};
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.tracker;
import java.util.ArrayList;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class Pattern extends ArrayList<Row> {
String description; // Not used currently
int id;
}

View File

@ -1,119 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.tracker;
import jace.apple2e.MOS65C02;
import jace.core.Card;
import jace.core.Computer;
import jace.core.Motherboard;
import jace.hardware.CardExt80Col;
import jace.hardware.CardMockingboard;
import java.util.Optional;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class PlaybackEngine extends Computer {
Computer dummyComputer = new Computer() {
@Override
public void coldStart() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void warmStart() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
protected void doPause() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
protected void doResume() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public String getName() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public String getShortName() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
};
Motherboard motherboard = new Motherboard(dummyComputer, null);
CardMockingboard mockingboard = new CardMockingboard(dummyComputer);
public PlaybackEngine() {
setMemory(new CardExt80Col(dummyComputer));
setCpu(new MOS65C02(dummyComputer));
getMemory().addCard(mockingboard, 5);
}
@Override
public void coldStart() {
for (Optional<Card> c : getMemory().getAllCards()) {
c.ifPresent(Card::reset);
}
}
@Override
public void warmStart() {
for (Optional<Card> c : getMemory().getAllCards()) {
c.ifPresent(Card::reset);
}
}
@Override
public boolean isRunning() {
return motherboard.isRunning();
}
@Override
protected void doPause() {
motherboard.suspend();
}
@Override
protected void doResume() {
motherboard.resume();
}
@Override
public String getName() {
return "Playback Computer";
}
@Override
public String getShortName() {
return "Computer";
}
@Override
public void reconfigure() {
// do nothing
}
}

View File

@ -1,218 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.tracker;
import jace.core.Utility;
import java.awt.image.BufferedImage;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Set;
import javax.swing.ImageIcon;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class Row {
public enum Note {
C0(3901),
CS0(3682),
D0(3476),
DS0(3279),
E0(3096),
F0(2922),
FS0(2759),
G0(2603),
GS0(2457),
A0(2319),
AS0(2189),
B0(2066),
C1(1950),
CS1(1841),
D1(1737),
DS1(1640),
E1(1548),
F1(1461),
FS1(1379),
G1(1302),
GS1(1229),
A1(1160),
AS1(1095),
B1(1033),
C2(975),
CS2(920),
D2(869),
DS2(820),
E2(774),
F2(731),
FS2(690),
G2(651),
GS2(614),
A2(580),
AS2(547),
B2(517),
C3(488),
CS3(460),
D3(434),
DS3(410),
E3(387),
F3(365),
FS3(345),
G3(325),
GS3(307),
A3(290),
AS3(274),
B3(258),
C4(244),
CS4(230),
D4(217),
DS4(205),
E4(193),
F4(183),
FS4(172),
G4(163),
GS4(154),
A4(145),
AS4(137),
B4(129),
C5(122),
CS5(115),
D5(109),
DS5(102),
E5(97),
F5(91),
FS5(86),
G5(81),
GS5(77),
A5(72),
AS5(68),
B5(65),
C6(61),
CS6(58),
D6(54),
DS6(51),
E6(48),
F6(46),
FS6(43),
G6(41),
GS6(38),
A6(36),
AS6(34),
B6(32),
C7(30),
CS7(29),
D7(27),
DS7(26),
E7(24),
F7(23),
FS7(22),
G7(20),
GS7(19),
A7(18),
AS7(17),
B7(16),
C8(15);
int freq;
Note(int f) {
freq = f;
}
@Override
public String toString() {
return super.toString().replace("S", "#");
}
}
static ImageIcon[] ENVELOPE_ICONS;
static {
ENVELOPE_ICONS = new ImageIcon[EnvelopeShape.values().length];
int i = 0;
for (EnvelopeShape shape : EnvelopeShape.values()) {
ENVELOPE_ICONS[i++] = shape.getIcon();
}
}
public enum EnvelopeShape {
unspecified(-1, ""),
pulse(0, "|\\____"),
pulseinv(4, "/|____"),
saw(8, "|\\|\\|\\"),
triangle(10,"\\/\\/\\/"),
triangleinv(14,"/\\/\\/\\"),
holdinv(11,"|\\|^^^"),
hold(13,"/^^^^^");
int value;
String pattern;
ImageIcon icon;
EnvelopeShape(int v, String p) {
value = v;
pattern = p;
}
ImageIcon getIcon() {
if (icon == null) {
if (value >= 0) {
// icon = Utility.loadIcon("ayenvelope"+value+".png");
} else {
icon = new ImageIcon(new BufferedImage(64, 12,BufferedImage.TYPE_4BYTE_ABGR));
}
icon.setDescription(toString());
}
return icon;
}
}
public enum Channel {A1, B1, C1, A2, B2, C2}
public static class ChannelData {
public Note tone;
public Integer volume; // Range 0-F
public Boolean toneActive;
public Boolean noiseActive;
public Boolean envelopeActive; // Results in volume = 0x010
public Set<Command> commands = new HashSet<Command>();
public boolean isEmpty() {
if (!commands.isEmpty()) return false;
return tone == null && volume == null && toneActive == null && noiseActive == null && envelopeActive == null;
}
}
public EnumMap<Channel, ChannelData> channels = new EnumMap<Channel, ChannelData>(Channel.class);
public Row() {
for (Channel c : Channel.values()) {
channels.put(c, new ChannelData());
}
}
public Integer ay1noisePeriod, ay2noisePeriod;
public Integer ay1envelopePeriod, ay2envelopePeriod;
public EnvelopeShape ay1envelopeShape, ay2envelopeShape;
public Set<Command> globalCommands = new HashSet<Command>();
public boolean isEmpty() {
for (ChannelData d : channels.values()) {
if (d != null && !d.isEmpty()) return false;
}
if (ay1envelopePeriod != null || ay2envelopePeriod != null) return false;
if (ay1envelopeShape != null || ay2envelopeShape != null) return false;
if (ay1noisePeriod != null || ay2noisePeriod != null) return false;
return globalCommands.isEmpty();
}
}

View File

@ -1,44 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.tracker;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class Song {
public enum Format {
woz0
}
Format format;
int fileSize;
String songName;
String authorName;
Map<Integer, Pattern> patterns = new HashMap<>();
Map<Integer, Pattern> macros = new HashMap<>();
int defaultPatternLength = 64;
int defaultMacroLength = 16;
List<Integer> order = new ArrayList<>();
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.tracker;
import java.io.InputStream;
import java.io.OutputStream;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class SongPersistor {
static void writeToBytes(OutputStream s) {
}
static Song readFromBytes(InputStream s) {
Song song = new Song();
return song;
}
}

View File

@ -1,258 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.tracker;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.xml.transform.Source;
/**
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class UserInterface {
static Font EDITOR_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 12);
public enum Theme {
background(0x000000),
foreground(0xffffff),
backgroundEdit(0x000080),
foregroundEdit(0xffff80);
Color color;
Theme(int col) {
color = new Color(col & 0x0ffffff);
}
}
public static int BASE_OCTAVE = 3;
public enum Note {
C0("C", -1),
CS0("CS", -1),
D0("D", -1),
DS0("DS", -1),
E0("E", -1),
F0("F", -1),
FS0("FS", -1),
G0("G", -1),
GS0("GS", -1),
A0("A", -1),
AS0("AS", -1),
B0("B", -1),
C1("C", 0),
CS1("CS", 0),
D1("D", 0),
DS1("DS", 0),
E1("E", 0),
F1("F", 0),
FS1("FS", 0),
G1("G", 0),
GS1("GS", 0),
A1("A", 0),
AS1("AS", 0),
B1("B", 0),
C2("C", 1),
CS2("CS", 1),
D2("D", 1),
DS2("DS", 1),
E2("E", 1);
public String note;
public int octaveOffset;
Note(String n, int offset) {
note = n;
octaveOffset = offset;
}
}
public static final Map<Integer, Note> KEYBOARD_MAP = new HashMap<Integer, Note>();
static {
KEYBOARD_MAP.put(KeyEvent.VK_Z, Note.C0);
KEYBOARD_MAP.put(KeyEvent.VK_S, Note.CS0);
KEYBOARD_MAP.put(KeyEvent.VK_X, Note.D0);
KEYBOARD_MAP.put(KeyEvent.VK_D, Note.DS0);
KEYBOARD_MAP.put(KeyEvent.VK_C, Note.E0);
KEYBOARD_MAP.put(KeyEvent.VK_V, Note.F0);
KEYBOARD_MAP.put(KeyEvent.VK_G, Note.FS0);
KEYBOARD_MAP.put(KeyEvent.VK_B, Note.G0);
KEYBOARD_MAP.put(KeyEvent.VK_H, Note.GS0);
KEYBOARD_MAP.put(KeyEvent.VK_N, Note.A0);
KEYBOARD_MAP.put(KeyEvent.VK_J, Note.AS0);
KEYBOARD_MAP.put(KeyEvent.VK_M, Note.B0);
KEYBOARD_MAP.put(KeyEvent.VK_Q, Note.C1);
KEYBOARD_MAP.put(KeyEvent.VK_2, Note.CS1);
KEYBOARD_MAP.put(KeyEvent.VK_W, Note.D1);
KEYBOARD_MAP.put(KeyEvent.VK_3, Note.DS1);
KEYBOARD_MAP.put(KeyEvent.VK_E, Note.E1);
KEYBOARD_MAP.put(KeyEvent.VK_R, Note.F1);
KEYBOARD_MAP.put(KeyEvent.VK_5, Note.FS1);
KEYBOARD_MAP.put(KeyEvent.VK_T, Note.G1);
KEYBOARD_MAP.put(KeyEvent.VK_6, Note.GS1);
KEYBOARD_MAP.put(KeyEvent.VK_Y, Note.A1);
KEYBOARD_MAP.put(KeyEvent.VK_7, Note.AS1);
KEYBOARD_MAP.put(KeyEvent.VK_U, Note.B1);
KEYBOARD_MAP.put(KeyEvent.VK_I, Note.C2);
KEYBOARD_MAP.put(KeyEvent.VK_9, Note.CS2);
KEYBOARD_MAP.put(KeyEvent.VK_O, Note.D2);
KEYBOARD_MAP.put(KeyEvent.VK_0, Note.DS2);
KEYBOARD_MAP.put(KeyEvent.VK_P, Note.E2);
}
public static void main(String... args) {
Row r = new Row();
JFrame testWindow = new JFrame();
testWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testWindow.setSize(900, 600);
Container content = testWindow.getContentPane();
content.setLayout(new BoxLayout(testWindow.getContentPane(), BoxLayout.Y_AXIS));
content.setBackground(Theme.background.color);
content.setForeground(Theme.foreground.color);
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
content.add(createRowEditor(r));
// testWindow.doLayout();
testWindow.setVisible(true);
}
public static KeyAdapter toneListner = new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
e.consume();
}
@Override
public void keyTyped(KeyEvent e) {
e.consume();
}
@Override
public void keyPressed(KeyEvent e) {
JTextField field = (JTextField) e.getSource();
if (KEYBOARD_MAP.containsKey(e.getKeyCode())) {
Note n = KEYBOARD_MAP.get(e.getKeyCode());
String noteval = n.note;
int octave = BASE_OCTAVE + n.octaveOffset;
noteval += octave;
try {
// Test the waters, is ths value ok?
Row.Note.valueOf(noteval);
// Looks like it worked -- use the value
field.setText(noteval);
} catch (Throwable t) {
// out of bounds or bad value
}
}
e.consume();
field.setFocusable(false);
field.setFocusable(true);
}
};
public static Component createRowEditor(Row r) {
JPanel rowEditor = new JPanel();
rowEditor.setSize(800, 24);
rowEditor.setLayout(new BoxLayout(rowEditor, BoxLayout.X_AXIS));
rowEditor.setBackground(Theme.background.color);
rowEditor.setOpaque(true);
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.A1.tone", 3, toneListner));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.A1.volume", 1));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.A1.commands", 3));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.B1.tone", 3, toneListner));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.B1.volume", 1));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.B1.commands", 3));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.C1.tone", 3, toneListner));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.C1.volume", 1));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.C1.commands", 3));
rowEditor.add(EditableLabel.generateTextLabel(r, "ay1noisePeriod", 4));
rowEditor.add(EditableLabel.generateTextLabel(r, "ay1envelopePeriod", 4));
rowEditor.add(generateEnvelopeEditor(r.ay1envelopeShape, r, "ay2envelopeShape"));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.A2.tone", 3, toneListner));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.A2.volume", 1));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.A2.commands", 3));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.B2.tone", 3, toneListner));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.B2.volume", 1));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.B2.commands", 3));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.C2.tone", 3, toneListner));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.C2.volume", 1));
rowEditor.add(EditableLabel.generateTextLabel(r, "channels.C2.commands", 3));
rowEditor.add(EditableLabel.generateTextLabel(r, "ay2noisePeriod", 4));
rowEditor.add(EditableLabel.generateTextLabel(r, "ay2envelopePeriod", 4));
rowEditor.add(generateEnvelopeEditor(r.ay2envelopeShape, r, "ay2envelopeShape"));
rowEditor.add(EditableLabel.generateTextLabel(r, "globalCommands", 6));
rowEditor.doLayout();
return rowEditor;
}
public static Component generateEnvelopeEditor(Row.EnvelopeShape envelope, Row row, String property) {
if (envelope == null) {
envelope = Row.EnvelopeShape.unspecified;
}
JLabel label = new JLabel(envelope.icon) {
@Override
public void setText(String text) {
Row.EnvelopeShape e;
try {
e = Row.EnvelopeShape.valueOf(text);
} catch (Throwable ex) {
e = Row.EnvelopeShape.unspecified;
}
setIcon(e.getIcon());
}
};
label.setText(envelope.toString());
JComboBox editor = new JComboBox(Row.ENVELOPE_ICONS);
EditableLabel result = new EditableLabel(label, editor, 64, row, property);
return result;
}
}

View File

@ -35,13 +35,16 @@ module lawlesslegends {
requires javafx.mediaEmpty;
requires javafx.media;
requires jdk.jsobject;
requires org.reflections;
// requires org.reflections;
opens jace to javafx.graphics, javafx.fxml, javafx.controls;
opens jace.config to javafx.fxml, javafx.controls;
opens jace.data to javafx.graphics, javafx.fxml, javafx.controls;
opens jace.ide to javafx.graphics, javafx.fxml, javafx.controls;
opens fxml to javafx.graphics, javafx.fxml, javafx.controls;
opens styles to javafx.graphics, javafx.fxml, javafx.controls;
uses javax.sound.sampled.SourceDataLine;
exports jace;
}

View File

@ -5,17 +5,6 @@
{
"name":"[Ljava.lang.String;"
},
{
"name":"[Lsun.java2d.loops.GraphicsPrimitive;"
},
{
"name":"com.apple.eawt._AppEventHandler",
"methods":[{"name":"handleNativeNotification","parameterTypes":["int"] }]
},
{
"name":"com.apple.eawt._AppMenuBarHandler",
"methods":[{"name":"initMenuStates","parameterTypes":["boolean","boolean","boolean","boolean"] }]
},
{
"name":"com.sun.glass.ui.Application",
"methods":[
@ -32,6 +21,25 @@
{"name":"notifyWillUnhide","parameterTypes":[] }
]
},
{
"name":"com.sun.glass.ui.CommonDialogs$ExtensionFilter",
"methods":[
{"name":"extensionsToArray","parameterTypes":[] },
{"name":"getDescription","parameterTypes":[] }
]
},
{
"name":"com.sun.glass.ui.CommonDialogs$FileChooserResult",
"methods":[{"name":"<init>","parameterTypes":["java.util.List","com.sun.glass.ui.CommonDialogs$ExtensionFilter"] }]
},
{
"name":"com.sun.glass.ui.EventLoop",
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"enter","parameterTypes":[] },
{"name":"leave","parameterTypes":["java.lang.Object"] }
]
},
{
"name":"com.sun.glass.ui.Menu",
"methods":[
@ -113,6 +121,50 @@
],
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.javafx.iio.common.ImageLoaderImpl",
"methods":[{"name":"emitWarning","parameterTypes":["java.lang.String"] }]
},
{
"name":"com.sun.javafx.iio.jpeg.JPEGImageLoader",
"methods":[
{"name":"setInputAttributes","parameterTypes":["int","int","int","int","int","byte[]"] },
{"name":"setOutputAttributes","parameterTypes":["int","int"] },
{"name":"updateImageProgress","parameterTypes":["int"] }
]
},
{
"name":"com.sun.media.jfxmedia.locator.Locator",
"methods":[{"name":"getStringLocation","parameterTypes":[] }]
},
{
"name":"com.sun.media.jfxmedia.logging.Logger",
"methods":[
{"name":"logMsg","parameterTypes":["int","java.lang.String"] },
{"name":"logMsg","parameterTypes":["int","java.lang.String","java.lang.String","java.lang.String"] }
]
},
{
"name":"com.sun.media.jfxmediaimpl.NativeMediaPlayer",
"methods":[
{"name":"sendAudioSpectrumEvent","parameterTypes":["double","double","boolean"] },
{"name":"sendAudioTrack","parameterTypes":["boolean","long","java.lang.String","int","java.lang.String","int","int","float"] },
{"name":"sendBufferProgressEvent","parameterTypes":["double","long","long","long"] },
{"name":"sendDurationUpdateEvent","parameterTypes":["double"] },
{"name":"sendFrameSizeChangedEvent","parameterTypes":["int","int"] },
{"name":"sendMarkerEvent","parameterTypes":["java.lang.String","double"] },
{"name":"sendNewFrameEvent","parameterTypes":["long"] },
{"name":"sendPlayerHaltEvent","parameterTypes":["java.lang.String","double"] },
{"name":"sendPlayerMediaErrorEvent","parameterTypes":["int"] },
{"name":"sendPlayerStateEvent","parameterTypes":["int","double"] },
{"name":"sendSubtitleTrack","parameterTypes":["boolean","long","java.lang.String","int","java.lang.String"] },
{"name":"sendVideoTrack","parameterTypes":["boolean","long","java.lang.String","int","int","int","float","boolean"] },
{"name":"sendWarning","parameterTypes":["int","java.lang.String"] }
]
},
{
"name":"com.sun.media.jfxmediaimpl.platform.osx.OSXMediaPlayer"
},
{
"name":"com.sun.media.sound.DirectAudioDevice",
"methods":[{"name":"addFormat","parameterTypes":["java.util.Vector","int","int","int","float","int","boolean","boolean"] }]
@ -126,77 +178,207 @@
"methods":[{"name":"<init>","parameterTypes":["int","java.lang.String","java.lang.String","java.lang.String","java.lang.String"] }]
},
{
"name":"java.awt.AlphaComposite",
"fields":[
{"name":"extraAlpha"},
{"name":"rule"}
"name":"com.sun.webkit.BackForwardList",
"methods":[{"name":"notifyChanged","parameterTypes":[] }]
},
{
"name":"com.sun.webkit.BackForwardList$Entry",
"methods":[
{"name":"<init>","parameterTypes":["long","long"] },
{"name":"notifyItemChanged","parameterTypes":[] },
{"name":"notifyItemDestroyed","parameterTypes":[] }
]
},
{
"name":"java.awt.Color",
"methods":[{"name":"getRGB","parameterTypes":[] }]
},
{
"name":"java.awt.DisplayMode",
"methods":[{"name":"<init>","parameterTypes":["int","int","int","int"] }]
},
{
"name":"java.awt.event.InputEvent",
"methods":[{"name":"getButtonDownMasks","parameterTypes":[] }]
},
{
"name":"java.awt.geom.AffineTransform",
"fields":[
{"name":"m00"},
{"name":"m01"},
{"name":"m02"},
{"name":"m10"},
{"name":"m11"},
{"name":"m12"}
"name":"com.sun.webkit.CursorManager",
"methods":[
{"name":"getCursorManager","parameterTypes":[] },
{"name":"getPredefinedCursorID","parameterTypes":["int"] }
]
},
{
"name":"java.awt.geom.Path2D",
"fields":[
{"name":"numTypes"},
{"name":"pointTypes"},
{"name":"windingRule"}
"name":"com.sun.webkit.FileSystem",
"methods":[
{"name":"fwkFileExists","parameterTypes":["java.lang.String"] },
{"name":"fwkMakeAllDirectories","parameterTypes":["java.lang.String"] },
{"name":"fwkPathByAppendingComponent","parameterTypes":["java.lang.String","java.lang.String"] }
]
},
{
"name":"java.awt.geom.Path2D$Float",
"fields":[{"name":"floatCoords"}]
"name":"com.sun.webkit.MainThread",
"methods":[{"name":"fwkScheduleDispatchFunctions","parameterTypes":[] }]
},
{
"name":"java.awt.geom.Point2D$Double",
"methods":[{"name":"<init>","parameterTypes":["double","double"] }]
"name":"com.sun.webkit.Timer",
"methods":[
{"name":"fwkSetFireTime","parameterTypes":["double"] },
{"name":"fwkStopTimer","parameterTypes":[] }
]
},
{
"name":"java.awt.geom.Rectangle2D$Double",
"methods":[{"name":"<init>","parameterTypes":["double","double","double","double"] }]
"name":"com.sun.webkit.WCWidget",
"methods":[
{"name":"fwkDestroy","parameterTypes":[] },
{"name":"fwkRequestFocus","parameterTypes":[] },
{"name":"fwkSetBounds","parameterTypes":["int","int","int","int"] },
{"name":"fwkSetCursor","parameterTypes":["long"] },
{"name":"fwkSetVisible","parameterTypes":["boolean"] }
]
},
{
"name":"java.awt.image.ColorModel",
"name":"com.sun.webkit.WebPage",
"methods":[
{"name":"fwkAddMessageToConsole","parameterTypes":["java.lang.String","int","java.lang.String"] },
{"name":"fwkAlert","parameterTypes":["java.lang.String"] },
{"name":"fwkCanRunBeforeUnloadConfirmPanel","parameterTypes":[] },
{"name":"fwkChooseFile","parameterTypes":["java.lang.String","boolean","java.lang.String"] },
{"name":"fwkCloseWindow","parameterTypes":[] },
{"name":"fwkConfirm","parameterTypes":["java.lang.String"] },
{"name":"fwkCreateWindow","parameterTypes":["boolean","boolean","boolean","boolean"] },
{"name":"fwkDidClearWindowObject","parameterTypes":["long","long"] },
{"name":"fwkFireLoadEvent","parameterTypes":["long","int","java.lang.String","java.lang.String","double","int"] },
{"name":"fwkFireResourceLoadEvent","parameterTypes":["long","int","int","java.lang.String","double","int"] },
{"name":"fwkFrameCreated","parameterTypes":["long"] },
{"name":"fwkFrameDestroyed","parameterTypes":["long"] },
{"name":"fwkGetPageBounds","parameterTypes":[] },
{"name":"fwkGetWindowBounds","parameterTypes":[] },
{"name":"fwkPermitAcceptResourceAction","parameterTypes":["long","java.lang.String"] },
{"name":"fwkPermitEnableScriptsAction","parameterTypes":["long","java.lang.String"] },
{"name":"fwkPermitNavigateAction","parameterTypes":["long","java.lang.String"] },
{"name":"fwkPermitNewWindowAction","parameterTypes":["long","java.lang.String"] },
{"name":"fwkPermitRedirectAction","parameterTypes":["long","java.lang.String"] },
{"name":"fwkPermitSubmitDataAction","parameterTypes":["long","java.lang.String","java.lang.String","boolean"] },
{"name":"fwkPrompt","parameterTypes":["java.lang.String","java.lang.String"] },
{"name":"fwkRemoveRequestURL","parameterTypes":["long","int"] },
{"name":"fwkRepaint","parameterTypes":["int","int","int","int"] },
{"name":"fwkRunBeforeUnloadConfirmPanel","parameterTypes":["java.lang.String"] },
{"name":"fwkScreenToWindow","parameterTypes":["com.sun.webkit.graphics.WCPoint"] },
{"name":"fwkSetCursor","parameterTypes":["long"] },
{"name":"fwkSetFocus","parameterTypes":["boolean"] },
{"name":"fwkSetRequestURL","parameterTypes":["long","int","java.lang.String"] },
{"name":"fwkSetScrollbarsVisible","parameterTypes":["boolean"] },
{"name":"fwkSetStatusbarText","parameterTypes":["java.lang.String"] },
{"name":"fwkSetTooltip","parameterTypes":["java.lang.String"] },
{"name":"fwkSetWindowBounds","parameterTypes":["int","int","int","int"] },
{"name":"fwkShowWindow","parameterTypes":[] },
{"name":"fwkTransferFocus","parameterTypes":["boolean"] },
{"name":"fwkWindowToScreen","parameterTypes":["com.sun.webkit.graphics.WCPoint"] },
{"name":"getHostWindow","parameterTypes":[] },
{"name":"getPage","parameterTypes":[] },
{"name":"getRenderTheme","parameterTypes":[] },
{"name":"setInputMethodState","parameterTypes":["boolean"] }
]
},
{
"name":"com.sun.webkit.dom.JSObject",
"fields":[{"name":"UNDEFINED"}],
"methods":[{"name":"<init>","parameterTypes":["long","int"] }]
},
{
"name":"com.sun.webkit.graphics.Ref",
"methods":[
{"name":"getID","parameterTypes":[] },
{"name":"ref","parameterTypes":[] }
]
},
{
"name":"com.sun.webkit.graphics.ScrollBarTheme",
"methods":[{"name":"getThickness","parameterTypes":[] }]
},
{
"name":"com.sun.webkit.graphics.WCFont",
"methods":[
{"name":"getAscent","parameterTypes":[] },
{"name":"getCapHeight","parameterTypes":[] },
{"name":"getDescent","parameterTypes":[] },
{"name":"getGlyphBoundingBox","parameterTypes":["int"] },
{"name":"getGlyphCodes","parameterTypes":["char[]"] },
{"name":"getGlyphWidth","parameterTypes":["int"] },
{"name":"getLineGap","parameterTypes":[] },
{"name":"getLineSpacing","parameterTypes":[] },
{"name":"getTextRuns","parameterTypes":["java.lang.String"] },
{"name":"getXHeight","parameterTypes":[] },
{"name":"hasUniformLineMetrics","parameterTypes":[] },
{"name":"hashCode","parameterTypes":[] }
]
},
{
"name":"com.sun.webkit.graphics.WCGraphicsManager",
"methods":[
{"name":"createWCPath","parameterTypes":[] },
{"name":"getGraphicsManager","parameterTypes":[] },
{"name":"getWCFont","parameterTypes":["java.lang.String","boolean","boolean","float"] }
]
},
{
"name":"com.sun.webkit.graphics.WCPoint",
"methods":[
{"name":"<init>","parameterTypes":["float","float"] },
{"name":"getX","parameterTypes":[] },
{"name":"getY","parameterTypes":[] }
]
},
{
"name":"com.sun.webkit.graphics.WCRectangle",
"fields":[
{"name":"colorSpace"},
{"name":"colorSpaceType"},
{"name":"isAlphaPremultiplied"},
{"name":"is_sRGB"},
{"name":"nBits"},
{"name":"numComponents"},
{"name":"pData"},
{"name":"supportsAlpha"},
{"name":"transparency"}
],
"methods":[{"name":"getRGBdefault","parameterTypes":[] }]
{"name":"h"},
{"name":"w"},
{"name":"x"},
{"name":"y"}
]
},
{
"name":"java.awt.image.IndexColorModel",
"fields":[
{"name":"allgrayopaque"},
{"name":"map_size"},
{"name":"rgb"},
{"name":"transparent_index"}
"name":"com.sun.webkit.graphics.WCRenderQueue",
"methods":[
{"name":"fwkAddBuffer","parameterTypes":["java.nio.ByteBuffer"] },
{"name":"fwkDisposeGraphics","parameterTypes":[] },
{"name":"refFloatArr","parameterTypes":["float[]"] },
{"name":"refIntArr","parameterTypes":["int[]"] }
]
},
{
"name":"com.sun.webkit.graphics.WCTextRun",
"methods":[
{"name":"getCharOffset","parameterTypes":["int"] },
{"name":"getEnd","parameterTypes":[] },
{"name":"getGlyph","parameterTypes":["int"] },
{"name":"getGlyphCount","parameterTypes":[] },
{"name":"getGlyphPosAndAdvance","parameterTypes":["int"] },
{"name":"getStart","parameterTypes":[] },
{"name":"isLeftToRight","parameterTypes":[] }
]
},
{
"name":"com.sun.webkit.network.FormDataElement",
"methods":[
{"name":"fwkCreateFromByteArray","parameterTypes":["byte[]"] },
{"name":"fwkCreateFromFile","parameterTypes":["java.lang.String"] }
]
},
{
"name":"com.sun.webkit.network.NetworkContext",
"methods":[
{"name":"canHandleURL","parameterTypes":["java.lang.String"] },
{"name":"fwkGetMaximumHTTPConnectionCountPerHost","parameterTypes":[] },
{"name":"fwkLoad","parameterTypes":["com.sun.webkit.WebPage","boolean","java.lang.String","java.lang.String","java.lang.String","com.sun.webkit.network.FormDataElement[]","long"] }
]
},
{
"name":"com.sun.webkit.network.URLLoaderBase",
"methods":[{"name":"fwkCancel","parameterTypes":[] }]
},
{
"name":"jace.ide.Program"
},
{
"name":"java.io.File",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.io.InputStream",
"methods":[
{"name":"read","parameterTypes":["byte[]","int","int"] },
{"name":"skip","parameterTypes":["long"] }
]
},
{
@ -205,7 +387,17 @@
},
{
"name":"java.lang.Class",
"methods":[{"name":"forName","parameterTypes":["java.lang.String","boolean","java.lang.ClassLoader"] }]
"methods":[
{"name":"forName","parameterTypes":["java.lang.String","boolean","java.lang.ClassLoader"] },
{"name":"isArray","parameterTypes":[] }
]
},
{
"name":"java.lang.ClassLoader",
"methods":[
{"name":"getPlatformClassLoader","parameterTypes":[] },
{"name":"loadClass","parameterTypes":["java.lang.String"] }
]
},
{
"name":"java.lang.Integer",
@ -218,6 +410,13 @@
"name":"java.lang.Long",
"methods":[{"name":"longValue","parameterTypes":[] }]
},
{
"name":"java.lang.Number"
},
{
"name":"java.lang.Object",
"methods":[{"name":"getClass","parameterTypes":[] }]
},
{
"name":"java.lang.Runnable",
"methods":[{"name":"run","parameterTypes":[] }]
@ -233,10 +432,13 @@
"name":"java.lang.System",
"methods":[
{"name":"getProperty","parameterTypes":["java.lang.String"] },
{"name":"load","parameterTypes":["java.lang.String"] },
{"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }
]
},
{
"name":"java.util.ArrayList",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"java.util.List",
"methods":[{"name":"add","parameterTypes":["java.lang.Object"] }]
@ -246,202 +448,11 @@
"methods":[{"name":"get","parameterTypes":["java.lang.Object"] }]
},
{
"name":"sun.awt.AWTAutoShutdown",
"methods":[{"name":"notifyToolkitThreadFree","parameterTypes":[] }]
"name":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"
},
{
"name":"sun.awt.SunHints",
"fields":[{"name":"INTVAL_STROKE_PURE"}]
},
{
"name":"sun.java2d.Disposer",
"methods":[{"name":"addRecord","parameterTypes":["java.lang.Object","long","long"] }]
},
{
"name":"sun.java2d.InvalidPipeException"
},
{
"name":"sun.java2d.NullSurfaceData"
},
{
"name":"sun.java2d.SunGraphics2D",
"fields":[
{"name":"clipRegion"},
{"name":"composite"},
{"name":"eargb"},
{"name":"lcdTextContrast"},
{"name":"pixel"},
{"name":"strokeHint"}
]
},
{
"name":"sun.java2d.SurfaceData",
"fields":[
{"name":"pData"},
{"name":"valid"}
]
},
{
"name":"sun.java2d.loops.Blit",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.BlitBg",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.CompositeType",
"fields":[
{"name":"AnyAlpha"},
{"name":"Src"},
{"name":"SrcNoEa"},
{"name":"SrcOver"},
{"name":"SrcOverNoEa"},
{"name":"Xor"}
]
},
{
"name":"sun.java2d.loops.DrawGlyphList",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.DrawGlyphListAA",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.DrawGlyphListLCD",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.DrawLine",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.DrawParallelogram",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.DrawPath",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.DrawPolygons",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.DrawRect",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.FillParallelogram",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.FillPath",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.FillRect",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.FillSpans",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.GraphicsPrimitive",
"fields":[{"name":"pNativePrim"}]
},
{
"name":"sun.java2d.loops.GraphicsPrimitiveMgr",
"methods":[{"name":"register","parameterTypes":["sun.java2d.loops.GraphicsPrimitive[]"] }]
},
{
"name":"sun.java2d.loops.MaskBlit",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.MaskFill",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.ScaledBlit",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.SurfaceType",
"fields":[
{"name":"Any3Byte"},
{"name":"Any4Byte"},
{"name":"AnyByte"},
{"name":"AnyColor"},
{"name":"AnyInt"},
{"name":"AnyShort"},
{"name":"ByteBinary1Bit"},
{"name":"ByteBinary2Bit"},
{"name":"ByteBinary4Bit"},
{"name":"ByteGray"},
{"name":"ByteIndexed"},
{"name":"ByteIndexedBm"},
{"name":"FourByteAbgr"},
{"name":"FourByteAbgrPre"},
{"name":"Index12Gray"},
{"name":"Index8Gray"},
{"name":"IntArgb"},
{"name":"IntArgbBm"},
{"name":"IntArgbPre"},
{"name":"IntBgr"},
{"name":"IntRgb"},
{"name":"IntRgbx"},
{"name":"OpaqueColor"},
{"name":"ThreeByteBgr"},
{"name":"Ushort4444Argb"},
{"name":"Ushort555Rgb"},
{"name":"Ushort555Rgbx"},
{"name":"Ushort565Rgb"},
{"name":"UshortGray"},
{"name":"UshortIndexed"}
]
},
{
"name":"sun.java2d.loops.TransformHelper",
"methods":[{"name":"<init>","parameterTypes":["long","sun.java2d.loops.SurfaceType","sun.java2d.loops.CompositeType","sun.java2d.loops.SurfaceType"] }]
},
{
"name":"sun.java2d.loops.XORComposite",
"fields":[
{"name":"alphaMask"},
{"name":"xorColor"},
{"name":"xorPixel"}
]
},
{
"name":"sun.java2d.opengl.OGLSurfaceData",
"fields":[
{"name":"isBIOpShaderEnabled"},
{"name":"isFBObjectEnabled"},
{"name":"isGradShaderEnabled"},
{"name":"isLCDShaderEnabled"}
]
},
{
"name":"sun.java2d.pipe.Region",
"fields":[
{"name":"bands"},
{"name":"endIndex"},
{"name":"hix"},
{"name":"hiy"},
{"name":"lox"},
{"name":"loy"}
]
},
{
"name":"sun.java2d.pipe.RegionIterator",
"fields":[
{"name":"curIndex"},
{"name":"numXbands"},
{"name":"region"}
]
"name":"org.graalvm.jniutils.JNIExceptionWrapperEntryPoints",
"methods":[{"name":"getClassName","parameterTypes":["java.lang.Class"] }]
},
{
"name":"sun.launcher.LauncherHelper$FXHelper",

View File

@ -2,9 +2,54 @@
{
"name":"[D"
},
{
"name":"apple.security.AppleProvider",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.AESCipher$General",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.ARCFOURCipher",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.DESCipher",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.DESedeCipher",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.DHParameters",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.TlsMasterSecretGenerator",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.glass.ui.Application"
},
{
"name":"com.sun.glass.ui.CommonDialogs$ExtensionFilter"
},
{
"name":"com.sun.glass.ui.CommonDialogs$FileChooserResult"
},
{
"name":"com.sun.glass.ui.EventLoop"
},
{
"name":"com.sun.glass.ui.Menu"
},
@ -41,6 +86,17 @@
"name":"com.sun.javafx.tk.quantum.QuantumToolkit",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.javafx.webkit.theme.ScrollBarWidget"
},
{
"name":"com.sun.media.jfxmediaimpl.platform.gstreamer.GSTPlatform",
"methods":[{"name":"getPlatformInstance","parameterTypes":[] }]
},
{
"name":"com.sun.media.jfxmediaimpl.platform.osx.OSXPlatform",
"methods":[{"name":"getPlatformInstance","parameterTypes":[] }]
},
{
"name":"com.sun.prism.GraphicsPipeline",
"methods":[
@ -48,6 +104,10 @@
{"name":"getPipeline","parameterTypes":[] }
]
},
{
"name":"com.sun.prism.shader.DrawRoundRect_Color_Loader",
"methods":[{"name":"loadShader","parameterTypes":["com.sun.prism.ps.ShaderFactory","java.io.InputStream"] }]
},
{
"name":"com.sun.prism.shader.FillPgram_Color_Loader",
"methods":[{"name":"loadShader","parameterTypes":["com.sun.prism.ps.ShaderFactory","java.io.InputStream"] }]
@ -101,7 +161,9 @@
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[
{"name":"runFile","parameterTypes":[] },
{"name":"scaleIntegerRatio","parameterTypes":[] },
{"name":"showAboutWindow","parameterTypes":[] },
{"name":"showConfig","parameterTypes":[] },
{"name":"showIDE","parameterTypes":[] },
{"name":"toggleFullscreen","parameterTypes":[] }
@ -142,7 +204,6 @@
{"name":"joy2enabled"},
{"name":"ramCard"},
{"name":"showSpeedMonitors"},
{"name":"useConsoleProbe"},
{"name":"useDebugRom"},
{"name":"videoRenderer"}
]
@ -161,19 +222,14 @@
{
"name":"jace.apple2e.Speaker",
"allPublicFields":true,
"queryAllPublicMethods":true
"queryAllPublicMethods":true,
"methods":[{"name":"toggleFileOutput","parameterTypes":[] }]
},
{
"name":"jace.apple2e.VideoDHGR"
},
{
"name":"jace.apple2e.VideoNTSC",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[
{"name":"<init>","parameterTypes":["jace.core.Computer"] },
{"name":"changeVideoMode","parameterTypes":[] }
]
"name":"jace.apple2e.VideoNTSC"
},
{
"name":"jace.cheat.MetaCheat"
@ -196,7 +252,8 @@
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"applyConfig","parameterTypes":["javafx.scene.input.MouseEvent"] },
{"name":"initialize","parameterTypes":[] }
{"name":"initialize","parameterTypes":[] },
{"name":"saveConfig","parameterTypes":["javafx.scene.input.MouseEvent"] }
]
},
{
@ -224,7 +281,10 @@
"name":"jace.core.Keyboard",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"solidApple","parameterTypes":["boolean"] }]
"methods":[
{"name":"openApple","parameterTypes":["boolean"] },
{"name":"solidApple","parameterTypes":["boolean"] }
]
},
{
"name":"jace.core.Motherboard",
@ -249,70 +309,39 @@
{"name":"speedRatio"}
]
},
{
"name":"jace.core.Video",
"fields":[
{"name":"MIN_SCREEN_REFRESH"},
{"name":"hblankOffsetX"},
{"name":"hblankOffsetY"},
{"name":"waitsPerCycle"}
]
},
{
"name":"jace.core.VideoWriter"
},
{
"name":"jace.hardware.CardAppleMouse",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
"name":"jace.hardware.CardAppleMouse"
},
{
"name":"jace.hardware.CardDiskII",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
},
{
"name":"jace.hardware.CardExt80Col",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
"name":"jace.hardware.CardExt80Col"
},
{
"name":"jace.hardware.CardHayesMicromodem"
},
{
"name":"jace.hardware.CardMockingboard",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
},
{
"name":"jace.hardware.CardMockingboard$1",
"allPublicFields":true,
"queryAllPublicMethods":true
},
{
"name":"jace.hardware.CardRamFactor",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
},
{
"name":"jace.hardware.CardRamworks",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
},
{
"name":"jace.hardware.CardSSC"
},
{
"name":"jace.hardware.CardThunderclock",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
"name":"jace.hardware.CardThunderclock"
},
{
"name":"jace.hardware.Joystick",
@ -325,10 +354,7 @@
"queryAllPublicMethods":true
},
{
"name":"jace.hardware.PassportMidiInterface",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
"name":"jace.hardware.PassportMidiInterface"
},
{
"name":"jace.hardware.ProdosDriver"
@ -343,8 +369,6 @@
},
{
"name":"jace.hardware.massStorage.CardMassStorage",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
},
{
@ -361,7 +385,18 @@
},
{
"name":"jace.ide.IdeController",
"methods":[{"name":"<init>","parameterTypes":[] }]
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"initialize","parameterTypes":[] },
{"name":"newApplesoftBasicClicked","parameterTypes":["javafx.event.ActionEvent"] },
{"name":"newApplesoftBasicFromMemoryClicked","parameterTypes":["javafx.event.ActionEvent"] },
{"name":"newAssemblyListingClicked","parameterTypes":["javafx.event.ActionEvent"] },
{"name":"onCloseClicked","parameterTypes":["javafx.event.ActionEvent"] },
{"name":"testCompileClicked","parameterTypes":["javafx.event.ActionEvent"] },
{"name":"viewCompilerOutputClicked","parameterTypes":["javafx.event.ActionEvent"] }
]
},
{
"name":"jace.ide.LanguageHandler"
@ -381,8 +416,6 @@
},
{
"name":"jace.lawless.LawlessVideo",
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":["jace.core.Computer"] }]
},
{
@ -391,18 +424,6 @@
{
"name":"jace.library.MediaConsumerParent"
},
{
"name":"java.awt.datatransfer.Transferable"
},
{
"name":"java.awt.event.FocusListener"
},
{
"name":"java.awt.event.KeyAdapter"
},
{
"name":"java.awt.event.MouseListener"
},
{
"name":"java.io.FileFilter"
},
@ -428,7 +449,7 @@
},
{
"name":"java.lang.Module",
"methods":[
"queriedMethods":[
{"name":"getDescriptor","parameterTypes":[] },
{"name":"getLayer","parameterTypes":[] },
{"name":"getName","parameterTypes":[] },
@ -461,6 +482,10 @@
{
"name":"java.net.URL"
},
{
"name":"java.net.URLConnection",
"methods":[{"name":"getContentLengthLong","parameterTypes":[] }]
},
{
"name":"java.nio.ByteBuffer",
"methods":[{"name":"order","parameterTypes":["java.nio.ByteOrder"] }]
@ -470,7 +495,13 @@
"methods":[{"name":"nativeOrder","parameterTypes":[] }]
},
{
"name":"java.util.ArrayList"
"name":"java.security.AlgorithmParametersSpi"
},
{
"name":"java.security.KeyStoreSpi"
},
{
"name":"java.security.SecureRandomParameters"
},
{
"name":"java.util.Comparator"
@ -480,17 +511,14 @@
},
{
"name":"java.util.List",
"methods":[{"name":"copyOf","parameterTypes":["java.util.Collection"] }]
"queriedMethods":[{"name":"copyOf","parameterTypes":["java.util.Collection"] }]
},
{
"name":"java.util.Map$Entry"
},
{
"name":"java.util.Optional",
"methods":[{"name":"isEmpty","parameterTypes":[] }]
},
{
"name":"java.util.TimerTask"
"queriedMethods":[{"name":"isEmpty","parameterTypes":[] }]
},
{
"name":"java.util.TreeMap"
@ -504,6 +532,9 @@
{
"name":"java.util.zip.DeflaterInputStream"
},
{
"name":"javafx.animation.KeyValue"
},
{
"name":"javafx.application.Application"
},
@ -575,6 +606,12 @@
"name":"javafx.scene.control.ButtonBase",
"queryAllDeclaredMethods":true
},
{
"name":"javafx.scene.control.CheckMenuItem",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"javafx.scene.control.ComboBox",
"queryAllDeclaredMethods":true,
@ -597,6 +634,10 @@
"name":"javafx.scene.control.Control",
"queryAllDeclaredMethods":true
},
{
"name":"javafx.scene.control.CustomMenuItem",
"queryAllDeclaredMethods":true
},
{
"name":"javafx.scene.control.Label",
"queryAllDeclaredMethods":true,
@ -614,6 +655,49 @@
{"name":"setText","parameterTypes":["java.lang.String"] }
]
},
{
"name":"javafx.scene.control.Menu",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"getItems","parameterTypes":[] }
]
},
{
"name":"javafx.scene.control.MenuBar",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"getMenus","parameterTypes":[] }
]
},
{
"name":"javafx.scene.control.MenuItem",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"getId","parameterTypes":[] },
{"name":"setAccelerator","parameterTypes":["javafx.scene.input.KeyCombination"] },
{"name":"setDisable","parameterTypes":["boolean"] },
{"name":"setId","parameterTypes":["java.lang.String"] },
{"name":"setMnemonicParsing","parameterTypes":["boolean"] },
{"name":"setOnAction","parameterTypes":["javafx.event.EventHandler"] },
{"name":"setText","parameterTypes":["java.lang.String"] }
]
},
{
"name":"javafx.scene.control.RadioMenuItem",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"setSelected","parameterTypes":["boolean"] },
{"name":"setToggleGroup","parameterTypes":["javafx.scene.control.ToggleGroup"] }
]
},
{
"name":"javafx.scene.control.ScrollPane",
"queryAllDeclaredMethods":true,
@ -625,6 +709,12 @@
{"name":"setFitToWidth","parameterTypes":["boolean"] }
]
},
{
"name":"javafx.scene.control.SeparatorMenuItem",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"javafx.scene.control.Slider",
"queryAllDeclaredMethods":true,
@ -651,6 +741,24 @@
{"name":"setDividerPositions","parameterTypes":["double[]"] }
]
},
{
"name":"javafx.scene.control.TabPane",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"setTabClosingPolicy","parameterTypes":["javafx.scene.control.TabPane$TabClosingPolicy"] }
]
},
{
"name":"javafx.scene.control.TabPane$TabClosingPolicy",
"methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
},
{
"name":"javafx.scene.control.ToggleGroup",
"queryAllPublicConstructors":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"javafx.scene.control.ToolBar",
"queryAllDeclaredMethods":true,
@ -686,20 +794,36 @@
{"name":"setImage","parameterTypes":["javafx.scene.image.Image"] }
]
},
{
"name":"javafx.scene.input.KeyCode",
"methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
},
{
"name":"javafx.scene.input.KeyCodeCombination",
"queryAllPublicMethods":true,
"queryAllPublicConstructors":true,
"methods":[{"name":"<init>","parameterTypes":["javafx.scene.input.KeyCode","javafx.scene.input.KeyCombination$ModifierValue","javafx.scene.input.KeyCombination$ModifierValue","javafx.scene.input.KeyCombination$ModifierValue","javafx.scene.input.KeyCombination$ModifierValue","javafx.scene.input.KeyCombination$ModifierValue"] }]
},
{
"name":"javafx.scene.input.KeyCombination$ModifierValue",
"methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
},
{
"name":"javafx.scene.layout.AnchorPane",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"getBottomAnchor","parameterTypes":["javafx.scene.Node"] },
{"name":"getLeftAnchor","parameterTypes":["javafx.scene.Node"] },
{"name":"getRightAnchor","parameterTypes":["javafx.scene.Node"] },
{"name":"getTopAnchor","parameterTypes":["javafx.scene.Node"] },
{"name":"setBottomAnchor","parameterTypes":["javafx.scene.Node","java.lang.Double"] },
{"name":"setLeftAnchor","parameterTypes":["javafx.scene.Node","java.lang.Double"] },
{"name":"setRightAnchor","parameterTypes":["javafx.scene.Node","java.lang.Double"] },
{"name":"setTopAnchor","parameterTypes":["javafx.scene.Node","java.lang.Double"] }
],
"queriedMethods":[
{"name":"getBottomAnchor","parameterTypes":["javafx.scene.Node"] },
{"name":"getLeftAnchor","parameterTypes":["javafx.scene.Node"] },
{"name":"getRightAnchor","parameterTypes":["javafx.scene.Node"] },
{"name":"getTopAnchor","parameterTypes":["javafx.scene.Node"] }
]
},
{
@ -708,12 +832,12 @@
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"getAlignment","parameterTypes":["javafx.scene.Node"] },
{"name":"setAlignment","parameterTypes":["javafx.scene.Node","javafx.geometry.Pos"] },
{"name":"setBottom","parameterTypes":["javafx.scene.Node"] },
{"name":"setCenter","parameterTypes":["javafx.scene.Node"] },
{"name":"setTop","parameterTypes":["javafx.scene.Node"] }
]
],
"queriedMethods":[{"name":"getAlignment","parameterTypes":["javafx.scene.Node"] }]
},
{
"name":"javafx.scene.layout.HBox",
@ -721,12 +845,12 @@
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"getHgrow","parameterTypes":["javafx.scene.Node"] },
{"name":"setAlignment","parameterTypes":["javafx.geometry.Pos"] },
{"name":"setFillHeight","parameterTypes":["boolean"] },
{"name":"setHgrow","parameterTypes":["javafx.scene.Node","javafx.scene.layout.Priority"] },
{"name":"setMargin","parameterTypes":["javafx.scene.Node","javafx.geometry.Insets"] }
]
],
"queriedMethods":[{"name":"getHgrow","parameterTypes":["javafx.scene.Node"] }]
},
{
"name":"javafx.scene.layout.Pane",
@ -758,10 +882,10 @@
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"getAlignment","parameterTypes":["javafx.scene.Node"] },
{"name":"setAlignment","parameterTypes":["javafx.scene.Node","javafx.geometry.Pos"] },
{"name":"setMargin","parameterTypes":["javafx.scene.Node","javafx.geometry.Insets"] }
]
],
"queriedMethods":[{"name":"getAlignment","parameterTypes":["javafx.scene.Node"] }]
},
{
"name":"javafx.scene.layout.TilePane",
@ -769,18 +893,21 @@
"queryAllPublicConstructors":true,
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"getAlignment","parameterTypes":["javafx.scene.Node"] },
{"name":"setAlignment","parameterTypes":["javafx.geometry.Pos"] },
{"name":"setAlignment","parameterTypes":["javafx.scene.Node","javafx.geometry.Pos"] },
{"name":"setHgap","parameterTypes":["double"] },
{"name":"setVgap","parameterTypes":["double"] }
]
],
"queriedMethods":[{"name":"getAlignment","parameterTypes":["javafx.scene.Node"] }]
},
{
"name":"javafx.scene.layout.VBox",
"queryAllDeclaredMethods":true,
"queryAllPublicConstructors":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"setVgrow","parameterTypes":["javafx.scene.Node","javafx.scene.layout.Priority"] }
]
},
{
"name":"javafx.scene.shape.LineTo"
@ -831,27 +958,160 @@
"name":"javafx.util.converter.IntegerStringConverter"
},
{
"name":"javax.swing.JLabel"
},
{
"name":"javax.swing.JPanel"
"name":"javax.security.auth.x500.X500Principal",
"fields":[{"name":"thisX500Name"}],
"queriedMethods":[{"name":"<init>","parameterTypes":["sun.security.x509.X500Name"] }]
},
{
"name":"javax.swing.tree.TreeModel"
},
{
"name":"org.ibex.nestedvm.RuntimeCompiler",
"queriedMethods":[{"name":"compile","parameterTypes":["org.ibex.nestedvm.util.Seekable","java.lang.String","java.lang.String"] }]
},
{
"name":"org.ibex.nestedvm.UnixRuntime"
},
{
"name":"sun.java2d.marlin.DMarlinRenderingEngine",
"name":"org.ibex.nestedvm.util.Platform"
},
{
"name":"org.ibex.nestedvm.util.Platform$Jdk14",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"org.ibex.nestedvm.util.Seekable"
},
{
"name":"sun.misc.Unsafe",
"fields":[{"name":"theUnsafe"}]
},
{
"name":"sun.security.pkcs12.PKCS12KeyStore",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.DSA$SHA224withDSA",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.DSA$SHA256withDSA",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.JavaKeyStore$JKS",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.MD5",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.NativePRNG",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.SHA",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.SHA2$SHA224",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.SHA2$SHA256",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.SHA5$SHA384",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.SHA5$SHA512",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.X509Factory",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.rsa.PSSParameters",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.rsa.RSAKeyFactory$Legacy",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.rsa.RSAPSSSignature",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.rsa.RSASignature$SHA224withRSA",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.ssl.KeyManagerFactoryImpl$SunX509",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.ssl.SSLContextImpl$DefaultSSLContext",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.x509.AuthorityInfoAccessExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.AuthorityKeyIdentifierExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.BasicConstraintsExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.CRLDistributionPointsExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.CertificatePoliciesExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.ExtendedKeyUsageExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.IssuerAlternativeNameExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.KeyUsageExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.NetscapeCertTypeExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.PrivateKeyUsageExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.SubjectAlternativeNameExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
}
]

View File

@ -1,24 +1,36 @@
{
"resources":{
"includes":[{
"includes":[
{
"pattern":"\\Qjace\\E"
}]},
},
{
"pattern":"^codemirror.*$"
},
{
"pattern":"^jace.*$"
},
{
"pattern":"^jace.data..*$"
},
{
"pattern":"^jace.data.sound..*$"
}
]},
"bundles":[
{
"name":"com.sun.javafx.tk.quantum.QuantumMessagesBundle",
"locales":[""]
"locales":[
"",
"und"
]
},
{
"name":"com/sun/javafx/scene/control/skin/resources/controls",
"locales":[""]
},
{
"name":"sun.awt.resources.awt",
"classNames":["sun.awt.resources.awt"]
},
{
"name":"sun.awt.resources.awtosx",
"classNames":["sun.awt.resources.awtosx"]
"locales":[
"",
"und"
]
}
]
}

View File

@ -1,8 +1,27 @@
{
"types":[
{
"name":"jace.config.Configuration$ConfigNode"
},
{
"name":"java.lang.Boolean"
},
{
"name":"java.lang.Integer"
},
{
"name":"java.lang.Number"
},
{
"name":"java.lang.Object[]"
},
{
"name":"java.lang.String"
},
{
"name":"java.util.TreeMap"
}
],
"lambdaCapturingTypes":[
],
"proxies":[
]
}

View File

@ -11,7 +11,7 @@
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" styleClass="mainFxmlClass" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="jace.ide.IdeController">
<stylesheets>
<URL value="@/styles/editor.css" />
<URL value="@../styles/editor.css" />
</stylesheets>
<children>
<VBox layoutX="116.0" layoutY="63.0" prefHeight="200.0" prefWidth="100.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">

View File

@ -15,10 +15,10 @@
*/
package jace;
import jace.apple2e.MOS65C02;
import jace.assembly.AssemblyHandler;
import jace.core.CPU;
import jace.core.Computer;
import jace.core.Device;
import jace.core.Utility;
import jace.ide.HeadlessProgram;
import jace.ide.Program;
@ -31,6 +31,11 @@ public class TestUtils {
// Utility class has no constructor
}
public static void initComputer() {
Utility.setHeadlessMode(true);
Emulator.withComputer(Computer::reconfigure);
}
public static void assemble(String code, int addr) {
runAssemblyCode(code, addr, 0);
}
@ -40,40 +45,43 @@ public class TestUtils {
}
public static void runAssemblyCode(String code, int addr, int ticks) {
CPU cpu = Emulator.getComputer().getCpu();
cpu.trace = true;
HeadlessProgram program = new HeadlessProgram(Program.DocumentType.assembly);
program.setValue("*=$"+Integer.toHexString(addr)+"\n "+code+"\n NOP\n RTS");
program.execute();
if (ticks > 0) {
cpu.resume();
for (int i=0; i < ticks; i++) {
cpu.doTick();
Emulator.withComputer(computer -> {
CPU cpu = computer.getCpu();
cpu.trace = true;
HeadlessProgram program = new HeadlessProgram(Program.DocumentType.assembly);
program.setValue("*=$"+Integer.toHexString(addr)+"\n "+code+"\n NOP\n RTS");
program.execute();
if (ticks > 0) {
cpu.resume();
for (int i=0; i < ticks; i++) {
cpu.doTick();
}
cpu.suspend();
}
cpu.suspend();
}
});
}
public static Device createSimpleDevice(Runnable r, String name) {
return new Device(Emulator.getComputer()) {
@Override
public void tick() {
r.run();
}
@Override
public String getShortName() {
return name;
}
@Override
public void reconfigure() {
}
@Override
protected String getDeviceName() {
return name;
}
};
return Emulator.withComputer(computer ->
new Device(computer) {
@Override
public void tick() {
r.run();
}
@Override
public String getShortName() {
return name;
}
@Override
public void reconfigure() {
}
@Override
protected String getDeviceName() {
return name;
}
}, null);
}
}

View File

@ -14,15 +14,19 @@
* limitations under the License.
*/
package jace.core;
import jace.Emulator;
import jace.apple2e.MOS65C02;
import jace.apple2e.RAM128k;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import static jace.TestUtils.*;
import jace.Emulator;
import static jace.TestUtils.initComputer;
import static jace.TestUtils.runAssemblyCode;
import jace.apple2e.MOS65C02;
import jace.apple2e.RAM128k;
/**
* Test that memory listeners fire appropriately.
@ -35,9 +39,9 @@ public class MemoryListenerTest {
@BeforeClass
public static void setupClass() {
Utility.setHeadlessMode(true);
initComputer();
SoundMixer.MUTE = true;
computer = Emulator.getComputer();
computer = Emulator.withComputer(c->c, null);
cpu = (MOS65C02) computer.getCpu();
ram = (RAM128k) computer.getMemory();
}

View File

@ -15,21 +15,21 @@
*/
package jace.cpu;
import jace.Emulator;
import jace.apple2e.MOS65C02;
import jace.apple2e.RAM128k;
import jace.core.Computer;
import jace.core.SoundMixer;
import jace.core.Utility;
import org.junit.AfterClass;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static jace.TestUtils.*;
import jace.Emulator;
import jace.TestUtils;
import static jace.TestUtils.runAssemblyCode;
import jace.apple2e.MOS65C02;
import jace.apple2e.RAM128k;
import jace.core.Computer;
import jace.core.SoundMixer;
/**
* Basic test functionality to assert correct 6502 decode and execution.
@ -44,9 +44,9 @@ public class Basic6502FuncationalityTest {
@BeforeClass
public static void setupClass() {
Utility.setHeadlessMode(true);
TestUtils.initComputer();
SoundMixer.MUTE = true;
computer = Emulator.getComputer();
computer = Emulator.withComputer(c->c, null);
cpu = (MOS65C02) computer.getCpu();
ram = (RAM128k) computer.getMemory();
}

View File

@ -15,18 +15,22 @@
*/
package jace.cpu;
import jace.Emulator;
import jace.core.Computer;
import jace.core.Utility;
import jace.core.SoundMixer;
import jace.apple2e.MOS65C02;
import jace.apple2e.RAM128k;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertEquals;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import static jace.TestUtils.*;
import jace.Emulator;
import static jace.TestUtils.assemble;
import static jace.TestUtils.createSimpleDevice;
import static jace.TestUtils.initComputer;
import static jace.TestUtils.runAssemblyCode;
import jace.apple2e.MOS65C02;
import jace.apple2e.RAM128k;
import jace.core.Computer;
import jace.core.RAMListener;
import jace.core.SoundMixer;
/**
@ -42,9 +46,9 @@ public class CycleCountTest {
@BeforeClass
public static void setupClass() {
Utility.setHeadlessMode(true);
initComputer();
SoundMixer.MUTE = true;
computer = Emulator.getComputer();
computer = Emulator.withComputer(c->c, null);
cpu = (MOS65C02) computer.getCpu();
ram = (RAM128k) computer.getMemory();
@ -86,8 +90,7 @@ WAIT3 sbc #$01
AtomicInteger breakpointEncountered = new AtomicInteger();
AtomicInteger cycleCount = new AtomicInteger();
// This listener will increment our breakpoint counter if it reaches our desired stoppoing point in time
ram.addExecutionTrap(0x01000, e -> breakpointEncountered.incrementAndGet());
RAMListener l = ram.addExecutionTrap(0x01000, e -> breakpointEncountered.incrementAndGet());
// This faux device counts the number of cycles executed
cpu.addChildDevice(createSimpleDevice(()->{
if (breakpointEncountered.get() == 0) {
@ -101,6 +104,7 @@ WAIT3 sbc #$01
runAssemblyCode(BELL, 552);
assertEquals("Should have encountered the breakpoint", 1, breakpointEncountered.get());
assertEquals("Should have taken about 551 cycles to complete", 551, cycleCount.get());
ram.removeListener(l);
cpu.suspend();
}
@ -112,7 +116,7 @@ WAIT3 sbc #$01
AtomicInteger breakpointEncountered = new AtomicInteger();
AtomicInteger cycleCount = new AtomicInteger();
// This listener will increment our breakpoint counter if it reaches our desired stoppoing point in time
ram.addExecutionTrap(0x01000, e -> breakpointEncountered.incrementAndGet());
RAMListener l = ram.addExecutionTrap(0x01000, e -> breakpointEncountered.incrementAndGet());
// This faux device counts the number of cycles executed
cpu.addChildDevice(createSimpleDevice(()->{
@ -124,24 +128,25 @@ WAIT3 sbc #$01
// This assembles the code and sets PC but doesn't actually do anything
assemble(BELL, 0x0300);
Emulator.getComputer().getMotherboard().resumeInThread();
for (int i=0; i < 552; i++) {
Emulator.getComputer().getMotherboard().doTick();
computer.getMotherboard().resumeInThread();
for (int i=0; i < 553; i++) {
computer.getMotherboard().doTick();
}
Emulator.getComputer().getMotherboard().suspend();
computer.getMotherboard().suspend();
assertEquals("Should have encountered the breakpoint", 1, breakpointEncountered.get());
assertEquals("Should have taken about 551 cycles to complete", 551, cycleCount.get());
ram.removeListener(l);
}
// The CPU cycle count should work the same even when the emulator is sped up.
@Test
public void testAcceleratedCycleCount() {
Emulator.getComputer().getMotherboard().setMaxSpeed(true);
Emulator.getComputer().getMotherboard().setSpeedInPercentage(20000);
computer.getMotherboard().setMaxSpeed(true);
computer.getMotherboard().setSpeedInPercentage(20000);
testMachineBeeperCycleCount();
Emulator.getComputer().getMotherboard().setMaxSpeed(false);
Emulator.getComputer().getMotherboard().setSpeedInPercentage(100);
computer.getMotherboard().setMaxSpeed(false);
computer.getMotherboard().setSpeedInPercentage(100);
}

View File

@ -5,19 +5,26 @@
*/
package jace.ide;
import jace.applesoft.ApplesoftProgram;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import static jace.TestUtils.initComputer;
import jace.applesoft.ApplesoftProgram;
/**
*
@ -32,6 +39,7 @@ public class ApplesoftTest {
@BeforeClass
public static void setUpClass() throws URISyntaxException, IOException {
initComputer();
byte[] lemonadeStand = readBinary("/jace/lemonade_stand.bin");
lemonadeStandBinary = ApplesoftProgram.toObjects(lemonadeStand);
}