Added better standalone testing for command line arguments. Got video mode to be a first-class startup parameter

This commit is contained in:
Brendan Robert 2019-06-19 00:47:04 -05:00
parent 553d439ff8
commit cc0cead894
7 changed files with 150 additions and 41 deletions

View File

@ -18,8 +18,8 @@
*/
package jace;
import jace.config.Configuration;
import jace.apple2e.Apple2e;
import jace.config.Configuration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -51,6 +51,10 @@ public class Emulator {
Configuration.buildTree();
Configuration.loadSettings();
mainThread = Thread.currentThread();
applyConfiguration(args);
}
public void applyConfiguration(List<String> args) {
Map<String, String> settings = new LinkedHashMap<>();
if (args != null) {
for (int i = 0; i < args.size(); i++) {

View File

@ -30,7 +30,6 @@ import jace.core.Computer;
import jace.core.Debugger;
import jace.core.RAM;
import jace.core.RAMListener;
import static jace.core.Utility.*;
import jace.ide.IdeController;
import java.io.File;
import java.io.FileInputStream;
@ -59,6 +58,8 @@ import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import static jace.core.Utility.*;
/**
* This class contains miscellaneous user-invoked actions such as debugger
* operations and running arbitrary files in the emulator. It is possible for
@ -560,6 +561,8 @@ public class EmulatorUILogic implements Reconfigurable {
@Override
public void reconfigure() {
if (JaceApplication.getApplication() != null) {
JaceApplication.getApplication().controller.setSpeed(speedSetting);
}
}
}

View File

@ -20,7 +20,6 @@ package jace.apple2e;
import jace.Emulator;
import jace.EmulatorUILogic;
import static jace.apple2e.VideoDHGR.BLACK;
import jace.config.ConfigurableField;
import jace.config.InvokableAction;
import jace.core.Computer;
@ -34,6 +33,8 @@ import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import static jace.apple2e.VideoDHGR.BLACK;
/**
* Provides a clean color monitor simulation, complete with text-friendly
* palette and mixed color/bw (mode 7) rendering. This class extends the
@ -59,6 +60,9 @@ public class VideoNTSC extends VideoDHGR {
int[] scanline = new int[20];
static public int[] divBy28 = new int[560];
@ConfigurableField(name = "Video Mode", category = "video", shortName = "mode", defaultValue = "TextFriendly", description = "Set Video Mode (Color|TextFriendly|Mode7|Mode7TextFriendly|Monochrome|Greenscreen|Amber)")
public static VideoMode videoMode = VideoMode.TextFriendly;
static {
for (int i = 0; i < 560; i++) {
divBy28[i] = i / 28;
@ -81,58 +85,68 @@ public class VideoNTSC extends VideoDHGR {
Greenscreen("Green"),
Amber("Amber");
String name;
VideoMode(String n) {
name = n;
}
}
static int currentMode = -1;
@InvokableAction(name = "Toggle video mode",
category = "video",
alternatives = "Gfx mode;color;b&w;monochrome",
defaultKeyMapping = {"ctrl+shift+g"})
public static void changeVideoMode() {
VideoNTSC thiss = (VideoNTSC) Emulator.computer.video;
int currentMode = Arrays.asList(VideoMode.values()).indexOf(thiss.getVideoMode());
currentMode++;
if (currentMode >= VideoMode.values().length) {
currentMode = 0;
}
thiss.monochomeMode = false;
thiss.setVideoMode(VideoMode.values()[currentMode]);
}
public void setVideoMode(VideoMode mode) {
videoMode = mode;
monochomeMode = false;
WHITE = Color.WHITE;
switch (VideoMode.values()[currentMode]) {
switch (mode) {
case Amber:
thiss.monochomeMode = true;
monochomeMode = true;
WHITE = Color.web("ff8000");
break;
case Greenscreen:
thiss.monochomeMode = true;
monochomeMode = true;
WHITE = Color.web("0ccc68");
break;
case Monochrome:
thiss.monochomeMode = true;
monochomeMode = true;
break;
case Color:
thiss.useTextPalette = false;
thiss.enableVideo7 = false;
useTextPalette = false;
enableVideo7 = false;
break;
case Mode7:
thiss.useTextPalette = false;
thiss.enableVideo7 = true;
useTextPalette = false;
enableVideo7 = true;
break;
case Mode7TextFriendly:
thiss.useTextPalette = true;
thiss.enableVideo7 = true;
useTextPalette = true;
enableVideo7 = true;
break;
case TextFriendly:
thiss.useTextPalette = true;
thiss.enableVideo7 = false;
useTextPalette = true;
enableVideo7 = false;
break;
}
thiss.activePalette = thiss.useTextPalette ? TEXT_PALETTE : SOLID_PALETTE;
EmulatorUILogic.notify("Video mode: "+VideoMode.values()[currentMode].name);
activePalette = useTextPalette ? TEXT_PALETTE : SOLID_PALETTE;
EmulatorUILogic.notify("Video mode: " + mode.name);
forceRefresh();
}
public VideoMode getVideoMode() {
return videoMode;
}
@Override
protected void showBW(WritableImage screen, int x, int y, int dhgrWord) {
int pos = divBy28[x];
@ -235,6 +249,7 @@ public class VideoNTSC extends VideoDHGR {
}
boolean monochomeMode = false;
private void renderScanline(WritableImage screen, int y) {
int p = 0;
if (rowStart != 0) {
@ -364,6 +379,7 @@ public class VideoNTSC extends VideoDHGR {
@Override
public void reconfigure() {
setVideoMode(videoMode);
activePalette = useTextPalette ? TEXT_PALETTE : SOLID_PALETTE;
super.reconfigure();
}

View File

@ -48,6 +48,9 @@ public class MemorySoftSwitch extends SoftSwitch {
// Todo: Implement floating bus, maybe?
@Override
protected byte readSwitch() {
if (computer.getVideo() == null) {
return 0x00;
} else {
byte value = computer.getVideo().getFloatingBus();
if (getState()) {
return (byte) (value | 0x080);
@ -56,3 +59,4 @@ public class MemorySoftSwitch extends SoftSwitch {
}
}
}
}

View File

@ -52,7 +52,6 @@ import java.util.logging.Logger;
import java.util.stream.Stream;
import javafx.collections.ObservableList;
import javafx.scene.control.TreeItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
/**
@ -190,16 +189,17 @@ public class Configuration implements Reconfigurable {
}
public void setFieldValue(String field, Serializable value) {
setChanged(true);
if (value != null) {
if (value.equals(getFieldValue(field))) {
return;
}
} else {
if (getFieldValue(field) == null) {
setChanged(false);
return;
}
}
setChanged(true);
setRawFieldValue(field, value);
}

View File

@ -18,6 +18,7 @@
*/
package jace.core;
import jace.Emulator;
import jace.config.Configuration;
import jace.config.InvokableAction;
import java.io.File;
@ -25,7 +26,6 @@ import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.reflections.Reflections;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -38,7 +38,6 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.control.Alert;
@ -49,6 +48,7 @@ import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import org.reflections.Reflections;
/**
* This is a set of helper functions which do not belong anywhere else.
@ -156,6 +156,9 @@ public class Utility {
public static void setHeadlessMode(boolean headless) {
isHeadless = headless;
if (Emulator.instance == null && headless) {
Emulator.instance = new Emulator(Collections.emptyList());
}
}
public static boolean isHeadlessMode() {

View File

@ -0,0 +1,79 @@
/*
* Copyright 2019 Brendan Robert
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jace.scripting;
import jace.Emulator;
import jace.apple2e.Apple2e;
import jace.apple2e.MOS65C02;
import jace.apple2e.VideoNTSC;
import jace.apple2e.VideoNTSC.VideoMode;
import jace.core.Computer;
import jace.core.RAM;
import jace.core.SoundMixer;
import jace.core.Utility;
import java.util.Arrays;
import javafx.embed.swing.JFXPanel;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Check out various command line arguments to see if they do the right thing
*/
public class TestCommandlineArgs {
static Computer computer;
static MOS65C02 cpu;
static RAM ram;
@BeforeClass
public static void initJavaFX() {
new JFXPanel();
}
@Before
public void setup() {
Utility.setHeadlessMode(true);
SoundMixer.MUTE = true;
computer = new Apple2e();
cpu = (MOS65C02) computer.getCpu();
ram = computer.getMemory();
Emulator.computer = (Apple2e) computer;
computer.pause();
cpu.suspend();
cpu.clearState();
}
static String GRAPHICS_MODE = "vid.videomode";
@Test
public void testVideoModes() {
for (VideoMode mode : VideoMode.values()) {
Emulator.instance.applyConfiguration(Arrays.asList("-" + GRAPHICS_MODE, mode.name().toLowerCase()));
assertTrue("Should be NTSC video module", computer.video instanceof VideoNTSC);
VideoNTSC video = (VideoNTSC) computer.video;
assertEquals("Should have switched to " + mode.name() + " mode", mode, video.getVideoMode());
Emulator.instance.applyConfiguration(Arrays.asList("-" + GRAPHICS_MODE, mode.name().toUpperCase()));
assertTrue("Should be NTSC video module", computer.video instanceof VideoNTSC);
video = (VideoNTSC) computer.video;
assertEquals("Should have switched to " + mode.name() + " mode", mode, video.getVideoMode());
}
}
}