mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-06-09 08:29:31 +00:00
Simplified the text enhancement hacks and bumped speed back to 200%
This commit is contained in:
parent
d81d0fedd7
commit
2ed008c9c3
|
@ -5,6 +5,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import jace.apple2e.MOS65C02;
|
||||||
import jace.apple2e.RAM128k;
|
import jace.apple2e.RAM128k;
|
||||||
import jace.apple2e.VideoNTSC;
|
import jace.apple2e.VideoNTSC;
|
||||||
import jace.cheat.Cheats.Cheat;
|
import jace.cheat.Cheats.Cheat;
|
||||||
|
@ -144,7 +145,7 @@ public class LawlessLegends extends Application {
|
||||||
c.coldStart();
|
c.coldStart();
|
||||||
try {
|
try {
|
||||||
Thread.sleep(watchdogDelay);
|
Thread.sleep(watchdogDelay);
|
||||||
if (!romStarted.get() || !c.isRunning() || c.getCpu().getProgramCounter() == 0xc700 || c.getCpu().getProgramCounter() == 0) {
|
if (!romStarted.get() || !c.isRunning() || c.getCpu().getProgramCounter() == MOS65C02.FASTBOOT || c.getCpu().getProgramCounter() == 0) {
|
||||||
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Boot not detected, performing a cold start");
|
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Boot not detected, performing a cold start");
|
||||||
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Old PC: {0}", c.getCpu().getProgramCounter());
|
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Old PC: {0}", c.getCpu().getProgramCounter());
|
||||||
resetEmulator();
|
resetEmulator();
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class Apple2e extends Computer {
|
||||||
static int IRQ_VECTOR = 0x003F2;
|
static int IRQ_VECTOR = 0x003F2;
|
||||||
|
|
||||||
@ConfigurableField(name = "Production mode", shortName = "production")
|
@ConfigurableField(name = "Production mode", shortName = "production")
|
||||||
public boolean PRODUCTION_MODE = false;
|
public boolean PRODUCTION_MODE = true;
|
||||||
@ConfigurableField(name = "Slot 1", shortName = "s1card")
|
@ConfigurableField(name = "Slot 1", shortName = "s1card")
|
||||||
public DeviceSelection<Cards> card1 = new DeviceSelection<>(Cards.class, null);
|
public DeviceSelection<Cards> card1 = new DeviceSelection<>(Cards.class, null);
|
||||||
@ConfigurableField(name = "Slot 2", shortName = "s2card")
|
@ConfigurableField(name = "Slot 2", shortName = "s2card")
|
||||||
|
@ -116,6 +116,9 @@ public class Apple2e extends Computer {
|
||||||
try {
|
try {
|
||||||
setCpu(new MOS65C02());
|
setCpu(new MOS65C02());
|
||||||
setMotherboard(new Motherboard(null));
|
setMotherboard(new Motherboard(null));
|
||||||
|
if (PRODUCTION_MODE) {
|
||||||
|
getMotherboard().setSpeedInPercentage(200);
|
||||||
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
System.err.println("Unable to initialize virtual machine");
|
System.err.println("Unable to initialize virtual machine");
|
||||||
t.printStackTrace(System.err);
|
t.printStackTrace(System.err);
|
||||||
|
@ -135,6 +138,11 @@ public class Apple2e extends Computer {
|
||||||
r.resetState();
|
r.resetState();
|
||||||
for (SoftSwitches s : SoftSwitches.values()) {
|
for (SoftSwitches s : SoftSwitches.values()) {
|
||||||
if ((s.getSwitch() instanceof VideoSoftSwitch)) {
|
if ((s.getSwitch() instanceof VideoSoftSwitch)) {
|
||||||
|
if (s == SoftSwitches.TEXT && PRODUCTION_MODE) {
|
||||||
|
s.getSwitch().setState(true);
|
||||||
|
} else {
|
||||||
|
s.getSwitch().reset();
|
||||||
|
}
|
||||||
s.getSwitch().reset();
|
s.getSwitch().reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,9 @@ public class MOS65C02 extends CPU {
|
||||||
private static final Logger LOG = Logger.getLogger(MOS65C02.class.getName());
|
private static final Logger LOG = Logger.getLogger(MOS65C02.class.getName());
|
||||||
|
|
||||||
public boolean readAddressTriggersEvent = true;
|
public boolean readAddressTriggersEvent = true;
|
||||||
static int RESET_VECTOR = 0x00FFFC;
|
public static int RESET_VECTOR = 0x00FFFC;
|
||||||
static int INT_VECTOR = 0x00FFFE;
|
public static int INT_VECTOR = 0x00FFFE;
|
||||||
static int FASTBOOT = 0x00FAA9;
|
public static int FASTBOOT = 0x00FAA9;
|
||||||
@Stateful
|
@Stateful
|
||||||
public int A = 0x0FF;
|
public int A = 0x0FF;
|
||||||
@Stateful
|
@Stateful
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package jace.core;
|
package jace.core;
|
||||||
|
|
||||||
|
import jace.apple2e.SoftSwitches;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A RAM event is defined as anything that causes a read or write to the
|
* A RAM event is defined as anything that causes a read or write to the
|
||||||
* mainboard RAM of the computer. This could be the result of an indirect
|
* mainboard RAM of the computer. This could be the result of an indirect
|
||||||
|
@ -147,4 +149,21 @@ public class RAMEvent {
|
||||||
public final boolean isIntercepted() {
|
public final boolean isIntercepted() {
|
||||||
return valueIntercepted;
|
return valueIntercepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMainMemory() {
|
||||||
|
if (type.isRead() && SoftSwitches.RAMRD.isOn()) {
|
||||||
|
return false;
|
||||||
|
} else if (!type.isRead() && SoftSwitches.RAMWRT.isOn()) {
|
||||||
|
return false;
|
||||||
|
} else if (address < 0x0200) {
|
||||||
|
// Check if zero page is pointed to auxiliary memory
|
||||||
|
return SoftSwitches.AUXZP.isOff();
|
||||||
|
}
|
||||||
|
if ((address >= 0x400 && address < 0x0800) || (address >= 0x2000 && address < 0x4000)) {
|
||||||
|
if (SoftSwitches._80STORE.isOn() && SoftSwitches.PAGE2.isOn()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import jace.Emulator;
|
import jace.Emulator;
|
||||||
|
import jace.apple2e.VideoDHGR;
|
||||||
import jace.cheat.Cheats;
|
import jace.cheat.Cheats;
|
||||||
import jace.core.RAMEvent;
|
import jace.core.RAMEvent;
|
||||||
import jace.lawless.LawlessVideo.RenderEngine;
|
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,12 +45,8 @@ public class LawlessHacks extends Cheats {
|
||||||
@Override
|
@Override
|
||||||
public void registerListeners() {
|
public void registerListeners() {
|
||||||
// Observe graphics changes
|
// Observe graphics changes
|
||||||
addCheat("Lawless Legends Graphics Modes", RAMEvent.TYPE.ANY, (e) -> {
|
addCheat("Lawless Text Speedup", RAMEvent.TYPE.EXECUTE, this::fastText, 0x0ee00, 0x0ee00 + 0x0f00);
|
||||||
int addr = e.getAddress();
|
addCheat("Lawless Text Enhancement", RAMEvent.TYPE.WRITE, this::enhanceText, 0x02000, 0x03fff);
|
||||||
if (addr >= MODE_SOFTSWITCH_MIN && e.getAddress() <= MODE_SOFTSWITCH_MAX) {
|
|
||||||
setEngineByOrdinal(e.getAddress() - MODE_SOFTSWITCH_MIN);
|
|
||||||
}
|
|
||||||
}, MODE_SOFTSWITCH_MIN, MODE_SOFTSWITCH_MAX);
|
|
||||||
addCheat("Lawless Legends Music Commands", RAMEvent.TYPE.WRITE, (e) -> {
|
addCheat("Lawless Legends Music Commands", RAMEvent.TYPE.WRITE, (e) -> {
|
||||||
playSound(e.getNewValue());
|
playSound(e.getNewValue());
|
||||||
}, SFX_TRIGGER);
|
}, SFX_TRIGGER);
|
||||||
|
@ -65,14 +61,33 @@ public class LawlessHacks extends Cheats {
|
||||||
public void tick() {
|
public void tick() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEngineByOrdinal(int mode) {
|
// Speed up text rendering
|
||||||
|
private void fastText(RAMEvent e) {
|
||||||
|
if (e.isMainMemory() && e.getOldValue() != 0x060) {
|
||||||
|
Emulator.withComputer((c->c.getMotherboard().requestSpeed(this)));
|
||||||
|
} else {
|
||||||
|
Emulator.withComputer((c->c.getMotherboard().cancelSpeedRequest(this)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enhance text rendering by forcing the text to be pure B&W
|
||||||
|
private void enhanceText(RAMEvent e) {
|
||||||
|
if (!e.isMainMemory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int pc = Emulator.withComputer(c->c.getCpu().getProgramCounter(), 0);
|
||||||
|
boolean drawingText = pc == 0x0ee46 || pc > 0x0f300;
|
||||||
Emulator.withVideo(v -> {
|
Emulator.withVideo(v -> {
|
||||||
if (v instanceof LawlessVideo) {
|
if (v instanceof LawlessVideo) {
|
||||||
LawlessVideo video = (LawlessVideo) v;
|
LawlessVideo video = (LawlessVideo) v;
|
||||||
if (mode >= 0 && mode < RenderEngine.values().length) {
|
int addr = e.getAddress();
|
||||||
video.setEngine(RenderEngine.values()[mode]);
|
int y = VideoDHGR.identifyHiresRow(addr);
|
||||||
} else {
|
if (y >= 0 && y <= 192) {
|
||||||
video.setEngine(RenderEngine.UNKNOWN);
|
int x = addr - video.getCurrentWriter().getYOffset(y);
|
||||||
|
if (x >= 0 && x < 40) {
|
||||||
|
video.activeMask[y][x*2] = !drawingText;
|
||||||
|
video.activeMask[y][x*2+1] = !drawingText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,94 +2,23 @@ package jace.lawless;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import jace.Emulator;
|
|
||||||
import jace.apple2e.RAM128k;
|
import jace.apple2e.RAM128k;
|
||||||
import jace.apple2e.VideoNTSC;
|
import jace.apple2e.VideoNTSC;
|
||||||
import jace.core.PagedMemory;
|
import jace.core.PagedMemory;
|
||||||
import jace.core.Video;
|
|
||||||
import javafx.scene.image.WritableImage;
|
import javafx.scene.image.WritableImage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lawless-enhanced video output for readable text
|
* Lawless-enhanced video output for readable text
|
||||||
*/
|
*/
|
||||||
public class LawlessVideo extends VideoNTSC {
|
public class LawlessVideo extends VideoNTSC {
|
||||||
|
public final boolean[][] activeMask = new boolean[192][80];
|
||||||
|
|
||||||
private static RenderEngine activeEngine = RenderEngine.UNKNOWN;
|
|
||||||
private boolean titleScreen = true;
|
|
||||||
private final boolean[][] activeMask = new boolean[192][80];
|
|
||||||
|
|
||||||
|
|
||||||
public enum RenderEngine {
|
|
||||||
FULL_COLOR,
|
|
||||||
FULL_TEXT(new int[]{
|
|
||||||
2, 6, 78, 186
|
|
||||||
}),
|
|
||||||
_2D(new int[]{
|
|
||||||
9, 8, 34, 17,
|
|
||||||
44, 24, 76, 136,
|
|
||||||
44, 143, 76, 184
|
|
||||||
}),
|
|
||||||
_3D(new int[]{
|
|
||||||
9, 8, 34, 17,
|
|
||||||
44, 24, 76, 136,
|
|
||||||
44, 143, 76, 183,
|
|
||||||
8, 172, 14, 182,}),
|
|
||||||
MAP(new int[]{
|
|
||||||
2, 6, 78, 11,
|
|
||||||
2, 11, 4, 186,
|
|
||||||
76, 11, 78, 186,
|
|
||||||
2, 182, 78, 186,
|
|
||||||
28, 3, 52, 6
|
|
||||||
}),
|
|
||||||
STORYBOOK(new int[]{
|
|
||||||
0, 0, 39, 191,
|
|
||||||
39, 130, 78, 191
|
|
||||||
}),
|
|
||||||
TITLE(new int[]{
|
|
||||||
16, 154, 64, 190
|
|
||||||
}),
|
|
||||||
UNKNOWN;
|
|
||||||
boolean[][] colorMask;
|
|
||||||
|
|
||||||
RenderEngine(int[] mask) {
|
|
||||||
this();
|
|
||||||
for (int i = 0; i < mask.length; i += 4) {
|
|
||||||
int x1 = mask[i],
|
|
||||||
y1 = mask[i + 1],
|
|
||||||
x2 = mask[i + 2],
|
|
||||||
y2 = mask[i + 3];
|
|
||||||
for (int y = y1; y < y2; y++) {
|
|
||||||
for (int x = x1; x < x2; x++) {
|
|
||||||
colorMask[y][x] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderEngine() {
|
|
||||||
colorMask = new boolean[192][80];
|
|
||||||
for (int y = 0; y < 192; y++) {
|
|
||||||
colorMask[y] = new boolean[80];
|
|
||||||
Arrays.fill(colorMask[y], true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LawlessVideo() {
|
public LawlessVideo() {
|
||||||
super();
|
super();
|
||||||
this.vblankStart();
|
this.vblankStart();
|
||||||
}
|
for (boolean[] row : activeMask) {
|
||||||
|
Arrays.fill(row, true);
|
||||||
public void setEngine(RenderEngine e) {
|
|
||||||
if (activeEngine != e) {
|
|
||||||
titleScreen = false;
|
|
||||||
activeEngine = e;
|
|
||||||
for (int y=0; y < 192; y++) {
|
|
||||||
System.arraycopy(activeEngine.colorMask[y], 0, activeMask[y], 0, 80);
|
|
||||||
}
|
|
||||||
|
|
||||||
Emulator.withComputer(c->c.onNextVBL(Video::forceRefresh));
|
|
||||||
System.out.println("Detected engine: " + e.name());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +29,6 @@ public class LawlessVideo extends VideoNTSC {
|
||||||
divBy56[i] = i / 56;
|
divBy56[i] = i / 56;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSummary(int row) {
|
public int getSummary(int row) {
|
||||||
PagedMemory mainMemory = ((RAM128k) getMemory()).getMainMemory();
|
PagedMemory mainMemory = ((RAM128k) getMemory()).getMainMemory();
|
||||||
int rowAddr = getCurrentWriter().getYOffset(row);
|
int rowAddr = getCurrentWriter().getYOffset(row);
|
||||||
|
@ -118,11 +46,7 @@ public class LawlessVideo extends VideoNTSC {
|
||||||
}
|
}
|
||||||
int rowStart = getCurrentWriter().getYOffset(y);
|
int rowStart = getCurrentWriter().getYOffset(y);
|
||||||
if (rowStart >= 0x02000) {
|
if (rowStart >= 0x02000) {
|
||||||
boolean[] color = activeMask[y];
|
System.arraycopy(activeMask[y], 0, colorActive, 0, 80);
|
||||||
if (titleScreen) {
|
|
||||||
color = RenderEngine.FULL_COLOR.colorMask[y];
|
|
||||||
}
|
|
||||||
System.arraycopy(color, 0, colorActive, 0, 80);
|
|
||||||
}
|
}
|
||||||
super.hblankStart(screen, y, isDirty);
|
super.hblankStart(screen, y, isDirty);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user