/* ======================================
     zmd2mid: making SMF track data
   ====================================== */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MThdINFO.h"
#include "VarLen.h"
#include "Putcode.h"
#include "zmscinit.h"
#include "structs.h"
#include "keyonoff.h"
#include "Panpot.h"
#include "bend.h"
#include "tempo.h"
#include "etc.h"
typedef struct {
	int bendstart;
	int bendend;
	int benddelay;
	int bendsign;
} BEND;

#ifdef _MSC_VER
#include <basetsd.h>
#endif
#include "config.h"
UBYTE *makeMTrk(UBYTE *zbuf,UBYTE *MTrk,DWORD *midc_,DWORD *zmdc_,
		DWORD bufs,DWORD trk,UBYTE trkch,DWORD next,DWORD init,
		DWORD looptime,DWORD R,DWORD MDDgate,
		DWORD fadespeed,DWORD fadedelay_,BYTE ABspc,DWORD runstatus,char *instname,
		DWORD *syncs,SYNCDAT **sync,DWORD syncmax,
		DWORD *tempos,TEMPODAT **tempo,DWORD tempomax,
		DWORD *debugs,DEBUGDAT **debug,DWORD debugmax,
		DWORD *loopst,DWORD *looped,BYTE opmtrk);
int geteig8(UBYTE *zbuf,WORD eig[]);
__int3264 all_noteoff(UBYTE *zbuf,UBYTE *harm,UBYTE *L0,DWORD *gate_old,DWORD trk);
void usech_init();
extern DWORD wavedatanum[],wavelooppoint[];
extern WORD *wavetable[];
extern BYTE wavelooptype[];
static BYTE usech[TRKMAX];
UBYTE *makeMTrk(UBYTE *zbuf,UBYTE *MTrk,DWORD *midc_,DWORD *zmdc_,
		DWORD bufs,DWORD trk,UBYTE trkch,DWORD next,DWORD init,
		DWORD looptime,DWORD R,DWORD MDDgate,
		DWORD fadespeed,DWORD fadedelay_,BYTE ABspc,DWORD runstatus,char *instname,
		DWORD *syncs,SYNCDAT **sync,DWORD syncmax,
		DWORD *tempos,TEMPODAT **tempo,DWORD tempomax,
		DWORD *debugs,DEBUGDAT **debug,DWORD debugmax,
		DWORD *loopst,DWORD *looped,BYTE opmtrk)
{
#ifdef DEBUG
	FILE *fp;
	char filename[30];
#endif
	UBYTE ID[4] = { 0x41, 0x10, 0x42, 0x12 };	/* default: GS */
	UBYTE NPRN[4] = { 0x63,0x62,0x06,0x26 };
	UBYTE *MTrk_ = MTrk;
	WORD vol=100,velo=127,velobak=127;
	DWORD zmdc= *zmdc_, i;
	DWORD count = 0;
	DWORD gate_old=MDDgate,total=MDDgate;
	WORD bend=0,extMOD_now=0,port_now=0,special_tie = 0;
	DWORD pan=64;
	DWORD *LOOP,*LOOPMAX,ldepth=0,ldepthmax=8,
		DOp=0,DOc=0,DC= *zmdc_,DCc=0,
		SEGNO=-1,SNc=0,CODA=-1;	/* ,CODAc=0; */
	__int3264 DOm = 0;
	DWORD ex_bytes = 0, ex_in_use = 0;
	UWORD step,gate;
	UBYTE note;
	BYTE TIEMODE=0,KEYOFF=0,AB=0,Ron=0;
	UBYTE ex_data[1024];		/* exclusive buffer: 1kb only, not dymanicaly allocat*/
	UBYTE tie=0,sw=0,harm[8+1+8+1],L0[8+1];			/* L0[]: notes that is voicing *0& */
	MODDAT  M = { 0,0,6,0,2,0 };					/* Modulation init */
	ARCCDAT A = { 11,-128,0x7F,0x7F,0,6,0,2,0 };	/* ARCC init */
	PORTDAT port;
	EIGHTH  E;
#ifdef __GCC__
	FADEDAT F = { 0,0,128,0,fadedelay_,0,0 };		/* fadein/out init */
#else
	FADEDAT F = { 0,0,128,0,0,0,0 };
#endif
	BEND Bbak;
#ifndef __GCC__
	F.delay = fadedelay_;
#endif
	trkch -= 9;	/*ID[0] = 0;*/					/* abs_trk -> MIDItrk, device ID initialize */
	for (i = 8; i >= 0; i--) {
		harm[i] = harm[9+i] = L0[i] = 0xFF;			/* chord,*0& init */
		E.eigMOD[i] = E.eigARC[i] = E.eigAFT[i] = 0;
	}
	*loopst = *looped = 0;
	port.sign = F.sign = 0;							/* Portament,FADEOUT init */
	E.eigMODm = E.eigARCm = E.eigAFTm = 0;			/* 1/8depth mode init */
	LOOP = (DWORD*)emalloc(sizeof(DWORD) * ldepthmax, "LOOP");
	LOOPMAX = (DWORD*)emalloc(sizeof(DWORD) * ldepthmax, "LOOPMAX");
	initCurrentNote();
	/* *(unsigned int*)MTrk = 0x4D54726B; */		/* == 'MTrk' */
	putDwordAlign(MTrk,0x4D54726B);					/* == 'MTrk' */
	MTrk += 4 + 4;
	if ((trkch < 0 && !opmtrk)|| trkch > 16) {
		if (trkch < -1) {
			ZTOMFormatMessage( stderr,"FM   ch %.2d skipped......",trkch + 1 + 9 );
		} else if (trkch == -1) {
			ZTOMFormatMessage( stderr,"ADPCMch 01 skipped......");
		} else {
			ZTOMFormatMessage( stderr,"ADPCMch %.2d skipped......",trkch - 14 );
		}
		zmdc = next;
	} else {
		if (opmtrk && trkch < 0) {
			trkch += 9;
			bendchg_init(1);
			MTrk += Putcode(MTrk,0,0xB0 + trkch,0x65,0x00);	/* bend range == 1oct */
			MTrk += Putcode(MTrk,0,0xB0 + trkch,0x64,0x00);
			MTrk += Putcode(MTrk,0,0xB0 + trkch,0x06,0x0C);
			ZTOMFormatMessage( stderr,"OPM  ch %.2d converting...",trkch + 1 );
		} else {
			bendchg_init(0);
			ZTOMFormatMessage( stderr,"MIDI ch %.2d converting...",trkch + 1 );
		}
		/* printf( "\x0dMIDI ch %.2d converting...\x1b[0K",trkch+1 ); */
		if (instname[0]) {
			/* printf( "\ninst:%s\n",instname); */
			/* MTrk[midc++] = 0x00; */
			MTrk += PutVarLen(MTrk,gate_old);
			gate_old = 0;
			*MTrk++ = 0xFF;
			*MTrk++ = 0x03;
			*MTrk++ = (UBYTE)strlen(instname);
			for (i = 0; i < (int)strlen(instname); i++) {
				*MTrk++ = (UBYTE)instname[i];
			}
		}
		status_init(runstatus == 1? USERUNSTAT : NOUSERUNSTAT );
		if (init >= 0) {
			if (usech[trkch]) {
				gate_old += zmscinit_delta(init);
			} else {
				MTrk += zmscinit(MTrk,init,&gate_old,trkch);
				usech[trkch] = 1;
			}
			total += zmscinit_delta(init);
		}
		ctrlchg_init();									/* bend,ARCC,modulation,vol init */
		bend_old_chg(0);
	}
	while (zmdc < next && zbuf[zmdc] != 0xFF) {
		UWORD uw;
		UBYTE ub;
		if (MTrk - MTrk_ > (bufs << 10) - 4096) {
			__int3264 d;
			bufs += 16;
			d = MTrk - MTrk_;
			MTrk_ = (UBYTE *)erealloc((void *)MTrk_,bufs * 1024, "MTrk_");
			MTrk = MTrk_ + d;
		}
		count++;
		/* printf("%X ",zbuf[zmdc]); */
		/* printf("zmdc:%x\n",zmdc); */
		switch (zbuf[zmdc++]) {
			DWORD i,val, val2;
			case 0x82:									/* FM音源ノイズoff(未サポート) */
				ZTOMFormatMessage(stderr,"[@O]");
				break;
			case 0x83:		/* 同期待ち(W) */
			case 0xAF:		/* 同期信号送信コマンド W */
				if (zbuf[zmdc - 1] == 0x83) {
					__int3264 d = MTrk - MTrk_;
					(*sync)[ *syncs ].midc   = (int)d;
					(*sync)[ *syncs ].trk    = trk;
					(*sync)[ *syncs ].offset = gate_old;
					gate_old = 0;
				} else {
					(*sync)[ *syncs ].midc   = -trk - 1;
					(*sync)[ *syncs ].trk    = zbuf[zmdc++];	/* - 9; */
					(*sync)[ *syncs ].offset = -1;
				}
				(*sync)[ *syncs   ].count  = count;
				(*sync)[(*syncs)++].total  = total;
				if (*syncs >= syncmax) {
					syncmax *= 2;
					*sync = (SYNCDAT *)erealloc((void *)*sync,sizeof(SYNCDAT) * syncmax, "sync");
				}
				break;
			case 0x84:		/* 臨時ベロシティー復元 */
				velo = velobak;
				break;
			case 0x90:		/* @t */
			case 0x91:		/* t  */
				(*tempo)[ *tempos   ].value     = zbuf[zmdc] * 0x100 + zbuf[zmdc + 1];
				(*tempo)[ *tempos   ].attribute = (zbuf[zmdc - 1] == 0x90)? 2 : 0;
				/* no break */
			case 0x92:		/* @t+ */
			case 0x93:		/* @t- */
			case 0x94:		/* t+ */
			case 0x95:		/* t- */
				if (zbuf[zmdc - 1] >= 0x92) {
					const DWORD i = zbuf[zmdc] * 0x100 + zbuf[zmdc + 1];
					(*tempo)[ *tempos   ].value     = (zbuf[zmdc - 1] & 1)? -i : i;
					(*tempo)[ *tempos   ].attribute = (zbuf[zmdc - 1] < 0x94)? 3 : 1;
				}
				(*tempo)[ *tempos   ].total     = total;
				(*tempo)[ *tempos   ].count     = count;
				(*tempo)[(*tempos)++].trk       = trk;
				/* MTrk += tempochg(MTrk,&gate_old,i); */
				/* (*tempo)[(*tempos)++].midc      = MTrk - MTrk_ - 3; */
				zmdc += 2;
				if (*tempos >= tempomax) {
					tempomax *= 2;
					*tempo = (TEMPODAT *)erealloc((void *)*tempo,sizeof(TEMPODAT) * tempomax, "tempo");
				}
				break;
			case 0x96:		/* 相対ピッチベンドUP(ZMDonly) */
			case 0x97:		/* 相対ピッチベンドDOWN(ZMDonly) */
				uw = zbuf[zmdc] * 0x100 + zbuf[zmdc + 1];
				if (zbuf[zmdc - 1] == 0x96) {
					bend += uw;
				} else {
					bend -= uw;
				}
				zmdc += 2;
				MTrk += bendchg(MTrk,&gate_old,bend,port_now,special_tie,extMOD_now,trkch);
				break;
			case 0x98:			/* モジュレーション選択波形(S) */
				if (zbuf[zmdc] != 0xFF) {
					M.Mtype = zbuf[zmdc];
					if (!M.Mmode) M.Mmode = 1;
				}
				if (zbuf[zmdc + 1] != 0xFF) {
					A.ARCCtype = zbuf[zmdc + 1];
					if (!A.ARCCmode) A.ARCCmode = 1;
				}
				zmdc += 2;
				if ( (M.Mtype > 31) || ((M.Mtype > 3) && (M.Mtype < 8)) ) {
#ifndef ENGLISH
					ZTOMFormatMessage(stderr,"[未定義の波形番号です(三角波にします)]");
#else
					ZTOMFormatMessage(stderr,"[undefined wave#!(change to saw)]");
#endif
					M.Mtype = 2;
				}
				if ( (A.ARCCtype > 31) || ((A.ARCCtype > 3) && (A.ARCCtype < 8)) ) {
#ifndef ENGLISH
					ZTOMFormatMessage(stderr,"[未定義の波形番号です(三角波にします)]");
#else
					ZTOMFormatMessage(stderr,"[undefined wave#!(change to saw)]");
#endif
					A.ARCCtype = 2;
				}
				break;
			case 0x99:			/* MIDIピッチモジュレーションモード選択(M) */
				if (zbuf[zmdc] != 0xFF) M.Mmode = zbuf[zmdc];
				if (M.Mmode) E.eigMODm = 0;
				if (zbuf[zmdc + 1] != 0xFF) A.ARCCmode = zbuf[zmdc + 1];
				if (A.ARCCmode) E.eigARCm = 0;
				zmdc += 2;
				break;
			case 0x9A:		/* ARCCコントロールチェンジ番号登録(@C) */
				if ((ub = zbuf[zmdc]  )   != 0xFF) A.ARCCc=ub;
				if ((ub = zbuf[zmdc + 1]) != 0xFF) A.ARCCr=ub;
				if ((ub = zbuf[zmdc + 2]) != 0xFF) A.ARCCn=ub;
				zmdc += 3;
				/* E.eigARCm = 1; */
				sw |= 2;		/* sw on */
				A.ARCCv = -128;		/* add v1.57 */
				break;
			case 0x9B:		/* ADPCM再生 y2,n(未サポート) */
				zmdc += 2;
				ZTOMFormatMessage(stderr,"[y2.n]");
				break;
			case 0x9C:		/* MOD波形同期・非同期 (H) */
				if ((ub = zbuf[zmdc]    ) != 0xFF) M.Msync = ub;
				if ((ub = zbuf[zmdc + 1]) != 0xFF) A.ARCCsync = ub;
				zmdc += 2;
				break;
			case 0xA0:		/* 音色変更 */
				MTrk += Putcode2(MTrk,gate_old,0xC0 + trkch,zbuf[zmdc++] - 1);
				gate_old = 0;
				break;
			case 0xA1:		/* MXDRV風音色変更 */
				zmdc++;
#ifndef ENGLISH
				ZTOMFormatMessage(stderr, "[MXDRV風音色切替]" );
#else
				ZTOMFormatMessage(stderr, "[MXDRV-like toneSet]" );
#endif
				break;
			case 0xA2:		/* ADPCM周波数変更 */
			case 0xA9:		/* ADPCM周波数変更 */
			case 0xB7:		/* ADPCM PAN */
			case 0xB8:		/* PCM効果音モード */
				zmdc++;
				ZTOMFormatMessage(stderr, "[ADPCM]" );
				break;
			case 0xA3:		/* チャンネルアサイン変更(N,@N) */
				trkch = zbuf[zmdc++] - 9;
				break;
			case 0xA4:		/* ARCC登録 @C oldVer */
				if ((ub = zbuf[zmdc++]) != 0xFF) A.ARCCc = ub;
				A.ARCCr = A.ARCCn= 0;
				E.eigARCm = 1;
				break;
			case 0xA5:		/* FM音源ノイズ(y15,n)(未サポート) */
				zmdc++;
				ZTOMFormatMessage(stderr, "[y15,n]" );
				break;
			case 0xA6:		/* フェードイン/アウト */
			case 0xCC:		/* 全トラックフェードイン・アウト */
				i = (BYTE)zbuf[zmdc++];
				if (zbuf[zmdc - 2] == 0xA6) {
					F.target = 0;	/* 通常の1trk fadein/out */
					F.volcor = (i < 0)? -1 : 128;
				} else {		/* ↓MT32 || GS */
					F.target = ( ID[0] == 0x41 && ID[2] == 0x16 )? 1 : 2;
					F.volcor = (i < 0)? -1 : ((F.target == 1)? 100 : 128);
				}
				if (i < 0) {
					F.sign = 1;
				} else if (!i) {
					F.sign = 0;
				} else {
					F.sign = -1;
				}
				F.delta = 0;	/* MAXi / 128 == 0 */
				/* F.correct=abs(i%128)*256/128; */
				F.correct = abs(i) * 2;
				F.cor = 0;
				break;
			case 0xA7:		/* ダンパーペダル:ホールド @D */
				ub = zbuf[zmdc++];
				if (ub) ub = 0x7F;
				MTrk += Putcode(MTrk,gate_old,0xB0 + trkch,0x40,ub);
				gate_old = 0;
				break;
			case 0xA8:		/* ベンドレンジ変更 */
				MTrk += bendrange(MTrk,&gate_old,zbuf[zmdc++],trkch);
				break;
			case 0xAA:		/* 相対ボリュームUP */
			case 0xAB:		/* 相対ボリュームDOWN */
			case 0xB6:		/* ボリューム (V) */
				switch (zbuf[zmdc - 1]) {
					case 0xAA:
						vol += zbuf[zmdc++];
						break;
					case 0xAB:
						vol -= zbuf[zmdc++];
						break;
					case 0xB6:
						vol = 127 - zbuf[zmdc++];
						break;
				}
				if (vol > 127) {
					ZTOMFormatMessage(stderr, "[V>127]");
					vol = 127;
				} else if (vol < 0) {
					vol = 0;
				}
				if (!F.sign || F.target) {
					F.volcor = 128;
					F.cor = 0;
				} else {
					vol = (vol * F.volcor) >> 7;
					if (vol > 127) {
						vol = 127;
					} else if (vol < 0) {
						vol = 0;
					}
				}
				MTrk += volchg(MTrk,&gate_old,vol,trkch);
				break;
			case 0xAC:		/* キーオフなしモード @R */
				Ron = zbuf[zmdc++];
				if (R < 0) {
					KEYOFF = Ron;
				} else {
					ZTOMFormatMessage(stderr,"[@R]");
				}
				break;
			case 0xAD:		/* 絶対音長０による強制発音 */
				/* goto absolute0_chord; */	/* とーとーやってしまった... */
				MTrk += Putcode(MTrk,gate_old,0x90 + trkch,zbuf[zmdc++],(UBYTE)velo);
				gate_old = 0;
				break;
			case 0xAE:		/* ARCC/拡張ARCC @A */
				A.ARCCv = zbuf[zmdc++];
				arcc_old_chg(A.ARCCr,tie);
				E.eigARCm = 0;
				sw |= 2;		/* スイッチオン */
				break;
			case 0xB0:		/* panpot p0 */
				MTrk += volchg(MTrk,&gate_old,0,trkch);	/* vol=0; */
				break;
			case 0xB1:		/* panpot p1 */
			case 0xB2:		/* panpot p2 */
			case 0xB3:		/* panpot p3 */
			case 0xB4:		/* panpot @Pn */
				switch (zbuf[zmdc - 1]) {
					case 0xB1:
						pan = 0;
						break;
					case 0xB2:
						pan = 127;
						break;
					case 0xB3:
						pan = 64;
						break;
					case 0xB4:
						pan = zbuf[zmdc++];
						break;
				}
				MTrk += panpot(MTrk,&gate_old,pan,trkch);
				break;
			case 0xB5:		/* Ym,n＝コントロールチェンジ */
				MTrk += Putcode(MTrk,gate_old,0xB0 + trkch,zbuf[zmdc],zbuf[zmdc + 1]);
				zmdc += 2;
				gate_old = 0;
				break;
			case 0xB9:		/* ベロシティー */
				velo = zbuf[zmdc++];
				if (velo > 127) {
					velo = 127;
					ZTOMFormatMessage(stderr,"[U>127]");
				} else if (velo < 0)   {
					velo = 0;
					ZTOMFormatMessage(stderr,"[U<0]");
				}
				velobak = velo;
				break;
			case 0xBA:		/* スイッチ (=) */
				zmdc += 8;
#ifndef ENGLISH
				ZTOMFormatMessage(stderr, "現在スイッチ関係(旧版)は未サポート。\n" );
#else
				ZTOMFormatMessage(stderr, "old-style SWITCH command isn't supported.\n" );
#endif
				break;
			case 0xBB:		/* ピッチモジュレーションスイッチ @M */
				if (!zbuf[zmdc++]) {
					/* if (tie == 1 && M.Mdepth != 0) { */	/* TIE中なら即変更 */
					MTrk += MODchg(MTrk,&gate_old,0,trkch);
					M.Mdepth = E.eigMODm = 0;
					sw &= 0xFE;		/* スイッチオフ */
				} else {
					sw |= 1;		/* スイッチオン */
				}
				/* mod_old_chg(M.Mdepth,tie); */
				mod_old_chg(tie);
				extMOD_now = 0;
				break;
			case 0xBC:		/* ARCCスイッチ (@A) */
				if (!zbuf[zmdc++]) {
					MTrk += ARCCchg(MTrk,&gate_old,A.ARCCc,A.ARCCr,trkch);
					A.ARCCv = A.ARCCr;
					E.eigARCm = 0;
					sw &= 0xFD;		/* スイッチオフ */
				} else {
					sw |= 2;		/* スイッチオン */
				}
				arcc_old_chg(A.ARCCr,tie);
				break;
			case 0xBD:		/* オートベンドスイッチ @B */
				if (!zbuf[zmdc++]) {
					if (!tie) {		/* if not tie */
						bend = port_now = 0;
						MTrk += bendchg(MTrk,&gate_old,bend,port_now,special_tie,extMOD_now,trkch);
						/* gate_old=0; */
					}
					AB = port.sign = 0;	/* no use bend flag */
					sw &= 0xFB;			/* スイッチオフ */
				} else {
					sw |= 4;			/* スイッチオン */
				}
				break;
			case 0xBE:		/* アフタータッチシーケンス(@Z) */
				if (zbuf[zmdc++]) {
/* この行は不要！？ */			/* midc+=Putcode2(&MTrk[midc],gate_old,0xD0+trkch,velo); */
					/* gate_old=0; */
					E.eigAFTm = 0;
					sw &= 0xF7;			/* スイッチオフ */
				} else {
					sw |= 8;			/* スイッチオン */
				}
				break;
			case 0xBF:		/* 強制キーオフ ` */
				MTrk += all_noteoff(MTrk,harm,L0,&gate_old,trkch);
				break;
			case 0xC0:		/* []コマンド系 */
				ub = zbuf[zmdc++];
				switch  (ub) {
					case 0:		/* reserved */
					case 1:
					case 2:
						ZTOMFormatMessage(stderr,"[RESERVED]");
						break;
					case 3:		/* [d.c.] */
						if (!DCc) {
							DCc = 1;	/* flag on */
							ZTOMFormatMessage(stderr,"[d.c.]");
							if (CODA == -1) {
								CODA = zmdc;
							}
							zmdc = DC;	/* 始めに戻る */
						}
						break;
					case 4:		/* [segno],[$] */
						ZTOMFormatMessage(stderr,"[$]");
						SEGNO = zmdc;
						break;
					case 5:		/* [d.s.] */
						ZTOMFormatMessage(stderr,"[d.s.]");
						if (!SNc) {
							SNc = 1;
							if (CODA == -1) CODA = zmdc;
							if (SEGNO >= 0) zmdc = SEGNO;
							/* else fprintf(stderr, "SEGNOはどこ？\n" ); */
						}
						break;
					case 6:		/* [coda] */
						ZTOMFormatMessage(stderr,"[coda]");
						CODA = zmdc;
						break;
					case 7:		/* [tocoda],[*] */
						ZTOMFormatMessage(stderr,"[tocoda]");
						/* if (!CODAc) { */
							/* CODAc = 1; */
							if (CODA >= 0) zmdc = CODA;
							/* else fprintf(stderr,"codaはどこ？\n"); */
						/* } */
						break;
					case 8:		/* [fine],[^] */
						ZTOMFormatMessage(stderr,"[fine]");
						if (DCc || SNc) {
							zmdc = next;
						}
						break;
					case 9:		/* [do] */
						ZTOMFormatMessage(stderr,"[do]");
						DOp     = zmdc;	/* 場所を覚える */
						*loopst = total;
						if (looptime == 0) {	/* でっちあげループイベント */
												/* 個人的にしか使わないでね */
#ifdef NOXMIDI
							MTrk += PutVarLen(MTrk, gate_old);
							*MTrk++ = 0xFF;
							*MTrk++ = 0x7F;
							*MTrk++ = 0x04;
							*MTrk++ = 0x89;
							*MTrk++ = 0x42;
							*MTrk++ = 0x10;
							*MTrk++ = 0x00;
#elif defined (XMIDI)
						/*  XMIDI LOOP EVENT */
							MTrk += PutVarLen(MTrk, gate_old);
							*MTrk++ = 0xFF;
							*MTrk++ = 0x7F;
							*MTrk++ = 0x02;
							*MTrk++ = 'X';
							*MTrk++ = 0x00;
#else
							/* CC121によるループイベント (RPGツクール)*/
							MTrk += Putcode(MTrk, gate_old, 0xB0 + trkch, 111, 0);
#endif
							DOm = MTrk - MTrk_;	/* 場所を覚える */
							status_init(runstatus == 1? USERUNSTAT : NOUSERUNSTAT );
							gate_old = 0;
						}
						break;
					case 10:	/* [loop] */
						if (DOp == 0) {
#ifndef ENGLISH
							ZTOMFormatMessage(stderr,"[do]がないのに[loop]があります。\n");
#else
							ZTOMFormatMessage(stderr,"[loop] is there, but [DO] isn't.\n");
#endif
						} else {
							if (DOc==0) {
								*looped = total;
							}
							if ((++DOc) >= looptime) {
								ZTOMFormatMessage(stderr,"[loop]");
								if (looptime == 0) {	/* 個人的にしか使わないでね */
#ifdef NOXMIDI
									MTrk += PutVarLen(MTrk, gate_old);
									*MTrk++ = 0xFF;
									*MTrk++ = 0x7F;
									*MTrk++ = 0x07;
									*MTrk++ = 0x89;
									*MTrk++ = 0x42;
									*MTrk++ = 0x11;
									MTrk += 4;
									val = MTrk - MTrk_ - DOm;
									for (i = 3; i >= 0; i--) {
										*MTrk-- = val & 0xFF;
										val >>= 8;
									}
									MTrk += 4;
#elif defined (XMIDI)
									/*  XMIDI LOOP EVENT */
									MTrk += PutVarLen(MTrk, gate_old);
									*MTrk++ = 0xFF;
									*MTrk++ = 0x7F;
									*MTrk++ = 0x02;
									*MTrk++ = 'X';
									*MTrk++ = 0x01;
#else
								/* CC121によるループイベントを使う */
								/* → ループ終端での処理は無し */
#endif
									status_init(runstatus == 1? USERUNSTAT : NOUSERUNSTAT );
									gate_old = 0;
								}
								if (fadespeed) {
									int i = fadespeed;
									F.sign = -1;
									F.delta = F.cor= 0;
									F.correct = i * 2;
									F.volcor  = 128;
									DOc = -1024;	/* 危険 */
									zmdc = DOp;
									break;
								}
								/* break; */	/* zmdc=next; */
							} else {
								zmdc = DOp;	/* [do]に戻る */
								/* break; */
							}
						}
						break;
					case 11:	/* [!] */
					case 12:	/* [@] */
						MTrk += PutVarLen(MTrk,gate_old);
						gate_old = 0;
						*MTrk++ = 0xFF;
						*MTrk++ = 0x07;		/* Que point */
						*MTrk++ = 0x03;
						*MTrk++ = '[';
						if (ub == 11) {
							ZTOMFormatMessage(stderr,"[!]");
							*MTrk++ = '!';
						} else {
							ZTOMFormatMessage(stderr,"[@]");
							*MTrk++ = '@';
						}
						*MTrk++ = ']';
						status_init(runstatus == 1? USERUNSTAT : NOUSERUNSTAT );
						(*debug)[ *debugs   ].mode      = ub - 10;		/* 1:[!] 2:[@] */
						(*debug)[ *debugs   ].total     = total;
						/* (*debug)[ *debugs   ].count     = count; */
						(*debug)[(*debugs)++].trk       = trk;
						/* (*tempo)[(*tempos)++].midc      = MTrk - MTrk_ - 3; */
						if (*debugs >= debugmax) {
/* fprintf(stderr,"##"); */
							debugmax *= 2;
							*debug = (DEBUGDAT *)erealloc((void *)*debug,sizeof(DEBUGDAT) * debugmax, "debug");
						}
						break;
					default:
						ZTOMFormatMessage(stderr, "[]" );
				}
				break;
			case 0xC1:		/* リピート開始 |: */
				/* fprintf(stderr,"|:"); */
				if (zbuf[zmdc++] != 0xCF) {
#ifndef ENGLISH
					ZTOMFormatMessage(stderr," |:コマンドの構造が異常。\n");
#else
					ZTOMFormatMessage(stderr," illegal '|:'.\n");
#endif
					zmdc++;
				} else {
#ifdef AAA
					if (ldepth >= 7) {
#ifndef ENGLISH
						ZTOMFormatMessage(stderr," |:〜:|のネストが深すぎます。\n" );
						ZTOMFormatMessage(stderr," (これが表示されるはずはないのですが..)\n");
#else
						ZTOMFormatMessage(stderr," Too deep the |: .. :| 's nest is.\n");
#endif	/* ENGLISH */
					} else {
#endif	/* AAA */
						LOOP[ldepth]      = 0;
						LOOPMAX[ldepth++] = zbuf[zmdc++];
						if (ldepth >= ldepthmax) {
							ldepthmax += 8;
							LOOP = (DWORD*)erealloc(LOOP, sizeof(DWORD) * ldepthmax, "LOOP");
							LOOPMAX = (DWORD*)erealloc(LOOPMAX, sizeof(DWORD) * ldepthmax, "LOOPMAX");
						}
#ifdef AAA
					}
#endif
				}
				break;
			case 0xC2:		/* リピート終端 :| */
				if (ldepth <= 0) {
#ifndef ENGLISH
					ZTOMFormatMessage(stderr, "':|'の数が多すぎます。\n" );
					ZTOMFormatMessage(stderr, " (これが表示されるはずはないのですが..)\n");
#else
					ZTOMFormatMessage(stderr, " Too many :| .\n");
#endif
					zmdc += 2;
				} else {
					val = zbuf[zmdc] * 0x100 + zbuf[zmdc + 1];
					zmdc += 2;
					if ( (++LOOP[ldepth - 1]) < LOOPMAX[ldepth - 1] ) {	/* まだループする */
				/* fprintf(stderr, "@"); */
						zmdc -= val;
						if ( zbuf[zmdc++] != 0xCF ) {
#ifndef ENGLISH
							ZTOMFormatMessage(stderr," |:コマンドの構造が異常。\n");
#else
							ZTOMFormatMessage(stderr," illegal '|:'.\n");
#endif
						}
						zmdc++;
					} else {			/* ループ終了 */
				/* fprintf(stderr,"@:|"); */
						ldepth--;
					}
				}
				break;
			case 0xC3:		/* リピートskip |n */
				if (ldepth <= 0) {
#ifndef ENGLISH
					ZTOMFormatMessage(stderr, "'|n'の位置がおかしい。\n" );
					ZTOMFormatMessage(stderr, " (これが表示されるはずはないのですが..)\n");
#else
					ZTOMFormatMessage(stderr,"illegal |n.\n");
#endif
					zmdc += 2;
				} else {
					const DWORD val2 = zbuf[zmdc];
					const DWORD val  = zbuf[zmdc + 1] * 0x100 + zbuf[zmdc + 2];
					zmdc += 3;
					if ( (LOOP[ldepth - 1] + 1) == val2 ) {	/* 指定回 */
						/* fprintf(stderr,"|%d ",val2); */
						break;
					} else {
						zmdc += val;			/* skip */
					}
				}
				break;
			case 0xC4:		/* リピートskip | */
				if (ldepth <= 0) {
				/*
					fprintf(stderr, "'|'の位置がおかしい。\n" );
					fprintf(stderr, " (これが表示されるはずはないのですが..)\n");
				*/
					zmdc += 2;
				} else {
					const DWORD val = zbuf[zmdc] * 0x100 + zbuf[zmdc + 1];
					zmdc += 2;
					if ( (LOOP[ldepth - 1] + 1) == LOOPMAX[ldepth - 1] ) {
						/* 最後のループ */
				/* fprintf(stderr,"| :|"); */
						zmdc += val;
						ldepth--;
					}
				}
				break;
			case 0xC5:		/* MIDIの タイ/スラー mode指定("n,@J) */
				TIEMODE = zbuf[zmdc++];
				if (!TIEMODE) {
					special_tie = 0;
				}
				break;
			case 0xC7:		/* 特殊コマンド制御スイッチ (=) */
				sw = zbuf[zmdc++];
				if (sw & 4) {
					port.delta  = Bbak.bendstart;
					port.correct= Bbak.bendend;
					port.delay  = Bbak.benddelay;
					port.sign   = Bbak.bendsign;
				}
				break;
			case 0xC8:		/* 相対パンポットup */
				pan += zbuf[zmdc++];
				if (pan > 127) {
					pan = 127;
				}
				MTrk += panpot(MTrk,&gate_old,pan,trkch);
				break;
			case 0xC9:		/* 相対パンポットdown */
				pan -= zbuf[zmdc++];
				if (pan < 0) {
					pan = 0;
				}
				MTrk += panpot(MTrk,&gate_old,pan,trkch);
				break;
			case 0xCA:		/* 相対ベロシティーUP */
				velo += zbuf[zmdc++];
				if (velo > 127) {
					velo = 127;
					ZTOMFormatMessage(stderr,"[U>127]");
				}
				velobak = velo;
				break;
			case 0xCB:		/* 相対ベロシティーDOWN */
				velo -= zbuf[zmdc++];
				if (velo < 0)   {
					velo = 0;
					ZTOMFormatMessage(stderr,"[U<0]");
				}
				velobak = velo;
				break;
			case 0xCD:		/* 絶対音長０による和音 *0& */
/* absolute0_chord: */
				if (L0[0] == 0xFF && harm[0] == 0xFF) {
/*
					MTrk += bendreset(MTrk,&bend,port.sign,&port_now,
								&special_tie,&extMOD_now,&gate_old,trkch);
*/
					MTrk += bendchg(MTrk,&gate_old,bend,port_now,
								special_tie,extMOD_now,trkch);
				}
				{
					DWORD flg = 1;
					const UBYTE val = zbuf[zmdc++];
					int i = 0;
					while (L0[i] != 0xFF) {			/* add 1.49.3 */
						if (L0[i++] == val) {
							flg = 0;
							break;
						}
					}
					if (flg) {
						for (i = 0; i < 8; i++) {
							if (L0[i] == 0xFF) {
								L0[i] = val;
								L0[i+1] = 0xFF;		/* flag set */
								/* fprintf(stderr, "o%x ",L0[i]); */
								break;
							}
						}
						MTrk += Putcode(MTrk,gate_old,0x90 + trkch,val,(UBYTE)velo);
						gate_old = 0;
					}
				}
				break;
			case 0xCE:		/* 強制再演奏コマンド */
				zmdc++;
				ZTOMFormatMessage(stderr, "[J]" );
				break;
			case 0xCF:		/* リピートコマンドの２バイト目 */
#ifndef ENGLISH
				ZTOMFormatMessage(stderr, "リピートコマンドの2バイト目($CF)がなぜ？\n" );
#else
				ZTOMFormatMessage(stderr,"unexpected $CF.\n");
#endif
				/* exit(1); */
				break;
			case 0xD0:		/* ウェイト(@W) */
				gate = step = zbuf[zmdc];
				total += step;
				R_w_chg('w');
				if (step) {
					count = 0;
				}
				if (abs(port.sign) != 2) {
					port.delta = 0;
				}
				MTrk += keyonoff2(MTrk,&tie,harm,step,gate,
					&gate_old,velo,trkch,0,
					&L0[0],KEYOFF,M,port,&bend,&port_now,&special_tie,
					&extMOD_now,
					A,E,&AB,sw,TIEMODE,
					vol,&F,ABspc,ID,(BYTE)runstatus);
				zmdc += 2;
				break;
			case 0xD1:		/* キートランスポーズデチューン(ベンド)@B,@K */
				bend = (WORD)(zbuf[zmdc + 2] * 0x100 + zbuf[zmdc + 3]);
				port_now = 0;
				zmdc += 4;
				MTrk += bendchg(MTrk,&gate_old,bend,port_now,special_tie,extMOD_now,trkch);
				/* bend_old_chg(bend); */ /* del 1.38 */
				port.sign = 0;
				sw &= 0xFB;		/* スイッチオフ */
				break;
			case 0xD2:		/* NRPN設定 (@Y) */
				for (i = 0; i < 4; i++) {
					UBYTE val;
					if ((val = zbuf[zmdc++]) != 0xFF) {
						MTrk += Putcode(MTrk,gate_old,0xB0 + trkch,NPRN[i],val);
						gate_old = 0;
					}
				}
				break;
			case 0xD3:		/* バリエーション・バンク変更 (I) */
				if ((ub = zbuf[zmdc    ]) != 0xFF) {
					MTrk += Putcode(MTrk,gate_old,0xB0 + trkch,0x00,ub);
					gate_old = 0;
				}
				if ((ub = zbuf[zmdc + 1]) != 0xFF) {
					MTrk += Putcode(MTrk,gate_old,0xB0 + trkch,0x20,ub);
					gate_old = 0;
				}
				zmdc += 2;
				break;
			case 0xD5:		/* ワークエリア直接書き換え (?) */
			case 0xD7:		/* ワーク書き換え　相対UP (?) */
			case 0xD8:		/* ワーク書き換え　相対DOWN (?) */
				zmdc += 2;
				ZTOMFormatMessage(stderr,"[?m,n]");
				break;
			case 0xD6:		/* モジュレーションスピード設定 (@S) */
				uw = zbuf[zmdc    ] * 0x100 + zbuf[zmdc + 1];
				if (uw) M.Mspeed = uw;
				uw = zbuf[zmdc + 2] * 0x100 + zbuf[zmdc + 3];
				zmdc += 4;
				if (uw) A.ARCCspeed = uw;
						/* ここだけ省略＝０とは... */
				break;
			case 0xD9:		/* 臨時ベロシティー 即値 */
				velo = zbuf[zmdc++];
				break;
			case 0xDA:		/* 臨時ベロシティー 相対UP */
				velo = velobak + zbuf[zmdc++];
				if (velo > 127) {
					velo = 127;
					ZTOMFormatMessage(stderr,"[U>127]");
				}
				break;
			case 0xDB:		/* 臨時ベロシティー 相対DONW */
				velo = velobak - zbuf[zmdc++];
				if (velo < 0)   {
					velo = 0;
					ZTOMFormatMessage(stderr,"[U<0]");
				}
				break;
			case 0xE0:		/* ポルタメント */
			case 0xE2:		/* 和音 */
				if (zbuf[zmdc - 1] == 0xE0) {
					val = 1;
					harm[0] = zbuf[zmdc];
					harm[1] = 0xFF;
					AB = 0;
					step = zbuf[zmdc+1] * 0x100 + zbuf[zmdc + 2];
					gate = zbuf[zmdc+3] * 0x100 + zbuf[zmdc + 4];
					total += step;
					if (R > 0 && Ron && gate > R) {
						gate = (UWORD)R;
					}
					port.delay =        zbuf[zmdc + 5] * 0x100 + zbuf[zmdc + 6];
					port.delta = (WORD)(zbuf[zmdc + 7] * 0x100 + zbuf[zmdc + 8]);
					port.correct = zbuf[zmdc + 9];
					port.sign = (BYTE)zbuf[zmdc + 10];
					val2 = 0;		/* delay */
					zmdc += 11;
				} else {
					val = 0;
					step = zbuf[zmdc    ] * 0x100 + zbuf[zmdc + 1];
					gate = zbuf[zmdc + 2] * 0x100 + zbuf[zmdc + 3];
					total += step;
					if (R > 0 && Ron && gate > R) {
						gate = (UWORD)R;
					}
					val2 = zbuf[zmdc + 4];	/* delay */
					if (abs(port.sign) != 2) {
						port.delta = port.sign = 0;
					}
					zmdc += 5;
					for (i = 0; i < 8; i++) {
						harm[i] = zbuf[zmdc++];
					}
				}
				if (step) {
					count = 0;
				}
				MTrk += keyonoff2(MTrk,&tie,harm,step,gate,
					&gate_old,velo,trkch,val2,
					&L0[0],KEYOFF,M,port,&bend,&port_now,&special_tie,
					&extMOD_now,
					A,E,&AB,sw,TIEMODE,
					vol,&F,ABspc,ID,(BYTE)runstatus);
				if (val) {
					port.sign = 0;
				}
				break;
			case 0xE1:		/* オートベンド @B */
				Bbak.bendstart = port.delta   = (WORD)(zbuf[zmdc + 4 ] * 0x100 + zbuf[zmdc + 5]);
				Bbak.bendend   = port.correct = (WORD)(zbuf[zmdc + 6 ] * 0x100 + zbuf[zmdc + 7]);
				Bbak.benddelay = port.delay   =        zbuf[zmdc + 8 ] * 0x100 + zbuf[zmdc + 9];
				Bbak.bendsign  = port.sign    = (BYTE)(zbuf[zmdc + 10]) * 2;
				AB = 0;				/* オートベンド使用可 */
				sw |= 4;			/* スイッチオン */
				zmdc += 11;
				break;
			case 0xE3:		/* アフタータッチシーケンス (@Z) */
				zmdc += geteig8(&zbuf[zmdc],&E.eigAFT[0]);
				E.eigAFTm++;
				sw |= 8;
				break;
			case 0xE4:		/* モジュレーションデプス1/8 (旧ver) @M */
				zmdc += geteig8(&zbuf[zmdc],&E.eigMOD[0]);
				E.eigMODm++;
				M.Mdepth = 0;
				mod_old_chg(tie);
				/* mod_old_chg(M.Mdepth,tie); */
				sw |= 1;
				break;
			case 0xE5:		/* ARCCセット1/8 (旧ver) @A */
				zmdc += geteig8(&zbuf[zmdc],&E.eigARC[0]);
				E.eigARCm++;
				A.ARCCv = -128;
				arcc_old_chg(A.ARCCr,tie);
				sw |= 2;
				break;
			case 0xE6:		/* モジュレーションデプス @M */
				M.Mdepth = zbuf[zmdc] * 0x100 + zbuf[zmdc + 1];
				zmdc += 2;
				E.eigMODm = 0;
				/* mod_old_chg(M.Mdepth,tie); */
				mod_old_chg(tie);
				sw |= 1;	/* スイッチオン */
				break;
			case 0xE8:		/* ディレイセット @H */
				val = zbuf[zmdc    ] * 0x100 + zbuf[zmdc + 1];
				if (val != 0xFFFF) M.Mdelay = val;
				val = zbuf[zmdc + 2] * 0x100 + zbuf[zmdc + 3];
				if (val != 0xFFFF) A.ARCCdelay = val;
				zmdc += 4;
				break;
			case 0xE9:		/* FM音源用モジュレーションスピード (@S) */
				zmdc++;
#ifndef ENGLISH
				ZTOMFormatMessage(stderr, "[旧@S]" );
#else
				ZTOMFormatMessage(stderr,"[old-style @S]");
#endif
				break;
			case 0xEA:		/* Roland Exclusive */
				MTrk += PutVarLen(MTrk,gate_old);
				*MTrk++ = 0xF0;
				val = zmdc;
				while (zbuf[zmdc++] != 0xFF) ;
				val = zmdc - val;
				MTrk += PutVarLen(MTrk,val + 4);
				for (val2 = 0; val2 < 4; val2++) {
					*MTrk++ = ID[val2];
				}
				zmdc -= val;
				while (zbuf[zmdc] != 0xFF) {
					*MTrk++ = zbuf[zmdc++];
				}
				*MTrk++ = 0xF7;
				zmdc++;
				status_init(runstatus == 1? USERUNSTAT : NOUSERUNSTAT );
				gate_old = 0;
				break;
			case 0xEB:		/* ＩＤセット(pass) */
				for (i = 0; i < 3; i++) {
					ID[i] = zbuf[zmdc++];
				}
				ID[3] = 0x12;		/* COMMAND */
				break;
			case 0xEC:		/* MIDI生データ送信 */
				val = zbuf[zmdc] * 0x100 + zbuf[zmdc + 1];
				zmdc += 2;
				while (val > 0) {
					if ((zbuf[zmdc] & 0x80) == 0x80) {
						/* MSBが1 == これが始めての送信なら */
						ex_in_use = zbuf[zmdc++];
						val--;
					}
					if (ex_in_use == 0xF0) {	/* ex送信中なら */
						while ((zbuf[zmdc] != 0xF7) && (val > 0)) {
							ex_data[ex_bytes++] = zbuf[zmdc++];
							val--;
						}
						if (zbuf[zmdc] == 0xF7) {
							MTrk += PutVarLen(MTrk,gate_old);
							*MTrk++ = 0xF0;
							MTrk += PutVarLen(MTrk,ex_bytes + 1);
							for (i = 0; i < ex_bytes; i++) {
								*MTrk++ = ex_data[i];
							}
							*MTrk++ = 0xF7;
							val--;
							zmdc++;
							ex_bytes = gate_old = 0;
							status_init(runstatus==1? USERUNSTAT : NOUSERUNSTAT );
						}
					} else {		/* コントロールチェンジ送信中なら */
						DWORD extmp = (ex_in_use & 0xF0);
						if ((extmp == 0xC0) || (extmp == 0xD0)) {
							MTrk += Putcode2(MTrk,gate_old,(UBYTE)(ex_in_use & 0xFF), zbuf[zmdc++]);
							val--;
							gate_old = ex_bytes = 0;
						} else {
							while ((ex_bytes != 2) && (val > 0)) {
								ex_data[ex_bytes++] = zbuf[zmdc++];
								val--;
							}
							if (ex_bytes == 2) {
								MTrk += Putcode(MTrk,gate_old,(UBYTE)(ex_in_use & 0xFF),ex_data[0],ex_data[1]);
								gate_old = ex_bytes = 0;
							}
						}
					}
				}
				if (zbuf[zmdc] != 0xEC) {	/* 次も生データ送信でなければ */
					ex_in_use = 0;
				}
				break;
			case 0xED:		/* エフェクト・コントロール */
				if ( ID[0] == 0x41 && ID[2] == 0x16 ) {	/* MT32 */
					UBYTE data[9] = { 3,0,0,0 };
					UBYTE val = zbuf[zmdc];
					val = (val == 0xFF)? trkch : val - 1;	/* 念のため */
					data[2] = val * 0x10 + 6;	/* part */
					val = zbuf[zmdc + 1];
					if (val != 0xFF) {		/* 念のため */
						data[3] = val;		/* reverb on/off */
						MTrk += put_ex(MTrk,&gate_old,ID,data,4,1,(BYTE)runstatus);
					}
				} else {			/* SC55,& so on */
					int val;
					if ((val = zbuf[zmdc]) != 0xFF) {
						MTrk += Putcode(MTrk,gate_old,0xB0 + trkch,0x5B,val);
						gate_old = 0;
					}
					if ((val = zbuf[zmdc + 1]) != 0xFF) {
						MTrk += Putcode(MTrk,gate_old,0xB0 + trkch,0x5D,val);
						gate_old = 0;
					}
					if ((val = zbuf[zmdc + 2]) != 0xFF) {
						MTrk += Putcode(MTrk,gate_old,0xB0 + trkch,0x5E,val);
						gate_old = 0;
					}
				}
				zmdc += 2 + 1;		/* skip effect 3 */
				break;
			case 0xEE:		/* ピッチモジュレーション・デプス1/8モード(@M)*/
				val = zbuf[zmdc++];
				E.eigMOD[0] = (WORD)(zbuf[zmdc] * 0x100 + zbuf[zmdc + 1]);
				if (!(val & 1)) {
					E.eigMOD[0] = E.eigMOD[7];	/* 最終値 */
				}
				zmdc += 2;
				for (i = 1; i < 8; i++) {
					E.eigMOD[i] = (WORD)(zbuf[zmdc] * 0x100 + zbuf[zmdc + 1]);
					zmdc += 2;
					val >>= 1;
					if (!(val & 1)) {
						E.eigMOD[i] = E.eigMOD[i - 1];
					}
				}
				E.eigMODm++;
				M.Mdepth = 0;
				/* mod_old_chg(M.Mdepth,tie); */
				mod_old_chg(tie);
				sw |= 1;
				break;
			case 0xEF:		/* ARCC・デプス1/8モード(@A)*/
				val = zbuf[zmdc++];
				E.eigARC[0] = (BYTE)zbuf[zmdc++];
				if (!(val & 1)) {
					E.eigARC[0] = E.eigARC[7];	/* 最終値 */
				}
				for (i = 1; i < 8; i++) {
					E.eigARC[i] = (BYTE)zbuf[zmdc++];
					val >>= 1;
					if (!(val & 1)) {
						E.eigARC[i] = E.eigARC[i - 1];
					}
				}
				arcc_old_chg(A.ARCCr,tie);
				E.eigARCm++;
				A.ARCCv = -128;
				sw |= 2;
				break;
			case 0xF0:		/* ＮＯＰ */
				break;
			case 0xF1:		/* skip */
				zmdc += 2 + zbuf[zmdc] * 0x100 + zbuf[zmdc + 1];
				break;
			case 0xFC:		/* NOTE OFF */
			case 0xFD:		/* NOTE ON */
				note = zbuf[zmdc];
				velo = zbuf[zmdc + 1];
				i = (zbuf[zmdc - 1] == 0xFC)? 0 : velo;
				zmdc += 2;
				MTrk += Putcode(MTrk,gate_old,0x90+trkch,note,(UBYTE)i);
				gate_old = 0;
				break;
			case 0xFE:		/* 絶対音長指定の音階 */
				note = zbuf[zmdc];
				step = zbuf[zmdc + 1] * 0x100 + zbuf[zmdc + 2];
				gate = zbuf[zmdc + 3] * 0x100 + zbuf[zmdc + 4];
				zmdc += 5;
				total += step;
				if (step) {
					count = 0;
				}
				if (R > 0 && Ron && gate > R) {
					gate = (UWORD)R;
				}
				if (note == 0xD0) {
					if (tie) {
						gate_old += step;
						break;
					} else {
						strncpy(&harm[0],&harm[9],8);
						gate = 0xFFFF;
					}
				} else {
					for (i = 7; i >= 0; i--) {
						harm[i] = 0xFF;
					}
					harm[0] = note;
				}
				if (abs(port.sign) != 2) {
					port.delta = 0;
				}
				MTrk += keyonoff2(MTrk,&tie,harm,step,gate,
					&gate_old,velo,trkch,0,
					&L0[0],KEYOFF,M,port,&bend,&port_now,&special_tie,
					&extMOD_now,
					A,E,&AB,sw,TIEMODE,
					vol,&F,ABspc,ID,(BYTE)runstatus);
				/* port.sign = 0; */
				break;
			default:
				if ((harm[0] = zbuf[zmdc - 1]) <= 0x80) {	/* 音階or休符 */
					harm[1] = 0xFF;
					step = zbuf[zmdc];
					total += step;
					if (harm[0] == 0x80) {
						R_w_chg('r');
					}
					if (step) {
						count = 0;
					}
					if ((gate = zbuf[zmdc + 1]) == 0xFF) {
						gate = 0xFFFF;
					} else if (R > 0 && Ron && gate > R) {
						gate = (UWORD)R;
					}
					if (abs(port.sign) != 2) {
						port.delta = 0;
					}
					zmdc += 2;
					MTrk += keyonoff2(MTrk,&tie,harm,step,gate,
						&gate_old,velo,trkch,0,
						&L0[0],KEYOFF,M,port,&bend,&port_now,&special_tie,
						&extMOD_now,
						A,E,&AB,sw,TIEMODE,
						vol,&F,ABspc,ID,(BYTE)runstatus);
				} else {	/* 未定義or未サポート */
					ZTOMFormatMessage(stderr,"[%x]",zbuf[zmdc - 1]);
				}
				break;
		}
		if ( F.sign ) {
			if ( (F.sign == -1) && (F.volcor <= 0) ) break;
			if ( F.volcor > (F.target == 1? 100 : 127) && F.sign == 1) {
				F.sign = 0;
				F.cor = 0;
				F.volcor = (F.target == 1)? 100 : 128;
			}
		}
	}
	if (tie && !KEYOFF) {			/* タイ途中で終わったら、キーオフを入れる */
		MTrk += all_noteoff(MTrk,harm,L0,&gate_old,trkch);
	}
	if (*syncs) {				/* 同期用。まあこんなもんでしょ */
		__int3264 d = MTrk - MTrk_;
		MTrk_ = (UBYTE *)erealloc((void *)MTrk_,bufs * 1024 + 2048, "MTrk_");
		MTrk = MTrk_ + d;
	}
	if ( (F.sign == -1) && (F.volcor <= 0) ) {
		gate_old = 0;	/* fadeout end */
	}
	efree(LOOPMAX, "LOOPMAX");
	efree(LOOP, "LOOP");
	MTrk += PutVarLen(MTrk,gate_old);
	*MTrk++ = 0xFF;	/* トラックの終わり */
	*MTrk++ = 0x2F;
	*MTrk++ = 0x00;
	*zmdc_ = zmdc;
	*midc_ = MTrk - MTrk_;
	/* MTrk = MTrk_ + 7; */
	/* *(int *)(MTrk_ + 4) = *midc_ - 8; */
	putDwordAlign(MTrk_ + 4,*midc_ - 8);
	ZTOMFormatMessage(stderr, "done.\n");
#ifdef DEBUG
	sprintf(stderr,filename,"MTr%d",trkch+1);
	fp=fopen(filename,"wb");		/* デバッグ用 */
	fwrite(MTrk_,sizeof(unsigned char),*midc_,fp);
	fclose(fp);
#endif
	return MTrk_;
}
/* ===============================================
     1/8モードのパラメータを読み出す(1byte/para)
   =============================================== */
int geteig8(UBYTE *zbuf,WORD eig[])
{
	int i;
	eig[0] = *zbuf++;
	if (eig[0] == 0xFF) {
		eig[0] = eig[7];
	}
	for (i = 1; i < 8; i++) {
		eig[i] = *zbuf++;
		if (eig[i] == 0xFF) {
			eig[i] = eig[i - 1];
		}
	}
	return 8;
}
/* ================
     全ノートオフ
   ================ */
__int3264 all_noteoff(UBYTE *MTrk,UBYTE *harm,UBYTE *L0,DWORD *gate_old,DWORD trk)
{
	UBYTE *MTrk_ = MTrk;
	if (harm[0] != 0x80) {
		if (L0[0] == 0xFF) {
			MTrk += keyoff(MTrk,&harm[9],NULL,*gate_old,trk);
			harm[0] = harm[9] = 0xFF;
		} else {
			if (harm[0] != 0xFF) {
				MTrk += keyoff(MTrk,&harm[0],NULL,*gate_old,trk);
				harm[0] = 0xFF;
				*gate_old = 0;
			}
			/* if (L0[0] != 0xFF) { */
				MTrk += keyoff(MTrk,&L0[0],NULL,*gate_old,trk);
				L0[0] = 0xFF;
			/* } */
		}
		*gate_old = 0;
	/* } else if (!KEYOFF && L0[0] != 0xFF) { */	/* *0&中休符&なら中止 */
	} else if (L0[0] != 0xFF) {	/* *0&中休符&なら中止 */
		MTrk += keyoff(MTrk,&L0[0],NULL,*gate_old,trk);
		L0[0] = 0xFF;
		*gate_old = 0;
	}
	return MTrk - MTrk_;
}
void usech_init()
{
	int i;
	for (i = 0; i < TRKMAX; i++) {
		usech[i] = 0;
	}
}