private int block() throws HU01Exception {
        ByteBuffer b = buffer.slice(); // slice to prevent changing buffer until we now we've got a full block 
        b.order(buffer.order());
        if (b.remaining() < 20) {
            // We need at least 20 bytes for the header
            return 0;
        }
        int magic = b.getInt(0);
        if (magic != SCBH_MAGIC) {
            char[] chars = new char[] {(char) (magic & 0xff), (char) ((magic >> 8) & 0xff), (char) ((magic >> 16) & 0xff), (char) ((magic >> 24) & 0xff)};
            throw new HU01Exception("Bad block header: 'SCBH' expected at beginning of block header (was " + new String(chars) + ")");
        }
        int headerSize = b.getInt(4);
        int decompressedBlockSize = b.getInt(8);
        long crc = b.getInt(12) & 0xffffffffL;
        int compressedBlockSize = b.getInt(16);
        if (b.remaining() < headerSize + compressedBlockSize) {
            // We need at least headerSize+compressedBlockSize bytes for the entire block
            return 0;
        }
        
        if (decoded == null || decoded.capacity() < decompressedBlockSize) {
            decoded = allocateBuffer(decompressedBlockSize);
        }
        decoded.clear();
        
        if (compressedBlockSize == decompressedBlockSize && decompressedBlockSize < 2048) {
            /*
             * Block isn't compressed. Just copy the bytes. We don't know how to properly check for 
             * uncompressed blocks. For now the check above seems to work.
             */
            b.position(headerSize);
            b.limit(headerSize + compressedBlockSize);
            decoded.put(b);
        } else {
            // Compressed block
            b.position(headerSize);
            b.limit(b.position() + TABLE_SIZE);
            if (!HU01.build_decompression_table(b.slice(), table)) {
                throw new HU01Exception("Bad block table");
            }
        
            b.position(headerSize + TABLE_SIZE);
            b.limit(headerSize + compressedBlockSize);
            HU01.decompress_hu01_block(b.slice(), table, decoded);
        }
        
        decoded.position(0);
        decoded.limit(decompressedBlockSize);
        
        buffer.position(buffer.position() + headerSize + compressedBlockSize);
        
        CRC32 crc32 = new CRC32();
        crc32.update(decoded.array(), decoded.position(), decoded.limit());
        if (crc32.getValue() != crc) {
            throw new HU01Exception("CRC check failed for block. Expected " + Long.toHexString(crc) 
                    + ". Was " + Long.toHexString(crc32.getValue()) + ".");
        }
        
        return decompressedBlockSize;
    }