diff --git a/Server/src/net/simon987/server/GameServer.java b/Server/src/net/simon987/server/GameServer.java index 1f26406..0c37de9 100644 --- a/Server/src/net/simon987/server/GameServer.java +++ b/Server/src/net/simon987/server/GameServer.java @@ -104,7 +104,8 @@ public class GameServer implements Runnable { gameUniverse.incrementTime(); //Process user code - for(User user : gameUniverse.getUsers()){ + ArrayList users_ = gameUniverse.getUsers(); + for (User user : users_) { if(user.getCpu() != null){ user.getCpu().reset(); diff --git a/Server/src/net/simon987/server/assembly/Assembler.java b/Server/src/net/simon987/server/assembly/Assembler.java index 34ce3c8..96aac4f 100755 --- a/Server/src/net/simon987/server/assembly/Assembler.java +++ b/Server/src/net/simon987/server/assembly/Assembler.java @@ -271,7 +271,7 @@ public class Assembler { * usage: constant_name EQU * A constant treated the same way as a label. */ - + line = line.trim(); String[] tokens = line.split("\\s+"); diff --git a/Server/src/net/simon987/server/assembly/CPU.java b/Server/src/net/simon987/server/assembly/CPU.java index d9d7543..3c30014 100755 --- a/Server/src/net/simon987/server/assembly/CPU.java +++ b/Server/src/net/simon987/server/assembly/CPU.java @@ -94,6 +94,10 @@ public class CPU implements JSONSerialisable{ instructionSet.add(new HwiInstruction(this)); instructionSet.add(new HwqInstruction(this)); instructionSet.add(new XchgInstruction(this)); + instructionSet.add(new JcInstruction(this)); + instructionSet.add(new JncInstruction(this)); + instructionSet.add(new JnoInstruction(this)); + instructionSet.add(new JoInstruction(this)); status = new Status(); memory = new Memory(config.getInt("memory_size")); diff --git a/Server/src/net/simon987/server/assembly/DefaultInstructionSet.java b/Server/src/net/simon987/server/assembly/DefaultInstructionSet.java index a7b2d3d..8ec302f 100755 --- a/Server/src/net/simon987/server/assembly/DefaultInstructionSet.java +++ b/Server/src/net/simon987/server/assembly/DefaultInstructionSet.java @@ -37,6 +37,8 @@ public class DefaultInstructionSet implements InstructionSet { add(new CmpInstruction()); add(new NegInstruction()); add(new NotInstruction()); + add(new RorInstruction()); + add(new RolInstruction()); } /** diff --git a/Server/src/net/simon987/server/assembly/instruction/JcInstruction.java b/Server/src/net/simon987/server/assembly/instruction/JcInstruction.java new file mode 100644 index 0000000..b9b1713 --- /dev/null +++ b/Server/src/net/simon987/server/assembly/instruction/JcInstruction.java @@ -0,0 +1,36 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.CPU; +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; + +public class JcInstruction extends Instruction { + + private static final int OPCODE = 33; + + private CPU cpu; + + public JcInstruction(CPU cpu) { + super("jc", OPCODE); + this.cpu = cpu; + } + + @Override + public Status execute(Target src, int srcIndex, Status status) { + if (status.isCarryFlag()) { + cpu.setIp((char) src.get(srcIndex)); + } + return status; + } + + @Override + public Status execute(int src, Status status) { + if (status.isCarryFlag()) { + cpu.setIp((char) src); + } + return status; + } + + +} diff --git a/Server/src/net/simon987/server/assembly/instruction/JncInstruction.java b/Server/src/net/simon987/server/assembly/instruction/JncInstruction.java new file mode 100644 index 0000000..dc24476 --- /dev/null +++ b/Server/src/net/simon987/server/assembly/instruction/JncInstruction.java @@ -0,0 +1,35 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.CPU; +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; + +public class JncInstruction extends Instruction { + + private static final int OPCODE = 34; + + private CPU cpu; + + public JncInstruction(CPU cpu) { + super("jnc", OPCODE); + this.cpu = cpu; + } + + @Override + public Status execute(Target src, int srcIndex, Status status) { + if (!status.isCarryFlag()) { + cpu.setIp((char) src.get(srcIndex)); + } + return status; + } + + @Override + public Status execute(int src, Status status) { + if (!status.isCarryFlag()) { + cpu.setIp((char) src); + } + return status; + } + +} diff --git a/Server/src/net/simon987/server/assembly/instruction/JnoInstruction.java b/Server/src/net/simon987/server/assembly/instruction/JnoInstruction.java new file mode 100644 index 0000000..8c1a653 --- /dev/null +++ b/Server/src/net/simon987/server/assembly/instruction/JnoInstruction.java @@ -0,0 +1,35 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.CPU; +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; + + +public class JnoInstruction extends Instruction { + + private static final int OPCODE = 37; + + private CPU cpu; + + public JnoInstruction(CPU cpu) { + super("jno", OPCODE); + this.cpu = cpu; + } + + @Override + public Status execute(Target src, int srcIndex, Status status) { + if (!status.isOverflowFlag()) { + cpu.setIp((char) src.get(srcIndex)); + } + return status; + } + + @Override + public Status execute(int src, Status status) { + if (!status.isOverflowFlag()) { + cpu.setIp((char) src); + } + return status; + } +} \ No newline at end of file diff --git a/Server/src/net/simon987/server/assembly/instruction/JoInstruction.java b/Server/src/net/simon987/server/assembly/instruction/JoInstruction.java new file mode 100644 index 0000000..d9ad1d6 --- /dev/null +++ b/Server/src/net/simon987/server/assembly/instruction/JoInstruction.java @@ -0,0 +1,34 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.CPU; +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; + +public class JoInstruction extends Instruction { + + private static final int OPCODE = 36; + + private CPU cpu; + + public JoInstruction(CPU cpu) { + super("jo", OPCODE); + this.cpu = cpu; + } + + @Override + public Status execute(Target src, int srcIndex, Status status) { + if (status.isOverflowFlag()) { + cpu.setIp((char) src.get(srcIndex)); + } + return status; + } + + @Override + public Status execute(int src, Status status) { + if (status.isOverflowFlag()) { + cpu.setIp((char) src); + } + return status; + } +} \ No newline at end of file diff --git a/Server/src/net/simon987/server/assembly/instruction/RolInstruction.java b/Server/src/net/simon987/server/assembly/instruction/RolInstruction.java new file mode 100644 index 0000000..fa114dc --- /dev/null +++ b/Server/src/net/simon987/server/assembly/instruction/RolInstruction.java @@ -0,0 +1,51 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; + +public class RolInstruction extends Instruction { + + private static final int OPCODE = 35; + + public RolInstruction() { + super("rol", OPCODE); + } + + @Override + public Status execute(Target dst, int dstIndex, Target src, int srcIndex, Status status) { + + int count = src.get(srcIndex); + + int destination = dst.get(dstIndex); + int signBit = (destination & 0x8000); + + destination = (destination << count) | (destination >>> (16 - count)); + if (count == 1) { + status.setOverflowFlag((destination & 0x8000) != signBit); //Set OF if sign bit changed + } + status.setCarryFlag((destination & 1) == 1); + dst.set(dstIndex, destination); + + + return status; + } + + @Override + public Status execute(Target dst, int dstIndex, int src, Status status) { + + + int destination = dst.get(dstIndex); + int signBit = (destination & 0x8000); + + destination = (destination << src) | (destination >>> (16 - src)); + if (src == 1) { + status.setOverflowFlag((destination & 0x8000) != signBit); //Set OF if sign bit changed + } + status.setCarryFlag((destination & 1) == 1); + dst.set(dstIndex, destination); + + + return status; + } +} diff --git a/Server/src/net/simon987/server/assembly/instruction/RorInstruction.java b/Server/src/net/simon987/server/assembly/instruction/RorInstruction.java new file mode 100644 index 0000000..e41d6cc --- /dev/null +++ b/Server/src/net/simon987/server/assembly/instruction/RorInstruction.java @@ -0,0 +1,51 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; + +/** + * Rotate right + *
+ * ->  destination -(CF)>  + */ +public class RorInstruction extends Instruction { + + private static final int OPCODE = 32; + + public RorInstruction() { + super("ror", OPCODE); + } + + @Override + public Status execute(Target dst, int dstIndex, Target src, int srcIndex, Status status) { + + int count = src.get(srcIndex); + + int destination = dst.get(dstIndex); + int signBit = (destination & 0x8000); + + destination = (destination >>> count) | (destination << (16 - count)); + if (count == 1) { + status.setOverflowFlag((destination & 0x8000) != signBit); //Set OF if sign bit changed + } + dst.set(dstIndex, destination); + status.setCarryFlag((destination & 0x8000) == 0x8000); + return status; + } + + @Override + public Status execute(Target dst, int dstIndex, int src, Status status) { + + int destination = dst.get(dstIndex); + int signBit = (destination & 0x8000); + + destination = (destination >>> src) | (destination << (16 - src)); + if (src == 1) { + status.setOverflowFlag((destination & 0x8000) != signBit); //Set OF if sign bit changed + } + dst.set(dstIndex, destination); + status.setCarryFlag((destination & 0x8000) == 0x8000); + return status; + } +} diff --git a/Server/src/net/simon987/server/game/GameUniverse.java b/Server/src/net/simon987/server/game/GameUniverse.java index 5d7bc99..8fe1bb7 100644 --- a/Server/src/net/simon987/server/game/GameUniverse.java +++ b/Server/src/net/simon987/server/game/GameUniverse.java @@ -129,8 +129,17 @@ public class GameUniverse implements JSONSerialisable{ } } + /** + * Get an object by id + *
+ * ConcurrentModificationException risk when inside game loop + * + * @param id id of the game object + * @return GameObject, null if not found + */ public GameObject getObject(int id) { + // for (World world : worlds) { for(GameObject object : world.getGameObjects()){ if(object.getObjectId() == id){ @@ -161,12 +170,14 @@ public class GameUniverse implements JSONSerialisable{ JSONArray worlds = new JSONArray(); - for(World world : this.worlds){ + ArrayList worlds_ = new ArrayList<>(this.worlds); + for (World world : worlds_){ worlds.add(world.serialise()); } JSONArray users = new JSONArray(); - for(User user : this.users){ + ArrayList users_ = new ArrayList(this.users); + for (User user : users_){ if (!user.isGuest()) { users.add(user.serialise()); } diff --git a/Server/src/net/simon987/server/game/World.java b/Server/src/net/simon987/server/game/World.java index 2d28595..e37eb6f 100644 --- a/Server/src/net/simon987/server/game/World.java +++ b/Server/src/net/simon987/server/game/World.java @@ -83,7 +83,8 @@ public class World implements JSONSerialisable{ JSONObject json = new JSONObject(); JSONArray objects = new JSONArray(); - for(GameObject obj : gameObjects){ + ArrayList gameObjects_ = new ArrayList<>(gameObjects); + for (GameObject obj : gameObjects_) { objects.add(obj.serialise()); } json.put("objects", objects);