/*
 * Please use Tiny/Large mode to compile.
 */



#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

enum segreg { ds, es, cs, ss };
enum _action { _if, _then };

struct cmp_str {
	enum _action action;
	enum segreg reg;
	unsigned int ofs, seg;
	unsigned char string[256];
};

void skp_spc( FILE *in );
void syntax_error( void );
get_string( FILE *in, struct cmp_str *str  );
extern int tsr_len( void );
extern int tsr_len2( void );
extern void tsr_portion( void );
extern void tsr_portion2( void );
void tsr_start( void );
void tsr_start2( void );

int main( int argc, char *argv[])
{
	FILE	*in, *out;
	struct	cmp_str	str;
	char	s[100], path[100];
	unsigned char	buf[0x4000];
	unsigned int	buf_idx;
	int	i, last_if = 0;
	int	total_if = 0, last_if2, no_then;
	int	code_start = 4;
	void	*tsr_code, *tsr_st;
	int	tsr_ln;

	memset( buf, 0, 0x4000 );

	if (argc != 3)
	{
		fprintf(stderr, "TSRCRACK Version 1.0 10/02/93 - TSR generator\n");
		fprintf(stderr, "Copyright (C) 1993  by Wong Wing Kin.  All rights reserved.\n" );
		fprintf(stderr, "\nUsage: TSRCRACK <Iinfile> <Outfile>\n");
		return 1;
	}

	if (!(in = fopen(argv[1], "rt")))
	{
		fprintf(stderr, "Cannot open input file.\n");
		return 1;
	}

	if (!(out = fopen(argv[2], "wb")))
	{
		fprintf(stderr, "Cannot open output file.\n");
		return 1;
	}

	fscanf( in, " %s", &s );
	if (!strcmp(strlwr(s), "program"))
	{
		code_start += 13;
		fscanf( in, "%s", &path );
		printf( "%s\t%s\n", s, path );
		fscanf( in, " %s", &s );
		memcpy( &buf[4], path, strlen(path) );
		tsr_code = &tsr_portion2;
		tsr_st = &tsr_start2;
		tsr_ln = tsr_len2();
	}
	else
	{
		tsr_code = &tsr_portion;
		tsr_st = &tsr_start;
		tsr_ln = tsr_len();
	}

	if (strcmp(strlwr(s), "int"))
		syntax_error();
	printf( s );
	fscanf( in, "%X", &i );
	printf( "\t%02X\t\n", i );

	memcpy( &buf[code_start+6], &i, 1 );
	buf_idx = code_start+8;

	while (!feof(in))
	{
		get_string(in, &str);
		if (str.action == _if)
		{
			if (last_if)
			{
				buf_idx += 0x100;
				memcpy( &buf[last_if+1], &buf_idx, 2);
				buf_idx -= 0x100;
				buf[last_if2] = no_then;
			}
			last_if = buf_idx;
			buf_idx += 3;
			no_then = 0;
			total_if++;
		}
		else
			no_then ++;

		buf[buf_idx] = str.reg;
		memcpy( &buf[buf_idx += 1], &str.ofs, 2 );
		memcpy( &buf[buf_idx += 2], &str.seg, 2 );
		memcpy( &buf[buf_idx += 2], &str.string, str.string[0]+1 );
		buf_idx += str.string[0]+1;

		if (str.action == _if)
			last_if2 = buf_idx++;
	}
	buf[last_if2] = no_then;
	memcpy( buf, tsr_st, 4 );
	buf_idx += 0x100;
	memcpy( &buf[code_start], &buf_idx, 2 );
	buf_idx -= 0x100;
	buf[code_start+7] = total_if;

	fwrite( buf, buf_idx, 1, out );
	fwrite( tsr_code, tsr_ln, 1, out );
	fclose(in);
	fclose(out);

	return 0;
}

void syntax_error( void )
{
	fprintf(stderr, "Syntax error.\n");
	exit(1);
}

get_string( FILE *in, struct cmp_str *str  )
{
	char	s[100];
	int	i;

	fscanf( in, " %s", &s );
	printf( s );
	if (strcmp( strlwr(s), "then" ) && strcmp( strlwr(s), "if" ))
		syntax_error();

	if (!strcmp( s, "if" ))
		str->action = _if;
	else
		str->action = _then;

	fscanf( in, " %[^:-+ ]", &s );
	strlwr( s );

	printf( "\t%s : ", s );
	switch (s[0]) {
	case 'd':
		str->reg = ds;
		break;
	case 'e':
		str->reg = es;
		break;
	case 'c':
		str->reg = cs;
		break;
	case 's':
		str->reg = ss;
		break;
	default:
		syntax_error();
	}
	if (s[1] != 's')
		syntax_error();

	str->seg = str->ofs = 0;

	fscanf( in, " %[:]", &s );
	fscanf( in, " %X", &str->seg );

	fscanf( in, " %[:]", &s );
	fscanf( in, " %X", &str->ofs );

	fscanf( in, " %[=]", &s );
	i = 0;
	while (fscanf( in, " %hX", &str->string[++i] ) && !feof( in ));
	str->string[0] = i-1;

	printf( "%04X : %04X = ", str->seg, str->ofs );
	for (i=1; i <= str->string[0]; i++)
	{
		printf( " %02X", str->string[i] );
	}
	printf("\n");

	return	0;
}

void tsr_start( void )
{
asm	{
		jmp	word ptr [104h]
	}
}

void tsr_start2( void )
{
asm	{
		jmp	word ptr [100h+4+13]
	}
}
