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