1 #include <stdio.h> 2 #include <stdint.h> 3 #include <string.h> 4 5 #ifdef ABS 6 #undef ABS 7 #endif 8 9 #define ABS(x) ((x) > 0 ? (x) : -(x)) 10 11 #define printf pclog 12 13 #define READFLASH_FDC 0 14 #define READFLASH_HDC 4 15 #define readflash_set(offset, drive) readflash |= 1<<((offset)+(drive)) 16 #define readflash_clear(offset, drive) readflash &= ~(1<<((offset)+(drive))) 17 #define readflash_get(offset, drive) ((readflash&(1<<((offset)+(drive)))) != 0) 18 19 /*Memory*/ 20 uint8_t *ram; 21 22 uint32_t rammask; 23 24 int readlookup[256],readlookupp[256]; 25 uintptr_t *readlookup2; 26 int readlnext; 27 int writelookup[256],writelookupp[256]; 28 uintptr_t *writelookup2; 29 int writelnext; 30 31 extern int mmu_perm; 32 33 #define readmemb(a) ((readlookup2[(a)>>12]==-1)?readmembl(a):*(uint8_t *)(readlookup2[(a) >> 12] + (a))) 34 #define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl(s,a):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) 35 #define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll(s,a):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) 36 37 //#define writememb(a,v) if (writelookup2[(a)>>12]==0xFFFFFFFF) writemembl(a,v); else ram[writelookup2[(a)>>12]+((a)&0xFFF)]=v 38 //#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v 39 //#define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememll(s,a,v); else *((uint32_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v 40 //#define readmemb(a) ((isram[((a)>>16)&255] && !(cr0>>31))?ram[a&0xFFFFFF]:readmembl(a)) 41 //#define writememb(a,v) if (isram[((a)>>16)&255] && !(cr0>>31)) ram[a&0xFFFFFF]=v; else writemembl(a,v) 42 43 //void writememb(uint32_t addr, uint8_t val); 44 uint8_t readmembl(uint32_t addr); 45 void writemembl(uint32_t addr, uint8_t val); 46 uint8_t readmemb386l(uint32_t seg, uint32_t addr); 47 void writememb386l(uint32_t seg, uint32_t addr, uint8_t val); 48 uint16_t readmemwl(uint32_t seg, uint32_t addr); 49 void writememwl(uint32_t seg, uint32_t addr, uint16_t val); 50 uint32_t readmemll(uint32_t seg, uint32_t addr); 51 void writememll(uint32_t seg, uint32_t addr, uint32_t val); 52 uint64_t readmemql(uint32_t seg, uint32_t addr); 53 void writememql(uint32_t seg, uint32_t addr, uint64_t val); 54 55 uint8_t *getpccache(uint32_t a); 56 57 uint32_t mmutranslatereal(uint32_t addr, int rw); 58 59 void addreadlookup(uint32_t virt, uint32_t phys); 60 void addwritelookup(uint32_t virt, uint32_t phys); 61 62 63 /*IO*/ 64 uint8_t inb(uint16_t port); 65 void outb(uint16_t port, uint8_t val); 66 uint16_t inw(uint16_t port); 67 void outw(uint16_t port, uint16_t val); 68 uint32_t inl(uint16_t port); 69 void outl(uint16_t port, uint32_t val); 70 71 FILE *romfopen(char *fn, char *mode); 72 extern int shadowbios,shadowbios_write; 73 extern int mem_size; 74 extern int readlnum,writelnum; 75 76 77 /*Processor*/ 78 #define EAX cpu_state.regs[0].l 79 #define ECX cpu_state.regs[1].l 80 #define EDX cpu_state.regs[2].l 81 #define EBX cpu_state.regs[3].l 82 #define ESP cpu_state.regs[4].l 83 #define EBP cpu_state.regs[5].l 84 #define ESI cpu_state.regs[6].l 85 #define EDI cpu_state.regs[7].l 86 #define AX cpu_state.regs[0].w 87 #define CX cpu_state.regs[1].w 88 #define DX cpu_state.regs[2].w 89 #define BX cpu_state.regs[3].w 90 #define SP cpu_state.regs[4].w 91 #define BP cpu_state.regs[5].w 92 #define SI cpu_state.regs[6].w 93 #define DI cpu_state.regs[7].w 94 #define AL cpu_state.regs[0].b.l 95 #define AH cpu_state.regs[0].b.h 96 #define CL cpu_state.regs[1].b.l 97 #define CH cpu_state.regs[1].b.h 98 #define DL cpu_state.regs[2].b.l 99 #define DH cpu_state.regs[2].b.h 100 #define BL cpu_state.regs[3].b.l 101 #define BH cpu_state.regs[3].b.h 102 103 typedef union 104 { 105 uint32_t l; 106 uint16_t w; 107 struct 108 { 109 uint8_t l,h; 110 } b; 111 } x86reg; 112 113 typedef struct 114 { 115 uint32_t base; 116 uint32_t limit; 117 uint8_t access; 118 uint16_t seg; 119 uint32_t limit_low, limit_high; 120 int checked; /*Non-zero if selector is known to be valid*/ 121 } x86seg; 122 123 typedef union MMX_REG 124 { 125 uint64_t q; 126 int64_t sq; 127 uint32_t l[2]; 128 int32_t sl[2]; 129 uint16_t w[4]; 130 int16_t sw[4]; 131 uint8_t b[8]; 132 int8_t sb[8]; 133 } MMX_REG; 134 135 struct 136 { 137 x86reg regs[8]; 138 139 uint8_t tag[8]; 140 141 x86seg *ea_seg; 142 uint32_t eaaddr; 143 144 int flags_op; 145 uint32_t flags_res; 146 uint32_t flags_op1, flags_op2; 147 148 uint32_t pc; 149 uint32_t oldpc; 150 uint32_t op32; 151 152 int TOP; 153 154 union 155 { 156 struct 157 { 158 int8_t rm, mod, reg; 159 } rm_mod_reg; 160 uint32_t rm_mod_reg_data; 161 } rm_data; 162 163 int8_t ssegs; 164 int8_t ismmx; 165 int8_t abrt; 166 167 int _cycles; 168 int cpu_recomp_ins; 169 170 uint16_t npxs, npxc; 171 172 double ST[8]; 173 174 uint16_t MM_w4[8]; 175 176 MMX_REG MM[8]; 177 178 uint16_t old_npxc, new_npxc; 179 } cpu_state; 180 181 #define cycles cpu_state._cycles 182 183 extern uint32_t cpu_cur_status; 184 185 /*The flags below must match in both cpu_cur_status and block->status for a block 186 to be valid*/ 187 #define CPU_STATUS_USE32 (1 << 0) 188 #define CPU_STATUS_STACK32 (1 << 1) 189 #define CPU_STATUS_PMODE (1 << 2) 190 #define CPU_STATUS_V86 (1 << 3) 191 #define CPU_STATUS_FLAGS 0xffff 192 193 /*If the flags below are set in cpu_cur_status, they must be set in block->status. 194 Otherwise they are ignored*/ 195 #define CPU_STATUS_NOTFLATDS (1 << 16) 196 #define CPU_STATUS_NOTFLATSS (1 << 17) 197 #define CPU_STATUS_MASK 0xffff0000 198 199 #define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0]; 200 201 COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128); 202 203 #define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128) 204 205 uint16_t flags,eflags; 206 uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; 207 208 extern int ins,output; 209 extern int cycdiff; 210 211 x86seg gdt,ldt,idt,tr; 212 x86seg _cs,_ds,_es,_ss,_fs,_gs; 213 x86seg _oldds; 214 215 uint32_t pccache; 216 uint8_t *pccache2; 217 /*Segments - 218 _cs,_ds,_es,_ss are the segment structures 219 CS,DS,ES,SS is the 16-bit data 220 cs,ds,es,ss are defines to the bases*/ 221 #define CS _cs.seg 222 #define DS _ds.seg 223 #define ES _es.seg 224 #define SS _ss.seg 225 #define FS _fs.seg 226 #define GS _gs.seg 227 #define cs _cs.base 228 #define ds _ds.base 229 #define es _es.base 230 #define ss _ss.base 231 #define seg_fs _fs.base 232 #define gs _gs.base 233 234 #define CPL ((_cs.access>>5)&3) 235 236 void loadseg(uint16_t seg, x86seg *s); 237 void loadcs(uint16_t seg); 238 239 union 240 { 241 uint32_t l; 242 uint16_t w; 243 } CR0; 244 245 #define cr0 CR0.l 246 #define msw CR0.w 247 248 uint32_t cr2, cr3, cr4; 249 uint32_t dr[8]; 250 251 #define C_FLAG 0x0001 252 #define P_FLAG 0x0004 253 #define A_FLAG 0x0010 254 #define Z_FLAG 0x0040 255 #define N_FLAG 0x0080 256 #define T_FLAG 0x0100 257 #define I_FLAG 0x0200 258 #define D_FLAG 0x0400 259 #define V_FLAG 0x0800 260 #define NT_FLAG 0x4000 261 #define VM_FLAG 0x0002 /*In EFLAGS*/ 262 #define VIF_FLAG 0x0008 /*In EFLAGS*/ 263 #define VIP_FLAG 0x0010 /*In EFLAGS*/ 264 265 #define WP_FLAG 0x10000 /*In CR0*/ 266 267 #define CR4_VME (1 << 0) 268 #define CR4_PVI (1 << 1) 269 #define CR4_PSE (1 << 4) 270 271 #define IOPL ((flags>>12)&3) 272 273 #define IOPLp ((!(msw&1)) || (CPL<=IOPL)) 274 //#define IOPLp 1 275 276 //#define IOPLV86 ((!(msw&1)) || (CPL<=IOPL)) 277 extern int cycles_lost; 278 extern int is486; 279 extern uint8_t opcode; 280 extern int insc; 281 extern int fpucount; 282 extern float mips,flops; 283 extern int cgate16; 284 extern int CPUID; 285 286 extern int cpl_override; 287 288 /*Timer*/ 289 typedef struct PIT_nr 290 { 291 int nr; 292 struct PIT *pit; 293 } PIT_nr; 294 295 typedef struct PIT 296 { 297 uint32_t l[3]; 298 int c[3]; 299 uint8_t m[3]; 300 uint8_t ctrl,ctrls[3]; 301 int wp,rm[3],wm[3]; 302 uint16_t rl[3]; 303 int thit[3]; 304 int delay[3]; 305 int rereadlatch[3]; 306 int gate[3]; 307 int out[3]; 308 int running[3]; 309 int enabled[3]; 310 int newcount[3]; 311 int count[3]; 312 int using_timer[3]; 313 int initial[3]; 314 int latched[3]; 315 int disabled[3]; 316 317 uint8_t read_status[3]; 318 int do_read_status[3]; 319 320 PIT_nr pit_nr[3]; 321 322 void (*set_out_funcs[3])(int new_out, int old_out); 323 } PIT; 324 325 PIT pit, pit2; 326 void setpitclock(float clock); 327 328 float pit_timer0_freq(); 329 330 #define cpu_rm cpu_state.rm_data.rm_mod_reg.rm 331 #define cpu_mod cpu_state.rm_data.rm_mod_reg.mod 332 #define cpu_reg cpu_state.rm_data.rm_mod_reg.reg 333 334 335 336 /*DMA*/ 337 typedef struct dma_t 338 { 339 uint32_t ab, ac; 340 uint16_t cb; 341 int cc; 342 int wp; 343 uint8_t m, mode; 344 uint8_t page; 345 uint8_t stat, stat_rq; 346 uint8_t command; 347 int size; 348 349 uint8_t ps2_mode; 350 uint8_t arb_level; 351 uint16_t io_addr; 352 } dma_t; 353 354 dma_t dma[8]; 355 356 /*PPI*/ 357 typedef struct PPI 358 { 359 int s2; 360 uint8_t pa,pb; 361 } PPI; 362 363 PPI ppi; 364 365 366 /*PIC*/ 367 typedef struct PIC 368 { 369 uint8_t icw1,icw4,mask,ins,pend,mask2; 370 int icw; 371 uint8_t vector; 372 int read; 373 uint8_t level_sensitive; 374 } PIC; 375 376 PIC pic,pic2; 377 extern int pic_intpending; 378 379 380 int disctime; 381 char discfns[2][256]; 382 int driveempty[2]; 383 384 #define PCJR (romset == ROM_IBMPCJR) 385 386 int GAMEBLASTER, GUS, SSI2001, voodoo_enabled; 387 extern int AMSTRAD, AT, is386, PCI, TANDY; 388 389 enum 390 { 391 ROM_IBMPC = 0, /*301 keyboard error, 131 cassette (!!!) error*/ 392 ROM_IBMXT, /*301 keyboard error*/ 393 ROM_IBMPCJR, 394 ROM_GENXT, /*'Generic XT BIOS'*/ 395 ROM_DTKXT, 396 ROM_EUROPC, 397 ROM_OLIM24, 398 ROM_TANDY, 399 ROM_PC1512, 400 ROM_PC200, 401 ROM_PC1640, 402 ROM_PC2086, 403 ROM_PC3086, 404 ROM_AMIXT, /*XT Clone with AMI BIOS*/ 405 ROM_LTXT, 406 ROM_LXT3, 407 ROM_PX386, 408 ROM_DTK386, 409 ROM_PXXT, 410 ROM_JUKOPC, 411 ROM_TANDY1000HX, 412 ROM_TANDY1000SL2, 413 ROM_IBMAT, 414 ROM_CMDPC30, 415 ROM_AMI286, 416 ROM_TG286M, 417 ROM_AWARD286, 418 ROM_GW286CT, 419 ROM_SPC4200P, 420 ROM_SPC4216P, 421 ROM_DELL200, 422 ROM_MISC286, 423 ROM_IBMAT386, 424 ROM_ACER386, 425 ROM_KMXC02, 426 ROM_MEGAPC, 427 ROM_AMA932J, 428 ROM_AMI386SX, 429 ROM_AMI486, 430 ROM_WIN486, 431 ROM_PCI486, 432 ROM_SIS496, 433 ROM_P55VA, /* Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ 434 ROM_P55TVP4, /* ASUS P/I-P55TVP4/430VX/Award/Winbond W8387F*/ 435 ROM_430VX, 436 ROM_ENDEAVOR, 437 ROM_REVENGE, 438 ROM_IBMPS1_2011, 439 ROM_DESKPRO_386, 440 ROM_IBMPS1_2121, 441 ROM_AMI386DX_OPTI495, 442 ROM_MR386DX_OPTI495, 443 ROM_P55T2P4, /* ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/ 444 ROM_IBMPS2_M30_286, 445 ROM_IBMPS2_M50, 446 ROM_IBMPS2_M55SX, 447 ROM_IBMPS2_M80, 448 ROM_ATARIPC3, 449 ROM_IBMXT286, 450 ROM_EPSON_PCAX, 451 ROM_EPSON_PCAX2E, 452 ROM_EPSON_PCAX3, 453 ROM_T3100E, 454 ROM_T1000, 455 ROM_T1200, 456 ROM_PB_L300SX, 457 ROM_NCR_PC4I, 458 ROM_TO16_PC, 459 ROM_COMPAQ_PII, 460 ROM_ELX_PC425X, 461 ROM_PB570, 462 ROM_ZAPPA, 463 ROM_PB520R, 464 ROM_COMPAQ_PIP, 465 ROM_XI8088, 466 ROM_IBMPS2_M70_TYPE3, 467 ROM_IBMPS2_M70_TYPE4, 468 ROM_TULIP_TC7, 469 ROM_ZD_SUPERS, /* [8088] Zenith Data Systems SupersPort */ 470 ROM_PB410A, 471 ROM_PPC512, 472 473 ROM_MAX 474 }; 475 476 extern int romspresent[ROM_MAX]; 477 478 int hasfpu; 479 int romset; 480 481 enum 482 { 483 GFX_BUILTIN = -1, 484 GFX_CGA = 0, 485 GFX_MDA, 486 GFX_HERCULES, 487 GFX_EGA, /*Using IBM EGA BIOS*/ 488 GFX_TVGA, /*Using Trident TVGA8900D BIOS*/ 489 GFX_ET4000, /*Tseng ET4000*/ 490 GFX_TGKOREANVGA, /*Trigem Korean VGA(Tseng ET4000AX)*/ 491 GFX_ET4000W32, /*Tseng ET4000/W32p (Diamond Stealth 32)*/ 492 GFX_BAHAMAS64, /*S3 Vision864 (Paradise Bahamas 64)*/ 493 GFX_N9_9FX, /*S3 764/Trio64 (Number Nine 9FX)*/ 494 GFX_VIRGE, /*S3 Virge*/ 495 GFX_TGUI9440, /*Trident TGUI9440*/ 496 GFX_VGA, /*IBM VGA*/ 497 GFX_VGAEDGE16, /*ATI VGA Edge-16 (18800-1)*/ 498 GFX_ATIKOREANVGA, /*ATI Korean VGA (28800-5)*/ 499 GFX_VGACHARGER, /*ATI VGA Charger (28800-5)*/ 500 GFX_OTI067, /*Oak OTI-067*/ 501 GFX_MACH64GX, /*ATI Graphics Pro Turbo (Mach64)*/ 502 GFX_CL_GD5429, /*Cirrus Logic CL-GD5429*/ 503 GFX_VIRGEDX, /*S3 Virge/DX*/ 504 GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/ 505 GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/ 506 GFX_INCOLOR, /* Hercules InColor */ 507 GFX_COLORPLUS, /* Plantronics ColorPlus */ 508 GFX_WY700, /* Wyse 700 */ 509 GFX_GENIUS, /* MDSI Genius */ 510 GFX_MACH64VT2, /*ATI Mach64 VT2*/ 511 GFX_OLIVETTI_GO481, /*Olivetti GO481 PVGA1A*/ 512 GFX_TGUI9400CXI, /*Trident TGUI9440CXi*/ 513 GFX_CL_GD5430, /*Cirrus Logic CL-GD5430*/ 514 GFX_CL_GD5434, /*Cirrus Logic CL-GD5434*/ 515 GFX_OTI037, /*Oak OTI-037*/ 516 GFX_COMPAQ_CGA, /*Compaq CGA*/ 517 GFX_SIGMA400, /*Sigma Designs Color 400 */ 518 GFX_MAX 519 }; 520 521 extern int gfx_present[GFX_MAX]; 522 523 int gfxcard; 524 525 int cpuspeed; 526 527 528 /*Video*/ 529 int readflash; 530 extern int egareads,egawrites; 531 extern int vid_resize; 532 extern int vid_api; 533 extern int winsizex,winsizey; 534 535 extern int changeframecount; 536 537 538 /*Sound*/ 539 int ppispeakon; 540 float CGACONST; 541 float MDACONST; 542 float VGACONST1,VGACONST2; 543 float RTCCONST; 544 int gated,speakval,speakon; 545 546 547 /*Sound Blaster*/ 548 #define SADLIB 1 /*No DSP*/ 549 #define SB1 2 /*DSP v1.05*/ 550 #define SB15 3 /*DSP v2.00*/ 551 #define SB2 4 /*DSP v2.01 - needed for high-speed DMA*/ 552 #define SBPRO 5 /*DSP v3.00*/ 553 #define SBPRO2 6 /*DSP v3.02 + OPL3*/ 554 #define SB16 7 /*DSP v4.05 + OPL3*/ 555 #define SADGOLD 8 /*AdLib Gold*/ 556 #define SND_WSS 9 /*Windows Sound System*/ 557 #define SND_PAS16 10 /*Pro Audio Spectrum 16*/ 558 559 560 /*Hard disc*/ 561 562 typedef struct 563 { 564 FILE *f; 565 int spt,hpc; /*Sectors per track, heads per cylinder*/ 566 int tracks; 567 } PcemHDC; 568 569 PcemHDC hdc[7]; 570 571 /*Keyboard*/ 572 int keybsenddelay; 573 574 575 /*CD-ROM*/ 576 extern int cdrom_drive; 577 extern int old_cdrom_drive; 578 extern int idecallback[2]; 579 580 #define CD_STATUS_EMPTY 0 581 #define CD_STATUS_DATA_ONLY 1 582 #define CD_STATUS_PLAYING 2 583 #define CD_STATUS_PAUSED 3 584 #define CD_STATUS_STOPPED 4 585 586 extern uint32_t atapi_get_cd_volume(int channel); 587 588 void pclog(const char *format, ...); 589 void fatal(const char *format, ...); 590 void warning(const char *format, ...); 591 extern int nmi; 592 extern int nmi_auto_clear; 593 594 595 extern float isa_timing, bus_timing; 596 597 598 uint64_t timer_read(); 599 extern uint64_t timer_freq; 600 601 602 void loadconfig(char *fn); 603 extern int config_override; 604 605 extern int infocus; 606 607 void onesec(); 608 609 void resetpc_cad(); 610 611 extern int start_in_fullscreen; 612 extern int window_w, window_h, window_x, window_y, window_remember; 613 614 void startblit(); 615 void endblit(); 616 617 void set_window_title(const char *s); 618 619 void updatewindowsize(int x, int y); 620 621 void initpc(int argc, char *argv[]); 622 void runpc(); 623 void closepc(); 624 void resetpc(); 625 void resetpchard(); 626 void speedchanged(); 627 628 void saveconfig(char *fn); 629 void saveconfig_global_only(); 630 631 #define UNUSED(x) (void)x 632 633 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 634 635 void ide_padstr(char *str, const char *src, int len); 636