char ___logging;
char ___log_frozen;
char ___log_freeze_pending;
char ___log_fire;
char ___log_set;
char ___log_log;
char ___log_launch;
char ___log_hex, ___log_empty;
unsigned char *___logp;
unsigned char *___log_start;
unsigned long ___log_period, ___log_freeze_time;
unsigned long ___log_next;
unsigned long ___log_mask;
int ___log_cnt;

void
___reset_log()
{
	___log_start = ___log_base;
	___logp = ___log_end;
	___set_log_full(0);
	___log_frozen = 0;
	___log_empty = 1;
}
int
___alloc_log(int entries)
{	
	int count;
	unsigned long t;

	if (___log_frozen)
		return(0);
	count = entries*2 + 4 + 1 + 1;
	if ((___log_end-___logp) < count) {
		*___logp = 0;
		___logp = ___log_base;
	}
	if (___log_empty) {
		___log_empty = 0;
	} else
	if (___logp <= ___log_start && (___logp+count) > ___log_start) {
		if (___log_freeze_pending) {
			t = *(unsigned long *)&___log_start[1];
			if (t >= ___log_freeze_time) {		
				___set_log_full(1);
				___log_frozen=1;
				return(0);
			}
		}
		___log_start += 6+2*(___log_start[5]);
		if (*___log_start==0)
			___log_start = ___log_base;
	}
	return(1);
}

void
___log_val(int v)
{
	*(int *)___logp = v;
	___logp += 2;
}

void
___log_time()
{
	*(unsigned long *)___logp = time;
	___logp += 4;
}

void ___log0(int type)
{
	if (!___logging || !___alloc_log(0))
		return;
	*___logp++ = type;
	___log_time();
	*___logp++ = 0;
}

void ___log1(int type, int v1)
{
	if (!___logging || !___alloc_log(1))
		return;
	*___logp++ = type;
	___log_time();
	*___logp++ = 1;
	___log_val(v1);
}
void ___log2(int type, int v1, int v2)
{
	if (!___logging || !___alloc_log(2))
		return;
	*___logp++ = type;
	___log_time();
	*___logp++ = 2;
	___log_val(v1);
	___log_val(v2);
}
int ___logN(int type, int cnt)
{
	if (!___logging || !___alloc_log(cnt))
		return(0);
	*___logp++ = type;
	___log_time();
	*___logp++ = cnt;
	return(1);
}

void
___log_print(int count)
{
	unsigned char *lp, *old;
	int i, j;
	unsigned long t;

	lp = ___log_start;
	for (i = 0; count==0||i < count; i++) {
		old = ___logp;
		t = *(unsigned long *)&lp[1];
		if (___log_hex) {
			phex((unsigned long)t);
			phex((lp[5]<<8)|lp[0]);
			for (j = 0; j < lp[5]; j++)
				phex(*(int *)&lp[6+(j*2)]);
		} else {
			pval((unsigned long)t);pchr('	');
			pval(lp[5]);pchr('	');
			pval(lp[0]);
			for (j = 0; j < lp[5]; j++) {
				pchr('	');
				pval(*(int *)&lp[6+(j*2)]);
			}
		}
		pchr('\n');
		lp += 6+2*(lp[5]);
		if (lp == ___logp)	
			break;
		if (*lp == 0)
			lp = ___log_base;
		if (lp == ___logp || (old < ___logp && lp >= ___logp))	
			break;
	}
}



void 
___log_ctl(int p1, int p2)
{
	if (___log_log)
		___log2(0x40, p1, p2);
	switch(p1) {
	case 0:	switch (p2) {
		case 0:	___logging = 0;
			break;
		case 1:	___logging = 1;
			___log_next = 0;
			___reset_log();
			break;
		case 2:	___logging = 0;
			break;
		case 3:	___logging = 1;
			break;
		case 4:	___reset_log();
			break;
		case 5:	___log_frozen=0;	
			___set_log_full(0);
			___log_freeze_pending = 0;
			break;
		case 6:	
			break;
		case 7:	
			break;
		case 8:	
			break;
		case 9:	
			break;
		case 10:___log_fire = 1;
			break;
		case 11:___log_fire = 0;
			break;
		case 12:___log_launch=1;
			break;
		case 13:___log_launch=0;
			break;
		case 14:___log_set=1;
			break;
		case 15:___log_set=0;
			break;
		case 16:___log_hex=1;
			break;
		case 17:___log_hex=0;
			break;
		case 18:___log_log=1;
			break;
		case 19:___log_log=0;
			break;
		}
		break;
	case 1:	___log_freeze_pending = 1;
		___log_freeze_time = time-p2;
		break;
	case 2: 
		break;
	case 3:
		break;
	case 4:
		break;
	case 5:	___log_print(p2);
		break;
	case 6:	___log_period=p2;
		___log_next = 0;
		break;
	case 7:	if (!(___log_mask&(1<<p2))) {
			___log_mask |= 1<<p2;
			___log_cnt++;
		}
		break;
	case 8:	if ((___log_mask&(1<<p2))) {
			___log_mask &= ~(1<<p2);
			___log_cnt--;
		}
		break;
	}
}

void 
___log(int tos, int ntos)
{
	___log2(0x41, tos, ntos);
}
@
___launch_channel=%d;
___launch_delta=%d;
___launch_wait=%d;
___launch_initial_wait=%d;
___launch_rel=%d;
___launch_delta_time=%d;

int ___launch_idle;
unsigned long ___launch_time;
unsigned long ___launch_start;
unsigned char ___launched;

void
___poll()
{
	int i, j, k, v;

	if (time < ___log_next)
		return;

	v = get(___launch_channel);

	if (!___launched)
	if (!___launch_start) {
		___launch_start = time+___launch_initial_wait;
	} else
	if (time < ___launch_start) {
		___launch_idle = v;
	} else
	if (___launch_rel) {
		if (v > (___launch_idle+___launch_delta) ||
		    v < (___launch_idle-___launch_delta)) {
			if (time >= ___launch_time) {
				___found_launch();
				if (___log_launch && !___launched)
					___log0(0x42);	
				___launched = 1;
			}
		} else {
			___launch_time = time+___launch_wait;
		}
	} else {
		if (v < (___launch_idle-___launch_delta)) {
			___found_launch();
			if (___log_launch && !___launched)
				___log0(0x42);
			___launched = 1;
		}
	}
	if (!___logging||___log_cnt == 0) {
		___log_next = time+___launch_delta_time;
		return;
	}
	___log_next = time+(((unsigned long)___log_period)&0xffff);
	if (!___logN(1, ___log_cnt))
		return;
	j = ___log_cnt;
	for (i = 1, k=0; j > 0; i=i<<1, k++)
	if (___log_mask&i) {
		if (k == ___launch_channel) {
			___log_val(v);
		} else {
			___log_val(get(k));
		}
		j--;
	}
}

void
___extra(int type, int v1, int v2)
{
	switch (type) {
	case 0x46:
			if (___log_set)
				___log2(type, v1, v2);
			break;
	case 0x45:
	case 0x44:
	case 0x43:	if (___log_fire)
				___log1(type, v1);
			break;
	}
}
@
___launch_channel=%d;
___launch_delta=%d;
___launch_wait=%d;
___launch_initial_wait=%d;
___launch_rel=%d;
___launch_delta_time=%d;

int ___launch_idle;
unsigned long ___launch_time, ___log_next;
unsigned long ___launch_start;
unsigned char ___launched;

void
___poll()
{
	int i, j, k, v;

	if (time < ___log_next)
		return;

	v = get(___launch_channel);

	if (!___launched) 
	if (!___launch_start) {
		___launch_start = time+___launch_initial_wait;
	} else
	if (time < ___launch_start) {
		___launch_idle = v;
	} else
	if (___launch_rel) {
		if (v > (___launch_idle+___launch_delta) ||
		    v < (___launch_idle-___launch_delta)) {
			if (time >= ___launch_time) {
				___found_launch();
				___launched = 1;
			}
		} else {
			___launch_time = time+___launch_wait;
		}
	} else {
		if (v < (___launch_idle-___launch_delta)) {
			___found_launch();
			___launched = 1;
		}
	}
	___log_next = time+___launch_delta_time;
}

void
___extra(int type, int v1, int v2)
{
	;
}
@
void
___poll()
{
	int i, j, k;

	if (!___logging || ___log_cnt == 0)
		return;

	if (time < ___log_next)
		return;
	___log_next = time+(((unsigned long)___log_period)&0xffff);
	if (!___logN(1, ___log_cnt))
		return;
	j = ___log_cnt;
	for (i = 1, k=0; j > 0; i=i<<1, k++)
	if (___log_mask&i) {
		___log_val(get(k));
		j--;
	}
}

void
___extra(int type, int v1, int v2)
{
	switch (type) {
	case 0x46:
			if (___log_set)
				___log2(type, v1, v2);
			break;
	case 0x45:
	case 0x44:
	case 0x43:	if (___log_fire)
				___log1(type, v1);
			break;
	}
}
