#include <com32.h>
#include <stdarg.h>

#define NULL ((void *)0)
int printf(const char *, ...);
int putchar(int);

static inline void memset(void *buf, int ch, unsigned int len)
{
  asm volatile("cld; rep; stosb"
               : "+D" (buf), "+c" (len) : "a" (ch) : "memory");
}

static void strcpy(char *dst, const char *src)
{
  while ( *src )
    *dst++ = *src++;

  *dst = '\0';
}

static void printregs(const com32sys_t *r)
{
  printf("eflags = %08x  ds = %04x  es = %04x  fs = %04x  gs = %04x\n"
	 "eax = %08x  ebx = %08x  ecx = %08x  edx = %08x\n"
	 "ebp = %08x  esi = %08x  edi = %08x  esp = %08x\n",
	 r->eflags.l, r->ds, r->es, r->fs, r->gs,
	 r->eax.l, r->ebx.l, r->ecx.l, r->edx.l,
	 r->ebp.l, r->esi.l, r->edi.l, r->_unused_esp.l);
}

int __start(void)
{
  unsigned int ax,cx,si,t;
  com32sys_t  inreg,outreg;
  char *p;

  /* Test null system call */
  inreg.eflags.l = 0xffffffff;
  inreg.eax.l = 0x11110000;
  inreg.ecx.l = 0x22222222;
  inreg.edx.l = 0x33333333;
  inreg.ebx.l = 0x44444444;
  inreg.ebp.l = 0x55555555;
  inreg.esi.l = 0x66666666;
  inreg.edi.l = 0x77777777;
  inreg.ds = 0xaaaa;
  inreg.es = 0xbbbb;
  inreg.fs = 0xcccc;
  inreg.gs = 0xdddd;
  printregs(&inreg);
  __com32.cs_intcall(0x22, &inreg, &outreg);
  printregs(&outreg);
  printf("----\n");

  memset(&inreg, 0, sizeof inreg);
  memset(&outreg, 0, sizeof outreg);
  strcpy(__com32.cs_bounce, "test.txt");
  inreg.eax.w[0] = 0x0006;  // Open file
  inreg.esi.w[0] = OFFS(__com32.cs_bounce);
  inreg.es = SEG(__com32.cs_bounce);
  printregs(&inreg);
  __com32.cs_intcall(0x22, &inreg, &outreg);
  printregs(&outreg);
  printf("----\n");

  si = outreg.esi.w[0];		/* File handle */
  cx = outreg.ecx.w[0];		/* Block size */
  ax = outreg.eax.l;		/* File length */

  while ( si ) {
    /* We can only read 64K per call */
    t = ( ax > 65536 ) ? 65536/cx : (ax+cx-1)/cx;

    memset(&inreg, 0, sizeof inreg);
    inreg.esi.w[0] = si;
    inreg.ecx.w[0] = t;		/* Block count */
    inreg.eax.w[0] = 0x0007;  // Read file
    inreg.ebx.w[0] = OFFS(__com32.cs_bounce);
    inreg.es = SEG(__com32.cs_bounce);
    printregs(&inreg);
    __com32.cs_intcall(0x22, &inreg, &outreg);
    printregs(&outreg);
    printf("----\n");
    si = outreg.esi.w[0];

    /* Print the buffer */
    t = (ax < 65536) ? ax : 65536;
    p = __com32.cs_bounce;
    while ( t ) {
      putchar(*p++);
      t--;
      ax--;
    }
  }

  return 0;
}
