Minimalistic - "Well-it-enumerates-I-guess" PCI impl
@@ -20,6 +20,8 @@ public final class Config {
|
||||
@Path("energy.blocks") public static int chargerEnergyStorage = 10000;
|
||||
@Path("energy.blocks") public static int projectorEnergyPerTick = 20;
|
||||
@Path("energy.blocks") public static int projectorEnergyStorage = 2000;
|
||||
@Path("energy.blocks") public static int cardCageEnergyPerTick = 20;
|
||||
@Path("energy.blocks") public static int cardCageEnergyStorage = 2000;
|
||||
|
||||
@Path("energy.entities") public static int robotEnergyPerTick = 5;
|
||||
@Path("energy.entities") public static int robotEnergyStorage = 750000;
|
||||
@@ -60,6 +62,10 @@ public final class Config {
|
||||
return projectorEnergyStorage > 0 && projectorEnergyPerTick > 0;
|
||||
}
|
||||
|
||||
public static boolean cardCagesUseEnergy() {
|
||||
return cardCageEnergyStorage > 0 && cardCageEnergyPerTick > 0;
|
||||
}
|
||||
|
||||
public static boolean robotsUseEnergy() {
|
||||
return robotEnergyPerTick > 0 && robotEnergyStorage > 0;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
package li.cil.oc2.common.block;
|
||||
|
||||
import li.cil.oc2.common.blockentity.VxlanBlockEntity;
|
||||
import li.cil.oc2.common.util.RegistryUtils;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
@@ -25,6 +27,8 @@ public final class Blocks {
|
||||
public static final RegistryObject<ProjectorBlock> PROJECTOR = BLOCKS.register("projector", ProjectorBlock::new);
|
||||
public static final RegistryObject<RedstoneInterfaceBlock> REDSTONE_INTERFACE = BLOCKS.register("redstone_interface", RedstoneInterfaceBlock::new);
|
||||
public static final RegistryObject<VxlanBlock> VXLAN_HUB = BLOCKS.register("vxlan_hub", VxlanBlock::new);
|
||||
public static final RegistryObject<PciCardCageBlock> PCI_CARD_CAGE = BLOCKS.register("pci_card_cage", PciCardCageBlock::new);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
100
src/main/java/li/cil/oc2/common/block/PciCardCageBlock.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.block;
|
||||
|
||||
import li.cil.oc2.common.Config;
|
||||
import li.cil.oc2.common.blockentity.BlockEntities;
|
||||
import li.cil.oc2.common.blockentity.TickableBlockEntity;
|
||||
import li.cil.oc2.common.util.VoxelShapeUtils;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class PciCardCageBlock extends HorizontalDirectionalBlock implements EntityBlock, EnergyConsumingBlock {
|
||||
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
||||
|
||||
// We bake the visual indents on the front and sides into the collision shape, to prevent stuff being
|
||||
// placeable on those sides, such as network connectors, torches, etc.
|
||||
private static final VoxelShape NEG_Z_SHAPE = Shapes.join(Shapes.block(), Shapes.or(
|
||||
Shapes.box(0 / 16f, 2 / 16f, 2 / 16f, 1 / 16f, 6 / 16f, 14 / 16f),
|
||||
Shapes.box(15 / 16f, 2 / 16f, 2 / 16f, 16 / 16f, 6 / 16f, 14 / 16f),
|
||||
Shapes.box(4 / 16f, 4 / 16f, 0 / 16f, 12 / 16f, 12 / 16f, 2 / 16f)
|
||||
), (a, b) -> a && !b);
|
||||
private static final VoxelShape NEG_X_SHAPE = VoxelShapeUtils.rotateHorizontalClockwise(NEG_Z_SHAPE);
|
||||
private static final VoxelShape POS_Z_SHAPE = VoxelShapeUtils.rotateHorizontalClockwise(NEG_X_SHAPE);
|
||||
private static final VoxelShape POS_X_SHAPE = VoxelShapeUtils.rotateHorizontalClockwise(POS_Z_SHAPE);
|
||||
|
||||
public PciCardCageBlock() {
|
||||
super(Properties
|
||||
.of(Material.METAL)
|
||||
.sound(SoundType.METAL)
|
||||
.lightLevel(state -> state.getValue(LIT) ? 8 : 0)
|
||||
.strength(1.5f, 6.0f));
|
||||
registerDefaultState(getStateDefinition().any()
|
||||
.setValue(FACING, Direction.NORTH)
|
||||
.setValue(LIT, false));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public int getEnergyConsumption() {
|
||||
if (Config.cardCagesUseEnergy()) {
|
||||
return Config.cardCageEnergyPerTick;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(final BlockPos pos, final BlockState state) {
|
||||
return BlockEntities.PCI_CARD_CAGE.get().create(pos, state);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(final Level level, final BlockState state, final BlockEntityType<T> type) {
|
||||
return TickableBlockEntity.createServerTicker(level, type, BlockEntities.PROJECTOR.get());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public VoxelShape getShape(final BlockState state, final BlockGetter level, final BlockPos blockPos, final CollisionContext context) {
|
||||
return switch (state.getValue(FACING)) {
|
||||
case NORTH -> NEG_Z_SHAPE;
|
||||
case SOUTH -> POS_Z_SHAPE;
|
||||
case WEST -> NEG_X_SHAPE;
|
||||
default -> POS_X_SHAPE;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(final BlockPlaceContext context) {
|
||||
return super.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING, LIT);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,8 @@ public final class BlockEntities {
|
||||
public static final RegistryObject<BlockEntityType<ProjectorBlockEntity>> PROJECTOR = register(Blocks.PROJECTOR, ProjectorBlockEntity::new);
|
||||
public static final RegistryObject<BlockEntityType<RedstoneInterfaceBlockEntity>> REDSTONE_INTERFACE = register(Blocks.REDSTONE_INTERFACE, RedstoneInterfaceBlockEntity::new);
|
||||
public static final RegistryObject<BlockEntityType<VxlanBlockEntity>> VXLAN_HUB = register(Blocks.VXLAN_HUB, VxlanBlockEntity::new);
|
||||
public static final RegistryObject<BlockEntityType<PciCardCageBlockEntity>> PCI_CARD_CAGE = register(Blocks.PCI_CARD_CAGE, PciCardCageBlockEntity::new);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.blockentity;
|
||||
|
||||
import li.cil.oc2.common.Config;
|
||||
import li.cil.oc2.common.block.PciCardCageBlock;
|
||||
import li.cil.oc2.common.bus.device.vm.block.PciCardCageDevice;
|
||||
import li.cil.oc2.common.capabilities.Capabilities;
|
||||
import li.cil.oc2.common.energy.FixedEnergyStorage;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
public final class PciCardCageBlockEntity extends ModBlockEntity implements TickableBlockEntity {
|
||||
|
||||
private static final String ENERGY_TAG_NAME = "energy";
|
||||
private static final String HAS_ENERGY_TAG_NAME = "has_energy";
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private final PciCardCageDevice cardCageDevice = new PciCardCageDevice(this, this::handleMountedChanged);
|
||||
private boolean isMounted, hasEnergy;
|
||||
private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.cardCageEnergyStorage);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
public PciCardCageBlockEntity(final BlockPos pos, final BlockState state) {
|
||||
super(BlockEntities.PCI_CARD_CAGE.get(), pos, state);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private void handleMountedChanged(final boolean value) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean hasEnergy() {
|
||||
return hasEnergy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serverTick() {
|
||||
if (!isMounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean isPowered;
|
||||
if (Config.cardCagesUseEnergy()) {
|
||||
isPowered = energy.extractEnergy(Config.cardCageEnergyPerTick, true) >= Config.cardCageEnergyPerTick;
|
||||
if (isPowered) {
|
||||
energy.extractEnergy(Config.cardCageEnergyPerTick, false);
|
||||
}
|
||||
} else {
|
||||
isPowered = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpdateTag() {
|
||||
final CompoundTag tag = super.getUpdateTag();
|
||||
|
||||
tag.putBoolean(HAS_ENERGY_TAG_NAME, hasEnergy);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpdateTag(final CompoundTag tag) {
|
||||
super.handleUpdateTag(tag);
|
||||
|
||||
hasEnergy = tag.getBoolean(HAS_ENERGY_TAG_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(final CompoundTag tag) {
|
||||
super.saveAdditional(tag);
|
||||
|
||||
tag.put(ENERGY_TAG_NAME, energy.serializeNBT());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(final CompoundTag tag) {
|
||||
super.load(tag);
|
||||
|
||||
energy.deserializeNBT(tag.getCompound(ENERGY_TAG_NAME));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void setBlockState(final BlockState state) {
|
||||
super.setBlockState(state);
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void collectCapabilities(final CapabilityCollector collector, @Nullable final Direction direction) {
|
||||
if (Config.cardCagesUseEnergy()) {
|
||||
collector.offer(Capabilities.energyStorage(), energy);
|
||||
}
|
||||
|
||||
if (direction == getBlockState().getValue(PciCardCageBlock.FACING).getOpposite()) {
|
||||
collector.offer(Capabilities.device(), cardCageDevice);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.bus.device.vm.block;
|
||||
|
||||
import it.unimi.dsi.fastutil.booleans.BooleanConsumer;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDevice;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult;
|
||||
import li.cil.oc2.api.bus.device.vm.context.VMContext;
|
||||
import li.cil.oc2.common.Constants;
|
||||
import li.cil.oc2.common.bus.device.util.IdentityProxy;
|
||||
import li.cil.oc2.common.bus.device.util.OptionalAddress;
|
||||
import li.cil.oc2.common.serialization.BlobStorage;
|
||||
import li.cil.oc2.common.util.NBTTagIds;
|
||||
import li.cil.oc2.common.vm.device.PciRootPortDevice;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class PciCardCageDevice extends IdentityProxy<BlockEntity> implements VMDevice {
|
||||
private static final String ADDRESS_TAG_NAME = "address";
|
||||
private static final String BLOB_HANDLE_TAG_NAME = "blob";
|
||||
|
||||
public static final int BUS_COUNT = 16;
|
||||
public static final int WINDOW_SIZE = 16 * 1024 * 1024;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private final BooleanConsumer onMountedChanged;
|
||||
|
||||
@Nullable private PciRootPortDevice device;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private final OptionalAddress address = new OptionalAddress();
|
||||
@Nullable private UUID blobHandle;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
public PciCardCageDevice(final BlockEntity identity, final BooleanConsumer onMountedChanged) {
|
||||
super(identity);
|
||||
this.onMountedChanged = onMountedChanged;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public VMDeviceLoadResult mount(final VMContext context) {
|
||||
if (!allocateDevice(context)) {
|
||||
return VMDeviceLoadResult.fail();
|
||||
}
|
||||
|
||||
assert device != null;
|
||||
if (!address.claim(context, device)) {
|
||||
return VMDeviceLoadResult.fail();
|
||||
}
|
||||
|
||||
onMountedChanged.accept(true);
|
||||
|
||||
return VMDeviceLoadResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unmount() {
|
||||
final PciRootPortDevice pciRootPortDevice = device;
|
||||
device = null;
|
||||
if (pciRootPortDevice != null) {
|
||||
pciRootPortDevice.close();
|
||||
}
|
||||
|
||||
if (blobHandle != null) {
|
||||
BlobStorage.close(blobHandle);
|
||||
}
|
||||
|
||||
onMountedChanged.accept(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (blobHandle != null) {
|
||||
BlobStorage.delete(blobHandle);
|
||||
blobHandle = null;
|
||||
}
|
||||
|
||||
address.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeNBT() {
|
||||
final CompoundTag tag = new CompoundTag();
|
||||
|
||||
if (blobHandle != null) {
|
||||
tag.putUUID(BLOB_HANDLE_TAG_NAME, blobHandle);
|
||||
}
|
||||
if (address.isPresent()) {
|
||||
tag.putLong(ADDRESS_TAG_NAME, address.getAsLong());
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(final CompoundTag tag) {
|
||||
if (tag.hasUUID(BLOB_HANDLE_TAG_NAME)) {
|
||||
blobHandle = tag.getUUID(BLOB_HANDLE_TAG_NAME);
|
||||
}
|
||||
if (tag.contains(ADDRESS_TAG_NAME, NBTTagIds.TAG_LONG)) {
|
||||
address.set(tag.getLong(ADDRESS_TAG_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private boolean allocateDevice(final VMContext context) {
|
||||
if (!context.getMemoryAllocator().claimMemory(Constants.PAGE_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
device = createPciRootPortDevice();
|
||||
} catch (final IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private PciRootPortDevice createPciRootPortDevice() throws IOException {
|
||||
blobHandle = BlobStorage.validateHandle(blobHandle);
|
||||
final FileChannel channel = BlobStorage.getOrOpen(blobHandle);
|
||||
final MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, WINDOW_SIZE * 2);
|
||||
return new PciRootPortDevice(BUS_COUNT, WINDOW_SIZE, buffer);
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ public final class Items {
|
||||
public static final RegistryObject<Item> PROJECTOR = register(Blocks.PROJECTOR);
|
||||
public static final RegistryObject<Item> REDSTONE_INTERFACE = register(Blocks.REDSTONE_INTERFACE);
|
||||
public static final RegistryObject<Item> VXLAN_HUB = register(Blocks.VXLAN_HUB);
|
||||
public static final RegistryObject<Item> PCI_CARD_CAGE = register(Blocks.PCI_CARD_CAGE);
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
|
||||
state.board.getCpu().setFrequency(Constants.CPU_FREQUENCY);
|
||||
state.board.setBootArguments("root=/dev/vda rw");
|
||||
state.board.setStandardOutputDevice(state.builtinDevices.uart);
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.vm.device;
|
||||
|
||||
import li.cil.sedna.api.device.MemoryMappedDevice;
|
||||
import li.cil.sedna.api.memory.MemoryAccessException;
|
||||
import li.cil.sedna.utils.DirectByteBufferUtils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
||||
public final class PciRootPortDevice implements MemoryMappedDevice {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private final ByteBuffer buffer;
|
||||
private int length;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
public PciRootPortDevice(final int bus_count, final int window_size, final ByteBuffer buffer) {
|
||||
|
||||
length = window_size * 2;
|
||||
if (buffer.capacity() < length) {
|
||||
throw new IllegalArgumentException("Buffer too small.");
|
||||
}
|
||||
|
||||
this.buffer = buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
this.buffer.putInt(0, 0x12345678);
|
||||
this.buffer.putInt(4, 0);
|
||||
this.buffer.putInt(8, 0xFF000000);
|
||||
this.buffer.putInt(12, 0x00000101);
|
||||
this.buffer.putInt(16, 0x40000000);
|
||||
this.buffer.putInt(0x2C, 0x12345678);
|
||||
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
public void close() {
|
||||
synchronized (buffer) {
|
||||
length = 0;
|
||||
DirectByteBufferUtils.release(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean hasChanges() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long load(final int offset, final int sizeLog2) throws MemoryAccessException {
|
||||
if (offset >= 0 && offset <= length - (1 << sizeLog2)) {
|
||||
System.out.println(String.format("PCI config read: %x", offset));
|
||||
return switch (sizeLog2) {
|
||||
case 0 -> buffer.get(offset);
|
||||
case 1 -> buffer.getShort(offset);
|
||||
case 2 -> buffer.getInt(offset);
|
||||
case 3 -> buffer.getLong(offset);
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(final int offset, final long value, final int sizeLog2) throws MemoryAccessException {
|
||||
if (offset >= 0 && offset <= length - (1 << sizeLog2)) {
|
||||
System.out.println(String.format("PCI config write: %x %x %x", offset, value, sizeLog2));
|
||||
switch (sizeLog2) {
|
||||
case 0 -> buffer.put(offset, (byte) value);
|
||||
case 1 -> buffer.putShort(offset, (short) value);
|
||||
case 2 -> buffer.putInt(offset, (int) value);
|
||||
case 3 -> buffer.putLong(offset, value);
|
||||
default -> throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
package li.cil.oc2.common.vm.provider;
|
||||
|
||||
import li.cil.oc2.common.vm.device.PciRootPortDevice;
|
||||
import li.cil.oc2.common.vm.device.SimpleFramebufferDevice;
|
||||
import li.cil.sedna.devicetree.DeviceTreeRegistry;
|
||||
|
||||
public final class DeviceTreeProviders {
|
||||
public static void initialize() {
|
||||
DeviceTreeRegistry.putProvider(SimpleFramebufferDevice.class, new SimpleFramebufferDeviceProvider());
|
||||
DeviceTreeRegistry.putProvider(PciRootPortDevice.class, new PciRootPortDeviceProvider());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.vm.provider;
|
||||
|
||||
import li.cil.oc2.common.vm.device.PciRootPortDevice;
|
||||
import li.cil.sedna.api.device.Device;
|
||||
import li.cil.sedna.api.device.MemoryMappedDevice;
|
||||
import li.cil.sedna.api.devicetree.DeviceNames;
|
||||
import li.cil.sedna.api.devicetree.DevicePropertyNames;
|
||||
import li.cil.sedna.api.devicetree.DeviceTree;
|
||||
import li.cil.sedna.api.devicetree.DeviceTreeProvider;
|
||||
import li.cil.sedna.api.memory.MappedMemoryRange;
|
||||
import li.cil.sedna.api.memory.MemoryMap;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class PciRootPortDeviceProvider implements DeviceTreeProvider {
|
||||
@Override
|
||||
public Optional<String> getName(final Device device) {
|
||||
return Optional.of("pci");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DeviceTree> createNode(final DeviceTree root, final MemoryMap memoryMap, final Device device, final String deviceName) {
|
||||
final Optional<MappedMemoryRange> range = memoryMap.getMemoryRange((MemoryMappedDevice) device);
|
||||
return range.map(r -> {
|
||||
final DeviceTree chosen = root.find("/soc");
|
||||
//chosen.addProp(DevicePropertyNames.RANGES);
|
||||
|
||||
return chosen.getChild(deviceName, r.address());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(final DeviceTree node, final MemoryMap memoryMap, final Device device) {
|
||||
final PciRootPortDevice pr = (PciRootPortDevice) device;
|
||||
final Optional<MappedMemoryRange> range = memoryMap.getMemoryRange((MemoryMappedDevice) device);
|
||||
node
|
||||
.addProp(DevicePropertyNames.COMPATIBLE, "pci-host-cam-generic")
|
||||
.addProp(DevicePropertyNames.DEVICE_TYPE, DeviceNames.PCI)
|
||||
.addProp(DevicePropertyNames.NUM_ADDRESS_CELLS,3)
|
||||
.addProp(DevicePropertyNames.NUM_SIZE_CELLS, 2)
|
||||
.addProp("bus-range", 0, 1)
|
||||
.addProp("linux,pci-probe-only", 1)
|
||||
.addProp(DevicePropertyNames.RANGES, 0x02000000, 0, 0x40000000, 0x40000000, 0, 0x20000000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public final class SimpleFramebufferDeviceProvider implements DeviceTreeProvider
|
||||
final Optional<MappedMemoryRange> range = memoryMap.getMemoryRange((MemoryMappedDevice) device);
|
||||
return range.map(r -> {
|
||||
final DeviceTree chosen = root.find("/chosen");
|
||||
chosen.addProp(DevicePropertyNames.RANGES);
|
||||
//chosen.addProp(DevicePropertyNames.RANGES);
|
||||
|
||||
return chosen.getChild(deviceName, r.address());
|
||||
});
|
||||
|
||||
@@ -28,6 +28,8 @@ public final class ModBlockStateProvider extends BlockStateProvider {
|
||||
private static final ResourceLocation NETWORK_HUB_MODEL = new ResourceLocation(API.MOD_ID, "block/network_hub");
|
||||
private static final ResourceLocation PROJECTOR_MODEL = new ResourceLocation(API.MOD_ID, "block/projector");
|
||||
private static final ResourceLocation REDSTONE_INTERFACE_MODEL = new ResourceLocation(API.MOD_ID, "block/redstone_interface");
|
||||
private static final ResourceLocation PCI_CARD_CAGE_MODEL = new ResourceLocation(API.MOD_ID, "block/pci_card_cage");
|
||||
|
||||
|
||||
public ModBlockStateProvider(final DataGenerator generator, final ExistingFileHelper existingFileHelper) {
|
||||
super(generator, API.MOD_ID, existingFileHelper);
|
||||
@@ -57,6 +59,7 @@ public final class ModBlockStateProvider extends BlockStateProvider {
|
||||
horizontalBlock(Blocks.NETWORK_SWITCH, Items.NETWORK_SWITCH, NETWORK_HUB_MODEL);
|
||||
horizontalBlock(Blocks.PROJECTOR, Items.PROJECTOR, PROJECTOR_MODEL);
|
||||
horizontalBlock(Blocks.REDSTONE_INTERFACE, Items.REDSTONE_INTERFACE, REDSTONE_INTERFACE_MODEL);
|
||||
horizontalBlock(Blocks.PCI_CARD_CAGE, Items.PCI_CARD_CAGE, PCI_CARD_CAGE_MODEL);
|
||||
|
||||
registerCableStates();
|
||||
}
|
||||
|
||||
34
src/main/resources/assets/oc2/blockstates/pci_card_cage.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=north,lit=false": {
|
||||
"model": "oc2:block/pci_card_cage"
|
||||
},
|
||||
"facing=south,lit=false": {
|
||||
"model": "oc2:block/pci_card_cage",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,lit=false": {
|
||||
"model": "oc2:block/pci_card_cage",
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,lit=false": {
|
||||
"model": "oc2:block/pci_card_cage",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,lit=true": {
|
||||
"model": "oc2:block/pci_card_cage"
|
||||
},
|
||||
"facing=south,lit=true": {
|
||||
"model": "oc2:block/pci_card_cage",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,lit=true": {
|
||||
"model": "oc2:block/pci_card_cage",
|
||||
"y": 270
|
||||
},
|
||||
"facing=east,lit=true": {
|
||||
"model": "oc2:block/pci_card_cage",
|
||||
"y": 90
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "oc2:block/pci_card_cage"
|
||||
}
|
||||
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 628 B |