Convert .c to .java [closed]
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 questionAny 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:
- 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/...
- 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)
- 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;
}
精彩评论