mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-07-05 01:28:57 +00:00
Some refinements to capture text inside the graphics area
This commit is contained in:
parent
c50ea6ec77
commit
69261e6915
@ -1,11 +1,11 @@
|
||||
package jace.lawless;
|
||||
|
||||
import jace.apple2e.MOS65C02;
|
||||
import jace.apple2e.SoftSwitches;
|
||||
import jace.cheat.Cheats;
|
||||
import jace.core.Computer;
|
||||
import jace.core.RAMEvent;
|
||||
import jace.lawless.LawlessVideo.RenderEngine;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Hacks that affect lawless legends gameplay
|
||||
@ -14,13 +14,12 @@ public class LawlessHacks extends Cheats {
|
||||
|
||||
// Location of font routines
|
||||
int FONT_ROUTINES = 0x0EC00;
|
||||
int FONT_ROUTINES_END = 0x0f800;
|
||||
int FONT_SPEEDUP_CYCLES = 10000;
|
||||
int FONT_ROUTINES_LEN = 0x0f00;
|
||||
int ENGINE_ADDR = 0x06000;
|
||||
int ENGINE_FIRST_OPCODE = ENGINE_ADDR + (13 * 3);
|
||||
int DETECT_ENGINE_WRITE = 0x060FF;
|
||||
Cheats speedupRequester = this;
|
||||
AtomicInteger speedupCounter = new AtomicInteger();
|
||||
|
||||
public LawlessHacks(Computer computer) {
|
||||
super(computer);
|
||||
@ -28,15 +27,22 @@ public class LawlessHacks extends Cheats {
|
||||
|
||||
@Override
|
||||
public void registerListeners() {
|
||||
for (int entry = 0; entry < 13; entry++) {
|
||||
int targetAddress = FONT_ROUTINES + (entry * 3);
|
||||
addCheat(RAMEvent.TYPE.EXECUTE, (e) -> {
|
||||
if (e.getAddress() == targetAddress) {
|
||||
computer.motherboard.requestSpeed(speedupRequester);
|
||||
speedupCounter.set(FONT_SPEEDUP_CYCLES);
|
||||
}
|
||||
}, targetAddress);
|
||||
}
|
||||
// Observe graphics changes
|
||||
addCheat(RAMEvent.TYPE.WRITE, (e) -> {
|
||||
if (e.getAddress() >= 0x02000 && e.getAddress() <= 0x05FFF) {
|
||||
((LawlessVideo) computer.getVideo()).setBWFlag(e.getAddress(),
|
||||
SoftSwitches.RAMWRT.getState() ||
|
||||
computer.getCpu().getProgramCounter() < FONT_ROUTINES ||
|
||||
computer.getCpu().getProgramCounter() > FONT_ROUTINES_END);
|
||||
}
|
||||
}, 0x02000, 0x05FFF);
|
||||
// Watch for font routine usage for speedup
|
||||
addCheat(RAMEvent.TYPE.EXECUTE, (e) -> {
|
||||
if ((e.getAddress() & 0x0ff00) == FONT_ROUTINES) {
|
||||
computer.motherboard.requestSpeed(this);
|
||||
}
|
||||
}, FONT_ROUTINES, FONT_ROUTINES | 0x0ff);
|
||||
// Try to detect engines changing
|
||||
addCheat(RAMEvent.TYPE.WRITE, false, (e) -> {
|
||||
if (e.getAddress() == DETECT_ENGINE_WRITE) {
|
||||
detectActiveEngine();
|
||||
@ -51,18 +57,10 @@ public class LawlessHacks extends Cheats {
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (speedupCounter.get() > 0 && speedupCounter.decrementAndGet() <= 0) {
|
||||
int pc = computer.getCpu().getProgramCounter();
|
||||
if (pc >= FONT_ROUTINES && pc <= FONT_ROUTINES + FONT_ROUTINES_LEN) {
|
||||
speedupCounter.addAndGet(500);
|
||||
computer.motherboard.requestSpeed(speedupRequester);
|
||||
} else {
|
||||
computer.motherboard.cancelSpeedRequest(speedupRequester);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void detectActiveEngine() {
|
||||
LawlessVideo video = (LawlessVideo) computer.getVideo();
|
||||
// for (int i = 0x06000; i < 0x06080;) {
|
||||
// System.out.printf("%04x: ", i);
|
||||
// for (int j = 0; j < 16; j++, i++) {
|
||||
@ -76,19 +74,19 @@ public class LawlessHacks extends Cheats {
|
||||
if (firstPageByte == MOS65C02.OPCODE.JMP_AB.getCode()
|
||||
&& firstDataByte == MOS65C02.OPCODE.LDX_ZP.getCode()) {
|
||||
// 2D Engine: First instruction is LDX MAP_PARTITION
|
||||
LawlessVideo.setEngine(RenderEngine._2D);
|
||||
video.setEngine(RenderEngine._2D);
|
||||
} else if (firstPageByte == MOS65C02.OPCODE.JMP_AB.getCode()
|
||||
&& firstDataByte == 0
|
||||
&& secondDataByte == 0) {
|
||||
// 3D Engine: First byte is a zero for MapHeader
|
||||
LawlessVideo.setEngine(RenderEngine._3D);
|
||||
video.setEngine(RenderEngine._3D);
|
||||
} else if (firstPageByte == MOS65C02.OPCODE.JMP_AB.getCode()
|
||||
&& firstDataByte == 0
|
||||
&& secondDataByte == 0x067) {
|
||||
// 3D Engine: First byte is a zero for MapHeader
|
||||
LawlessVideo.setEngine(RenderEngine.PORTRAIT);
|
||||
video.setEngine(RenderEngine.PORTRAIT);
|
||||
} else {
|
||||
LawlessVideo.setEngine(RenderEngine.UNKNOWN);
|
||||
video.setEngine(RenderEngine.UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,9 @@ public class LawlessVideo extends VideoNTSC {
|
||||
private static RenderEngine activeEngine = RenderEngine.UNKNOWN;
|
||||
private boolean invActive = false;
|
||||
private boolean titleScreen = false;
|
||||
|
||||
private boolean[][] activeMask = new boolean[192][80];
|
||||
|
||||
|
||||
public static enum RenderEngine {
|
||||
_2D(new int[]{
|
||||
9, 8, 34, 17,
|
||||
@ -63,10 +65,30 @@ public class LawlessVideo extends VideoNTSC {
|
||||
super(computer);
|
||||
}
|
||||
|
||||
public static void setEngine(RenderEngine e) {
|
||||
public void setEngine(RenderEngine e) {
|
||||
activeEngine = e;
|
||||
Emulator.computer.onNextVBL(()->Emulator.computer.getVideo().forceRefresh());
|
||||
// System.out.println("Detected engine: " + e.name());
|
||||
for (int y=0; y < 192; y++) {
|
||||
System.arraycopy(e.colorMask[y], 0, activeMask[y], 0, 80);
|
||||
}
|
||||
Emulator.computer.onNextVBL(() -> Emulator.computer.getVideo().forceRefresh());
|
||||
System.out.println("Detected engine: " + e.name());
|
||||
}
|
||||
|
||||
public void setBWFlag(int addr, boolean b) {
|
||||
addr &= 0x01FFF;
|
||||
int row = VideoNTSC.identifyHiresRow(addr);
|
||||
if (row < 0 || row > 192) {
|
||||
return;
|
||||
}
|
||||
int col = addr - VideoNTSC.calculateHiresOffset(row);
|
||||
if (row > 20 && row < 136 && col < 20) {
|
||||
boolean prev = activeMask[row][col*2];
|
||||
activeMask[row][col*2] = b;
|
||||
activeMask[row][col*2+1] = b;
|
||||
if (prev ^ b) {
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public int[] divBy56 = new int[560];
|
||||
@ -86,10 +108,10 @@ public class LawlessVideo extends VideoNTSC {
|
||||
int row6 = getSummary(6);
|
||||
int row7 = getSummary(7);
|
||||
// Rows 6,7 = White
|
||||
invActive = row5 == 0
|
||||
&& row6 == 1270
|
||||
invActive = row5 == 0
|
||||
&& row6 == 1270
|
||||
&& row7 == 1270;
|
||||
titleScreen = row4 == 828 && row5 == 513 && row6 == 382;
|
||||
titleScreen = row4 == 828 && row5 == 513 && row6 == 382;
|
||||
}
|
||||
|
||||
public int getSummary(int row) {
|
||||
@ -106,7 +128,7 @@ public class LawlessVideo extends VideoNTSC {
|
||||
public void hblankStart(WritableImage screen, int y, boolean isDirty) {
|
||||
int rowStart = getCurrentWriter().getYOffset(y);
|
||||
if (rowStart >= 0x02000) {
|
||||
boolean[] color = activeEngine.colorMask[y];
|
||||
boolean[] color = activeMask[y];
|
||||
if (titleScreen) {
|
||||
color = RenderEngine.UNKNOWN.colorMask[y];
|
||||
} else if (invActive) {
|
||||
|
Loading…
Reference in New Issue
Block a user