/* This file is part of jpcsp. Jpcsp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jpcsp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.filesystems.umdiso; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Arrays; import java.util.HashMap; public class BufferedFileSectorDevice extends AbstractFileSectorDevice { protected RandomAccessFile tocFile; protected ISectorDevice sectorDevice; protected HashMap<Integer, Integer> toc; protected boolean tocDirty; protected int nextFreeBufferedSectorNumber; protected int numSectors; public BufferedFileSectorDevice(RandomAccessFile tocFile, RandomAccessFile fileAccess, ISectorDevice sectorDevice) { super(fileAccess); this.tocFile = tocFile; this.sectorDevice = sectorDevice; readToc(); } protected void readToc() { toc = new HashMap<Integer, Integer>(); nextFreeBufferedSectorNumber = 0; tocDirty = false; try { tocFile.seek(0); long length = tocFile.length(); if (length >= 4) { numSectors = tocFile.readInt(); for (long i = 4; i < length; i += 8) { int sectorNumber = tocFile.readInt(); int bufferedSectorNumber = tocFile.readInt(); toc.put(sectorNumber, bufferedSectorNumber); nextFreeBufferedSectorNumber = Math.max(nextFreeBufferedSectorNumber, bufferedSectorNumber + 1); } } else if (sectorDevice != null) { numSectors = sectorDevice.getNumSectors(); } } catch (IOException e) { log.error("readToc", e); } } protected void writeToc() { if (tocDirty) { try { tocFile.seek(0); tocFile.writeInt(getNumSectors()); for (Integer sectorNumber : toc.keySet()) { Integer bufferedSectorNumber = toc.get(sectorNumber); tocFile.writeInt(sectorNumber.intValue()); tocFile.writeInt(bufferedSectorNumber.intValue()); } tocDirty = false; } catch (IOException e) { log.error("writeToc", e); } } } @Override public void readSector(int sectorNumber, byte[] buffer, int offset) throws IOException { Integer bufferedSectorNumber = toc.get(sectorNumber); if (bufferedSectorNumber != null) { fileAccess.seek(((long) sectorLength) * bufferedSectorNumber.intValue()); fileAccess.read(buffer, offset, sectorLength); return; } if (sectorDevice == null) { log.warn(String.format("Reading outside the UMD buffer file (sector=0x%X)", sectorNumber)); Arrays.fill(buffer, offset, offset + sectorLength, (byte) 0); } else { sectorDevice.readSector(sectorNumber, buffer, offset); fileAccess.seek(((long) sectorLength) * nextFreeBufferedSectorNumber); fileAccess.write(buffer, offset, sectorLength); toc.put(sectorNumber, nextFreeBufferedSectorNumber); nextFreeBufferedSectorNumber++; tocDirty = true; } } @Override public int getNumSectors() throws IOException { return numSectors; } @Override public void close() throws IOException { super.close(); if (sectorDevice != null) { sectorDevice.close(); sectorDevice = null; } writeToc(); tocFile.close(); tocFile = null; toc = null; } }