Merge branch 'master' into implement-SETcc-instructions#184

This commit is contained in:
Kevin Ramharak
2019-01-22 18:40:32 +01:00
24 changed files with 232 additions and 51 deletions

View File

@@ -33,7 +33,7 @@ public class GameServer implements Runnable {
private GameEventDispatcher eventDispatcher;
private PluginManager pluginManager;
private ServerConfiguration config;
private IServerConfiguration config;
private SocketServer socketServer;
@@ -308,7 +308,7 @@ public class GameServer implements Runnable {
}
}
public ServerConfiguration getConfig() {
public IServerConfiguration getConfig() {
return config;
}

View File

@@ -0,0 +1,12 @@
package net.simon987.server;
public interface IServerConfiguration {
int getInt(String key);
String getString(String key);
void setInt(String key, int value);
void setString(String key, String value);
}

View File

@@ -9,11 +9,15 @@ import java.util.Properties;
/**
* Wrapper for Java Properties class
*/
public class ServerConfiguration {
public class ServerConfiguration implements IServerConfiguration {
private Properties properties;
private String fileName;
public ServerConfiguration() {
this.properties = new Properties();
}
public ServerConfiguration(String fileName) {
this.fileName = fileName;

View File

@@ -1,7 +1,6 @@
package net.simon987.server.assembly;
import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.IServerConfiguration;
import net.simon987.server.assembly.exception.*;
import net.simon987.server.logging.LogManager;
import org.apache.commons.text.StringEscapeUtils;
@@ -19,18 +18,22 @@ import java.util.regex.Pattern;
*/
public class Assembler {
private ServerConfiguration config;
private IServerConfiguration config;
private InstructionSet instructionSet;
private RegisterSet registerSet;
private static final int MEM_SIZE = GameServer.INSTANCE.getConfig().getInt("memory_size");
private static int MEM_SIZE;
private static String labelPattern = "^\\s*[a-zA-Z_]\\w*:";
private static Pattern commentPattern = Pattern.compile("\"[^\"]*\"|(;)");
public Assembler(InstructionSet instructionSet, RegisterSet registerSet, ServerConfiguration config) {
public Assembler(InstructionSet instructionSet, RegisterSet registerSet, IServerConfiguration config) {
this.instructionSet = instructionSet;
this.registerSet = registerSet;
this.config = config;
Assembler.MEM_SIZE = config.getInt("memory_size");
}
/**
@@ -40,11 +43,17 @@ public class Assembler {
* @return The line without its comment part
*/
private static String removeComment(String line) {
if (line.indexOf(';') != -1) {
return line.substring(0, line.indexOf(';'));
} else {
return line;
Matcher m = commentPattern.matcher(line);
while (m.find()) {
try {
return line.substring(0, m.start(1));
} catch (IndexOutOfBoundsException ignored) {
}
}
return line;
}
/**
@@ -55,8 +64,7 @@ public class Assembler {
*/
private static String removeLabel(String line) {
return line.replaceAll("^\\s*\\b\\w*\\b:", "");
return line.replaceAll(labelPattern, "");
}
/**
@@ -98,7 +106,7 @@ public class Assembler {
line = removeComment(line);
//Check for labels
Pattern pattern = Pattern.compile("^\\s*\\b\\w*\\b:");
Pattern pattern = Pattern.compile(labelPattern);
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
@@ -161,7 +169,7 @@ public class Assembler {
string = StringEscapeUtils.unescapeJava(string);
} catch (IllegalArgumentException e) {
throw new InvalidOperandException(
"Invalid string operand \"" + string + "\": " + e.getMessage(),
"Invalid string operand \"" + string + "\": " + e.getMessage(),
currentLine);
}

View File

@@ -1,6 +1,6 @@
package net.simon987.server.assembly;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.IServerConfiguration;
import net.simon987.server.assembly.exception.AssemblyException;
import net.simon987.server.assembly.exception.DuplicateSectionException;
import net.simon987.server.logging.LogManager;
@@ -59,7 +59,7 @@ public class AssemblyResult {
*/
private boolean dataSectionSet = false;
AssemblyResult(ServerConfiguration config) {
AssemblyResult(IServerConfiguration config) {
origin = config.getInt("org_offset");
}

View File

@@ -1,7 +1,7 @@
package net.simon987.server.assembly;
import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.IServerConfiguration;
import net.simon987.server.assembly.exception.CancelledException;
import net.simon987.server.assembly.instruction.*;
import net.simon987.server.event.CpuInitialisationEvent;
@@ -98,7 +98,7 @@ public class CPU implements MongoSerializable {
/**
* Creates a new CPU
*/
public CPU(ServerConfiguration config, ControllableUnit unit) throws CancelledException {
public CPU(IServerConfiguration config, ControllableUnit unit) throws CancelledException {
instructionSet = new DefaultInstructionSet();
registerSet = new DefaultRegisterSet();
codeSectionOffset = config.getInt("org_offset");

View File

@@ -4,6 +4,7 @@ import net.simon987.server.assembly.instruction.*;
import net.simon987.server.logging.LogManager;
import java.util.HashMap;
import java.util.Map;
/**
* Default instruction set for the CPU
@@ -13,7 +14,12 @@ public class DefaultInstructionSet implements InstructionSet {
/**
* Map of instructions, stored in opcode : Instruction format
*/
private HashMap<Integer, Instruction> instructionMap = new HashMap<>(32);
private Map<Integer, Instruction> instructionMap = new HashMap<>(32);
/**
* Map of aliasses, stored in mnemonic : Instruction format
*/
private Map<String, Instruction> aliasesMap = new HashMap<>(16);
private Instruction defaultInstruction;
@@ -32,7 +38,6 @@ public class DefaultInstructionSet implements InstructionSet {
add(new AndInstruction());
add(new OrInstruction());
add(new ShlInstruction());
add(new SalInstruction()); //Alias is added
add(new ShrInstruction());
add(new XorInstruction());
add(new TestInstruction());
@@ -46,6 +51,9 @@ public class DefaultInstructionSet implements InstructionSet {
add(new SarInstruction());
add(new IncInstruction());
add(new DecInstruction());
// aliases
add(new SalInstruction());
}
/**
@@ -86,16 +94,22 @@ public class DefaultInstructionSet implements InstructionSet {
}
}
Instruction aliasedInstruction = aliasesMap.get(mnemonic.toLowerCase());
if (aliasedInstruction != null) {
return aliasedInstruction;
}
return null;
}
@Override
public void add(Instruction instruction) {
if (instructionMap.containsKey(instruction.getOpCode())) {
LogManager.LOGGER.fine(instruction.getMnemonic() + " instruction is an alias for " +
instructionMap.get(instruction.getOpCode()).getMnemonic());
Instruction aliasedInstruction = instructionMap.get(instruction.getOpCode());
if (aliasedInstruction != null) {
aliasesMap.put(instruction.getMnemonic(), aliasedInstruction);
} else {
instructionMap.put(instruction.getOpCode(), instruction);
}
instructionMap.put(instruction.getOpCode(), instruction);
}
}

View File

@@ -5,7 +5,7 @@ import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.IServerConfiguration;
import net.simon987.server.assembly.exception.CancelledException;
import net.simon987.server.game.objects.GameObject;
import net.simon987.server.game.world.World;
@@ -32,7 +32,7 @@ public class GameUniverse {
private int maxWidth = 0xFFFF;
public GameUniverse(ServerConfiguration config) {
public GameUniverse(IServerConfiguration config) {
worlds = new ConcurrentHashMap<>(256);
users = new ConcurrentHashMap<>(16);

View File

@@ -1,7 +1,7 @@
package net.simon987.server.game.world;
import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.IServerConfiguration;
import net.simon987.server.assembly.exception.CancelledException;
import net.simon987.server.event.GameEvent;
import net.simon987.server.event.WorldGenerationEvent;
@@ -48,7 +48,7 @@ public class WorldGenerator {
private HashMap<Point, Integer> centerPointsMap;
public WorldGenerator(ServerConfiguration config) {
public WorldGenerator(IServerConfiguration config) {
dimension = config.getString("new_user_dimension");

View File

@@ -1,6 +1,6 @@
package net.simon987.server.web;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.IServerConfiguration;
import net.simon987.server.logging.LogManager;
import net.simon987.server.websocket.SocketServer;
import org.apache.velocity.app.VelocityEngine;
@@ -14,7 +14,7 @@ public class WebServer {
private SocketServer socketServer;
private GuestPolicy guestPolicy;
public WebServer(ServerConfiguration config) {
public WebServer(IServerConfiguration config) {
//Velocity config
Properties properties = new Properties();
@@ -63,7 +63,7 @@ public class WebServer {
* Load guest policy from config.
* If no valid policy is specified in the config, the default <code>GuestPolicy.ALLOW</code> is used
*/
private void initGuestPolicy(ServerConfiguration config) {
private void initGuestPolicy(IServerConfiguration config) {
String guestPolicyStr = config.getString("guest_policy");
try {
this.guestPolicy = GuestPolicy.valueOf(guestPolicyStr);

View File

@@ -28,7 +28,7 @@ function checkForLabel(line, result) {
line = removeComment(line);
var match;
if ((match = /\b\w*\b:/.exec(line)) !== null) {
if ((match = /^[a-zA-Z_]\w*:/.exec(line)) !== null) {
result.labels.push(match[0].substring(0, match[0].length - 1));
}

View File

@@ -0,0 +1,33 @@
package net.simon987.server;
import java.util.Properties;
public class FakeConfiguration implements IServerConfiguration {
private Properties properties;
public FakeConfiguration() {
this.properties = new Properties();
}
@Override
public int getInt(String key) {
return Integer.parseInt(properties.getProperty(key));
}
@Override
public String getString(String key) {
return properties.getProperty(key);
}
@Override
public void setInt(String key, int value) {
properties.setProperty(key, String.valueOf(value));
}
@Override
public void setString(String key, String value) {
properties.setProperty(key, value);
}
}

View File

@@ -0,0 +1,24 @@
package net.simon987.server.assembly;
import net.simon987.server.FakeConfiguration;
import net.simon987.server.IServerConfiguration;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class DWTest {
@Test
public void TestSemiColonInString() {
IServerConfiguration configuration = new FakeConfiguration();
configuration.setInt("memory_size", 1000);
configuration.setInt("org_offset", 400);
Assembler assembler = new Assembler(new DefaultInstructionSet(), new DefaultRegisterSet(), configuration);
AssemblyResult ar = assembler.parse("DW \";\"");
assertEquals(0, ar.exceptions.size());
}
}

View File

@@ -0,0 +1,30 @@
package net.simon987.server.assembly;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class LabelTest {
@Test
public void TestNumericLabel() {
Assembler asm = TestHelper.getTestAsm();
AssemblyResult ar = asm.parse("999:");
assertEquals(ar.labels.size(), 0);
}
@Test
public void TestValidLabel() {
Assembler asm = TestHelper.getTestAsm();
AssemblyResult ar = asm.parse("\ttest_label: dw 1 ; comment");
assertNotNull(ar.labels.get("test_label"));
}
}

View File

@@ -0,0 +1,38 @@
package net.simon987.server.assembly;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TestComment {
@Test
public void TestCommentInQuotes() {
Assembler asm = TestHelper.getTestAsm();
AssemblyResult r1 = asm.parse("dw \";\", 12");
assertEquals(r1.bytes.length, 4);
}
@Test
public void TestRegularComment() {
Assembler asm = TestHelper.getTestAsm();
AssemblyResult r1 = asm.parse("register_SP: DW \"SP=\",0 ; register_A + 28");
assertEquals(8, r1.bytes.length);
assertEquals(0, r1.exceptions.size());
}
@Test
public void TestStandaloneComment() {
Assembler asm = TestHelper.getTestAsm();
AssemblyResult r1 = asm.parse("; Set display_mode to DECIMAL_MODE");
assertEquals(0, r1.bytes.length);
assertEquals(0, r1.exceptions.size());
}
}

View File

@@ -0,0 +1,18 @@
package net.simon987.server.assembly;
import net.simon987.server.FakeConfiguration;
import net.simon987.server.IServerConfiguration;
class TestHelper {
static Assembler getTestAsm() {
IServerConfiguration configuration = new FakeConfiguration();
configuration.setInt("memory_size", 1000);
configuration.setInt("org_offset", 400);
return new Assembler(new DefaultInstructionSet(), new DefaultRegisterSet(), configuration);
}
}