/* BaseTrackDiskImage.java (c) 2010-2013 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.engine.files.image; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.List; import v9t9.common.client.ISettingsHandler; import v9t9.common.files.IdMarker; import v9t9.engine.dsr.realdisk.CRC16; public abstract class BaseTrackDiskImage extends BaseDiskImage { private CRC16 crcAlg = new CRC16(0x1021); public BaseTrackDiskImage(String name, File file, ISettingsHandler settings) { super(name, file, settings); } @Override public void writeSectorData(byte[] rwBuffer, int start, int buflen, IdMarker marker) { int ptr; int idoffset = marker.idoffset; int dataoffset = marker.dataoffset; // write new ID field int offs = idoffset; if (trackBuffer[offs] != marker.idCode) dumper.error("Inconsistent idoffset ({0})", idoffset); trackBuffer[offs+0] = marker.idCode; trackBuffer[offs+1] = marker.trackid; trackBuffer[offs+2] = marker.sideid; trackBuffer[offs+3] = marker.sectorid; trackBuffer[offs+4] = marker.sizeid; trackBuffer[offs+5] = (byte) (marker.crcid >> 8); trackBuffer[offs+6] = (byte) (marker.crcid & 255); // write data with new CRC if (trackBuffer[dataoffset] != marker.dataCode) dumper.error("Inconsistent dataoffset ({0})", dataoffset); trackBuffer[dataoffset] = marker.dataCode; offs = dataoffset; int size = (128 << marker.sizeid); ptr = offs + 1; crcAlg.reset(); crcAlg.feed(marker.dataCode); while (size > 0) { int tocopy = Math.min(trackBuffer.length - ptr, size); System.arraycopy(rwBuffer, 0, trackBuffer, ptr, tocopy); while (tocopy-- > 0) { crcAlg.feed(trackBuffer[ptr++]); size--; } if (ptr >= trackBuffer.length) ptr = 0; } trackBuffer[ptr++] = (byte) (marker.crcid >> 8); trackBuffer[ptr++] = (byte) (marker.crcid & 0xff); trackChanged = true; // dump contents RealDiskUtils.dumpBuffer(dumper, rwBuffer, start, buflen); } /** * Scan the current track for ID markers * @return */ @Override public void fetchFormatAndTrackMarkers() { try { readCurrentTrackData(); } catch (IOException e) { dumper.error(e.getMessage()); trackMarkers = Collections.emptyList(); trackFormat = fmFormat; return; } List<IdMarker> fmMarkers = fmFormat.fetchIdMarkers(trackBuffer, hdr.getTrackSize(), false); List<IdMarker> mfmMarkers = mfmFormat.fetchIdMarkers(trackBuffer, hdr.getTrackSize(), false); if (fmMarkers.size() == 0 && mfmMarkers.size() == 0) { // unformatted if (trackFormat == null) { trackFormat = fmFormat; } else { // keep last format } trackMarkers = Collections.emptyList(); } else { int totFmSize = 0; int totMfmSize = 0; for (IdMarker marker : fmMarkers) { totFmSize += marker.getSectorSize(); } for (IdMarker marker : mfmMarkers) { totMfmSize += marker.getSectorSize(); } if (totFmSize < hdr.getTrackSize() / 2 && mfmMarkers.size() == 0) { dumper.info("found only " + fmMarkers.size() + " FM sectors on track " + track +" in disk image " + spec); } else if (totMfmSize < hdr.getTrackSize() / 2 && fmMarkers.size() == 0) { dumper.info("found only " + mfmMarkers.size() + " MFM sectors on track " + track +" in disk image " + spec); } if (fmMarkers.size() > mfmMarkers.size()) { crcAlg = new CRC16(0x1021); trackMarkers = fmMarkers; trackFormat = fmFormat; } else { crcAlg = new CRC16(0x1021); trackMarkers = mfmMarkers; trackFormat = mfmFormat; } } } /* (non-Javadoc) * @see v9t9.engine.files.image.BaseDiskImage#discoverSide2TrackOrdering() */ @Override protected void discoverSide2TrackOrdering() { // detect the side 2 ordering int origTrack = track; try { setTrack(0); fetchFormatAndTrackMarkers(); boolean any = false; for (IdMarker marker : trackMarkers) { if (marker.sideid != 1) continue; if (marker.trackid == hdr.getTracks() - 1) { any = true; hdr.setInvertedSide2(true); break; } else if (marker.trackid == 0) { any = true; hdr.setInvertedSide2(false); break; } } if (any) { hdr.setSide2DirectionKnown(true); } } catch (IOException e) { // ok, leave it alone for now } finally { try { setTrack(origTrack); } catch (IOException e) { e.printStackTrace(); } } } }