mirror of https://github.com/badvision/jace.git
Live Coding support for Applesoft basic! :D
This commit is contained in:
parent
0b696a2379
commit
29161bcf7e
|
@ -20,6 +20,8 @@ package jace.applesoft;
|
||||||
|
|
||||||
import jace.Emulator;
|
import jace.Emulator;
|
||||||
import jace.core.RAM;
|
import jace.core.RAM;
|
||||||
|
import jace.core.RAMEvent;
|
||||||
|
import jace.core.RAMListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
@ -29,6 +31,7 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode an applesoft program into a list of program lines Right now this is an
|
* Decode an applesoft program into a list of program lines Right now this is an
|
||||||
|
@ -45,7 +48,12 @@ public class ApplesoftProgram {
|
||||||
public static final int VARIABLE_TABLE = 0x069;
|
public static final int VARIABLE_TABLE = 0x069;
|
||||||
public static final int ARRAY_TABLE = 0x06b;
|
public static final int ARRAY_TABLE = 0x06b;
|
||||||
public static final int VARIABLE_TABLE_END = 0x06d;
|
public static final int VARIABLE_TABLE_END = 0x06d;
|
||||||
|
public static final int STRING_TABLE = 0x06f;
|
||||||
|
public static final int HIMEM = 0x073;
|
||||||
public static final int BASIC_RUN = 0x0e000;
|
public static final int BASIC_RUN = 0x0e000;
|
||||||
|
public static final int RUNNING_FLAG = 0x076;
|
||||||
|
public static final int NOT_RUNNING = 0x0FF;
|
||||||
|
public static final int GOTO_CMD = 0x0D944; //actually starts at D93E
|
||||||
int startingAddress = 0x0801;
|
int startingAddress = 0x0801;
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
|
@ -143,9 +151,25 @@ public class ApplesoftProgram {
|
||||||
public void run() {
|
public void run() {
|
||||||
RAM memory = Emulator.computer.memory;
|
RAM memory = Emulator.computer.memory;
|
||||||
Emulator.computer.pause();
|
Emulator.computer.pause();
|
||||||
|
int programStart = memory.readWordRaw(START_OF_PROG_POINTER);
|
||||||
|
int programEnd = programStart + getProgramSize();
|
||||||
|
if (isProgramRunning()) {
|
||||||
|
whenReady(()->{
|
||||||
|
relocateVariables(programEnd);
|
||||||
|
injectProgram();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
injectProgram();
|
||||||
|
clearVariables(programEnd);
|
||||||
|
}
|
||||||
|
Emulator.computer.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void injectProgram() {
|
||||||
|
RAM memory = Emulator.computer.memory;
|
||||||
int pos = memory.readWordRaw(START_OF_PROG_POINTER);
|
int pos = memory.readWordRaw(START_OF_PROG_POINTER);
|
||||||
for (Line line : lines) {
|
for (Line line : lines) {
|
||||||
int nextPos = pos + line.getLength() + 1;
|
int nextPos = pos + line.getLength();
|
||||||
memory.writeWord(pos, nextPos, false, true);
|
memory.writeWord(pos, nextPos, false, true);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
memory.writeWord(pos, line.getNumber(), false, true);
|
memory.writeWord(pos, line.getNumber(), false, true);
|
||||||
|
@ -165,10 +189,31 @@ public class ApplesoftProgram {
|
||||||
memory.write(pos++, (byte) 0, false, true);
|
memory.write(pos++, (byte) 0, false, true);
|
||||||
memory.write(pos++, (byte) 0, false, true);
|
memory.write(pos++, (byte) 0, false, true);
|
||||||
memory.write(pos++, (byte) 0, false, true);
|
memory.write(pos++, (byte) 0, false, true);
|
||||||
memory.write(pos++, (byte) 0, false, true);
|
memory.write(pos++, (byte) 0, false, true);
|
||||||
clearVariables(pos);
|
}
|
||||||
// Emulator.computer.cpu.setProgramCounter(BASIC_RUN);
|
|
||||||
Emulator.computer.resume();
|
private boolean isProgramRunning() {
|
||||||
|
RAM memory = Emulator.computer.memory;
|
||||||
|
return (memory.readRaw(RUNNING_FLAG) & 0x0FF) != NOT_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the program is running, wait until it advances to the next line
|
||||||
|
*/
|
||||||
|
private void whenReady(Runnable r) {
|
||||||
|
RAM memory = Emulator.computer.memory;
|
||||||
|
memory.addListener(new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
|
||||||
|
@Override
|
||||||
|
protected void doConfig() {
|
||||||
|
setScopeStart(GOTO_CMD);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doEvent(RAMEvent e) {
|
||||||
|
r.run();
|
||||||
|
memory.removeListener(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,6 +226,32 @@ public class ApplesoftProgram {
|
||||||
memory.writeWord(ARRAY_TABLE, programEnd, false, true);
|
memory.writeWord(ARRAY_TABLE, programEnd, false, true);
|
||||||
memory.writeWord(VARIABLE_TABLE, programEnd, false, true);
|
memory.writeWord(VARIABLE_TABLE, programEnd, false, true);
|
||||||
memory.writeWord(VARIABLE_TABLE_END, programEnd, false, true);
|
memory.writeWord(VARIABLE_TABLE_END, programEnd, false, true);
|
||||||
|
memory.writeWord(END_OF_PROG_POINTER, programEnd, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move variables around to accommodate bigger program
|
||||||
|
* @param programEnd Program ending address
|
||||||
|
*/
|
||||||
|
private void relocateVariables(int programEnd) {
|
||||||
|
RAM memory = Emulator.computer.memory;
|
||||||
|
int currentEnd = memory.readWordRaw(END_OF_PROG_POINTER);
|
||||||
memory.writeWord(END_OF_PROG_POINTER, programEnd, false, true);
|
memory.writeWord(END_OF_PROG_POINTER, programEnd, false, true);
|
||||||
|
if (programEnd > currentEnd) {
|
||||||
|
int diff = programEnd - currentEnd;
|
||||||
|
int himem = memory.readWordRaw(HIMEM);
|
||||||
|
for (int i=himem - diff; i >= programEnd; i--) {
|
||||||
|
memory.write(i+diff, memory.readRaw(i), false, true);
|
||||||
|
}
|
||||||
|
memory.writeWord(VARIABLE_TABLE, memory.readWordRaw(VARIABLE_TABLE) + diff, false, true);
|
||||||
|
memory.writeWord(ARRAY_TABLE, memory.readWordRaw(ARRAY_TABLE) + diff, false, true);
|
||||||
|
memory.writeWord(VARIABLE_TABLE_END, memory.readWordRaw(VARIABLE_TABLE_END) + diff, false, true);
|
||||||
|
memory.writeWord(STRING_TABLE, memory.readWordRaw(STRING_TABLE) + diff, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getProgramSize() {
|
||||||
|
int size = lines.stream().collect(Collectors.summingInt(Line::getLength)) + 4;
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package jace.applesoft;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A command is a list of parts, either raw bytes (ascii text) or tokens. When
|
* A command is a list of parts, either raw bytes (ascii text) or tokens. When
|
||||||
|
@ -220,14 +221,10 @@ public class Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<ByteOrToken> parts = new ArrayList<ByteOrToken>();
|
List<ByteOrToken> parts = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String out = "";
|
return parts.stream().map(ByteOrToken::toString).collect(Collectors.joining());
|
||||||
for (ByteOrToken p : parts) {
|
|
||||||
out += p.toString();
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -153,7 +153,7 @@ public class Line {
|
||||||
boolean isComment = false;
|
boolean isComment = false;
|
||||||
Command currentCommand = new Command();
|
Command currentCommand = new Command();
|
||||||
l.commands.add(currentCommand);
|
l.commands.add(currentCommand);
|
||||||
l.length = 4;
|
l.length = 5; // 4 pointer bytes + 1 null byte at the end
|
||||||
String upperLineString = lineString.toUpperCase();
|
String upperLineString = lineString.toUpperCase();
|
||||||
for (int i = 0; i < lineString.length(); i++) {
|
for (int i = 0; i < lineString.length(); i++) {
|
||||||
if (!hasLineNumber) {
|
if (!hasLineNumber) {
|
||||||
|
@ -211,5 +211,4 @@ public class Line {
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
Loading…
Reference in New Issue