/****************************************************************************
 *FILE: test11p.c
 *
 *DESCRIPTION:
 * Simple demonstration program of how to use ARMPOLL, ARMSERVE, ARMRDCH and
 * ARMWRCH.  It simulates (in a very simple way) being connected.
 * The most obious deficiency of this demonstration is the lack of the VDU
 * drivers.
 *
 *COMPILER:  Mark Williams MWC86 Version 3.0.6
 *
 */
 
 
#include <dos.h>
#include <stdio.h>
#include <ctype.h>
#include "armintc.h"



/* Define TRUE and FALSE here.  Didn't want to include stds.h */
typedef int 	BOOL;
#define TRUE	(BOOL)1
#define FALSE	(BOOL)0



/* Routines in this file. */
extern	int		main(  /* int argc, char *argv[] */  );
extern	BOOL	chkrrsig(  /* void */  );
extern	void	print_help(  /* void */  );



/***************************************************************************
 */
int		main( argc, argv )
int		argc;
char	*argv[];
	{
	struct reg			sreg,	rreg;


	/*	printf("test11p.c: Main of test11p.exe entered.\n");	*/


	if (argc != 1)
		{
		print_help();
		return(1);
		}


	/* Check for the ram resident interface software being loaded. 
	 */
	if (!chkrrsig())
		{
		printf( "test11p:  ARM interface sortware is not loaded.  Use arminit.\n" );
		return(1);
		}


	/* Initialise the interface software and the ARM card.
	 */
	sreg.r_ax = ARMINIT;
	intcall(&sreg, &rreg, ARMINT);
	if (rreg.r_ax != FNOK)
		{
		printf("test11p:  ARMINIT failed:  error number = 0x%x\n", rreg.r_ax);
		return( 1 );
		}


	/* Send the command stdioon to the interface software.  This ensures that
	 * if the user types any inbuilt commands such as DIR then their output
	 * will be placed on stdout,  not printed via the vdu driver.
	 */
		{
		char		*inbuilt_command = "stdioon\n";
		int			i;

		for (i=0; inbuilt_command[i] != '\0'; i++)
			{
			sreg.r_ax = ARMRDCH;
			sreg.r_bx = (unsigned int)inbuilt_command[i];
			intcall(&sreg, &rreg, ARMINT);
			if (rreg.r_ax != FNOK)
				{
				printf("\ntest11p:  ARMRDCH failed.  Error = %x\n", rreg.r_ax);
				return(1);
				}
			}
	    sreg.r_ax = ARMSERV;
	    intcall(&sreg, &rreg, ARMINT);
		if (rreg.r_ax != FNOK)
			{
			printf("\ntest11p:  ARMSERVE failed.  Error = %x\n", rreg.r_ax);
			return(1);
			}
		}



	/*
	 * Issue continuous ARMSERVs to simulate a connection.
	 */
	for( ; ; )
		{
		char	ch;

		/* First of all see if a command is required to be serviced. */
	    sreg.r_ax = ARMPOLL;
	    intcall(&sreg, &rreg, ARMINT);

		/* printf("\ntest11p:  ARMPOLL returned %x\n", rreg.r_ax); */

		switch (rreg.r_ax)
			{
			case FNOK:
				/* No command waiting to be serviced.  Do nothing. */
				break;


			case TBVDUPEND:
				/* A character is waiting to be output. */
			    sreg.r_ax = ARMWRCH;
			    intcall(&sreg, &rreg, ARMINT);
			    ch = (char)rreg.r_bx;
			    if (rreg.r_ax != FNOK)
					{
					/* This should never happen as the ARMPOLL has reported
					 * that a character is waiting. */
					printf("\ntest11p:  ARMWRCH failed.  Error = %x\n", 
							rreg.r_ax);
					return(1);
					}

				if (isascii(ch) && (isprint(ch) || isspace(ch)))
					printf("%c", ch);

#				ifdef VERBOS
				/* Print non printable characters in hex. */
				if ( !(isascii(ch) && (isprint(ch) || isspace(ch))) )
					printf("#%02x", ((unsigned int)ch & 0xFF) );
#				endif

				fflush( stdout );

				break;


			case TBCMNDPEND:
				/* Service the requested command. */
			    sreg.r_ax = ARMSERV;
			    intcall(&sreg, &rreg, ARMINT);

				if ( (rreg.r_ax != FNOK) && (rreg.r_ax != TBCMNDRDCHS) )
					{
#					ifdef VERBOS
					printf("\ntest11p:  ARMSERVE failed.  Error = %x\n",
							rreg.r_ax);
#					endif
					}

				if (rreg.r_ax == TBCMNDRDCHS)
					{
					/* ARMSERV failed because a RDCH was requested and no
					 * characters were in the keyboard buffer.
					 * Read a character from the PC's standard input 
					 * unbuffered.
					 */

					ch = getcnb();

					/* Since unbuffered input is being used trap <ctrl C> */
					if (ch == (char)3)
						exit(1);

					sreg.r_ax = ARMRDCH;
					sreg.r_bx = (unsigned int)ch;
					intcall(&sreg, &rreg, ARMINT);
					if (rreg.r_ax != FNOK)
						{
						/* This should never happen as characters are put and
						 * got one at a time. The keyboard buffer should only
						 * ever have zero or one character in it.
						 */
						printf("\ntest11p:  ARMRDCH failed. Error = %x\n",
								rreg.r_ax);
						return(1);
						}
					}
 				break;


			default:
				/* Should never be used. */
				printf("\ntest11p:  Unknown return from ARMPOLL = %x\n",
						rreg.r_ax);
				return(1);
				break;
			}
		}
	return(0);
	}


/*************************************************************************
 * Check that ram resident code signature is present.
 */
BOOL chkrrsig()
	{
	struct reg r;
	r.r_ax = GETVEC | ARMSINT;		/* Get old vector */
    intcall(&r, &r, DOSINT);
    if ((r.r_es == ARMSIG2) && (r.r_bx == ARMSIG1))
    	return( TRUE );
    else
    	return( FALSE );
	}


/*************************************************************************
 */
void		print_help()
	{
	printf( "%s%s%s%s%s", 
"test11p:  Requires no arguments.\n\n",
"This program is a simple demonstration program of how to use ARMPOLL, \n",
"ARMSERVE, ARMRDCH and ARMWRCH.  It simulates (in a very simple way) being\n",
"connected.  The most obious deficiency of this demonstration is the lack\n",
"of the VDU drivers.\n" );
	}
