sacio

XM file test

Aug 4th, 2012
28
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×