wok rev 17124

runcom: misc enhancements
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Sep 07 21:21:07 2014 +0200 (2014-09-07)
parents 77c872ed3f55
children 984910ac3270
files runcom/stuff/runcom.c
line diff
     1.1 --- a/runcom/stuff/runcom.c	Sat Sep 06 22:48:52 2014 +0300
     1.2 +++ b/runcom/stuff/runcom.c	Sun Sep 07 21:21:07 2014 +0200
     1.3 @@ -13,10 +13,13 @@
     1.4  #include <sys/time.h>
     1.5  #include <sys/types.h>
     1.6  #include <sys/stat.h>
     1.7 +#include <sys/statfs.h>
     1.8  #include <signal.h>
     1.9  #include <errno.h>
    1.10  #include <ctype.h>
    1.11  #include <termios.h>
    1.12 +#include <dirent.h>
    1.13 +#include <fnmatch.h>
    1.14  
    1.15  #include <sys/syscall.h>
    1.16  #include <asm/vm86.h>
    1.17 @@ -87,6 +90,9 @@
    1.18      fprintf(stderr,"\n");
    1.19  }
    1.20  
    1.21 +static int argflags;
    1.22 +#define DEBUG 1
    1.23 +
    1.24  #define DOS_FD_MAX 256
    1.25  typedef struct {
    1.26      int fd; /* -1 means closed */
    1.27 @@ -94,6 +100,8 @@
    1.28  
    1.29  DOSFile dos_files[DOS_FD_MAX];
    1.30  uint16_t cur_psp;
    1.31 +uint16_t cur_dta_seg;
    1.32 +uint16_t cur_dta_ofs;
    1.33  
    1.34  void dos_init(void)
    1.35  {
    1.36 @@ -155,6 +163,8 @@
    1.37          offset++;
    1.38      }
    1.39      *q = '\0';
    1.40 +    if (buf[1] == ':')
    1.41 +    	strcpy(buf, buf+2);
    1.42      return buf;
    1.43  } 
    1.44  
    1.45 @@ -163,6 +173,15 @@
    1.46      return get_filename1(r, buf, buf_size, r->ds, r->edx & 0xffff);
    1.47  }
    1.48  
    1.49 +static char *upcase(const char *s)
    1.50 +{
    1.51 +    static char buffer[80];
    1.52 +    int i;
    1.53 +    for (i = 0; i < sizeof(buffer)-1; i++, s++)
    1.54 +	buffer[i] = (*s >= 'a' && *s <= 'z') ? *s + 'A' - 'a' : *s;
    1.55 +    return buffer;
    1.56 +}
    1.57 +
    1.58  typedef struct __attribute__((packed)) {
    1.59      uint8_t drive_num;
    1.60      uint8_t file_name[8];
    1.61 @@ -187,6 +206,22 @@
    1.62      uint16_t ip, cs;
    1.63  } ExecParamBlock;
    1.64  
    1.65 +typedef struct __attribute__((packed)) {
    1.66 +    /* internals */
    1.67 +	uint8_t attr;		/* 00 */
    1.68 +	uint8_t drive_letter;	/* 01 */
    1.69 +	uint8_t template[11];	/* 02 */
    1.70 +	uint16_t entry_count;	/* 0D */
    1.71 +	uint32_t dta_address;	/* 0F */
    1.72 +	uint16_t cluster_parent_dir;	/* 13 */
    1.73 +    /* output */
    1.74 +	uint8_t attr_found;	/* 15 */
    1.75 +	uint16_t file_time;	/* 16 */
    1.76 +	uint16_t file_date;	/* 18 */
    1.77 +	uint32_t file_size;	/* 1A */
    1.78 +	uint8_t filename[13];	/* 1E */
    1.79 +} dirdta;
    1.80 +
    1.81  typedef struct MemBlock {
    1.82      struct MemBlock *next;
    1.83      uint16_t seg;
    1.84 @@ -340,7 +375,8 @@
    1.85      header.min_extra_paragraphs += (size-1)/16;
    1.86      
    1.87      /* address of last segment allocated */
    1.88 -    *(uint16_t *)seg_to_linear(psp, 2) = psp + header.min_extra_paragraphs;
    1.89 +    //*(uint16_t *)seg_to_linear(psp, 2) = psp + header.min_extra_paragraphs;
    1.90 +    *(uint16_t *)seg_to_linear(psp, 2) = 0x9fff;
    1.91      
    1.92      if (pfile_size)
    1.93          *pfile_size = size;
    1.94 @@ -378,6 +414,8 @@
    1.95  
    1.96      /* load the MSDOS .com executable */
    1.97      fd = open(filename, O_RDONLY);
    1.98 +    if (fd < 0)
    1.99 +        fd = open(upcase(filename), O_RDONLY);
   1.100      if (fd < 0) {
   1.101          return -1;
   1.102      }
   1.103 @@ -394,10 +432,10 @@
   1.104      /* reset the PSP */
   1.105      memset(seg_to_linear(psp, 0), 0, 0x100);
   1.106  
   1.107 -    *seg_to_linear(psp, 0) = 0xcd; /* int $0x20 */
   1.108 -    *seg_to_linear(psp, 1) = 0x20;
   1.109 +    * (uint16_t *) seg_to_linear(psp, 0) = 0x20CD; /* int $0x20 */
   1.110      /* address of last segment allocated */
   1.111 -    *(uint16_t *)seg_to_linear(psp, 2) = psp + 0xfff;
   1.112 +    //*(uint16_t *)seg_to_linear(psp, 2) = psp + 0xfff;
   1.113 +    *(uint16_t *)seg_to_linear(psp, 2) = 0x9fff;
   1.114  
   1.115      if (argc) {
   1.116          int i, p;
   1.117 @@ -499,18 +537,98 @@
   1.118      }
   1.119  }
   1.120  
   1.121 +#define ESC "\033"
   1.122  void do_int10(struct vm86_regs *r)
   1.123  {
   1.124      uint8_t ah;
   1.125 +    char buf[20];
   1.126 +    static unsigned cursorlines = 0x0607;
   1.127 +    static unsigned activepage = 0;
   1.128 +    static uint8_t cursrow, curscol;
   1.129      
   1.130      ah = (r->eax >> 8);
   1.131      switch(ah) {
   1.132 +    case 0x02: /* set cursor position (BH == page number) */
   1.133 +        cursrow = r->edx >> 8;
   1.134 +        curscol = r->edx;
   1.135 +        * (uint16_t *) seg_to_linear(0x40, 0x50 + 2*((r->ebx >> 8) & 0xFF)) = r->edx;
   1.136 +	sprintf(buf,ESC"[%u;%uH",cursrow + 1, curscol + 1);
   1.137 +	write(1, buf, strlen(buf));
   1.138 +        break;
   1.139 +    case 0x03: /* get cursor position (BH == page number) */
   1.140 +	r->eax = 0;
   1.141 +	r->ecx = cursorlines;
   1.142 +	r->edx &= ~0xFFFF;
   1.143 +        r->edx |= * (uint16_t *) seg_to_linear(0x40, 0x50 + 2*((r->ebx >> 8) & 0xFF));
   1.144 +	sprintf(buf,ESC"[%u;%uH",cursrow + 1, curscol + 1);
   1.145 +	write(1, buf, strlen(buf));
   1.146 +        break;
   1.147 +    case 0x05: /* set active page */
   1.148 +	activepage = r->eax & 0xFF;
   1.149 +        break;
   1.150 +    case 0x06: /* scroll up */
   1.151 +    case 0x07: /* scroll down */
   1.152 +	{
   1.153 +	    int i = r->eax & 0xFF;
   1.154 +	    if (i == 0) i = 50;
   1.155 +    	/* FIXME assume full row, ignore colums in CL, DL */
   1.156 +	    sprintf(buf,ESC"[%u;%ur",1+(r->ecx >> 8) & 0xFF, 1+(r->edx >> 8) & 0xFF);
   1.157 +	    write(1, buf, strlen(buf));
   1.158 +	    buf[2] = (ah != 6) ? 'T' : 'S';
   1.159 +	    while (i--) write(1,buf,3);
   1.160 +	}
   1.161 +        break;
   1.162 +    case 0x09: /* write char and attribute at cursor position (BH == page number) */
   1.163 +        {
   1.164 +            static char color[8] = "04261537";
   1.165 +            char extra[5], *s = extra;
   1.166 +            uint8_t c = r->eax;
   1.167 +            uint16_t n = r->ecx;
   1.168 +            int i;
   1.169 +
   1.170 +	    if (r->ebx & 0x8) { *s++ = '1'; *s++ = ';'; } // bold
   1.171 +	    if (r->ebx & 0x80) { *s++ = '5'; *s++ = ';'; } // blink
   1.172 +	    *s = 0;
   1.173 +	    sprintf(buf,ESC"[0;%s4%c;3%cm",extra,
   1.174 +	    	   color[(r->ebx & 0x70) >> 4],color[r->ebx & 0x7]);
   1.175 +	    write(1, buf, strlen(buf));
   1.176 +            for (i = 0; i < n; i++) 
   1.177 +		write(1, &c, 1);
   1.178 +	    write(1, ESC"[0m", 4); /* restore attributes */
   1.179 +        }
   1.180 +        break;
   1.181      case 0x0E: /* write char */
   1.182          {
   1.183              uint8_t c = r->eax;
   1.184              write(1, &c, 1);
   1.185          }
   1.186          break;
   1.187 +    case 0x0F: /* get current video mode */
   1.188 +        {
   1.189 +	    r->eax &= ~0xFFFF;
   1.190 +	    r->eax |= 0x5003; /* color or 5007 mono */
   1.191 +	    r->ebx &= ~0xFF00;
   1.192 +	    r->ebx |= activepage << 8;
   1.193 +        }
   1.194 +        break;
   1.195 +    case 0x11: /* get window coordonates  */
   1.196 +        r->ecx &= ~0xFFFF;
   1.197 +        r->edx &= ~0xFFFF;
   1.198 +        r->edx |= ~0x1950; /* 80x25 */
   1.199 +        break;
   1.200 +    case 0x12: /* get blanking attribute (for scroll) */
   1.201 +        r->ebx &= ~0xFF00;
   1.202 +        break;
   1.203 +    case 0x1A: /* get display combination code */
   1.204 +#if 0
   1.205 +        set_error(r, 1);
   1.206 +#else
   1.207 +        r->eax &= ~0xFF;
   1.208 +        r->eax |= ~0x1A;
   1.209 +        r->ebx &= ~0xFFFF;
   1.210 +        r->ebx |= ~0x0202; // CGA + color display
   1.211 +#endif
   1.212 +        break;
   1.213      default:
   1.214          unsupported_function(r, 0x10, ah);
   1.215      }
   1.216 @@ -684,6 +802,8 @@
   1.217  void do_int21(struct vm86_regs *r)
   1.218  {
   1.219      uint8_t ah;
   1.220 +    DIR *dirp;
   1.221 +    dirdta *dta;
   1.222      
   1.223      ah = (r->eax >> 8);
   1.224      switch(ah) {
   1.225 @@ -695,6 +815,11 @@
   1.226              write(1, &c, 1);
   1.227          }
   1.228          break;
   1.229 +    case 0x08: /* read stdin */
   1.230 +        {
   1.231 +            read(0,&r->eax,1);
   1.232 +        }
   1.233 +        break;
   1.234      case 0x09: /* write string */
   1.235          {
   1.236              uint8_t c;
   1.237 @@ -738,6 +863,34 @@
   1.238              *seg_to_linear(r->ds, off + 2 + cur_len) = '\r';
   1.239          }
   1.240          break;
   1.241 +    case 0x0b: /* get stdin status */
   1.242 +        {
   1.243 +	    r->eax &= ~0xFF; /* no character available */
   1.244 +        }
   1.245 +        break;
   1.246 +    case 0x0d: /* disk reset */
   1.247 +        {
   1.248 +            sync();
   1.249 +        }
   1.250 +        break;
   1.251 +    case 0x0e: /* select default disk */
   1.252 +        {
   1.253 +            r->eax &= ~0xFF;
   1.254 +            r->eax |= 3; /* A: B: & C: valid */
   1.255 +        }
   1.256 +        break;
   1.257 +    case 0x19: /* get current default drive */
   1.258 +        {
   1.259 +	    r->eax &= ~0xFF;
   1.260 +	    r->eax |= 2; /* C: */
   1.261 +        }
   1.262 +        break;
   1.263 +    case 0x1a: /* set DTA (disk transfert address) */
   1.264 +        {
   1.265 +	    cur_dta_seg = r->ds;
   1.266 +	    cur_dta_ofs = r->edx;
   1.267 +        }
   1.268 +        break;
   1.269      case 0x25: /* set interrupt vector */
   1.270          {
   1.271              uint16_t *ptr;
   1.272 @@ -851,6 +1004,12 @@
   1.273              r->edx = (tim.tv_sec * 256) + tim.tv_usec/10000;
   1.274          }
   1.275          break;
   1.276 +    case 0x2f: /* get DTA (disk transfert address */
   1.277 +        {
   1.278 +	    r->es = cur_dta_seg;
   1.279 +	    r->ebx = cur_dta_ofs;
   1.280 +        }
   1.281 +        break;
   1.282      case 0x30: /* get dos version */
   1.283          {
   1.284              int major, minor, serial, oem;
   1.285 @@ -864,6 +1023,11 @@
   1.286              r->ebx = (r->ebx & ~0xffff) | (serial & 0xff) | (0x66 << 8);
   1.287          }
   1.288          break;
   1.289 +    case 0x33: /* extended break checking */
   1.290 +        {
   1.291 +	    r->edx &= ~0xFFFF;
   1.292 +        }
   1.293 +        break;
   1.294      case 0x35: /* get interrupt vector */
   1.295          {
   1.296              uint16_t *ptr;
   1.297 @@ -872,6 +1036,25 @@
   1.298              r->es = ptr[1];
   1.299          }
   1.300          break;
   1.301 +    case 0x36: /* get free disk space */
   1.302 +        {
   1.303 +            struct statfs buf;
   1.304 +            
   1.305 +            if (statfs(".", &buf)) {
   1.306 +		r->eax |= 0xFFFF;
   1.307 +            }
   1.308 +            else {
   1.309 +		r->eax &= ~0xFFFF;
   1.310 +		r->eax |= buf.f_bsize / 512; /* sectors per cluster */
   1.311 +		r->ebx &= ~0xFFFF;
   1.312 +		r->ebx |= buf.f_bavail;
   1.313 +		r->ecx &= ~0xFFFF;
   1.314 +		r->ecx |= 512; /* bytes per sector */
   1.315 +		r->edx &= ~0xFFFF;
   1.316 +		r->edx |= buf.f_blocks;
   1.317 +            }
   1.318 +        }
   1.319 +        break;
   1.320      case 0x37: 
   1.321          {
   1.322              switch(r->eax & 0xff) {
   1.323 @@ -884,6 +1067,15 @@
   1.324              }
   1.325          }
   1.326          break;
   1.327 +    case 0x3B: 
   1.328 +        {
   1.329 +            char filename[1024];
   1.330 +        
   1.331 +            get_filename(r, filename, sizeof(filename));
   1.332 +            if (chdir(filename))
   1.333 +                set_error(r, 0x03); /* path not found */
   1.334 +        }
   1.335 +        break;
   1.336      case 0x3c: /* create or truncate file */
   1.337          {
   1.338              char filename[1024];
   1.339 @@ -899,6 +1091,8 @@
   1.340                  else
   1.341                      flags = 0777;
   1.342                  fd = open(filename, O_RDWR | O_TRUNC | O_CREAT, flags);
   1.343 +                if (fd < 0)
   1.344 +                    fd = open(upcase(filename), O_RDWR | O_TRUNC | O_CREAT, flags);
   1.345  #ifdef DUMP_INT21
   1.346                  printf("int21: create: file='%s' cx=0x%04x ret=%d\n", 
   1.347                         filename, (int)(r->ecx & 0xffff), h);
   1.348 @@ -923,11 +1117,9 @@
   1.349                  set_error(r, 0x04); /* too many open files */
   1.350              } else {
   1.351                  get_filename(r, filename, sizeof(filename));
   1.352 -#ifdef DUMP_INT21
   1.353 -                printf("int21: open: file='%s' al=0x%02x ret=%d\n", 
   1.354 -                       filename, (int)(r->eax & 0xff), h);
   1.355 -#endif
   1.356                  fd = open(filename, r->eax & 3);
   1.357 +                if (fd < 1)
   1.358 +                    fd = open(upcase(filename), r->eax & 3);
   1.359                  if (fd < 0) {
   1.360                      set_error(r, 0x02); /* file not found */
   1.361                  } else {
   1.362 @@ -1031,7 +1223,7 @@
   1.363          {
   1.364              char filename[1024];
   1.365              get_filename(r, filename, sizeof(filename));
   1.366 -            if (unlink(filename) < 0) {
   1.367 +            if (unlink(filename) < 0 && unlink(upcase(filename))) {
   1.368                  set_error(r, 0x02); /* file not found */
   1.369              } else {
   1.370                  set_error(r, 0);
   1.371 @@ -1062,6 +1254,20 @@
   1.372              }
   1.373          }
   1.374          break;
   1.375 +    case 0x43: /* get attribute */
   1.376 +        {
   1.377 +	    struct stat statbuf;
   1.378 +            char filename[1024];
   1.379 +            get_filename(r, filename, sizeof(filename));
   1.380 +            if (stat(filename, &statbuf) && stat(upcase(filename), &statbuf)) {
   1.381 +		set_error(r, 5);
   1.382 +            }
   1.383 +            else {
   1.384 +            	r->ecx &= ~0xFFFF;
   1.385 +		if (S_ISDIR(statbuf.st_mode)) r->ecx |= 0x10;
   1.386 +            }
   1.387 +        }
   1.388 +        break;
   1.389      case 0x44: /* ioctl */
   1.390          switch(r->eax & 0xff) {
   1.391          case 0x00: /* get device information */
   1.392 @@ -1084,11 +1290,23 @@
   1.393                      set_error(r, 0);
   1.394                  }
   1.395              }
   1.396 +        case 0x01: /* set device information */
   1.397              break;
   1.398          default:
   1.399              goto unsupported;
   1.400          }
   1.401          break;
   1.402 +    case 0x47: /* get current directory (DL drive)*/
   1.403 +        {
   1.404 +            char *s = seg_to_linear(r->ds, r->esi);
   1.405 +            getcwd(s,64);
   1.406 +            strcpy(s,s+1);
   1.407 +            while (*s)
   1.408 +        	if (*s++ == '/')
   1.409 +        	    s[-1] = '\\';
   1.410 +            r->eax = 0x100;
   1.411 +        }
   1.412 +        break;
   1.413      case 0x48: /* allocate memory */
   1.414          {
   1.415              int ret, max_size;
   1.416 @@ -1144,10 +1362,13 @@
   1.417              get_filename(r, filename, sizeof(filename));
   1.418              blk = (ExecParamBlock *)seg_to_linear(r->es, r->ebx);
   1.419              ret = load_com(blk, filename, NULL, 0, NULL);
   1.420 +            if (ret < 0)
   1.421 +                ret = load_com(blk, upcase(filename), NULL, 0, NULL);
   1.422              if (ret < 0) {
   1.423                  set_error(r, 0x02); /* file not found */
   1.424              } else {
   1.425 -                cur_psp = ret;
   1.426 +                cur_dta_seg = cur_psp = ret;
   1.427 +                cur_dta_ofs = 0x80;
   1.428                  set_error(r, 0);
   1.429              }
   1.430          }
   1.431 @@ -1155,6 +1376,53 @@
   1.432      case 0x4c: /* exit with return code */
   1.433          exit(r->eax & 0xff);
   1.434          break;
   1.435 +    case 0x4e: /* find first matching file */
   1.436 +// TODO AL input support
   1.437 +	dirp = opendir(".");
   1.438 +	if (dirp == NULL) {
   1.439 +		set_error(r, (errno == ENOTDIR) ? 0x03 /* path not found */
   1.440 +						: 0x02 /* file not found */ );
   1.441 +		goto pattern_found;		
   1.442 +	}
   1.443 +	else {
   1.444 +		struct dirent *dp;
   1.445 +		char *s;
   1.446 +		
   1.447 +		dta = (dirdta *) seg_to_linear(cur_dta_seg, cur_dta_ofs);
   1.448 +		dta->attr = r->ecx;
   1.449 +    		* (DIR **) &dta->entry_count = dirp;
   1.450 +    		s = seg_to_linear(r->ds, r->edx);
   1.451 +    		if (s[1] == ':') s+= 2;
   1.452 +    		if (s[0] == '\\') s++;
   1.453 +		strncpy(dta->template, s, 11);
   1.454 +        // NO break;
   1.455 +    case 0x4f: /* find next matching file */
   1.456 +		dta = (dirdta *) seg_to_linear(cur_dta_seg, cur_dta_ofs);
   1.457 +    		dirp = * (DIR **) &dta->entry_count;
   1.458 +		while ((dp = readdir(dirp)) != NULL) {
   1.459 +			if (!fnmatch(dta->template, dp->d_name, 0)) {
   1.460 +				struct stat statbuf;
   1.461 +				
   1.462 +				r->eflags &= ~CF_MASK;
   1.463 +				strncpy(dta->filename, dp->d_name, 13);
   1.464 +				stat(dp->d_name, &statbuf);
   1.465 +				dta->file_size = statbuf.st_size;
   1.466 +				dta->file_date = 0; //DOSDATE(statbuf.st_mtime);
   1.467 +				dta->file_time = 0; //DOSIME(statbuf.st_mtime);
   1.468 +				dta->attr_found = S_ISDIR(statbuf.st_mode) ?
   1.469 +					0x10 /*aDvshr*/ : 0x20 /*Advshr*/;
   1.470 +#if 0
   1.471 +				if ((dta->attr_found ^ dta->attr) & 0x16)
   1.472 +					continue;
   1.473 +#endif
   1.474 +				goto pattern_found;		
   1.475 +			}
   1.476 +		}
   1.477 +	}
   1.478 +	closedir(dirp);
   1.479 +	set_error(r, 0x12 /* no more files */);
   1.480 +pattern_found:
   1.481 +        break;
   1.482      case 0x50: /* set PSP address */
   1.483  #ifdef DUMP_INT21
   1.484          printf("int21: set PSP: 0x%04x\n", (uint16_t)r->ebx);
   1.485 @@ -1182,6 +1450,11 @@
   1.486              r->eax = (r->eax & ~0xff);
   1.487          }
   1.488          break;
   1.489 +    case 0x56: /* rename file (CL attribute mask) */
   1.490 +        if (rename((char *) seg_to_linear(r->ds, r->edx),
   1.491 +	           (char *) seg_to_linear(r->es, r->edi)))
   1.492 +	    set_error(r, 0x5 /* access denied or 2,3,0x11 */);
   1.493 +        break;
   1.494      default:
   1.495      unsupported:
   1.496          unsupported_function(r, 0x21, ah);
   1.497 @@ -1194,26 +1467,45 @@
   1.498      write(1, &c, 1);
   1.499  }
   1.500  
   1.501 +static int int8pending;
   1.502 +
   1.503  void raise_interrupt(int number)
   1.504  {
   1.505      if (* (uint32_t *) seg_to_linear(0, number * 4) == 0)
   1.506          return;
   1.507 -    // FIXME VM86_SIGNAL
   1.508 +    int8pending++;
   1.509  }
   1.510  
   1.511  void biosclock()
   1.512  {
   1.513 -    uint32_t *timer = (uint32_t *) seg_to_linear(0, 0x46C);
   1.514 -    ++*timer;
   1.515 +    //uint32_t *timer = (uint32_t *) seg_to_linear(0, 0x46C);
   1.516 +    //++*timer;
   1.517      raise_interrupt(8);
   1.518 -    raise_interrupt(0x1C);
   1.519 +    //raise_interrupt(0x1C);
   1.520 +}
   1.521 +
   1.522 +static void exec_int(struct vm86_regs *r, unsigned num)
   1.523 +{
   1.524 +    uint16_t *int_vector;
   1.525 +    uint32_t eflags;
   1.526 +
   1.527 +    eflags = r->eflags & ~IF_MASK;
   1.528 +    if (r->eflags & VIF_MASK)
   1.529 +        eflags |= IF_MASK;
   1.530 +    pushw(r, eflags);
   1.531 +    pushw(r, r->cs);
   1.532 +    pushw(r, r->eip);
   1.533 +    int_vector = (uint16_t *)seg_to_linear(0, num * 4);
   1.534 +    r->eip = int_vector[0];
   1.535 +    r->cs = int_vector[1];
   1.536 +    r->eflags &= ~(VIF_MASK | TF_MASK | AC_MASK);
   1.537  }
   1.538  
   1.539  int main(int argc, char **argv)
   1.540  {
   1.541      uint8_t *vm86_mem;
   1.542      const char *filename;
   1.543 -    int ret;
   1.544 +    int i, ret;
   1.545      uint32_t file_size;
   1.546      struct sigaction sa; 
   1.547      struct itimerval timerval;
   1.548 @@ -1221,6 +1513,16 @@
   1.549      struct vm86_regs *r;
   1.550      ExecParamBlock blk1, *blk = &blk1;
   1.551  
   1.552 +    for (argflags = 0; *argv[1] == '-'; argv++) {
   1.553 +    	char *s = argv[1];
   1.554 +
   1.555 +    	while (1)
   1.556 +    	switch (*++s) {
   1.557 +    	case 'd' : argflags |= DEBUG; break;
   1.558 +    	case 0 : goto nextargv;
   1.559 +    	}
   1.560 +nextargv:;
   1.561 +    }
   1.562      if (argc < 2)
   1.563          usage();
   1.564      filename = argv[1];
   1.565 @@ -1253,7 +1555,8 @@
   1.566              perror(filename);
   1.567              exit(1);
   1.568          }
   1.569 -        cur_psp = ret;
   1.570 +        cur_dta_seg = cur_psp = ret;
   1.571 +        cur_dta_ofs = 0x80;
   1.572  
   1.573          /* init basic registers */
   1.574          r->eip = blk->ip;
   1.575 @@ -1291,6 +1594,13 @@
   1.576          timerval.it_interval.tv_usec = timerval.it_value.tv_usec = 10000000 / 182;
   1.577          setitimer (ITIMER_REAL, &timerval, NULL);
   1.578      }
   1.579 +    *(uint8_t *)seg_to_linear(0xF000, 0) = 0xCF;
   1.580 +    for (i = 0; i < 16; i++) 
   1.581 +	*(uint32_t *)seg_to_linear(0, i * 4) = 0xF0000000;
   1.582 +    *(uint32_t *)seg_to_linear(0, 0x18 * 4) = 0xF0000000; /* Basic */
   1.583 +    *(uint32_t *)seg_to_linear(0, 0x1B * 4) = 0xF0000000; /* Keyboard Ctrl-Break */
   1.584 +    *(uint32_t *)seg_to_linear(0, 0x23 * 4) = 0xF0000000; /* DOS Ctrl-Break */
   1.585 +    *(uint32_t *)seg_to_linear(0, 0x24 * 4) = 0xF0000000; /* Critical error */
   1.586  
   1.587      for(;;) {
   1.588          ret = vm86(VM86_ENTER, &ctx);
   1.589 @@ -1300,6 +1610,9 @@
   1.590                  int int_num;
   1.591  
   1.592                  int_num = VM86_ARG(ret);
   1.593 +		if (argflags & 1)
   1.594 +			fprintf(stderr,"Int%02X: CS:IP=%04X:%04X AX=%04X\n",
   1.595 +				int_num, r->cs, r->eip, r->eax);
   1.596                  switch(int_num) {
   1.597                  case 0x10:
   1.598                      do_int10(r);
   1.599 @@ -1334,27 +1647,32 @@
   1.600              break;
   1.601          case VM86_SIGNAL:
   1.602              /* a signal came, we just ignore that */
   1.603 +            if (int8pending) {
   1.604 +		int8pending--;
   1.605 +		exec_int(r, 8);
   1.606 +            }
   1.607              break;
   1.608          case VM86_STI:
   1.609              break;
   1.610          case VM86_TRAP:
   1.611              /* just executes the interruption */
   1.612 -            {
   1.613 -                uint16_t *int_vector;
   1.614 -                uint32_t eflags;
   1.615 -                
   1.616 -                eflags = r->eflags & ~IF_MASK;
   1.617 -                if (r->eflags & VIF_MASK)
   1.618 -                    eflags |= IF_MASK;
   1.619 -                pushw(r, eflags);
   1.620 -                pushw(r, r->cs);
   1.621 -                pushw(r, r->eip);
   1.622 -                int_vector = (uint16_t *)seg_to_linear(0, VM86_ARG(ret) * 4);
   1.623 -                r->eip = int_vector[0];
   1.624 -                r->cs = int_vector[1];
   1.625 -                r->eflags &= ~(VIF_MASK | TF_MASK | AC_MASK);
   1.626 +            exec_int(r, VM86_ARG(ret));
   1.627 +            break;
   1.628 +        case VM86_UNKNOWN:
   1.629 +            switch ( *(uint8_t *)seg_to_linear(r->cs, r->eip) ) {
   1.630 +            case 0xE4: /* inx portb,al */
   1.631 +            case 0xE5: /* in portb,ax */
   1.632 +            case 0xE6: /* out al,portb */
   1.633 +            case 0xE7: /* out ax,portb */
   1.634 +            	r->eip += 2;
   1.635 +            	continue;
   1.636 +            case 0xEC: /* in dx,al */
   1.637 +            case 0xED: /* in dx,ax */
   1.638 +            case 0xEE: /* out al,dx */
   1.639 +            case 0xEF: /* out ax,dx */
   1.640 +            	r->eip++;
   1.641 +            	continue;
   1.642              }
   1.643 -            break;
   1.644          default:
   1.645              fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret);
   1.646              dump_regs(&ctx.regs);