/*************************************************
BIT.C: Routines to read bit-aligned .REL files for LOADER.

Written by:  Douglas Braun
             99 Summit Rd.
	     Riverside, CT 06878

July 1, 1985

**************************************************/

#include "LOADER.H"

FILE *infile;
char curchar;
int bit;
int isopen = FALSE;


BIT getbit()
{
    static int maskarr[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
    static retbit;  /* Static for speed */

    if (bit < 0)  /* We have gone past the LSB */
    {
	bit = 7;
	if ((curchar=getc(infile)) == EOF)
	    return(EOF);
    }

    retbit = (curchar & maskarr[bit--]) ? 1 : 0;
    return(retbit);

}



/* Open a bitfile. Same args as fopen. */
bitfopen(name,mode)
char *name, *mode;
{

   if (isopen == TRUE) /* Close the previous open file */
   {
        fclose(infile);
	isopen = FALSE;
   }

   infile = fopen(name,mode);

   if (infile == NULL)
       return(FALSE);

    bit = -1;

    isopen = TRUE;
    return(TRUE);
}


/* Get an int made up of n bits.
The msb is read first. This will not work
for addresses, which need bytes swapped. */
getnbits(n)
int n;
{
    static j;
    static result;
    static newbit;

    result = 0;
    for (j=1; j <=n; j++)
    {
	result <<= 1;
	newbit = getbit();
	if (newbit == EOF)
	    return(EOF);
	result |= newbit;
    }

    return(result);
}

/* Get 8 bits that form an ascii char. */
getbchar()
{
    register mask;
    static int maskarr[] = { 0x7f, 0x3f, 0x1f, 0xf, 0x7, 0x3, 0x1, 0x0 };
    static result;

    if (bit < 0)
    {
	result = getc(infile);
    }
    else if (bit == 7)
    {
	result = curchar;
	curchar = getc(infile);
    } else {
	mask = maskarr[bit];
	result = (curchar << (7-bit)) & ~mask;
	curchar = getc(infile);
	result = result | ((curchar >> (bit+1)) & mask);
    }

    return(result & 0xff);
}



/* Force alignment to byte bountary */
bytesync()
{
    bit = -1;
}



/* Get an 8080 16-bit address.  No info about EOF returned. */
int getaddr()
{
    int lowbyte;

    lowbyte = getbchar();
    return( lowbyte | (getbchar() << 8));
}



/* Read in an "A field", consisting of
a 2 bit address type and a 16 bit address */

getafield(afield)
AFIELD *afield;
{
    afield->addrtype = getnbits(2);
    afield->address = getaddr();
}



/* Read in a "B field", which is a 3 bit length
field, followed by 8-bit ascii chars. */

getbfield(bfield)
BFIELD *bfield;
{
    int length;
    char *cp;
    int j;

    cp = bfield->b_symbol;
    length = getnbits(3);

    for (j=1; j<=length; j++)
    {
	*(cp++) = getbchar();
    }
    *cp = '\0';
}

