fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 470 lines 9.1 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/arch/dos/dos.c * 7 * Created: 2012-12-30 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2012-2017 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include "main.h" 24#include "dos.h" 25#include "dosmem.h" 26#include "int.h" 27 28#include <cpu/e8086/e8086.h> 29 30#include <ctype.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34 35 36#define DEBUG_MEM 0 37 38 39static 40unsigned char sim_get_mem8 (void *ext, unsigned long addr) 41{ 42 dos_t *sim = ext; 43 44#if DEBUG_MEM 45 if (addr < 0x60) { 46 fprintf (stderr, "get 8: %04lX\n", addr); 47 } 48#endif 49 50 if (addr < sim->mem_cnt) { 51 return (sim->mem[addr]); 52 } 53 54 return (0); 55} 56 57static 58unsigned short sim_get_mem16 (void *ext, unsigned long addr) 59{ 60 unsigned short val; 61 dos_t *sim = ext; 62 63#if DEBUG_MEM 64 if (addr < 0x60) { 65 fprintf (stderr, "get 16: %04lX\n", addr); 66 } 67#endif 68 69 if ((addr + 1) < sim->mem_cnt) { 70 return (((unsigned) sim->mem[addr + 1] << 8) | sim->mem[addr]); 71 } 72 73 val = (sim_get_mem8 (sim, addr + 1) << 8) | sim_get_mem8 (sim, addr); 74 75 return (val); 76} 77 78static 79void sim_set_mem8 (void *ext, unsigned long addr, unsigned char val) 80{ 81 dos_t *sim = ext; 82 83#if DEBUG_MEM 84 if (addr < 0x60) { 85 fprintf (stderr, "set 8: %04lX\n", addr); 86 } 87#endif 88 89 if (addr < sim->mem_cnt) { 90 sim->mem[addr] = val; 91 } 92} 93 94static 95void sim_set_mem16 (void *ext, unsigned long addr, unsigned short val) 96{ 97 dos_t *sim = ext; 98 99#if DEBUG_MEM 100 if (addr < 0x60) { 101 fprintf (stderr, "set 16: %04lX\n", addr); 102 } 103#endif 104 105 if (addr < sim->mem_cnt) { 106 sim->mem[addr] = val & 0xff; 107 } 108 109 if ((addr + 1) < sim->mem_cnt) { 110 sim->mem[addr + 1] = (val >> 8) & 0xff; 111 } 112} 113 114static 115unsigned char sim_get_port8 (void *ext, unsigned long addr) 116{ 117 if (addr == 0x21) { 118 return (0); 119 } 120 121 fprintf (stderr, "unknown port8 read: %04lX\n", addr); 122 exit (1); 123 124 return (0); 125} 126 127static 128unsigned short sim_get_port16 (void *ext, unsigned long addr) 129{ 130 fprintf (stderr, "unknown port16 read: %04lX\n", addr); 131 exit (1); 132 133 return (0); 134} 135 136static 137void sim_set_port8 (void *ext, unsigned long addr, unsigned char val) 138{ 139 fprintf (stderr, "unknown port8 write: %04lX <- %02X\n", addr, val); 140 exit (1); 141} 142 143static 144void sim_set_port16 (void *ext, unsigned long addr, unsigned short val) 145{ 146 fprintf (stderr, "unknown port16 write: %04lX <- %04X\n", addr, val); 147 exit (1); 148} 149 150unsigned char sim_get_uint8 (dos_t *sim, unsigned short seg, unsigned short ofs) 151{ 152 unsigned long addr; 153 154 addr = ((unsigned long) seg << 4) + ofs; 155 156 return (sim_get_mem8 (sim, addr)); 157} 158 159unsigned short sim_get_uint16 (dos_t *sim, unsigned short seg, unsigned short ofs) 160{ 161 unsigned long addr; 162 163 addr = ((unsigned long) seg << 4) + ofs; 164 165 return (sim_get_mem16 (sim, addr)); 166} 167 168void sim_set_uint8 (dos_t *sim, unsigned short seg, unsigned short ofs, unsigned char val) 169{ 170 unsigned long addr; 171 172 addr = ((unsigned long) seg << 4) + ofs; 173 174 sim_set_mem8 (sim, addr, val); 175} 176 177void sim_set_uint16 (dos_t *sim, unsigned short seg, unsigned short ofs, unsigned short val) 178{ 179 unsigned long addr; 180 181 addr = ((unsigned long) seg << 4) + ofs; 182 183 sim_set_mem16 (sim, addr, val); 184} 185 186int sim_get_asciiz (dos_t *sim, unsigned short seg, unsigned short ofs, char *dst, unsigned max) 187{ 188 unsigned i; 189 190 for (i = 0; i < max; i++) { 191 if ((dst[i] = sim_get_uint8 (sim, seg, ofs)) == 0) { 192 break; 193 } 194 195 ofs = (ofs + 1) & 0xffff; 196 } 197 198 if (i >= max) { 199 return (1); 200 } 201 202 dst[i] = 0; 203 204 return (0); 205} 206 207void sim_print_state_cpu (dos_t *sim, FILE *fp) 208{ 209 e8086_t *c; 210 211 c = &sim->cpu; 212 213 fprintf (fp, 214 "%04X:%04X AX=%04X BX=%04X CX=%04X DX=%04X " 215 "BP=%04X SI=%04X:%04X DI=%04X:%04X " 216 "SP=%04X:%04X F=%04X", 217 e86_get_cs (c), e86_get_ip (c), 218 e86_get_ax (c), e86_get_bx (c), e86_get_cx (c), e86_get_dx (c), 219 e86_get_bp (c), 220 e86_get_ds (c), e86_get_si (c), 221 e86_get_es (c), e86_get_di (c), 222 e86_get_ss (c), e86_get_sp (c), 223 c->flg 224 ); 225 226 fprintf (fp, 227 "[%c%c%c%c%c%c%c%c]", 228 e86_get_if (c) ? 'I' : '-', 229 e86_get_df (c) ? 'D' : '-', 230 e86_get_of (c) ? 'O' : '-', 231 e86_get_sf (c) ? 'S' : '-', 232 e86_get_zf (c) ? 'Z' : '-', 233 e86_get_af (c) ? 'A' : '-', 234 e86_get_pf (c) ? 'P' : '-', 235 e86_get_cf (c) ? 'C' : '-' 236 ); 237 238 if (e86_get_halt (c)) { 239 fprintf (fp, " HALT=1"); 240 } 241 242 fputc ('\n', fp); 243 244 fflush (fp); 245} 246 247int sim_set_drive (dos_t *sim, unsigned drive, const char *path) 248{ 249 unsigned n; 250 251 if (drive >= sim->drive_cnt) { 252 return (1); 253 } 254 255 if (sim->drive[drive] != NULL) { 256 free (sim->drive[drive]); 257 } 258 259 n = strlen (path); 260 261 if ((sim->drive[drive] = malloc (n + 1)) == NULL) { 262 return (1); 263 } 264 265 strcpy (sim->drive[drive], path); 266 267 return (0); 268} 269 270int sim_init_env (dos_t *sim, const char *prog, const unsigned char *env, unsigned envcnt) 271{ 272 unsigned i, n; 273 unsigned para; 274 275 n = envcnt + 4 + strlen (prog); 276 277 para = (n + 15) >> 4; 278 para += 1; 279 280 sim->env = sim_mem_alloc (sim, para, para); 281 282 if (sim->env == 0) { 283 return (1); 284 } 285 286 for (i = 0; i < envcnt; i++) { 287 sim_set_uint8 (sim, sim->env, i, env[i]); 288 } 289 290 sim_set_uint16 (sim, sim->env, envcnt + 0, 0); 291 sim_set_uint16 (sim, sim->env, envcnt + 2, 0x0001); 292 293 i = 0; 294 while (prog[i] != 0) { 295 sim_set_uint8 (sim, sim->env, envcnt + 4 + i, prog[i]); 296 i += 1; 297 } 298 299 sim_set_uint8 (sim, sim->env, envcnt + 4 + i, 0); 300 301 return (0); 302} 303 304void sim_init_psp (dos_t *sim) 305{ 306 unsigned i; 307 308 for (i = 0; i < 256; i++) { 309 sim_set_uint8 (sim, sim->psp, i, 0); 310 } 311 312 sim_set_uint16 (sim, sim->psp, 0x0000, 0x20cd); 313 sim_set_uint16 (sim, sim->psp, 0x0002, sim->psp + sim_get_uint16 (sim, sim->psp - 1, 3)); 314 sim_set_uint16 (sim, sim->psp, 0x002c, sim->env); 315} 316 317int sim_init_args (dos_t *sim, const char **argv) 318{ 319 unsigned i; 320 unsigned char c; 321 int ispath; 322 const char *s; 323 324 i = 0; 325 326 while (*argv != NULL) { 327 s = *argv; 328 329 if (i > 0) { 330 sim_set_uint8 (sim, sim->psp, 0x81 + i, ' '); 331 332 if ((i += 1) > 127) { 333 return (1); 334 } 335 } 336 337 ispath = 0; 338 339 while (*s != 0) { 340 while (*s == '%') { 341 s += 1; 342 343 if (*s == '%') { 344 break; 345 } 346 347 ispath = !ispath; 348 } 349 350 c = *s; 351 352 if (ispath) { 353 if (c == '/') { 354 c = '\\'; 355 } 356 } 357 358 sim_set_uint8 (sim, sim->psp, 0x81 + i, c); 359 360 s += 1; 361 362 if ((i += 1) > 127) { 363 return (1); 364 } 365 } 366 367 argv += 1; 368 } 369 370 sim_set_uint8 (sim, sim->psp, 0x80, i); 371 372 return (0); 373} 374 375static 376int sim_init_mem (dos_t *sim, unsigned kb) 377{ 378 unsigned i; 379 380 sim->mem_cnt = 1024UL * kb; 381 sim->mem = malloc (sim->mem_cnt); 382 383 if (sim->mem == NULL) { 384 return (1); 385 } 386 387 sim->env = 0; 388 sim->psp = 0; 389 390 memset (sim->mem, 0, sim->mem_cnt); 391 392 sim->mem_start = 0x60; 393 394 sim_set_uint8 (sim, sim->mem_start, 0, 0x5a); 395 sim_set_uint16 (sim, sim->mem_start, 1, 0); 396 sim_set_uint16 (sim, sim->mem_start, 3, (sim->mem_cnt >> 4) - sim->mem_start - 1); 397 398 sim->mem[0x510] = 0xcf; 399 400 for (i = 0; i < 256; i++) { 401 sim_set_uint16 (sim, 0, 4 * i + 0, 0x0010); 402 sim_set_uint16 (sim, 0, 4 * i + 2, 0x0050); 403 } 404 405 sim_set_uint16 (sim, 0x40, 0x13, kb); 406 407 return (0); 408} 409 410int sim_init (dos_t *sim, unsigned kb) 411{ 412 unsigned i; 413 414 if (sim_init_mem (sim, kb)) { 415 return (1); 416 } 417 418 e86_init (&sim->cpu); 419 420 e86_set_prt (&sim->cpu, sim, sim_get_port8, sim_set_port8, sim_get_port16, sim_set_port16); 421 e86_set_mem (&sim->cpu, sim, sim_get_mem8, sim_set_mem8, sim_get_mem16, sim_set_mem16); 422 e86_set_ram (&sim->cpu, sim->mem, sim->mem_cnt); 423 424 sim->cpu.op_ext = sim; 425 sim->cpu.op_int = (void *) sim_int; 426 427 e86_reset (&sim->cpu); 428 429 sim->cpu.state = 0; 430 431 sim->log_int = 0; 432 sim->cur_drive = 2; 433 434 sim->file_cnt = DOS_FILES_MAX; 435 436 for (i = 0; i < sim->file_cnt; i++) { 437 sim->file[i] = NULL; 438 } 439 440 sim->file[0] = stdin; 441 sim->file[1] = stdout; 442 sim->file[2] = stderr; 443 444 sim->drive_cnt = DOS_DRIVES_MAX; 445 446 for (i = 0; i < sim->drive_cnt; i++) { 447 sim->drive[i] = NULL; 448 } 449 450 sim_set_drive (sim, 2, "."); 451 452 sim->search_dir = NULL; 453 sim->search_dir_name = NULL; 454 455 return (0); 456} 457 458void sim_free (dos_t *sim) 459{ 460 free (sim->mem); 461 462 e86_free (&sim->cpu); 463} 464 465void sim_run (dos_t *sim) 466{ 467 while (1) { 468 e86_clock (&sim->cpu, 64); 469 } 470}