// CNGSOFT's block generator for MINILOAD.I80 loader - sometime in 2018-2019 //

#include <stdio.h> // fopen...
#include <stdlib.h> // atoi...

unsigned char m[1<<16],h[1<<5],o[1<<16]; int oo=0;

#define putc(i) (o[oo++]=i)
int putcc(int i) { putc(i); return putc(i>>8); }
#define flushc(f) (fwrite(o,1,oo,f),oo=0)

int main(int argc,char **argv)
{
	int i=0,j=0,l=0,bit0=0,hold=2560;
	char *s=NULL,*t=NULL;
	while (++i<argc)
	{
		if (!bit0)
			bit0=atoi(argv[i]);
		else if (argv[i][0]==':')
			h[j++]=atoi(&argv[i][1]); // bytes to include within the prefix
		else if (!s)
			s=argv[i];
		else if (!t)
			t=argv[i];
		else if (!(hold=atoi(argv[i])))
			i=argc; // HELP!
	}
	if (i>argc||!bit0||!t)
		return printf("usage: MINILOAD bit0 [:number ...] [+]source [+]target [pause]\n"),1;
	FILE *f;
	if (i=(*s=='+')) ++s; // "+source" skips the first 128 bytes (AMSDOS/+3DOS)
	if (!(f=fopen(s,"rb")))
		return printf("error: cannot open source!\n"),1;
	if (i)
		fread(m,1,128,f);
	l+=fread(m,1,sizeof(m),f);
	fclose(f);
	if (i=(*t=='+')) ++t; // "+target" inserts a +2-byte prefix with the block size!
	if (!(f=fopen(t,"ab")))
		return printf("error: cannot create target!\n"),1;
	int tones=4096,x;
	if (hold<0)
		hold=-hold,tones/=2;
	if (i|j)
	{
		putc(0x11);
		putcc(bit0*2); // PILOT pulse
		putcc(bit0); // SYNC1 pulse
		putcc(bit0); // SYNC2 pulse
		putcc(bit0); // BIT0 pulse
		putcc(bit0*2); // BIT1 pulse
		putcc(tones); // PILOT length
		putc(8); // trailing bits
		putcc(10); // PAUSE in ms
		if (i)
		{
			putcc(3+j); // DATA length (L)
			putc(0); // DATA length (H)
			flushc(f); fwrite(h,1,j,f); // extra bytes
			putcc(l); // block length
			x=l^(l>>8);
		}
		else
		{
			putcc(1+j); // DATA length (L)
			putc(0); // DATA length (H)
			flushc(f); fwrite(h,1,j,f); // extra bytes
			x=0;
		}
		for (i=0;i<j;++i)
			x^=h[i];
		putc(~x);
	}
	putc(0x11);
	putcc(bit0*2); // PILOT pulse
	putcc(bit0); // SYNC1 pulse
	putcc(bit0); // SYNC2 pulse
	putcc(bit0); // BIT0 pulse
	putcc(bit0*2); // BIT1 pulse
	putcc(tones); // PILOT length
	putc(8); // trailing bits
	putcc(hold); // PAUSE in ms
	putcc(l+1); // DATA length (L)
	putc(0); // DATA length (H)
	flushc(f); fwrite(m,1,l,f);
	for (x=0,i=0;i<l;++i)
		x^=m[i];
	putc(~x);
	flushc(f); fclose(f);
	return 0;
}
