import java.io.*; import java.util.*; class Ccfx { public static void main ( String args[] ) throws IOException { int op = 0; if ( args.length != 1 ) { System.out.println("CCFX file\textracts");System.out.println("CCFX directory\trecompiles");System.exit(0); } File test = new File(args[0]); if ( test.isDirectory() == true ) {op = 2;} else { if ( (test.exists() == true) && (test.length() != 0 )) op = 1; } if ( op == 0 ) { System.out.println("File error! Descriptive, eh ? ");System.exit(0); } if ( op == 1 ) { // start extract File fxFile= new File(args[0]); File dataFile = new File("fxdata.fx"); RandomAccessFile data = new RandomAccessFile(dataFile,"rw"); RandomAccessFile fx = new RandomAccessFile(fxFile,"rw"); data.seek(8); int i,u,y; int fxFiles = intelToMac(data.readInt()); //data.seek(21319); String tempFxName=""; String[] fxNames = new String[fxFiles]; int[] offsets = new int[fxFiles]; int offset; for( i = 0 ; i < fxFiles ; i++ ) { data.seek(3340+i*1088); offsets[i] = 3340+i*1088; for ( u = 0 ; u < 13 ; u++ ) { tempFxName = tempFxName + new Character((char)data.read()).toString(); } fxNames[i] = tempFxName.trim(); //System.out.println(tempFxName.trim()); tempFxName = ""; } offset = getOffset(fxNames,fxFile.toString()); if ( offset == 0 ) {System.out.println("Oops, something's wrong " + fxFile.toString() + " " + fxNames[0]);System.exit(0); } int tgaFiles; fx.seek(8); tgaFiles = intelToMac(fx.readInt()); int[] tgaOffsets = new int[tgaFiles]; for ( i = 0 ; i < tgaFiles ; i++ ) { tgaOffsets[i] = intelToMac(fx.readInt())+(tgaFiles*4+12); } int[] widths = new int[tgaFiles]; int[] heights = new int[tgaFiles]; int[] hotX = new int[tgaFiles]; int[] hotY = new int[tgaFiles]; data.seek(offset+32); //System.out.println("Offset " + offset); int a; if ( ( a = intelToMac(data.readInt())) != tgaFiles ) {System.out.println("Oops, something's wrong 2 " + tgaFiles + " " + a);System.exit(0); } // skip the 2 mysterious ints data.skipBytes(8); for ( i = 0 ; i < tgaFiles ; i++ ) { hotX[i]=intelToMac(data.readInt()); hotY[i]=intelToMac(data.readInt()); } data.seek(offset+564); // skip the 2 mysterious ints data.skipBytes(8); int counter2=0; //System.out.println("here"); String dataDir = fxFile.toString().substring(0,fxFile.toString().length()-2); File td = new File(dataDir); td.mkdir(); File tgaFile = new File(dataDir+"\\image001." + hotX[0] + "." + hotY[0] + ".tga"); RandomAccessFile tgaOut = new RandomAccessFile(tgaFile,"rw"); int b,g,r,alpha; for ( i = 0 ; i < tgaFiles ; i++ ) { widths[i]=intelToMac(data.readInt()); heights[i]=intelToMac(data.readInt()); } String name; for ( i = 0 ; i < tgaFiles ; i++ ) { //header name = Integer.toString(i+1); while ( name.length() < 3 ) name = "0" + name; tgaFile = new File(dataDir + "\\image" + name + "." + hotX[i] + "." + hotY[i] +".tga"); tgaOut = new RandomAccessFile(tgaFile,"rw"); tgaOut.write(0);tgaOut.write(0);tgaOut.write(2);tgaOut.write(0); tgaOut.write(0);tgaOut.write(0);tgaOut.write(0);tgaOut.write(0); tgaOut.write(0);tgaOut.write(0);tgaOut.write(0);tgaOut.write(0); tgaOut.write((widths[i]));tgaOut.write(0); tgaOut.write((heights[i]));tgaOut.write(0); tgaOut.write(0x20);tgaOut.write(0x8); fx.seek(tgaOffsets[i]); //System.out.println(tgaOffsets[i]); counter2=widths[i]*heights[i]*4; y=0;u=0; for ( u = 0 ; u < heights[i] ; u++ ) { fx.seek(tgaOffsets[i]+ (heights[i]-(u+1))*widths[i]*4 ); for ( y = 0 ; y < widths[i] ; y++ ) { b = fx.read(); g = fx.read(); r = fx.read(); if ( ( 8*b - 1 ) > 0 ) b = 8*b-1; if ( ( 8*g - 1 ) > 0 ) g = 8*g-1; if ( ( 8*r - 1 ) > 0 ) r = 8*r-1; tgaOut.write(r); tgaOut.write(g); tgaOut.write(b); alpha= fx.read(); if ( alpha == 0 ) { tgaOut.write(alpha); } else { tgaOut.write(alpha*8-1);} } } tgaOut.close(); System.out.print("\b\b\b" + i*100/tgaFiles + "%"); } System.out.print("\b\b\b\b100%"); fx.close(); data.close(); } // end extract if ( op == 2 ) { // start recompile String dir = args[0]; File dirTest = new File(dir); if ( dirTest.exists() == false ) {System.out.print("Directory " + dir + " not found");System.exit(0); } String[] files = new String[getFiles("tga",dir).length]; files = getFiles("tga",dir); files = sortFileList(files); File inFile = new File(dir+".fx"); inFile.delete(); RandomAccessFile fx = new RandomAccessFile(inFile,"rw"); RandomAccessFile data = new RandomAccessFile("fxdata.fx","rw"); RandomAccessFile tgaRead = new RandomAccessFile(dir + "\\" + files[0],"r"); StringTokenizer parser = new StringTokenizer("","."); int[] hotspotsX = new int[files.length]; int[] hotspotsY = new int[files.length]; int[] widths = new int[files.length]; int[] heights = new int[files.length]; int[] offsets = new int[files.length]; fx.write(201);fx.write(3);fx.write(0);fx.write(0); int i=0; for ( i = 0 ; i < files.length*4 + 8 ; i++ ) { fx.write(0); } int counter=0; int j=0; int b,g,r; for ( i = 0 ; i < files.length ; i ++ ) { tgaRead = new RandomAccessFile(dir + "\\" + files[i],"r"); tgaRead.skipBytes(12); widths[i] = tgaRead.read();tgaRead.read(); heights[i] = tgaRead.read();tgaRead.read(); if ( tgaRead.read() != 32 ) { System.out.println("Error : File " + files[i] + " is corrupt or the wrong bitdepth");System.exit(0); } tgaRead.read(); int w=0; offsets[i] = ((int) fx.getFilePointer())-(12+files.length*4); tgaRead.seek(tgaRead.getFilePointer() + 4*widths[i]*heights[i]); for ( j = 0 ; j < heights[i] ; j++ ) { tgaRead.seek(tgaRead.getFilePointer() - 2*4*widths[i]); for ( w = 0; w < widths[i] ; w++ ) { b=(tgaRead.read()+1)/8; g=(tgaRead.read()+1)/8; r=(tgaRead.read()+1)/8; if ( b > 32 ) b = 32; if ( g > 32 ) g = 32; if ( r > 32 ) r = 32; fx.write(r); fx.write(g); fx.write(b); fx.write((tgaRead.read()+1)/8); } } tgaRead.close(); parser = new StringTokenizer(files[i],"."); parser.nextToken(); hotspotsX[i] = Integer.parseInt(parser.nextToken()); hotspotsY[i] = Integer.parseInt(parser.nextToken()); System.out.print("\b\b\b" + i*100/files.length + "%"); } System.out.print("\b\b\b100%"); fx.seek(4); fx.writeInt(intelToMac( ( (int) fx.length() ) -(12+4*files.length) )); fx.writeInt(intelToMac(files.length)); for ( i = 0 ; i < files.length ; i++ ) { fx.writeInt(intelToMac(offsets[i])); } data.seek(8); int fxFiles = intelToMac(data.readInt()); int[] fxOffsets = new int[fxFiles]; String[] fxNames = new String[fxFiles]; String tempFxName = ""; int u; for( i = 0 ; i < fxFiles ; i++ ) { data.seek(3340+i*1088); fxOffsets[i] = 3340+i*1088; for ( u = 0 ; u < 13 ; u++ ) { tempFxName = tempFxName + new Character((char)data.read()).toString(); } fxNames[i] = tempFxName.trim(); //System.out.println(tempFxName.trim()); tempFxName = ""; } int fxOffset = getOffset(fxNames,inFile.toString()); //System.out.println(fxOffset); data.seek(fxOffset+32); data.writeInt(intelToMac(files.length)); data.seek(fxOffset+44); for ( i = 0 ; i < files.length ; i++ ) { data.writeInt(intelToMac(hotspotsX[i])); data.writeInt(intelToMac(hotspotsY[i])); } data.seek(fxOffset+564+8); for ( i = 0 ; i < files.length ; i++ ) { data.writeInt(intelToMac(widths[i])); data.writeInt(intelToMac(heights[i])); } data.close(); fx.close(); } // end recompile } // end main public static int intelToMac(int i) { int byte0 = i & 0xff; int byte1 = (i>>8) & 0xff; int byte2 = (i>>16) & 0xff; int byte3 = (i>>24) & 0xff; // swap the byte order return (byte0<<24) | (byte1<<16) | (byte2<<8) | byte3; } public static int findStringArray(String[] arr,String target ) { //System.out.println(files); int l=arr.length; int i; int ret=-1; for ( i = 0 ; i < l ; i++ ) { if (arr[i].equalsIgnoreCase(target)) { ret=i;i=l;} } return(ret); } public static int swabShort (int v) { String hexString = Integer.toHexString(v); //System.out.println(hexString); while ( hexString.length() < 4 ) hexString = "0" + hexString; String revHex = new String(hexString.substring(2,4)+hexString.substring(0,2)); //System.out.println(revHex); return( Integer.parseInt(revHex.trim(),16)); } public static int getOffset ( String[] names, String name ) { int i;int offset=0; for ( i = 0 ; i < names.length ; i++ ) { if ( names[i].equalsIgnoreCase(name)) offset = 3340+i*1088; } return(offset); } public static String[] getFiles (String fileDesc,String direct) { Filter nf = new Filter (fileDesc); File dir = new File (direct + "\\."); String[] strs = dir.list(nf); return (strs); } public static String[] sortFileList ( String[] origList ) { String[] sortedList = new String[origList.length]; int i,u; String iString=""; String fileString; for ( i = 0 ; i < origList.length ; i++ ) {iString = Integer.toString(i+1); while ( iString.length() < 3 ) iString = "0" + iString; fileString = "image" + iString; //System.out.println("Original at index " + i + " = " + origList[i]); for ( u = 0 ; u < origList.length ; u++ ) { if ( origList[u].substring(0,8).equalsIgnoreCase(fileString) ) {sortedList[i] = origList[u];u=origList.length;} } //System.out.println("Sorted at index " + i + " = " + sortedList[i]); } return(sortedList); } } // end CCfx