home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * File : gtkformat.c
- * Author(s) : Fredrik Kling (gnilk@home.se)
- * Original : 2001-01-27 01:42:43
- * Last edit : 2001-01-27 19:49:18
- * Description : Holds all system handling of the gtk_format
- *
- *---------------------------------------------------------------------------
- * Changes:
- *
- * -- Date -- | -- Name ------- | -- Did what...
- * 2001-11-27 | gnilk | Fixed expanding patterns/seq on loading if smaller..
- * 2001-11-26 | gnilk | Support for oldversions, and memory loading...
- * 2001-01-27 | gnilk | Implementation...
- *
- *****************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include "gtkformat.h"
-
- /*
- Format changes:
- 0103
- * pattern and sequencer length is 16 bit
-
- 0102 - First version
- */
-
- // apa hack!
- static HANDLE rfile;
-
- static unsigned short load_version;
-
- /*
- Reads some "normal" datatypes from within the file
- */
- static void writeint (HANDLE file,int i)
- {
- DWORD num;
- WriteFile (file,&i,sizeof (int),&num,NULL);
- }
- static void writebyte (HANDLE file,unsigned char i)
- {
- DWORD num;
- WriteFile (file,&i,1,&num,NULL);
- }
- static void writeword (HANDLE file,unsigned short i)
- {
- DWORD num;
- WriteFile (file,&i,sizeof (unsigned short),&num,NULL);
- }
-
- static int readint (HANDLE file)
- {
- DWORD num;
- int i;
- #ifndef __GTK_MEMREAD__
- ReadFile (file,&i,sizeof (int),&num,NULL);
- #else
- int *buf = (int *)rfile;
- i = *buf;
- rfile= (HANDLE)(buf + 1);
- #endif
- return i;
- }
- static unsigned char readbyte (HANDLE file)
- {
- DWORD num;
- unsigned char i;
- #ifndef __GTK_MEMREAD__
- ReadFile (file,&i,1,&num,NULL);
- #else
- unsigned char *pek = (unsigned char *)rfile;
- i = *pek;
- rfile = (HANDLE)(pek + 1);
- #endif
- return i;
- }
- static unsigned short readword (HANDLE file)
- {
- DWORD num;
- unsigned short i;
- #ifndef __GTK_MEMREAD__
- ReadFile (file,&i,sizeof(unsigned short),&num,NULL);
- #else
- unsigned short *pek = (unsigned short *)rfile;
- i = *pek;
- rfile = (HANDLE)(pek + 1);
- #endif
- return i;
- }
-
- static int ismem (char *ptr, char val, int sz)
- {
- int i;
- for (i=0;i<sz;i++) if (ptr[i]!=val) return 0;
- return 1;
- }
- static int checkpos (GTK_PATTERNPOS *ppos)
- {
- int flag,i;
- flag = 0;
- for (i=0;i<GTK_DEFAULT_PATCHANNELS;i++)
- {
- if (!ismem ((char *)&ppos[i],0,sizeof (GTK_PATTERNPOS)) )
- flag |= (1<<i);
- }
- return flag;
- }
-
- void gtk_expand_seq (GTK_SEQCHANNEL *chn,int oldlen)
- {
- chn->positions = (GTK_SEQPOS *)realloc(chn->positions,sizeof (GTK_SEQPOS) * chn->len);
- if (chn->len > oldlen)
- memset (&chn->positions[oldlen],0,sizeof (GTK_SEQPOS) * (chn->len - oldlen));
- }
- void gtk_expand_pat (GTK_PATTERN *pat, int oldlen)
- {
- int i;
- pat->patterndata = (GTK_PATTERNPOS **)realloc(pat->patterndata,sizeof (GTK_PATTERNPOS *) * pat->len); //GTK_DEFAULT_PATCHANNELS);
-
- // fixed overflow bug.. 2002-03-17. Dan
- for (i=oldlen;i<pat->len;i++)
- {
- pat->patterndata[i] = (GTK_PATTERNPOS *)malloc (sizeof (GTK_PATTERNPOS) * GTK_DEFAULT_PATCHANNELS); //gtk->patterns[i].len);
- memset (pat->patterndata[i],0,sizeof (GTK_PATTERNPOS) * GTK_DEFAULT_PATCHANNELS); // gtk->patterns[i].len);
- }
-
- }
- /*
-
- file layout:
-
- 0 GOAT
- 4 version (0x0101)
- 6 number of seq channels
- 7 number of patterns
- 8 number of instruments
- 9 song BPM
-
- 10 sequence tick per row
- 11 default pattern tick per row
- 12.. seq channel 0 of N in packed form
- X.. Pattern 0 of N in packed form...
-
- seqchannel data is stored as:
- 0 id of channel (which channel is this),
- 1 channel length (number of positions in channel)
- 2.. position data in packed form
-
- seq pos data is stored as:
- flag, indicating (bit flags)
- 0 no data is stored for this position
- 1 pattern number is stored
- 2 transpose values is stored
- 4 fx parameter is stored
- 8 param1 of fx is stored
- 0x10 param2 of fx is stored
- 0x20 param3 of fx is stored
- 0x40 param1 of fx is stored
- 0x80 param2 of fx is stored
- 0x100 param3 of fx is stored
-
- flag is stored as word..
- number of bytes indicated by the flags (each type has one byte)
- max is: 9 bytes in the order: <pattern><trans><instr><param1><param2><param3><param1><param2><param3>
-
-
- pattern data is stored as:
-
- 0 id of pattern, important: the sequencer will point to this number
- 1 length of pattern positions
-
- each row in a pattern is stored as:
-
- 0 flag, indicating which of the 16 channels that are used...
- if bit=1 pos data is available, bit 0 = pos 0, bit 1 = pos 1, bit 2 = pos 2.. (bit 0 = 0x01)
-
- 4 the position data itself is not packed...
- if position data is available it is stored as:
- <note><velocity><fx><param>
-
-
- */
- static void ReadSongData (HANDLE hFile, GTK *gtk)
- {
- DWORD nchn,npat,id;
- unsigned short flag;
- GTK_SEQPOS *spos;
- GTK_PATTERNPOS *ppos;
- DWORD num,k;
- int seqlen,patlen;
- int maxlen;
- int i,j;
-
- nchn = readbyte (hFile);
- npat = readbyte (hFile);
- gtk->num_instruments = readbyte (hFile);
- gtk->def_bpm = readbyte (hFile);
- gtk->def_pattick = readbyte (hFile);
- gtk->internal_seqtick= readbyte (hFile);
- gtk->def_seqtick = GTK_SEQ_MUL * gtk->internal_seqtick;
- seqlen = gtk->channels[0].len;
-
- maxlen = 0;
-
- for (i=0;i<nchn;i++)
- {
- id = readbyte (hFile);
- switch (load_version)
- {
- case 0x0102 :
- gtk->channels[id].len = readbyte (hFile);
- break;
- default :
- gtk->channels[id].len = readword (hFile);
- if (gtk->channels[id].len != seqlen)
- gtk_expand_seq (>k->channels[i],seqlen);
-
-
-
- break;
- }
- if (gtk->channels[id].len > maxlen)
- maxlen = gtk->channels[id].len;
- for (j=0;j<gtk->channels[id].len;j++)
- {
- spos = >k->channels[id].positions[j];
- flag = readword (hFile);
- if (flag)
- {
- if (flag & GTK_FILEFLAG_SEQPOS_PATTERN)
- spos->pattern = readbyte (hFile);
- if (flag & GTK_FILEFLAG_SEQPOS_TRANSPOSE)
- spos->transpose = readbyte (hFile);
- if (flag & GTK_FILEFLAG_SEQPOS_FX)
- spos->fx = readbyte (hFile);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM1)
- spos->param1 = readbyte (hFile);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM2)
- spos->param2 = readbyte (hFile);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM3)
- spos->param3 = readbyte (hFile);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM4)
- spos->param4 = readbyte (hFile);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM5)
- spos->param5 = readbyte (hFile);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM6)
- spos->param6 = readbyte (hFile);
- }
- }
- }
-
- // expand all patterns... if needed..
- for (i=0;i<gtk->num_channels;i++)
- {
- if (gtk->channels[i].len < maxlen)
- {
- int tmp;
- tmp = gtk->channels[i].len;
- gtk->channels[i].len = maxlen;
- gtk_expand_seq(>k->channels[i],tmp);
- }
- }
-
- patlen = gtk->patterns[0].len;
- for (i=0;i<npat;i++)
- {
- // write the "pattern" ID in the file...
- id = readbyte (hFile);
- // write down the pattern length
- switch (load_version)
- {
- case 0x0102 :
- gtk->patterns[id].len = readbyte (hFile);
- break;
- default :
- gtk->patterns[id].len = readword (hFile);
- if (gtk->patterns[id].len != patlen)
- gtk_expand_pat (>k->patterns[id],patlen);
- break;
- }
-
- for (j=0;j<gtk->patterns[id].len;j++)
- {
- unsigned int posflag;
- // ppos is a one row of position data... (hence: 16 pos)
- ppos = gtk->patterns[id].patterndata[j];
- // read the pos bitfield
- posflag = readint (hFile);
- // if there was any patterndata found at that row
- // loop through all positions and write down thoose with data..
- if (posflag)
- for (k=0;k<GTK_DEFAULT_PATCHANNELS;k++)
- if ((posflag >> k) & 1)
- {
- #ifndef __GTK_MEMREAD__
- ReadFile (hFile,&ppos[k],sizeof (GTK_PATTERNPOS),&num,NULL);
- #else
- {
- BYTE *pek;
- pek = (BYTE *)rfile;
- memcpy (&ppos[k],pek,sizeof (GTK_PATTERNPOS));
- rfile = (HANDLE)(pek + sizeof (GTK_PATTERNPOS));
- }
- #endif
- }
- }
-
-
-
- }
- }
-
- static void WriteSongData (HANDLE hFile, GTK *gtk)
- {
- int i,j,k;
- int nchn,npat;
- BYTE flag;
- DWORD num;
- int chnlist[16],patlist[256];
- GTK_SEQPOS *spos;
- GTK_PATTERNPOS *ppos;
-
- nchn = npat = 0;
- memset (chnlist,0,sizeof (int) * 16);
- memset (patlist,0,sizeof (int) * 256);
- // calc all patterns in the song...
- for (i=0;i<gtk->num_channels;i++)
- {
- for (j=0;j<gtk->channels[i].len;j++)
- {
- if (gtk->channels[i].positions[j].pattern!=0)
- {
- if (!chnlist[i]) nchn++;
- chnlist[i]=1;
- if (!patlist[gtk->channels[i].positions[j].pattern]) npat++;
- patlist[gtk->channels[i].positions[j].pattern]=1;
- }
- }
- }
- // write down how many there was...
- writebyte (hFile,nchn);
- writebyte (hFile,npat);
- writebyte (hFile,gtk->num_instruments);
- writebyte (hFile,gtk->def_bpm);
- writebyte (hFile,gtk->def_pattick);
- writebyte (hFile,gtk->internal_seqtick);
- // loop through and store each seq-channel
- for (i=0;i<gtk->num_channels;i++)
- {
- if (chnlist[i])
- {
- writebyte (hFile,i);
- writeword (hFile,gtk->channels[i].len);
- for (j=0;j<gtk->channels[i].len;j++)
- {
- spos = >k->channels[i].positions[j];
- flag = GTK_FILEFLAG_SEQPOS_NONE;
- if (spos->pattern) flag |= GTK_FILEFLAG_SEQPOS_PATTERN;
- if (spos->transpose) flag |= GTK_FILEFLAG_SEQPOS_TRANSPOSE;
- if (spos->fx) flag |= GTK_FILEFLAG_SEQPOS_FX;
- if (spos->param1) flag |= GTK_FILEFLAG_SEQPOS_PARAM1;
- if (spos->param2) flag |= GTK_FILEFLAG_SEQPOS_PARAM2;
- if (spos->param3) flag |= GTK_FILEFLAG_SEQPOS_PARAM3;
- if (spos->param4) flag |= GTK_FILEFLAG_SEQPOS_PARAM4;
- if (spos->param5) flag |= GTK_FILEFLAG_SEQPOS_PARAM5;
- if (spos->param6) flag |= GTK_FILEFLAG_SEQPOS_PARAM6;
- // writebyte (hFile,flag);
- writeword (hFile,flag);
-
- if (flag)
- {
- if (flag & GTK_FILEFLAG_SEQPOS_PATTERN)
- writebyte (hFile,spos->pattern);
- if (flag & GTK_FILEFLAG_SEQPOS_TRANSPOSE)
- writebyte (hFile,spos->transpose);
- if (flag & GTK_FILEFLAG_SEQPOS_FX)
- writebyte (hFile,spos->fx);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM1)
- writebyte (hFile,spos->param1);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM2)
- writebyte (hFile,spos->param2);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM3)
- writebyte (hFile,spos->param3);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM4)
- writebyte (hFile,spos->param4);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM5)
- writebyte (hFile,spos->param5);
- if (flag & GTK_FILEFLAG_SEQPOS_PARAM6)
- writebyte (hFile,spos->param6);
- }
- } // for (j=0;....
- } // if (chnlist
- }// for (i=0;...
-
-
- // now lets save all patterns in a slightly packed form...
- for (i=0;i<gtk->num_patterns;i++)
- {
- // if we have a pattern that should be stored
- if (patlist[i])
- {
- // write the "pattern" ID in the file...
- writebyte (hFile,i);
- // write down the pattern length
- // !VERSION! changed from byte to word from version 0102
- writeword (hFile,gtk->patterns[i].len);
- for (j=0;j<gtk->patterns[i].len;j++)
- {
- unsigned int posflag;
- // ppos is a one row of position data... (hence: 16 pos)
- ppos = gtk->patterns[i].patterndata[j];
- // check which rows to save
- posflag = checkpos (ppos);
- // write down the bitfiled
- writeint (hFile,posflag);
- // if there was any patterndata found at that row
- // loop through all positions and write down thoose with data..
- if (posflag)
- for (k=0;k<GTK_DEFAULT_PATCHANNELS;k++)
- if ((posflag >> k) & 1) WriteFile (hFile,&ppos[k],sizeof (GTK_PATTERNPOS),&num,NULL);
- }
- }
- }
-
-
- }
- int gtk_save (GTK *gtk,isSynth *synth,char *fname)
- {
- HANDLE hfile;
- DWORD num;
- unsigned short version=GTK_CURRENT_VERSION;
-
- hfile = CreateFile (fname,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if (hfile == INVALID_HANDLE_VALUE) return 0;
-
- // first write the synths data
- isFile f(hfile,false);
- synth->Save(&f);
-
- WriteFile (hfile,"GOAT",4,&num,NULL);
- WriteFile (hfile,&version,2,&num,NULL);
- WriteSongData (hfile,gtk);
-
- CloseHandle (hfile);
- return 0;
- };
-
- GTK *gtk_load (isSynth *synth,char *fname)
- {
- HANDLE hfile;
- DWORD num;
- char mod_id[5];
- GTK *gtk;
-
- gtk = NULL;
-
- #ifndef __GTK_MEMREAD__
- hfile = CreateFile (fname,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
- if (hfile == INVALID_HANDLE_VALUE)
- return 0;
- memset (mod_id,0,5);
- // first read the synths data
- isFile f(hfile,false);
- #else
- hfile = (HANDLE)fname;
- isFile f(hfile,true);
- #endif
- synth->Load(&f);
-
- #ifndef __GTK_MEMREAD__
- ReadFile (hfile,mod_id,4,&num,NULL);
- #else
- {
- DWORD pos;
- pos = f.GetPos();
- BYTE *pek = (BYTE *)hfile;
- hfile = (HANDLE)(pek + pos);
- pek = (BYTE *)hfile;
- memcpy (&mod_id,pek,4);
- rfile = (HANDLE)(pek+4);
- }
- #endif
- gtk = NULL;
- if (!memcmp (mod_id,"GOAT",4))
- {
- //ReadFile (hfile,&load_version,2,&num,NULL);
- load_version = readword(hfile);
- // if (version==GTK_CURRENT_VERSION)
- {
- gtk = gtk_create ();
- ReadSongData (hfile,gtk);
- }
- } else
- MessageBox( NULL, "Could not load song!", "rARHR", MB_OK );
- #ifndef __GTK_MEMREAD__
- CloseHandle (hfile);
- #endif
- return gtk;
-
- }
-
- int gtk_clearmod (GTK *mod)
- {
- return 1;
- }
- GTK *gtk_create (void)
- {
- GTK *gtk;
- int i,j;
- gtk = (GTK *)malloc (sizeof (GTK));
- gtk->num_channels = 16;
- gtk->num_patterns = 255;
- gtk->num_instruments=0;
- gtk->def_bpm=GTK_DEFAULT_BPM;
- gtk->def_pattick=GTK_DEFAULT_PATTICK;
- gtk->internal_seqtick = GTK_DEFAULT_SEQTICK;
- gtk->def_seqtick=gtk->internal_seqtick * GTK_SEQ_MUL;
-
- gtk->channels = (GTK_SEQCHANNEL *)malloc (sizeof (GTK_SEQCHANNEL) * gtk->num_channels);
- for (i=0;i<gtk->num_channels;i++)
- {
- gtk->channels[i].len = 64;
- gtk->channels[i].positions = (GTK_SEQPOS *)malloc (sizeof (GTK_SEQPOS) * 64);
- // for (j=0;j<gtk->channels[i].len;j++)
- memset (gtk->channels[i].positions,0,sizeof (GTK_SEQPOS) * gtk->channels[i].len);
- }
-
- gtk->patterns = (GTK_PATTERN *)malloc (sizeof (GTK_PATTERN) * gtk->num_patterns);
- for (i=0;i<gtk->num_patterns;i++)
- {
- gtk->patterns[i].len = 64;
- gtk->patterns[i].patterndata = (GTK_PATTERNPOS **)malloc (sizeof (GTK_PATTERNPOS *) * gtk->patterns[i].len); //GTK_DEFAULT_PATCHANNELS);
- for (j=0;j<gtk->patterns[i].len;j++)
- {
- gtk->patterns[i].patterndata[j] = (GTK_PATTERNPOS *)malloc (sizeof (GTK_PATTERNPOS) * GTK_DEFAULT_PATCHANNELS); //gtk->patterns[i].len);
- memset (gtk->patterns[i].patterndata[j],0,sizeof (GTK_PATTERNPOS) * GTK_DEFAULT_PATCHANNELS); // gtk->patterns[i].len);
- }
- }
- return gtk;
- }