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