Import of Ekit 0.9h
[old-projects.git] / ekit / com / hexidec / util / DMCScodec.java
CommitLineData
c2da4d40 1/*\rGNU General Public License\r\rDMCScodec\rCopyright (C) 2002 Howard A Kistler\r\rThis program is free software; you can redistribute it and/or\rmodify it under the terms of the GNU General Public License\ras published by the Free Software Foundation; either version 2\rof the License, or (at your option) any later version.\r\rThis program is distributed in the hope that it will be useful,\rbut WITHOUT ANY WARRANTY; without even the implied warranty of\rMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\rGNU General Public License for more details.\r\rYou should have received a copy of the GNU General Public License\ralong with this program; if not, write to the Free Software\rFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r*/\r\rpackage com.hexidec.util;\r\rimport java.awt.AWTException;\rimport java.io.File;\rimport java.io.FileInputStream;\rimport java.io.FileNotFoundException;\rimport java.io.FileOutputStream;\rimport java.io.FileWriter;\rimport java.io.IOException;\r\r/** DMCScodec\r *\r * Utility for reading (and eventually converting) Deluxe Music\r * Construction Set (DMCS) files\r *\r * @author Howard Kistler\r * @version 0.1\r *\r * VERSION HISTORY\r * 0.1 (03/13/2002) - initial creation (03/13/2002)\r */\r\rpublic class DMCScodec\r{\r\r// Constants ---------------------------------------------------------------------------->\r\r/*\r DMCS File Structure\r\r FILE HEADER\r ====================\r (At the beginning of each file)\r FILE HEADER BLOCK\r 4 bytes - FORM\r 4 bytes - ?\r 4 bytes - DMCS\r 4 bytes - AMGA (for Amiga files)\r 4 bytes - ? (all zeroes?)\r SC HEADER BLOCK\r 4 bytes - USC1\r 8 bytes - ?\r 4 bytes - ?\r 8 bytes - ?\r 4 x 32 bytes - ?\r 1 byte - Title Byte count (number of letters in song title)\r X bytes - Song Title (length stated in previous byte)\r 16 bytes - 00 05 FE 77 01 01 01 02 00 00 3F 80 00 7F 00 00\r\r SONG BODY\r ====================\r UBR1 BLOCKS\r 4 bytes - UBR1\r\r INSTRUMENT BLOCK\r ====================\r (At the end of each file)\r INSTRUMENT HEAD BLOCK\r 4 bytes - UVLT\r 22 bytes - 00 00 00 12 00 00 00 0A 00 13 00 1F 00 2F 00 3F 00 51 00 69 00 7F\r INDIVIDUAL INSTRUMENT BLOCKS\r 4 bytes - UIID\r 4 bytes - ? (small int)\r X bytes - Instrument Name\r 2 bytes - 00 00 (last instrument may have just one byte of 00)\r*/\r\r // Header Array Sizes\r private final static byte StartFileHeaderSize = (byte)20;\r private final static byte InfoHeaderSize = (byte)40; // InfoHeader is always 40 bytes in size for BMP/ICO/CUR format\r\r // File Header Fields\r private final static byte[] FileHeaderFormWord = { 'F', 'O', 'R', 'M', };\r private static byte[] FileHeaderSizeWord = new byte[4];\r private final static byte[] FileHeaderTypeWord = { 'D', 'M', 'C', 'S' };\r private final static byte[] FileHeaderOSAMWord = { 'A', 'M', 'G', 'A' }; // OS Word for Amiga DMCS files\r private final static byte[] FileHeaderTailWord = { (byte)0, (byte)0, (byte)0, (byte)0 };\r\r // Song Body Fields\r private final static byte[] SongBlockUnitWord = { 'U', 'B', 'R', '1' };\r\r // Instrument Body Fields\r private final static byte[] InstrumentBlockHeadWord = { 'U', 'V', 'L', 'T' };\r private final static byte[] InstrumentBlockUnitWord = { 'U', 'I', 'I', 'D' };\r\r// Public Vartypes ---------------------------------------------------------------------->\r\r public final static int FILETYPE_DMCS = 1;\r public final static int FILETYPE_TEXT = 2;\r public final static int FILETYPE_FINALE = 3;\r\r// Constructor -------------------------------------------------------------------------->\r\r public DMCScodec()\r {\r }\r\r// Decode Method ------------------------------------------------------------------------>\r\r public static void decode(String sourceFile, String destFile)\r throws FileNotFoundException, IOException, AWTException\r {\r convertToTextFile(sourceFile, destFile);\r }\r\r// Encode Method ------------------------------------------------------------------------>\r\r public static void encode(String sourceFile, String destFile, int fileType)\r throws FileNotFoundException, IOException, AWTException\r {\r// String newFormat = convertToFormat(sourceFile, fileType);\r// writeToDMCSFile(newFormat, destFile);\r }\r\r// DMCS-to-TEXT File Conversion -------------------------------------------------------->\r\r protected static void convertToTextFile(String inFile, String outFile)\r throws IOException\r {\r File srcFile = new File(inFile);\r FileInputStream fis = new FileInputStream(srcFile);\r int filesize = (int)(srcFile.length());\r byte[] bData = new byte[filesize];\r int iCounter = 0;\r while(iCounter < filesize)\r {\r bData[iCounter] = (byte)(fis.read());\r iCounter++;\r }\r fis.close();\r\r FileWriter fw = new FileWriter(new File(outFile));\r\r String sOutput = "FILE SIZE : " + srcFile.length() + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "BYTES READ : " + iCounter + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r int iPlace = 0;\r\r sOutput = "====================\rFILE HEADER\r====================\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "--------------------\rFILE HEADER BLOCK\r--------------------\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "FORM BLOCK : " + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r int iSize =\r (int)(\r ((bData[iPlace++]) << 24) +\r ((bData[iPlace++]) << 16) +\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "SIZE BLOCK : " + iSize + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "TYPE BLOCK : " + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "OS BLOCK : " + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "TAIL BLOCK : " + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "--------------------\rSC HEADER BLOCK\r--------------------\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "USC1 BLOCK : " + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + (char)(bData[iPlace++]) + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r int iData =\r (int)(\r ((bData[iPlace++]) << 24) +\r ((bData[iPlace++]) << 16) +\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "DATA INT 1 : " + iData + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r iData =\r (int)(\r ((bData[iPlace++]) << 24) +\r ((bData[iPlace++]) << 16) +\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "DATA INT 2 : " + iData + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r iData =\r (int)(\r ((bData[iPlace++]) << 24) +\r ((bData[iPlace++]) << 16) +\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "DATA INT 3 : " + iData + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r iData =\r (int)(\r ((bData[iPlace++]) << 24) +\r ((bData[iPlace++]) << 16) +\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "DATA INT 4 : " + iData + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r iData =\r (int)(\r ((bData[iPlace++]) << 24) +\r ((bData[iPlace++]) << 16) +\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "DATA INT 5 : " + iData + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r for(int i = 0; i < 32; i++)\r {\r iData =\r (int)(\r ((bData[iPlace++]) << 24) +\r ((bData[iPlace++]) << 16) +\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "SUB INT " + (i+1) + " : " + iData + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r\r sOutput = "PAD BYTES : " + bData[iPlace++] + bData[iPlace++] + bData[iPlace++] + bData[iPlace++] + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r int titleCharCount = (int)(bData[iPlace++]);\r sOutput = "TITLE BYTE : " + titleCharCount + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "SONG TITLE : ";\r for(int i = 0; i < titleCharCount; i++)\r {\r sOutput = sOutput + (char)(bData[iPlace++]);\r }\r sOutput = sOutput + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r for(int i = 0; i < 19; i++)\r {\r sOutput = "POST BYTE " + (i+1) + " : " + bData[iPlace++] + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r\r sOutput = "====================\rSONG BODY\r====================\r";\r fw.write(sOutput, 0, sOutput.length());\r\r byte byteA = (byte)0;\r byte byteB = (byte)0;\r String blockWord = "";\r while(iPlace < filesize - 5)\r {\r byteA = bData[iPlace++];\r byteB = bData[iPlace++];\r blockWord = "" + (char)byteA + (char)byteB;\r if(blockWord.equals("UB"))\r {\r byte byteC = bData[iPlace++];\r byte byteD = bData[iPlace++];\r String blockWord2 = "" + (char)byteC + (char)byteD;\r if(blockWord2.equals("R1"))\r {\r sOutput = "--------------------\rUBR1 DATA BLOCK\r--------------------\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "DATA HEAD : " + blockWord + blockWord2 + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r else\r {\r int iWord =\r (int)(\r (byteA << 8) +\r (byteB )\r );\r sOutput = "WORD VALUE : " + iWord + "\r";\r fw.write(sOutput, 0, sOutput.length());\r iWord =\r (int)(\r (byteC << 8) +\r (byteD )\r );\r sOutput = "WORD VALUE : " + iWord + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r }\r else if(blockWord.equals("UV"))\r {\r byte byteC = bData[iPlace++];\r byte byteD = bData[iPlace++];\r String blockWord2 = "" + (char)byteC + (char)byteD;\r if(blockWord2.equals("LT"))\r {\r sOutput = "====================\rINSTRUMENT BLOCK\r====================\r";\r fw.write(sOutput, 0, sOutput.length());\r \r sOutput = "--------------------\rINSTRUMENT HEAD BLOCK\r--------------------\r";\r fw.write(sOutput, 0, sOutput.length());\r \r sOutput = "GROUP HEAD : " + blockWord + blockWord2 + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r int iWord = 0;\r for(int i = 0; i < 11; i++)\r {\r iWord =\r (int)(\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "SUB WORD " + (i+1) + " : " + iWord + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r }\r else\r {\r int iWord =\r (int)(\r (byteA << 8) +\r (byteB )\r );\r sOutput = "WORD VALUE : " + iWord + "\r";\r fw.write(sOutput, 0, sOutput.length());\r iWord =\r (int)(\r (byteC << 8) +\r (byteD )\r );\r sOutput = "WORD VALUE : " + iWord + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r }\r else if(blockWord.equals("UI"))\r {\r byte byteC = bData[iPlace++];\r byte byteD = bData[iPlace++];\r String blockWord2 = "" + (char)byteC + (char)byteD;\r if(blockWord2.equals("ID"))\r {\r sOutput = "--------------------\rINDIVIDUAL INSTRUMENT BLOCK\r--------------------\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "INSTR HEAD : " + blockWord + blockWord2 + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r int iVal =\r (int)(\r ((bData[iPlace++]) << 24) +\r ((bData[iPlace++]) << 16) +\r ((bData[iPlace++]) << 8) +\r ((bData[iPlace++]) )\r );\r sOutput = "NAME BYTES : " + iVal + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r sOutput = "INSTR NAME : ";\r for(int i = 0; i < iVal - 1; i++)\r {\r sOutput = sOutput + (char)(bData[iPlace++]);\r }\r sOutput = sOutput + "\r";\r fw.write(sOutput, 0, sOutput.length());\r\r if(iPlace < filesize - 2)\r {\r sOutput = "PAD BYTES : " + bData[iPlace++] + bData[iPlace++] + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r }\r else\r {\r int iWord =\r (int)(\r (byteA << 8) +\r (byteB )\r );\r sOutput = "WORD VALUE : " + iWord + "\r";\r fw.write(sOutput, 0, sOutput.length());\r iWord =\r (int)(\r (byteC << 8) +\r (byteD )\r );\r sOutput = "WORD VALUE : " + iWord + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r }\r else {\r int iWord =\r (int)(\r (byteA << 8) +\r (byteB )\r );\r sOutput = "WORD VALUE : " + iWord + "\r";\r fw.write(sOutput, 0, sOutput.length());\r }\r }\r\r fw.flush();\r fw.close();\r }\r\r// File Write Method ------------------------------------------------------------------->\r\r protected static void writeToDMCSFile(String fileData, String outFile)\r throws IOException\r {\r FileOutputStream fos = new FileOutputStream(new File(outFile));\r\r byte FileSizeByte1 = (byte)(fileData.length() & 0xFF);\r byte FileSizeByte2 = (byte)((fileData.length() >> 8) & 0xFF);\r byte FileSizeByte3 = (byte)((fileData.length() >> 16) & 0xFF);\r byte FileSizeByte4 = (byte)((fileData.length() >> 24) & 0xFF);\r\r byte[] DMCSFileHeader = new byte[]\r {\r FileHeaderFormWord[0], FileHeaderFormWord[1], FileHeaderFormWord[2], FileHeaderFormWord[3],\r FileSizeByte1, FileSizeByte2, FileSizeByte3, FileSizeByte4,\r FileHeaderTypeWord[0], FileHeaderTypeWord[1], FileHeaderTypeWord[2], FileHeaderTypeWord[3],\r FileHeaderOSAMWord[0], FileHeaderOSAMWord[1], FileHeaderOSAMWord[2], FileHeaderOSAMWord[3],\r FileHeaderTailWord[0], FileHeaderTailWord[1], FileHeaderTailWord[2], FileHeaderTailWord[3]\r };\r fos.write(DMCSFileHeader);\r\r/*\r byte BitmapWidthByte1 = (byte)(IntBitmapWidth & 0xFF);\r byte BitmapWidthByte2 = (byte)((IntBitmapWidth >> 8) & 0xFF);\r byte BitmapWidthByte3 = (byte)((IntBitmapWidth >> 16) & 0xFF);\r byte BitmapWidthByte4 = (byte)((IntBitmapWidth >> 24) & 0xFF);\r byte BitmapHeightByte1 = (byte)(IntBitmapHeight & 0xFF);\r byte BitmapHeightByte2 = (byte)((IntBitmapHeight >> 8) & 0xFF);\r byte BitmapHeightByte3 = (byte)((IntBitmapHeight >> 16) & 0xFF);\r byte BitmapHeightByte4 = (byte)((IntBitmapHeight >> 24) & 0xFF);\r byte BitmapImageSizeByte1 = (byte)(IntBitmapSize & 0xFF);\r byte BitmapImageSizeByte2 = (byte)((IntBitmapSize >> 8) & 0xFF);\r byte BitmapImageSizeByte3 = (byte)((IntBitmapSize >> 16) & 0xFF);\r byte BitmapImageSizeByte4 = (byte)((IntBitmapSize >> 24) & 0xFF);\r\r byte[] BitmapBodyHeader = new byte[] {\r InfoHeaderSizeByte1, InfoHeaderSizeByte2, InfoHeaderSizeByte3, InfoHeaderSizeByte4,\r BitmapWidthByte1, BitmapWidthByte2, BitmapWidthByte3, BitmapWidthByte4,\r BitmapHeightByte1, BitmapHeightByte2, BitmapHeightByte3, BitmapHeightByte4,\r BitmapPlanesByte1, BitmapPlanesByte2,\r BitmapBitCountByte1, BitmapBitCountByte2,\r BitmapCompressionByte1, BitmapCompressionByte2, BitmapCompressionByte3, BitmapCompressionByte4,\r BitmapImageSizeByte1, BitmapImageSizeByte2, BitmapImageSizeByte3, BitmapImageSizeByte4,\r BitmapXPixelsPerMByte1, BitmapXPixelsPerMByte2, BitmapXPixelsPerMByte3, BitmapXPixelsPerMByte4,\r BitmapYPixelsPerMByte1, BitmapYPixelsPerMByte2, BitmapYPixelsPerMByte3, BitmapYPixelsPerMByte4,\r BitmapColorsUsedByte1, BitmapColorsUsedByte2, BitmapColorsUsedByte3, BitmapColorsUsedByte4,\r BitmapColorsImportantByte1, BitmapColorsImportantByte2, BitmapColorsImportantByte3, BitmapColorsImportantByte4\r };\r fos.write(BitmapBodyHeader);\r\r int bodySize = IntBitmapWidth * IntBitmapHeight;\r int bitPad = 4 - ((IntBitmapWidth * 3) % 4);\r if(bitPad == 4) { bitPad = 0; }\r int countRow = 1;\r int indexRow = bodySize - IntBitmapWidth;\r int indexLastRow = indexRow;\r byte[] rgbArray = new byte[3];\r\r for(int i = 0; i < bodySize; i++)\r {\r int colorValue = PixelMap[indexRow];\r rgbArray[0] = (byte)(colorValue & 0xFF); // red\r rgbArray[1] = (byte)((colorValue >> 8) & 0xFF); // green\r rgbArray[2] = (byte)((colorValue >> 16) & 0xFF); // blue\r fos.write(rgbArray);\r if(countRow == IntBitmapWidth)\r {\r // pad row to 4 bits requirement\r for(int p = 0; p < bitPad; p++)\r {\r fos.write(0x00);\r }\r countRow = 1;\r indexRow = indexLastRow - IntBitmapWidth;\r indexLastRow = indexRow;\r }\r else\r {\r countRow++;\r }\r indexRow++;\r }\r*/\r\r fos.flush();\r fos.close();\r }\r\r public static void main(String[] args)\r {\r if(args.length < 3)\r {\r System.out.println("USAGE : DMCScodec -action input output");\r }\r else\r {\r if(args[0].equals("-t"))\r {\r try\r {\r decode(args[1], args[2]);\r }\r catch(Exception e)\r {\r System.out.println(e);\r }\r }\r else\r {\r System.out.println("action " + args[0] + "not yet supported");\r }\r }\r }\r\r}\r