From b3dd00b90be42397f377209337600c701398aa21 Mon Sep 17 00:00:00 2001 From: Peter Jakubco Date: Sun, 19 Feb 2023 14:18:58 +0100 Subject: [PATCH] [#318] TAP loader in memory --- .../bytemem/gui/actions/LoadImageAction.java | 4 +- .../memory/bytemem/loaders/BinaryLoader.java | 15 ++--- .../memory/bytemem/loaders/TapLoader.java | 60 ++++++++++++++++++- .../memory/bytemem/loaders/TzxLoader.java | 4 +- 4 files changed, 69 insertions(+), 14 deletions(-) diff --git a/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/gui/actions/LoadImageAction.java b/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/gui/actions/LoadImageAction.java index 5903c3689..e48309bbc 100644 --- a/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/gui/actions/LoadImageAction.java +++ b/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/gui/actions/LoadImageAction.java @@ -42,12 +42,14 @@ public void actionPerformed(ActionEvent e) { false, IMAGE_EXTENSION_FILTER); imagePath.ifPresent(path -> { Loader loader = Loader.createLoader(path); - Loader.MemoryBank bank = askForMemoryBank(loader.isMemoryAddressAware()); + Loader.MemoryBank bank = askForMemoryBank(!loader.isMemoryAddressAware()); try { loader.load(path, context, bank); repaint.run(); } catch (Exception ex) { dialogs.showError("Could not load selected image file: " + ex.getMessage(), "Load image file"); + + ex.printStackTrace(); } }); } diff --git a/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/BinaryLoader.java b/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/BinaryLoader.java index 2f641b86d..62c31c1b6 100644 --- a/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/BinaryLoader.java +++ b/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/BinaryLoader.java @@ -18,9 +18,10 @@ */ package net.emustudio.plugins.memory.bytemem.loaders; +import net.emustudio.emulib.runtime.helpers.NumberUtils; import net.emustudio.plugins.memory.bytemem.api.ByteMemoryContext; -import java.io.RandomAccessFile; +import java.io.FileInputStream; import java.nio.file.Path; public class BinaryLoader implements Loader { @@ -33,15 +34,11 @@ public boolean isMemoryAddressAware() { @Override public void load(Path path, ByteMemoryContext memory, MemoryBank bank) throws Exception { int oldBank = memory.getSelectedBank(); - try (RandomAccessFile binaryFile = new RandomAccessFile(path.toFile(), "r")) { - memory.selectBank(bank.bank); - long position = 0, length = binaryFile.length(); - int address = bank.address; - while (position < length) { - memory.write(address++, (byte) (binaryFile.readUnsignedByte() & 0xFF)); - position++; - } + try (FileInputStream stream = new FileInputStream(path.toFile())) { + memory.selectBank(bank.bank); + byte[] content = stream.readAllBytes(); + memory.write(bank.address, NumberUtils.nativeBytesToBytes(content)); } catch (Exception e) { memory.selectBank(oldBank); throw e; diff --git a/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/TapLoader.java b/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/TapLoader.java index bd5d1372b..04c88452b 100644 --- a/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/TapLoader.java +++ b/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/TapLoader.java @@ -18,19 +18,75 @@ */ package net.emustudio.plugins.memory.bytemem.loaders; +import net.emustudio.emulib.runtime.helpers.NumberUtils; import net.emustudio.plugins.memory.bytemem.api.ByteMemoryContext; +import java.io.FileInputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.file.Path; +import java.util.Optional; -public class TapLoader implements Loader { +public class TapLoader implements Loader { @Override public boolean isMemoryAddressAware() { - return true; + // Tape is usually loaded by BASIC; interprets program start line to address; it depends on emulated machine.. + return false; } @Override public void load(Path path, ByteMemoryContext memory, MemoryBank bank) throws Exception { + int oldBank = memory.getSelectedBank(); + try (FileInputStream stream = new FileInputStream(path.toFile())) { + memory.selectBank(bank.bank); + parse(stream.readAllBytes(), bank.address, memory); + } catch (Exception e) { + memory.selectBank(oldBank); + throw e; + } + } + + private void parse(byte[] content, int address, ByteMemoryContext memory) { + Optional startAddress = Optional.empty(); + + ByteBuffer buffer = ByteBuffer.wrap(content); + buffer.order(ByteOrder.LITTLE_ENDIAN); + while (buffer.position() < buffer.limit()) { + int blockLength = buffer.getShort() & 0xFFFF; + int flagByte = buffer.get() & 0xFF; + + if (flagByte == 0) { + final Optional javaFail = startAddress; + startAddress = parseHeader(buffer).or(() -> javaFail); + } else { + byte[] data = new byte[blockLength - 2]; + buffer.get(data); + + if (startAddress.isPresent()) { + memory.write(startAddress.get(), NumberUtils.nativeBytesToBytes(data)); + } else { + memory.write(0, NumberUtils.nativeBytesToBytes(data)); + startAddress = Optional.of(data.length); + } + } + buffer.get(); // checksum + } + + memory.write(address, NumberUtils.nativeBytesToBytes(content)); + } + + private Optional parseHeader(ByteBuffer buffer) { + int headerFlag = buffer.get() & 0xFF; + byte[] maybeFileName = new byte[10]; + buffer.get(maybeFileName); // filename + buffer.getShort(); // length + int maybeAddress = buffer.getShort() & 0xFFFF; + buffer.getShort(); + if (headerFlag == 3) { + return Optional.of(maybeAddress); + } + return Optional.empty(); } } diff --git a/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/TzxLoader.java b/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/TzxLoader.java index 734591cf3..7799ee83b 100644 --- a/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/TzxLoader.java +++ b/plugins/memory/byte-mem/src/main/java/net/emustudio/plugins/memory/bytemem/loaders/TzxLoader.java @@ -26,11 +26,11 @@ public class TzxLoader implements Loader { @Override public boolean isMemoryAddressAware() { - return true; + return false; } @Override public void load(Path path, ByteMemoryContext memory, MemoryBank bank) throws Exception { - + throw new RuntimeException("Not supported yet!"); } }