home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 369b.lha / MED_v2.0 / Source / Player / songloader.c < prev   
C/C++ Source or Header  |  1990-05-03  |  8KB  |  312 lines

  1. /* songloader.c by Teijo Kinnunen 1990 */
  2. #include <exec/types.h>
  3. #include <exec/memory.h>
  4. #include <libraries/dos.h>
  5. #ifdef LATTICE
  6. #include <dos.h>
  7. #include <string.h>
  8. #include <proto/exec.h>
  9. #include <proto/dos.h>
  10. #endif
  11. UWORD chip zeroptr;
  12. struct ObjSong {
  13.     UBYTE vol[32];
  14.     UWORD rep[32],replen[32];
  15.     UWORD blocks;
  16.     UBYTE playseq[100];
  17.     UWORD songlen;
  18.     BYTE  playtransp;
  19.     UBYTE flags;
  20.     UWORD slide;
  21.     UBYTE midichan[32],midipres[32];
  22. } song;
  23. static UWORD lohkoja,tempo;
  24. struct Lohko { UBYTE numtracks; UBYTE pad[3]; UBYTE music[768]; } *blocks[100];
  25. struct Soitin { ULONG length; UWORD type; } *samples[32];
  26. #define M0F_LINEMSK0F    0x1
  27. #define M0F_LINEMSK1F    0x2
  28. #define M0F_FXMSK0F    0x4
  29. #define M0F_FXMSK1F    0x8
  30. #define M0F_LINEMSK00    0x10
  31. #define M0F_LINEMSK10    0x20
  32. #define M0F_FXMSK00    0x40
  33. #define M0F_FXMSK10    0x80
  34. BOOL LataaKappale();
  35. static BOOL NewInstrument(),diskerr(),AllocBlock();
  36. static void FreeBlocksAndSamples();
  37.  
  38. static BOOL FRead(fh,ptr,len)
  39. BPTR fh;
  40. char *ptr;
  41. long len;
  42. {
  43.     return((BOOL)(Read(fh,ptr,len) != len));
  44. }
  45.  
  46. static UBYTE GetNibble(mem,nbnum)
  47. UBYTE *mem;
  48. UWORD *nbnum;
  49. {
  50.     UBYTE *mloc = mem + (*nbnum / 2),res;
  51.     if(*nbnum & 0x1) res = *mloc & 0x0f;
  52.     else res = *mloc >> 4;
  53.     (*nbnum)++;
  54.     return(res);
  55. }
  56.  
  57. static UWORD GetNibbles(mem,nbnum,nbs)
  58. UBYTE *mem;
  59. UWORD *nbnum;
  60. UBYTE nbs;
  61. {
  62.     UWORD res = 0;
  63.     while(nbs--) { res <<= 4; res |= GetNibble(mem,nbnum); }
  64.     return(res);
  65. }
  66.  
  67. static void UnpackBlock(bnum,from)
  68. UWORD bnum;
  69. UBYTE *from;
  70. {
  71.     UBYTE *to = blocks[bnum]->music,lcnt,trkn = blocks[bnum]->numtracks;
  72.     ULONG linemsk0 = *((ULONG *)from),linemsk1 = *((ULONG *)from + 1);
  73.     ULONG fxmsk0 = *((ULONG *)from + 2),fxmsk1 = *((ULONG *)from + 3);
  74.     ULONG *lmptr = &linemsk0,*fxptr = &fxmsk0;
  75.     UWORD fromn = 0,lmsk;
  76.     UBYTE *fromst = from + 16,bcnt,*tmpto;
  77.     from += 16;
  78.     for(lcnt = 0; lcnt < 64; lcnt++) {
  79.         if(lcnt == 32) { lmptr = &linemsk1; fxptr = &fxmsk1; }
  80.         if(*lmptr & 0x80000000) {
  81.             lmsk = GetNibbles(fromst,&fromn,(UBYTE)(trkn / 4));
  82.             lmsk <<= (16 - trkn);
  83.             tmpto = to;
  84.             for(bcnt = 0; bcnt < trkn; bcnt++) {
  85.                 if(lmsk & 0x8000) {
  86.                     *tmpto = (UBYTE)GetNibbles(fromst,
  87.                         &fromn,2);
  88.                     *(tmpto+1) = (GetNibble(fromst,
  89.                             &fromn) << 4);
  90.                 }
  91.                 lmsk <<= 1; tmpto += 3;
  92.             }
  93.         }
  94.         if(*fxptr & 0x80000000) {
  95.             lmsk = GetNibbles(fromst,&fromn,(UBYTE)(trkn / 4));
  96.             lmsk <<= (16 - trkn);
  97.             tmpto = to;
  98.             for(bcnt = 0; bcnt < trkn; bcnt++) {
  99.                 if(lmsk & 0x8000) {
  100.                     *(tmpto+1) |= GetNibble(fromst,
  101.                             &fromn);
  102.                     *(tmpto+2) = (UBYTE)GetNibbles(
  103.                         fromst,&fromn,2);
  104.                 }
  105.                 lmsk <<= 1; tmpto += 3;
  106.             }
  107.         }
  108.         to += 3 * trkn;
  109.         *lmptr <<= 1; *fxptr <<= 1;
  110.     }
  111. }
  112.  
  113. static BOOL Load200Song(fh)
  114. BPTR fh;
  115. {
  116.     ULONG zmsk,*conv = 0;
  117.     UWORD convsz;
  118.     UBYTE scnt,namech,blkcnt;
  119.     if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0)); /* MED\x03 */
  120.     for(scnt = 0; scnt < 32; scnt++) {
  121.         for(;;) {
  122.             if(FRead(fh,&namech,1)) return(diskerr(fh,0));
  123.             if(namech == '\0') break;
  124.         }
  125.     }
  126.     if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
  127.     for(scnt = 0; scnt < 32; scnt++) {
  128.         if(zmsk & 0x80000000) {
  129.             if(FRead(fh,&song.vol[scnt],1)) return(diskerr(fh,0));
  130.         } else song.vol[scnt] = 0;
  131.         zmsk <<= 1;
  132.     }
  133.     if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
  134.     for(scnt = 0; scnt < 32; scnt++) {
  135.         if(zmsk & 0x80000000) {
  136.             if(FRead(fh,(char *)(&song.rep[scnt]),2)) return(diskerr(fh,0));
  137.         } else song.rep[scnt] = 0;
  138.         zmsk <<= 1;
  139.     }
  140.     if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
  141.     for(scnt = 0; scnt < 32; scnt++) {
  142.         if(zmsk & 0x80000000) {
  143.             if(FRead(fh,(char *)(&song.replen[scnt]),2)) return(diskerr(fh,0));
  144.         } else song.replen[scnt] = 0;
  145.         zmsk <<= 1;
  146.     }
  147.     if(FRead(fh,(char *)(&song.blocks),2)) return(diskerr(fh,0));
  148.     if(FRead(fh,(char *)(&song.songlen),2)) return(diskerr(fh,0));
  149.     if(FRead(fh,song.playseq,song.songlen)) return(diskerr(fh,0));
  150.     if(FRead(fh,(char *)(&tempo),2)) return(diskerr(fh,0));
  151.     if(FRead(fh,(char *)(&song.playtransp),4)) return(diskerr(fh,0));
  152.     for(scnt = 0; scnt < 20; scnt++) { /* skip 20 bytes (jump,color) */
  153.         if(FRead(fh,&namech,1)) return(diskerr(fh,0));
  154.     }
  155.     if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
  156.     for(scnt = 0; scnt < 32; scnt++) {
  157.         if(zmsk & 0x80000000) {
  158.             if(FRead(fh,&song.midichan[scnt],1)) return(diskerr(fh,0));
  159.         } else song.midichan[scnt] = 0;
  160.         zmsk <<= 1;
  161.     }
  162.     if(FRead(fh,(char *)(&zmsk),4)) return(diskerr(fh,0));
  163.     for(scnt = 0; scnt < 32; scnt++) {
  164.         if(zmsk & 0x80000000) {
  165.             if(FRead(fh,&song.midipres[scnt],1)) return(diskerr(fh,0));
  166.         } else song.midipres[scnt] = 0;
  167.         zmsk <<= 1;
  168.     }
  169.     lohkoja = 0;
  170.     for(blkcnt = 0; blkcnt < song.blocks; blkcnt++) {
  171.         if(FRead(fh,&scnt,1)) return(diskerr(fh,0));
  172.         if(AllocBlock(blkcnt,scnt)) return(diskerr(fh,"No memory."));
  173.         lohkoja++;
  174.         if(FRead(fh,&scnt,1)) return(diskerr(fh,0));
  175.         if(FRead(fh,(char *)(&convsz),2)) return(diskerr(fh,0));
  176.         if(!(conv = AllocMem(convsz+16,MEMF_PUBLIC|MEMF_CLEAR))) return(diskerr(fh,"No memory."));
  177.         if(scnt & M0F_LINEMSK00) *conv = 0L;
  178.         else if(scnt & M0F_LINEMSK0F) *conv = 0xffffffff;
  179.         else if(FRead(fh,(UBYTE *)conv,4)) return(diskerr(fh,0));
  180.         if(scnt & M0F_LINEMSK10) *(conv+1) = 0L;
  181.         else if(scnt & M0F_LINEMSK1F) *(conv+1) = 0xffffffff;
  182.         else if(FRead(fh,(UBYTE *)(conv + 1),4)) return(diskerr(fh,0));
  183.         if(scnt & M0F_FXMSK00) *(conv+2) = 0L;
  184.         else if(scnt & M0F_FXMSK0F) *(conv+2) = 0xffffffff;
  185.         else if(FRead(fh,(UBYTE *)(conv + 2),4)) return(diskerr(fh,0));
  186.         if(scnt & M0F_FXMSK10) *(conv+3) = 0L;
  187.         else if(scnt & M0F_FXMSK1F) *(conv+3) = 0xffffffff;
  188.         else if(FRead(fh,(UBYTE *)(conv + 3),4)) return(diskerr(fh,0));
  189.         if(FRead(fh,(UBYTE *)(conv + 4),convsz)) return(diskerr(fh,0));
  190.         UnpackBlock((UWORD)blkcnt,(UBYTE *)conv);
  191.         FreeMem(conv,convsz+16); conv = 0;
  192.     }
  193.     return(FALSE);
  194. }
  195.  
  196. static BOOL LoadAttachedInstrs(fh)
  197. BPTR fh;
  198. {
  199.     ULONG imsk,instrnum;
  200.     struct Soitin loaded;
  201.     if(FRead(fh,(char *)(&imsk),4)) return(diskerr(0,0));
  202.     instrnum = 0;
  203.     while(instrnum < 31) {
  204.         imsk <<= 1;    /* There's no instrument #0 */
  205.         instrnum++;
  206.         if(imsk & 0x80000000) {
  207.             if(FRead(fh,(char *)(&loaded),sizeof(struct Soitin)))
  208.                 return(diskerr(0,0));
  209.             if(NewInstrument(loaded.length,instrnum))
  210.                 return(diskerr(0,"Out of memory."));
  211.             samples[instrnum]->type = loaded.type;
  212.             if(FRead(fh,((char *)samples[instrnum]) +
  213.                 sizeof(struct Soitin),loaded.length))
  214.                 return(diskerr(0,0));
  215.         }
  216.     }
  217.     return(FALSE);
  218. }
  219.  
  220. static BOOL NewInstrument(size,num)
  221. ULONG size;
  222. UWORD num;
  223. {
  224.     if(samples[num]) {
  225.         FreeMem((void *)samples[num],samples[num]->length +
  226.         sizeof(struct Soitin));
  227.         samples[num] = NULL;
  228.     }
  229.     samples[num] = AllocMem(size + sizeof(struct Soitin),
  230.                 MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR);
  231.     if(!samples[num]) return(TRUE);
  232.     samples[num]->length = size;
  233.     return(FALSE);
  234. }
  235.  
  236. BOOL LoadSong(name)
  237. char *name;
  238. {
  239.     BPTR fh;
  240.     char tunnus[5];
  241.     StopPlayer();
  242.     FreeBlocksAndSamples();
  243.     if(!(fh = Open(name,MODE_OLDFILE))) return(diskerr(fh,0));
  244.     if(Read(fh,tunnus,4) != 4) return(diskerr(fh,"Not a song!"));
  245.     tunnus[4] = '\0';
  246.     Seek(fh,0,OFFSET_BEGINNING);
  247.     if(AllocBlock(0,4)) return(diskerr(fh,"No memory."));
  248.     lohkoja = 0;
  249.     if(!strcmp(tunnus,"MED\x03")) {
  250.         if(Load200Song(fh)) return(diskerr(fh,0));
  251.     } else    return(diskerr(fh,"Not a MEDV2.00 song!!"));
  252.     if(song.flags & 0x8) LoadAttachedInstrs(fh);
  253.     Close(fh);
  254.     SetTempo(tempo);
  255.     return(FALSE);
  256. }
  257.  
  258. static BOOL diskerr(fh,txt)
  259. BPTR fh;
  260. char *txt; /* some text about error (if 0, call IoErr()) */
  261. {
  262.     if(fh) Close(fh);
  263. /* Add code here, if you want error handling. */
  264.     return(TRUE);
  265. }
  266.  
  267. static void FreeBlock(num)
  268. UWORD num;
  269. {
  270.     if(blocks[num]) {
  271.         FreeMem(blocks[num],4 + blocks[num]->numtracks * 3 * 64);
  272.         blocks[num] = 0L;
  273.     }
  274. }
  275.  
  276. static BOOL AllocBlock(num,tracks) /* TRUE = error, FALSE = ok!! */
  277. UWORD num;
  278. UBYTE tracks;
  279. {
  280.     if(blocks[num]) {
  281.         if(blocks[num]->numtracks == tracks) return(FALSE);
  282.         FreeBlock(num);
  283.     }
  284.     if(!(blocks[num] = AllocMem(4 + (3 * 64) * tracks,MEMF_PUBLIC|
  285.         MEMF_CLEAR))) return(TRUE);
  286.     blocks[num]->numtracks = tracks;
  287.     return(FALSE);
  288. }
  289.  
  290. static void FreeAllBlocks()
  291. {
  292.     int cnt;
  293.     for(cnt = 0; cnt < 100; cnt++) FreeBlock(cnt);
  294. }
  295.  
  296. static void FreeSamples()
  297. {
  298.     UWORD scnt;
  299.     for(scnt = 1; scnt < 32; scnt++)
  300.         if(samples[scnt]) {
  301.             FreeMem((void *)samples[scnt],samples[scnt]->length
  302.                 + sizeof(struct Soitin));
  303.             samples[scnt] = NULL;
  304.         }
  305. }
  306.  
  307. void FreeBlocksAndSamples()
  308. {
  309.     FreeAllBlocks();
  310.     FreeSamples();
  311. }
  312.