mirror of
https://github.com/badvision/jace.git
synced 2024-11-23 23:32:59 +00:00
Fixed some edge case language card issues and implemented false reads for absolute indexed addressing modes, improved test coverage
This commit is contained in:
parent
1c26ecad3d
commit
519c561537
@ -414,6 +414,8 @@ public class MOS65C02 extends CPU {
|
||||
ABSOLUTE_X(3, "$~2~1,X", (cpu) -> {
|
||||
int address2 = cpu.getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false);
|
||||
int address = 0x0FFFF & (address2 + cpu.X);
|
||||
// False read
|
||||
cpu.getMemory().read(address, TYPE.READ_DATA, true, false);
|
||||
cpu.setPageBoundaryPenalty((address & 0x00ff00) != (address2 & 0x00ff00));
|
||||
cpu.setPageBoundaryApplied(true);
|
||||
return address;
|
||||
@ -421,6 +423,8 @@ public class MOS65C02 extends CPU {
|
||||
ABSOLUTE_Y(3, "$~2~1,Y", (cpu) -> {
|
||||
int address2 = cpu.getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false);
|
||||
int address = 0x0FFFF & (address2 + cpu.Y);
|
||||
// False read
|
||||
cpu.getMemory().read(address, TYPE.READ_DATA, true, false);
|
||||
cpu.setPageBoundaryPenalty((address & 0x00ff00) != (address2 & 0x00ff00));
|
||||
cpu.setPageBoundaryApplied(true);
|
||||
return address;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package jace.apple2e.softswitch;
|
||||
|
||||
import jace.core.RAMEvent;
|
||||
import jace.core.RAMEvent.TYPE;
|
||||
|
||||
/**
|
||||
@ -23,32 +24,30 @@ import jace.core.RAMEvent.TYPE;
|
||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||
*/
|
||||
public class Memory2SoftSwitch extends MemorySoftSwitch {
|
||||
public Memory2SoftSwitch(String name, int offAddress, int onAddress, int queryAddress, TYPE changeType, Boolean initalState) {
|
||||
super(name, offAddress, onAddress, queryAddress, changeType, initalState);
|
||||
}
|
||||
|
||||
public Memory2SoftSwitch(String name, int[] offAddrs, int[] onAddrs, int[] queryAddrs, TYPE changeType, Boolean initalState) {
|
||||
super(name, offAddrs, onAddrs, queryAddrs, changeType, initalState);
|
||||
}
|
||||
|
||||
// The switch must be set true two times in a row before it will actually be set.
|
||||
int count = 0;
|
||||
int readCount = 0;
|
||||
@Override
|
||||
public void setState(boolean newState) {
|
||||
public void setState(boolean newState, RAMEvent e) {
|
||||
if (!newState) {
|
||||
count = 0;
|
||||
super.setState(newState);
|
||||
super.setState(false);
|
||||
readCount = 0;
|
||||
} else {
|
||||
count++;
|
||||
if (count >= 2) {
|
||||
super.setState(newState);
|
||||
count = 0;
|
||||
if (e.getType().isRead()) {
|
||||
readCount++;
|
||||
} else {
|
||||
readCount = 0;
|
||||
}
|
||||
if (readCount >= 2) {
|
||||
super.setState(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName()+(getState()?":1":":0")+"~~"+count;
|
||||
return getName()+(getState()?":1":":0")+"~~"+readCount;
|
||||
}
|
||||
}
|
@ -114,8 +114,7 @@ public abstract class SoftSwitch {
|
||||
@Override
|
||||
protected void doEvent(RAMEvent e) {
|
||||
if (!exclusionActivate.contains(e.getAddress())) {
|
||||
// System.out.println("Access to "+Integer.toHexString(e.getAddress())+" ENABLES switch "+getName());
|
||||
setState(!getState());
|
||||
setState(!getState(), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -148,7 +147,7 @@ public abstract class SoftSwitch {
|
||||
}
|
||||
if (!exclusionActivate.contains(e.getAddress())) {
|
||||
// System.out.println("Access to "+Integer.toHexString(e.getAddress())+" ENABLES switch "+getName());
|
||||
setState(true);
|
||||
setState(true, e);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -177,7 +176,7 @@ public abstract class SoftSwitch {
|
||||
@Override
|
||||
protected void doEvent(RAMEvent e) {
|
||||
if (!exclusionDeactivate.contains(e.getAddress())) {
|
||||
setState(false);
|
||||
setState(false, e);
|
||||
// System.out.println("Access to "+Integer.toHexString(e.getAddress())+" disables switch "+getName());
|
||||
}
|
||||
}
|
||||
@ -250,6 +249,12 @@ public abstract class SoftSwitch {
|
||||
});
|
||||
}
|
||||
|
||||
// Most softswitches act the same regardless of the ram event triggering them
|
||||
// But some softswitches are a little tricky (such as language card write) and need to assert extra conditions
|
||||
public void setState(boolean newState, RAMEvent e) {
|
||||
setState(newState);
|
||||
}
|
||||
|
||||
public void setState(boolean newState) {
|
||||
if (inhibit()) {
|
||||
return;
|
||||
|
@ -246,10 +246,10 @@ public class TestProgram {
|
||||
private void handleTrace(byte val) {
|
||||
if (val == (byte)0x01) {
|
||||
System.out.println("Trace on");
|
||||
Full65C02Test.cpu.setTraceEnabled(true);
|
||||
Emulator.withComputer(c->c.getCpu().setTraceEnabled(true));
|
||||
} else {
|
||||
System.out.println("Trace off");
|
||||
Full65C02Test.cpu.setTraceEnabled(false);
|
||||
Emulator.withComputer(c->c.getCpu().setTraceEnabled(false));
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,6 +274,13 @@ public class TestProgram {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TestProgram assertEquals(String message) {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
String caller = stackTrace[2].toString();
|
||||
_test(TestProgram.INDENT + TestProgram.Flag.IS_ZERO.code, message + "<<" + caller + ">>");
|
||||
return this;
|
||||
}
|
||||
|
||||
public TestProgram assertFlags(TestProgram.Flag... flags) {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
String caller = stackTrace[2].toString();
|
||||
@ -372,7 +379,11 @@ public class TestProgram {
|
||||
+throwError %s
|
||||
+ ; >> Test """.formatted(condition, code, errorNum));
|
||||
}
|
||||
|
||||
|
||||
public TestProgram throwError(String error) {
|
||||
_test("", error);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Note the current breakpoint, helpful in understanding error locations
|
||||
*
|
||||
@ -447,6 +458,12 @@ public class TestProgram {
|
||||
for (int i=0; i < maxTicks; i++) {
|
||||
cpu.doTick();
|
||||
tickCount++;
|
||||
if (cpu.interruptSignalled) {
|
||||
if (lastError == null) {
|
||||
lastError = new ProgramException("Interrupt signalled by BRK opcode", lastBreakpoint);
|
||||
}
|
||||
programReportedError=true;
|
||||
}
|
||||
if (programReportedError) {
|
||||
throw lastError;
|
||||
}
|
||||
|
@ -20,14 +20,22 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import jace.Emulator;
|
||||
import jace.ProgramException;
|
||||
import jace.TestProgram;
|
||||
import jace.apple2e.MOS65C02;
|
||||
import jace.apple2e.RAM128k;
|
||||
import jace.apple2e.SoftSwitches;
|
||||
|
||||
/**
|
||||
* Test that memory listeners fire appropriately.
|
||||
@ -37,14 +45,36 @@ public class MemoryTest {
|
||||
static Computer computer;
|
||||
static MOS65C02 cpu;
|
||||
static RAM128k ram;
|
||||
static String MEMORY_TEST_COMMONS;
|
||||
static String MACHINE_IDENTIFICATION;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupClass() {
|
||||
public static void setupClass() throws IOException, URISyntaxException {
|
||||
initComputer();
|
||||
SoundMixer.MUTE = true;
|
||||
computer = Emulator.withComputer(c->c, null);
|
||||
cpu = (MOS65C02) computer.getCpu();
|
||||
ram = (RAM128k) computer.getMemory();
|
||||
ram.addExecutionTrap("COUT intercept", 0x0FDF0, (e)->{
|
||||
char c = (char) (cpu.A & 0x07f);
|
||||
if (c == '\r') {
|
||||
System.out.println();
|
||||
} else {
|
||||
System.out.print(c);
|
||||
}
|
||||
});
|
||||
MEMORY_TEST_COMMONS = Files.readString(Paths.get(MemoryTest.class.getResource("/jace/memory_test_commons.asm").toURI()));
|
||||
MACHINE_IDENTIFICATION = Files.readString(Paths.get(MemoryTest.class.getResource("/jace/machine_identification.asm").toURI()));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
computer.pause();
|
||||
cpu.clearState();
|
||||
// Reset softswitches
|
||||
for (SoftSwitches softswitch : SoftSwitches.values()) {
|
||||
softswitch.getSwitch().reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -152,5 +182,324 @@ public class MemoryTest {
|
||||
assertEquals("Should have no writes for 0x0100", 0, writeEventCaught.get());
|
||||
assertEquals("Should have read event for 0x0100", 1, readAnyEventCaught.get());
|
||||
assertEquals("Should have execute for 0x0100", 1, executeEventCaught.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adapted version of the Apple II Family Identification Program from:
|
||||
* http://www.1000bit.it/support/manuali/apple/technotes/misc/tn.misc.02.html00
|
||||
*
|
||||
* Adapted to ACME by Zellyn Hunter
|
||||
*
|
||||
* @throws ProgramException
|
||||
*/
|
||||
@Test
|
||||
public void machineIdentificationTEst() throws ProgramException {
|
||||
TestProgram memoryDetectTestProgram = new TestProgram(MEMORY_TEST_COMMONS);
|
||||
memoryDetectTestProgram.add(MACHINE_IDENTIFICATION);
|
||||
// Assert this is an Apple //e
|
||||
memoryDetectTestProgram.assertAddrVal(0x0800, 0x04);
|
||||
// Assert this is an enhanced revision
|
||||
memoryDetectTestProgram.assertAddrVal(0x0801, 0x02);
|
||||
// Aser this is a 128k machine
|
||||
memoryDetectTestProgram.assertAddrVal(0x0802, 128);
|
||||
memoryDetectTestProgram.run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Adapted from Zellyn Hunder's language card test:
|
||||
* https://github.com/zellyn/a2audit/blob/main/audit/langcard.asm
|
||||
*
|
||||
* Adjusted to use JACE hooks to perform assertions and error reporting
|
||||
*/
|
||||
@Test
|
||||
public void languageCardBankswitchTest() throws ProgramException {
|
||||
TestProgram lcTestProgram = new TestProgram(MEMORY_TEST_COMMONS);
|
||||
lcTestProgram.add("""
|
||||
;; Setup - store differing values in bank first and second banked areas.
|
||||
lda $C08B ; Read and write bank 1
|
||||
lda $C08B
|
||||
lda #$11
|
||||
sta $D17B ; $D17B is $53 in Apple II/plus/e/enhanced
|
||||
cmp $D17B
|
||||
""")
|
||||
.assertEquals("E0004: We tried to put the language card into read bank 1, write bank 1, but failed to write.")
|
||||
.add("""
|
||||
lda #$33
|
||||
sta $FE1F ; FE1F is $60 in Apple II/plus/e/enhanced
|
||||
cmp $FE1F
|
||||
""")
|
||||
//
|
||||
.assertEquals("E0005: We tried to put the language card into read RAM, write RAM, but failed to write.")
|
||||
.add("""
|
||||
lda $C083 ; Read and write bank 2
|
||||
lda $C083
|
||||
lda #$22
|
||||
sta $D17B
|
||||
cmp $D17B
|
||||
""")
|
||||
.assertEquals("E0006: We tried to put the language card into read bank 2, write bank 2, but failed to write.")
|
||||
.add("""
|
||||
lda $C08B ; Read and write bank 1 with single access (only one needed if banked in already)
|
||||
lda #$11
|
||||
cmp $D17B
|
||||
""")
|
||||
.assertEquals("E000D: We tried to put the language card into read bank 1, but failed to read.")
|
||||
.add("""
|
||||
lda $C081 ; Read ROM with single access (only one needed to bank out)
|
||||
lda #$53
|
||||
cmp $D17B
|
||||
""")
|
||||
.assertEquals("E000E: We tried to put the language card into read ROM, but failed to read (from ROM).")
|
||||
.add("""
|
||||
;;; Main data-driven test. PCL,PCH holds the address of the next
|
||||
;;; data-driven test routine. We expect the various softswitches
|
||||
;;; to be reset each time we loop at .ddloop.
|
||||
.datadriventests
|
||||
lda #<.tests
|
||||
sta PCL
|
||||
lda #>.tests
|
||||
sta PCH
|
||||
;;; Main data-drive-test loop.
|
||||
.ddloop
|
||||
ldy #0
|
||||
|
||||
;; Initialize to known state:
|
||||
;; - $11 in $D17B bank 1 (ROM: $53)
|
||||
;; - $22 in $D17B bank 2 (ROM: $53)
|
||||
;; - $33 in $FE1F (ROM: $60)
|
||||
lda $C08B ; Read and write bank 1
|
||||
lda $C08B
|
||||
lda #$11
|
||||
sta $D17B
|
||||
lda #$33
|
||||
sta $FE1F
|
||||
lda $C083 ; Read and write bank 2
|
||||
lda $C083
|
||||
lda #$22
|
||||
sta $D17B
|
||||
lda $C080
|
||||
|
||||
jmp (PCL) ; Jump to test routine
|
||||
|
||||
|
||||
;; Test routine will JSR back to here, so the check data address is on the stack.
|
||||
|
||||
.test ;; ... test the quintiple of test values
|
||||
inc $D17B
|
||||
inc $FE1F
|
||||
|
||||
;; pull address off of stack: it points just below check data for this test.
|
||||
pla
|
||||
sta .checkdata
|
||||
pla
|
||||
sta .checkdata+1
|
||||
|
||||
;; .checkdata now points to d17b-current,fe1f-current,bank1,bank2,fe1f-ram test quintiple
|
||||
|
||||
;; Test current $D17B
|
||||
jsr NEXTCHECK
|
||||
cmp $D17B
|
||||
beq +
|
||||
lda $D17B
|
||||
pha
|
||||
jsr .printseq
|
||||
+print
|
||||
!text "$D17B TO CONTAIN $"
|
||||
+printed
|
||||
jsr CURCHECK
|
||||
jsr PRBYTE
|
||||
+print
|
||||
!text ", GOT $"
|
||||
+printed
|
||||
pla
|
||||
jsr PRBYTE
|
||||
lda #$8D
|
||||
jsr COUT
|
||||
jmp .datatesturl
|
||||
|
||||
+ ;; Test current $FE1F
|
||||
jsr NEXTCHECK
|
||||
cmp $FE1F
|
||||
beq +
|
||||
lda $FE1F
|
||||
pha
|
||||
jsr .printseq
|
||||
+print
|
||||
!text "$FE1F=$"
|
||||
+printed
|
||||
jsr CURCHECK
|
||||
jsr PRBYTE
|
||||
+print
|
||||
!text ", GOT $"
|
||||
+printed
|
||||
pla
|
||||
jsr PRBYTE
|
||||
lda #$8D
|
||||
jsr COUT
|
||||
jmp .datatesturl
|
||||
|
||||
+ ;; Test bank 1 $D17B
|
||||
lda $C088
|
||||
jsr NEXTCHECK
|
||||
cmp $D17B
|
||||
beq +
|
||||
lda $D17B
|
||||
pha
|
||||
jsr .printseq
|
||||
+print
|
||||
!text "$D17B IN RAM BANK 1 TO CONTAIN $"
|
||||
+printed
|
||||
jsr CURCHECK
|
||||
jsr PRBYTE
|
||||
+print
|
||||
!text ", GOT $"
|
||||
+printed
|
||||
pla
|
||||
jsr PRBYTE
|
||||
lda #$8D
|
||||
jsr COUT
|
||||
jmp .datatesturl
|
||||
|
||||
+ ;; Test bank 2 $D17B
|
||||
lda $C080
|
||||
jsr NEXTCHECK
|
||||
cmp $D17B
|
||||
beq +
|
||||
lda $D17B
|
||||
pha
|
||||
jsr .printseq
|
||||
+print
|
||||
!text "$D17B IN RAM BANK 2 TO CONTAIN $"
|
||||
+printed
|
||||
jsr CURCHECK
|
||||
jsr PRBYTE
|
||||
+print
|
||||
!text ", GOT $"
|
||||
+printed
|
||||
pla
|
||||
jsr PRBYTE
|
||||
lda #$8D
|
||||
jsr COUT
|
||||
jmp .datatesturl
|
||||
|
||||
+ ;; Test RAM $FE1F
|
||||
lda $C080
|
||||
jsr NEXTCHECK
|
||||
cmp $FE1F
|
||||
beq +
|
||||
lda $FE1F
|
||||
pha
|
||||
jsr .printseq
|
||||
+print
|
||||
!text "RAM $FE1F=$"
|
||||
+printed
|
||||
jsr CURCHECK
|
||||
jsr PRBYTE
|
||||
+print
|
||||
!text ", GOT $"
|
||||
+printed
|
||||
pla
|
||||
jsr PRBYTE
|
||||
lda #$8D
|
||||
jsr COUT
|
||||
jmp .datatesturl
|
||||
|
||||
+ ;; Jump PCL,PCH up to after the test data, and loop.
|
||||
jsr NEXTCHECK
|
||||
bne +
|
||||
+success
|
||||
+ ldx .checkdata
|
||||
ldy .checkdata+1
|
||||
stx PCL
|
||||
sty PCH
|
||||
jmp .ddloop
|
||||
|
||||
.datatesturl
|
||||
""")
|
||||
.throwError("E0007: This is a data-driven test of Language Card operation. We initialize $D17B in RAM bank 1 to $11, $D17B in RAM bank 2 to $22, and $FE1F in RAM to $33. Then, we perform a testdata-driven sequence of LDA and STA to the $C08X range. Finally we (try to) increment $D17B and $FE1F. Then we test (a) the current live value in $D17B, (b) the current live value in $FE1F, (c) the RAM bank 1 value of $D17B, (d) the RAM bank 2 value of $D17B, and (e) the RAM value of $FE1F, to see whether they match expected values. $D17B is usually $53 in ROM, and $FE1F is usally $60. For more information on the operation of the language card soft-switches, see Understanding the Apple IIe, by James Fielding Sather, Pg 5-24.")
|
||||
.add("""
|
||||
rts
|
||||
|
||||
.printseq
|
||||
+print
|
||||
!text "AFTER SEQUENCE OF:",$8D,"- LDA $C080",$8D
|
||||
+printed
|
||||
jsr PRINTTEST
|
||||
+print
|
||||
!text "- INC $D17B",$8D,"- INC $FE1F",$8D,"EXPECTED "
|
||||
+printed
|
||||
rts
|
||||
|
||||
.tests
|
||||
;; Format:
|
||||
;; Sequence of test instructions, finishing with `jsr .test`.
|
||||
;; - quint: expected current $d17b and fe1f, then d17b in bank1, d17b in bank 2, and fe1f
|
||||
;; (All sequences start with lda $C080, just to reset things to a known state.)
|
||||
;; 0-byte to terminate tests.
|
||||
|
||||
lda $C088 ; Read $C088 (RAM read, write protected)
|
||||
jsr .test ;
|
||||
!byte $11, $33, $11, $22, $33 ;
|
||||
jsr .test ;
|
||||
!byte $22, $33, $11, $22, $33 ;
|
||||
lda $C081 ; Read $C081 (ROM read, write disabled)
|
||||
jsr .test ;
|
||||
!byte $53, $60, $11, $22, $33
|
||||
lda $C081 ; Read $C081, $C089 (ROM read, bank 1 write)
|
||||
lda $C089 ;
|
||||
jsr .test ;
|
||||
!byte $53, $60, $54, $22, $61
|
||||
lda $C081 ; Read $C081, $C081 (read ROM, write RAM bank 2)
|
||||
lda $C081 ;
|
||||
jsr .test ;
|
||||
!byte $53, $60, $11, $54, $61
|
||||
lda $C081 ; Read $C081, $C081, write $C081 (read ROM, write RAM bank bank 2)
|
||||
lda $C081 ; See https://github.com/zellyn/a2audit/issues/3
|
||||
sta $C081 ;
|
||||
jsr .test ;
|
||||
!byte $53, $60, $11, $54, $61
|
||||
lda $C081 ; Read $C081, $C081; write $C081, $C081
|
||||
lda $C081 ; See https://github.com/zellyn/a2audit/issues/4
|
||||
sta $C081 ;
|
||||
sta $C081 ;
|
||||
jsr .test ;
|
||||
!byte $53, $60, $11, $54, $61
|
||||
lda $C08B ; Read $C08B (read RAM bank 1, no write)
|
||||
jsr .test ;
|
||||
!byte $11, $33, $11, $22, $33
|
||||
lda $C083 ; Read $C083 (read RAM bank 2, no write)
|
||||
jsr .test ;
|
||||
!byte $22, $33, $11, $22, $33
|
||||
lda $C08B ; Read $C08B, $C08B (read/write RAM bank 1)
|
||||
lda $C08B ;
|
||||
jsr .test ;
|
||||
!byte $12, $34, $12, $22, $34
|
||||
lda $C08F ; Read $C08F, $C087 (read/write RAM bank 2)
|
||||
lda $C087 ;
|
||||
jsr .test ;
|
||||
!byte $23, $34, $11, $23, $34
|
||||
lda $C087 ; Read $C087, read $C08D (read ROM, write bank 1)
|
||||
lda $C08D ;
|
||||
jsr .test ;
|
||||
!byte $53, $60, $54, $22, $61
|
||||
lda $C08B ; Read $C08B, write $C08B, read $C08B (read RAM bank 1, no write)
|
||||
sta $C08B ; (this one is tricky: reset WRTCOUNT by writing halfway)
|
||||
lda $C08B ;
|
||||
jsr .test ;
|
||||
!byte $11, $33, $11, $22, $33
|
||||
sta $C08B ; Write $C08B, write $C08B, read $C08B (read RAM bank 1, no write)
|
||||
sta $C08B ;
|
||||
lda $C08B ;
|
||||
jsr .test ;
|
||||
!byte $11, $33, $11, $22, $33
|
||||
clc ; Read $C083, $C083 (read/write RAM bank 2)
|
||||
ldx #0 ; Uses "6502 false read"
|
||||
inc $C083,x ;
|
||||
jsr .test ;
|
||||
!byte $23, $34, $11, $23, $34
|
||||
!byte 0
|
||||
""")
|
||||
.runForTicks(10000000);
|
||||
}
|
||||
}
|
||||
|
396
src/test/resources/jace/machine_identification.asm
Normal file
396
src/test/resources/jace/machine_identification.asm
Normal file
@ -0,0 +1,396 @@
|
||||
JSR IDENTIFY
|
||||
JMP END_DETECT_PROGRAM
|
||||
;;; From http://www.1000bit.it/support/manuali/apple/technotes/misc/tn.misc.02.html
|
||||
;;; *********************************************
|
||||
;;; * *
|
||||
;;; * Apple II Family Identification Program *
|
||||
;;; * *
|
||||
;;; * Version 2.2 *
|
||||
;;; * *
|
||||
;;; * March, 1990 *
|
||||
;;; * *
|
||||
;;; * Includes support for the Apple IIe Card *
|
||||
;;; * for the Macintosh LC. *
|
||||
;;; * *
|
||||
;;; *********************************************
|
||||
|
||||
; First, some global equates for the routine:
|
||||
IIplain = $01 ;Apple II
|
||||
IIplus = $02 ;Apple II+
|
||||
IIIem = $03 ;Apple /// in emulation mode
|
||||
IIe = $04 ;Apple IIe
|
||||
IIc = $05 ;Apple IIc
|
||||
IIeCard = $06 ;Apple IIe Card for the Macintosh LC
|
||||
|
||||
.safe = $0001 ;start of code relocated to zp
|
||||
.location = $06 ;zero page location to use
|
||||
|
||||
.test1 = $AA ;test byte #1
|
||||
.test2 = $55 ;lsr of test1
|
||||
.test3 = $88 ;test byte #3
|
||||
.test4 = $EE ;test byte #4
|
||||
|
||||
.begpage1 = $400 ;beginning of text page 1
|
||||
.begpage2 = $800 ;beginning of text page 2
|
||||
.begsprse = $C00 ;byte after text page 2
|
||||
|
||||
.clr80col = $C000 ;disable 80-column store
|
||||
.set80col = $C001 ;enable 80-column store
|
||||
.rdmainram = $C002 ;read main ram
|
||||
.rdcardram = $C003 ;read aux ram
|
||||
.wrmainram = $C004 ;write main ram
|
||||
.wrcardram = $C005 ;write aux ram
|
||||
.rdramrd = $C013 ;are we reading aux ram?
|
||||
.rdaltzp = $C016 ;are we reading aux zero page?
|
||||
.rd80col = $C018 ;are we using 80-columns?
|
||||
.rdtext = $C01A ;read if text is displayed
|
||||
.rdpage2 = $C01C ;read if page 2 is displayed
|
||||
.txtclr = $C050 ;switch in graphics
|
||||
.txtset = $C051 ;switch in text
|
||||
.txtpage1 = $C054 ;switch in page 1
|
||||
.txtpage2 = $C055 ;switch in page 2
|
||||
.ramin = $C080 ;read LC bank 2, write protected
|
||||
.romin = $C081 ;read ROM, 2 reads write enable LC
|
||||
.lcbank1 = $C08B ;LC bank 1 enable
|
||||
|
||||
.lc1 = $E000 ;bytes to save for LC
|
||||
.lc2 = $D000 ;save/restore routine
|
||||
.lc3 = $D400
|
||||
.lc4 = $D800
|
||||
|
||||
.idroutine = $FE1F ;IIgs id routine
|
||||
|
||||
; Start by saving the state of the language card banks and
|
||||
; by switching in main ROM.
|
||||
|
||||
IDENTIFY
|
||||
php ;save the processor state
|
||||
sei ;before disabling interrupts
|
||||
lda .lc1 ;save four bytes from
|
||||
sta .save ;ROM/RAM area for later
|
||||
lda .lc2 ;restoring of RAM/ROM
|
||||
sta .save+1 ;to original condition
|
||||
lda .lc3
|
||||
sta .save+2
|
||||
lda .lc4
|
||||
sta .save+3
|
||||
lda $C081 ;read ROM
|
||||
lda $C081
|
||||
lda #0 ;start by assuming unknown machine
|
||||
sta MACHINE
|
||||
sta ROMLEVEL
|
||||
.IdStart
|
||||
lda .location ;save zero page locations
|
||||
sta .save+4 ;for later restoration
|
||||
lda .location+1
|
||||
sta .save+5
|
||||
lda #$FB ;all ID bytes are in page $FB
|
||||
sta .location+1 ;save in zero page as high byte
|
||||
ldx #0 ;init pointer to start of ID table
|
||||
.loop lda .IDTable,x ;get the machine we are testing for
|
||||
sta MACHINE ;and save it
|
||||
lda .IDTable+1,x ;get the ROM level we are testing for
|
||||
sta ROMLEVEL ;and save it
|
||||
ora MACHINE ;are both zero?
|
||||
beq .matched ;yes - at end of list - leave
|
||||
|
||||
.loop2 inx ;bump index to loc/byte pair to test
|
||||
inx
|
||||
lda .IDTable,x ;get the byte that should be in ROM
|
||||
beq .matched ;if zero, we're at end of list
|
||||
sta .location ;save in zero page
|
||||
|
||||
ldy #0 ;init index for indirect addressing
|
||||
lda .IDTable+1,x ;get the byte that should be in ROM
|
||||
cmp (.location),y ;is it there?
|
||||
beq .loop2 ;yes, so keep on looping
|
||||
|
||||
.loop3 inx ;we didn't match. Scoot to the end of the
|
||||
inx ;line in the ID table so we can start
|
||||
lda .IDTable,x ;checking for another machine
|
||||
bne .loop3
|
||||
inx ;point to start of next line
|
||||
bne .loop ;should always be taken
|
||||
|
||||
.matched ; anop
|
||||
|
||||
; Here we check the 16-bit ID routine at idroutine ($FE1F). If it
|
||||
; returns with carry clear, we call it again in 16-bit
|
||||
; mode to provide more information on the machine.
|
||||
|
||||
!cpu 65816 {
|
||||
.idIIgs
|
||||
sec ;set the carry bit
|
||||
jsr .idroutine ;Apple IIgs ID Routine
|
||||
bcc .idIIgs2 ;it's a IIgs or equivalent
|
||||
jmp .IIgsOut ;nope, go check memory
|
||||
.idIIgs2
|
||||
lda MACHINE ;get the value for machine
|
||||
ora #$80 ;and set the high bit
|
||||
sta MACHINE ;put it back
|
||||
clc ;get ready to switch into native mode
|
||||
xce
|
||||
php ;save the processor status
|
||||
rep #$30 ;sets 16-bit registers
|
||||
!al { ;longa on
|
||||
!rl { ;longi on
|
||||
jsr .idroutine ;call the ID routine again
|
||||
sta .IIgsA ;16-bit store!
|
||||
stx .IIgsX ;16-bit store!
|
||||
sty .IIgsY ;16-bit store!
|
||||
plp ;restores 8-bit registers
|
||||
xce ;switches back to whatever it was before
|
||||
} ;longi off
|
||||
} ;longa off
|
||||
|
||||
ldy .IIgsY ;get the ROM vers number (starts at 0)
|
||||
cpy #$02 ;is it ROM 01 or 00?
|
||||
bcs .idIIgs3 ;if not, don't increment
|
||||
iny ;bump it up for romlevel
|
||||
.idIIgs3
|
||||
sty ROMLEVEL ;and put it there
|
||||
cpy #$01 ;is it the first ROM?
|
||||
bne .IIgsOut ;no, go on with things
|
||||
lda .IIgsY+1 ;check the other byte too
|
||||
bne .IIgsOut ;nope, it's a IIgs successor
|
||||
lda #$7F ;fix faulty ROM 00 on the IIgs
|
||||
sta .IIgsA
|
||||
.IIgsOut ; anop
|
||||
}
|
||||
|
||||
;;; ******************************************
|
||||
;;; * This part of the code checks for the *
|
||||
;;; * memory configuration of the machine. *
|
||||
;;; * If it's a IIgs, we've already stored *
|
||||
;;; * the total memory from above. If it's *
|
||||
;;; * a IIc or a IIe Card, we know it's *
|
||||
;;; * 128K; if it's a ][+, we know it's at *
|
||||
;;; * least 48K and maybe 64K. We won't *
|
||||
;;; * check for less than 48K, since that's *
|
||||
;;; * a really rare circumstance. *
|
||||
;;; ******************************************
|
||||
|
||||
.exit lda MACHINE ;get the machine kind
|
||||
bmi .exit128 ;it's a 16-bit machine (has 128K)
|
||||
cmp #IIc ;is it a IIc?
|
||||
beq .exit128 ;yup, it's got 128K
|
||||
cmp #IIeCard ;is it a IIe Card?
|
||||
beq .exit128 ;yes, it's got 128K
|
||||
cmp #IIe ;is it a IIe?
|
||||
bne .contexit ;yes, go muck with aux memory
|
||||
jmp .muckaux
|
||||
.contexit
|
||||
cmp #IIIem ;is it a /// in emulation?
|
||||
bne .exitII ;nope, it's a ][ or ][+
|
||||
lda #48 ;/// emulation has 48K
|
||||
jmp .exita
|
||||
.exit128
|
||||
lda #128 ;128K
|
||||
.exita sta MEMORY
|
||||
.exit1 lda .lc1 ;time to restore the LC
|
||||
cmp .save ;if all 4 bytes are the same
|
||||
bne .exit2 ;then LC was never on so
|
||||
lda .lc2 ;do nothing
|
||||
cmp .save+1
|
||||
bne .exit2
|
||||
lda .lc3
|
||||
cmp .save+2
|
||||
bne .exit2
|
||||
lda .lc4
|
||||
cmp .save+3
|
||||
beq .exit6
|
||||
.exit2 lda $C088 ;no match! so turn first LC
|
||||
lda .lc1 ;bank on and check
|
||||
cmp .save
|
||||
beq .exit3
|
||||
lda $C080
|
||||
jmp .exit6
|
||||
.exit3 lda .lc2
|
||||
cmp .save+1 ;if all locations check
|
||||
beq .exit4 ;then do more more else
|
||||
lda $C080 ;turn on bank 2
|
||||
jmp .exit6
|
||||
.exit4 lda .lc3 ;check second byte in bank 1
|
||||
cmp .save+2
|
||||
beq .exit5
|
||||
lda $C080 ;select bank 2
|
||||
jmp .exit6
|
||||
.exit5 lda .lc4 ;check third byte in bank 1
|
||||
cmp .save+3
|
||||
beq .exit6
|
||||
lda $C080 ;select bank 2
|
||||
.exit6 plp ;restore interrupt status
|
||||
lda .save+4 ;put zero page back
|
||||
sta .location
|
||||
lda .save+5 ;like we found it
|
||||
sta .location+1
|
||||
rts ;and go home.
|
||||
|
||||
.exitII
|
||||
lda .lcbank1 ;force in language card
|
||||
lda .lcbank1 ;bank 1
|
||||
ldx .lc2 ;save the byte there
|
||||
lda #.test1 ;use this as a test byte
|
||||
sta .lc2
|
||||
eor .lc2 ;if the same, should return zero
|
||||
bne .noLC
|
||||
lsr .lc2 ;check twice just to be sure
|
||||
lda #.test2 ;this is the shifted value
|
||||
eor .lc2 ;here's the second check
|
||||
bne .noLC
|
||||
stx .lc2 ;put it back!
|
||||
lda #64 ;there's 64K here
|
||||
jmp .exita
|
||||
.noLC lda #48 ;no restore - no LC!
|
||||
jmp .exita ;and get out of here
|
||||
|
||||
.muckaux
|
||||
ldx .rdtext ;remember graphics in X
|
||||
lda .rdpage2 ;remember current video display
|
||||
asl ;in the carry bit
|
||||
lda #.test3 ;another test character
|
||||
bit .rd80col ;remember video mode in N
|
||||
sta .set80col ;enable 80-column store
|
||||
php ;save N and C flags
|
||||
sta .txtpage2 ;set page two
|
||||
sta .txtset ;set text
|
||||
ldy .begpage1 ;save first character
|
||||
sta .begpage1 ;and replace it with test character
|
||||
lda .begpage1 ;get it back
|
||||
sty .begpage1 ;and put back what was there
|
||||
plp
|
||||
bcs .muck2 ;stay in page 2
|
||||
sta .txtpage1 ;restore page 1
|
||||
.muck1 bmi .muck2 ;stay in 80-columns
|
||||
sta $c000 ;turn off 80-columns
|
||||
.muck2 tay ;save returned character
|
||||
txa ;get graphics/text setting
|
||||
bmi .muck3
|
||||
sta .txtclr ;turn graphics back on
|
||||
.muck3 cpy #.test3 ;finally compare it
|
||||
bne .nocard ;no 80-column card!
|
||||
lda .rdramrd ;is aux memory being read?
|
||||
bmi .muck128 ;yup, there's 128K!
|
||||
lda .rdaltzp ;is aux zero page used?
|
||||
bmi .muck128 ;yup!
|
||||
ldy #.done-.start
|
||||
.move ldx .start-1,y ;swap section of zero page
|
||||
lda <.safe-1,y ;code needing safe location during
|
||||
stx <.safe-1,y ;reading of aux mem
|
||||
sta .start-1,Y
|
||||
dey
|
||||
bne .move
|
||||
jmp .safe ;jump to safe ground
|
||||
.back php ;save status
|
||||
ldy #.done-.start ;move zero page back
|
||||
.move2 lda .start-1,y
|
||||
sta .safe-1,y
|
||||
dey
|
||||
bne .move2
|
||||
pla
|
||||
bcs .noaux
|
||||
.isaux jmp .muck128 ;there is 128K
|
||||
|
||||
;;; * You can put your own routine at "noaux" if you wish to
|
||||
;;; * distinguish between 64K without an 80-column card and
|
||||
;;; * 64K with an 80-column card.
|
||||
|
||||
.noaux ; anop
|
||||
.nocard lda #64 ;only 64K
|
||||
jmp .exita
|
||||
.muck128
|
||||
jmp .exit128 ;there's 128K
|
||||
|
||||
;;; * This is the routine run in the safe area not affected
|
||||
;;; * by bank-switching the main and aux RAM.
|
||||
|
||||
.start lda #.test4 ;yet another test byte
|
||||
sta .wrcardram ;write to aux while on main zero page
|
||||
sta .rdcardram ;read aux ram as well
|
||||
sta .begpage2 ;check for sparse memory mapping
|
||||
lda .begsprse ;if sparse, these will be the same
|
||||
cmp #.test4 ;value since they're 1K apart
|
||||
bne .auxmem ;yup, there's 128K!
|
||||
asl .begsprse ;may have been lucky so we'll
|
||||
lda .begpage2 ;change the value and see what happens
|
||||
cmp .begsprse
|
||||
bne .auxmem
|
||||
sec ;oops, no auxiliary memory
|
||||
bcs .goback
|
||||
.auxmem clc
|
||||
.goback sta .wrmainram ;write main RAM
|
||||
sta .rdmainram ;read main RAM
|
||||
jmp .back ;continue with program in main mem
|
||||
.done nop ;end of relocated program marker
|
||||
|
||||
|
||||
;;; * The storage locations for the returned machine ID:
|
||||
|
||||
.IIgsA !word 0 ;16-bit field
|
||||
.IIgsX !word 0 ;16-bit field
|
||||
.IIgsY !word 0 ;16-bit field
|
||||
.save !fill 6,0 ;six bytes for saved data
|
||||
|
||||
.IDTable
|
||||
;dc I1'1,1' ;Apple ][
|
||||
;dc H'B3 38 00'
|
||||
!byte 1,1
|
||||
!byte $B3,$38,0
|
||||
|
||||
;dc I1'2,1' ;Apple ][+
|
||||
;dc H'B3 EA 1E AD 00'
|
||||
!byte 2,1
|
||||
!byte $B3,$EA,$1E,$AD,0
|
||||
|
||||
;dc I1'3,1' ;Apple /// (emulation)
|
||||
;dc H'B3 EA 1E 8A 00'
|
||||
!byte 3,1
|
||||
!byte $B3,$EA,$1E,$8A,0
|
||||
|
||||
;dc I1'4,1' ;Apple IIe (original)
|
||||
;dc H'B3 06 C0 EA 00'
|
||||
!byte 4,1
|
||||
!byte $B3,$06,$C0,$EA,0
|
||||
|
||||
; Note: You must check for the Apple IIe Card BEFORE you
|
||||
; check for the enhanced Apple IIe since the first
|
||||
; two identification bytes are the same.
|
||||
|
||||
;dc I1'6,1' ;Apple IIe Card for the Macintosh LC (1st release)
|
||||
;dc H'B3 06 C0 E0 DD 02 BE 00 00'
|
||||
!byte 6,1
|
||||
!byte $B3,$06,$C0,$E0,$DD,$02,$BE,$00,0
|
||||
|
||||
;dc I1'4,2' ;Apple IIe (enhanced)
|
||||
;dc H'B3 06 C0 E0 00'
|
||||
!byte 4,2
|
||||
!byte $B3,$06,$C0,$E0,0
|
||||
|
||||
;dc I1'5,1' ;Apple IIc (original)
|
||||
;dc H'B3 06 C0 00 BF FF 00'
|
||||
!byte 5,1
|
||||
!byte $B3,$06,$C0,$00,$BF,$FF,0
|
||||
|
||||
;dc I1'5,2' ;Apple IIc (3.5 ROM)
|
||||
;dc H'B3 06 C0 00 BF 00 00'
|
||||
!byte 5,2
|
||||
!byte $B3,$06,$C0,$00,$BF,$00,0
|
||||
|
||||
;dc I1'5,3' ;Apple IIc (Mem. Exp)
|
||||
;dc H'B3 06 C0 00 BF 03 00'
|
||||
!byte 5,3
|
||||
!byte $B3,$06,$C0,$00,$BF,$03,0
|
||||
|
||||
;dc I1'5,4' ;Apple IIc (Rev. Mem. Exp.)
|
||||
;dc H'B3 06 C0 00 BF 04 00'
|
||||
!byte 5,4
|
||||
!byte $B3,$06,$C0,$00,$BF,$04,0
|
||||
|
||||
;dc I1'5,5' ;Apple IIc Plus
|
||||
;dc H'B3 06 C0 00 BF 05 00'
|
||||
!byte 5,5
|
||||
!byte $B3,$06,$C0,$00,$BF,$05,0
|
||||
|
||||
;dc I1'0,0' ;end of table
|
||||
!byte 0,0
|
||||
END_DETECT_PROGRAM
|
204
src/test/resources/jace/memory_test_commons.asm
Normal file
204
src/test/resources/jace/memory_test_commons.asm
Normal file
@ -0,0 +1,204 @@
|
||||
jmp START
|
||||
MACHINE = $800 ;the type of Apple II
|
||||
ROMLEVEL = $801 ;which revision of the machine
|
||||
MEMORY = $802 ;how much memory (up to 128K)
|
||||
|
||||
LCRESULT = $10
|
||||
LCRESULT1 = $11
|
||||
|
||||
lda #0
|
||||
sta LCRESULT
|
||||
|
||||
;; Zero-page locations.
|
||||
SCRATCH = $1
|
||||
SCRATCH2 = $2
|
||||
SCRATCH3 = $3
|
||||
LCRESULT = $10
|
||||
LCRESULT1 = $11
|
||||
AUXRESULT = $12
|
||||
SOFTSWITCHRESULT = $13
|
||||
|
||||
CSW = $36
|
||||
KSW = $38
|
||||
|
||||
PCL=$3A
|
||||
PCH=$3B
|
||||
A1L=$3C
|
||||
A1H=$3D
|
||||
A2L=$3E
|
||||
A2H=$3F
|
||||
A3L=$40
|
||||
A3H=$41
|
||||
A4L=$42
|
||||
A4H=$43
|
||||
|
||||
!addr tmp0 = $f9
|
||||
!addr tmp1 = $fa
|
||||
!addr tmp2 = $fb
|
||||
!addr tmp3 = $fc
|
||||
!addr tmp4 = $fd
|
||||
!addr tmp5 = $fe
|
||||
!addr tmp6 = $ff
|
||||
.checkdata = tmp1
|
||||
|
||||
STRINGS = $8000
|
||||
!set LASTSTRING = STRINGS
|
||||
|
||||
KBD = $C000
|
||||
KBDSTRB = $C010
|
||||
|
||||
;; Monitor locations.
|
||||
;HOME = $FC58
|
||||
COUT = $FDED
|
||||
COUT1 = $FDF0
|
||||
KEYIN = $FD1B
|
||||
CROUT = $FD8E
|
||||
PRBYTE = $FDDA
|
||||
PRNTYX = $F940
|
||||
|
||||
;; Softswitch locations.
|
||||
RESET_80STORE = $C000
|
||||
SET_80STORE = $C001
|
||||
READ_80STORE = $C018
|
||||
|
||||
RESET_RAMRD = $C002
|
||||
SET_RAMRD = $C003
|
||||
READ_RAMRD = $C013
|
||||
|
||||
RESET_RAMWRT = $C004
|
||||
SET_RAMWRT = $C005
|
||||
READ_RAMWRT = $C014
|
||||
|
||||
RESET_INTCXROM = $C006
|
||||
SET_INTCXROM = $C007
|
||||
READ_INTCXROM = $C015
|
||||
|
||||
RESET_ALTZP = $C008
|
||||
SET_ALTZP = $C009
|
||||
READ_ALTZP = $C016
|
||||
|
||||
RESET_SLOTC3ROM = $C00A
|
||||
SET_SLOTC3ROM = $C00B
|
||||
READ_SLOTC3ROM = $C017
|
||||
|
||||
RESET_80COL = $C00C
|
||||
SET_80COL = $C00D
|
||||
READ_80COL = $C01F
|
||||
|
||||
RESET_ALTCHRSET = $C00E
|
||||
SET_ALTCHRSET = $C00F
|
||||
READ_ALTCHRSET = $C01E
|
||||
|
||||
RESET_TEXT = $C050
|
||||
SET_TEXT = $C051
|
||||
READ_TEXT = $C01A
|
||||
|
||||
RESET_MIXED = $C052
|
||||
SET_MIXED = $C053
|
||||
READ_MIXED = $C01B
|
||||
|
||||
RESET_PAGE2 = $C054
|
||||
SET_PAGE2 = $C055
|
||||
READ_PAGE2 = $C01C
|
||||
|
||||
RESET_HIRES = $C056
|
||||
SET_HIRES = $C057
|
||||
READ_HIRES = $C01D
|
||||
|
||||
RESET_AN3 = $C05E
|
||||
SET_AN3 = $C05F
|
||||
|
||||
RESET_INTC8ROM = $CFFF
|
||||
|
||||
;; Readable things without corresponding set/reset pairs.
|
||||
READ_HRAM_BANK2 = $C011
|
||||
READ_HRAMRD = $C012
|
||||
READ_VBL = $C019
|
||||
|
||||
print
|
||||
lda $C081
|
||||
lda $C081
|
||||
pla
|
||||
sta getch+1
|
||||
pla
|
||||
sta getch+2
|
||||
- inc getch+1
|
||||
bne getch
|
||||
inc getch+2
|
||||
getch lda $FEED ; FEED gets modified
|
||||
beq +
|
||||
jsr COUT
|
||||
jmp -
|
||||
+ rts
|
||||
|
||||
PRINTTEST
|
||||
-
|
||||
ldy #0
|
||||
lda (PCL),y
|
||||
cmp #$20
|
||||
beq +++
|
||||
lda #'-'
|
||||
jsr COUT
|
||||
lda #' '
|
||||
jsr COUT
|
||||
ldx #0
|
||||
lda (PCL,x)
|
||||
jsr $f88e
|
||||
ldx #3
|
||||
jsr $f8ea
|
||||
jsr $f953
|
||||
sta PCL
|
||||
sty PCH
|
||||
lda #$8D
|
||||
jsr COUT
|
||||
jmp -
|
||||
+++ rts
|
||||
|
||||
;;; Increment .checkdata pointer to the next memory location, and load
|
||||
;;; it into the accumulator. X and Y are preserved.
|
||||
NEXTCHECK
|
||||
inc .checkdata
|
||||
bne CURCHECK
|
||||
inc .checkdata+1
|
||||
CURCHECK
|
||||
sty SCRATCH
|
||||
ldy #0
|
||||
lda (.checkdata),y
|
||||
ldy SCRATCH
|
||||
ora #0
|
||||
rts
|
||||
|
||||
!macro print {
|
||||
jsr LASTSTRING
|
||||
!set TEMP = *
|
||||
* = LASTSTRING
|
||||
jsr print
|
||||
}
|
||||
!macro printed {
|
||||
!byte 0
|
||||
!set LASTSTRING=*
|
||||
* = TEMP
|
||||
}
|
||||
|
||||
START
|
||||
;;; Reset all soft-switches to known-good state. Burns $300 and $301 in main mem.
|
||||
RESETALL
|
||||
; The COUT hook isn't set up yet, so the monitor routine will crash unless we set it up
|
||||
lda #<COUT1
|
||||
sta CSW
|
||||
lda #>COUT1
|
||||
sta CSW+1
|
||||
sta RESET_RAMRD
|
||||
sta RESET_RAMWRT
|
||||
;; Save return address in X and A, in case we switch zero-page memory.
|
||||
sta RESET_80STORE
|
||||
sta RESET_INTCXROM
|
||||
sta RESET_ALTZP
|
||||
sta RESET_SLOTC3ROM
|
||||
sta RESET_INTC8ROM
|
||||
sta RESET_80COL
|
||||
sta RESET_ALTCHRSET
|
||||
sta SET_TEXT
|
||||
sta RESET_MIXED
|
||||
sta RESET_PAGE2
|
||||
sta RESET_HIRES
|
Loading…
Reference in New Issue
Block a user