

extern int _AX_, _BX_, _CX_, _DX_, _SI_, _DI_;
int call_dosemu (ax)
int ax {
  _AX_ = ax;
  int86 (0xe6);
  return _AX_;
}













struct _86reg {
  unsigned int hw;
  unsigned int lw;
};


struct x86regs {
  struct _86reg eax;
  struct _86reg ebx;
  struct _86reg ecx;
  struct _86reg edx;
  struct _86reg esi;
  struct _86reg edi;
  struct _86reg flags;
  unsigned int es;
  unsigned int cs;
  unsigned int ds;
};


struct daemon_comms {
  unsigned int command;
  unsigned int arg;
  unsigned int dosbuf; 
  struct x86regs regs; 
};




struct x86regs dos86regs;
struct daemon_comms daemon_comm;

dump_regs () {
  printf ("ax = 0x%x \tbx = 0x%x \tcx = 0x%x \tdx = 0x%x\n si = 0x%x \tdi = 0x%x\n",
   _AX_, _BX_, _CX_, _DX_, _SI_, _DI_);
}
call_irq (i)
int i; {
  
  asm {
    INT 2Fh
  };
}





copy_regs_from_dosemu () {
  _AX_ = daemon_comm.regs.eax.lw;
  _BX_ = daemon_comm.regs.ebx.lw;
  _CX_ = daemon_comm.regs.ecx.lw;
  _DX_ = daemon_comm.regs.edx.lw;
  _DI_ = daemon_comm.regs.edi.lw;
  _SI_ = daemon_comm.regs.esi.lw;
  set_es (dosregs.es);
  asm {
    mov DS, DGRP:_daemon_comm.regs.ds
  }
}

copy_regs_to_dosemu() {
  dosregs.es = get_es();
  dosregs.ds = get_ds();
  daemon_comm.regs.eax.lw = _AX_;
  daemon_comm.regs.ebx.lw = _BX_;
  daemon_comm.regs.ecx.lw = _CX_;
  daemon_comm.regs.edx.lw = _DX_;
  daemon_comm.regs.esi.lw = _SI_;
  daemon_comm.regs.edi.lw = _DI_;
}

main() {
  printf ("ds = 0x%x\n", get_ds());
  printf ("&daemon_comm = 0x%x\n", daemon_comm);

  
  daemon_comm.command = 0;

  _BX_ = daemon_comm;
  call_dosemu(0x0666);

  for (;;) {
    switch (daemon_comm.command) {
     case 99:
      printf ("EXIT_DAEMON called\n");
      exit(-1);
      
     case 11:
      printf ("allocating %u bytes dos buffer memory\n", daemon_comm.arg);
      if (daemon_comm.dosbuf)
      	free (daemon_comm.dosbuf);
      daemon_comm.dosbuf = malloc (daemon_comm.arg);
      strcpy (daemon_comm.dosbuf, "hello 123");
      printf ("dosbuf = 0x%x\n", daemon_comm.dosbuf);
      daemon_comm.command = 0;
      break;
      
     case 10:
      printf ("calling irq 0x%x (%d)\n", daemon_comm.arg, daemon_comm.arg);
      dump_regs();
      copy_regs_from_dosemu();
      int86(daemon_comm.arg); 
      copy_regs_to_dosemu();

      dump_regs();
      printf ("finished irq call\n");
      daemon_comm.command = 0;
      break;
      
     case 12:
      daemon_comm.command = daemon_comm.arg;
      break;
      
     case 3:
      
      printf ("running dos for %d cycles\n", daemon_comm.arg);
      while (daemon_comm.arg--);
      daemon_comm.command = 0;
      break;
      
     default:
      daemon_comm.command = 1;
    }
    if (!daemon_comm.command)
      daemon_comm.command = 1;

    call_dosemu(0x0666);
    
  }
}
    
