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 # Ignore NetBeans project files
Platform/Apple/tools/jace/nb-configuration.xml Platform/Apple/tools/jace/nb-configuration.xml
Platform/Apple/tools/jace/nbactions.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(); resetEmulator();
configureEmulatorForGame(); configureEmulatorForGame();
bootWatchdog(); bootWatchdog();
// Emulator.getComputer().getCpu().trace=true;
} else { } else {
startListener.unregister(); startListener.unregister();
} }

View File

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

View File

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

View File

@ -10,6 +10,7 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -18,7 +19,10 @@ import java.util.regex.Pattern;
import jace.Emulator; import jace.Emulator;
import jace.apple2e.VideoDHGR; import jace.apple2e.VideoDHGR;
import jace.cheat.Cheats; import jace.cheat.Cheats;
import jace.core.Computer;
import jace.core.Motherboard;
import jace.core.RAMEvent; import jace.core.RAMEvent;
import jace.core.TimedDevice;
import javafx.util.Duration; 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 Speedup", RAMEvent.TYPE.EXECUTE, this::fastText, 0x0ee00, 0x0ee00 + 0x0f00);
addCheat("Lawless Text Enhancement", RAMEvent.TYPE.WRITE, this::enhanceText, 0x02000, 0x03fff); 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 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 @Override
@ -76,12 +81,27 @@ public class LawlessHacks extends Cheats {
} }
// Enhance text rendering by forcing the text to be pure B&W // 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) { private void enhanceText(RAMEvent e) {
if (!e.isMainMemory()) { if (!e.isMainMemory()) {
return; return;
} }
int pc = Emulator.withComputer(c->c.getCpu().getProgramCounter(), 0); 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 -> { Emulator.withVideo(v -> {
if (v instanceof LawlessVideo) { if (v instanceof LawlessVideo) {
LawlessVideo video = (LawlessVideo) v; 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_NONE = "none";
public static final String SCORE_COMMON = "common"; public static final String SCORE_COMMON = "common";
public static final String SCORE_ORCHESTRAL = "8-bit orchestral samples"; public static final String SCORE_ORCHESTRAL = "8-bit orchestral samples";

View File

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

View File

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