web-dev-qa-db-fra.com

Convertir .c en .java

Des outils pour convertir le code C en code Java? Je suis intéressé par la conversion de ce code en 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;
}
10
Aymon Fournier

Avez-vous envisagé d'utiliser JNI au lieu de vous préoccuper de la traduction de C en Java?

5
Catchwa

Votre meilleur pari est de réécrire le code.

Toute conversion automatisée produirait au mieux un code de mauvaise qualité et non maintenable.

14
James McNellis

La vision du monde en C ne se mélange pas bien avec la vision du monde en Java. Si vous voulez vraiment compiler en un formulaire exécutable en Java, jetez un coup d’œil à NestedVM - http://nestedvm.ibex.org/ - qui est un compilateur croisé compilant un dialecte MIPS qui peut ensuite être facilement "run" en Java, soit par interprétation, soit par conversion en bytecode reflétant les instructions MIPS d'origine.

Je recommanderais une version Java du code.

12

Il existait auparavant des outils appelés Ephedra, Convert2Java et C2J ++. Mais ils n'ont pas vraiment fonctionné et ne sont plus disponibles. Cela laisse trois entreprises proposant une traduction automatique de C en Java dans la gamme inutilisable, utile et bonne:

  1. Novosoft , C2J: Le code Java créé nécessite un travail manuel important. C2J crée du code quelque peu illisible (pour avoir un support de pointeur très limité) et ne supporte pas les types non signés/les instructions goto/les bibliothèques natives/les macros/les commentaires/...
  2. Solutions logicielles tangibles , C++ 2Java: Le code Java créé nécessite un peu de travail manuel. C++ 2Java ne prend pas en charge les pointeurs/types non signés/instructions goto/bibliothèques natives/macros/... (Sachin Bhansali a posté la traduction du code unecm C ci-dessus)
  3. mtSystems , Coot: crée un code fonctionnellement équivalent (en prenant en charge les pointeurs, les pointeurs de fonction, les types non signés, les instructions goto, les bibliothèques natives, ...) et le code lisible (conserve les macros/commentaires, renomme les identifiants, applique divers optimisations, ...).

Voici la classe créée par mtSystems (non modifiée):

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();
    }
}
8
user3669782

J'ai utilisé Convertisseur C++ en Java pour convertir le code ci-dessus. Ce ne sera pas correct à 100% mais au moins, cela donne une idée des tarifs pour ce qui doit être fait.

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);
    }
}
4
Sachin Bhansali

La question demande "n'importe quel outil?", Voici donc un outil.
S'il vous plaît, ne votez pas parce que vous n'aimez pas les outils.

J'ai essayé un outil de conversion C-to-Java appelé " Novosoft C2J ". Verdict:

  • Très buggy
  • Se bloque souvent
  • Propriétaire (même s'il dit "les versions bêta de C2J sont sous GNU licence", le code source est introuvable)

J'ai réussi à convertir un fichier C avec peu de dépendances, mais j'ai dû le "pré-traiter" en copiant-collant le contenu des fichiers d'en-tête dans les en-têtes, car C2J ne me permet pas de sélectionner des fichiers .h à inclure dans un projet.

Le code traduit est statique, avec des appels étranges "nextlevel ()" et "prevlevel ()".
Certains codes traduits nécessitent un travail manuel, par exemple: UndefFcs.cisnan([...])

Conclusion: outil de buggy, mais il est possible qu'il n'y ait pas de meilleur outil.

1
Nicolas Raoul

J'ai réalisé que je n'avais jamais posté ma solution

Dans l'activité Android:

Public class UnECMActivity extends Activity {
...

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

Dans unecm.c, ajoutez:

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
Aymon Fournier