Advertisement
sacio

XM file test

Aug 4th, 2012
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.01 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <stdio.h>
  4.  
  5. #include "main.h"
  6.  
  7. using namespace std;
  8.  
  9. void printStr(char * inputString, unsigned int stringSize, bool newLine);
  10.  
  11. //Globals
  12. int fileSize;               //Holds the file size of the xm file
  13. xmFileStruct xmData = {};        //Holds the xmData after parsing it
  14.  
  15. int main(){
  16.     printf("XM PARSE TEST (V1 0308) ODIN / SACIO\n\n");
  17.  
  18.     const char * fileName = "simple.xm";
  19.  
  20.     ifstream xmFile(fileName, ios::in | ios::binary | ios::ate);            //Load xm file for input operations in binary mode and set pointer at end
  21.                                                                             //so we can get file size by calling tellg() later on
  22.     if(!xmFile.is_open()){                                                  //Failed to open file
  23.         printf("ERROR: Failed to open file!\n");
  24.         return -1;                                                          //Return error
  25.     }
  26.  
  27.     fileSize = (int) xmFile.tellg();                                        //Set fileSize to the current position get-pointer (at the end)
  28.     xmFile.seekg(0, ios::beg);                                              //Set get-pointer to begining of file (no offset)
  29.  
  30.     //Print filename, size and memory address
  31.     printf("\tFilename:\t\t%s\n\tSize:\t\t\t%d bytes\n\n", fileName, fileSize);
  32.  
  33.     //Read XM Header
  34.     xmFile.read(xmData.xmHeader.IDText, 17);
  35.     xmFile.read(xmData.xmHeader.moduleName, 20);
  36.     xmFile.read(&xmData.xmHeader.checkByte, 1);
  37.     xmFile.read(xmData.xmHeader.trackerName, 20);
  38.     xmFile.read((char*)&xmData.xmHeader.versionNumber, 2);
  39.     xmFile.read((char*)&xmData.xmHeader.headerSize, 4);
  40.     xmFile.read((char*)&xmData.xmHeader.songLength, 2);
  41.     xmFile.read((char*)&xmData.xmHeader.restartPosition, 2);
  42.     xmFile.read((char*)&xmData.xmHeader.numberOfChannels, 2);
  43.     xmFile.read((char*)&xmData.xmHeader.numberOfPatterns, 2);
  44.     xmFile.read((char*)&xmData.xmHeader.numberOfInstruments, 2);
  45.     xmFile.read((char*)&xmData.xmHeader.flags, 2);
  46.     xmFile.read((char*)&xmData.xmHeader.defaultTempo, 2);
  47.     xmFile.read((char*)&xmData.xmHeader.defaultBPM, 2);
  48.     xmFile.read(xmData.xmHeader.patternOrderTable, 256);
  49.  
  50.     //Read pattern headers
  51.     xmData.patternHeaders = new xmPatternHeaderStruct[xmData.xmHeader.numberOfPatterns];    //Allocate space for pattern headers
  52.     xmData.patterns = new xmPatternStruct[xmData.xmHeader.numberOfPatterns];                //Allocate space for patterns
  53.     xmFile.seekg(xmData.xmHeader.headerSize+60, ios::beg);                                  //Set pointer at first pattern header (headersize+60)
  54.     for(int i=0; i<xmData.xmHeader.numberOfPatterns; i++){
  55.         //Read header for current pattern
  56.         xmFile.read((char*)&xmData.patternHeaders[i].headerLength, 4);
  57.         xmFile.read(&xmData.patternHeaders[i].packingType, 1);
  58.         xmFile.read((char*)&xmData.patternHeaders[i].numberOfRows, 2);
  59.         xmFile.read((char*)&xmData.patternHeaders[i].patternDataSize, 2);
  60.         if(xmData.patternHeaders[i].patternDataSize<=0){
  61.             //Pattern is empty, set standard values
  62.             xmData.patternHeaders[i].isEmpty = true;
  63.             xmData.patternHeaders[i].headerLength = 9;
  64.             xmData.patternHeaders[i].packingType = 0;
  65.             xmData.patternHeaders[i].numberOfRows = 64;
  66.             xmData.patternHeaders[i].patternDataSize = 64*xmData.xmHeader.numberOfChannels;
  67.             xmData.patternHeaders[i].patternData = new char[xmData.patternHeaders[i].patternDataSize];  //Allocate space for pattern data
  68.             //Fill pattern with 0x80
  69.             for(int x=0; x<xmData.patternHeaders[i].patternDataSize; x++){
  70.                xmData.patternHeaders[i].patternData[x] = 0x80;
  71.             }
  72.             //Set pointer to new offset (xm header + 60 + pattern header (pattern datasize is 0 in file))
  73.             xmFile.seekg(xmData.xmHeader.headerSize+60+xmData.patternHeaders[i].headerLength, ios::beg);
  74.         }else{
  75.             //Start to read pattern data
  76.             xmData.patternHeaders[i].patternData = new char[xmData.patternHeaders[i].patternDataSize];  //Allocate space for pattern data
  77.             xmFile.read(xmData.patternHeaders[i].patternData, xmData.patternHeaders[i].patternDataSize);
  78.             //Set pointer to new offset (xm header + 60 + pattern header + pattern data size)
  79.             xmFile.seekg(xmData.xmHeader.headerSize+60+xmData.patternHeaders[i].headerLength+xmData.patternHeaders[i].patternDataSize, ios::beg);
  80.         }
  81.         //Decompress and store pattern data into pattern structs
  82.         xmData.patterns[i].lines = new xmLineStruct[xmData.patternHeaders[i].numberOfRows];             //Allocate space for lines in pattern
  83.         for(int x=0; x<xmData.patternHeaders[i].numberOfRows; x++){
  84.             xmData.patterns[i].lines[x].notes = new xmNoteStruct[xmData.xmHeader.numberOfChannels];     //Allocate space for notes on line
  85.         }
  86.         bool patternComplete = false;   //Decompression complete?
  87.         bool lineComplete = false;      //Line complete?
  88.         int currentLine = 0;            //Current line in pattern
  89.         int currentNote = 0;            //Current note on line
  90.         int dataIndex = 0;              //Position in pattern data
  91.         while(!patternComplete){
  92.             while(!lineComplete){
  93.  
  94.                 if(xmData.patternHeaders[i].patternData[dataIndex]&0x80){                                   //Pattern data is compressed (MSB=1)
  95.                     if(xmData.patternHeaders[i].patternData[dataIndex]&0x01){                               //Note follows
  96.                         xmData.patterns[i].lines[currentLine].notes[currentNote].noteFollows = true;
  97.                     }
  98.                     if(xmData.patternHeaders[i].patternData[dataIndex]&0x02){                               //Instrument follows
  99.                         xmData.patterns[i].lines[currentLine].notes[currentNote].instrumentFollows = true;
  100.                     }
  101.                     if(xmData.patternHeaders[i].patternData[dataIndex]&0x04){                               //Volume column byte follows
  102.                         xmData.patterns[i].lines[currentLine].notes[currentNote].volumeFollows = true;
  103.                     }
  104.                     if(xmData.patternHeaders[i].patternData[dataIndex]&0x08){                               //Effect type follows
  105.                         xmData.patterns[i].lines[currentLine].notes[currentNote].effectTypeFollows = true;
  106.                     }
  107.                     if(xmData.patternHeaders[i].patternData[dataIndex]&0x10){                               //Effect parameter follows
  108.                         xmData.patterns[i].lines[currentLine].notes[currentNote].effectParamFollows = true;
  109.                     }
  110.                 }else{
  111.  
  112.                 }
  113.                 if(++currentNote>=xmData.xmHeader.numberOfChannels){                                        //No more notes on line
  114.                     lineComplete = true;                                                                    //Stop loop
  115.                 }
  116.             }
  117.  
  118.             if(++currentLine>=xmData.patternHeaders[i].numberOfRows){                                       //No more rows in pattern?
  119.                 patternComplete = true;                                                                     //Stop loop
  120.             }
  121.         }
  122.         for(int x=0; x<xmData.patternHeaders[i].patternDataSize; x+=5){                                 //Loop pattern data (5 bytes = 1 note)
  123.             //xmData.patterns[i].note[x] = patternHeaders[i].patternData[x];
  124.         }
  125.  
  126.         //Print pattern data
  127.         printf("Pattern %02d\n"
  128.                "\tLength: %d \n"
  129.                "\tPacktype: %d \n"
  130.                "\tRows: %d \n"
  131.                "\tDatasize: %d \n\n",
  132.                i,
  133.                xmData.patternHeaders[i].headerLength,
  134.                xmData.patternHeaders[i].packingType,
  135.                xmData.patternHeaders[i].numberOfRows,
  136.                xmData.patternHeaders[i].patternDataSize
  137.                );
  138.     }
  139.  
  140.  
  141.  
  142.     //Format and print data
  143.     printStr(xmData.xmHeader.IDText, 17, true);
  144.     printStr(xmData.xmHeader.moduleName, 20, true);
  145.     if(xmData.xmHeader.checkByte==0x1A){                //Is valid XM?
  146.         puts("Checkbyte matches XM specifications");
  147.     }else{
  148.         puts("ERROR: Checkbyte does not match!");
  149.         return -2;
  150.     }
  151.     printStr(xmData.xmHeader.trackerName, 20, true);
  152.     //Print version number. Hi byte = major, lo byte = minor version.
  153.     printf("v%d.%d\n", xmData.xmHeader.versionNumber>>8, xmData.xmHeader.versionNumber&0x00FF);
  154.     printf( "Header size: %d\n"
  155.             "Song length: %d\n"
  156.             "Restart position: %d\n"
  157.             "Number of Channels: %d\n"
  158.             "Number of Patterns: %d\n"
  159.             "Number of Instruments: %d\n",
  160.             xmData.xmHeader.headerSize,
  161.             xmData.xmHeader.songLength,
  162.             xmData.xmHeader.restartPosition,
  163.             xmData.xmHeader.numberOfChannels,
  164.             xmData.xmHeader.numberOfPatterns,
  165.             xmData.xmHeader.numberOfInstruments
  166.            );
  167.     if(xmData.xmHeader.flags&1){
  168.         puts("Linear frequency table");
  169.     }else{
  170.         puts("Amiga frequency table");
  171.     }
  172.     printf("Default tempo: %d\nDefault BPM: %d\n", xmData.xmHeader.defaultTempo,  xmData.xmHeader.defaultBPM);
  173.     puts("Pattern Order Table:");
  174.     for(int i=0; i<xmData.xmHeader.songLength; i++){
  175.         printf("%02d ", xmData.xmHeader.patternOrderTable[i]);
  176.     }
  177.  
  178.     if(!xmFile)
  179.         printf("FILE READ ERROR\n");
  180.     xmFile.close();                                                         //Close xm file
  181.     return 0;                                                               //Complete, return from main()
  182. }
  183.  
  184. void printStr(char * inputString, unsigned int stringSize, bool newLine){   //Print unterminated string to stdio (adds null terminator)
  185.     for(unsigned int i=0; i<stringSize; i++){
  186.         putchar(inputString[i]);
  187.     }
  188.     putchar('\0');
  189.     if(newLine)
  190.         putchar('\n');
  191.     return;
  192. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement