home *** CD-ROM | disk | FTP | other *** search
- /* songloader.c by Teijo Kinnunen 1990 */
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <libraries/dos.h>
- #ifdef LATTICE
- #include <dos.h>
- #include <string.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #endif
- UWORD chip zeroptr;
- struct ObjSong {
- UBYTE vol[32];
- UWORD rep[32],replen[32];
- UWORD blocks;
- UBYTE playseq[100];
- UWORD songlen;
- BYTE playtransp;
- UBYTE flags;
- UWORD slide;
- UBYTE midichan[32],midipres[32];
- } song;
- static UWORD lohkoja,tempo;
- struct Lohko { UBYTE numtracks; UBYTE pad[3]; UBYTE music[768]; } *blocks[100];
- struct Soitin { ULONG length; UWORD type; } *samples[32];
- #define M0F_LINEMSK0F 0x1
- #define M0F_LINEMSK1F 0x2
- #define M0F_FXMSK0F 0x4
- #define M0F_FXMSK1F 0x8
- #define M0F_LINEMSK00 0x10
- #define M0F_LINEMSK10 0x20
- #define M0F_FXMSK00 0x40
- #define M0F_FXMSK10 0x80
- BOOL LataaKappale();
- static BOOL NewInstrument(),diskerr(),AllocBlock();
- static void FreeBlocksAndSamples();
-
- static BOOL FRead(fh,ptr,len)
- BPTR fh;
- char *ptr;
- long len;
- {
- return((BOOL)(Read(fh,ptr,len) != len));
- }
-
- static UBYTE GetNibble(mem,nbnum)
- UBYTE *mem;
- UWORD *nbnum;
- {
- UBYTE *mloc = mem + (*nbnum / 2),res;
- if(*nbnum & 0x1) res = *mloc & 0x0f;
- else res = *mloc >> 4;
- (*nbnum)++;
- return(res);
- }
-
- static UWORD GetNibbles(mem,nbnum,nbs)
- UBYTE *mem;
- UWORD *nbnum;
- UBYTE nbs;
- {
- UWORD res = 0;
- while(nbs--) { res <<= 4; res |= GetNibble(mem,nbnum); }
- return(res);
- }
-
- static void UnpackBlock(bnum,from)
- UWORD bnum;
- UBYTE *from;
- {
- UBYTE *to = blocks[bnum]->music,lcnt,trkn = blocks[bnum]->numtracks;
- ULONG linemsk0 = *((ULONG *)from),linemsk1 = *((ULONG *)from + 1);
- ULONG fxmsk0 = *((ULONG *)from + 2),fxmsk1 = *((ULONG *)from + 3);
- ULONG *lmptr = &linemsk0,*fxptr = &fxmsk0;
- UWORD fromn = 0,lmsk;
- UBYTE *fromst = from + 16,bcnt,*tmpto;
- from += 16;
- for(lcnt = 0; lcnt < 64; lcnt++) {
- if(lcnt == 32) { lmptr = &linemsk1; fxptr = &fxmsk1; }
- if(*lmptr & 0x80000000) {
- lmsk = GetNibbles(fromst,&fromn,(UBYTE)(trkn /á4));
- lmsk <<= (16 - trkn);
- tmpto = to;
- for(bcnt = 0; bcnt < trkn; bcnt++) {
- if(lmsk & 0x8000) {
- *tmpto = (UBYTE)GetNibbles(fromst,
- &fromn,2);
- *(tmpto+1) = (GetNibble(fromst,
- &fromn) << 4);
- }
- lmsk <<= 1; tmpto += 3;
- }
- }
- if(*fxptr & 0x80000000) {
- lmsk = GetNibbles(fromst,&fromn,(UBYTE)(trkn /á4));
- lmsk <<= (16 - trkn);
- tmpto = to;
- for(bcnt = 0; bcnt < trkn; bcnt++) {
- if(lmsk & 0x8000) {
- *(tmpto+1) |= GetNibble(fromst,
- &fromn);
- *(tmpto+2) = (UBYTE)GetNibbles(
- fromst,&fromn,2);
- }
- lmsk <<= 1; tmpto += 3;
- }
- }
- to += 3 * trkn;
- *lmptr <<= 1; *fxptr <<= 1;
- }
- }
-
- static BOOL Load200Song(fh)
- BPTR fh;
- {
- ULONG zmsk,*conv = 0;
- UWORD convsz;
- UBYTE scnt,namech,blkcnt;
- if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0)); /* MED\x03 */
- for(scnt = 0; scnt < 32; scnt++) {
- for(;;) {
- if(FRead(fh,&namech,1)) return(diskerr(fh,0));
- if(namech == '\0') break;
- }
- }
- if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
- for(scnt = 0; scnt < 32; scnt++) {
- if(zmsk & 0x80000000) {
- if(FRead(fh,&song.vol[scnt],1)) return(diskerr(fh,0));
- } else song.vol[scnt] = 0;
- zmsk <<= 1;
- }
- if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
- for(scnt = 0; scnt < 32; scnt++) {
- if(zmsk & 0x80000000) {
- if(FRead(fh,(char *)(&song.rep[scnt]),2)) return(diskerr(fh,0));
- } else song.rep[scnt] = 0;
- zmsk <<= 1;
- }
- if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
- for(scnt = 0; scnt < 32; scnt++) {
- if(zmsk & 0x80000000) {
- if(FRead(fh,(char *)(&song.replen[scnt]),2)) return(diskerr(fh,0));
- } else song.replen[scnt] = 0;
- zmsk <<= 1;
- }
- if(FRead(fh,(char *)(&song.blocks),2)) return(diskerr(fh,0));
- if(FRead(fh,(char *)(&song.songlen),2)) return(diskerr(fh,0));
- if(FRead(fh,song.playseq,song.songlen)) return(diskerr(fh,0));
- if(FRead(fh,(char *)(&tempo),2)) return(diskerr(fh,0));
- if(FRead(fh,(char *)(&song.playtransp),4)) return(diskerr(fh,0));
- for(scnt = 0; scnt < 20; scnt++) { /* skip 20 bytes (jump,color) */
- if(FRead(fh,&namech,1)) return(diskerr(fh,0));
- }
- if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
- for(scnt = 0; scnt < 32; scnt++) {
- if(zmsk & 0x80000000) {
- if(FRead(fh,&song.midichan[scnt],1)) return(diskerr(fh,0));
- } else song.midichan[scnt] = 0;
- zmsk <<= 1;
- }
- if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
- for(scnt = 0; scnt < 32; scnt++) {
- if(zmsk & 0x80000000) {
- if(FRead(fh,&song.midipres[scnt],1)) return(diskerr(fh,0));
- } else song.midipres[scnt] = 0;
- zmsk <<= 1;
- }
- lohkoja = 0;
- for(blkcnt = 0; blkcnt < song.blocks; blkcnt++) {
- if(FRead(fh,&scnt,1)) return(diskerr(fh,0));
- if(AllocBlock(blkcnt,scnt)) return(diskerr(fh,"No memory."));
- lohkoja++;
- if(FRead(fh,&scnt,1)) return(diskerr(fh,0));
- if(FRead(fh,(char *)(&convsz),2)) return(diskerr(fh,0));
- if(!(conv = AllocMem(convsz+16,MEMF_PUBLIC|MEMF_CLEAR))) return(diskerr(fh,"No memory."));
- if(scnt & M0F_LINEMSK00) *conv = 0L;
- else if(scnt & M0F_LINEMSK0F) *conv = 0xffffffff;
- else if(FRead(fh,(UBYTE *)conv,4)) return(diskerr(fh,0));
- if(scnt & M0F_LINEMSK10) *(conv+1) = 0L;
- else if(scnt & M0F_LINEMSK1F) *(conv+1) = 0xffffffff;
- else if(FRead(fh,(UBYTE *)(conv + 1),4)) return(diskerr(fh,0));
- if(scnt & M0F_FXMSK00) *(conv+2) = 0L;
- else if(scnt & M0F_FXMSK0F) *(conv+2) = 0xffffffff;
- else if(FRead(fh,(UBYTE *)(conv + 2),4)) return(diskerr(fh,0));
- if(scnt & M0F_FXMSK10) *(conv+3) = 0L;
- else if(scnt & M0F_FXMSK1F) *(conv+3) = 0xffffffff;
- else if(FRead(fh,(UBYTE *)(conv + 3),4)) return(diskerr(fh,0));
- if(FRead(fh,(UBYTE *)(conv + 4),convsz)) return(diskerr(fh,0));
- UnpackBlock((UWORD)blkcnt,(UBYTE *)conv);
- FreeMem(conv,convsz+16); conv = 0;
- }
- return(FALSE);
- }
-
- static BOOL LoadAttachedInstrs(fh)
- BPTR fh;
- {
- ULONG imsk,instrnum;
- struct Soitin loaded;
- if(FRead(fh,(char *)(&imsk),4)) return(diskerr(0,0));
- instrnum = 0;
- while(instrnum < 31) {
- imsk <<= 1; /* There's no instrument #0 */
- instrnum++;
- if(imsk & 0x80000000) {
- if(FRead(fh,(char *)(&loaded),sizeof(struct Soitin)))
- return(diskerr(0,0));
- if(NewInstrument(loaded.length,instrnum))
- return(diskerr(0,"Out of memory."));
- samples[instrnum]->type = loaded.type;
- if(FRead(fh,((char *)samples[instrnum]) +
- sizeof(struct Soitin),loaded.length))
- return(diskerr(0,0));
- }
- }
- return(FALSE);
- }
-
- static BOOL NewInstrument(size,num)
- ULONG size;
- UWORD num;
- {
- if(samples[num]) {
- FreeMem((void *)samples[num],samples[num]->length +
- sizeof(struct Soitin));
- samples[num] = NULL;
- }
- samples[num] = AllocMem(size + sizeof(struct Soitin),
- MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR);
- if(!samples[num]) return(TRUE);
- samples[num]->length = size;
- return(FALSE);
- }
-
- BOOL LoadSong(name)
- char *name;
- {
- BPTR fh;
- char tunnus[5];
- StopPlayer();
- FreeBlocksAndSamples();
- if(!(fh = Open(name,MODE_OLDFILE))) return(diskerr(fh,0));
- if(Read(fh,tunnus,4) != 4) return(diskerr(fh,"Not a song!"));
- tunnus[4] = '\0';
- Seek(fh,0,OFFSET_BEGINNING);
- if(AllocBlock(0,4)) return(diskerr(fh,"No memory."));
- lohkoja = 0;
- if(!strcmp(tunnus,"MED\x03")) {
- if(Load200Song(fh)) return(diskerr(fh,0));
- } else return(diskerr(fh,"Not a MEDV2.00 song!!"));
- if(song.flags & 0x8) LoadAttachedInstrs(fh);
- Close(fh);
- SetTempo(tempo);
- return(FALSE);
- }
-
- static BOOL diskerr(fh,txt)
- BPTR fh;
- char *txt; /* some text about error (if 0, call IoErr()) */
- {
- if(fh) Close(fh);
- /* Add code here, if you want error handling. */
- return(TRUE);
- }
-
- static void FreeBlock(num)
- UWORD num;
- {
- if(blocks[num]) {
- FreeMem(blocks[num],4 + blocks[num]->numtracks * 3 * 64);
- blocks[num] = 0L;
- }
- }
-
- static BOOL AllocBlock(num,tracks) /* TRUE = error, FALSE = ok!! */
- UWORD num;
- UBYTE tracks;
- {
- if(blocks[num]) {
- if(blocks[num]->numtracks == tracks) return(FALSE);
- FreeBlock(num);
- }
- if(!(blocks[num] = AllocMem(4 + (3 * 64) * tracks,MEMF_PUBLIC|
- MEMF_CLEAR))) return(TRUE);
- blocks[num]->numtracks = tracks;
- return(FALSE);
- }
-
- static void FreeAllBlocks()
- {
- int cnt;
- for(cnt = 0; cnt < 100; cnt++) FreeBlock(cnt);
- }
-
- static void FreeSamples()
- {
- UWORD scnt;
- for(scnt = 1; scnt < 32; scnt++)
- if(samples[scnt]) {
- FreeMem((void *)samples[scnt],samples[scnt]->length
- + sizeof(struct Soitin));
- samples[scnt] = NULL;
- }
- }
-
- void FreeBlocksAndSamples()
- {
- FreeAllBlocks();
- FreeSamples();
- }
-