/* memtest the c version by john collyer */

#include <os9.h>
#include <stdio.h>
#include <signal.h>

#define false 0
#define true  1

struct registers regs;
int count1,count2,mblk,savU;
char bmap[256];
char errnum;
char mapped;
char *ptr;

int errortrap ( code )
{
int code;
    clearblock();
    printf("\n\t");
    deallocate();
    _exit(0);
}

main ( argc, argv )
int argc;
char **argv;
{
    intercept(errortrap);
    for(count1 = 0; count1 < 256; count1++)
        bmap[count1] = 0;
    mapped = false;
    printf("\nMemTest v2.00 - by John Collyer\n");
    ptr = bmap;
    regs.rg_x = ptr;
    _os9(25,&regs);  /* F$GBlkMp (pg 8-18) */
    mblk = regs.rg_y;

    /* allocate everything available */
    printf("  Allocating Block: $  ");
    for(;;)
    {
        regs.rg_b = 1;           /* 1 block */
        _os9(57,&regs);          /* F$AllRam (pg 8-72) */
        if((regs.rg_cc & 1) > 0) /* Carry set */
            break;
        count1 = (int) (regs.rg_b & 0xFF);
        bmap[count1] |= 16;
        printf("\b\b%02X", count1);
    }
    printf("\n\t");

    /* test each block */
    printf("     Testing Block: $  ");
    for(count1 = 0; count1 < mblk; count1++)
    {
        if((bmap[count1] & 16) > 0)
        {
            printf("\b\b%02X", (count1 & 0xFF));
            regs.rg_b = 1;  /* 1 block */
            regs.rg_x = count1;
            _os9(79,&regs); /* F$MapBlk (pg 8-96) */
            savU = regs.rg_u;
            mapped = true;
            for(count2 = 0; count2 < 8192; count2++)
            {
#asm
                ldu  savU,y
                ldd  count2,y
                leax d,u
                lda  #$55
                sta  ,x
                lda  ,x
                cmpa #$55
                bne  setbad
                lda  #$AA
                sta  ,x
                lda  ,x
                cmpa #$AA
                bne  setbad
                bra  ok
setbad          equ  *
#endasm
                bmap[count1] |= 96;
#asm
ok              equ  *
#endasm
            }
            bmap[count1] |= 32;
            clearblock();
        }
    }
    printf("\n\t");
    deallocate();
}

deallocate()
{
    printf("Deallocating Block: $  ");
    for(count1 = 0; count1 < mblk; count1++)
    {
        if((bmap[count1] & 16) > 0)
        {
            printf("\b\b%02X", (count1 & 0xFF));
            regs.rg_b = 1;  /* 1 block */
            regs.rg_x = count1;
            _os9(81,&regs); /* F$DelRam (pg 8-81) */
        }
    }
    printf("\n");
    printf("     0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
    printf("   +--------------------------------\n");
    for(count1 = 0; count1 < mblk/16; count1++)
    {
        printf("%2X", count1*16);
        printf(" |");
        for(count2 = 0; count2 < 16; count2++)
        {
            switch(bmap[count1*16+count2])
            {
                case 0:
                    printf(" _");
                    break;
                case 1:
                    printf(" U");
                    break;
                case 3:
                    printf(" M");
                    break;
               case 16:
                    printf(" .");
                    break;
               case 48:
                    printf(" !");
                    break;
               case 112:
                    printf(" ?");
                    break;
            }
        }
        printf("\n");
    }
    printf("\n");
    printf("Legend:\n");
    printf("'_' = unallocated & untested, 'U' = in use,    'M' = module\n");
    printf("'.' = allocated & untested,   '!' = tested OK, '?' = tested BAD!\n");
}

clearblock()
{
    if(mapped)
    {
        regs.rg_b = 1;  /* 1 block */
        regs.rg_u = savU;
        _os9(80,&regs); /* F$ClrBlk (pg 8-77) */
        mapped = false;
    }
}
