diff --git a/src/main/java/jace/applesoft/ApplesoftProgram.java b/src/main/java/jace/applesoft/ApplesoftProgram.java index 6d6c98f..c40e0a7 100755 --- a/src/main/java/jace/applesoft/ApplesoftProgram.java +++ b/src/main/java/jace/applesoft/ApplesoftProgram.java @@ -66,10 +66,6 @@ public class ApplesoftProgram { return bytes; } - public static ApplesoftProgram fromBinary(List binary) { - return fromBinary(binary, 0x0801); - } - public static ApplesoftProgram fromMemory(RAM memory) { int startAddress = memory.readWordRaw(startingAddressPointer); int nextCheck = memory.readWordRaw(startAddress); @@ -84,6 +80,10 @@ public class ApplesoftProgram { return fromBinary(bytes, startAddress); } + public static ApplesoftProgram fromBinary(List binary) { + return fromBinary(binary, 0x0801); + } + public static ApplesoftProgram fromBinary(List binary, int startAddress) { ApplesoftProgram program = new ApplesoftProgram(); int currentAddress = startAddress; diff --git a/src/main/java/jace/applesoft/Command.java b/src/main/java/jace/applesoft/Command.java index ec006af..a48bdbc 100755 --- a/src/main/java/jace/applesoft/Command.java +++ b/src/main/java/jace/applesoft/Command.java @@ -143,8 +143,8 @@ public class Command { for (TOKEN t : values()) { int i = start; boolean found = true; - for (int j = 0; j < t.toString().length() && j + i < search.length(); j++) { - while (search.charAt(j + i) == ' ') { + for (int j = 0; j < t.toString().length(); j++) { + while (i+j < search.length() && search.charAt(j + i) == ' ') { i++; } if (i + j >= search.length() diff --git a/src/main/java/jace/applesoft/Line.java b/src/main/java/jace/applesoft/Line.java index 103c5cd..d7fb860 100755 --- a/src/main/java/jace/applesoft/Line.java +++ b/src/main/java/jace/applesoft/Line.java @@ -154,7 +154,6 @@ public class Line { Command currentCommand = new Command(); l.commands.add(currentCommand); l.length = 4; - lineString = lineString.trim(); String upperLineString = lineString.toUpperCase(); for (int i = 0; i < lineString.length(); i++) { if (!hasLineNumber) { @@ -183,24 +182,23 @@ public class Line { Command.ByteOrToken part = new Command.ByteOrToken(TOKEN.PRINT); currentCommand.parts.add(part); l.length++; + } else if (lineString.charAt(i) == ' ') { + continue; } else { TOKEN match = Command.TOKEN.findMatch(upperLineString, i); if (match != null) { - if (match == TOKEN.REM) { - isComment = true; - } Command.ByteOrToken part = new Command.ByteOrToken(match); currentCommand.parts.add(part); - for (int j=0; j+i <= match.toString().length(); j++) { - while (lineString.charAt(i+j) == ' ') { + if (match == TOKEN.REM || match == TOKEN.DATA) { + isComment = true; + } + for (int j=0; j < match.toString().length(); j++, i++) { + while (i < lineString.length() && lineString.charAt(i) == ' ') { i++; } } - i += match.toString().length() - 1; - if (isComment) { - while (i+1 < lineString.length() && lineString.charAt(i+1) == ' ') { - i++; - } + if (!isComment) { + i--; } l.length++; } else { diff --git a/src/main/java/jace/core/Keyboard.java b/src/main/java/jace/core/Keyboard.java index 7820dc4..5f9ec9d 100644 --- a/src/main/java/jace/core/Keyboard.java +++ b/src/main/java/jace/core/Keyboard.java @@ -95,7 +95,7 @@ public class Keyboard implements Reconfigurable { registerKeyHandler(new KeyHandler(code) { @Override public boolean handleKeyUp(KeyEvent e) { - if (!action.notifyOnRelease()) { + if (action == null || !action.notifyOnRelease()) { return false; } // System.out.println("Key up: "+method.toString()); @@ -131,7 +131,7 @@ public class Keyboard implements Reconfigurable { if (returnValue != null) { return (Boolean) returnValue; } - return action.consumeKeyEvent(); + return action != null ? action.consumeKeyEvent() : null; } }, owner); } diff --git a/src/test/java/jace/ide/ApplesoftTest.java b/src/test/java/jace/ide/ApplesoftTest.java new file mode 100644 index 0000000..13277da --- /dev/null +++ b/src/test/java/jace/ide/ApplesoftTest.java @@ -0,0 +1,85 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package jace.ide; + +import com.google.common.collect.Lists; +import jace.Emulator; +import jace.apple2e.Apple2e; +import jace.applesoft.ApplesoftProgram; +import jace.core.Video; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import javafx.scene.image.WritableImage; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author blurry + */ +public class ApplesoftTest { + + public ApplesoftTest() { + } + + static Byte[] lemonadeStandBinary; + + @BeforeClass + public static void setUpClass() throws URISyntaxException, IOException { +// Emulator.computer = new Apple2e(); +// Emulator.computer.card6.setValue(null); +// Emulator.computer.card7.setValue(null); + + byte[] lemonadeStand = readBinary("/jace/lemonade_stand.bin"); + lemonadeStandBinary = ApplesoftProgram.toObjects(lemonadeStand); + } + + public static byte[] readBinary(String path) throws IOException, URISyntaxException { + Path resource = Paths.get(ApplesoftTest.class.getResource(path).toURI()); + return Files.readAllBytes(resource); + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + @Test + public void deserializeBinary() { + ApplesoftProgram program = ApplesoftProgram.fromBinary(Lists.newArrayList(lemonadeStandBinary), 0x0801); + assertNotNull(program); + assertNotSame("", program.toString()); + } + + @Test + public void roundTripStringComparison() { + ApplesoftProgram program = ApplesoftProgram.fromBinary(Lists.newArrayList(lemonadeStandBinary), 0x0801); + String serialized = program.toString(); + ApplesoftProgram deserialized = ApplesoftProgram.fromString(serialized); + String[] serializedLines = serialized.split("\\n"); + String[] researializedLines = deserialized.toString().split("\\n"); + for (int i=0; i < serializedLines.length; i++) { + assertEquals("Line "+(i+1)+" should match", serializedLines[i], researializedLines[i]); + } + } +} diff --git a/src/test/resources/jace/lemonade_stand.bin b/src/test/resources/jace/lemonade_stand.bin new file mode 100755 index 0000000..d5d165c Binary files /dev/null and b/src/test/resources/jace/lemonade_stand.bin differ