开发者

Convert .c to .java [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.

Want to improve this question? Update the question so it focuses on one problem only by editing this post.

Closed 7 years ago.

Improve this question

Any tools to convert C code into Java code? I am interested in converting this code into Java:

***************************************************************************/
/*
** UNECM - Decoder for ECM (Error Code Modeler) format.
** Version 1.0
** Copyright (C) 2002 Neill Corlett
**
** This program 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 2
** of the License, or (at your option) any later version.
**
** This program 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 this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
/***************************************************************************/
/*
** Portability notes:
**
** - Assumes a 32-bit or higher integer size
** - No assumptions about byte order
** - No assumptions about struct packing
** - No unaligned memory access
*/
/***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/***************************************************************************/

void banner(void) {
  fprintf(stderr,
    "UNECM - Decoder for Error Code Modeler format v1.0\n"
    "Copyright (C) 2002 Neill Corlett\n\n"
  );
}

/***************************************************************************/

/* Data types */
#define ecc_uint8 unsigned char
#define ecc_uint16 unsigned short
#define ecc_uint32 unsigned

/* LUTs used for computing ECC/EDC */
static ecc_uint8 ecc_f_lut[256];
static ecc_uint8 ecc_b_lut[256];
static ecc_uint32 edc_lut[256];

/* Init routine */
static void eccedc_init(void) {
  ecc_uint32 i, j, edc;
  for(i = 0; i < 256; i++) {
    j = (i << 1) ^ (i & 0x80 ? 0x11D : 0);
    ecc_f_lut[i] = j;
    ecc_b_lut[i ^ j] = i;
    edc = i;
    for(j = 0; j < 8; j++) edc = (edc >> 1) ^ (edc & 1 ? 0xD8018001 : 0);
    edc_lut[i] = edc;
  }
}

/***************************************************************************/
/*
** Compute EDC for a block
*/
ecc_uint32 edc_partial_computeblock(
        ecc_uint32  edc,
  const ecc_uint8  *src,
        ecc_uint16  size
) {
  while(size--) edc = (edc >> 8) ^ edc_lut[(edc ^ (*src++)) & 0xFF];
  return edc;
}

void edc_computeblock(
  const ecc_uint8  *src,
        ecc_uint16  size,
        ecc_uint8  *dest
) {
  ecc_uint32 edc = edc_partial_computeblock(0, src, size);
  dest[0] = (edc >>  0) & 0xFF;
  dest[1] = (edc >>  8) & 0xFF;
  dest[2] = (edc >> 16) & 0xFF;
  dest[3] = (edc >> 24) & 0xFF;
}

/***************************************************************************/
/*
** Compute ECC for a block (can do either P or Q)
*/
static void ecc_computeblock(
  ecc_uint8 *src,
  ecc_uint32 major_count,
  ecc_uint32 minor_count,
  ecc_uint32 major_mult,
  ecc_uint32 minor_inc,
  ecc_uint8 *dest
) {
  ecc_uint32 size = major_count * minor_count;
  ecc_uint32 major, minor;
  for(major = 0; major < major_count; major++) {
    ecc_uint32 index = (major >> 1) * major_mult + (major & 1);
    ecc_uint8 ecc_a = 0;
    ecc_uint8 ecc_b = 0;
    for(minor = 0; minor < minor_count; minor++) {
      ecc_uint8 temp = src[index];
      index += minor_inc;
      if(index >= size) index -= size;
      ecc_a ^= temp;
      ecc_b ^= temp;
      ecc_a = ecc_f_lut[ecc_a];
    }
    ecc_a = ecc_b_lut[ecc_f_lut[ecc_a] ^ ecc_b];
    dest[major              ] = ecc_a;
    dest[major + major_count] = ecc_a ^ ecc_b;
  }
}

/*
** Generate ECC P and Q codes for a block
*/
static void ecc_generate(
  ecc_uint8 *sector,
  int        zeroaddress
) {
  ecc_uint8 address[4], i;
  /* Save the address and zero it out */
  if(zeroaddress) for(i = 0; i < 4; i++) {
    address[i] = sector[12 + i];
    sector[12 + i] = 0;
  }
  /* Compute ECC P code */
  ecc_computeblock(sector + 0xC, 86, 24,  2, 86, sector + 0x81C);
  /* Compute ECC Q code */
  ecc_computeblock(sector + 0xC, 52, 43, 86, 88, sector + 0x8C8);
  /* Restore the address */
  if(zeroaddress) for(i = 0; i < 4; i++) sector[12 + i] = address[i];
}

/***************************************************************************/
/*
** Generate ECC/EDC information for a sector (must be 2352 = 0x930 bytes)
** Returns 0 on success
*/
void eccedc_generate(ecc_uint8 *sector, int type) {
  ecc_uint32 i;
  switch(type) {
  case 1: /* Mode 1 */
    开发者_开发知识库/* Compute EDC */
    edc_computeblock(sector + 0x00, 0x810, sector + 0x810);
    /* Write out zero bytes */
    for(i = 0; i < 8; i++) sector[0x814 + i] = 0;
    /* Generate ECC P/Q codes */
    ecc_generate(sector, 0);
    break;
  case 2: /* Mode 2 form 1 */
    /* Compute EDC */
    edc_computeblock(sector + 0x10, 0x808, sector + 0x818);
    /* Generate ECC P/Q codes */
    ecc_generate(sector, 1);
    break;
  case 3: /* Mode 2 form 2 */
    /* Compute EDC */
    edc_computeblock(sector + 0x10, 0x91C, sector + 0x92C);
    break;
  }
}

/***************************************************************************/

unsigned mycounter;
unsigned mycounter_total;

void resetcounter(unsigned total) {
  mycounter = 0;
  mycounter_total = total;
}

void setcounter(unsigned n) {
  if((n >> 20) != (mycounter >> 20)) {
    unsigned a = (n+64)/128;
    unsigned d = (mycounter_total+64)/128;
    if(!d) d = 1;
    fprintf(stderr, "Decoding (%02d%%)\r", (100*a) / d);
  }
  mycounter = n;
}

int unecmify(
  FILE *in,
  FILE *out
) {
  unsigned checkedc = 0;
  unsigned char sector[2352];
  unsigned type;
  unsigned num;
  fseek(in, 0, SEEK_END);
  resetcounter(ftell(in));
  fseek(in, 0, SEEK_SET);
  if(
    (fgetc(in) != 'E') ||
    (fgetc(in) != 'C') ||
    (fgetc(in) != 'M') ||
    (fgetc(in) != 0x00)
  ) {
    fprintf(stderr, "Header not found!\n");
    goto corrupt;
  }
  for(;;) {
    int c = fgetc(in);
    int bits = 5;
    if(c == EOF) goto uneof;
    type = c & 3;
    num = (c >> 2) & 0x1F;
    while(c & 0x80) {
      c = fgetc(in);
      if(c == EOF) goto uneof;
      num |= ((unsigned)(c & 0x7F)) << bits;
      bits += 7;
    }
    if(num == 0xFFFFFFFF) break;
    num++;
    if(num >= 0x80000000) goto corrupt;
    if(!type) {
      while(num) {
        int b = num;
        if(b > 2352) b = 2352;
        if(fread(sector, 1, b, in) != b) goto uneof;
        checkedc = edc_partial_computeblock(checkedc, sector, b);
        fwrite(sector, 1, b, out);
        num -= b;
        setcounter(ftell(in));
      }
    } else {
      while(num--) {
        memset(sector, 0, sizeof(sector));
        memset(sector + 1, 0xFF, 10);
        switch(type) {
        case 1:
          sector[0x0F] = 0x01;
          if(fread(sector + 0x00C, 1, 0x003, in) != 0x003) goto uneof;
          if(fread(sector + 0x010, 1, 0x800, in) != 0x800) goto uneof;
          eccedc_generate(sector, 1);
          checkedc = edc_partial_computeblock(checkedc, sector, 2352);
          fwrite(sector, 2352, 1, out);
          setcounter(ftell(in));
          break;
        case 2:
          sector[0x0F] = 0x02;
          if(fread(sector + 0x014, 1, 0x804, in) != 0x804) goto uneof;
          sector[0x10] = sector[0x14];
          sector[0x11] = sector[0x15];
          sector[0x12] = sector[0x16];
          sector[0x13] = sector[0x17];
          eccedc_generate(sector, 2);
          checkedc = edc_partial_computeblock(checkedc, sector + 0x10, 2336);
          fwrite(sector + 0x10, 2336, 1, out);
          setcounter(ftell(in));
          break;
        case 3:
          sector[0x0F] = 0x02;
          if(fread(sector + 0x014, 1, 0x918, in) != 0x918) goto uneof;
          sector[0x10] = sector[0x14];
          sector[0x11] = sector[0x15];
          sector[0x12] = sector[0x16];
          sector[0x13] = sector[0x17];
          eccedc_generate(sector, 3);
          checkedc = edc_partial_computeblock(checkedc, sector + 0x10, 2336);
          fwrite(sector + 0x10, 2336, 1, out);
          setcounter(ftell(in));
          break;
        }
      }
    }
  }
  if(fread(sector, 1, 4, in) != 4) goto uneof;
  fprintf(stderr, "Decoded %ld bytes -> %ld bytes\n", ftell(in), ftell(out));
  if(
    (sector[0] != ((checkedc >>  0) & 0xFF)) ||
    (sector[1] != ((checkedc >>  8) & 0xFF)) ||
    (sector[2] != ((checkedc >> 16) & 0xFF)) ||
    (sector[3] != ((checkedc >> 24) & 0xFF))
  ) {
    fprintf(stderr, "EDC error (%08X, should be %02X%02X%02X%02X)\n",
      checkedc,
      sector[3],
      sector[2],
      sector[1],
      sector[0]
    );
    goto corrupt;
  }
  fprintf(stderr, "Done; file is OK\n");
  return 0;
uneof:
  fprintf(stderr, "Unexpected EOF!\n");
corrupt:
  fprintf(stderr, "Corrupt ECM file!\n");
  return 1;
}

/***************************************************************************/

int main(int argc, char **argv) {
  FILE *fin, *fout;
  char *infilename;
  char *outfilename;
  banner();
  /*
  ** Initialize the ECC/EDC tables
  */
  eccedc_init();
  /*
  ** Check command line
  */
  if((argc != 2) && (argc != 3)) {
    fprintf(stderr, "usage: %s ecmfile [outputfile]\n", argv[0]);
    return 1;
  }
  /*
  ** Verify that the input filename is valid
  */
  infilename = argv[1];
  if(strlen(infilename) < 5) {
    fprintf(stderr, "filename '%s' is too short\n", infilename);
    return 1;
  }
  if(strcasecmp(infilename + strlen(infilename) - 4, ".ecm")) {
    fprintf(stderr, "filename must end in .ecm\n");
    return 1;
  }
  /*
  ** Figure out what the output filename should be
  */
  if(argc == 3) {
    outfilename = argv[2];
  } else {
    outfilename = malloc(strlen(infilename) - 3);
    if(!outfilename) abort();
    memcpy(outfilename, infilename, strlen(infilename) - 4);
    outfilename[strlen(infilename) - 4] = 0;
  }
  fprintf(stderr, "Decoding %s to %s.\n", infilename, outfilename);
  /*
  ** Open both files
  */
  fin = fopen(infilename, "rb");
  if(!fin) {
    perror(infilename);
    return 1;
  }
  fout = fopen(outfilename, "wb");
  if(!fout) {
    perror(outfilename);
    fclose(fin);
    return 1;
  }
  /*
  ** Decode
  */
  unecmify(fin, fout);
  /*
  ** Close everything
  */
  fclose(fout);
  fclose(fin);
  return 0;
}


Your best bet is to rewrite the code.

Any automated conversion would, at best, yield poor-quality and unmaintainable code.


The C view of the world does not mix well with the Java view of the world. If you really want to compile to a form executable by Java, have a look at NestedVM - http://nestedvm.ibex.org/ - which is a cross compiler compiling to a MIPS-dialect which can then easily be "run" in Java either through interpretation or by conversion to actual bytecode reflecting the original MIPS-instructions.

I would recommend getting a Java version of the code.


There used to be tools called Ephedra, Convert2Java and C2J++. But they didn't really work and are no longer available. This leaves three companies offering automatic C to Java translation in the range of unusable, helpful and good:

  1. Novosoft, C2J: The created Java code needs serious manual work. C2J creates somewhat unreadable code (to have very limited pointer support) and has no support for unsigned types/goto statements/native libraries/macros/comments/...
  2. Tangible Software Solutions, C++2Java: The created Java code needs quite some manual work. C++2Java has no support for pointers/unsigned types/goto statements/native libraries/macros/... (Sachin Bhansali posted the translation of the unecm C code above)
  3. mtSystems, Coot: Creates functionally equivalent code (by having full support for pointers, function pointers, unsigned types, goto statements, native libraries, ...) and readable code (keeps macros/comments, renames identifiers, applies various optimizations, ...).

Here the created class from mtSystems (unaltered):

import static ch.mtsystems.coot.String8.cs8;
import static ch.mtsystems.coot.String8.nnc;

import ch.mtsystems.coot.String8;

import java.io.IOException;
import java.io.RandomAccessFile;

public class Unecm {
    public static void banner() {
        System.err.println("UNECM - Decoder for Error Code Modeler format v1.0\nCopyright (C) 2002 Neill Corlett\n");
    }

    /**
     * LUTs used for computing ECC/EDC
     */
    private static byte[] eccFLut_U = new byte[256];

    private static byte[] eccBLut_U = new byte[256];

    private static int[] edcLut_U = new int[256];

    /**
     * Init routine
     */
    private static void eccedcInit() {
        int j_U, edc_U;
        for(int i_U = 0; Integer.compareUnsigned(i_U, 256) < 0; i_U++) {
            j_U = i_U << 1 ^ ((i_U & 0x80) != 0 ? 0x11D : 0);
            eccFLut_U[i_U] = (byte)j_U;
            eccBLut_U[i_U ^ j_U] = (byte)i_U;
            edc_U = i_U;
            for(j_U = 0; Integer.compareUnsigned(j_U, 8) < 0; j_U++) {
                edc_U = edc_U >>> 1 ^ ((edc_U & 1) != 0 ? 0xD8018001 : 0);
            }
            edcLut_U[i_U] = edc_U;
        }
    }

    /**
     * Compute EDC for a block
     */
    public static int edcPartialComputeblock_U(int edc_U, String8 src_U, short size_U) {
        while(size_U-- != 0) {
            edc_U = edc_U >>> 8 ^ edcLut_U[(edc_U ^ Byte.toUnsignedInt((src_U = nnc(src_U).shift(1)).get(-1))) & 0xFF];
        }
        return edc_U;
    }

    public static void edcComputeblock(String8 src_U, short size_U, String8 dest_U) {
        int edc_U = edcPartialComputeblock_U(0, src_U, size_U);
        dest_U.set(0, (byte)(edc_U >>> 0 & 0xFF));
        dest_U.set(1, (byte)(edc_U >>> 8 & 0xFF));
        dest_U.set(2, (byte)(edc_U >>> 16 & 0xFF));
        dest_U.set(3, (byte)(edc_U >>> 24 & 0xFF));
    }

    /**
     * Compute ECC for a block (can do either P or Q)
     */
    private static void eccComputeblock(String8 src_U, int majorCount_U, int minorCount_U, int majorMult_U, int minorInc_U, String8 dest_U) {
        int size_U = majorCount_U * minorCount_U;
        for(int major_U = 0; Integer.compareUnsigned(major_U, majorCount_U) < 0; major_U++) {
            int index_U = (major_U >>> 1) * majorMult_U + (major_U & 1);
            byte eccA_U = 0;
            byte eccB_U = 0;
            for(int minor_U = 0; Integer.compareUnsigned(minor_U, minorCount_U) < 0; minor_U++) {
                byte temp_U = src_U.get(index_U);
                index_U += minorInc_U;
                if(Integer.compareUnsigned(index_U, size_U) >= 0) {
                    index_U -= size_U;
                }
                eccA_U = (byte)(Byte.toUnsignedInt(eccA_U) ^ Byte.toUnsignedInt(temp_U));
                eccB_U = (byte)(Byte.toUnsignedInt(eccB_U) ^ Byte.toUnsignedInt(temp_U));
                eccA_U = eccFLut_U[Byte.toUnsignedInt(eccA_U)];
            }
            eccA_U = eccBLut_U[Byte.toUnsignedInt(eccFLut_U[Byte.toUnsignedInt(eccA_U)]) ^ Byte.toUnsignedInt(eccB_U)];
            dest_U.set(major_U, eccA_U);
            dest_U.set(major_U + majorCount_U, (byte)(Byte.toUnsignedInt(eccA_U) ^ Byte.toUnsignedInt(eccB_U)));
        }
    }

    /**
     * Generate ECC P and Q codes for a block
     */
    private static void eccGenerate(String8 sector_U, int zeroaddress) {
        byte[] address_U = new byte[4];
        /* Save the address and zero it out */
        if(zeroaddress != 0) {
            for(byte i_U = 0; Byte.toUnsignedInt(i_U) < 4; i_U++) {
                address_U[Byte.toUnsignedInt(i_U)] = sector_U.get(12 + Byte.toUnsignedInt(i_U));
                sector_U.set(12 + Byte.toUnsignedInt(i_U), (byte)0);
            }
        }
        /* Compute ECC P code */
        eccComputeblock(nnc(sector_U).shift(0xC), 86, 24, 2, 86, nnc(sector_U).shift(0x81C));
        /* Compute ECC Q code */
        eccComputeblock(nnc(sector_U).shift(0xC), 52, 43, 86, 88, nnc(sector_U).shift(0x8C8));
        /* Restore the address */
        if(zeroaddress != 0) {
            for(byte i_U = 0; Byte.toUnsignedInt(i_U) < 4; i_U++) {
                sector_U.set(12 + Byte.toUnsignedInt(i_U), address_U[Byte.toUnsignedInt(i_U)]);
            }
        }
    }

    /**
     * Generate ECC/EDC information for a sector (must be 2352 = 0x930 bytes)
     * Returns 0 on success
     */
    public static void eccedcGenerate(String8 sector_U, int type) {
        switch(type) {
        case 1: /* Mode 1 */
            /* Compute EDC */
            edcComputeblock(nnc(sector_U).shift(0x00), (short)0x810, nnc(sector_U).shift(0x810));
            /* Write out zero bytes */
            for(int i_U = 0; Integer.compareUnsigned(i_U, 8) < 0; i_U++) {
                sector_U.set(0x814 + i_U, (byte)0);
            }
            /* Generate ECC P/Q codes */
            eccGenerate(sector_U, 0);
            break;
        case 2: /* Mode 2 form 1 */
            /* Compute EDC */
            edcComputeblock(nnc(sector_U).shift(0x10), (short)0x808, nnc(sector_U).shift(0x818));
            /* Generate ECC P/Q codes */
            eccGenerate(sector_U, 1);
            break;
        case 3: /* Mode 2 form 2 */
            /* Compute EDC */
            edcComputeblock(nnc(sector_U).shift(0x10), (short)0x91C, nnc(sector_U).shift(0x92C));
            break;
        }
    }

    public static int mycounter_U;

    public static int mycounterTotal_U;

    public static void resetcounter(int total_U) {
        mycounter_U = 0;
        mycounterTotal_U = total_U;
    }

    public static void setcounter(int n_U) {
        if(n_U >>> 20 != mycounter_U >>> 20) {
            int a_U = Integer.divideUnsigned(n_U + 64, 128);
            int d_U = Integer.divideUnsigned(mycounterTotal_U + 64, 128);
            if(d_U == 0) {
                d_U = 1;
            }
            System.err.printf("Decoding (%02d%%)\r", Integer.divideUnsigned(100 * a_U, d_U));
        }
        mycounter_U = n_U;
    }

    public static int unecmify(RandomAccessFile in, RandomAccessFile out) throws IOException {
        final int posUneof = 1, posCorrupt = 2;
        positionLoop:
        for(int pos = 0; true;) switch(pos) {
        default:
            int checkedc_U = 0;
            String8 sector_U = new String8(2_352);
            int type_U;
            int num_U;
            in.seek(in.length());
            resetcounter((int)in.getFilePointer());
            in.seek(0);
            if(in.read() != 'E' || in.read() != 'C' || in.read() != 'M' || in.read() != 0x00) {
                System.err.println("Header not found!");
                pos = posCorrupt;
                continue positionLoop;
            }
            for(;;) {
                int c = in.read();
                int bits = 5;
                if(c == -1) {
                    pos = posUneof;
                    continue positionLoop;
                }
                type_U = c & 3;
                num_U = c >> 2 & 0x1F;
                while((c & 0x80) != 0) {
                    c = in.read();
                    if(c == -1) {
                        pos = posUneof;
                        continue positionLoop;
                    }
                    num_U |= (c & 0x7F) << bits;
                    bits += 7;
                }
                if(num_U == 0xFFFFFFFF) {
                    break;
                }
                num_U++;
                if(Integer.compareUnsigned(num_U, 0x80000000) >= 0) {
                    pos = posCorrupt;
                    continue positionLoop;
                }
                if(type_U == 0) {
                    while(num_U != 0) {
                        int b = num_U;
                        if(b > 2_352) {
                            b = 2_352;
                        }
                        byte[] tmpBuf = new byte[b];
                        int readCount = Math.max(in.read(tmpBuf), 0);
                        sector_U.copyFrom(tmpBuf, readCount);
                        if(readCount != b) {
                            pos = posUneof;
                            continue positionLoop;
                        }
                        checkedc_U = edcPartialComputeblock_U(checkedc_U, sector_U, (short)b);
                        byte[] tmpBuf2 = new byte[b];
                        sector_U.copyTo(tmpBuf2);
                        out.write(tmpBuf2);
                        num_U -= b;
                        setcounter((int)in.getFilePointer());
                    }
                } else {
                    while(num_U-- != 0) {
                        sector_U.fill(0, sector_U.size(), (byte)0);
                        sector_U.shift(1).fill(0, 10, (byte)0xFF);
                        switch(type_U) {
                        case 1:
                            sector_U.set(0x0F, (byte)0x01);
                            byte[] tmpBuf = new byte[0x003];
                            int readCount = Math.max(in.read(tmpBuf), 0);
                            nnc(sector_U.shift(0x00C)).copyFrom(tmpBuf, readCount);
                            if(readCount != 0x003) {
                                pos = posUneof;
                                continue positionLoop;
                            }
                            byte[] tmpBuf2 = new byte[0x800];
                            int readCount2 = Math.max(in.read(tmpBuf2), 0);
                            nnc(sector_U.shift(0x010)).copyFrom(tmpBuf2, readCount2);
                            if(readCount2 != 0x800) {
                                pos = posUneof;
                                continue positionLoop;
                            }
                            eccedcGenerate(sector_U, 1);
                            checkedc_U = edcPartialComputeblock_U(checkedc_U, sector_U, (short)2_352);
                            byte[] tmpBuf3 = new byte[2_352];
                            sector_U.copyTo(tmpBuf3);
                            out.write(tmpBuf3);
                            setcounter((int)in.getFilePointer());
                            break;
                        case 2:
                            sector_U.set(0x0F, (byte)0x02);
                            byte[] tmpBuf4 = new byte[0x804];
                            int readCount3 = Math.max(in.read(tmpBuf4), 0);
                            nnc(sector_U.shift(0x014)).copyFrom(tmpBuf4, readCount3);
                            if(readCount3 != 0x804) {
                                pos = posUneof;
                                continue positionLoop;
                            }
                            sector_U.set(0x10, sector_U.get(0x14));
                            sector_U.set(0x11, sector_U.get(0x15));
                            sector_U.set(0x12, sector_U.get(0x16));
                            sector_U.set(0x13, sector_U.get(0x17));
                            eccedcGenerate(sector_U, 2);
                            checkedc_U = edcPartialComputeblock_U(checkedc_U, sector_U.shift(0x10), (short)2_336);
                            byte[] tmpBuf5 = new byte[2_336];
                            sector_U.shift(0x10).copyTo(tmpBuf5);
                            out.write(tmpBuf5);
                            setcounter((int)in.getFilePointer());
                            break;
                        case 3:
                            sector_U.set(0x0F, (byte)0x02);
                            byte[] tmpBuf6 = new byte[0x918];
                            int readCount4 = Math.max(in.read(tmpBuf6), 0);
                            nnc(sector_U.shift(0x014)).copyFrom(tmpBuf6, readCount4);
                            if(readCount4 != 0x918) {
                                pos = posUneof;
                                continue positionLoop;
                            }
                            sector_U.set(0x10, sector_U.get(0x14));
                            sector_U.set(0x11, sector_U.get(0x15));
                            sector_U.set(0x12, sector_U.get(0x16));
                            sector_U.set(0x13, sector_U.get(0x17));
                            eccedcGenerate(sector_U, 3);
                            checkedc_U = edcPartialComputeblock_U(checkedc_U, sector_U.shift(0x10), (short)2_336);
                            byte[] tmpBuf7 = new byte[2_336];
                            sector_U.shift(0x10).copyTo(tmpBuf7);
                            out.write(tmpBuf7);
                            setcounter((int)in.getFilePointer());
                            break;
                        }
                    }
                }
            }
            byte[] tmpBuf = new byte[4];
            int readCount = Math.max(in.read(tmpBuf), 0);
            sector_U.copyFrom(tmpBuf, readCount);
            if(readCount != 4) {
                pos = posUneof;
                continue positionLoop;
            }
            System.err.println("Decoded " + in.getFilePointer() + " bytes -> " + out.getFilePointer() + " bytes");
            if(Byte.toUnsignedInt(sector_U.get(0)) != (checkedc_U >>> 0 & 0xFF) || Byte.toUnsignedInt(sector_U.get(1)) != (checkedc_U >>> 8 & 0xFF) || Byte.toUnsignedInt(sector_U.get(2)) != (checkedc_U >>> 16 & 0xFF) || Byte.toUnsignedInt(sector_U.get(3)) != (checkedc_U >>> 24 & 0xFF)) {
                System.err.printf("EDC error (%08X, should be %02X%02X%02X%02X)\n", checkedc_U, Byte.toUnsignedInt(sector_U.get(3)), Byte.toUnsignedInt(sector_U.get(2)), Byte.toUnsignedInt(sector_U.get(1)), Byte.toUnsignedInt(sector_U.get(0)));
                pos = posCorrupt;
                continue positionLoop;
            }
            System.err.println("Done; file is OK");
            return 0;
        case posUneof:
            System.err.println("Unexpected EOF!");
        case posCorrupt:
            System.err.println("Corrupt ECM file!");
            return 1;
        }
    }

    public static void main(String[] args) throws IOException {
        RandomAccessFile fin, fout;
        String8 infilename;
        String8 outfilename;
        banner();
        /*
         ** Initialize the ECC/EDC tables
         */
        eccedcInit();
        /*
         ** Check command line
         */
        if(args.length != 1 && args.length != 2) {
            System.err.println("usage: " + Unecm.class.getSimpleName() + " ecmfile [outputfile]");
            System.exit(1);
        }
        /*
         ** Verify that the input filename is valid
         */
        infilename = cs8(args[0]);
        if(Integer.compareUnsigned(infilename.length(), 5) < 0) {
            System.err.println("filename '" + infilename + "' is too short");
            System.exit(1);
        }
        if(!nnc(infilename).shift(infilename.length() - 4).equalsIgnoreCase(".ecm")) {
            System.err.println("filename must end in .ecm");
            System.exit(1);
        }
        /*
         ** Figure out what the output filename should be
         */
        if(args.length == 2) {
            outfilename = cs8(args[1]);
        } else {
            outfilename = new String8(true, infilename.length() - 3);
            nnc(outfilename).copyFrom(infilename, infilename.length() - 4);
            outfilename.set(infilename.length() - 4, (byte)0);
        }
        System.err.println("Decoding " + infilename + " to " + outfilename + ".");
        /*
         ** Open both files
         */
        try {
            fin = new RandomAccessFile(infilename.toString(), "r");
        } catch(IOException ex) {
            fin = null;
            ex.printStackTrace();
            System.exit(1);
        }
        try {
            fout = new RandomAccessFile(outfilename.toString(), "rw");
            fout.setLength(0);
        } catch(IOException ex) {
            fout = null;
            ex.printStackTrace();
            fin.close();
            System.exit(1);
        }
        /*
         ** Decode
         */
        unecmify(fin, fout);
        /*
         ** Close everything
         */
        fout.close();
        fin.close();
    }
}


Have you considered using JNI instead of bothering doing the translation from C to Java?


I used C++ to Java converter to convert above code. It wont be 100% correct but at least it gives fare idea as to what needs to be done.

public class GlobalMembersTest
{
    /*
    ** UNECM - Decoder for ECM (Error Code Modeler) format.
    ** Version 1.0
    ** Copyright (C) 2002 Neill Corlett
    **
    ** This program 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 2
    ** of the License, or (at your option) any later version.
    **
    ** This program 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 this program; if not, write to the Free Software
    ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    */
    /***************************************************************************/
    /*
    ** Portability notes:
    **
    ** - Assumes a 32-bit or higher integer size
    ** - No assumptions about byte order
    ** - No assumptions about struct packing
    ** - No unaligned memory access
    */
    /***************************************************************************/
    /***************************************************************************/
    public static void banner()
    {
      fprintf(stderr, "UNECM - Decoder for Error Code Modeler format v1.0\n" + "Copyright (C) 2002 Neill Corlett\n\n");
    }

    /***************************************************************************/

    /* Data types */
    //C++ TO JAVA CONVERTER NOTE: The following #define macro was replaced in-line:
    ///#define ecc_uint8 unsigned char
    //C++ TO JAVA CONVERTER NOTE: The following #define macro was replaced in-line:
    ///#define ecc_uint16 unsigned short
    //C++ TO JAVA CONVERTER NOTE: The following #define macro was replaced in-line:
    ///#define ecc_uint32 unsigned

    /* LUTs used for computing ECC/EDC */
    public static byte[] ecc_f_lut = new byte[256];
    public static byte[] ecc_b_lut = new byte[256];
    public static int[] edc_lut = new int[256];

    /* Init routine */
    public static void eccedc_init()
    {
      int i;
      int j;
      int edc;
      for (i = 0; i < 256; i++)
      {
        j = (i << 1)  (i & 0x80 ? 0x11D : 0);
        ecc_f_lut[i] = j;
        ecc_b_lut[i ^ j] = i;
        edc = i;
        for (j = 0; j < 8; j++)
            edc = (edc >> 1) ^ (edc & 1 ? 0xD8018001 : 0);
        edc_lut[i] = edc;
      }
    }

    /***************************************************************************/
    /*
    ** Compute EDC for a block
    */
    public static int edc_partial_computeblock(int edc, String src, short size)
    {
      while (size--)
          edc = (edc >> 8) ^ edc_lut[(edc ^ (src++)) & 0xFF];
      return edc;
    }

    public static void edc_computeblock(String src, short size, byte[] dest)
    {
      int edc = GlobalMembersTest.edc_partial_computeblock(0, src, size);
      dest[0] = (edc >> 0) & 0xFF;
      dest[1] = (edc >> 8) & 0xFF;
      dest[2] = (edc >> 16) & 0xFF;
      dest[3] = (edc >> 24) & 0xFF;
    }

    /***************************************************************************/
    /*
    ** Compute ECC for a block (can do either P or Q)
    */
    public static void ecc_computeblock(byte[] src, int major_count, int minor_count, int major_mult, int minor_inc, byte[] dest)
    {
      int size = major_count * minor_count;
      int major;
      int minor;
      for (major = 0; major < major_count; major++)
      {
        int index = (major >> 1) * major_mult + (major & 1);
        byte ecc_a = 0;
        byte ecc_b = 0;
        for (minor = 0; minor < minor_count; minor++)
        {
          byte temp = src[index];
          index += minor_inc;
          if (index >= size)
              index -= size;
          ecc_a ^= temp;
          ecc_b ^= temp;
          ecc_a = ecc_f_lut[ecc_a];
        }
        ecc_a = ecc_b_lut[ecc_f_lut[ecc_a] ^ ecc_b];
        dest[major] = ecc_a;
        dest[major + major_count] = ecc_a ^ ecc_b;
      }
    }

    /*
    ** Generate ECC P and Q codes for a block
    */
    public static void ecc_generate(byte[] sector, int zeroaddress)
    {
      byte[] address = new byte[4];
      byte i;
      /* Save the address and zero it out */
      if (zeroaddress != 0)
          for (i = 0; i < 4; i++)
          {
        address[i] = sector[12 + i];
        sector[12 + i] = 0;
          }
      /* Compute ECC P code */
      GlobalMembersTest.ecc_computeblock(sector + 0xC, 86, 24, 2, 86, sector + 0x81C);
      /* Compute ECC Q code */
      GlobalMembersTest.ecc_computeblock(sector + 0xC, 52, 43, 86, 88, sector + 0x8C8);
      /* Restore the address */
      if (zeroaddress != 0)
          for (i = 0; i < 4; i++)
              sector[12 + i] = address[i];
    }

    /***************************************************************************/
    /*
    ** Generate ECC/EDC information for a sector (must be 2352 = 0x930 bytes)
    ** Returns 0 on success
    */
    public static void eccedc_generate(byte[] sector, int type)
    {
      int i;
      switch (type)
      {
      case 1: // Mode 1
        /* Compute EDC */
        GlobalMembersTest.edc_computeblock(sector + 0x00, 0x810, sector + 0x810);
        /* Write out zero bytes */
        for (i = 0; i < 8; i++)
            sector[0x814 + i] = 0;
        /* Generate ECC P/Q codes */
        GlobalMembersTest.ecc_generate(sector, 0);
        break;
      case 2: // Mode 2 form 1
        /* Compute EDC */
        GlobalMembersTest.edc_computeblock(sector + 0x10, 0x808, sector + 0x818);
        /* Generate ECC P/Q codes */
        GlobalMembersTest.ecc_generate(sector, 1);
        break;
      case 3: // Mode 2 form 2
        /* Compute EDC */
        GlobalMembersTest.edc_computeblock(sector + 0x10, 0x91C, sector + 0x92C);
        break;
      }
    }

    /***************************************************************************/

    public static int mycounter;
    public static int mycounter_total;

    public static void resetcounter(int total)
    {
      mycounter = 0;
      mycounter_total = total;
    }

    public static void setcounter(int n)
    {
      if ((n >> 20) != (mycounter >> 20))
      {
        int a = (n + 64) / 128;
        int d = (mycounter_total + 64) / 128;
        if (d == 0)
            d = 1;
        fprintf(stderr, "Decoding (%02d%%)\r", (100 * a) / d);
      }
      mycounter = n;
    }

    public static int unecmify(FILE in, FILE out)
    {
      int checkedc = 0;
      byte[] sector = new byte[2352];
      int type;
      int num;
      fseek(in, 0, SEEK_END);
      GlobalMembersTest.resetcounter(ftell(in));
      fseek(in, 0, SEEK_SET);
      if ((fgetc(in) != 'E') || (fgetc(in) != 'C') || (fgetc(in) != 'M') || (fgetc(in) != 0x00))
      {
        fprintf(stderr, "Header not found!\n");
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
        goto corrupt;
      }
      for (;;)
      {
        int c = fgetc(in);
        int bits = 5;
        if (c == EOF)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
            goto uneof;
        type = c & 3;
        num = (c >> 2) & 0x1F;
        while (c & 0x80 != 0)
        {
          c = fgetc(in);
          if (c == EOF)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
              goto uneof;
          num |= ((int)(c & 0x7F)) << bits;
          bits += 7;
        }
        if (num == 0xFFFFFFFF)
            break;
        num++;
        if (num >= 0x80000000)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
            goto corrupt;
        if (type == 0)
        {
          while (num != 0)
          {
            int b = num;
            if (b > 2352)
                b = 2352;
            if (fread(sector, 1, b, in) != b)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                goto uneof;
            checkedc = GlobalMembersTest.edc_partial_computeblock(checkedc, sector, b);
            fwrite(sector, 1, b, out);
            num -= b;
            GlobalMembersTest.setcounter(ftell(in));
          }
        }
        else
        {
          while (num--)
          {
//C++ TO JAVA CONVERTER TODO TASK: The memory management function 'memset' has no equivalent in Java:
//C++ TO JAVA CONVERTER TODO TASK: There is no Java equivalent to 'sizeof':
            memset(sector, 0, sizeof(sector));
//C++ TO JAVA CONVERTER TODO TASK: The memory management function 'memset' has no equivalent in Java:
            memset(sector + 1, 0xFF, 10);
            switch (type)
            {
            case 1:
              sector[0x0F] = 0x01;
              if (fread(sector + 0x00C, 1, 0x003, in) != 0x003)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                  goto uneof;
              if (fread(sector + 0x010, 1, 0x800, in) != 0x800)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                  goto uneof;
              GlobalMembersTest.eccedc_generate(sector, 1);
              checkedc = GlobalMembersTest.edc_partial_computeblock(checkedc, sector, 2352);
              fwrite(sector, 2352, 1, out);
              GlobalMembersTest.setcounter(ftell(in));
              break;
            case 2:
              sector[0x0F] = 0x02;
              if (fread(sector + 0x014, 1, 0x804, in) != 0x804)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                  goto uneof;
              sector[0x10] = sector[0x14];
              sector[0x11] = sector[0x15];
              sector[0x12] = sector[0x16];
              sector[0x13] = sector[0x17];
              GlobalMembersTest.eccedc_generate(sector, 2);
              checkedc = GlobalMembersTest.edc_partial_computeblock(checkedc, sector + 0x10, 2336);
              fwrite(sector + 0x10, 2336, 1, out);
              GlobalMembersTest.setcounter(ftell(in));
              break;
            case 3:
              sector[0x0F] = 0x02;
              if (fread(sector + 0x014, 1, 0x918, in) != 0x918)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                  goto uneof;
              sector[0x10] = sector[0x14];
              sector[0x11] = sector[0x15];
              sector[0x12] = sector[0x16];
              sector[0x13] = sector[0x17];
              GlobalMembersTest.eccedc_generate(sector, 3);
              checkedc = GlobalMembersTest.edc_partial_computeblock(checkedc, sector + 0x10, 2336);
              fwrite(sector + 0x10, 2336, 1, out);
              GlobalMembersTest.setcounter(ftell(in));
              break;
            }
          }
        }
      }
      if (fread(sector, 1, 4, in) != 4)
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
          goto uneof;
      fprintf(stderr, "Decoded %ld bytes -> %ld bytes\n", ftell(in), ftell(out));
      if ((sector[0] != ((checkedc >> 0) & 0xFF)) || (sector[1] != ((checkedc >> 8) & 0xFF)) || (sector[2] != ((checkedc >> 16) & 0xFF)) || (sector[3] != ((checkedc >> 24) & 0xFF)))
      {
        fprintf(stderr, "EDC error (%08X, should be %02X%02X%02X%02X)\n", checkedc, sector[3], sector[2], sector[1], sector[0]);
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
        goto corrupt;
      }
      fprintf(stderr, "Done; file is OK\n");
      return 0;
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
    uneof:
      fprintf(stderr, "Unexpected EOF!\n");
//C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
    corrupt:
      fprintf(stderr, "Corrupt ECM file!\n");
      return 1;
    }

    /***************************************************************************/

    public static int Main(int argc, String[] args)
    {
      FILE fin;
      FILE fout;
      String infilename;
      String outfilename;
      GlobalMembersTest.banner();
      /*
      ** Initialize the ECC/EDC tables
      */
      GlobalMembersTest.eccedc_init();
      /*
      ** Check command line
      */
      if ((argc != 2) && (argc != 3))
      {
        fprintf(stderr, "usage: %s ecmfile [outputfile]\n", args[0]);
        return 1;
      }
      /*
      ** Verify that the input filename is valid
      */
      infilename = args[1];
      if (infilename.length() < 5)
      {
        fprintf(stderr, "filename '%s' is too short\n", infilename);
        return 1;
      }
      if (strcasecmp(infilename + infilename.length() - 4, ".ecm"))
      {
        fprintf(stderr, "filename must end in .ecm\n");
        return 1;
      }
      /*
      ** Figure out what the output filename should be
      */
      if (argc == 3)
      {
        outfilename = args[2];
      }
      else
      {
//C++ TO JAVA CONVERTER TODO TASK: The memory management function 'malloc' has no equivalent in Java:
        outfilename = malloc(infilename.length() - 3);
        if (outfilename == null)
            abort();
//C++ TO JAVA CONVERTER TODO TASK: The memory management function 'memcpy' has no equivalent in Java:
        memcpy(outfilename, infilename, infilename.length() - 4);
        outfilename = outfilename.substring(0, infilename.length() - 4);
      }
      fprintf(stderr, "Decoding %s to %s.\n", infilename, outfilename);
      /*
      ** Open both files
      */
      fin = fopen(infilename, "rb");
      if (fin == null)
      {
        perror(infilename);
        return 1;
      }
      fout = fopen(outfilename, "wb");
      if (fout == null)
      {
        perror(outfilename);
        fclose(fin);
        return 1;
      }
      /*
      ** Decode
      */
      GlobalMembersTest.unecmify(fin, fout);
      /*
      ** Close everything
      */
      fclose(fout);
      fclose(fin);
    }
}


The question is asking "any tool?", so here is a tool.
Please don't downvote just because you don't like tools.

I tried a C-to-Java conversion tool called "Novosoft C2J". Verdict:

  • Very buggy
  • Crashes often
  • Proprietary (even though it claims "Beta versions of C2J are under GNU license", source code is nowhere to be found)

I managed to convert a C file with few dependencies, but had to "pre-process" it by copy-pasting the content of header files to headers, because C2J won't let me select .h files for inclusion in a project.

Translated code is static, with strange "nextlevel()" and "prevlevel()" calls.
Some translated code needs manual work, for instance: UndefFcs.cisnan([...])

Conclusion: Buggy tool, but it might be the case that there is no better tool.


I realized I never posted my solution

In Android Activity:

Public class UnECMActivity extends Activity {
...

    static {
    System.loadLibrary("unecm");
}
private native int rununecm(String fileName);

In unecm.c add:

jint Java_com_romcessed_unecm_UnECMActivity_rununecm(JNIEnv* env, jobject javaThis, jstring fileName) {
  FILE *fin, *fout;
  jboolean *iscopy;
  char *infilename = (*env)->GetStringUTFChars(env, fileName, iscopy);
  char *outfilename;
  banner();
  eccedc_init();

  /*
  ** Verify that the input filename is valid
  */
  if(strlen(infilename) < 5) {
    fprintf(stderr, "filename '%s' is too short\n", infilename);
    return 1;
  }
  if(strcasecmp(infilename + strlen(infilename) - 4, ".ecm")) {
    fprintf(stderr, "filename must end in .ecm\n");
    return 1;
  }

  /*
  ** Figure out what the output filename should be
  */
    outfilename = malloc(strlen(infilename) - 3);
    if(!outfilename) abort();
    memcpy(outfilename, infilename, strlen(infilename) - 4);
    outfilename[strlen(infilename) - 4] = 0;

  fprintf(stderr, "Decoding %s to %s.\n", infilename, outfilename);
  /*
  ** Open both files
  */
  fin = fopen(infilename, "rb");
  if(!fin) {
    perror(infilename);
    return 1;
  }
  fout = fopen(outfilename, "wb");
  if(!fout) {
    perror(outfilename);
    fclose(fin);
    return 1;
  }
  /*
  ** Decode
  */
  unecmify(fin, fout);
  /*
  ** Close everything
  */
  fclose(fout);
  fclose(fin);
  return 0;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜