/* EmulatedDiskImageFile.java (c) 2012-2015 Edward Swartz All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html */ package v9t9.common.files; import java.io.IOException; /** * @author ejs * */ public class EmulatedDiskImageFile extends EmulatedBaseFDRFile implements IEmulatedFile { private IDiskImage diskImage; private int indexSector; public EmulatedDiskImageFile(IDiskImage diskImage, int indexSector, FDR fdr, String name) { super(diskImage, fdr); if (false == fdr instanceof DiskImageFDR) throw new IllegalArgumentException(); this.diskImage = diskImage; this.indexSector = indexSector; } /* (non-Javadoc) * @see v9t9.common.files.NativeFile#readContents(byte[], int, int, int) */ @Override public int readContents(byte[] contents, int contentOffset, int offset, int length) throws IOException { int secOffs = offset / 256; if (secOffs < 0) throw new IllegalArgumentException(); int[] fileSecs = fdr.getContentSectors(); int origOffset = contentOffset; boolean wasOpen = diskImage.isDiskImageOpen(); if (!wasOpen) diskImage.openDiskImage(); byte[] sector = new byte[256]; int lastSector = -1; while (length > 0 ) { if (fileSecs.length <= secOffs) break; int toRead = Math.min(256, length); if (lastSector != fileSecs[secOffs]) { //diskImage.readSector(fileSecs[secOffs], contents, contentOffset, toRead); diskImage.readSector(fileSecs[secOffs], sector, 0, 256); lastSector = fileSecs[secOffs]; } System.arraycopy(sector, offset % 256, contents, contentOffset, toRead); secOffs++; contentOffset += toRead; length -= toRead; } if (!wasOpen) diskImage.closeDiskImage(); return contentOffset - origOffset; } /* (non-Javadoc) * @see v9t9.common.files.NativeFile#writeContents(byte[], int, int, int) */ @Override public int writeContents(final byte[] contents, final int startContentOffset, final int startOffset, final int length) throws IOException { int[] secs = getContentSectors(); if (startOffset + length > secs.length * 256) { throw new IOException("writing past end of file (only " + secs.length + " sectors allocated)"); } int left = length; int offset = startOffset; while (left > 0) { int toWrite = Math.min(256 - offset % 256, left); int sec = secs[offset / 256]; if (sec < 0) { throw new IOException("corrupt FDR: not enough sectors allocated at position " + offset); } writeContentToSector(sec, contents, startContentOffset + offset % 256, offset % 256, toWrite); left -= toWrite; offset += toWrite; } return length; } /** * @throws IOException */ protected void writeContentToSector(int sec, final byte[] contents, final int contentOffset, final int offset, final int length) throws IOException { diskImage.updateSector(sec, new IDiskImage.SectorUpdater() { @Override public boolean updateSector(byte[] content) { System.arraycopy(contents, contentOffset, content, offset, length); return true; } }); } /* (non-Javadoc) * @see v9t9.common.files.NativeFile#validate() */ @Override public void validate() throws InvalidFDRException { fdr.validate(); } /* (non-Javadoc) * @see v9t9.common.files.NativeFile#flush() */ @Override public void flush() throws IOException { diskImage.closeDiskImage(); } /** * @return */ public int getIndexSector() { return indexSector; } /* (non-Javadoc) * @see v9t9.common.files.IFDRInfo#getComment() */ @Override public String getComment() { return fdr.getComment(); } }