#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "..\DPMI.H"
#include "..\DPMI10.H"

static char Yes[] = "yes";
static char No[] = "no";


static void print_dpmi09_info(void)
{
#define N_FREEMEM 8
    static char * freemem_text[N_FREEMEM] = {
	"Number free pages                  ",
	"Number free pages to lock          ",
	"Number pages of linear addr space  ",
	"Number pages not locked            ",
	"Number pages not used              ",
	"Number pages managed by the Dpmi   ",
	"Number pages free addr space       ",
	"Number pages in swapfile           "
    };

    FREEMEMINFO freeinfo;
    int i;
    long pages;

    GetFreeMemInfo(&freeinfo);

    printf("Largest available block : %lu Bytes = %lu KB\n",
	   freeinfo.LargestFree, freeinfo.LargestFree >> 10);

    for (i = 0; i < N_FREEMEM; i++) {
	pages = *(((long *) (&freeinfo)) + i + 1);

	if (pages == -1)
	    printf("%s : not supported\n", freemem_text[i]);
	else {
	    printf("%s : %10lu = ", freemem_text[i], pages);
	    pages *= 4;
	    if (pages > 16*1024)
		printf("%8lu MB\n", pages / 1024);
	    else
		printf("%8lu KB\n", pages);
	}
    }
}


static void print_dpmi10_meminfo(void)
{
#define N_MEMO 13
    static char * memo_text[N_MEMO] = {
	"HostPhysicalMemory        " ,
	"HostVirtuelMemory         " ,
	"HostFreeVirtuelMemory     " ,
	"VMVirtuelMemory           " ,
	"VMFreeVirtuelMemory       " ,
	"ClientVirtuelMemory       " ,
	"ClientFreeVirtuelMemory   " ,
	"LockedMemory              " ,
	"ClientMaxLockedMemory     " ,
	"ClientHighestLinearAddress" ,
	"LargestMemoryBlock        " ,
	"MinimumUnitValue          " ,
	"MemoryAlignValue          "
    } ;
    DPMI10INFO info;
    int i;
    DWORD *p;

    if (GetMemoryInfo(&info)) {
	puts("no dpmi 1.0 meminfo");
	return;
    }
    printf("\nDPMI 1.0 Linear Memory\n");
    printf("Host free %lX\n", info.HostPhysicalMemory);

    p = (DWORD *) & info;
    for (i = 0; i < N_MEMO; ++i)
	printf("%s = %8lu KB\n", memo_text[i], *(p+i)/1024);

    fflush(stdout);
}


static void print_dpmi10_cap(void)
{
#define N_INFO_BITS 7
    static char * info_text[N_INFO_BITS] = {
	"page access/dirty" ,
	"exceptions restartability" ,
	"device mapping" ,
	"conventional mapping" ,
	"demand zero fill" ,
	"write-protect client" ,
	"write-protect host"
    };

    char hostbuf[128];
    DPMICAP cap;
    int i;

    if (GetDPMICapabilities(&cap, hostbuf)) {
	puts("no dpmi 1.0 capabilities");
	return;
    }
    printf("\nDPMI 1.0 Capabilities\n");
    printf("host %s %d.%d\n", hostbuf+2, hostbuf[0], hostbuf[1]);

    for (i = 0; i < N_INFO_BITS; ++i) {
	printf("%s supported: %s \n", info_text[i], (cap.bits & 1) ? Yes : No);
	cap.bits >>= 1;
    }
    putchar('\n');
    fflush(stdout);
}

/*
**  Test DPMI server
*/
#ifdef __EMX__
static int test_dpmi_server(void)
{
    return ((_emx_env & 0x80) | (_emx_env & 0x100));
}
#endif

#ifdef __GO32__
#include <go32.h>
extern Go32_Info_Block _go32_info_block;

static int test_dpmi_server(void)
{
    return _go32_info_block.run_mode & _GO32_RUN_MODE_DPMI;
}
#endif


int main(int argc, char **argv, char **env)
{
    DPMIVERSION dpmi_ver;
    int i;

    if (!test_dpmi_server()) {
	puts("I need dpmi, run this program with a dpmiextender\n");
	puts("EMX: run rsx ; DJGPP run go32 not with 'nodpmi'\n");
	return 1;
    }

    if (argc > 1 && strcmp(argv[1],"-?") == 0) {
	printf("usage: %s [-c -m]\n", argv[0]);
	printf("-c : Print DPMI 1.0 Capabilities\n");
	printf("-m : Print DPMI 1.0 Memory Info\n");
	return 0;
    }

    GetDPMIVersion(&dpmi_ver);
    printf("\nDPMI version %d.%d\n", dpmi_ver.major, dpmi_ver.minor);
    printf("32bit supported: %s\n", (dpmi_ver.flags & 1) ? Yes : No);
    printf("CPU detected %d86\n", dpmi_ver.cpu);

    printf("\nDpmi Memory\n");
    print_dpmi09_info();
    fflush(stdout);

    for (i = 1; argv[i]; i++) {
	if (strcmp(argv[i],"-m") == 0)
	    print_dpmi10_meminfo();
	else if (strcmp(argv[i],"-c") == 0)
	    print_dpmi10_cap();
    }
    if (argc == 1)
	printf("\nGet help with '-?'\n");
    return 0;
}
