mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-07-06 07:29:13 +00:00
Merge branch 'master' of github.com:badvision/lawless-legends
This commit is contained in:
commit
433eaf3f47
@ -1340,7 +1340,16 @@ LEAVEX INY ;+INC_IP
|
|||||||
STA IFPL
|
STA IFPL
|
||||||
PLA
|
PLA
|
||||||
STA IFPH
|
STA IFPH
|
||||||
RETX STA ALTRDOFF
|
STA ALTRDOFF
|
||||||
|
LDA PSR
|
||||||
|
PHA
|
||||||
|
PLP
|
||||||
|
RTS
|
||||||
|
RETX LDA IFPL
|
||||||
|
STA PPL
|
||||||
|
LDA IFPH
|
||||||
|
STA PPH
|
||||||
|
STA ALTRDOFF
|
||||||
LDA PSR
|
LDA PSR
|
||||||
PHA
|
PHA
|
||||||
PLP
|
PLP
|
||||||
|
@ -21,6 +21,7 @@ package jace.core;
|
|||||||
import jace.apple2e.SoftSwitches;
|
import jace.apple2e.SoftSwitches;
|
||||||
import jace.apple2e.Speaker;
|
import jace.apple2e.Speaker;
|
||||||
import jace.config.ConfigurableField;
|
import jace.config.ConfigurableField;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -40,7 +41,7 @@ import java.util.logging.Logger;
|
|||||||
*/
|
*/
|
||||||
public class Motherboard extends TimedDevice {
|
public class Motherboard extends TimedDevice {
|
||||||
|
|
||||||
final public Set<Device> miscDevices = new LinkedHashSet<>();
|
final public Set<Device> miscDevices = Collections.synchronizedSet(new LinkedHashSet<>());
|
||||||
@ConfigurableField(name = "Enable Speaker", shortName = "speaker", defaultValue = "true")
|
@ConfigurableField(name = "Enable Speaker", shortName = "speaker", defaultValue = "true")
|
||||||
public static boolean enableSpeaker = true;
|
public static boolean enableSpeaker = true;
|
||||||
public Speaker speaker;
|
public Speaker speaker;
|
||||||
|
@ -21,6 +21,7 @@ package jace.core;
|
|||||||
import jace.apple2e.SoftSwitches;
|
import jace.apple2e.SoftSwitches;
|
||||||
import jace.config.Reconfigurable;
|
import jace.config.Reconfigurable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -160,7 +161,7 @@ public abstract class RAM implements Reconfigurable {
|
|||||||
int index = address & 0x0FF;
|
int index = address & 0x0FF;
|
||||||
Set<RAMListener> ioListeners = ioListenerMap[index];
|
Set<RAMListener> ioListeners = ioListenerMap[index];
|
||||||
if (ioListeners == null) {
|
if (ioListeners == null) {
|
||||||
ioListeners = new HashSet<>();
|
ioListeners = Collections.synchronizedSet(new HashSet<>());
|
||||||
ioListenerMap[index] = ioListeners;
|
ioListenerMap[index] = ioListeners;
|
||||||
}
|
}
|
||||||
ioListeners.add(l);
|
ioListeners.add(l);
|
||||||
@ -168,7 +169,7 @@ public abstract class RAM implements Reconfigurable {
|
|||||||
int index = address >> 8;
|
int index = address >> 8;
|
||||||
Set<RAMListener> otherListeners = listenerMap[index];
|
Set<RAMListener> otherListeners = listenerMap[index];
|
||||||
if (otherListeners == null) {
|
if (otherListeners == null) {
|
||||||
otherListeners = new HashSet<>();
|
otherListeners = Collections.synchronizedSet(new HashSet<>());
|
||||||
listenerMap[index] = otherListeners;
|
listenerMap[index] = otherListeners;
|
||||||
}
|
}
|
||||||
otherListeners.add(l);
|
otherListeners.add(l);
|
||||||
|
@ -27,7 +27,6 @@ import jace.core.RAMEvent;
|
|||||||
import jace.core.RAMEvent.TYPE;
|
import jace.core.RAMEvent.TYPE;
|
||||||
import jace.core.RAMListener;
|
import jace.core.RAMListener;
|
||||||
import jace.core.SoundMixer;
|
import jace.core.SoundMixer;
|
||||||
import static jace.core.Utility.*;
|
|
||||||
import jace.hardware.mockingboard.PSG;
|
import jace.hardware.mockingboard.PSG;
|
||||||
import jace.hardware.mockingboard.R6522;
|
import jace.hardware.mockingboard.R6522;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -90,7 +89,7 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
super(computer);
|
super(computer);
|
||||||
controllers = new R6522[2];
|
controllers = new R6522[2];
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
//don't ask...
|
// has to be final to be used inside of anonymous class below
|
||||||
final int j = i;
|
final int j = i;
|
||||||
controllers[i] = new R6522(computer) {
|
controllers[i] = new R6522(computer) {
|
||||||
int controller = j;
|
int controller = j;
|
||||||
@ -131,6 +130,13 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
public String getShortName() {
|
public String getShortName() {
|
||||||
return "timer" + j;
|
return "timer" + j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void doTick() {
|
||||||
|
super.doTick();
|
||||||
|
if (controller == 0) {
|
||||||
|
doSoundTick();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,6 +147,18 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
}
|
}
|
||||||
RAMListener mainListener = null;
|
RAMListener mainListener = null;
|
||||||
|
|
||||||
|
boolean heatbeatUnclocked = false;
|
||||||
|
long heartbeatReclockTime = 0L;
|
||||||
|
long unclockTime = 5000L;
|
||||||
|
|
||||||
|
private void setUnclocked(boolean unclocked) {
|
||||||
|
heatbeatUnclocked = unclocked;
|
||||||
|
for (R6522 controller : controllers) {
|
||||||
|
controller.setUnclocked(unclocked);
|
||||||
|
}
|
||||||
|
heartbeatReclockTime = System.currentTimeMillis() + unclockTime;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleFirmwareAccess(int register, TYPE type, int value, RAMEvent e) {
|
protected void handleFirmwareAccess(int register, TYPE type, int value, RAMEvent e) {
|
||||||
resume();
|
resume();
|
||||||
@ -152,7 +170,7 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
chip++;
|
chip++;
|
||||||
}
|
}
|
||||||
if (chip >= 2) {
|
if (chip >= 2) {
|
||||||
System.err.println("Could not determine which PSG to communicate to");
|
System.err.println("Could not determine which PSG to communicate to for access to regsiter + " + Integer.toHexString(register));
|
||||||
e.setNewValue(computer.getVideo().getFloatingBus());
|
e.setNewValue(computer.getVideo().getFloatingBus());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -177,13 +195,21 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (heatbeatUnclocked) {
|
||||||
|
if (System.currentTimeMillis() - heartbeatReclockTime >= unclockTime) {
|
||||||
|
setUnclocked(false);
|
||||||
|
} else {
|
||||||
for (R6522 c : controllers) {
|
for (R6522 c : controllers) {
|
||||||
if (c == null || !c.isRunning()) {
|
if (c == null || !c.isRunning()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
c.tick();
|
c.doTick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void doSoundTick() {
|
||||||
if (isRunning() && !pause) {
|
if (isRunning() && !pause) {
|
||||||
// buildMixerTable();
|
// buildMixerTable();
|
||||||
timerSync.lock();
|
timerSync.lock();
|
||||||
@ -194,7 +220,7 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
while (isRunning() && ticksSinceLastPlayback >= ticksBetweenPlayback) {
|
while (isRunning() && ticksSinceLastPlayback >= ticksBetweenPlayback) {
|
||||||
if (!playbackFinished.await(1, TimeUnit.SECONDS)) {
|
if (!playbackFinished.await(1, TimeUnit.SECONDS)) {
|
||||||
// gripe("The mockingboard playback thread has stalled. Disabling mockingboard.");
|
// gripe("The mockingboard playback thread has stalled. Disabling mockingboard.");
|
||||||
suspend();
|
suspendSound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,7 +289,6 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
@Override
|
@Override
|
||||||
public void resume() {
|
public void resume() {
|
||||||
pause = false;
|
pause = false;
|
||||||
if (!isRunning()) {
|
|
||||||
if (chips == null) {
|
if (chips == null) {
|
||||||
initPSG();
|
initPSG();
|
||||||
for (PSG psg : chips) {
|
for (PSG psg : chips) {
|
||||||
@ -271,6 +296,8 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
psg.reset();
|
psg.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!isRunning()) {
|
||||||
|
setUnclocked(true);
|
||||||
for (R6522 controller : controllers) {
|
for (R6522 controller : controllers) {
|
||||||
controller.attach();
|
controller.attach();
|
||||||
controller.resume();
|
controller.resume();
|
||||||
@ -290,6 +317,10 @@ public class CardMockingboard extends Card implements Runnable {
|
|||||||
controller.suspend();
|
controller.suspend();
|
||||||
controller.detach();
|
controller.detach();
|
||||||
}
|
}
|
||||||
|
return suspendSound();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean suspendSound() {
|
||||||
if (playbackThread == null || !playbackThread.isAlive()) {
|
if (playbackThread == null || !playbackThread.isAlive()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,15 @@ package jace.hardware.mockingboard;
|
|||||||
|
|
||||||
import jace.core.Computer;
|
import jace.core.Computer;
|
||||||
import jace.core.Device;
|
import jace.core.Device;
|
||||||
|
import jace.core.TimedDevice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of 6522 VIA chip
|
* Implementation of 6522 VIA chip
|
||||||
*
|
*
|
||||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||||
*/
|
*/
|
||||||
public abstract class R6522 extends Device {
|
public abstract class R6522 extends TimedDevice {
|
||||||
|
public static long SPEED = 1020484L; // (NTSC)
|
||||||
|
|
||||||
public R6522(Computer computer) {
|
public R6522(Computer computer) {
|
||||||
super(computer);
|
super(computer);
|
||||||
@ -34,9 +36,15 @@ public abstract class R6522 extends Device {
|
|||||||
timer1running = true;
|
timer1running = true;
|
||||||
timer1latch = 0x1fff;
|
timer1latch = 0x1fff;
|
||||||
timer1interruptEnabled = false;
|
timer1interruptEnabled = false;
|
||||||
|
setSpeedInHz(SPEED);
|
||||||
setRun(true);
|
setRun(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long defaultCyclesPerSecond() {
|
||||||
|
return SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
// 6522 VIA
|
// 6522 VIA
|
||||||
// http://www.applevault.com/twiki/Main/Mockingboard/6522.pdf
|
// http://www.applevault.com/twiki/Main/Mockingboard/6522.pdf
|
||||||
// I/O registers
|
// I/O registers
|
||||||
@ -133,6 +141,7 @@ public abstract class R6522 extends Device {
|
|||||||
public int timer2latch = 0;
|
public int timer2latch = 0;
|
||||||
public int timer2counter = 0;
|
public int timer2counter = 0;
|
||||||
public boolean timer2running = false;
|
public boolean timer2running = false;
|
||||||
|
public boolean unclocked = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getDeviceName() {
|
protected String getDeviceName() {
|
||||||
@ -141,6 +150,16 @@ public abstract class R6522 extends Device {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (!unclocked) {
|
||||||
|
doTick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUnclocked(boolean unclocked) {
|
||||||
|
this.unclocked = unclocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTick() {
|
||||||
if (timer1running) {
|
if (timer1running) {
|
||||||
timer1counter--;
|
timer1counter--;
|
||||||
if (timer1counter < 0) {
|
if (timer1counter < 0) {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package jace.lawless;
|
package jace.lawless;
|
||||||
|
|
||||||
import jace.apple2e.MOS65C02;
|
|
||||||
import jace.apple2e.SoftSwitches;
|
|
||||||
import jace.cheat.Cheats;
|
import jace.cheat.Cheats;
|
||||||
import jace.core.Computer;
|
import jace.core.Computer;
|
||||||
import jace.core.RAMEvent;
|
import jace.core.RAMEvent;
|
||||||
@ -12,11 +10,6 @@ import jace.lawless.LawlessVideo.RenderEngine;
|
|||||||
*/
|
*/
|
||||||
public class LawlessHacks extends Cheats {
|
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;
|
|
||||||
// Modes specified by the game engine
|
// Modes specified by the game engine
|
||||||
int MODE_SOFTSWITCH = 0x0C020;
|
int MODE_SOFTSWITCH = 0x0C020;
|
||||||
|
|
||||||
@ -28,21 +21,6 @@ public class LawlessHacks extends Cheats {
|
|||||||
@Override
|
@Override
|
||||||
public void registerListeners() {
|
public void registerListeners() {
|
||||||
// Observe graphics changes
|
// 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.ANY, false, (e) -> {
|
addCheat(RAMEvent.TYPE.ANY, false, (e) -> {
|
||||||
if ((e.getAddress() & 0x0FFF0) == MODE_SOFTSWITCH) {
|
if ((e.getAddress() & 0x0FFF0) == MODE_SOFTSWITCH) {
|
||||||
System.out.println("Trapped " + e.getType().toString() + " to $"+Integer.toHexString(e.getAddress()));
|
System.out.println("Trapped " + e.getType().toString() + " to $"+Integer.toHexString(e.getAddress()));
|
||||||
|
@ -85,25 +85,6 @@ public class LawlessVideo extends VideoNTSC {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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];
|
static public int[] divBy56 = new int[560];
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
Loading…
Reference in New Issue
Block a user