206 lines
3.4 KiB
C++
206 lines
3.4 KiB
C++
|
#include "main.h"
|
||
|
#include "cvt.h"
|
||
|
|
||
|
#define _MThd 'dhTM'
|
||
|
#define _MTrk 'krTM'
|
||
|
|
||
|
#define tempo 0x188000
|
||
|
|
||
|
#define Q_MAX 128
|
||
|
|
||
|
struct HMI_cvt
|
||
|
{
|
||
|
public:
|
||
|
struct
|
||
|
{
|
||
|
DWORD tm;
|
||
|
BYTE ch,n;
|
||
|
} q_rel[Q_MAX];
|
||
|
|
||
|
void inline q_add(BYTE ch,BYTE nt,DWORD t)
|
||
|
{
|
||
|
UINT n=0;
|
||
|
while(q_rel[n].tm!=-1) n++;
|
||
|
q_rel[n].tm=t;
|
||
|
q_rel[n].ch=ch;
|
||
|
q_rel[n].n=nt;
|
||
|
}
|
||
|
grow_buf buf;
|
||
|
|
||
|
UINT DoTrack(const BYTE* t,UINT *_bw);
|
||
|
void DoQueue(DWORD ct,DWORD& tw,BYTE& _run);
|
||
|
bool run(MIDI_file * mf,const BYTE* _buf,DWORD sz);
|
||
|
};
|
||
|
|
||
|
|
||
|
#define FixHeader(H) {(H).fmt=rev16((H).fmt);(H).trax=rev16((H).trax);(H).dtx=rev16((H).dtx);}
|
||
|
|
||
|
void HMI_cvt::DoQueue(DWORD ct,DWORD& tw,BYTE& _run)
|
||
|
{
|
||
|
UINT n,mt,_n;
|
||
|
_t:
|
||
|
mt=-1;
|
||
|
for(n=0;n<Q_MAX;n++)
|
||
|
{
|
||
|
if (q_rel[n].tm<mt) {_n=n;mt=q_rel[n].tm;}
|
||
|
}
|
||
|
if (mt>ct) return;
|
||
|
gb_write_delta(buf,mt-tw);
|
||
|
tw=mt;
|
||
|
BYTE _e=q_rel[_n].ch|0x90;
|
||
|
if (_e!=_run) buf.write_byte(_run=_e);
|
||
|
buf.write_byte(q_rel[_n].n);
|
||
|
buf.write_byte(0);
|
||
|
q_rel[_n].tm=-1;
|
||
|
goto _t;
|
||
|
}
|
||
|
|
||
|
extern BYTE ff7loopstart[12];
|
||
|
|
||
|
UINT HMI_cvt::DoTrack(const BYTE* t,UINT *_bw)
|
||
|
{
|
||
|
{
|
||
|
UINT n;
|
||
|
for(n=0;n<Q_MAX;n++) q_rel[n].tm=-1;
|
||
|
}
|
||
|
DWORD pt=0;
|
||
|
DWORD ct=0,tw=0;
|
||
|
BYTE run=0;
|
||
|
BYTE _run=0;
|
||
|
DWORD bw_s=buf.get_size();
|
||
|
while(1)
|
||
|
{
|
||
|
{
|
||
|
unsigned int _d;
|
||
|
pt+=DecodeDelta(t+pt,&_d);
|
||
|
ct+=_d;
|
||
|
}
|
||
|
DoQueue(ct,tw,_run);
|
||
|
BYTE c=t[pt];
|
||
|
if (c==0xFF)
|
||
|
{
|
||
|
DoQueue(-2,tw,_run);
|
||
|
if (t[pt+1]==0x2f)
|
||
|
{
|
||
|
pt+=3;
|
||
|
buf.write_dword(0x002FFF00);
|
||
|
break;
|
||
|
}
|
||
|
return -1;
|
||
|
|
||
|
}
|
||
|
else if (c==0xF0)
|
||
|
{
|
||
|
gb_write_delta(buf,ct-tw);
|
||
|
tw=ct;
|
||
|
UINT _p=pt;
|
||
|
while(t[pt]!=0xF7) pt++;
|
||
|
pt++;
|
||
|
buf.write(t+_p,pt-_p);
|
||
|
}
|
||
|
else if (c==0xFE)
|
||
|
{
|
||
|
c=t[pt+1];
|
||
|
if (c==0x10)
|
||
|
{
|
||
|
pt+=t[pt+4]+9;
|
||
|
}
|
||
|
else if (c==0x14)
|
||
|
{
|
||
|
pt+=4;
|
||
|
gb_write_delta(buf,ct-tw);
|
||
|
tw=ct;
|
||
|
buf.write(ff7loopstart,12);
|
||
|
}
|
||
|
else if (c==0x15) pt+=8;
|
||
|
else return -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gb_write_delta(buf,ct-tw);
|
||
|
tw=ct;
|
||
|
if (c&0x80) {pt++;run=c;}
|
||
|
else c=run;
|
||
|
if (c!=_run) buf.write_byte(_run=c);
|
||
|
buf.write_byte(t[pt++]);
|
||
|
BYTE c1=c&0xF0;
|
||
|
if (c1!=0xC0 && c1!=0xD0) buf.write_byte(t[pt++]);
|
||
|
if (c1==0x90)
|
||
|
{
|
||
|
BYTE b=t[pt-2];
|
||
|
unsigned int _t;
|
||
|
pt+=DecodeDelta(t+pt,&_t);
|
||
|
q_add(c&0xF,b,_t+ct);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
(*_bw)+=buf.get_size()-bw_s;
|
||
|
return pt;
|
||
|
}
|
||
|
|
||
|
extern BYTE hmp_track0[19]; //hmp.cpp
|
||
|
|
||
|
bool HMI_cvt::run(MIDI_file* mf,const BYTE* _buf,DWORD sz)
|
||
|
{
|
||
|
const BYTE *ptr=_buf;
|
||
|
|
||
|
while(*(DWORD*)ptr!='CART')
|
||
|
{
|
||
|
ptr++;
|
||
|
if (ptr==_buf+sz) {return 0;}
|
||
|
}
|
||
|
|
||
|
buf.write(0,14);
|
||
|
|
||
|
ptr-=8;
|
||
|
UINT ntrax=1;
|
||
|
UINT nft=*(DWORD*)(_buf+0xE4);
|
||
|
|
||
|
buf.write(hmp_track0,sizeof(hmp_track0));
|
||
|
|
||
|
UINT n;
|
||
|
for(n=0;n<nft;n++)
|
||
|
{
|
||
|
if (ptr>_buf+sz) return 0;
|
||
|
UINT _b=0;
|
||
|
ntrax++;
|
||
|
buf.write_dword(_rv('MTrk'));
|
||
|
DWORD _s=buf.get_size();
|
||
|
buf.write(0,4);
|
||
|
{
|
||
|
const BYTE* p1=ptr+ptr[0x4B];
|
||
|
const BYTE* _p=p1+p1[1];
|
||
|
p1+=2;
|
||
|
while(_p[-1]==' ') _p--;
|
||
|
_b=(_p-p1)+4;
|
||
|
|
||
|
BYTE tmp[3]={0,0xFF,1};
|
||
|
buf.write(tmp,3);
|
||
|
gb_write_delta(buf,_p-p1);
|
||
|
buf.write(p1,_p-p1);
|
||
|
p1=_p;
|
||
|
}
|
||
|
ptr+=ptr[0x57];
|
||
|
{
|
||
|
DWORD d=DoTrack(ptr,&_b);
|
||
|
if (d==-1) return 0;
|
||
|
ptr+=d;
|
||
|
}
|
||
|
buf.write_dword_ptr(rev32(_b),_s);
|
||
|
}
|
||
|
buf.write_dword_ptr(_rv('MThd'),0);
|
||
|
buf.write_dword_ptr(_rv(6),4);
|
||
|
|
||
|
MIDIHEADER mhd={0x0100,rev16(ntrax),0xC000};
|
||
|
buf.write_ptr(&mhd,sizeof(mhd),8);
|
||
|
|
||
|
mf->size = buf.get_size();
|
||
|
mf->data = (BYTE*)buf.finish();
|
||
|
return !!mf->data;
|
||
|
}
|
||
|
|
||
|
bool load_hmi(MIDI_file* mf,const BYTE* _buf,size_t sz)
|
||
|
{
|
||
|
HMI_cvt c;
|
||
|
return c.run(mf,_buf,sz);
|
||
|
}
|