home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "mloader.h"
- #include "munitrk.h"
-
-
- typedef struct MMD0 {
- ULONG id;
- ULONG modlen;
- ULONG MMD0songP; // struct MMD0song *song;
- UWORD psecnum; /* for the player routine, MMD2 only */
- UWORD pseq; /* " " " " */
- ULONG MMD0BlockPP; // struct MMD0Block **blockarr;
- ULONG reserved1;
- ULONG InstrHdrPP; // struct InstrHdr **smplarr;
- ULONG reserved2;
- ULONG MMD0expP; // struct MMD0exp *expdata;
- ULONG reserved3;
- UWORD pstate; // some data for the player routine */
- UWORD pblock;
- UWORD pline;
- UWORD pseqnum;
- WORD actplayline;
- UBYTE counter;
- UBYTE extra_songs; /* number of songs - 1 */
- } MMD0; /* length = 52 bytes */
-
-
- typedef struct MMD0sample {
- UWORD rep,replen; /* offs: 0(s), 2(s) */
- UBYTE midich; /* offs: 4(s) */
- UBYTE midipreset; /* offs: 5(s) */
- UBYTE svol; /* offs: 6(s) */
- BYTE strans; /* offs: 7(s) */
- } MMD0sample;
-
-
- typedef struct MMD0song {
- MMD0sample sample[63]; /* 63 * 8 bytes = 504 bytes */
- UWORD numblocks; /* offs: 504 */
- UWORD songlen; /* offs: 506 */
- UBYTE playseq[256]; /* offs: 508 */
- UWORD deftempo; /* offs: 764 */
- BYTE playtransp; /* offs: 766 */
- UBYTE flags; /* offs: 767 */
- UBYTE flags2; /* offs: 768 */
- UBYTE tempo2; /* offs: 769 */
- UBYTE trkvol[16]; /* offs: 770 */
- UBYTE mastervol; /* offs: 786 */
- UBYTE numsamples; /* offs: 787 */
- } MMD0song; /* length = 788 bytes */
-
-
- typedef struct MMD0NOTE{
- UBYTE a,b,c;
- } MMD0NOTE;
-
-
- typedef struct MMD1NOTE{
- UBYTE a,b,c,d;
- } MMD1NOTE;
-
-
- typedef struct InstrHdr {
- ULONG length;
- WORD type;
- /* Followed by actual data */
- } InstrHdr;
-
- static MMD0 *mh;
- static MMD0song *ms;
- static ULONG *ba;
-
- static MMD0NOTE *mmd0pat;
- static MMD1NOTE *mmd1pat;
-
- #define d0note(row,col) mmd0pat[(row*(UWORD)of.numchn)+col]
- #define d1note(row,col) mmd1pat[(row*(UWORD)of.numchn)+col]
-
- char MED_Version[]="MED";
-
-
- ULONG mlong(ULONG p)
- {
- return( ((p&0xff000000)>>24) |
- ((p&0x00ff0000)>>8) |
- ((p&0x0000ff00)<<8) |
- ((p&0x000000ff)<<24) );
- }
-
-
- UWORD mword(UWORD p)
- {
- #ifdef __BORLANDC__
- asm{
- mov ax,p
- xchg al,ah
- }
- return _AX;
- #else
- return( ((p&0xff00)>>8) |
- ((p&0x00ff)<<8) );
- #endif
- }
-
-
- #define clong(a) a=mlong(a)
- #define cword(a) a=mword(a)
-
-
-
-
- BOOL MED_Test(void)
- {
- char id[4];
- rewind(modfp);
- if(!fread(id,4,1,modfp)) return 0;
- if(!memcmp(id,"MMD0",4)) return 1;
- if(!memcmp(id,"MMD1",4)) return 1;
- return 0;
- }
-
-
- BOOL MED_Init(void)
- {
- mh=NULL;
- ms=NULL;
- ba=NULL; // blockarr
- mmd0pat=NULL;
- mmd1pat=NULL;
-
- if(!(mh=(MMD0 *)MyCalloc(1,sizeof(MMD0)))) return 0;
- if(!(ms=(MMD0song *)MyCalloc(1,sizeof(MMD0song)))) return 0;
- return 1;
- }
-
-
- void MED_Cleanup(void)
- {
- if(mh!=NULL) free(mh);
- if(ms!=NULL) free(ms);
- if(ba!=NULL) free(ba);
-
- if(mmd0pat!=NULL) free(mmd0pat);
- if(mmd1pat!=NULL) free(mmd1pat);
- }
-
-
-
- void MMD02Intel(MMD0 *p)
- {
- clong(p->id);
- clong(p->modlen);
- clong(p->MMD0songP); // struct MMD0song *song;
- cword(p->psecnum); // for the player routine, MMD2 only
- cword(p->pseq); // " " " "
- clong(p->MMD0BlockPP); // struct MMD0Block **blockarr;
- clong(p->reserved1);
- clong(p->InstrHdrPP); // struct InstrHdr **smplarr;
- clong(p->reserved2);
- clong(p->MMD0expP); // struct MMD0exp *expdata;
- clong(p->reserved3);
- cword(p->pstate); // some data for the player routine
- cword(p->pblock);
- cword(p->pline);
- cword(p->pseqnum);
- cword(p->actplayline);
- }
-
-
-
- void MMD0song2Intel(MMD0song *p)
- {
- int t;
- for(t=0;t<63;t++){
- cword(p->sample[t].rep);
- cword(p->sample[t].replen);
- }
- cword(p->numblocks); /* offs: 504 */
- cword(p->songlen); /* offs: 506 */
- cword(p->deftempo); /* offs: 764 */
- }
-
-
-
- void EffectCvt(UBYTE eff,UBYTE dat)
- {
- switch(eff){
-
- // 0x0 0x1 0x2 0x3 0x4 // PT effects
-
- case 0x5: // PT vibrato with speed/depth nibbles swapped
- UniPTEffect(0x4,(dat>>4) | ((dat&0xf)<<4) );
- break;
-
- case 0x6: // not used
- case 0x7: // not used
- case 0x8: // midi hold/decay
- break;
-
- case 0x9:
- if(dat<=0x20) UniPTEffect(0xf,dat);
- break;
-
- // 0xa 0xb 0xc all PT effects
-
- case 0xd: // same as PT volslide
- UniPTEffect(0xa,dat);
- break;
-
- case 0xe: // synth jmp - midi
- break;
-
- case 0xf:
-
- // F00 does patternbreak with med
-
- if(dat==0) UniPTEffect(0xd,0);
- else if(dat<=0xa) UniPTEffect(0xf,dat);
- else if(dat<0xf1) UniPTEffect(0xf,((UWORD)dat*125)/33);
- else if(dat==0xff) UniPTEffect(0xc,0); // stop note
- break;
-
- default: // all normal PT effects are handled here :)
- UniPTEffect(eff,dat);
- break;
- }
- }
-
-
-
- UBYTE *MED_Convert1(int col)
- {
- int t;
- UBYTE a,b,c,d,inst,note,eff,dat;
- MMD1NOTE *n;
-
- UniReset();
- for(t=0;t<64;t++){
-
- n=&d1note(t,col);
-
- a=n->a;
- b=n->b;
- c=n->c;
- d=n->d;
-
- note=a&0x7f;
- inst=b&0x3f;
- eff=c&0xf;
- dat=d;
-
- if(inst!=0){
- UniInstrument(inst-1);
- }
-
- if(note!=0){
- UniNote(note+23);
- }
-
- EffectCvt(eff,dat);
-
- UniNewline();
- }
- return UniDup();
- }
-
-
-
- UBYTE *MED_Convert0(int col)
- {
- int t;
- UBYTE a,b,c,inst,note,eff,dat;
- MMD0NOTE *n;
-
- UniReset();
- for(t=0;t<64;t++){
-
- n=&d0note(t,col);
-
- a=n->a;
- b=n->b;
- c=n->c;
-
- note=a&0x3f;
- a>>=6;
- a=((a&1)<<1)|(a>>1);
- inst=(b>>4)|(a<<4);
- eff=b&0xf;
- dat=c;
-
- if(inst!=0){
- UniInstrument(inst-1);
- }
-
- if(note!=0){
- UniNote(note+35);
- }
-
- EffectCvt(eff,dat);
- UniNewline();
- }
- return UniDup();
- }
-
-
-
- BOOL LoadMMD0Patterns(void)
- {
- int t,row,col;
- UWORD numtracks,numlines,maxlines=0,track=0;
-
- // first, scan patterns to see how many channels are used
-
- for(t=0;t<of.numpat;t++){
-
- fseek(modfp,mlong(ba[t]),SEEK_SET);
-
- numtracks=fgetc(modfp);
- numlines=fgetc(modfp);
-
- if(numtracks>of.numchn) of.numchn=numtracks;
- if(numlines>maxlines) maxlines=numlines;
- }
-
- of.numtrk=of.numpat*of.numchn;
-
- if(!AllocTracks()) return 0;
- if(!AllocPatterns()) return 0;
-
- if(!(mmd0pat=(MMD0NOTE *)MyCalloc(of.numchn*(maxlines+1),sizeof(MMD0NOTE)))) return 0;
-
- /* second read: no more mr. nice guy,
- really read and convert patterns */
-
- for(t=0;t<of.numpat;t++){
-
- fseek(modfp,mlong(ba[t]),SEEK_SET);
-
- numtracks=fgetc(modfp);
- numlines=fgetc(modfp);
-
- of.pattrows[t]=numlines+1;
-
- memset(mmd0pat,0,of.numchn*maxlines*sizeof(MMD0NOTE));
-
- for(row=0;row<=numlines;row++){
- fread(&d0note(row,0),sizeof(MMD0NOTE),numtracks,modfp);
- }
-
- for(col=0;col<of.numchn;col++){
- of.tracks[track]=MED_Convert0(col);
- track++;
- }
- }
-
- return 1;
- }
-
-
-
- BOOL LoadMMD1Patterns(void)
- {
- int t,row,col;
- UWORD numtracks,numlines,maxlines=0,track=0;
-
- // first, scan patterns to see how many channels are used
-
- for(t=0;t<of.numpat;t++){
-
- fseek(modfp,mlong(ba[t]),SEEK_SET);
-
- fread(&numtracks,sizeof(UWORD),1,modfp); cword(numtracks);
- fread(&numlines,sizeof(UWORD),1,modfp); cword(numlines);
- fseek(modfp,sizeof(ULONG),SEEK_CUR);
-
- if(numtracks>of.numchn) of.numchn=numtracks;
- if(numlines>maxlines) maxlines=numlines;
-
- if(numlines>255){
- puts("Can't load patterns > 256 rows");
- return 0;
- }
- }
-
- of.numtrk=of.numpat*of.numchn;
-
- if(!AllocTracks()) return 0;
- if(!AllocPatterns()) return 0;
-
- if(!(mmd1pat=MyCalloc(of.numchn*(maxlines+1),sizeof(MMD1NOTE)))) return 0;
-
- /* second read: no more mr. nice guy,
- really read and convert patterns */
-
- for(t=0;t<of.numpat;t++){
-
- fseek(modfp,mlong(ba[t]),SEEK_SET);
-
- fread(&numtracks,sizeof(UWORD),1,modfp); cword(numtracks);
- fread(&numlines,sizeof(UWORD),1,modfp); cword(numlines);
- fseek(modfp,sizeof(ULONG),SEEK_CUR);
-
- of.pattrows[t]=numlines;
-
- memset(mmd1pat,0,of.numchn*maxlines*sizeof(MMD1NOTE));
-
- for(row=0;row<=numlines;row++){
- fread(&d1note(row,0),sizeof(MMD1NOTE),numtracks,modfp);
- }
-
- for(col=0;col<of.numchn;col++){
- of.tracks[track]=MED_Convert1(col);
- track++;
- }
- }
-
- return 1;
- }
-
-
-
- BOOL MED_Load(void)
- {
- int t;
- ULONG sa[64];
- InstrHdr s;
- INSTRUMENT *d;
- SAMPLE *q;
-
- rewind(modfp);
-
- // try to read module header
-
- if(!fread(mh,sizeof(MMD0),1,modfp)){
- myerr=ERROR_LOADING_HEADER;
- return 0;
- }
-
- MMD02Intel(mh);
-
- // Seek to MMD0song struct
-
- fseek(modfp,mh->MMD0songP,SEEK_SET);
-
- if(!fread(ms,sizeof(MMD0song),1,modfp)){
- myerr=ERROR_LOADING_HEADER;
- return 0;
- }
-
- MMD0song2Intel(ms);
-
- // seek to samplepointer array
-
- fseek(modfp,mh->InstrHdrPP,SEEK_SET);
-
- // read sample array
-
- if(fread(sa,sizeof(ULONG),ms->numsamples,modfp)<ms->numsamples){
- myerr=ERROR_LOADING_HEADER;
- return 0;
- }
-
- // alloc blockpointer array
-
- if(!(ba=MyCalloc(ms->numblocks,sizeof(ULONG)))) return 0;
-
- // seek to blockpointer array
-
- fseek(modfp,mh->MMD0BlockPP,SEEK_SET);
-
- // read blockpointer array
-
- if(fread(ba,sizeof(ULONG),ms->numblocks,modfp)<ms->numblocks){
- myerr=ERROR_LOADING_HEADER;
- return 0;
- }
-
- // copy song positions
-
- for(t=0;t<ms->songlen;t++){
- of.positions[t]=ms->playseq[t];
- }
-
- of.initspeed=6;
- of.inittempo=((UWORD)ms->deftempo*125)/33;
- of.modtype=strdup("MED");
- of.numchn=0; // will be counted later
- of.numpat=ms->numblocks;
- of.numpos=ms->songlen;
- of.numins=ms->numsamples;
-
- if(!AllocInstruments()) return 0;
-
- d=of.instruments;
-
- for(t=0;t<of.numins;t++){
-
- d->numsmp=1;
- if(!AllocSamples(d)) return 0;
- q=d->samples;
-
- fseek(modfp,mlong(sa[t]),SEEK_SET);
-
- if(!fread(&s,sizeof(InstrHdr),1,modfp)){
- myerr=ERROR_LOADING_SAMPLEINFO;
- return 0;
- }
-
- d->insname=NULL;
- q->length=mlong(s.length);
- q->seekpos=ftell(modfp);
- q->loopstart=ms->sample[t].rep<<1;
- q->loopend=q->loopstart+(ms->sample[t].replen<<1);
- q->flags=SF_SIGNED;
- q->c2spd=8363;
- q->volume=64;
- if(ms->sample[t].replen>1) q->flags|=SF_LOOP;
-
- // don't load sample if length>='MMD0' hah.. hah.. very funny.. NOT!
-
- if(q->length>=0x4d4d4430) q->length=0;
-
- d++;
- }
-
- if(mh->id==0x4D4D4430){
- if(!LoadMMD0Patterns()) return 0;
- }
- else if(mh->id==0x4D4D4431){
- if(!LoadMMD1Patterns()) return 0;
- }
- else{
- puts("Can't load MMD2 yet");
- return 0;
- }
-
- return 1;
- }
-
-
- LOADER medload={
- NULL,
- "MED",
- "MED loader v0.1",
- MED_Init,
- MED_Test,
- MED_Load,
- MED_Cleanup
- };
-