mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-19 10:36:43 +00:00
Changed byte array in Memory to char array (+60% performance improvement)
This commit is contained in:
parent
d004386b7b
commit
12db25e726
@ -187,6 +187,13 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Memory getFloppyData() {
|
public Memory getFloppyData() {
|
||||||
return ((CubotFloppyDrive) getParent().getCpu().getHardware(CubotFloppyDrive.DEFAULT_ADDRESS)).getFloppy().getMemory();
|
|
||||||
|
CubotFloppyDrive drive = ((CubotFloppyDrive) getParent().getCpu().getHardware(CubotFloppyDrive.DEFAULT_ADDRESS));
|
||||||
|
|
||||||
|
if (drive.getFloppy() != null) {
|
||||||
|
return drive.getFloppy().getMemory();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ public class CubotFloppyDrive extends CpuHardware {
|
|||||||
|
|
||||||
public CubotFloppyDrive(Cubot cubot) {
|
public CubotFloppyDrive(Cubot cubot) {
|
||||||
this.cubot = cubot;
|
this.cubot = cubot;
|
||||||
|
|
||||||
|
floppyDisk = new FloppyDisk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,8 +96,6 @@ public class CubotFloppyDrive extends CpuHardware {
|
|||||||
|
|
||||||
if (hwJSON.containsKey("floppy")) {
|
if (hwJSON.containsKey("floppy")) {
|
||||||
drive.floppyDisk = FloppyDisk.deserialise((JSONObject) hwJSON.get("floppy"));
|
drive.floppyDisk = FloppyDisk.deserialise((JSONObject) hwJSON.get("floppy"));
|
||||||
} else {
|
|
||||||
drive.floppyDisk = new FloppyDisk();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return drive;
|
return drive;
|
||||||
|
@ -25,7 +25,7 @@ public class FloppyDisk implements JSONSerialisable {
|
|||||||
|
|
||||||
|
|
||||||
public FloppyDisk() {
|
public FloppyDisk() {
|
||||||
this.memory = new Memory(1024 * 1440);
|
this.memory = new Memory(512 * 1440);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,7 +39,7 @@ public class FloppyDisk implements JSONSerialisable {
|
|||||||
public boolean readSector(int sector, Memory cpuMemory, int ramAddress) {
|
public boolean readSector(int sector, Memory cpuMemory, int ramAddress) {
|
||||||
|
|
||||||
if (sector <= 1440) {
|
if (sector <= 1440) {
|
||||||
cpuMemory.write(ramAddress, memory.getBytes(), sector * 1024, 1024);
|
cpuMemory.write(ramAddress, memory.getWords(), sector * 512, 512);
|
||||||
|
|
||||||
//Calculate seek time
|
//Calculate seek time
|
||||||
int deltaTrack = (sector / 80) - rwHeadTrack;
|
int deltaTrack = (sector / 80) - rwHeadTrack;
|
||||||
@ -66,7 +66,7 @@ public class FloppyDisk implements JSONSerialisable {
|
|||||||
public boolean writeSector(int sector, Memory cpuMemory, int ramAddress) {
|
public boolean writeSector(int sector, Memory cpuMemory, int ramAddress) {
|
||||||
|
|
||||||
if (sector <= 1440) {
|
if (sector <= 1440) {
|
||||||
memory.write(sector * 512, cpuMemory.getBytes(), ramAddress * 2, 1024);
|
memory.write(sector * 512, cpuMemory.getWords(), ramAddress, 512);
|
||||||
|
|
||||||
//Calculate seek time
|
//Calculate seek time
|
||||||
int deltaTrack = (sector / 80) - rwHeadTrack;
|
int deltaTrack = (sector / 80) - rwHeadTrack;
|
||||||
|
@ -5,6 +5,8 @@ import net.simon987.server.assembly.exception.AssemblyException;
|
|||||||
import net.simon987.server.assembly.exception.DuplicateSegmentException;
|
import net.simon987.server.assembly.exception.DuplicateSegmentException;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
@ -30,7 +32,7 @@ public class AssemblyResult {
|
|||||||
/**
|
/**
|
||||||
* Offset of the code segment
|
* Offset of the code segment
|
||||||
*/
|
*/
|
||||||
public int codeSegmentOffset;
|
private int codeSegmentOffset;
|
||||||
/**
|
/**
|
||||||
* Line of the code segment definition (for editor icons)
|
* Line of the code segment definition (for editor icons)
|
||||||
*/
|
*/
|
||||||
@ -104,4 +106,20 @@ public class AssemblyResult {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public char[] getWords() {
|
||||||
|
|
||||||
|
char[] assembledCode = new char[bytes.length / 2];
|
||||||
|
ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(assembledCode);
|
||||||
|
|
||||||
|
return assembledCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCodeSegmentOffset() {
|
||||||
|
if (codeSegmentSet) {
|
||||||
|
return codeSegmentOffset;
|
||||||
|
} else {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package net.simon987.server.assembly;
|
package net.simon987.server.assembly;
|
||||||
|
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.io.JSONSerialisable;
|
import net.simon987.server.io.JSONSerialisable;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
@ -23,7 +26,7 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
/**
|
/**
|
||||||
* Contents of the memory
|
* Contents of the memory
|
||||||
*/
|
*/
|
||||||
private byte[] bytes;
|
private char[] words;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an empty Memory object
|
* Create an empty Memory object
|
||||||
@ -31,7 +34,7 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
* @param size Size of the memory, in words
|
* @param size Size of the memory, in words
|
||||||
*/
|
*/
|
||||||
public Memory(int size) {
|
public Memory(int size) {
|
||||||
bytes = new byte[size];
|
words = new char[size];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,29 +45,26 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int get(int address) {
|
public int get(int address) {
|
||||||
address = address * 2; //Because our Memory is only divisible by 16bits
|
address = (char) address;
|
||||||
|
|
||||||
if (address + 2 > bytes.length) {
|
if (address >= words.length) {
|
||||||
LogManager.LOGGER.info("DEBUG: Trying to get memory out of bounds " + address);
|
LogManager.LOGGER.info("DEBUG: Trying to get memory out of bounds " + address);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((bytes[address] & 0xFF) << 8) | (bytes[address + 1] & 0xFF);
|
return words[address];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write x words from an array at an offset
|
* Write x words from an array at an offset
|
||||||
*/
|
*/
|
||||||
public boolean write(int offset, byte[] bytes, int srcOffset, int count) {
|
public boolean write(int offset, char[] src, int srcOffset, int count) {
|
||||||
|
|
||||||
offset = (char)offset * 2;
|
if (offset + count > this.words.length || srcOffset >= src.length || count < 0 || offset < 0) {
|
||||||
|
|
||||||
|
|
||||||
if (offset + count > this.bytes.length || srcOffset >= bytes.length || count < 0 || offset < 0) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.arraycopy(bytes, srcOffset, this.bytes, offset, count);
|
System.arraycopy(src, srcOffset, this.words, offset, count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,30 +76,31 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void set(int address, int value) {
|
public void set(int address, int value) {
|
||||||
|
address = (char) address;
|
||||||
|
|
||||||
address = (char)address * 2;
|
if (address >= words.length) {
|
||||||
|
|
||||||
|
|
||||||
if (address + 2 > bytes.length) {
|
|
||||||
LogManager.LOGGER.info("DEBUG: Trying to set memory out of bounds: " + address);
|
LogManager.LOGGER.info("DEBUG: Trying to set memory out of bounds: " + address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes[address] = (byte) ((value >> 8));
|
words[address] = (char) value;
|
||||||
bytes[address + 1] = (byte) (value & 0xFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the memory with 0s
|
* Fill the memory with 0s
|
||||||
*/
|
*/
|
||||||
public void clear() {
|
public void clear() {
|
||||||
Arrays.fill(bytes, (byte) 0);
|
Arrays.fill(words, (char) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get byte array of the Memory object
|
* Get byte array of the Memory object
|
||||||
*/
|
*/
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
|
|
||||||
|
byte[] bytes = new byte[words.length * 2];
|
||||||
|
ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asCharBuffer().put(words);
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +113,7 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
Deflater compressor = new Deflater(Deflater.BEST_COMPRESSION, true);
|
Deflater compressor = new Deflater(Deflater.BEST_COMPRESSION, true);
|
||||||
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(stream, compressor);
|
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(stream, compressor);
|
||||||
deflaterOutputStream.write(bytes);
|
deflaterOutputStream.write(getBytes());
|
||||||
deflaterOutputStream.close();
|
deflaterOutputStream.close();
|
||||||
byte[] compressedBytes = stream.toByteArray();
|
byte[] compressedBytes = stream.toByteArray();
|
||||||
|
|
||||||
@ -128,7 +129,11 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
public static Memory deserialize(JSONObject json){
|
public static Memory deserialize(JSONObject json){
|
||||||
|
|
||||||
Memory memory = new Memory(0);
|
Memory memory = new Memory(0);
|
||||||
byte[] compressedBytes = Base64.getDecoder().decode((String)json.get("zipBytes"));
|
|
||||||
|
String zipBytesStr = (String) json.get("zipBytes");
|
||||||
|
|
||||||
|
if (zipBytesStr != null) {
|
||||||
|
byte[] compressedBytes = Base64.getDecoder().decode((String) json.get("zipBytes"));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
@ -137,16 +142,26 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
inflaterOutputStream.write(compressedBytes);
|
inflaterOutputStream.write(compressedBytes);
|
||||||
inflaterOutputStream.close();
|
inflaterOutputStream.close();
|
||||||
|
|
||||||
memory.bytes = baos.toByteArray();
|
memory.setBytes(baos.toByteArray());
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LogManager.LOGGER.severe("Memory was manually deleted");
|
||||||
|
memory = new Memory(GameServer.INSTANCE.getConfig().getInt("memory_size"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBytes(byte[] bytes) {
|
public void setBytes(byte[] bytes) {
|
||||||
this.bytes = bytes;
|
this.words = new char[bytes.length / 2];
|
||||||
|
ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(this.words);
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] getWords() {
|
||||||
|
return words;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,10 +113,11 @@ public class GameUniverse implements JSONSerialisable{
|
|||||||
user.getCpu().getMemory().clear();
|
user.getCpu().getMemory().clear();
|
||||||
|
|
||||||
//Write assembled code to mem
|
//Write assembled code to mem
|
||||||
user.getCpu().getMemory().write((short) ar.origin, ar.bytes, 0, ar.bytes.length);
|
char[] assembledCode = ar.getWords();
|
||||||
user.getCpu().setCodeSegmentOffset(ar.codeSegmentOffset);
|
|
||||||
|
user.getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length);
|
||||||
|
user.getCpu().setCodeSegmentOffset(ar.getCodeSegmentOffset());
|
||||||
|
|
||||||
//Init
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
user = new User(null);
|
user = new User(null);
|
||||||
|
@ -28,8 +28,10 @@ public class CodeUploadHandler implements MessageHandler {
|
|||||||
user.getUser().getCpu().getMemory().clear();
|
user.getUser().getCpu().getMemory().clear();
|
||||||
|
|
||||||
//Write assembled code to mem
|
//Write assembled code to mem
|
||||||
user.getUser().getCpu().getMemory().write((char) ar.origin, ar.bytes, 0, ar.bytes.length);
|
char[] assembledCode = ar.getWords();
|
||||||
user.getUser().getCpu().setCodeSegmentOffset(ar.codeSegmentOffset);
|
|
||||||
|
user.getUser().getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length);
|
||||||
|
user.getUser().getCpu().setCodeSegmentOffset(ar.getCodeSegmentOffset());
|
||||||
|
|
||||||
JSONObject response = new JSONObject();
|
JSONObject response = new JSONObject();
|
||||||
response.put("t", "codeResponse");
|
response.put("t", "codeResponse");
|
||||||
|
@ -15,11 +15,15 @@ public class FloppyHandler implements MessageHandler {
|
|||||||
|
|
||||||
LogManager.LOGGER.info("(WS) Floppy download request from " + user.getUser().getUsername());
|
LogManager.LOGGER.info("(WS) Floppy download request from " + user.getUser().getUsername());
|
||||||
|
|
||||||
|
if (user.isGuest()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//floppy
|
if (user.getUser().getControlledUnit().getFloppyData() != null) {
|
||||||
byte[] bytes = user.getUser().getControlledUnit().getFloppyData().getBytes();
|
byte[] bytes = user.getUser().getControlledUnit().getFloppyData().getBytes();
|
||||||
|
|
||||||
user.getWebSocket().send(bytes);
|
user.getWebSocket().send(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if (json.get("t").equals("floppyUp")) {
|
} else if (json.get("t").equals("floppyUp")) {
|
||||||
|
|
||||||
|
@ -36,14 +36,14 @@ public class MemoryTest {
|
|||||||
Memory memory = new Memory(memorySize);
|
Memory memory = new Memory(memorySize);
|
||||||
|
|
||||||
|
|
||||||
assertTrue(memory.write(0, new byte[memorySize], 0, memorySize));
|
assertTrue(memory.write(0, new char[memorySize], 0, memorySize));
|
||||||
assertFalse(memory.write(0, new byte[memorySize], 0, memorySize + 1));
|
assertFalse(memory.write(0, new char[memorySize], 0, memorySize + 1));
|
||||||
assertFalse(memory.write(0, new byte[memorySize], 0, -1));
|
assertFalse(memory.write(0, new char[memorySize], 0, -1));
|
||||||
assertFalse(memory.write(-1, new byte[memorySize], 0, 10));
|
assertFalse(memory.write(-1, new char[memorySize], 0, 10));
|
||||||
|
|
||||||
assertFalse(memory.write(memorySize / 2, new byte[15], 0, 1));
|
assertFalse(memory.write(memorySize, new char[15], 0, 1));
|
||||||
assertFalse(memory.write((memorySize / 2) - 5, new byte[11], 0, 11));
|
assertFalse(memory.write((memorySize) - 5, new char[11], 0, 6));
|
||||||
assertTrue(memory.write((memorySize / 2) - 5, new byte[11], 0, 10));
|
assertTrue(memory.write((memorySize) - 5, new char[11], 0, 5));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,10 +55,10 @@ public class AddInstructionTest {
|
|||||||
assertFalse(status.isBreakFlag());
|
assertFalse(status.isBreakFlag());
|
||||||
|
|
||||||
memory.clear();
|
memory.clear();
|
||||||
memory.set(memorySize, 10);
|
memory.set(memorySize - 1, 10);
|
||||||
memory.set(1, 10);
|
memory.set(1, 10);
|
||||||
addInstruction.execute(memory, memorySize, memory, 1, status);
|
addInstruction.execute(memory, memorySize - 1, memory, 1, status);
|
||||||
assertEquals(20, memory.get(memorySize));
|
assertEquals(20, memory.get(memorySize - 1));
|
||||||
assertEquals(10, memory.get(1));
|
assertEquals(10, memory.get(1));
|
||||||
//FLAGS Should be CF=0 ZF=0 SF=0 OF=0
|
//FLAGS Should be CF=0 ZF=0 SF=0 OF=0
|
||||||
assertFalse(status.isSignFlag());
|
assertFalse(status.isSignFlag());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user