home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
beaversweeper_v101.zip
/
src
/
gtkformat.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2003-01-06
|
16KB
|
542 lines
/*****************************************************************************
* 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;
}