diff --git a/src/main/java/jace/apple2e/RAM128k.java b/src/main/java/jace/apple2e/RAM128k.java index 9fd00e7..4fb8320 100644 --- a/src/main/java/jace/apple2e/RAM128k.java +++ b/src/main/java/jace/apple2e/RAM128k.java @@ -194,9 +194,9 @@ abstract public class RAM128k extends RAM { public String getReadConfiguration() { String rstate = ""; if (SoftSwitches.RAMRD.getState()) { - rstate += "Ra"; + rstate += "Ra_"; } else { - rstate += "R0"; + rstate += "R0_"; } String LCR = "L0R"; if (SoftSwitches.LCRAM.isOn()) { @@ -214,16 +214,16 @@ abstract public class RAM128k extends RAM { } rstate += LCR; if (SoftSwitches.CXROM.getState()) { - rstate += "CXROM"; + rstate += "_CXROM"; } else { - rstate += "!CX"; + rstate += "_!CX"; if (SoftSwitches.SLOTC3ROM.isOff()) { - rstate += "C3"; + rstate += "_C3"; } if (SoftSwitches.INTC8ROM.isOn()) { - rstate += "C8"; + rstate += "_C8"; } else { - rstate += "C8"+getActiveSlot(); + rstate += "_C8"+getActiveSlot(); } } @@ -233,9 +233,9 @@ abstract public class RAM128k extends RAM { public String getWriteConfiguration() { String wstate = ""; if (SoftSwitches.RAMWRT.getState()) { - wstate += "Wa"; + wstate += "Wa_"; } else { - wstate += "W0"; + wstate += "W0_"; } String LCW = "L0W"; if (SoftSwitches.LCWRITE.isOn()) { @@ -256,22 +256,26 @@ abstract public class RAM128k extends RAM { } public String getAuxZPConfiguration() { - String astate = ""; + String astate = "__"; if (SoftSwitches._80STORE.isOn()) { - astate += "80S"; + astate += "80S_"; if (SoftSwitches.PAGE2.isOn()) { - astate += "2"; + astate += "P2_"; + } else { + astate += "P1_"; } if (SoftSwitches.HIRES.isOn()) { - astate += "H"; + astate += "H1_"; + } else { + astate += "H0_"; } } // Handle zero-page bankswitching if (SoftSwitches.AUXZP.getState()) { - astate += "Za"; + astate += "Za_"; } else { - astate += "Z0"; + astate += "Z0_"; } return astate; } @@ -417,7 +421,8 @@ abstract public class RAM128k extends RAM { state = newState; log("MMU Switches"); - + // System.out.println("read: " + readConfiguration); + // System.out.println("write: " + writeConfiguration); if (memoryConfigurations.containsKey(readConfiguration)) { activeRead = memoryConfigurations.get(readConfiguration); } else { diff --git a/src/main/java/jace/apple2e/SoftSwitches.java b/src/main/java/jace/apple2e/SoftSwitches.java index f366348..2fc5bd0 100644 --- a/src/main/java/jace/apple2e/SoftSwitches.java +++ b/src/main/java/jace/apple2e/SoftSwitches.java @@ -74,11 +74,20 @@ public enum SoftSwitches { if (_80STORE.isOn()) { Emulator.withMemory(m->m.configureActiveMemory()); } else { - Emulator.withVideo(v->v.configureVideoMode()); + super.stateChanged(); } } }), - HIRES(new VideoSoftSwitch("Hires", 0x0c056, 0x0c057, 0x0c01d, RAMEvent.TYPE.ANY, false)), + HIRES(new VideoSoftSwitch("Hires", 0x0c056, 0x0c057, 0x0c01d, RAMEvent.TYPE.ANY, false) { + @Override + public void stateChanged() { + // PAGE2 is a hybrid switch; 80STORE ? memory : video + if (_80STORE.isOn()) { + Emulator.withMemory(m->m.configureActiveMemory()); + } + super.stateChanged(); + } + }), DHIRES(new VideoSoftSwitch("Double-hires", 0x0c05f, 0x0c05e, 0x0c07f, RAMEvent.TYPE.ANY, false)), PB0(new MemorySoftSwitch("Pushbutton0", -1, -1, 0x0c061, RAMEvent.TYPE.ANY, null)), PB1(new MemorySoftSwitch("Pushbutton1", -1, -1, 0x0c062, RAMEvent.TYPE.ANY, null)), diff --git a/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java b/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java index 4714511..c217be2 100644 --- a/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java +++ b/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java @@ -38,7 +38,7 @@ public class MemorySoftSwitch extends SoftSwitch { @Override public void stateChanged() { -// System.out.println(getName()+ " was switched to "+getState()); + // System.out.println(getName()+ " was switched to "+getState()); Emulator.withMemory(m->m.configureActiveMemory()); } diff --git a/src/main/java/jace/hardware/CardMockingboard.java b/src/main/java/jace/hardware/CardMockingboard.java index 701c80e..73ee56b 100644 --- a/src/main/java/jace/hardware/CardMockingboard.java +++ b/src/main/java/jace/hardware/CardMockingboard.java @@ -140,6 +140,9 @@ public class CardMockingboard extends Card { @Override protected void handleFirmwareAccess(int register, TYPE type, int value, RAMEvent e) { + if (type == TYPE.READ_FAKE) { + return; + } if (chips == null) { reconfigure(); } diff --git a/src/test/java/jace/core/MemoryTest.java b/src/test/java/jace/core/MemoryTest.java index b62a155..c9c5dc7 100644 --- a/src/test/java/jace/core/MemoryTest.java +++ b/src/test/java/jace/core/MemoryTest.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; +import java.text.MessageFormat; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Before; @@ -36,6 +37,7 @@ import jace.TestProgram; import jace.apple2e.MOS65C02; import jace.apple2e.RAM128k; import jace.apple2e.SoftSwitches; +import jace.core.RAMEvent.TYPE; /** * Test that memory listeners fire appropriately. @@ -68,9 +70,13 @@ public class MemoryTest { } @Before - public void setup() { + public void resetEmulator() { computer.pause(); cpu.clearState(); + } + + @Before + public void resetSoftSwitches() { // Reset softswitches for (SoftSwitches softswitch : SoftSwitches.values()) { softswitch.getSwitch().reset(); @@ -229,7 +235,6 @@ public class MemoryTest { 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 @@ -513,4 +518,68 @@ public class MemoryTest { SoftSwitches._80STORE.getSwitch().setState(true); languageCardBankswitchTest(); } + + public record MemoryTestCase(int[] softswitches, byte... expected) {} + + int[] testLocations = { + 0x0FF, 0x100, 0x200, 0x3FF, 0x427, 0x7FF, 0x800, 0x1FFF, + 0x2000, 0x3FFF, 0x4000, 0x5FFF, 0xBFFF + }; + private void assertMemoryTest(MemoryTestCase testCase) { + // Set the values in memory in main and aux banks + // This is done directly to ensure the values are exactly as expected + // The next tests will try to read these values using the softswitches + for (int location : testLocations) { + ((RAM128k) ram).getMainMemory().writeByte(location, (byte) 1); + ((RAM128k) ram).getAuxMemory().writeByte(location, (byte) 3); + } + resetSoftSwitches(); + + for (int softswitch : testCase.softswitches) { + System.out.println("Setting softswitch " + Integer.toHexString(softswitch)); + ram.write(softswitch, (byte) 0, true, false); + } + for (int i=0; i < testLocations.length; i++) { + int address = testLocations[i]; + byte current = ram.read(address, TYPE.READ_DATA, false, false); + ram.write(address, (byte) (current+1), false, false); + byte expected = testCase.expected[i]; + try { + assertEquals("Unexpected value at " + Integer.toHexString(address), expected, ram.read(address, TYPE.READ_DATA, false, false)); + } catch (AssertionError err) { + for (SoftSwitches softswitch : SoftSwitches.values()) { + System.out.println(MessageFormat.format("{0}\t{1}", softswitch.name(), (softswitch.isOn() ? "on" : "off"))); + } + throw err; + } + } + } + + @Test + public void auxBankSwitchTest() throws ProgramException { + byte M1 = (byte) 1; // Main + no change + byte M2 = (byte) 2; // Main + 1 + byte A1 = (byte) 3; // Aux + no change + byte A2 = (byte) 4; // Aux + 1 + + // 80 STORE + RAMWRT + HIRES / Page 1 (Main mem) + assertMemoryTest(new MemoryTestCase(new int[] {0x0C005, 0x0C001, 0x0C057}, + M2, M2, M1, M1, M2, M2, M1, M1, M2, M2, M1, M1, M1)); + + // RAMRD + AUXZP + assertMemoryTest(new MemoryTestCase(new int[] {0xC003, 0xC009}, + A2, A2, A1, A1, A1, A1, A1, A1, A1, A1, A1, A1, A1)); + + // RAMRD + MAINZP + assertMemoryTest(new MemoryTestCase(new int[] {0xC003, 0xC008}, + M2, M2, A1, A1, A1, A1, A1, A1, A1, A1, A1, A1, A1)); + + // 80 STORE + HIRES' + Page 2 + assertMemoryTest(new MemoryTestCase(new int[] {0x0C001, 0x0C056, 0x0C055}, + M2, M2, M2, M2, A2, A2, M2, M2, M2, M2, M2, M2, M2)); + + // 80 STORE + HIRES + Page 2 + assertMemoryTest(new MemoryTestCase(new int[] {0x0C001, 0x0C057, 0x0C055}, + M2, M2, M2, M2, A2, A2, M2, M2, A2, A2, M2, M2, M2)); + } }