Anonymous avatar Anonymous committed 3305deb Merge

artificial commit to compensate for changes in 453756d19cc4 from a CVS
vendor branch

Comments (0)

Files changed (28)

Add a comment to this file

unimod/Debug/mikmod.ilk

Binary file added.

Add a comment to this file

unimod/Debug/mikmod.pch

Binary file added.

Add a comment to this file

unimod/Debug/mikmod.pdb

Binary file added.

Binary file added.

Binary file added.

unimod/ISoundDriver.h

+/*
+    Sound driver interface.
+
+
+    Currently, Unimods own their samples and instruments exclusively.  There is no way to share them between mods at present.
+    Must implement a better way of storing them, so that it can be done.
+
+    I'm not sure I like this setup.  The ISoundDriver implementation will have to cast an ISoundBuffer to whatever implementation matches
+    the driver.  Icky.  Ordinal handles? (ickier, but safer too)
+*/
+
+#pragma once
+
+namespace MikMod
+{
+
+    class ISoundBuffer;
+
+    class ISoundDriver
+    {
+    public:
+        // Sample factory
+        virtual ISoundBuffer* CreateSoundBuffer(u8* sampledata,u32 length,std::bitset<32> flags)=0;
+        virtual void FreeSoundBuffer(ISoundBuffer* s)=0;
+
+        // Driver stuffs
+        virtual void Update()=0;
+
+        // Cleanup.
+        virtual ~ISoundDriver() {}
+    };
+
+    // Platform/API specific buffer for holding a hunk of sound data.
+    class ISoundBuffer
+    {
+        // uhm... @_x
+    };
+
+};

unimod/PlayContext.h

+/*
+    I think this where the unimod mixer goes. :o
+*/
+
+#pragma once
+
+#include "types.h"
+#include "ISoundDriver.h"
+#include "Unimod.h"
+
+namespace MikMod
+{
+    // is an interface necessary?
+    class PlayContext
+    {
+        Unimod*                 pMod;
+        ISoundDriver*           pDriver;
+
+        vector<ISoundBuffer*>   pSamples;
+
+    public:
+        PlayContext(Unimod* mod,ISoundDriver* driver);
+        ~PlayContext();
+
+        void Update();
+    };
+};

unimod/common/types.h

+/*
+    Commonly used types, enums, etc...
+*/
+
+#ifndef TYPES_H
+#define TYPES_H
+
+#pragma warning (disable:4786)                      // identifier too long (stupid compiler)
+
+#include <vector>
+#include <string>
+#include <bitset>
+
+using std::string;
+using std::vector;
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long u64;
+
+#endif
+/*
+    Testbox.
+*/
+
+#include "PlayContext.h"
+
+void main()
+{
+}

unimod/mikmod.dsp

+# Microsoft Developer Studio Project File - Name="mikmod" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mikmod - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "mikmod.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "mikmod.mak" CFG="mikmod - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "mikmod - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mikmod - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "mikmod - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "unimod/" /I "common/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x1009 /d "NDEBUG"
+# ADD RSC /l 0x1009 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "mikmod - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "unimod/" /I "common/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x1009 /d "_DEBUG"
+# ADD RSC /l 0x1009 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "mikmod - Win32 Release"
+# Name "mikmod - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\out_DirectSound.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\ISoundDriver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\out_DirectSound.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PlayContext.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project

unimod/mikmod.dsw

+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "mikmod"=.\mikmod.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "unimod"=.\unimod\unimod.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

unimod/mikmod.plg

+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: mikmod - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\Andy1\LOCALS~1\Temp\RSP1A3.tmp" with contents
+[
+/nologo /MLd /W3 /Gm /GX /ZI /Od /I "unimod/" /I "common/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/mikmod.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c 
+"C:\src\mikmod.net\out_DirectSound.cpp"
+]
+Creating command line "cl.exe @C:\DOCUME~1\Andy1\LOCALS~1\Temp\RSP1A3.tmp" 
+<h3>Output Window</h3>
+Compiling...
+out_DirectSound.cpp
+
+
+
+<h3>Results</h3>
+out_DirectSound.obj - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>

unimod/out_DirectSound.cpp

+
+#include "out_DirectSound.h"
+
+using namespace MikMod;
+
+DirectSoundDriver::DirectSoundDriver()
+{
+    nBuffersallocated=0;        // keep a count, for debugging purposes.
+
+    HRESULT result=DirectSoundCreate8(NULL,&pDirectsound,NULL);
+    // if failed result blah blah
+}
+
+DirectSoundDriver::~DirectSoundDriver()
+{
+    pDirectsound->Release();
+}
+
+//---------------------------------------------------------------------------
+
+DirectSoundBuffer::DirectSoundBuffer(u8* sampledata,u32 length,std::bitset<32> flags)
+{
+    CDSBUFFERDESC bufferdesc;
+
+    bufferdesc.dwSize=sizeof bufferdesc;
+    bufferdesc.dwFlags=DSBCAPS_CTRLFREQUENCY;
+    bufferdesc.dwBufferBytes=length;
+    bufferdesc.dwReserved=0;
+
+
+    HRESULT result=pDirectsound->CreateSoundBuffer(&bufferdesc,&pBuffer,NULL);
+}

unimod/out_DirectSound.h

+
+#include "types.h"
+#include "ISoundDriver.h"
+#include <dsound.h>
+
+namespace MikMod
+{
+    class DirectSoundBuffer;
+
+    class DirectSoundDriver : public ISoundDriver
+    {
+        IDirectSound8*  pDirectsound;
+
+        // keep a list of ISoundBuffers this object has created?
+        int nBuffersallocated;
+
+    public:
+        DirectSoundDriver();
+        ~DirectSoundDriver();
+
+        virtual ISoundBuffer* CreateSoundBuffer(u8* sampledata,u32 length,std::bitset<32> flags);
+        virtual void FreeSoundBuffer(ISoundBuffer* s);
+
+        virtual void Update();
+    };
+
+    class DirectSoundBuffer : public ISoundBuffer
+    {
+        IDirectSoundBuffer8* pBuffer;
+    public:
+
+        DirectSoundBuffer(u8* sampledata,u32 length,std::bitset<32> flags);
+        ~DirectSoundBuffer();
+    };
+};

unimod/unimod/MODLoader.cpp

+
+#include <ios>
+#include "fileio.h"
+#include "types.h"
+#include "MODLoader.h"
+
+#include "fileio.h"
+
+using namespace MikMod;
+
+namespace
+{
+    // MOD specific headers and crap
+
+    struct SampleInfo
+    {
+        char    sName[22];
+        u16     nLength;
+        u8      finetune;
+        u8      nVolume;
+        u16     nReppos;
+        u16     nReplen;
+
+        SampleInfo()
+            : nLength(0),finetune(0),nVolume(0),nReppos(0),nReplen(0)
+        {}
+
+        void Read(BinaryStream& stream)
+        {
+            stream.read(sName,22);
+            stream >>
+                nLength >>
+                finetune >>
+                nVolume >>
+                nReppos >>
+                nReplen;
+        }
+    };
+
+    struct Header
+    {
+        char        sName[20];
+        SampleInfo  samples[31];
+        u8          nLength;
+        u8          magic1;             // should be 127
+        u8          nPosition[128];     // The order in which patterns should be played.
+        string      sID;                // id string.  4 bytes long
+        //u8          magic2[4];          // string "M.K.", "FLT4" or "FLT8"
+
+        void Read(BinaryStream& stream)
+        {
+            stream.read(sName,20);
+            for (int i=0; i<31; i++)
+                samples[i].Read(stream);//stream >> samples[i];
+
+            stream >> nLength;
+            stream >> magic1;               // eat up magic bytes
+            stream.read((char*)nPosition,128);
+
+            char sTemp[5];
+            sTemp[4]=0;
+            stream.read(sTemp,4);
+            sID=sTemp;
+        }
+    };
+
+    const int nHeadersize=1084;
+
+    struct ModType
+    {
+        char    id[5];
+        u8      nChannels;
+        string  sName;
+
+        ModType(){}
+
+        ModType(char bleh[5],int c,const char* s)
+        {
+            for (int i=0; i<5; i++) id[i]=bleh[i];
+            nChannels=c;
+            sName=s;
+        }
+    };
+
+    struct ModNote
+    {
+        u8 a,b,c,d;
+    };
+
+    static char protracker []  = "Protracker";
+    static char startrekker[]  = "Startrekker";
+    static char fasttracker[]  = "Fasttracker";
+    static char oktalyzer  []  = "Oktalyzer";
+    static char taketracker[]  = "TakeTracker";
+
+    ModType modtypes[] =
+    {  ModType("M.K.",4,protracker   ),   // protracker 4 channel
+       ModType("M!K!",4,protracker   ),   // protracker 4 channel
+       ModType("FLT4",4,startrekker  ),   // startracker 4 channel
+       ModType("2CHN",2,fasttracker  ),   // fasttracker 2 channel
+       ModType("4CHN",4,fasttracker  ),   // fasttracker 4 channel
+       ModType("6CHN",6,fasttracker  ),   // fasttracker 6 channel
+       ModType("8CHN",8,fasttracker  ),   // fasttracker 8 channel
+       ModType("10CH",10,fasttracker ),   // fasttracker 10 channel
+       ModType("12CH",12,fasttracker ),   // fasttracker 12 channel
+       ModType("14CH",14,fasttracker ),   // fasttracker 14 channel
+       ModType("16CH",16,fasttracker ),   // fasttracker 16 channel
+       ModType("18CH",18,fasttracker ),   // fasttracker 18 channel
+       ModType("20CH",20,fasttracker ),   // fasttracker 20 channel
+       ModType("22CH",22,fasttracker ),   // fasttracker 22 channel
+       ModType("24CH",24,fasttracker ),   // fasttracker 24 channel
+       ModType("26CH",26,fasttracker ),   // fasttracker 26 channel
+       ModType("28CH",28,fasttracker ),   // fasttracker 28 channel
+       ModType("30CH",30,fasttracker ),   // fasttracker 30 channel
+       ModType("CD81",8,oktalyzer    ),   // atari oktalyzer 8 channel
+       ModType("OKTA",8,oktalyzer    ),   // atari oktalyzer 8 channel
+       ModType("16CN",16,taketracker ),   // taketracker 16 channel
+       ModType("32CN",32,taketracker ),   // taketracker 32 channel
+    };
+
+    const int nModtypes=23;
+
+    // Stream overloads for gushy loading syntax
+    BinaryStream& operator >> (BinaryStream& src,SampleInfo& dest)
+    {
+        dest.Read(src);
+
+        return src;
+    }
+
+    BinaryStream& operator >> (BinaryStream& src,Header& dest)
+    {
+        dest.Read(src);
+
+        return src;
+    }
+
+};
+
+Note MODLoader::ConvertNote(const ModNote& n)
+{
+    // Table directly lifted from the original.  Algorithm almost directly lifted from the original.
+    static u16 notexlat[60] =
+    {   // -> Tuning 0
+        1712,1616,1524,1440,1356,1280,1208,1140,1076,1016 ,960 ,906,
+        856 ,808 ,762 ,720 ,678 ,640 ,604 ,570 ,538 ,508  ,480 ,453,
+        428 ,404 ,381 ,360 ,339 ,320 ,302 ,285 ,269 ,254  ,240 ,226,
+        214 ,202 ,190 ,180 ,170 ,160 ,151 ,143 ,135 ,127  ,120 ,113,
+        107 ,101 ,95  ,90  ,85  ,80  ,75  ,71  ,67  ,63   ,60  ,56
+    };
+
+    Note nprime;
+    int period;
+
+    nprime.instrument=(n.a & 0x10) | (n.c >> 4);
+    nprime.effect=n.c&0x0F;
+    nprime.effectdata=n.d;
+    period=((n.a & 0x0F)<<8) + n.b;
+
+    if (period!=0)
+    {
+        // Get the note closest to the period given.  (actually, this returns the first one bigger than the period specified)
+        for (int i=0; i<60; i++)
+            if (period>=notexlat[i])
+            {
+                nprime.note=i;
+                break;
+            }
+
+        nprime.note++;
+
+        // Really low period?
+        if (i==61)
+            nprime.note=0;
+    }
+    else
+        nprime.note=0;
+
+    if (nprime.effect==0x0D)    // convert jump thingie from dec to hex
+        nprime.effectdata=(((nprime.effectdata&0xf0)>>4)*10)+(nprime.effectdata&0xf);
+
+    return nprime;
+}
+
+void MODLoader::LoadPatterns(BinaryStream& stream,Unimod* mod)
+{
+    // Heh, lots of sizing vectors going on here.
+
+    ModNote n;
+
+    mod->patterns.resize(mod->numpatterns);
+
+    for (int nPattern=0; nPattern<mod->numpatterns; nPattern++)
+    {
+        Pattern& pattern=mod->patterns[nPattern];
+        pattern.channel.resize(mod->numchannels);
+
+        for (int nTrack=0; nTrack<64; nTrack++)
+        {
+            for (int nChan=0; nChan<mod->numchannels; nChan++)
+            {
+                pattern.channel[nChan].notes.resize(64);
+
+                stream >> n.a >> n.b >> n.c >> n.d;
+
+                pattern.channel[nChan].notes[nTrack]=ConvertNote(n);
+            }
+        }
+    }
+}
+
+void MODLoader::LoadSamples(BinaryStream& stream,Unimod* mod)
+{
+    // No support for much of anything remotely cool.
+
+    for (int i=0; i<mod->numsamples; i++)
+    {
+        UniSample& s=mod->samples[i];
+
+        delete[] s.pSampledata;         // paranoia.  This should always be null.
+
+        s.pSampledata=new u16[s.length];
+
+        if (!s.format.at(UniSample::sf_16bit))
+        {
+            // decode 8 bit crap into 16 bit!
+            u8* pTemp=new u8[s.length];
+
+            stream.read(pTemp,s.length);
+
+            for (int j=0; j<s.length; j++)
+                s.pSampledata[j]=pTemp[j]<<8;
+
+            delete[] pTemp;
+        }
+        else
+            // It's already 16 bits.  Woo.
+            stream.read(s.pSampledata,s.length);
+    }
+}
+
+Unimod* MODLoader::Load(std::istream& _stream)
+{
+    Unimod* mod=new Unimod;
+
+    BinaryStream stream(_stream);
+
+    char sTemp[1024];   // temp C string buffer thing
+    int i;              // omnipurpose loop iterator
+
+    Header header;
+
+    stream >> header;
+
+    // "Fix for FREAKY mods..  Not sure if it works for all of 'em tho.. ?"
+    // Directly copied from the original.  No idea what it means.
+    if (header.nLength>=129)    header.nLength=header.magic1;
+
+    int nModtype=0;
+
+    for (i=0; i<nModtypes; i++)
+    {
+        if (header.sID==modtypes[i].sName)
+        {
+            nModtype=i;
+            break;
+        }
+    }
+
+    mod->initspeed=6;
+    mod->inittempo=125;
+    mod->numchannels=modtypes[nModtype].nChannels;
+    mod->modtype=modtypes[nModtype].sName;
+    mod->songname=header.sName;
+    mod->numpositions=header.nLength;
+
+    mod->positions.resize(mod->numpositions);
+    for (i=0; i<mod->numpositions; i++)
+        mod->positions[i]=header.nPosition[i];
+
+    // No idea.  Something about counting the number of patterns
+    mod->numpatterns=0;
+
+    for (i=0; i<128; i++)
+    {
+        if (header.nPosition[i]>mod->numpatterns)
+            mod->numpatterns=header.nPosition[i];
+    }
+
+    mod->numpatterns++;
+    mod->numtracks=mod->numpatterns*mod->numchannels;
+
+    // sample info stuffs
+    mod->numsamples=31;
+    mod->samples.resize(mod->numsamples);
+
+    for (i=0; i<mod->numsamples; i++)
+    {
+        UniSample& unismp=mod->samples[i];
+        SampleInfo& modsmp=header.samples[i];
+
+        stream.read(sTemp,22);      unismp.sName=sTemp;
+        
+        unismp.speed     = MikMod::FineTune(modsmp.finetune);
+        unismp.volume    = modsmp.nVolume*2;
+        unismp.loopstart = modsmp.nReppos*2;
+        unismp.loopend   = unismp.loopstart + modsmp.nReplen*2;
+        unismp.length    = modsmp.nLength*2;
+        unismp.format    = UniSample::sf_signed;
+
+        if (modsmp.nReplen>1)
+            unismp.flags.set(UniSample::sl_loop);
+
+        // Enable aggressive declicking for songs that do not loop and that
+        // are long enough that they won't be adversely affected.
+        if (! (unismp.flags.at(UniSample::sl_loop) || unismp.flags.at(UniSample::sl_sustain_loop)) )
+            unismp.flags.set(UniSample::sl_declick);
+
+        if (unismp.loopend>unismp.length)
+            unismp.loopend=unismp.length;
+    }
+
+    LoadPatterns(stream,mod);
+
+    LoadSamples(stream,mod);
+
+    return mod;
+}

unimod/unimod/MODLoader.h

+
+#pragma once
+
+#include "types.h"
+#include "unimod.h"
+#include "fileio.h"
+#include "loader.h"
+#include <ios>
+
+namespace
+{
+    struct ModNote;
+};
+
+namespace MikMod
+{
+    class MODLoader : public ILoader
+    {
+        static Note ConvertNote(const struct ModNote& n);
+        static void LoadPatterns(BinaryStream& stream,Unimod* mod);
+        static void LoadSamples(BinaryStream& stream,Unimod* mod);
+    public:
+        virtual const char* GetExtension() { return "MOD"; }
+
+        virtual Unimod* Load(std::istream& stream);
+    };
+};

unimod/unimod/UniSample.cpp

+

unimod/unimod/UniSample.h

+
+#pragma once
+
+#include "types.h"
+#include <bitset>
+
+namespace MikMod
+{
+
+    struct UniSample
+    {
+        enum LoopFlags
+        {
+            sl_loop,
+            sl_bidirectional,
+            sl_reverse,
+            sl_sustain_loop,
+            sl_sustain_bidirectional,
+            sl_sustain_reverse,
+            sl_declick,
+
+            sl_resonance_filter,
+        };
+
+        enum FormatFlags
+        {
+            sf_16bit,
+            sf_stereo,
+            sf_signed,
+            sf_delta,
+            sf_big_endian,
+        };
+
+        // Mikmod's custom module player sample structure, used in the place of the MD_SAMPLE,
+        // which I normally use in applications for sound effects.  Reason: this has a lot of
+        // extra little tidbits which would be otherwise worthless in a sound effects situaiton.
+        std::bitset<32> flags;  // looping and player flags!
+        int    handle;          // handle to the sample loaded into the driver
+
+        u32    speed;           // default playback speed (almost anything is legal)
+        int    volume;          // 0 to 128 volume range
+        int    panning;         // PAN_LEFT to PAN_RIGHT range
+
+        u32    length;          // Length of the sample (samples, not bytes!)
+        u32    loopstart;       // Sample looping smackdown!
+        u32    loopend;
+        u32    susbegin;        // sustain loop begin (in samples)
+        u32    susend;          // sustain loop end
+
+        int    cutoff;          // the cutoff frequency (range 0 to 16384)
+        int    resonance;       // the resonance factor (range -128 to 128)
+
+        string sName;           // name of the sample    
+
+        bool   used;
+
+        // Sample Loading information - relay info between the loaders and
+        // unimod.c - like wow dude!
+
+        std::bitset<32> format; // diskformat flags, describe sample prior to loading!
+        u32    compress;        // compression status of the sample.
+        u64    seekpos;         // seekpos within the module.
+
+        u16*     pSampledata;
+
+        UniSample() : pSampledata(0) {}
+        ~UniSample() { delete[] pSampledata; }
+
+    };
+
+    class ExtSample { /* TODO... or even better... rethink */ };
+
+};

unimod/unimod/constants.h

+
+namespace MikMod
+{
+
+};

unimod/unimod/fileio.cpp

+
+#include "fileio.h"
+
+using namespace MikMod;
+
+BinaryStream::BinaryStream(std::istream& s)
+: stream(s)
+{
+}
+
+BinaryStream& BinaryStream::operator >> (u8& dest)
+{
+    stream.read((char*)&dest,1);
+
+    return *this;
+}
+
+BinaryStream& BinaryStream::operator >> (u16& dest)
+{
+    u8 b[2];
+
+    stream.read((char*)b,2);
+
+    dest=(b[1]<<16)|b[0];
+    return *this;
+}
+
+BinaryStream& BinaryStream::operator >> (u32& dest)
+{
+    u8 b[4];
+
+    stream.read((char*)b,4);
+
+    dest=(b[3]<<24) | (b[2]<<16) | (b[1]<<8) | b[0];
+    return *this;
+}
+
+void BinaryStream::read(void* dest,int numbytes)
+{
+    stream.read((char*)dest,numbytes);
+}

unimod/unimod/fileio.h

+
+/*
+    Useful things for file i/o in an endian independant manner.
+
+    Further, it's just better syntax. ^_^
+*/
+
+#pragma once
+
+#include <iostream>
+#include "types.h"
+
+namespace MikMod
+{
+    // input only.  Consider an output version?
+
+    class BinaryStream
+    {
+    private:
+        std::istream& stream;
+    public:
+
+        BinaryStream(std::istream& s);
+
+        BinaryStream& operator >> (u8& dest);
+        BinaryStream& operator >> (u16& dest);
+        BinaryStream& operator >> (u32& dest);
+
+        void read(void* dest,int numbytes);
+        
+    };
+};

unimod/unimod/loader.cpp

+
+#include "types.h"
+#include "loader.h"
+#include "unimod.h"
+#include <fstream>
+
+using namespace MikMod;
+
+Unimod* ILoader::Load(const string& fname)
+{
+    std::ifstream fstream(fname.c_str(),std::ios::binary);
+
+    return Load(fstream);
+}
+
+Loader::~Loader()
+{
+    for (std::map<string,ILoader*>::iterator i=loaders.begin(); i!=loaders.end(); i++)
+    {
+        delete i->second;
+    }
+}
+
+void Loader::RegisterLoader(ILoader* newloader)
+{
+    string extension=newloader->GetExtension();
+
+    if (loaders[extension]!=0)
+        delete loaders[extension];
+
+    loaders[extension]=newloader;
+}
+
+Unimod* Loader::Load(const string& fname)
+{
+    string s=fname;
+    for (int i=0; i<s.length(); i++)
+        if (s[i]>='a' && s[i]<='z')
+            s[i]&=~32;
+
+    int pos=s.rfind(".");
+    if (pos==string::npos)
+        return 0;
+
+    string sExtension=s.substr(pos+1);
+
+    std::ifstream fstream(fname.c_str(),std::ios::binary);
+
+    if (loaders[sExtension])
+        return loaders[sExtension]->Load(fstream);
+
+    return 0;
+}

unimod/unimod/loader.h

+
+#pragma once
+
+#include "types.h"
+#include <ios>
+#include <map>
+
+namespace MikMod
+{
+    // proto
+    class Unimod;
+
+    // Interface for module loaders
+    class ILoader
+    {
+    public:
+        virtual const char* GetExtension()=0;
+
+        virtual Unimod* Load(std::istream& stream)=0;
+        Unimod* Load(const string& fname);                  // convenience method for skipping the Loader class.
+    };
+
+    // Manages ILoader instances and presents a unified interface for loading modules.
+    // Maybe this should be a singleton or something.
+    class Loader
+    {
+        std::map<string,ILoader*> loaders;
+    public:
+
+        ~Loader();
+
+        void Loader::RegisterLoader(ILoader* newloader);
+
+        Unimod* Load(const string& fname);
+    };
+};

unimod/unimod/test.cpp

+/*
+    A simple testbox.  Not part of the API.
+*/
+
+#include "unimod.h"
+#include "modloader.h"
+#include <iostream>
+
+using namespace std;
+
+void main()
+{
+    MikMod::Loader loader;
+    loader.RegisterLoader(new MikMod::MODLoader);
+    MikMod::Unimod* pMod=loader.Load("aurora.mod");
+
+    for (vector<u16>::iterator i=pMod->positions.begin(); i!=pMod->positions.end(); i++)
+    {
+        cout << *i << " ";
+    }
+
+    cout << endl;
+
+    delete pMod;
+}

unimod/unimod/unimod.cpp

+
+#include "unimod.h"
+
+u16 MikMod::FineTune(u16 w)
+{
+    static u16 finetunexlat[] = 
+    {   
+        8363,   8413,   8463,   8529,   8581,   8651,   8723,   8757,
+        7895,   7941,   7985,   8046,   8107,   8169,   8232,   8280
+    };
+
+    return finetunexlat[w&0x0F];
+}

unimod/unimod/unimod.dsp

+# Microsoft Developer Studio Project File - Name="unimod" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=unimod - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "unimod.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "unimod.mak" CFG="unimod - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "unimod - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "unimod - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "unimod - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x1009 /d "NDEBUG"
+# ADD RSC /l 0x1009 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "unimod - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "unimod/" /I "..\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x1009 /d "_DEBUG"
+# ADD RSC /l 0x1009 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "unimod - Win32 Release"
+# Name "unimod - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\fileio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\loader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MODLoader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\unimod.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UniSample.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\fileio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\loader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MODLoader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\types.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\unimod.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UniSample.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\test.cpp
+# End Source File
+# End Target
+# End Project

unimod/unimod/unimod.dsw

+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "unimod"=.\unimod.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

unimod/unimod/unimod.h

+/*
+    Unimod.
+
+    VERY closely related to Air's MikMod implementation.  Very little code was directly used,
+    but the loaders are all based on his, and the structures are more or less his as well.
+
+    This is purely an in-memory representation of a MOD file.  Nothing here even closely relates to
+    actually doing anything other than storing a MOD file.
+*/
+
+#pragma once
+
+#include "types.h"
+#include "UniSample.h"
+
+namespace MikMod
+{
+
+    class Instrument { /* TODO */ };
+
+
+    // This gets convoluted.  Sadly.
+    // A mod consists of a number of patterns.
+    // A pattern is a number of tracks.  One for each channel.
+    // A track is a number of notes for one channel.
+
+    // The usual visual representation is that a pattern is a 2D grid, with a list of tracks on it.
+    // The mod consists of several of these.
+
+    struct Note
+    {
+        int instrument;             // instrument index
+        int note;                   // The note, fool.
+        int effect;                 // Effect thingies I'm not sure.
+        int effectdata;             // Fuck if I know.
+    };
+
+    struct Pattern
+    {
+        struct Track
+        {
+            vector<Note>    notes;
+        };
+        
+        vector<Track> channel;
+    };
+
+    class Unimod
+    {
+    public:
+        // Untimely ripped from Air's mikmod stuff.  All I did was C++ize it. -- andy
+
+        // This section of elements are all file-storage related.
+        // all of this information can be found in the UNIMOD disk format.
+        // For further details about there variables, see the MikMod Docs.
+
+//        u32        flags;         // See UniMod Flags above
+        // Options
+        bool bXmbehaviour;          // XP periods/finetuning/behaviour
+        bool bLinear;               // linear periods
+        bool bLinearpitenv;         // linear slides on envelopes?
+        bool bInstruments;          // using instruments?
+        bool bNewnoteactions;       // New Note Actions used (set numvoices rather than numchn)
+        bool bLinearfreq;           // Tran's frequency-linear mode (instead of periods)
+        bool bNopanning;            // dispable 8xx panning effects
+        bool bNoextspeed;           // disable PT extended speed
+        bool bNoresonance;          // disable 8xx panning effects
+        bool bExtsamples;           // uses extended samples?
+        //bool
+
+        // ...
+        u32        numchannels;     // number of module channels
+        u32        numvoices;       // voices allocated to NNA playback
+        u64        songlen;         // length of the song as predicted by PredictSongLength (1/1000th of a second).
+        u64        filesize;        // size of the module file, in bytes
+        u32        memsize;         // number of per-channel effect memory entires (a->memory) to allocate.
+
+        u32        numpositions;    // number of positions in this song
+        u32        numpatterns;     // number of patterns in this song
+        u32        numtracks;       // number of tracks
+        u32        numinstruments;  // number of instruments
+        u32        numsamples;      // number of samples
+        u32        reppos;          // restart position
+        u32        initspeed;       // initial song speed
+        u32        inittempo;       // initial song tempo
+        u32        initvolume;      // initial global volume (0 - 128)
+
+        int        panning[64];     // 64 initial panning positions
+        u32        chanvol[64];     // 64 initial channel volumes
+        bool       muted[64];       // 64 muting flags (I really should change this to a struct)
+
+        int        pansep;          // Panning separation (0=mono, 128=full stereo).
+
+        string     songname;        // name of the song
+        string     filename;        // name of the file this song came from (optional)
+        string     composername;    // name of the composer
+        string     comment;         // module comments
+        string     modtype;         // string type of module loaded
+
+        // Instruments and Samples!
+        vector<Instrument> instruments; // all instruments
+        vector<UniSample> samples;      // all samples
+        vector<ExtSample> extsamples;   // all extended sample-info (corresponds to each sample)
+
+        // UniTrack related -> Tracks and reading them!
+  
+        // Big problem here.  I have NO IDEA how this worked.  Sort of got the jist of it, then
+        // coded my own implementation.  Which means it's not the same as Air's!  Hope the renderer 
+        // can be adapted to cope easily.
+        vector<Pattern> patterns;
+        vector<u16> positions;      // pattern indeces.  Contains the order in which the patterns are to be played in.
+
+
+/*        // STL!  oh god, please.  STL.
+        u8     **tracks;         // array of numtrk pointers to tracks
+        u8     **globtracks;     // array of numpat pointers to global tracks
+        u16      *patterns;       // array of Patterns [index to tracks for each channel].
+        u16      *pattrows;       // array of number of rows for each pattern*/
+
+        u8       memflag[64];    // flags for each memory slot (alloc'd to mf->memsize)
+
+        //void      (*localeffects)(int effect, INT_MOB dat);
+        //void      (*globaleffects)(int effect, INT_MOB dat);
+
+        u64          strip_threshold;  // time, in milliseconds, before shortening song.
+        int          sngpos_silence;   // number of positions in this song
+        int          patpos_silence;   // number of patterns in this song
+
+        //------------------------------------------------
+        // Methods
+    };
+
+    u16 FineTune(u16 w);
+};
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.