Compare commits

...

9 Commits

Author SHA1 Message Date
Peter Ferrie 9f0c43af18
Merge d4d3c59b8c into b3ec0df929 2024-04-06 11:59:39 -05:00
Brendan Robert b3ec0df929 Speed adjusts down for portrait animation 2024-04-06 11:59:29 -05:00
Brendan Robert 25d5f293e8 Start of animation speed adjustment 2024-04-06 08:20:08 -05:00
Brendan Robert 90771cb31e Fix text issue with locket message 2024-04-03 00:03:43 -05:00
Brendan Robert e8c6fb3efe update ignore file for temporary pom files 2024-04-02 23:29:31 -05:00
Peter Ferrie d4d3c59b8c defer case check to be faster 2023-09-03 15:08:16 -07:00
Peter Ferrie c540527370 another fix 2023-09-03 14:42:51 -07:00
Peter Ferrie 3f359cf3ff fix a couple of bugs, compare a bit faster 2023-09-03 14:41:10 -07:00
Peter Ferrie b258ed441a decompress faster 2023-09-02 11:30:15 -07:00
7 changed files with 107 additions and 47 deletions

3
.gitignore vendored
View File

@ -68,3 +68,6 @@ error_stack.txt
# Ignore NetBeans project files
Platform/Apple/tools/jace/nb-configuration.xml
Platform/Apple/tools/jace/nbactions.xml
# Ignore temporary pom files
Platform/Apple/tools/jace/runPom.xml

View File

@ -167,7 +167,6 @@ public class LawlessLegends extends Application {
resetEmulator();
configureEmulatorForGame();
bootWatchdog();
// Emulator.getComputer().getCpu().trace=true;
} else {
startListener.unregister();
}

View File

@ -123,5 +123,5 @@ public class Motherboard extends IndependentTimedDevice {
if (accelorationRequestors.remove(requester) && accelorationRequestors.isEmpty()) {
disableTempMaxSpeed();
}
}
}
}

View File

@ -124,6 +124,10 @@ public abstract class TimedDevice extends Device {
}
}
public final boolean isMaxSpeedEnabled() {
return maxspeed;
}
public final boolean isMaxSpeed() {
return forceMaxspeed || maxspeed;
}

View File

@ -10,6 +10,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
@ -18,7 +19,10 @@ import java.util.regex.Pattern;
import jace.Emulator;
import jace.apple2e.VideoDHGR;
import jace.cheat.Cheats;
import jace.core.Computer;
import jace.core.Motherboard;
import jace.core.RAMEvent;
import jace.core.TimedDevice;
import javafx.util.Duration;
/**
@ -48,6 +52,7 @@ public class LawlessHacks extends Cheats {
addCheat("Lawless Text Speedup", RAMEvent.TYPE.EXECUTE, this::fastText, 0x0ee00, 0x0ee00 + 0x0f00);
addCheat("Lawless Text Enhancement", RAMEvent.TYPE.WRITE, this::enhanceText, 0x02000, 0x03fff);
addCheat("Lawless Legends Music Commands", RAMEvent.TYPE.WRITE, (e) -> playSound(e.getNewValue()), SFX_TRIGGER);
addCheat("Lawless Adjust Animation Speed", RAMEvent.TYPE.READ, this::adjustAnimationSpeed, 0x0c000, 0x0c010);
}
@Override
@ -76,12 +81,27 @@ public class LawlessHacks extends Cheats {
}
// Enhance text rendering by forcing the text to be pure B&W
Map<Integer, Integer> detectedEntryPoints = new TreeMap<>();
long lastStatus = 0;
private void enhanceText(RAMEvent e) {
if (!e.isMainMemory()) {
return;
}
int pc = Emulator.withComputer(c->c.getCpu().getProgramCounter(), 0);
boolean drawingText = pc == 0x0ee46 || pc > 0x0f300;
boolean drawingText = (pc >= 0x0ee00 && pc <= 0x0f0c0) || pc > 0x0f100;
if (DEBUG) {
if (drawingText) {
detectedEntryPoints.put(pc, detectedEntryPoints.getOrDefault(pc, 0) + 1);
}
if ((System.currentTimeMillis() - lastStatus) >= 10000) {
lastStatus = System.currentTimeMillis();
System.out.println("---text entry points---");
detectedEntryPoints.forEach((addr, count) -> {
System.out.println(Integer.toHexString(addr) + ": " + count);
});
}
}
Emulator.withVideo(v -> {
if (v instanceof LawlessVideo) {
LawlessVideo video = (LawlessVideo) v;
@ -98,6 +118,45 @@ public class LawlessHacks extends Cheats {
});
}
private Map<Integer, Integer> keyReadAddresses = new TreeMap<>();
long lastKeyStatus = 0;
long lastKnownSpeed = -1;
boolean isCurrentlyMaxSpeed = false;
private void adjustAnimationSpeed(RAMEvent e) {
int pc = Emulator.withComputer(c->c.getCpu().getProgramCounter(), 0);
if (DEBUG) {
keyReadAddresses.put(pc, keyReadAddresses.getOrDefault(pc, 0) + 1);
if ((System.currentTimeMillis() - lastKeyStatus) >= 10000) {
lastKeyStatus = System.currentTimeMillis();
System.out.println("---keyin points---");
keyReadAddresses.forEach((addr, count) -> {
System.out.println(Integer.toHexString(addr) + ": " + count);
});
}
}
Motherboard m = Emulator.withComputer(Computer::getMotherboard, null);
long currentSpeed = m.getSpeedInHz();
if (pc == 0x0D5FE) {
long slowerSpeed = (long) (TimedDevice.NTSC_1MHZ * 1.5);
// We are waiting for a key in portait mode, slow to 1.5x
if (currentSpeed > slowerSpeed || m.isMaxSpeedEnabled()) {
lastKnownSpeed = currentSpeed;
isCurrentlyMaxSpeed = m.isMaxSpeedEnabled();
m.setSpeedInHz(slowerSpeed);
m.setMaxSpeed(false);
m.cancelSpeedRequest(this);
}
} else {
// We're in some other mode, go back the default speed
if (currentSpeed < lastKnownSpeed || isCurrentlyMaxSpeed) {
m.setSpeedInHz(lastKnownSpeed);
m.setMaxSpeed(isCurrentlyMaxSpeed);
isCurrentlyMaxSpeed = false;
lastKnownSpeed = -1;
}
}
}
public static final String SCORE_NONE = "none";
public static final String SCORE_COMMON = "common";
public static final String SCORE_ORCHESTRAL = "8-bit orchestral samples";

View File

@ -33,8 +33,9 @@ DEBUG = 0
decomp !zone {
jsr .chkdst
ldy #0 ; In lit loop Y must be zero
sec
.fill1A jsr .getbt2
jmp .fill1B
bne .fill1B ; always taken
.incdst inc pDst+1
.chkdst ldx pDst+1
@ -174,19 +175,19 @@ decomp !zone {
bne .gshift ; always taken
; Get another 8 bits into our bit buffer. Destroys X. Preserves A. Requires Y=0.
; Carry is always set on entry, Z always clear on exit
; Alternately, use .getbt2 to preserve X and destroy A
.getbts tax
.getbt2 lda (pSrc),y
inc pSrc
beq .src3A
.src3B sec
rol
sta bits
txa
inc pSrc
beq .src3A
rts
.src3A inc pSrc+1
bne .src3B ; always taken
rts
} ; end of zone

View File

@ -364,7 +364,7 @@ export asm memcpy(pSrc, pDst, len, auxWr)#0
inc pTmp+1
bne .pglup ; always taken
.part:
cpx #0
txa
beq .done
- lda (tmp),y
sta (pTmp),y
@ -390,8 +390,8 @@ export asm memset(pDst, val, len)#0
lda evalStkL,x ; len lo
pha
lda evalStkH,x ; len hi
tax
beq +
tax
lda tmp
- sta (pTmp),y
iny
@ -420,10 +420,10 @@ export asm readAuxByte(ptr)#1
sta $10-1,y
dey
bne -
jmp $10
.rdauxb
sei ; prevent interrupts while in aux mem
sta setAuxRd
jmp $10
.rdauxb
lda (pTmp),y
sta clrAuxRd
cli
@ -462,19 +462,19 @@ end
export asm finishString(isPlural)#1
!zone {
+asmPlasmRet 1
ldy prevCSWL+ABS_OFFSET ; put the cout vector back to default
sty cswl
ldy prevCSWL+1+ABS_OFFSET ; put the cout vector back to default
sty cswh
ldy #0 ; dest offset in Y (will be incremented before store)
cpy inbuf
beq .done1 ; failsafe: handle zero-length string
tax ; test for isPlural == 0
beq +
lda #$40 ; for setting V later
+ sta tmp ; save isPlural flag
lda prevCSWL+ABS_OFFSET ; put the cout vector back to default
sta cswl
lda prevCSWL+1+ABS_OFFSET ; put the cout vector back to default
sta cswh
clv ; V flag for prev-is-alpha
ldy #0 ; dest offset in Y (will be incremented before store)
ldx #0 ; source offset in X (will be incremented before load)
cpx inbuf
beq .done ; failsafe: handle zero-length string
.fetch
inx
lda inbuf,x ; get next input char
@ -488,11 +488,11 @@ export asm finishString(isPlural)#1
dey ; undo copy of the paren
stx tmp+1 ; save position in input
dex ; needed for failsafe operation
bit tmp ; set copy flag (V) initially to same as isPlural flag
.findsl ; see if there's a slash within the parens
inx
cpx inbuf
bcs .done ; failsafe: handle missing end-paren
lda inbuf,x
ora #$80 ; normalize hi-bit for comparisons below
cmp #"/"
@ -503,11 +503,8 @@ export asm finishString(isPlural)#1
pha
plp
+ cmp #")" ; scan until ending paren
beq +
cpx inbuf
bcc .findsl ; loop to scan next char
bcs .done ; failsafe: handle missing end-paren (always taken)
+ ldx tmp+1 ; get back to start of parens
bne .findsl ; loop to scan next char
ldx tmp+1 ; get back to start of parens
; copy mode flag is now in V: if slash present, single=copy, plural=nocopy
; if no slash: single=nocopy, plural=copy
.plup
@ -541,6 +538,7 @@ export asm finishString(isPlural)#1
.done
sty inbuf ; save new length
.done1
lda #<inbuf ; return pointer to string
ldy #>inbuf
rts
@ -575,8 +573,8 @@ export asm blit(isAux, srcData, dstScreenPtr, nLines, lineSize)#0
lsr ; to carry bit
bcc +
ldy #15 ; put aux copy routine in zero page
- lda .cpaux + ABS_OFFSET,y
sta $10,y
- ldx .cpaux + ABS_OFFSET,y
stx $10,y
dey
bpl -
+ pla ; get line count
@ -694,8 +692,9 @@ export asm puts(str)#0
sta pTmp
lda #'!'
ldx #1
sty pTmp+1
tya
beq + ; safety: print '!' instead of null string
sty pTmp+1
ldy #0
lda (pTmp),y
tax
@ -913,9 +912,8 @@ export asm rawDisplayStr(pStr)#0
lda (pTmp),y
sta tmp
- cpy tmp
bcc +
rts
+ iny
bcs ++
iny
lda (pTmp),y
ora #$80
cmp #"^"
@ -929,7 +927,8 @@ export asm rawDisplayStr(pStr)#0
+ sty tmp+1
jsr DisplayChar
ldy tmp+1
bne -
bne - ; always taken
++rts
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -991,8 +990,8 @@ export asm streqi(a, b)#1
lda evalStkL+1,x
sta pTmp
lda evalStkH+1,x
sta pTmp+1
beq .null
sta pTmp+1
ldy #0
lda (tmp),y
cmp (pTmp),y
@ -1004,21 +1003,16 @@ export asm streqi(a, b)#1
+ tax ; count up to (verified same) length of the strings
- iny
lda (tmp),y
cmp #('z'&$7F)+1 ; convert to upper case
bcs +
eor (pTmp),y
beq + ; matched
cmp #$20 ; check for case bit
bne .noteqi ; abort on alpha inequality
ora (tmp),y ; convert to lower case
cmp #('z'&$7F)+1
bcs .noteqi ; abort on inequality
cmp #'a'&$7F
bcc +
sbc #$20
+ sta ysav
lda (pTmp),y
cmp #('z'&$7F)+1 ; convert to upper case
bcs +
cmp #'a'&$7F
bcc +
sbc #$20
+ cmp ysav
bne .noteqi ; abort on inequality
dex
bcc .noteqi ; abort on inequality
+ dex
bne -
lda #1
ldy #0 ; okay, they're equal. Return 1 (not just any char; so that PLASMA when...is can work)