
org.monte.media.iff.MC68000InputStream Maven / Gradle / Ivy
/*
* @(#)MC68000InputStream.java 1.3 2010-08-03
*
* Copyright (c) 1999-2003 Werner Randelshofer, Goldau, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package org.monte.media.iff;
import java.io.*;
/**
* A MC 68000 input stream lets an application read primitive data
* types in the MC 68000 CPU format from an underlying input stream.
*
* This stream filter is suitable for IFF-EA85 files.
*
* @author Werner Randelshofer, Hausmatt 10, CH-6405 Goldau, Switzerland
* @version 1.3 2010-08-03 Moved unpackByteRun1 method into this class.
*
1.2.1 2004-08-09 Read methods for primitives throw now EOFException's,
* when the unexpected EOF's occur.
*
1.2 2003-04-01 Method skipFully added.
*
1.1 2000-06-11 Method readFully added.
*
1.0 1999-10-19
*
0.1 1999-01-02 Created.
*/
public class MC68000InputStream
extends FilterInputStream {
private long scan_, mark_;
/**
* Creates a new instance.
*
* @param in the input stream.
*/
public MC68000InputStream(InputStream in)
{ super(in); }
/**
* Read 1 byte from the input stream and interpret
* them as an MC 68000 8 Bit unsigned UBYTE value.
*/
public int readUBYTE()
throws IOException {
int b0 = in.read();
if (b0 == -1) {
throw new EOFException();
}
scan_ += 1;
return b0 & 0xff;
}
/**
* Read 2 bytes from the input stream and interpret
* them as an MC 68000 16 Bit signed WORD value.
*/
public short readWORD()
throws IOException {
int b0 = in.read();
int b1 = in.read();
if (b1 == -1) {
throw new EOFException();
}
scan_ += 2;
return (short) (((b0 & 0xff) << 8) | (b1 & 0xff));
}
/**
* Read 2 bytes from the input stream and interpret
* them as an MC 68000 16 Bit unsigned UWORD value.
*/
public int readUWORD()
throws IOException {
return readWORD() & 0xffff;
}
/**
* Read 4 bytes from the input stream and interpret
* them as an MC 68000 32 Bit signed LONG value.
*/
public int readLONG()
throws IOException {
int b0 = in.read();
int b1 = in.read();
int b2 = in.read();
int b3 = in.read();
if (b3 == -1) {
throw new EOFException();
}
scan_ += 4;
return ((b0 & 0xff) << 24)
| ((b1 & 0xff) << 16)
| ((b2 & 0xff) << 8)
| (b3 & 0xff);
}
/**
* Read 4 Bytes from the input Stream and interpret
* them as an unsigned Integer value of MC 68000
* type ULONG.
*/
public long readULONG()
throws IOException {
return (long)(readLONG()) & 0x00ffffffff;
}
/**
* Align to an even byte position in the input stream.
* This will skip one byte in the stream if the current
* read position is not even.
*/
public void align()
throws IOException {
if (scan_ % 2 == 1) {
in.skip(1);
scan_++;
}
}
/**
* Get the current read position within the file (as seen
* by this input stream filter).
*/
public long getScan()
{ return scan_; }
/**
* Reads one byte.
*/
public int read()
throws IOException {
int data = in.read();
scan_++;
return data;
}
/**
* Reads a sequence of bytes.
*/
public int readFully(byte[] b,int offset, int length)
throws IOException {
return read(b, offset, length);
}
/**
* Reads a sequence of bytes.
*/
public int read(byte[] b,int offset, int length)
throws IOException {
int count = 0;
while (count < length) {
count += in.read(b,offset+count,length-count);
}
scan_ += count;
return count;
}
/**
* Marks the input stream.
* @param readlimit The maximum limit of bytes that can be read before
* the mark position becomes invalid.
*/
public void mark(int readlimit) {
in.mark(readlimit);
mark_ = scan_;
}
/**
* Repositions the stream at the previously marked position.
*
* @exception java.io.IOException If the stream has not been marked or if the
* mark has been invalidated.
*/
public void reset()
throws IOException {
in.reset();
scan_ = mark_;
}
/**
* Skips over and discards n bytes of data from this input stream. This skip
* method tries to skip the p
*/
public long skip(long n)
throws IOException {
long skipped = in.skip(n);
scan_ += skipped;
return skipped;
}
/**
* Skips over and discards n bytes of data from this input stream. Throws
*
* @param n the number of bytes to be skipped.
* @exception java.io.EOFException if this input stream reaches the end before
* skipping all the bytes.
*/
public void skipFully(long n)
throws IOException {
int total = 0;
int cur = 0;
while ((total 0)) {
total += cur;
}
if (cur == 0) throw new EOFException();
scan_ += total;
}
/**
* ByteRun1 run decoder.
*
* The run encoding scheme by byteRun1 is best described by pseudo
* code for the decoder Unpacker (called UnPackBits in
* the Macintosh toolbox.
*
* UnPacker:
* LOOP until produced the desired number of bytes
* Read the next source byte into n
* SELECT n FROM
* [0..127] => copy the next n+1 bytes literally
* [-1..-127] => replicate the next byte -n+1 times
* -128 => no operation
* ENDCASE;
* ENDLOOP;
*
*
* @param in
* @param out
* @throws ParseException
*/
public static int unpackByteRun1(byte[] in, byte[] out)
throws IOException {
int iOut = 0; // output array index
int iIn = 0; // input array index
int n = 0; // The unpack command
byte copyByte;
try {
while (iOut < out.length) {
n = in[iIn++];
if (n >= 0) { // [0..127] => copy the next n+1 bytes literally
n = n + 1;
System.arraycopy(in, iIn, out, iOut, n);
iOut += n;
iIn += n;
} else {
if (n != -128) {//[-1..-127] => replicate the next byte -n+1 times
copyByte = in[iIn++];
for (; n < 1; n++) {
out[iOut++] = copyByte;
}
}
}
}
} catch (IndexOutOfBoundsException e) {
System.out.println("PBMDecoder.unpackByteRun1(): " + e);
System.out.println(" Plane-Index: " + iOut + " Plane size:" + out.length);
System.out.println(" Buffer-Index: " + iIn + " Buffer size:" + in.length);
System.out.println(" Command: " + n);
}
return iOut;
}
}