diff --git a/build.gradle b/build.gradle index 8bdef40..c81d793 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ repositories { // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. maven { url 'https://maven.dblsaiko.net' } //qcommon + maven { url 'https://jitpack.io' } //uxnkt } loom { @@ -52,8 +53,8 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - shadow(implementation(project(":J65el02"))) - + //shadow(implementation(project(":J65el02"))) + shadow(implementation('com.github.walksanatora:uxnkt:v1.2.2')) shadow(implementation(group: "net.dblsaiko.qcommon.croco", name: "croco", version: "2.1.3")) } diff --git a/src/main/java/net/brokenmoon/redcontrol/api/DeviceBus.kt b/src/main/java/net/brokenmoon/redcontrol/api/DeviceBus.kt new file mode 100644 index 0000000..332eec7 --- /dev/null +++ b/src/main/java/net/brokenmoon/redcontrol/api/DeviceBus.kt @@ -0,0 +1,21 @@ +package net.brokenmoon.redcontrol.api + +import net.walksanator.uxnkt.vm.Device +import net.walksanator.uxnkt.vm.IDevice + +class DeviceBus { + var isValid = true + val devices = Array(256) { Device() } + + fun tryClaimId(id: Byte, device: IDevice): Boolean { + val obj = devices[id.toInt()] + if (obj.javaClass == Device::class.java) { + devices[id.toInt()] = device + return true + } + return false + } + fun forceClaimId(id: Byte, device: IDevice) { + devices[id.toInt()] = device + } +} \ No newline at end of file diff --git a/src/main/java/net/brokenmoon/redcontrol/api/Emulator.java b/src/main/java/net/brokenmoon/redcontrol/api/Emulator.java deleted file mode 100644 index 4b4ba3f..0000000 --- a/src/main/java/net/brokenmoon/redcontrol/api/Emulator.java +++ /dev/null @@ -1,209 +0,0 @@ -package net.brokenmoon.redcontrol.api; - -import com.simon816.j65el02.Bus; -import com.simon816.j65el02.Cpu; -import com.simon816.j65el02.CpuState; -import com.simon816.j65el02.device.Memory; -import com.simon816.j65el02.device.RedBus; -import com.simon816.j65el02.device.RedBusState; -import net.brokenmoon.redcontrol.RedControl; -import net.brokenmoon.redcontrol.mixin.BusAccessor; -import net.brokenmoon.redcontrol.mixin.CpuAccessor; -import net.brokenmoon.redcontrol.mixin.MemoryAccessor; -import net.minecraft.nbt.NbtCompound; - -import java.io.IOException; -import java.nio.file.Paths; - - -/** - * A serializable emulator - */ -public class Emulator { - - private RedBus bus; - public Cpu cpu; - private Memory ram; - - public Emulator(RedBus bus){ - this.bus = bus; - cpu = new Cpu(); - cpu.setLogCallback((i) -> RedControl.LOGGER.info("CPU emitted a byte {}",i)); - cpu.setBus(new Bus(bus)); - ram = new Memory(0x0000, 0x4000 - 1, ((CpuAccessor)cpu).getRedBusState()); - ram.loadFromBytes(RedControl.images.get("rpcboot.bin"),0x400,0x100); - cpu.getBus().addDevice(ram, ((CpuAccessor)cpu).getRedBusState()); - cpu.reset(); - ram.write(0, 2, ((CpuAccessor)cpu).getRedBusState()); - ram.write(1, 1, ((CpuAccessor)cpu).getRedBusState()); - } - - /** - * gets the RedBus attached to this Emulator - * @return the red bus attached to this emulator - */ - public RedBus getBus() { - return bus; - } - - /** - * sets the bus and sets redbus on the CPU - * @param bus the bus to set the cpu and this emu to - */ - public void setBus(RedBus bus) { - this.bus = bus; - ((BusAccessor)this.cpu.getBus()).setRedBus(bus); - } - - /** - * returns if the CPU is waiting on interupt - * @return if the cpu is waiting on a interupt - */ - public boolean isWaitingOnInterrupt(){ - return cpu.isWaitingForInterrupt(); - } - - /** - * sets the CPU's interupt state - * @param interrupt the new interupt state - */ - public void setWaitingOnInterrupt(boolean interrupt){ - cpu.getCpuState().intWait = interrupt; - } - - /** - * steps the CPU by 1 instruction - * and updates all bus/redbus attached devices - */ - public void step() { - if(!isWaitingOnInterrupt()) { - this.cpu.step(); - this.cpu.getBus().update(((CpuAccessor)cpu).getRedBusState()); - } - } - - /** - * resets the CPU to default values, and loads driveID and monitorID back for bootloader to use - * @param driveId the drive bootloader will read from - * @param monitorId the monitor id bootloder and initial program will write to - */ - public void reset(int driveId, int monitorId){ - cpu.reset(); - ram.write(0, driveId, ((CpuAccessor)cpu).getRedBusState()); - ram.write(1, monitorId, ((CpuAccessor)cpu).getRedBusState()); - } - - /** - * save the emulator into NBT - * @param nbt the NBT to write state into - */ - public void writeNbt(NbtCompound nbt) { - //Cpu write nbt - - //Cpu state write nbt - nbt.putInt("aRegister", cpu.getCpuState().a); - nbt.putInt("aTopRegister", cpu.getCpuState().aTop); - nbt.putInt("xRegister", cpu.getCpuState().x); - nbt.putInt("yRegister", cpu.getCpuState().y); - nbt.putInt("spRegister", cpu.getCpuState().sp); - nbt.putInt("pcRegister", cpu.getCpuState().pc); - nbt.putInt("irRegister", cpu.getCpuState().ir); - nbt.putInt("iRegister", cpu.getCpuState().i); - nbt.putInt("rRegister", cpu.getCpuState().r); - nbt.putInt("dRegister", cpu.getCpuState().d); - nbt.putInt("brkRegister", cpu.getCpuState().brk); - nbt.putInt("porRegister", cpu.getCpuState().por); - nbt.putInt("nextirRegister", cpu.getCpuState().nextIr); - nbt.putInt("args1Register", cpu.getCpuState().args[0]); - nbt.putInt("args2Register", cpu.getCpuState().args[1]); - nbt.putInt("nextArgs1Register", cpu.getCpuState().nextArgs[0]); - nbt.putInt("nextArgs2Register", cpu.getCpuState().nextArgs[1]); - nbt.putInt("instSizeRegister", cpu.getCpuState().instSize); - nbt.putBoolean("opTrap", cpu.getCpuState().opTrap); - nbt.putBoolean("irqAsserted", cpu.getCpuState().irqAsserted); - nbt.putBoolean("nmiAsserted", cpu.getCpuState().nmiAsserted); - nbt.putInt("lastPc", cpu.getCpuState().lastPc); - nbt.putBoolean("intWait", cpu.getCpuState().intWait); - nbt.putBoolean("signalStop", cpu.getCpuState().signalStop); - - nbt.putBoolean("carryFlag", cpu.getCpuState().carryFlag); - nbt.putBoolean("negativeFlag", cpu.getCpuState().negativeFlag); - nbt.putBoolean("zeroFlag", cpu.getCpuState().zeroFlag); - nbt.putBoolean("irqDisable", cpu.getCpuState().irqDisableFlag); - nbt.putBoolean("decimalMode", cpu.getCpuState().decimalModeFlag); - nbt.putBoolean("breakFlag", cpu.getCpuState().breakFlag); - nbt.putBoolean("overflowFlag", cpu.getCpuState().overflowFlag); - nbt.putBoolean("emuFlag", cpu.getCpuState().emulationFlag); - nbt.putBoolean("mWidth", cpu.getCpuState().mWidthFlag); - nbt.putBoolean("indexWidth", cpu.getCpuState().indexWidthFlag); - nbt.putLong("stepCounter", cpu.getCpuState().stepCounter); - - //Redbus state write nbt - RedBusState redBusState = ((CpuAccessor)cpu).getRedBusState(); - nbt.putInt("deviceId", redBusState.activeDeviceId); - nbt.putInt("offset", redBusState.offset); - nbt.putInt("memoryWindow", redBusState.memoryWindow); - nbt.putBoolean("enabled", redBusState.enabled); - nbt.putBoolean("enableWindow", redBusState.enableWindow); - - //Ram write nbt. - nbt.putByteArray("ramValues", ((MemoryAccessor)this.ram).getMem()); - } - - /** - * load emulator state from NBT - * @param nbt the NBT to load from. - */ - public void readNbt(NbtCompound nbt) { - //Cpu write nbt - - //Cpu state write nbt - cpu.getCpuState().a = nbt.getInt("aRegister"); - cpu.getCpuState().aTop = nbt.getInt("aTopRegister"); - cpu.getCpuState().x = nbt.getInt("xRegister"); - cpu.getCpuState().y = nbt.getInt("yRegister"); - cpu.getCpuState().pc = nbt.getInt("pcRegister"); - cpu.getCpuState().sp = nbt.getInt("spRegister"); - cpu.getCpuState().ir = nbt.getInt("irRegister"); - cpu.getCpuState().i = nbt.getInt("iRegister"); - cpu.getCpuState().r = nbt.getInt("rRegister"); - cpu.getCpuState().d = nbt.getInt("dRegister"); - cpu.getCpuState().brk = nbt.getInt("brkRegister"); - cpu.getCpuState().por = nbt.getInt("porRegister"); - cpu.getCpuState().nextIr = nbt.getInt("nextirRegister"); - cpu.getCpuState().args[0] = nbt.getInt("args1Register"); - cpu.getCpuState().args[1] = nbt.getInt("args2Register"); - cpu.getCpuState().nextArgs[0] = nbt.getInt("nextArgs1Register"); - cpu.getCpuState().nextArgs[1] = nbt.getInt("nextArgs2Register"); - cpu.getCpuState().instSize = nbt.getInt("instSizeRegister"); - cpu.getCpuState().opTrap = nbt.getBoolean("opTrap"); - cpu.getCpuState().irqAsserted = nbt.getBoolean("irqAsserted"); - cpu.getCpuState().nmiAsserted = nbt.getBoolean("nmiAsserted"); - cpu.getCpuState().lastPc = nbt.getInt("lastPc"); - cpu.getCpuState().intWait = nbt.getBoolean("intWait"); - cpu.getCpuState().signalStop = nbt.getBoolean("signalStop"); - - cpu.getCpuState().carryFlag = nbt.getBoolean("carryFlag"); - cpu.getCpuState().negativeFlag = nbt.getBoolean("negativeFlag"); - cpu.getCpuState().zeroFlag = nbt.getBoolean("zeroFlag"); - cpu.getCpuState().irqDisableFlag = nbt.getBoolean("irqDisable"); - cpu.getCpuState().decimalModeFlag = nbt.getBoolean("decimalMode"); - cpu.getCpuState().breakFlag = nbt.getBoolean("breakFlag"); - cpu.getCpuState().overflowFlag = nbt.getBoolean("overflowFlag"); - cpu.getCpuState().emulationFlag = nbt.getBoolean("emuFlag"); - cpu.getCpuState().mWidthFlag = nbt.getBoolean("mWidth"); - cpu.getCpuState().indexWidthFlag = nbt.getBoolean("indexWidth"); - cpu.getCpuState().stepCounter = nbt.getLong("stepCounter"); - - //Redbus state write nbt - RedBusState redBusState = ((CpuAccessor)cpu).getRedBusState(); - redBusState.activeDeviceId = nbt.getInt("deviceId"); - redBusState.offset = nbt.getInt("offset"); - redBusState.memoryWindow = nbt.getInt("memoryWindow"); - redBusState.enabled = nbt.getBoolean("enabled"); - redBusState.enableWindow = nbt.getBoolean("enableWindow"); - - //Ram write nbt. - ((MemoryAccessor)ram).setMem(nbt.getByteArray("ramValues")); - } -} diff --git a/src/main/java/net/brokenmoon/redcontrol/api/NetworkHolder.java b/src/main/java/net/brokenmoon/redcontrol/api/NetworkHolder.java index b1b2836..5815779 100644 --- a/src/main/java/net/brokenmoon/redcontrol/api/NetworkHolder.java +++ b/src/main/java/net/brokenmoon/redcontrol/api/NetworkHolder.java @@ -1,21 +1,17 @@ package net.brokenmoon.redcontrol.api; -import com.simon816.j65el02.device.RedBus; import net.brokenmoon.redcontrol.util.FloodFill; -import net.minecraft.block.Block; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public interface NetworkHolder { - RCWorldBus getBus(World world, BlockPos pos); - void setBus(World world, BlockPos pos, RCWorldBus bus); + DeviceBus getBus(World world, BlockPos pos); + void setBus(World world, BlockPos pos, DeviceBus bus); default void generateBus(ServerWorld world, BlockPos pos){ - Block worldBlock = world.getBlockState(pos).getBlock(); if(world.getBlockEntity(pos) instanceof Peripheral entityBlock){ - RCWorldBus bus = new RCWorldBus(new RedBus(), world, pos); + DeviceBus bus = new DeviceBus(); entityBlock.setBus(bus); - entityBlock.getBus().setValid(true); this.setBus(world,pos,entityBlock.getBus()); FloodFill.INSTANCE.blockFloodFiller(world, pos); } diff --git a/src/main/java/net/brokenmoon/redcontrol/api/Peripheral.java b/src/main/java/net/brokenmoon/redcontrol/api/Peripheral.java index cd100f4..9c675ba 100644 --- a/src/main/java/net/brokenmoon/redcontrol/api/Peripheral.java +++ b/src/main/java/net/brokenmoon/redcontrol/api/Peripheral.java @@ -1,20 +1,18 @@ package net.brokenmoon.redcontrol.api; -import com.simon816.j65el02.device.RedBus; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.util.math.BlockPos; +import net.walksanator.uxnkt.vm.IDevice; import org.jetbrains.annotations.NotNull; /** * a BlockEntity peripheral */ -public abstract class Peripheral extends BlockEntity implements RedBus.Peripheral { - - protected RedBus bus; - protected RCWorldBus worldBus; +public abstract class Peripheral extends BlockEntity implements IDevice { + protected DeviceBus bus; protected int id; @@ -27,21 +25,20 @@ public abstract class Peripheral extends BlockEntity implements RedBus.Periphera * get the redbus (or creates a new one if it does not exists or is invalid) * @return the redbus for this peripheral */ - public RCWorldBus getBus(){ - if (this.worldBus == null || !this.worldBus.getValid()) { - this.worldBus = new RCWorldBus(new RedBus(),world,getPos()); + public DeviceBus getBus(){ + if (this.bus == null || !this.bus.isValid()) { + this.bus = new DeviceBus(); } - return this.worldBus; + return this.bus; } /** - * sets the bus for this peripheral and attaches it's self to the bus + * sets the bus for this peripheral and tries to attach it's self at the desired ID * @param bus */ - public void setBus(@NotNull RCWorldBus bus){ - this.bus = bus.getRedBus(); - this.bus.setPeripheral(id, this); - this.worldBus = bus; + public void setBus(@NotNull DeviceBus bus){ + this.bus = bus; + this.bus.tryClaimId((byte)id,this); } /** diff --git a/src/main/java/net/brokenmoon/redcontrol/api/RCWorldBus.java b/src/main/java/net/brokenmoon/redcontrol/api/RCWorldBus.java deleted file mode 100644 index 486c911..0000000 --- a/src/main/java/net/brokenmoon/redcontrol/api/RCWorldBus.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.brokenmoon.redcontrol.api; - -import com.simon816.j65el02.device.RedBus; -import net.brokenmoon.redcontrol.blocks.NetworkCarrier; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -/** - * A Bus holder including the blockpos and redbus and a cached world - * also holds if the bus is valid - */ -public class RCWorldBus { - - private boolean isValid = false; - - private RedBus redBus; - - private World backupWorld; - private BlockPos backupPos; - - public RCWorldBus(RedBus redBus, World world, BlockPos pos) { - this.redBus = redBus; - backupWorld = world; - backupPos = pos; - } - - - - public void generateBus(ServerWorld world, BlockPos pos){ - ((NetworkCarrier)(world.getBlockState(pos).getBlock())).generateBus(world, pos); - } - - public RedBus getRedBus() { - return redBus; - } - - public void setRedBus(RedBus redBus) { - this.redBus = redBus; - } - - public void setValid(boolean val){ - this.isValid = val; - } - - public boolean getValid(){ - return this.isValid; - } -} diff --git a/src/main/java/net/brokenmoon/redcontrol/api/drive/ByteDiskDriver.java b/src/main/java/net/brokenmoon/redcontrol/api/drive/ByteDiskDriver.java new file mode 100644 index 0000000..22d58e2 --- /dev/null +++ b/src/main/java/net/brokenmoon/redcontrol/api/drive/ByteDiskDriver.java @@ -0,0 +1,51 @@ +package net.brokenmoon.redcontrol.api.drive; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +public class ByteDiskDriver implements DiskDriver{ + + private final ByteBuffer bytes; + private final byte[] drive_name; + private final byte[] drive_serial; + + public ByteDiskDriver(byte[] bytes, String name, String serial) { + this.bytes = ByteBuffer.wrap(bytes); + this.drive_name = name.getBytes(StandardCharsets.UTF_8); + this.drive_serial = serial.getBytes(StandardCharsets.UTF_8); + } + + @Override + public byte[] getDriveName() { + return drive_name; + } + + @Override + public byte[] getDriveSerial() { + return drive_serial; + } + + @Override + public void seek(int location) throws IOException { + this.bytes.position(Math.min(bytes.limit(),location)); + } + + @Override + public void read(ByteBuffer buffer) throws IOException { + int size = Math.min(buffer.capacity(),bytes.remaining()); + for (int i = 0; i < size; i++) { + buffer.put(bytes.get()); + } + } + + @Override + public void write(ByteBuffer buffer) throws IOException { + this.bytes.position(this.bytes.position() + buffer.capacity()); + } + + @Override + public void writeDiskName(byte[] diskName) throws IOException { + + } +} diff --git a/src/main/java/net/brokenmoon/redcontrol/api/drive/DiskDriver.java b/src/main/java/net/brokenmoon/redcontrol/api/drive/DiskDriver.java new file mode 100644 index 0000000..b91cc9a --- /dev/null +++ b/src/main/java/net/brokenmoon/redcontrol/api/drive/DiskDriver.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018 Simon816 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.brokenmoon.redcontrol.api.drive; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public interface DiskDriver { + + /** + * Gets the name of the drive. + * + * @return Drive name + */ + byte[] getDriveName(); + + /** + * Gets the serial name of the drive. + * + * @return Drive serial + */ + byte[] getDriveSerial(); + + /** + * Seeks to the given location in the drive. + * + * @param location Absolute location in the drive + * @throws IOException If the seek operation fails + */ + void seek(int location) throws IOException; + + /** + * Reads data from the drive at the current position into the buffer. + * + * @param buffer Buffer where data is to be put into + * @throws IOException If the read operation fails + */ + void read(ByteBuffer buffer) throws IOException; + + /** + * Write data from the buffer into the drive at the current position. + * + * @param buffer Buffer to pull data from + * @throws IOException If the write operation fails + */ + void write(ByteBuffer buffer) throws IOException; + + /** + * Updates the name of the disk to the given name. + * + * @param diskName New name of the disk + * @throws IOException If the name update operation fails + */ + void writeDiskName(byte[] diskName) throws IOException; + +} diff --git a/src/main/java/net/brokenmoon/redcontrol/api/DriveFactory.kt b/src/main/java/net/brokenmoon/redcontrol/api/drive/DriveFactory.kt similarity index 86% rename from src/main/java/net/brokenmoon/redcontrol/api/DriveFactory.kt rename to src/main/java/net/brokenmoon/redcontrol/api/drive/DriveFactory.kt index 24766eb..765cd8a 100644 --- a/src/main/java/net/brokenmoon/redcontrol/api/DriveFactory.kt +++ b/src/main/java/net/brokenmoon/redcontrol/api/drive/DriveFactory.kt @@ -1,8 +1,5 @@ -package net.brokenmoon.redcontrol.api +package net.brokenmoon.redcontrol.api.drive -import com.simon816.j65el02.device.ByteDiskDriver -import com.simon816.j65el02.device.DiskDriver -import com.simon816.j65el02.device.FileDiskDriver import net.brokenmoon.redcontrol.RedControl import net.fabricmc.loader.api.FabricLoader import net.minecraft.data.client.BlockStateVariantMap.TriFunction @@ -41,10 +38,10 @@ object DriveFactory { "rosave" -> { val path = gamedir.resolve(uri.host+uri.path).absolute() if (path.startsWith(gamedir)) { - return FileDiskDriver(path,name,serial,false) + return FileDiskDriver(path,name,serial,true) } else { return null } } - "http", "https" -> {return null} + //"http", "https" -> {return null} //TODO: implement http(s) Read-Only drives else -> { if (extendedDrivers.containsKey(uri.scheme)) { return extendedDrivers[uri.scheme]!!.apply(uri,name,serial) diff --git a/src/main/java/net/brokenmoon/redcontrol/api/drive/FileDiskDriver.java b/src/main/java/net/brokenmoon/redcontrol/api/drive/FileDiskDriver.java new file mode 100644 index 0000000..3e25f6e --- /dev/null +++ b/src/main/java/net/brokenmoon/redcontrol/api/drive/FileDiskDriver.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018 Simon816 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.brokenmoon.redcontrol.api.drive; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.EnumSet; + +/** + * A {@link DiskDriver} backed by a real file. + */ +public class FileDiskDriver implements DiskDriver { + + private final SeekableByteChannel channel; + private byte[] driveName; + private byte[] driveSerial; + + /** + * Constructs a disk driver backed by a real file. The file is opened for reading, and optionally + * writing, until {@link #close} is called. + * + * @param file Path to the file backing this disk + * @param driveName Name of the drive presented to the program + * @param serial Serial number of the drive + * @param readOnly Whether the file should be opened for reading only + * @throws IOException If the file cannot be opened + */ + public FileDiskDriver(Path file, String driveName, String serial, boolean readOnly) throws IOException { + EnumSet openOptions = EnumSet.of(StandardOpenOption.READ); + if (!readOnly) { + openOptions.add(StandardOpenOption.WRITE); + } + this.channel = Files.newByteChannel(file, openOptions); + this.driveName = driveName.getBytes(StandardCharsets.US_ASCII); + this.driveSerial = serial.getBytes(StandardCharsets.US_ASCII); + } + + /** + * Closes the underlying open file for this drive. + *

+ * This should be called after the machine has been terminated. Using the drive after closing is + * undefined. + * + * @throws IOException If an error occurs when closing + */ + public void close() throws IOException { + this.channel.close(); + } + + @Override + public byte[] getDriveName() { + return this.driveName; + } + + @Override + public byte[] getDriveSerial() { + return this.driveSerial; + } + + @Override + public void seek(int location) throws IOException { + this.channel.position(location); + } + + @Override + public void read(ByteBuffer buffer) throws IOException { + this.channel.read(buffer); + } + + @Override + public void write(ByteBuffer buffer) throws IOException { + this.channel.write(buffer); + } + + @Override + public void writeDiskName(byte[] diskName) throws IOException { + // TODO This does nothing + } +} diff --git a/src/main/java/net/brokenmoon/redcontrol/api/uxn/MMIOWrappingByteBuffer.kt b/src/main/java/net/brokenmoon/redcontrol/api/uxn/MMIOWrappingByteBuffer.kt new file mode 100644 index 0000000..6e700f1 --- /dev/null +++ b/src/main/java/net/brokenmoon/redcontrol/api/uxn/MMIOWrappingByteBuffer.kt @@ -0,0 +1,6 @@ +package net.brokenmoon.redcontrol.api.uxn + +import net.walksanator.uxnkt.vm.WrappingByteArray + +class MMIOWrappingByteArray : WrappingByteArray(0x10000git st) { +} \ No newline at end of file diff --git a/src/main/java/net/brokenmoon/redcontrol/api/uxn/MinecraftComputer.kt b/src/main/java/net/brokenmoon/redcontrol/api/uxn/MinecraftComputer.kt new file mode 100644 index 0000000..793d6e8 --- /dev/null +++ b/src/main/java/net/brokenmoon/redcontrol/api/uxn/MinecraftComputer.kt @@ -0,0 +1,17 @@ +package net.brokenmoon.redcontrol.api.uxn + +import net.walksanator.uxnkt.vm.Computer +import net.walksanator.uxnkt.vm.Uxn +import java.util.function.Consumer + +class MinecraftComputer(cpu: Uxn) : Computer(cpu) { + + + override fun queue(prerun: Consumer) { + TODO("Not yet implemented") + } + + override fun run() { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java b/src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java index 952e695..fc005c8 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java +++ b/src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java @@ -1,6 +1,5 @@ package net.brokenmoon.redcontrol.blockentities; -import com.simon816.j65el02.device.RedBus; import net.brokenmoon.redcontrol.RedControl; import net.brokenmoon.redcontrol.api.*; import net.brokenmoon.redcontrol.blocks.NetworkCarrier; @@ -16,7 +15,6 @@ import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; public class CpuEntity extends Peripheral implements CpuControl { - public int i = 0; public boolean notTicked = true; public Emulator core = new Emulator(new RedBus()); @@ -30,8 +28,6 @@ public class CpuEntity extends Peripheral implements CpuControl { private int resetTimer = 5; - - public CpuEntity(BlockPos pos, BlockState state) { super(RedControl.CPU_BLOCK_ENTITY, pos, state, 0); } @@ -99,30 +95,9 @@ public class CpuEntity extends Peripheral implements CpuControl { } public void step() { - i++; - core.step(); - } - - @Override - public void write(int address, int data) { - - } - @Override - public int read(int address) { - return 0; } - @Override - public void update() {} - - @Override - public void setBus(RCWorldBus bus){ - this.bus = bus.getRedBus(); - this.core.setBus(this.bus); - this.bus.setPeripheral(id, this); - this.worldBus = bus; - } @Nullable @Override diff --git a/src/main/java/net/brokenmoon/redcontrol/blockentities/DriveEntity.java b/src/main/java/net/brokenmoon/redcontrol/blockentities/DriveEntity.java index c769b1b..97c50b7 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blockentities/DriveEntity.java +++ b/src/main/java/net/brokenmoon/redcontrol/blockentities/DriveEntity.java @@ -1,9 +1,8 @@ package net.brokenmoon.redcontrol.blockentities; -import com.simon816.j65el02.device.DiskDriver; import net.brokenmoon.redcontrol.RedControl; -import net.brokenmoon.redcontrol.api.DriveFactory; import net.brokenmoon.redcontrol.api.Peripheral; +import net.brokenmoon.redcontrol.api.drive.DiskDriver; import net.brokenmoon.redcontrol.item.FloppyDisk; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; diff --git a/src/main/java/net/brokenmoon/redcontrol/blocks/NetworkCarrier.java b/src/main/java/net/brokenmoon/redcontrol/blocks/NetworkCarrier.java index 3a5dd18..ee59ae7 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blocks/NetworkCarrier.java +++ b/src/main/java/net/brokenmoon/redcontrol/blocks/NetworkCarrier.java @@ -1,11 +1,9 @@ package net.brokenmoon.redcontrol.blocks; -import com.simon816.j65el02.device.RedBus; import net.brokenmoon.redcontrol.RedControl; +import net.brokenmoon.redcontrol.api.DeviceBus; import net.brokenmoon.redcontrol.api.NetworkHolder; -import net.brokenmoon.redcontrol.api.RCWorldBus; import net.brokenmoon.redcontrol.api.Peripheral; -import net.brokenmoon.redcontrol.mixin.RedBusAccessor; import net.minecraft.block.*; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; @@ -20,6 +18,7 @@ import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.walksanator.uxnkt.vm.IDevice; import org.jetbrains.annotations.Nullable; public abstract class NetworkCarrier extends BlockWithEntity implements BlockEntityProvider, NetworkHolder { @@ -27,11 +26,11 @@ public abstract class NetworkCarrier extends BlockWithEntity implements BlockEnt super(settings); } - public RCWorldBus getBus(World world, BlockPos pos){ + public DeviceBus getBus(World world, BlockPos pos){ return ((Peripheral)world.getBlockEntity(pos)).getBus(); } - public void setBus(World world, BlockPos pos, RCWorldBus bus){ + public void setBus(World world, BlockPos pos, DeviceBus bus){ ((Peripheral)world.getBlockEntity(pos)).setBus(bus); } @@ -69,8 +68,8 @@ public abstract class NetworkCarrier extends BlockWithEntity implements BlockEnt player.sendMessage(Text.literal(" " + Integer.toHexString(peripheral.getBus().hashCode())), false); player.sendMessage(Text.literal(" " + Integer.toHexString(peripheral.getBus().getRedBus().hashCode())), false); player.sendMessage(Text.literal(" Peripherals on RedBus: "), false); - RedBus.Peripheral[] peripherals = ((RedBusAccessor) peripheral.getBus().getRedBus()).getPeripherals(); - for (RedBus.Peripheral value : peripherals) { + IDevice[] peripherals = peripheral.getBus().getDevices(); + for (IDevice value : peripherals) { if (value != null) { player.sendMessage(Text.literal(" " + value.getClass().toString()), false); } diff --git a/src/main/java/net/brokenmoon/redcontrol/blocks/Terminal.kt b/src/main/java/net/brokenmoon/redcontrol/blocks/Terminal.kt index d03edd7..edc6b61 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blocks/Terminal.kt +++ b/src/main/java/net/brokenmoon/redcontrol/blocks/Terminal.kt @@ -23,6 +23,7 @@ import net.minecraft.util.Hand import net.minecraft.util.hit.BlockHitResult import net.minecraft.util.math.BlockPos import net.minecraft.world.World +import net.walksanator.uxnkt.vm.Uxn import java.io.FileNotFoundException import kotlin.experimental.xor @@ -57,6 +58,10 @@ class TerminalBlock(settings: Settings) : NetworkCarrier(settings) { class TerminalEntity(pos: BlockPos, state: BlockState) : Peripheral(RedControl.TERMINAL_BLOCK_ENTITY, pos, state,1) { + override fun postTick(uxn: Uxn) = update() + override fun readByte(address: Byte): Byte = readData(address) + override fun writeByte(address: Byte, byte: Byte) = storeData(address,byte) + val screen = ByteArray(80 * 50) { 0x20 } val charset = RedControl.images["charset.bin"]?.clone()?: throw FileNotFoundException("expected a charset.bin in images datapack") val kb = ByteArray(16) @@ -109,8 +114,7 @@ class TerminalEntity(pos: BlockPos, state: BlockState) : Peripheral(RedControl.T } } - override fun read(address: Int): Int = readData(address.toByte()).toInt() - override fun update() { + fun update() { val data = this var error = false @@ -130,8 +134,6 @@ class TerminalEntity(pos: BlockPos, state: BlockState) : Peripheral(RedControl.T data.command = if (error) -1 else 0 } - override fun write(address: Int, data: Int) = storeData(address.toByte(),data.toByte()) - private fun readData(at: Byte): Byte { return when (val at = at.unsigned) { 0x00 -> row.toByte() diff --git a/src/main/java/net/brokenmoon/redcontrol/mixin/BusAccessor.java b/src/main/java/net/brokenmoon/redcontrol/mixin/BusAccessor.java deleted file mode 100644 index 0ec7097..0000000 --- a/src/main/java/net/brokenmoon/redcontrol/mixin/BusAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.brokenmoon.redcontrol.mixin; - -import com.simon816.j65el02.Bus; -import com.simon816.j65el02.device.RedBus; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(Bus.class) -public interface BusAccessor { - @Accessor(value = "redBus",remap = false) - void setRedBus(RedBus redBus); -} diff --git a/src/main/java/net/brokenmoon/redcontrol/mixin/CpuAccessor.java b/src/main/java/net/brokenmoon/redcontrol/mixin/CpuAccessor.java deleted file mode 100644 index 1dc6f48..0000000 --- a/src/main/java/net/brokenmoon/redcontrol/mixin/CpuAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.brokenmoon.redcontrol.mixin; - -import com.simon816.j65el02.Cpu; -import com.simon816.j65el02.CpuState; -import com.simon816.j65el02.device.RedBusState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(Cpu.class) -public interface CpuAccessor { - @Accessor(value = "redBusState",remap = false) - RedBusState getRedBusState(); - @Accessor(value = "state",remap = false) - CpuState getState(); -} diff --git a/src/main/java/net/brokenmoon/redcontrol/mixin/MemoryAccessor.java b/src/main/java/net/brokenmoon/redcontrol/mixin/MemoryAccessor.java deleted file mode 100644 index 55fa670..0000000 --- a/src/main/java/net/brokenmoon/redcontrol/mixin/MemoryAccessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.brokenmoon.redcontrol.mixin; - -import com.simon816.j65el02.device.Memory; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(Memory.class) -public interface MemoryAccessor { - @Accessor(value = "mem",remap = false) - byte[] getMem(); - @Accessor(value = "mem",remap = false) - void setMem(byte[] mem); -} diff --git a/src/main/java/net/brokenmoon/redcontrol/mixin/RedBusAccessor.java b/src/main/java/net/brokenmoon/redcontrol/mixin/RedBusAccessor.java deleted file mode 100644 index 212b4cc..0000000 --- a/src/main/java/net/brokenmoon/redcontrol/mixin/RedBusAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.brokenmoon.redcontrol.mixin; - -import com.simon816.j65el02.device.RedBus; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(RedBus.class) -public interface RedBusAccessor { - @Accessor(value = "peripherals",remap = false) - RedBus.Peripheral[] getPeripherals(); - -} diff --git a/src/main/java/net/brokenmoon/redcontrol/util/FloodFill.kt b/src/main/java/net/brokenmoon/redcontrol/util/FloodFill.kt index a2aea06..4789510 100644 --- a/src/main/java/net/brokenmoon/redcontrol/util/FloodFill.kt +++ b/src/main/java/net/brokenmoon/redcontrol/util/FloodFill.kt @@ -1,9 +1,8 @@ package net.brokenmoon.redcontrol.util import net.brokenmoon.redcontrol.RedControl +import net.brokenmoon.redcontrol.api.DeviceBus import net.brokenmoon.redcontrol.api.NetworkHolder -import net.brokenmoon.redcontrol.api.RCWorldBus -import net.brokenmoon.redcontrol.blocks.NetworkCarrier import net.minecraft.particle.ParticleTypes import net.minecraft.server.world.ServerWorld import net.minecraft.util.math.BlockPos @@ -13,7 +12,7 @@ object FloodFill { fun blockFloodFiller(world: ServerWorld, seed: BlockPos) { val checkable = mutableListOf(seed) val seen = mutableListOf() - var bus: RCWorldBus? = null + var bus: DeviceBus? = null while (checkable.isNotEmpty()) { val pos = checkable.removeFirst() if (pos in seen) {continue} @@ -58,7 +57,7 @@ object FloodFill { seen.add(pos) val nc = (state.block as? NetworkHolder) if (nc != null) { - nc.getBus(world,pos).valid = false + nc.getBus(world,pos).isValid = false val cpos = pos.toCenterPos() world.spawnParticles(ParticleTypes.WAX_OFF,cpos.x,cpos.y,cpos.z,20,0.6,0.6,0.6,0.2) } diff --git a/src/main/resources/redcontrol.mixins.json b/src/main/resources/redcontrol.mixins.json index fc14a4e..d18efe9 100644 --- a/src/main/resources/redcontrol.mixins.json +++ b/src/main/resources/redcontrol.mixins.json @@ -3,11 +3,7 @@ "package": "net.brokenmoon.redcontrol.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "BusAccessor", - "CpuAccessor", "ExampleMixin", - "MemoryAccessor", - "RedBusAccessor", "WorldMixin" ], "injectors": {