From 9312de19aca7e05f07cd53027b9ff1f5cde49070 Mon Sep 17 00:00:00 2001 From: TomW Date: Mon, 27 May 2013 17:46:42 +0100 Subject: [PATCH] Now up to date with current dev version. Changes since v0.7 : - Major CPU reorganisation. This has possibly broken some stuff, though I fixed all the regressions I could find - Lazy flags. This brought 10% speed improvement at one point, but that's probably been lost now - 430 VX chipset emulation - IDT Winchip emulation (currently sans MMX). Timing is probably wrong - Fixed a few FPU bugs - Timer reorganisation - Sound reorganisation - Other general reorganisation - AdLib Gold emulation - Windows Sound System emulation - Pro Audio Spectrum 16 emulation. This currently works with most DOS stuff, but not in Windows - Major improvements to GUS emulation. Has the downside that it now conflicts with SB emulation, so probably best to not enable both simultaneously - New graphics cards : - ATI-18800 (VGA Edge-16) - ATI-28800 (VGA Charger) - ATI Mach64GX (Graphics Pro Turbo). Quite a few features missing, but Windows doesn't seem to use half the features of this card - Cirrus Logic CL-GD5429. Blitter is a bit broken - Oak OTI-067 - S3 Trio64 (Number Nine 9FX) - S3 Virge. Only framebuffer stuff at the minute, Windows won't recognise the card - Trident TGUI-9440 - VGA. Doesn't work yet - Beginnings of 3DFX emulation, however this is in extremely early stages and doesn't do anything useful - Fixed DMA bug stopping floppy drives working in Windows 3.x - Fixed some other stuff probably - Broke some other stuff probably as well --- src/386.c | 7748 ++------------------------------------ src/Makefile.mingw | 26 +- src/acer386sx.c | 6 +- src/ali1429.c | 18 +- src/amstrad.c | 19 +- src/cdrom-ioctl.c | 9 +- src/config.c | 28 +- src/config.h | 4 + src/cpu.c | 88 +- src/cpu.h | 11 +- src/dma.c | 340 +- src/dma.h | 12 + src/ega.c | 9 +- src/fdc.c | 104 +- src/fdc.h | 2 + src/headland.c | 10 +- src/ibm.h | 78 +- src/ide.c | 388 +- src/ide.h | 5 + src/io.c | 208 +- src/io.h | 26 +- src/jim.c | 7 +- src/keyboard.c | 2 +- src/keyboard_amstrad.c | 7 +- src/keyboard_at.c | 37 +- src/keyboard_olim24.c | 9 +- src/keyboard_xt.c | 15 +- src/lpt.c | 35 +- src/lpt.h | 8 +- src/mem.c | 454 ++- src/mem.h | 46 +- src/model.c | 69 +- src/model.h | 4 + src/mouse_serial.c | 6 +- src/neat.c | 14 +- src/nvr.c | 32 +- src/nvr.h | 2 + src/olivetti_m24.c | 4 +- src/pc.c | 205 +- src/pci.c | 29 +- src/pci.h | 4 +- src/pic.c | 33 +- src/pic.h | 6 + src/pit.c | 42 +- src/resources.h | 1 + src/serial.c | 32 +- src/sound.c | 276 +- src/sound.h | 8 + src/soundopenal.c | 2 +- src/um8881f.c | 25 +- src/vid_cga.c | 34 +- src/vid_cga.h | 8 +- src/vid_ega.c | 52 +- src/vid_ega.h | 8 +- src/vid_et4000.c | 16 +- src/vid_et4000w32.c | 76 +- src/vid_hercules.c | 33 +- src/vid_mda.c | 29 +- src/vid_olivetti_m24.c | 32 +- src/vid_oti067.c | 44 +- src/vid_paradise.c | 38 +- src/vid_pc1512.c | 38 +- src/vid_pc1640.c | 30 +- src/vid_pc200.c | 12 +- src/vid_s3.c | 149 +- src/vid_sdac_ramdac.c | 9 +- src/vid_sdac_ramdac.h | 4 +- src/vid_stg_ramdac.c | 8 +- src/vid_stg_ramdac.h | 4 +- src/vid_svga.c | 612 ++- src/vid_svga.h | 33 +- src/vid_tandy.c | 30 +- src/vid_tkd8001_ramdac.c | 8 +- src/vid_tkd8001_ramdac.h | 4 +- src/vid_tvga.c | 809 +++- src/vid_unk_ramdac.c | 8 +- src/vid_unk_ramdac.h | 4 +- src/video.c | 90 +- src/video.h | 69 +- src/wd76c10.c | 28 +- src/win-video.c | 2 + src/win.c | 227 +- src/x86.h | 9 +- src/x86_flags.h | 386 +- src/x86seg.c | 45 +- src/x87.c | 239 +- src/xtide.c | 11 +- 87 files changed, 4473 insertions(+), 9318 deletions(-) diff --git a/src/386.c b/src/386.c index 7322ef7..b9f5492 100644 --- a/src/386.c +++ b/src/386.c @@ -1,9 +1,3 @@ -//61% -//Win 3.1 - Timer (vtdapi.386) IRQ handler 80020E04 stores to 800200F8 - -//11A2D -//3EF08 - SYS_FloatTime() - #include #include #include @@ -13,14 +7,24 @@ #include "mem.h" #include "cpu.h" #include "fdc.h" +#include "timer.h" #include "video.h" -extern int resets; -int gpf = 0; -int ins2 = 0; +int nmi_enable = 1; -// pclog("IO perm fail on %04X\n",port); \ +int inscounts[256]; +uint32_t oldpc2; +#define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \ + { \ + int tempi = checkio(port); \ + if (abrt) return 0; \ + if (tempi) \ + { \ + x86gpf(NULL,0); \ + return 0; \ + } \ + } #define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \ { \ @@ -42,26 +46,12 @@ int times; uint16_t rds; uint16_t ea_rseg; -int hitits=0; - -uint32_t oldpc2; int is486; int cgate32; -uint8_t opcode2; -int incga; -int enters=0; -int ec; -uint32_t ten3688; -int oldv86=0,oldpmode=0,itson=0; -uint8_t old22; #undef readmemb #undef writememb -//#define readmemb(s,a) readmemb386l(s,a) -//#define writememb(s,a,v) writememb386l(s,a,v) - -//#define is486 1 #define readmemb(s,a) ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF)?readmemb386l(s,a):ram[readlookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]) @@ -71,37 +61,12 @@ uint8_t old22; #define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC) writememll(s,a,v); else *((uint32_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v -/*#undef readmemw -#undef readmeml - -#define readmemb(s, a) readmemb386l(s, a) -#define readmemw(s, a) readmemwl(s, a) -#define readmeml(s, a) readmemll(s, a)*/ - -/*#define writememb(s,a,v) writememb386l(s, a, v) -#define writememw(s,a,v) writememwl(s, a, v) -#define writememl(s,a,v) writememll(s, a, v)*/ -//#define readmemb(s,a) readmemb((s)+(a)) -//#define writememb(s,a,v) writememb((s)+(a),v) uint32_t mmucache[0x100000]; uint8_t romext[32768]; uint8_t *ram,*rom,*vram,*vrom; uint16_t biosmask; -/*uint16_t getwordx() -{ - pc+=2; - return readmemw(cs,(pc-2)); -}*/ - -#define getword() getwordx() - - -//#define readmemb(s,a) readmemb386(s,a) -//#define writememb(s,a,v) writememb386(s,a,v) - -//uint32_t fetchdat; uint32_t rmdat32; #define rmdat rmdat32 #define fetchdat rmdat32 @@ -114,6 +79,15 @@ uint32_t oldcs2; uint32_t oldecx; uint32_t op32; +static inline uint8_t fastreadb(uint32_t a) +{ + if ((a >> 12) == pccache) + return *((uint8_t *)&pccache2[a]); + pccache2 = getpccache(a); + pccache = a >> 12; + return *((uint8_t *)&pccache2[a]); +} + static inline uint16_t fastreadw(uint32_t a) { uint32_t t; @@ -152,6 +126,13 @@ static inline uint32_t fastreadl(uint32_t a) return val; } + +static inline uint8_t getbyte() +{ + pc++; + return fastreadb(cs + (pc - 1)); +} + static inline uint16_t getword() { pc+=2; @@ -191,219 +172,234 @@ static inline uint32_t geteal() return readmeml(easeg,eaaddr); } -#define seteab(v) if (mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,eaaddr,v); } else if (rm&4) regs[rm&3].b.h=v; else regs[rm].b.l=v +static inline uint8_t geteab_mem() +{ + if (eal_r) return *(uint8_t *)eal_r; + return readmemb(easeg,eaaddr); +} +static inline uint16_t geteaw_mem() +{ + if (eal_r) return *(uint16_t *)eal_r; + return readmemw(easeg,eaaddr); +} +static inline uint32_t geteal_mem() +{ + if (eal_r) return *eal_r; + return readmeml(easeg,eaaddr); +} + +#define seteab(v) if (mod!=3) { /*if (eal_w) *(uint8_t *)eal_w=v; else */writememb386l(easeg,eaaddr,v); } else if (rm&4) regs[rm&3].b.h=v; else regs[rm].b.l=v #define seteaw(v) if (mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v); } else regs[rm].w=v #define seteal(v) if (mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,eaaddr,v); } else regs[rm].l=v -static inline void fetcheal32sib() -{ - uint8_t sib; - sib=rmdat>>8;// pc++; - switch (mod) - { - case 0: eaaddr=regs[sib&7].l; pc++; break; - case 1: eaaddr=((uint32_t)(int8_t)(rmdat>>16))+regs[sib&7].l; pc+=2; break; - case 2: eaaddr=(fastreadl(cs+pc+1))+regs[sib&7].l; pc+=5; break; - } - /*SIB byte present*/ - if ((sib&7)==5 && !mod) eaaddr=getlong(); - else if ((sib&6)==4) - { - easeg=ss; - ea_rseg=SS; - } - if (((sib>>3)&7)!=4) eaaddr+=regs[(sib>>3)&7].l<<(sib>>6); -} - -static inline void fetcheal32nosib() -{ - if (rm==5) - { - easeg=ss; - ea_rseg=SS; - } - if (mod==1) { eaaddr+=((uint32_t)(int8_t)(rmdat>>8)); pc++; } - else { eaaddr+=getlong(); } -} +#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,eaaddr,v); +#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v); +#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg,eaaddr,v); uint16_t *mod1add[2][8]; uint32_t *mod1seg[8]; -void fetchea32() +static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; - if (op32&0x200) + easeg = ds; + ea_rseg = DS; + if (rm == 4) { - /*rmdat=readmemw(cs,pc); */pc++; - reg=(rmdat>>3)&7; - mod=(rmdat>>6)&3; - rm=rmdat&7; + uint8_t sib = rmdat >> 8; - if (mod!=3) + switch (mod) { - easeg=ds; - ea_rseg=DS; - if (rm==4) fetcheal32sib(); - else - { - eaaddr=regs[rm].l; - if (mod) fetcheal32nosib(); - else if (rm==5) eaaddr=getlong(); - } - if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) - { - if ( readlookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF) - eal_r = (uint32_t *)&ram[ readlookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)]; - if (writelookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF) - eal_w = (uint32_t *)&ram[writelookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)]; - } + case 0: + eaaddr = regs[sib & 7].l; + pc++; + break; + case 1: + pc++; + eaaddr = ((uint32_t)(int8_t)getbyte()) + regs[sib & 7].l; +// pc++; + break; + case 2: + eaaddr = (fastreadl(cs + pc + 1)) + regs[sib & 7].l; + pc += 5; + break; } + /*SIB byte present*/ + if ((sib & 7) == 5 && !mod) + eaaddr = getlong(); + else if ((sib & 6) == 4) + { + easeg = ss; + ea_rseg = SS; + } + if (((sib >> 3) & 7) != 4) + eaaddr += regs[(sib >> 3) & 7].l << (sib >> 6); } else { - /*rmdat=readmemb(cs,pc); */pc++; - reg=(rmdat>>3)&7; - mod=(rmdat>>6)&3; - rm=rmdat&7; - if (mod!=3) + eaaddr = regs[rm].l; + if (mod) { - if (!mod && rm==6) { eaaddr=(rmdat>>8)&0xFFFF; pc+=2; easeg=ds; ea_rseg=DS; } - else + if (rm == 5) { - switch (mod) - { - case 0: - eaaddr=0; - break; - case 1: - eaaddr=(uint16_t)(int8_t)(rmdat>>8); pc++; - break; - case 2: - eaaddr=getword(); - break; - } - eaaddr+=(*mod1add[0][rm])+(*mod1add[1][rm]); - easeg=*mod1seg[rm]; - if (mod1seg[rm]==&ss) ea_rseg=SS; - else ea_rseg=DS; - eaaddr&=0xFFFF; + easeg = ss; + ea_rseg = SS; } - if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) + if (mod == 1) + { + eaaddr += ((uint32_t)(int8_t)(rmdat >> 8)); + pc++; + } + else { - if ( readlookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF) - eal_r = (uint32_t *)&ram[ readlookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)]; - if (writelookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF) - eal_w = (uint32_t *)&ram[writelookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)]; + eaaddr += getlong(); } -/* if (readlookup2[(easeg+eaaddr)>>12]!=0xFFFFFFFF && easeg!=0xFFFFFFFF && ((easeg+eaaddr)&0xFFF)<=0xFFC) - eal=(uint32_t *)&ram[readlookup2[(easeg+eaaddr)>>12]+((easeg+eaaddr)&0xFFF)];*/ } + else if (rm == 5) + { + eaaddr = getlong(); + } + } + if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) + { + if ( readlookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF) + eal_r = (uint32_t *)&ram[ readlookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)]; + if (writelookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF) + eal_w = (uint32_t *)&ram[writelookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)]; } } -#undef fetchea -#define fetchea() fetchea32(); if (abrt) break -#define fetchea2() rmdat=fastreadl(cs+pc); fetchea32(); if (abrt) break +static inline void fetch_ea_16_long(uint32_t rmdat) +{ + eal_r = eal_w = NULL; + if (!mod && rm == 6) + { + eaaddr = getword(); + easeg = ds; + ea_rseg = DS; + } + else + { + switch (mod) + { + case 0: + eaaddr = 0; + break; + case 1: + eaaddr = (uint16_t)(int8_t)(rmdat >> 8); pc++; + break; + case 2: + eaaddr = getword(); + break; + } + eaaddr += (*mod1add[0][rm]) + (*mod1add[1][rm]); + easeg = *mod1seg[rm]; + if (mod1seg[rm] == &ss) ea_rseg = SS; + else ea_rseg = DS; + eaaddr &= 0xFFFF; + } + if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) + { + if ( readlookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF) + eal_r = (uint32_t *)&ram[ readlookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)]; + if (writelookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF) + eal_w = (uint32_t *)&ram[writelookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)]; + } +} + +#define fetch_ea_16(rmdat) pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_16_long(rmdat); if (abrt) return 0; } +#define fetch_ea_32(rmdat) pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_32_long(rmdat); } if (abrt) return 0 #include "x86_flags.h" -void setadd32(uint32_t a, uint32_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b; - flags&=~0x8D5; - flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0)); - flags|=(znptable8[c&0xFF]&P_FLAG); - if (ca) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -void setsub32nc(uint32_t a, uint32_t b) -{ - uint32_t c=(uint32_t)a-(uint32_t)b; - flags&=~0x8D4; - flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0)); - flags|=(znptable8[c&0xFF]&P_FLAG); - if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -void setsbc32(uint32_t a, uint32_t b) -{ - uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); - flags&=~0x8D5; - flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0)); - flags|=(znptable8[c&0xFF]&P_FLAG); - if ((c>a) || (c==a && tempc)) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG; - if (((a&0xF)-((b&0xF)+tempc))&0x10) flags|=A_FLAG; -} - - - void x86_int(int num) { uint32_t addr; - pc=oldpc; - if (msw&1) - { - pmodeint(num,0); - } - else - { - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,flags); - writememw(ss,ESP-4,CS); - writememw(ss,ESP-6,pc); - ESP-=6; - } - else - { - writememw(ss,((SP-2)&0xFFFF),flags); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),pc); - SP-=6; - } - addr=num<<2; +// pclog("x86_int\n"); + flags_rebuild(); + pc=oldpc; + if (msw&1) + { + pmodeint(num,0); + } + else + { + if (ssegs) ss=oldss; + if (stack32) + { + writememw(ss,ESP-2,flags); + writememw(ss,ESP-4,CS); + writememw(ss,ESP-6,pc); + ESP-=6; + } + else + { + writememw(ss,((SP-2)&0xFFFF),flags); + writememw(ss,((SP-4)&0xFFFF),CS); + writememw(ss,((SP-6)&0xFFFF),pc); + SP-=6; + } + addr=num<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; - oxpc=pc; - pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - } - cycles-=70; + flags&=~I_FLAG; + flags&=~T_FLAG; + oxpc=pc; + pc=readmemw(0,addr); + loadcs(readmemw(0,addr+2)); + } + cycles-=70; } +void x86_int_sw(int num) +{ + uint32_t addr; +// pclog("x86_int\n"); + flags_rebuild(); + if (msw&1) + { + pmodeint(num,1); + } + else + { + if (ssegs) ss=oldss; + if (stack32) + { + writememw(ss,ESP-2,flags); + writememw(ss,ESP-4,CS); + writememw(ss,ESP-6,pc); + ESP-=6; + } + else + { + writememw(ss,((SP-2)&0xFFFF),flags); + writememw(ss,((SP-4)&0xFFFF),CS); + writememw(ss,((SP-6)&0xFFFF),pc); + SP-=6; + } + addr=num<<2; + + flags&=~I_FLAG; + flags&=~T_FLAG; + oxpc=pc; + pc=readmemw(0,addr); + loadcs(readmemw(0,addr+2)); + } + cycles-=70; +} + +void x86illegal() +{ + uint16_t addr; + pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode); +// if (output) +// { +// dumpregs(); +// exit(-1); +// } + x86_int(6); +} + + #define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\ { \ x86_int(6); \ @@ -415,7 +411,7 @@ void rep386(int fv) uint8_t temp; uint32_t c;//=CX; uint8_t temp2; - uint16_t tempw,tempw2,tempw3,of=flags; + uint16_t tempw,tempw2,of; uint32_t ipc=oldpc;//pc-1; int changeds=0; uint32_t oldds; @@ -423,6 +419,9 @@ void rep386(int fv) uint32_t templ,templ2; int tempz; int tempi; + + flags_rebuild(); + of = flags; // if (output) pclog("REP32 %04X %04X ",use32,rep32); startrep: temp=opcode2=readmemb(cs,pc); pc++; @@ -743,9 +742,8 @@ void rep386(int fv) else firstrepcycle=1; break; case 0xA6: case 0x1A6: /*REP CMPSB*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { temp=readmemb(ds,SI); temp2=readmemb(es,DI); @@ -755,14 +753,14 @@ void rep386(int fv) c--; cycles-=(is486)?7:9; setsub8(temp,temp2); + tempz = (ZF_SET()) ? 1 : 0; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0x2A6: case 0x3A6: /*REP CMPSB*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { temp=readmemb(ds,ESI); temp2=readmemb(es,EDI); @@ -772,14 +770,14 @@ void rep386(int fv) c--; cycles-=(is486)?7:9; setsub8(temp,temp2); + tempz = (ZF_SET()) ? 1 : 0; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0xA7: /*REP CMPSW*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { // pclog("CMPSW %05X %05X %08X %08X ", ds+SI, es+DI, readlookup2[(ds+SI)>>12], readlookup2[(es+DI)>>12]); tempw=readmemw(ds,SI); @@ -792,14 +790,14 @@ void rep386(int fv) c--; cycles-=(is486)?7:9; setsub16(tempw,tempw2); + tempz = (ZF_SET()) ? 1 : 0; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0x1A7: /*REP CMPSL*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { templ=readmeml(ds,SI); templ2=readmeml(es,DI); @@ -809,14 +807,14 @@ void rep386(int fv) c--; cycles-=(is486)?7:9; setsub32(templ,templ2); + tempz = (ZF_SET()) ? 1 : 0; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0x2A7: /*REP CMPSW*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { tempw=readmemw(ds,ESI); tempw2=readmemw(es,EDI); @@ -826,14 +824,14 @@ void rep386(int fv) c--; cycles-=(is486)?7:9; setsub16(tempw,tempw2); + tempz = (ZF_SET()) ? 1 : 0; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0x3A7: /*REP CMPSL*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { templ=readmeml(ds,ESI); templ2=readmeml(es,EDI); @@ -843,8 +841,9 @@ void rep386(int fv) c--; cycles-=(is486)?7:9; setsub32(templ,templ2); + tempz = (ZF_SET()) ? 1 : 0; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; @@ -1013,107 +1012,106 @@ void rep386(int fv) case 0xAE: case 0x1AE: /*REP SCASB*/ // if (es==0xFFFFFFFF) pclog("Null selector REP SCASB %04X(%06X):%06X\n",CS,cs,pc); // tempz=(fv)?1:0; - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { temp2=readmemb(es,DI); if (abrt) { flags=of; break; } setsub8(AL,temp2); + tempz = (ZF_SET()) ? 1 : 0; if (flags&D_FLAG) DI--; else DI++; c--; cycles-=(is486)?5:8; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0x2AE: case 0x3AE: /*REP SCASB*/ // if (es==0xFFFFFFFF) pclog("Null selector REP SCASB %04X(%06X):%06X\n",CS,cs,pc); // tempz=(fv)?1:0; - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; -// if (output) pclog("REP SCASB - %i %04X %i\n",fv,flags&Z_FLAG,c); - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { temp2=readmemb(es,EDI); if (abrt) { flags=of; break; } // if (output) pclog("Compare %02X,%02X\n",temp2,AL); setsub8(AL,temp2); + tempz = (ZF_SET()) ? 1 : 0; if (flags&D_FLAG) EDI--; else EDI++; c--; cycles-=(is486)?5:8; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0xAF: /*REP SCASW*/ // if (es==0xFFFFFFFF) pclog("Null selector REP SCASW %04X(%06X):%06X\n",CS,cs,pc); - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { tempw=readmemw(es,DI); if (abrt) { flags=of; break; } setsub16(AX,tempw); + tempz = (ZF_SET()) ? 1 : 0; if (flags&D_FLAG) DI-=2; else DI+=2; c--; cycles-=(is486)?5:8; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0x1AF: /*REP SCASL*/ // if (es==0xFFFFFFFF) pclog("Null selector REP SCASL %04X(%06X):%06X\n",CS,cs,pc); - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { templ=readmeml(es,DI); if (abrt) { flags=of; break; } setsub32(EAX,templ); + tempz = (ZF_SET()) ? 1 : 0; if (flags&D_FLAG) DI-=4; else DI+=4; c--; cycles-=(is486)?5:8; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0x2AF: /*REP SCASW*/ // if (es==0xFFFFFFFF) pclog("Null selector REP SCASW %04X(%06X):%06X\n",CS,cs,pc); - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { tempw=readmemw(es,EDI); if (abrt) { flags=of; break; } setsub16(AX,tempw); + tempz = (ZF_SET()) ? 1 : 0; if (flags&D_FLAG) EDI-=2; else EDI+=2; c--; cycles-=(is486)?5:8; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; case 0x3AF: /*REP SCASL*/ // if (es==0xFFFFFFFF) pclog("Null selector REP SCASL %04X(%06X):%06X\n",CS,cs,pc); - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + tempz = (fv) ? 1 : 0; + if ((c>0) && (fv==tempz)) { templ=readmeml(es,EDI); if (abrt) { flags=of; break; } setsub32(EAX,templ); + tempz = (ZF_SET()) ? 1 : 0; if (flags&D_FLAG) EDI-=4; else EDI+=4; c--; cycles-=(is486)?5:8; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } + if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; } else firstrepcycle=1; break; @@ -1121,8 +1119,8 @@ void rep386(int fv) default: pc=ipc; cycles-=20; + fatal("Bad REP %02X %i\n",temp,rep32>>8); x86illegal(); - pclog("Bad REP %02X %i\n",temp,rep32>>8); } if (rep32&0x200) ECX=c; else CX=c; @@ -1142,7 +1140,8 @@ int checkio(int port) // pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3)); if ((t+(port>>3))>tr.limit) return 1; cpl_override = 1; - d=readmemb(tr.base,t+(port>>3)); + d = readmemb386l(0, tr.base + t + (port >> 3)); +// d=readmemb(tr.base,t+(port>>3)); cpl_override = 0; // pclog("%02X %02X\n",d,d&(1<<(port&7))); return d&(1<<(port&7)); @@ -1157,68 +1156,90 @@ int xout=0; #define divexcp() { \ pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,pc); \ - pc=oldpc; \ - if (msw&1) pmodeint(0,0); \ - else \ - { \ - writememw(ss,(SP-2)&0xFFFF,flags); \ - writememw(ss,(SP-4)&0xFFFF,CS); \ - writememw(ss,(SP-6)&0xFFFF,pc); \ - SP-=6; \ - flags&=~I_FLAG; \ - oxpc=pc; \ - pc=readmemw(0,0); \ - loadcs(readmemw(0,2)); \ - } \ - return; \ + x86_int(0); \ } void divl(uint32_t val) { - if (val==0) divexcp(); + if (val==0) + { + divexcp(); + return; + } uint64_t num=(((uint64_t)EDX)<<32)|EAX; uint64_t quo=num/val; uint32_t rem=num%val; uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF); - if (quo!=(uint64_t)quo32) divexcp(); + if (quo!=(uint64_t)quo32) + { + divexcp(); + return; + } EDX=rem; EAX=quo32; } void idivl(int32_t val) { - if (val==0) divexcp(); + if (val==0) + { + divexcp(); + return; + } int64_t num=(((uint64_t)EDX)<<32)|EAX; int64_t quo=num/val; int32_t rem=num%val; int32_t quo32=(int32_t)(quo&0xFFFFFFFF); - if (quo!=(int64_t)quo32) divexcp(); + if (quo!=(int64_t)quo32) + { + divexcp(); + return; + } EDX=rem; EAX=quo32; } + +void cpu_386_flags_extract() +{ + flags_extract(); +} +void cpu_386_flags_rebuild() +{ + flags_rebuild(); +} + int oldi; +static uint64_t tsc = 0; + uint32_t testr[9]; int dontprint=0; + +#undef NOTRM +#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\ + { \ + x86_int(6); \ + return 0; \ + } + +#include "386_ops.h" + +#undef NOTRM +#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\ + { \ + x86_int(6); \ + break; \ + } + void exec386(int cycs) { - uint64_t temp64; - int64_t temp64i; - uint8_t temp,temp2; - uint16_t tempw,tempw2,tempw3,tempw4; - int8_t offset; - int8_t temps; - int16_t temps16; - volatile int tempws,tempws2; - uint32_t templ,templ2,templ3,addr; - int c,cycdiff; - int oldcyc; + uint8_t temp; + uint32_t addr; int tempi; - int cyctot=0; - int trap; + int cycdiff; + int oldcyc; + int trap = flags & T_FLAG; - FILE *f; - cycles+=cycs; // output=3; while (cycles>0) @@ -1228,11 +1249,12 @@ void exec386(int cycs) // pclog("%i %02X\n", ins, ram[8]); while (cycdiff<100) { -/* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX; - testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP; - testr[8]=flags;*/ + /* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX; + testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/ +/* testr[8]=flags;*/ // oldcs2=oldcs; // oldpc2=oldpc; +opcode_realstart: oldcs=CS; oldpc=pc; oldcpl=CPL; @@ -1240,6921 +1262,32 @@ void exec386(int cycs) dontprint=0; - opcodestart: - fetchdat=fastreadl(cs+pc); - if (abrt) goto opcodeend; - - tempc=flags&C_FLAG; - trap=flags&T_FLAG; - opcode=fetchdat&0xFF; - fetchdat>>=8; +opcodestart: + fetchdat = fastreadl(cs + pc); + if (!abrt) + { + tempc = CF_SET(); + trap = flags & T_FLAG; + opcode = fetchdat & 0xFF; + fetchdat >>= 8; - if (output==3 && !dontprint) - { - if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle) + if (output == 3) { - if (!skipnextprint) - { - pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,writelookup2, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, readmode); - //x87_print(); - } - skipnextprint=0; + pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]); } + pc++; + if (x86_opcodes[(opcode | op32) & 0x3ff](fetchdat)) + goto opcodestart; } - dontprint=1; -//#endif - pc++; - inhlt=0; - switch ((opcode|op32)&0x3FF) + + if (!use32) pc &= 0xffff; +/* if (ins == 74400000) { - case 0x00: case 0x100: case 0x200: case 0x300: /*ADD 8,reg*/ - fetchea(); - //if (!rmdat && output) pc--; -/* if (!rmdat && output) - { - fatal("Crashed\n"); -// clear_keybuf(); -// readkey(); - - - }*/ - if (mod == 3) - { - temp = getr8(rm); - temp2 = getr8(reg); - setadd8(temp, temp2); - setr8(rm, temp + temp2); - cycles -= timing_rr; - } - else - { - temp = geteab(); if (abrt) break; - temp2 = getr8(reg); - seteab(temp + temp2); if (abrt) break; - setadd8(temp, temp2); - cycles -= timing_mr; - } - break; - case 0x01: case 0x201: /*ADD 16,reg*/ - fetchea(); - if (mod == 3) - { - setadd16(regs[rm].w, regs[reg].w); - regs[rm].w += regs[reg].w; - cycles -= timing_rr; - } - else - { - tempw = geteaw(); if (abrt) break; - seteaw(tempw + regs[reg].w); if (abrt) break; - setadd16(tempw, regs[reg].w); - cycles -= timing_mr; - } - break; - case 0x101: case 0x301: /*ADD 32,reg*/ - fetchea(); - if (mod == 3) - { - setadd32(regs[rm].l, regs[reg].l); - regs[rm].l += regs[reg].l; - cycles -= timing_rr; - } - else - { - templ = geteal(); if (abrt) break; - seteal(templ + regs[reg].l); if (abrt) break; - setadd32(templ, regs[reg].l); - cycles -= timing_mrl; - } - break; - case 0x02: case 0x102: case 0x202: case 0x302: /*ADD reg,8*/ - fetchea(); - temp=geteab(); if (abrt) break; - setadd8(getr8(reg),temp); - setr8(reg,getr8(reg)+temp); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x03: case 0x203: /*ADD reg,16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - setadd16(regs[reg].w,tempw); - regs[reg].w+=tempw; - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x103: case 0x303: /*ADD reg,32*/ - fetchea(); - templ=geteal(); if (abrt) break; - setadd32(regs[reg].l,templ); - regs[reg].l+=templ; - cycles -= (mod == 3) ? timing_rr : timing_rml; - break; - case 0x04: case 0x104: case 0x204: case 0x304: /*ADD AL,#8*/ - temp=getbytef(); - setadd8(AL,temp); - AL+=temp; - cycles -= timing_rr; - break; - case 0x05: case 0x205: /*ADD AX,#16*/ - tempw=getwordf(); - setadd16(AX,tempw); - AX+=tempw; - cycles -= timing_rr; - break; - case 0x105: case 0x305: /*ADD EAX,#32*/ - templ=getlong(); if (abrt) break; - setadd32(EAX,templ); - EAX+=templ; - cycles -= timing_rr; - break; - - case 0x06: case 0x206: /*PUSH ES*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,ES); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),ES); if (abrt) break; - SP-=2; - } - cycles-=2; - break; - case 0x106: case 0x306: /*PUSH ES*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,ES); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),ES); if (abrt) break; - SP-=4; - } - cycles-=2; - break; - case 0x07: case 0x207: /*POP ES*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_es); if (abrt) break; - ESP+=2; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_es); if (abrt) break; - SP+=2; - } - cycles-=(is486)?3:7; - break; - case 0x107: case 0x307: /*POP ES*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmeml(ss,ESP)&0xFFFF; if (abrt) break; - loadseg(tempw,&_es); if (abrt) break; - ESP+=4; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_es); if (abrt) break; - SP+=4; - } - cycles-=(is486)?3:7; - break; - - - case 0x08: case 0x108: case 0x208: case 0x308: /*OR 8,reg*/ - fetchea(); - if (mod == 3) - { - temp = getr8(rm) | getr8(reg); - setr8(rm, temp); - setznp8(temp); - cycles -= timing_rr; - } - else - { - temp = geteab(); if (abrt) break; - temp2 = getr8(reg); - seteab(temp | temp2); if (abrt) break; - setznp8(temp | temp2); - cycles -= timing_mr; - } - break; - case 0x09: case 0x209: /*OR 16,reg*/ - fetchea(); - if (mod == 3) - { - regs[rm].w |= regs[reg].w; - setznp16(regs[rm].w); - cycles -= timing_rr; - } - else - { - tempw = geteaw() | regs[reg].w; if (abrt) break; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= timing_mr; - } - break; - case 0x109: case 0x309: /*OR 32,reg*/ - fetchea(); - if (mod == 3) - { - regs[rm].l |= regs[reg].l; - setznp32(regs[rm].l); - cycles -= timing_rr; - } - else - { - templ = geteal() | regs[reg].l; if (abrt) break; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= timing_mrl; - } - break; - case 0x0A: case 0x10A: case 0x20A: case 0x30A: /*OR reg,8*/ - fetchea(); - temp=geteab(); if (abrt) break; - temp|=getr8(reg); - setznp8(temp); - setr8(reg,temp); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x0B: case 0x20B: /*OR reg,16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw|=regs[reg].w; - setznp16(tempw); - regs[reg].w=tempw; - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x10B: case 0x30B: /*OR reg,32*/ - fetchea(); - templ=geteal(); if (abrt) break; - templ|=regs[reg].l; - setznp32(templ); - regs[reg].l=templ; - cycles -= (mod == 3) ? timing_rr : timing_rml; - break; - case 0x0C: case 0x10C: case 0x20C: case 0x30C: /*OR AL,#8*/ - AL|=getbytef(); - setznp8(AL); - cycles -= timing_rr; - break; - case 0x0D: case 0x20D: /*OR AX,#16*/ - AX|=getwordf(); - setznp16(AX); - cycles -= timing_rr; - break; - case 0x10D: case 0x30D: /*OR AX,#32*/ - templ=getlong(); if (abrt) break; - EAX|=templ; - setznp32(EAX); - cycles -= timing_rr; - break; - - case 0x0E: case 0x20E: /*PUSH CS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,CS); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),CS); if (abrt) break; - SP-=2; - } - cycles-=2; - break; - case 0x10E: case 0x30E: /*PUSH CS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,CS); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),CS); if (abrt) break; - SP-=4; - } - cycles-=2; - break; - - case 0x0F: case 0x20F: - temp=fetchdat&0xFF/*readmemb(cs+pc)*/; pc++; - opcode2=temp; -// if (temp>5 && temp!=0x82 && temp!=0x85 && temp!=0x84 && temp!=0x87 && temp!=0x8D && temp!=0x8F && temp!=0x8C && temp!=0x20 && temp!=0x22) pclog("Using magic 386 0F instruction %02X!\n",temp); - switch (temp) - { - case 0: - if (!(cr0&1) || (eflags&VM_FLAG)) goto inv16; - fetchea2(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*SLDT*/ - NOTRM - seteaw(ldt.seg); - cycles-=4; - break; - case 0x08: /*STR*/ - NOTRM - seteaw(tr.seg); - cycles-=4; - break; - case 0x10: /*LLDT*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) - { - pclog("Invalid LLDT!\n"); - x86gpf(NULL,0); - break; - } - NOTRM - ldt.seg=geteaw(); -// pclog("Load LDT %04X ",ldt.seg); - templ=(ldt.seg&~7)+gdt.base; -// pclog("%06X ",gdt.base); - templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16); - templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24); - if (abrt) break; - ldt.limit=templ3; - ldt.access=readmemb(0,templ+6); - if (readmemb(0,templ+6)&0x80) - { - ldt.limit<<=12; - ldt.limit|=0xFFF; - } - ldt.base=templ2; -// /*if (output==3) */pclog("LLDT %04X %08X %04X %08X %08X\n",ldt.seg,ldt.base,ldt.limit,readmeml(0,templ),readmeml(0,templ+4)); - - cycles-=20; - break; - case 0x18: /*LTR*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) - { - pclog("Invalid LTR!\n"); - x86gpf(NULL,0); - break; - } - NOTRM - tr.seg=geteaw(); - templ=(tr.seg&~7)+gdt.base; - templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16); - templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24); - temp=readmemb(0,templ+5); - if (abrt) break; - tr.limit=templ3; - tr.access=readmemb(0,templ+6); - if (readmemb(0,templ+6)&0x80) - { - tr.limit<<=12; - tr.limit|=0xFFF; - } - tr.base=templ2; -// pclog("TR base = %08X\n",templ2); - tr.access=temp; - cycles-=20; - break; - case 0x20: /*VERR*/ - NOTRM - tempw=geteaw(); if (abrt) break; - flags&=~Z_FLAG; - if (!(tempw&0xFFFC)) break; /*Null selector*/ - cpl_override=1; - tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit); - tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4); - cpl_override=0; - if (abrt) break; - if (!(tempw2&0x1000)) tempi=0; - if ((tempw2&0xC00)!=0xC00) /*Exclude conforming code segments*/ - { - tempw3=(tempw2>>13)&3; /*Check permissions*/ - if (tempw3>13)&3; /*Check permissions*/ - if (tempw3>16)&0xFF); - cycles-=7; //less seteaw time - break; - case 0x08: /*SIDT*/ - seteaw(idt.limit); - writememw(easeg,eaaddr+2,idt.base); - writememw(easeg,eaaddr+4,(idt.base>>16)&0xFF); - cycles-=7; - break; - case 0x10: /*LGDT*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) - { - pclog("Invalid LGDT!\n"); - x86gpf(NULL,0); - break; - } - tempw=geteaw(); - templ=readmeml(0,easeg+eaaddr+2)&0xFFFFFF; - if (abrt) break; - gdt.limit=tempw; - gdt.base=templ; - cycles-=11; - break; - case 0x18: /*LIDT*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) - { - pclog("Invalid LIDT!\n"); - x86gpf(NULL,0); - break; - } - tempw=geteaw(); - templ=readmeml(0,easeg+eaaddr+2)&0xFFFFFF; - if (abrt) break; - idt.limit=tempw; - idt.base=templ; - cycles-=11; - break; - - case 0x20: /*SMSW*/ - if (is486) seteaw(msw); - else seteaw(msw|0xFF00); -// pclog("SMSW %04X:%04X %04X %i\n",CS,pc,msw,is486); - cycles-=2; - break; - case 0x30: /*LMSW*/ - if ((CPL || eflags&VM_FLAG) && (msw&1)) - { - pclog("LMSW - ring not zero!\n"); - x86gpf(NULL,0); - break; - } - tempw=geteaw(); if (abrt) break; - if (msw&1) tempw|=1; - msw=tempw; - break; - - default: - pclog("Bad 0F 01 opcode %02X\n",rmdat&0x38); - pc-=3; - x86illegal(); - break; - } - break; - - case 2: /*LAR*/ - NOTRM - fetchea2(); - tempw=geteaw(); if (abrt) break; -// pclog("LAR seg %04X\n",tempw); - - if (!(tempw&0xFFFC)) { flags&=~Z_FLAG; break; } /*Null selector*/ - tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit); - if (tempi) - { - cpl_override=1; - tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4); - cpl_override=0; - if (abrt) break; - } - flags&=~Z_FLAG; -// pclog("tempw2 %04X %i %04X %04X\n",tempw2,tempi,ldt.limit,gdt.limit); - if ((tempw2&0x1F00)==0x000) tempi=0; - if ((tempw2&0x1F00)==0x800) tempi=0; - if ((tempw2&0x1F00)==0xA00) tempi=0; - if ((tempw2&0x1F00)==0xD00) tempi=0; - if ((tempw2&0x1C00)<0x1C00) /*Exclude conforming code segments*/ - { - tempw3=(tempw2>>13)&3; - if (tempw3>13)&3; - if (tempw3>31) flushmmucache(); - if ((regs[rm].l^cr0) & 0x80000001) flushmmucache(); - cr0=regs[rm].l;//&~2; - if (cpu_16bitbus) cr0 |= 0x10; -// if (cs<0xF0000 && cr0&1) output=3; - if (cr0&0x80000000) - { - } - else mmu_perm=4; - break; - case 2: - cr2=regs[rm].l; - break; - case 3: - cr3=regs[rm].l&~0xFFF; -// pclog("Loading CR3 with %08X at %08X:%08X\n",cr3,cs,pc); -// if (pc==0x204) output=3; - flushmmucache(); - break; - default: - pclog("Bad load CR%i\n",reg); - pc=oldpc; - x86illegal(); - break; - } - cycles-=10; - break; - case 0x23: /*MOV DRx,reg32*/ - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) - { - pclog("Can't load DRx\n"); - x86gpf(NULL,0); - break; - } - fetchea2(); - cycles-=6; - break; - case 0x24: /*MOV reg32,TRx*/ - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) - { - pclog("Can't load from TRx\n"); - x86gpf(NULL,0); - break; - } - fetchea2(); - regs[rm].l=0; - cycles-=6; - break; - case 0x26: /*MOV TRx,reg32*/ - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) - { - pclog("Can't load TRx\n"); - x86gpf(NULL,0); - break; - } - fetchea2(); - cycles-=6; - break; - - case 0x32: x86illegal(); break; - - case 0x80: /*JO*/ - tempw=getword2f(); - if (flags&V_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x81: /*JNO*/ - tempw=getword2f(); - if (!(flags&V_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x82: /*JB*/ - tempw=getword2f(); - if (flags&C_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x83: /*JNB*/ - tempw=getword2f(); - if (!(flags&C_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x84: /*JE*/ - tempw=getword2f(); - if (flags&Z_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x85: /*JNE*/ - tempw=getword2f(); - if (!(flags&Z_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x86: /*JBE*/ - tempw=getword2f(); - if (flags&(C_FLAG|Z_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x87: /*JNBE*/ - tempw=getword2f(); - if (!(flags&(C_FLAG|Z_FLAG))) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x88: /*JS*/ - tempw=getword2f(); - if (flags&N_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x89: /*JNS*/ - tempw=getword2f(); - if (!(flags&N_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x8A: /*JP*/ - tempw=getword2f(); - if (flags&P_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x8B: /*JNP*/ - tempw=getword2f(); - if (!(flags&P_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x8C: /*JL*/ - tempw=getword2f(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp!=temp2) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x8D: /*JNL*/ - tempw=getword2f(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp==temp2) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x8E: /*JLE*/ - tempw=getword2f(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if ((flags&Z_FLAG) || (temp!=temp2)) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - case 0x8F: /*JNLE*/ - tempw=getword2f(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (!((flags&Z_FLAG) || (temp!=temp2))) { pc+=(int16_t)tempw; cycles-=timing_bt; } - cycles -= timing_bnt; - break; - - case 0x90: /*SETO*/ - fetchea2(); - seteab((flags&V_FLAG)?1:0); - cycles-=4; - break; - case 0x91: /*SETNO*/ - fetchea2(); - seteab((flags&V_FLAG)?0:1); - cycles-=4; - break; - case 0x92: /*SETC*/ - fetchea2(); - seteab((flags&C_FLAG)?1:0); - cycles-=4; - break; - case 0x93: /*SETAE*/ - fetchea2(); - seteab((flags&C_FLAG)?0:1); - cycles-=4; - break; - case 0x94: /*SETZ*/ - fetchea2(); - seteab((flags&Z_FLAG)?1:0); - cycles-=4; - break; - case 0x95: /*SETNZ*/ - fetchea2(); - seteab((flags&Z_FLAG)?0:1); - cycles-=4; - break; - case 0x96: /*SETBE*/ - fetchea2(); - seteab((flags&(C_FLAG|Z_FLAG))?1:0); - cycles-=4; - break; - case 0x97: /*SETNBE*/ - fetchea2(); - seteab((flags&(C_FLAG|Z_FLAG))?0:1); - cycles-=4; - break; - case 0x98: /*SETS*/ - fetchea2(); - seteab((flags&N_FLAG)?1:0); - cycles-=4; - break; - case 0x99: /*SETNS*/ - fetchea2(); - seteab((flags&N_FLAG)?0:1); - cycles-=4; - break; - case 0x9A: /*SETP*/ - fetchea2(); - seteab((flags&P_FLAG)?1:0); - cycles-=4; - break; - case 0x9B: /*SETNP*/ - fetchea2(); - seteab((flags&P_FLAG)?0:1); - cycles-=4; - break; - case 0x9C: /*SETL*/ - fetchea2(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - seteab(temp^temp2); - cycles-=4; - break; - case 0x9D: /*SETGE*/ - fetchea2(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - seteab((temp^temp2)?0:1); - cycles-=4; - break; - case 0x9E: /*SETLE*/ - fetchea2(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - seteab(((temp^temp2) || (flags&Z_FLAG))?1:0); - cycles-=4; - break; - case 0x9F: /*SETNLE*/ - fetchea2(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - seteab(((temp^temp2) || (flags&Z_FLAG))?0:1); - cycles-=4; - break; - - case 0xA0: /*PUSH FS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,FS); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),FS); if (abrt) break; - SP-=2; - } - cycles-=2; - break; - case 0xA1: /*POP FS*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_fs); if (abrt) break; - ESP+=2; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_fs); if (abrt) break; - SP+=2; - } - cycles-=(is486)?3:7; - break; - case 0xA3: /*BT r16*/ - fetchea2(); - eaaddr+=((regs[reg].w/16)*2); eal_r = 0; - tempw=geteaw(); if (abrt) break; - if (tempw&(1<<(regs[reg].w&15))) flags|=C_FLAG; - else flags&=~C_FLAG; - cycles-=3; - break; - case 0xA4: /*SHLD imm*/ - fetchea2(); - temp=readmemb(cs,pc)&31; pc++; - if (temp) - { - tempw=geteaw(); if (abrt) break; - tempc=((tempw<<(temp-1))&0x8000)?1:0; - templ=(tempw<<16)|regs[reg].w; - if (temp<=16) tempw=templ>>(16-temp); - else tempw=(templ<>16; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - if (tempc) flags|=C_FLAG; - } - cycles-=3; - break; - case 0xA5: /*SHLD CL*/ - fetchea2(); - temp=CL&31; - if (temp) - { - tempw=geteaw(); if (abrt) break; - tempc=((tempw<<(temp-1))&0x8000)?1:0; - templ=(tempw<<16)|regs[reg].w; - if (temp<=16) tempw=templ>>(16-temp); - else tempw=(templ<>16; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - if (tempc) flags|=C_FLAG; - } - cycles-=3; - break; - case 0xA8: /*PUSH GS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,GS); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),GS); if (abrt) break; - SP-=2; - } - cycles-=2; - break; - case 0xA9: /*POP GS*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_gs); if (abrt) break; - ESP+=2; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_gs); if (abrt) break; - SP+=2; - } - cycles-=(is486)?3:7; - break; - case 0xAB: /*BTS r16*/ - fetchea2(); - eaaddr+=((regs[reg].w/16)*2); eal_r = eal_w = 0; - tempw=geteaw(); if (abrt) break; - tempc=(tempw&(1<<(regs[reg].w&15)))?1:0; - tempw|=(1<<(regs[reg].w&15)); - seteaw(tempw); if (abrt) break; - if (tempc) flags|=C_FLAG; - else flags&=~C_FLAG; - cycles-=6; - break; - case 0xAC: /*SHRD imm*/ - fetchea2(); - temp=readmemb(cs,pc)&31; pc++; - if (temp) - { - tempw=geteaw(); if (abrt) break; - tempc=(tempw>>(temp-1))&1; - templ=tempw|(regs[reg].w<<16); - tempw=templ>>temp; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - if (tempc) flags|=C_FLAG; - } - cycles-=3; - break; - case 0xAD: /*SHRD CL*/ - fetchea2(); - temp=CL&31; - if (temp) - { - tempw=geteaw(); if (abrt) break; - tempc=(tempw>>(temp-1))&1; - templ=tempw|(regs[reg].w<<16); - tempw=templ>>temp; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - if (tempc) flags|=C_FLAG; - } - cycles-=3; - break; - - case 0xAF: /*IMUL reg16,rm16*/ - fetchea2(); - templ=(int32_t)(int16_t)regs[reg].w*(int32_t)(int16_t)geteaw(); - if (abrt) break; - regs[reg].w=templ&0xFFFF; - if ((templ>>16) && (templ>>16)!=0xFFFF) flags|=C_FLAG|V_FLAG; - else flags&=~(C_FLAG|V_FLAG); - cycles-=18; - break; - - case 0xB0: /*CMPXCHG rm8, reg8*/ - if (!is486) goto inv16; - fetchea2(); - temp = geteab(); - setsub8(AL, temp); - if (AL == temp) seteab(getr8(reg)); - else AL = temp; - cycles -= (mod == 3) ? 6 : 10; - break; - case 0xB1: /*CMPXCHG rm16, reg16*/ - if (!is486) goto inv16; - fetchea2(); - tempw = geteaw(); - setsub16(AX, tempw); - if (AX == tempw) seteaw(regs[reg].w); - else AX = tempw; - cycles -= (mod == 3) ? 6 : 10; - break; - - case 0xB3: /*BTR r16*/ - fetchea2(); - eaaddr+=((regs[reg].w/16)*2); eal_r = eal_w = 0; - tempw=geteaw(); if (abrt) break; - tempc=tempw&(1<<(regs[reg].w&15)); - tempw&=~(1<<(regs[reg].w&15)); - seteaw(tempw); if (abrt) break; - if (tempc) flags|=C_FLAG; - else flags&=~C_FLAG; - cycles-=6; - break; - - case 0xB2: /*LSS*/ - fetchea2(); - tempw2=readmemw(easeg,eaaddr); - tempw=readmemw(easeg,(eaaddr+2)); if (abrt) break; - loadseg(tempw,&_ss); if (abrt) break; - regs[reg].w=tempw2; - oldss=ss; - cycles-=7; - break; - case 0xB4: /*LFS*/ - fetchea2(); - tempw2=readmemw(easeg,eaaddr); - tempw=readmemw(easeg,(eaaddr+2)); if (abrt) break; - loadseg(tempw,&_fs); if (abrt) break; - regs[reg].w=tempw2; - cycles-=7; - break; - case 0xB5: /*LGS*/ - fetchea2(); - tempw2=readmemw(easeg,eaaddr); - tempw=readmemw(easeg,(eaaddr+2)); if (abrt) break; - loadseg(tempw,&_gs); if (abrt) break; - regs[reg].w=tempw2; - cycles-=7; - break; - - case 0xB6: /*MOVZX b*/ - fetchea2(); - tempw=geteab(); if (abrt) break; - regs[reg].w=tempw; - cycles-=3; - break; - case 0xB7: /*MOVZX w*/ - fetchea2(); /*Slightly pointless?*/ - tempw=geteaw(); if (abrt) break; - regs[reg].w=tempw; - cycles-=3; - break; - case 0xBE: /*MOVSX b*/ - fetchea2(); - tempw=geteab(); if (abrt) break; - if (tempw&0x80) tempw|=0xFF00; - regs[reg].w=tempw; - cycles-=3; - break; - - case 0xBA: /*MORE?!?!?!*/ - fetchea2(); - switch (rmdat&0x38) - { - case 0x20: /*BT w,imm*/ - tempw=geteaw(); - temp=readmemb(cs,pc); pc++; if (abrt) break; - if (tempw&(1<= 0; tempi--) - { - cycles -= 3; - if (tempw & (1 << tempi)) - { - flags &= ~Z_FLAG; - regs[reg].w = tempi; - break; - } - } - } - cycles -= (is486) ? 6 : 10; - break; - - case 0xA2: /*CPUID*/ - if (CPUID) - { - cpu_CPUID(); - cycles-=9; - break; - } - goto inv16; - - case 0xC0: /*XADD b*/ - pclog("XADDb 16\n"); - fetchea2(); - temp=geteab(); if (abrt) break; - seteab(temp+getr8(reg)); if (abrt) break; - setadd8(temp,getr8(reg)); - setr8(reg,temp); - break; - case 0xC1: /*XADD w*/ - pclog("XADDw 16\n"); - fetchea2(); - tempw=geteaw(); if (abrt) break; - seteaw(tempw+regs[reg].w); if (abrt) break; - setadd16(tempw,regs[reg].w); - regs[reg].w=tempw; - break; - - case 0xA6: /*XBTS/CMPXCHG486*/ - pclog("CMPXCHG486\n"); -// output=1; - case 0xFF: /*Invalid - Windows 3.1 syscall trap?*/ - inv16: - pc-=2; - if (msw&1) - { - pmodeint(6,0); - } - else - { - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,flags); - writememw(ss,ESP-4,CS); - writememw(ss,ESP-6,pc); - ESP-=6; - } - else - { - writememw(ss,((SP-2)&0xFFFF),flags); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),pc); - SP-=6; - } - addr=6<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; - oxpc=pc; - pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - } - cycles-=70; - break; - - default: - pclog("Bad 16-bit 0F opcode %02X 386 %i\n",temp,ins); - pc=oldpc; - x86illegal(); - break; - } - break; - - case 0x10F: case 0x30F: - temp=fetchdat&0xFF/*readmemb(cs+pc)*/; pc++; - opcode2=temp; - switch (temp) - { - case 0: - if (!(cr0&1) || (eflags&VM_FLAG)) goto inv32; - fetchea2(); -// pclog("32-bit op %02X\n",rmdat&0x38); - switch (rmdat&0x38) - { - case 0x00: /*SLDT*/ - NOTRM - seteaw(ldt.seg); - cycles-=4; - break; - case 0x08: /*STR*/ - NOTRM - seteaw(tr.seg); - cycles-=4; - break; - case 0x10: /*LLDT*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) - { - pclog("Invalid LLDT32!\n"); - x86gpf(NULL,0); - break; - } - NOTRM - ldt.seg=geteaw(); if (abrt) break; - templ=(ldt.seg&~7)+gdt.base; - templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16); - templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24); - if (abrt) break; - ldt.limit=templ3; - ldt.base=templ2; - ldt.access=readmemb(0,templ+6); - if (readmemb(0,templ+6)&0x80) - { - ldt.limit<<=12; - ldt.limit|=0xFFF; - } -// /*if (output==3) */pclog("LLDT32 %04X %08X %04X\n",ldt.seg,ldt.base,ldt.limit,readmeml(0,templ),readmeml(0,templ+4)); - cycles-=20; - break; - case 0x18: /*LTR*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) - { - pclog("Invalid LTR32!\n"); - x86gpf(NULL,0); - break; - } - NOTRM - tempw=geteaw(); if (abrt) break; - tr.seg=tempw; - templ=(tempw&~7)+gdt.base; - templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16); - templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24); - temp=readmemb(0,templ+5); - if (abrt) break; - tr.seg=tempw; - tr.limit=templ3; - tr.access=readmemb(0,templ+6); - if (readmemb(0,templ+6)&0x80) - { - tr.limit<<=12; - tr.limit|=0xFFF; - } - tr.base=templ2; -// pclog("TR base = %08X\n",templ2); - tr.access=temp; - cycles-=20; - break; - - case 0x20: /*VERR*/ - NOTRM - tempw=geteaw(); if (abrt) break; - flags&=~Z_FLAG; - if (!(tempw&0xFFFC)) break; /*Null selector*/ - cpl_override=1; - tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit); - tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4); - cpl_override=0; - if (abrt) break; - if (!(tempw2&0x1000)) tempi=0; - if ((tempw2&0xC00)!=0xC00) /*Exclude conforming code segments*/ - { - tempw3=(tempw2>>13)&3; /*Check permissions*/ - if (tempw3>13)&3; /*Check permissions*/ - if (tempw3>13)&3; - if (tempw3>13)&3; - if (tempw3>31) flushmmucache(); - if ((regs[rm].l^cr0) & 0x80000001) flushmmucache(); - cr0=regs[rm].l;//&~2; - if (cpu_16bitbus) cr0 |= 0x10; -// if (cs<0xF0000 && cr0&1) output=3; - if (cr0&0x80000000) - { - } - else mmu_perm=4; - break; - case 2: - cr2=regs[rm].l; - break; - case 3: - cr3=regs[rm].l&~0xFFF; -// pclog("Loading CR3 with %08X at %08X:%08X\n",cr3,cs,pc); - flushmmucache(); - break; - default: - pclog("Bad load CR%i\n",reg); - pc=oldpc; - x86illegal(); - break; - } - cycles-=10; - break; - case 0x23: /*MOV DRx,reg32*/ - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) - { - pclog("Can't load DRx\n"); - x86gpf(NULL,0); - break; - } - fetchea2(); - cycles-=6; - break; - case 0x24: /*MOV reg32,TRx*/ - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) - { - pclog("Can't load from TRx\n"); - x86gpf(NULL,0); - break; - } - fetchea2(); - regs[rm].l=0; - cycles-=6; - break; - case 0x26: /*MOV TRx,reg32*/ - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) - { - pclog("Can't load TRx\n"); - x86gpf(NULL,0); - break; - } - fetchea2(); - cycles-=6; - break; - - case 0x80: /*JO*/ - templ=getlong(); if (abrt) break; - if (flags&V_FLAG) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x81: /*JNO*/ - templ=getlong(); if (abrt) break; - if (!(flags&V_FLAG)) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x82: /*JB*/ - templ=getlong(); if (abrt) break; - if (flags&C_FLAG) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x83: /*JNB*/ - templ=getlong(); if (abrt) break; - if (!(flags&C_FLAG)) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x84: /*JE*/ - templ=getlong(); if (abrt) break; - if (flags&Z_FLAG) pc+=templ; - cycles-=4; - break; - case 0x85: /*JNE*/ - templ=getlong(); if (abrt) break; - if (!(flags&Z_FLAG)) pc+=templ; - cycles-=4; - break; - case 0x86: /*JBE*/ - templ=getlong(); if (abrt) break; - if (flags&(C_FLAG|Z_FLAG)) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x87: /*JNBE*/ - templ=getlong(); if (abrt) break; - if (!(flags&(C_FLAG|Z_FLAG))) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x88: /*JS*/ - templ=getlong(); if (abrt) break; - if (flags&N_FLAG) pc+=templ; - cycles-=4; - break; - case 0x89: /*JNS*/ - templ=getlong(); if (abrt) break; - if (!(flags&N_FLAG)) pc+=templ; - cycles-=4; - break; - case 0x8A: /*JP*/ - templ=getlong(); if (abrt) break; - if (flags&P_FLAG) pc+=templ; - cycles-=4; - break; - case 0x8B: /*JNP*/ - templ=getlong(); if (abrt) break; - if (!(flags&P_FLAG)) pc+=templ; - cycles-=4; - break; - case 0x8C: /*JL*/ - templ=getlong(); if (abrt) break; - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp!=temp2) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x8D: /*JNL*/ - templ=getlong(); if (abrt) break; - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp==temp2) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x8E: /*JLE*/ - templ=getlong(); if (abrt) break; - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if ((flags&Z_FLAG) || (temp!=temp2)) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - case 0x8F: /*JNLE*/ - templ=getlong(); if (abrt) break; - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (!((flags&Z_FLAG) || (temp!=temp2))) { pc+=templ; cycles-=((is486)?2:4); } - cycles-=((is486)?1:3); - break; - - case 0x90: /*SETO*/ - fetchea2(); - seteab((flags&V_FLAG)?1:0); - cycles-=4; - break; - case 0x91: /*SETNO*/ - fetchea2(); - seteab((flags&V_FLAG)?0:1); - cycles-=4; - break; - case 0x92: /*SETC*/ - fetchea2(); - seteab((flags&C_FLAG)?1:0); - cycles-=4; - break; - case 0x93: /*SETAE*/ - fetchea2(); - seteab((flags&C_FLAG)?0:1); - cycles-=4; - break; - case 0x94: /*SETZ*/ - fetchea2(); - seteab((flags&Z_FLAG)?1:0); - cycles-=4; - break; - case 0x95: /*SETNZ*/ - fetchea2(); - seteab((flags&Z_FLAG)?0:1); - cycles-=4; - break; - case 0x96: /*SETBE*/ - fetchea2(); - seteab((flags&(C_FLAG|Z_FLAG))?1:0); - cycles-=4; - break; - case 0x97: /*SETNBE*/ - fetchea2(); - seteab((flags&(C_FLAG|Z_FLAG))?0:1); - cycles-=4; - break; - case 0x98: /*SETS*/ - fetchea2(); - seteab((flags&N_FLAG)?1:0); - cycles-=4; - break; - case 0x99: /*SETNS*/ - fetchea2(); - seteab((flags&N_FLAG)?0:1); - cycles-=4; - break; - case 0x9A: /*SETP*/ - fetchea2(); - seteab((flags&P_FLAG)?1:0); - cycles-=4; - break; - case 0x9B: /*SETNP*/ - fetchea2(); - seteab((flags&P_FLAG)?0:1); - cycles-=4; - break; - case 0x9C: /*SETL*/ - fetchea2(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - seteab(temp^temp2); - cycles-=4; - break; - case 0x9D: /*SETGE*/ - fetchea2(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - seteab((temp^temp2)?0:1); - cycles-=4; - break; - case 0x9E: /*SETLE*/ - fetchea2(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - seteab(((temp^temp2) || (flags&Z_FLAG))?1:0); - cycles-=4; - break; - case 0x9F: /*SETNLE*/ - fetchea2(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - seteab(((temp^temp2) || (flags&Z_FLAG))?0:1); - cycles-=4; - break; - - case 0xA0: /*PUSH FS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,FS); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),FS); if (abrt) break; - SP-=4; - } - cycles-=2; - break; - case 0xA1: /*POP FS*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_fs); if (abrt) break; - ESP+=4; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_fs); if (abrt) break; - SP+=4; - } - cycles-=(is486)?3:7; - break; - case 0xA8: /*PUSH GS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,GS); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),GS); if (abrt) break; - SP-=4; - } - cycles-=2; - break; - case 0xA9: /*POP GS*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_gs); if (abrt) break; - ESP+=4; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_gs); if (abrt) break; - SP+=4; - } - cycles-=(is486)?3:7; - break; - - case 0xA3: /*BT r32*/ - fetchea2(); - eaaddr+=((regs[reg].l/32)*4); eal_r = 0; - templ=geteal(); if (abrt) break; - if (templ&(1<<(regs[reg].l&31))) flags|=C_FLAG; - else flags&=~C_FLAG; - cycles-=3; - break; - case 0xA4: /*SHLD imm*/ - fetchea2(); - temp=readmemb(cs,pc)&31; pc++; - if (temp) - { - templ=geteal(); if (abrt) break; - tempc=((templ<<(temp-1))&0x80000000)?1:0; - templ=(templ<>(32-temp)); - seteal(templ); if (abrt) break; - setznp32(templ); - if (tempc) flags|=C_FLAG; - } - cycles-=3; - break; - case 0xA5: /*SHLD CL*/ - fetchea2(); - temp=CL&31; - if (temp) - { - templ=geteal(); if (abrt) break; - tempc=((templ<<(temp-1))&0x80000000)?1:0; - templ=(templ<>(32-temp)); - seteal(templ); if (abrt) break; - setznp32(templ); - if (tempc) flags|=C_FLAG; - } - cycles-=3; - break; - case 0xAB: /*BTS r32*/ - fetchea2(); - eaaddr+=((regs[reg].l/32)*4); eal_r = eal_w = 0; - templ=geteal(); if (abrt) break; - tempc=(templ&(1<<(regs[reg].l&31)))?1:0; - templ|=(1<<(regs[reg].l&31)); - seteal(templ); if (abrt) break; - if (tempc) flags|=C_FLAG; - else flags&=~C_FLAG; - cycles-=6; - break; - case 0xAC: /*SHRD imm*/ - fetchea2(); - temp=readmemb(cs,pc)&31; pc++; - if (temp) - { - templ=geteal(); if (abrt) break; - tempc=(templ>>(temp-1))&1; - templ=(templ>>temp)|(regs[reg].l<<(32-temp)); - seteal(templ); if (abrt) break; - setznp32(templ); - if (tempc) flags|=C_FLAG; - } - cycles-=3; - break; - case 0xAD: /*SHRD CL*/ - fetchea2(); - temp=CL&31; - if (temp) - { - templ=geteal(); if (abrt) break; - tempc=(templ>>(temp-1))&1; - templ=(templ>>temp)|(regs[reg].l<<(32-temp)); - seteal(templ); if (abrt) break; - setznp32(templ); - if (tempc) flags|=C_FLAG; - } - cycles-=3; - break; - - case 0xAF: /*IMUL reg32,rm32*/ - fetchea2(); - temp64=(int64_t)(int32_t)regs[reg].l*(int64_t)(int32_t)geteal(); - if (abrt) break; - regs[reg].l=temp64&0xFFFFFFFF; - if ((temp64>>32) && (temp64>>32)!=0xFFFFFFFF) flags|=C_FLAG|V_FLAG; - else flags&=~(C_FLAG|V_FLAG); - cycles-=30; - break; - - case 0xB0: /*CMPXCHG rm8, reg8*/ - if (!is486) goto inv32; - fetchea2(); - temp = geteab(); - setsub8(AL, temp); - if (AL == temp) seteab(getr8(reg)); - else AL = temp; - cycles -= (mod == 3) ? 6 : 10; - break; - case 0xB1: /*CMPXCHG rm32, reg32*/ - if (!is486) goto inv32; - fetchea2(); - templ = geteal(); - setsub32(EAX, templ); - if (EAX == templ) seteal(regs[reg].l); - else EAX = templ; - cycles -= (mod == 3) ? 6 : 10; - break; - - case 0xB3: /*BTR r32*/ - fetchea2(); - eaaddr+=((regs[reg].l/32)*4); eal_r = eal_w = 0; - templ=geteal(); if (abrt) break; - tempc=(templ&(1<<(regs[reg].l&31)))?1:0; - templ&=~(1<<(regs[reg].l&31)); - seteal(templ); if (abrt) break; - if (tempc) flags|=C_FLAG; - else flags&=~C_FLAG; - cycles-=6; - break; - - case 0xB2: /*LSS*/ - fetchea2(); - templ=readmeml(easeg,eaaddr); - tempw=readmemw(easeg,(eaaddr+4)); if (abrt) break; - loadseg(tempw,&_ss); if (abrt) break; - regs[reg].l=templ; - oldss=ss; - cycles-=7; - break; - case 0xB4: /*LFS*/ - fetchea2(); - templ=readmeml(easeg,eaaddr); - tempw=readmemw(easeg,(eaaddr+4)); if (abrt) break; - loadseg(tempw,&_fs); if (abrt) break; - regs[reg].l=templ; - cycles-=7; - break; - case 0xB5: /*LGS*/ - fetchea2(); - templ=readmeml(easeg,eaaddr); - tempw=readmemw(easeg,(eaaddr+4)); if (abrt) break; - loadseg(tempw,&_gs); if (abrt) break; - regs[reg].l=templ; - cycles-=7; - break; - - case 0xB6: /*MOVZX b*/ - fetchea2(); - templ=geteab(); if (abrt) break; - regs[reg].l=templ; - cycles-=3; - break; - case 0xB7: /*MOVZX w*/ - fetchea2(); - templ=geteaw(); if (abrt) break; - regs[reg].l=templ; - cycles-=3; -// if (pc==0x30B) output=1; - break; - - case 0xBA: /*MORE?!?!?!*/ - fetchea2(); - switch (rmdat&0x38) - { - case 0x20: /*BT l,imm*/ - templ=geteal(); - temp=readmemb(cs,pc); pc++; - if (abrt) break; - if (templ&(1<=0;tempi--) - { - cycles -= 3; - if (templ&(1<>24)|((regs[temp&7].l>>8)&0xFF00)|((regs[temp&7].l<<8)&0xFF0000)|((regs[temp&7].l<<24)&0xFF000000); - cycles--; - break; - - case 0xA2: /*CPUID*/ - if (CPUID) - { - cpu_CPUID(); - cycles-=9; - break; - } - goto inv32; - - case 0xFF: - inv32: - pclog("INV32!\n"); - default: - pclog("Bad 32-bit 0F opcode %02X 386\n",temp); - pc=oldpc; - x86illegal(); - break; - } - break; - - case 0x10: case 0x110: case 0x210: case 0x310: /*ADC 8,reg*/ - fetchea(); - if (mod == 3) - { - temp = getr8(rm); - temp2 = getr8(reg); - setadc8(temp, temp2); - setr8(rm, temp + temp2 + tempc); - cycles -= timing_rr; - } - else - { - temp = geteab(); if (abrt) break; - temp2 = getr8(reg); - seteab(temp + temp2 + tempc); if (abrt) break; - setadc8(temp, temp2); - cycles -= timing_mr; - } - break; - case 0x11: case 0x211: /*ADC 16,reg*/ - fetchea(); - if (mod == 3) - { - setadc16(regs[rm].w, regs[reg].w); - regs[rm].w += regs[reg].w + tempc; - cycles -= timing_rr; - } - else - { - tempw = geteaw(); if (abrt) break; - tempw2 = regs[reg].w; - seteaw(tempw + tempw2 + tempc); if (abrt) break; - setadc16(tempw, tempw2); - cycles -= timing_mr; - } - break; - case 0x111: case 0x311: /*ADC 32,reg*/ - fetchea(); - if (mod == 3) - { - setadc32(regs[rm].l, regs[reg].l); - regs[rm].l += regs[reg].l + tempc; - cycles -= timing_rr; - } - else - { - templ = geteal(); if (abrt) break; - templ2 = regs[reg].l; - seteal(templ + templ2 + tempc); if (abrt) break; - setadc32(templ, templ2); - cycles -= timing_mrl; - } - break; - case 0x12: case 0x112: case 0x212: case 0x312: /*ADC reg,8*/ - fetchea(); - temp=geteab(); if (abrt) break; - setadc8(getr8(reg),temp); - setr8(reg,getr8(reg)+temp+tempc); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x13: case 0x213: /*ADC reg,16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - setadc16(regs[reg].w,tempw); - regs[reg].w+=tempw+tempc; - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x113: case 0x313: /*ADC reg,32*/ - fetchea(); - templ=geteal(); if (abrt) break; - setadc32(regs[reg].l,templ); - regs[reg].l+=templ+tempc; - cycles -= (mod == 3) ? timing_rr : timing_rml; - break; - case 0x14: case 0x114: case 0x214: case 0x314: /*ADC AL,#8*/ - tempw=getbytef(); - setadc8(AL,tempw); - AL+=tempw+tempc; - cycles -= timing_rr; - break; - case 0x15: case 0x215: /*ADC AX,#16*/ - tempw=getwordf(); - setadc16(AX,tempw); - AX+=tempw+tempc; - cycles -= timing_rr; - break; - case 0x115: case 0x315: /*ADC EAX,#32*/ - templ=getlong(); if (abrt) break; - setadc32(EAX,templ); - EAX+=templ+tempc; - cycles -= timing_rr; - break; - - case 0x16: case 0x216: /*PUSH SS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,SS); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),SS); if (abrt) break; - SP-=2; - } - cycles-=2; - break; - case 0x116: case 0x316: /*PUSH SS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,SS); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),SS); if (abrt) break; - SP-=4; - } - cycles-=2; - break; - case 0x17: case 0x217: /*POP SS*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_ss); if (abrt) break; - ESP+=2; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_ss); if (abrt) break; - SP+=2; - } - cycles-=(is486)?3:7; - break; - case 0x117: case 0x317: /*POP SS*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_ss); if (abrt) break; - ESP+=4; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_ss); if (abrt) break; - SP+=4; - } - cycles-=(is486)?3:7; - break; - - case 0x18: case 0x118: case 0x218: case 0x318: /*SBB 8,reg*/ - fetchea(); - if (mod == 3) - { - temp = getr8(rm); - temp2 = getr8(reg); - setsbc8(temp, temp2); - setr8(rm, temp - (temp2 + tempc)); - cycles -= timing_rr; - } - else - { - temp = geteab(); if (abrt) break; - temp2 = getr8(reg); - seteab(temp - (temp2 + tempc)); if (abrt) break; - setsbc8(temp, temp2); - cycles -= timing_mr; - } - break; - case 0x19: case 0x219: /*SBB 16,reg*/ - fetchea(); - if (mod == 3) - { - setsbc16(regs[rm].w, regs[reg].w); - regs[rm].w -= (regs[reg].w + tempc); - cycles -= timing_rr; - } - else - { - tempw = geteaw(); if (abrt) break; - tempw2 = regs[reg].w; - seteaw(tempw - (tempw2 + tempc)); if (abrt) break; - setsbc16(tempw, tempw2); - cycles -= timing_mr; - } - break; - case 0x119: case 0x319: /*SBB 32,reg*/ - fetchea(); - if (mod == 3) - { - setsbc32(regs[rm].l, regs[reg].l); - regs[rm].l -= (regs[reg].l + tempc); - cycles -= timing_rr; - } - else - { - templ = geteal(); if (abrt) break; - templ2 = regs[reg].l; - seteal(templ - (templ2 + tempc)); if (abrt) break; - setsbc32(templ, templ2); - cycles -= timing_mrl; - } - break; - case 0x1A: case 0x11A: case 0x21A: case 0x31A: /*SBB reg,8*/ - fetchea(); - temp=geteab(); if (abrt) break; - setsbc8(getr8(reg),temp); - setr8(reg,getr8(reg)-(temp+tempc)); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x1B: case 0x21B: /*SBB reg,16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw2=regs[reg].w; - setsbc16(tempw2,tempw); - tempw2-=(tempw+tempc); - regs[reg].w=tempw2; - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x11B: case 0x31B: /*SBB reg,32*/ - fetchea(); - templ=geteal(); if (abrt) break; - templ2=regs[reg].l; - setsbc32(templ2,templ); - templ2-=(templ+tempc); - regs[reg].l=templ2; - cycles -= (mod == 3) ? timing_rr : timing_rml; - break; - case 0x1C: case 0x11C: case 0x21C: case 0x31C: /*SBB AL,#8*/ - temp=getbytef(); - setsbc8(AL,temp); - AL-=(temp+tempc); - cycles-=(is486)?1:2; - break; - case 0x1D: case 0x21D: /*SBB AX,#16*/ - tempw=getwordf(); - setsbc16(AX,tempw); - AX-=(tempw+tempc); - cycles-=(is486)?1:2; - break; - case 0x11D: case 0x31D: /*SBB AX,#32*/ - templ=getlong(); if (abrt) break; - setsbc32(EAX,templ); - EAX-=(templ+tempc); - cycles-=(is486)?1:2; - break; - - case 0x1E: case 0x21E: /*PUSH DS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,DS); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),DS); if (abrt) break; - SP-=2; - } - cycles-=2; - break; - case 0x11E: case 0x31E: /*PUSH DS*/ - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,DS); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),DS); if (abrt) break; - SP-=4; - } - cycles-=2; - break; - case 0x1F: case 0x21F: /*POP DS*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_ds); if (abrt) break; - ESP+=2; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_ds); if (abrt) break; - SP+=2; - } - cycles-=(is486)?3:7; - break; - case 0x11F: case 0x31F: /*POP DS*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - loadseg(tempw,&_ds); if (abrt) break; - ESP+=4; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - loadseg(tempw,&_ds); if (abrt) break; - SP+=4; - } - cycles-=(is486)?3:7; - break; - - case 0x20: case 0x120: case 0x220: case 0x320: /*AND 8,reg*/ - fetchea(); - if (mod == 3) - { - temp = getr8(rm) & getr8(reg); - setr8(rm, temp); - setznp8(temp); - cycles -= timing_rr; - } - else - { - temp = geteab(); if (abrt) break; - temp &= getr8(reg); - seteab(temp); if (abrt) break; - setznp8(temp); - cycles -= timing_mr; - } - break; - case 0x21: case 0x221: /*AND 16,reg*/ - fetchea(); - if (mod == 3) - { - regs[rm].w &= regs[reg].w; - setznp16(regs[rm].w); - cycles -= timing_rr; - } - else - { - tempw = geteaw() & regs[reg].w; if (abrt) break; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= timing_mr; - } - break; - case 0x121: case 0x321: /*AND 32,reg*/ - fetchea(); - if (mod == 3) - { - regs[rm].l &= regs[reg].l; - setznp32(regs[rm].l); - cycles -= timing_rr; - } - else - { - templ = geteal() & regs[reg].l; if (abrt) break; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= timing_mrl; - } - break; - case 0x22: case 0x122: case 0x222: case 0x322: /*AND reg,8*/ - fetchea(); - temp=geteab(); if (abrt) break; - temp&=getr8(reg); - setznp8(temp); - setr8(reg,temp); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x23: case 0x223: /*AND reg,16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw&=regs[reg].w; - setznp16(tempw); - regs[reg].w=tempw; - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x123: case 0x323: /*AND reg,32*/ - fetchea(); - templ=geteal(); if (abrt) break; - templ&=regs[reg].l; - setznp32(templ); - regs[reg].l=templ; - cycles -= (mod == 3) ? timing_rr : timing_rml; - break; - case 0x24: case 0x124: case 0x224: case 0x324: /*AND AL,#8*/ - AL&=getbytef(); - setznp8(AL); - cycles -= timing_rr; - break; - case 0x25: case 0x225: /*AND AX,#16*/ - AX&=getwordf(); - setznp16(AX); - cycles -= timing_rr; - break; - case 0x125: case 0x325: /*AND EAX,#32*/ - templ=getlong(); if (abrt) break; - EAX&=templ; - setznp32(EAX); - cycles -= timing_rr; - break; - - case 0x26: case 0x126: case 0x226: case 0x326: /*ES:*/ - oldss=ss; - oldds=ds; - ds=ss=es; - rds=ES; - ssegs=2; - cycles-=4; - goto opcodestart; -// break; - - case 0x27: case 0x127: case 0x227: case 0x327: /*DAA*/ - if ((flags & A_FLAG) || ((AL & 0xF) > 9)) - { - tempi = ((uint16_t)AL) + 6; - AL += 6; - flags |= A_FLAG; - if (tempi & 0x100) flags |= C_FLAG; - } -// else -// flags&=~A_FLAG; - if ((flags&C_FLAG) || (AL>0x9F)) - { - AL+=0x60; - flags|=C_FLAG; - } -// else -// flags&=~C_FLAG; - tempw = flags & (C_FLAG | A_FLAG); - setznp8(AL); - flags |= tempw; - cycles-=4; - break; - - case 0x28: case 0x128: case 0x228: case 0x328: /*SUB 8,reg*/ - fetchea(); - if (mod == 3) - { - temp = getr8(rm); - temp2 = getr8(reg); - setsub8(temp, temp2); - setr8(rm, temp - temp2); - cycles -= timing_rr; - } - else - { - temp = geteab(); if (abrt) break; - temp2 = getr8(reg); - seteab(temp - temp2); if (abrt) break; - setsub8(temp, temp2); - cycles -= timing_mr; - } - break; - case 0x29: case 0x229: /*SUB 16,reg*/ - fetchea(); - if (mod == 3) - { - setsub16(regs[rm].w, regs[reg].w); - regs[rm].w -= regs[reg].w; - cycles -= timing_rr; - } - else - { - tempw = geteaw(); if (abrt) break; - seteaw(tempw - regs[reg].w); if (abrt) break; - setsub16(tempw, regs[reg].w); - cycles -= timing_mr; - } - break; - case 0x129: case 0x329: /*SUB 32,reg*/ - fetchea(); - if (mod == 3) - { - setsub32(regs[rm].l, regs[reg].l); - regs[rm].l -= regs[reg].l; - cycles -= timing_rr; - } - else - { - templ = geteal(); if (abrt) break; - seteal(templ - regs[reg].l); if (abrt) break; - setsub32(templ, regs[reg].l); - cycles -= timing_mrl; - } - break; - case 0x2A: case 0x12A: case 0x22A: case 0x32A: /*SUB reg,8*/ - fetchea(); - temp=geteab(); if (abrt) break; - setsub8(getr8(reg),temp); - setr8(reg,getr8(reg)-temp); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x2B: case 0x22B: /*SUB reg,16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - setsub16(regs[reg].w,tempw); - regs[reg].w-=tempw; - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x12B: case 0x32B: /*SUB reg,32*/ - fetchea(); - templ=geteal(); if (abrt) break; - setsub32(regs[reg].l,templ); - regs[reg].l-=templ; - cycles -= (mod == 3) ? timing_rr : timing_rml; - break; - case 0x2C: case 0x12C: case 0x22C: case 0x32C: /*SUB AL,#8*/ - temp=getbytef(); - setsub8(AL,temp); - AL-=temp; - cycles -= timing_rr; - break; - case 0x2D: case 0x22D: /*SUB AX,#16*/ - tempw=getwordf(); - setsub16(AX,tempw); - AX-=tempw; - cycles -= timing_rr; - break; - case 0x12D: case 0x32D: /*SUB EAX,#32*/ - templ=getlong(); if (abrt) break; - setsub32(EAX,templ); - EAX-=templ; - cycles -= timing_rr; - break; - - case 0x2E: case 0x12E: case 0x22E: case 0x32E: /*CS:*/ - oldss=ss; - oldds=ds; - ds=ss=cs; - rds=CS; - ssegs=2; - cycles-=4; - goto opcodestart; - case 0x2F: case 0x12F: case 0x22F: case 0x32F: /*DAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - tempi=((uint16_t)AL)-6; - AL-=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; - } -// else -// flags&=~A_FLAG; - if ((flags&C_FLAG)||(AL>0x9F)) - { - AL-=0x60; - flags|=C_FLAG; - } -// else -// flags&=~C_FLAG; - tempw = flags & (C_FLAG | A_FLAG); - setznp8(AL); - flags |= tempw; - cycles-=4; - break; - - case 0x30: case 0x130: case 0x230: case 0x330: /*XOR 8,reg*/ - fetchea(); - if (mod == 3) - { - temp = getr8(rm) ^ getr8(reg); - setr8(rm, temp); - setznp8(temp); - cycles -= timing_rr; - } - else - { - temp = geteab(); if (abrt) break; - temp ^= getr8(reg); - seteab(temp); if (abrt) break; - setznp8(temp); - cycles -= timing_mr; - } - break; - case 0x31: case 0x231: /*XOR 16,reg*/ - fetchea(); - if (mod == 3) - { - regs[rm].w ^= regs[reg].w; - setznp16(regs[rm].w); - cycles -= timing_rr; - } - else - { - tempw = geteaw() ^ regs[reg].w; if (abrt) break; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= timing_mr; - } - break; - case 0x131: case 0x331: /*XOR 32,reg*/ - fetchea(); - if (mod == 3) - { - regs[rm].l ^= regs[reg].l; - setznp32(regs[rm].l); - cycles -= timing_rr; - } - else - { - templ = geteal() ^ regs[reg].l; if (abrt) break; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= timing_mrl; - } - break; - case 0x32: case 0x132: case 0x232: case 0x332: /*XOR reg,8*/ - fetchea(); - temp=geteab(); if (abrt) break; - temp^=getr8(reg); - setznp8(temp); - setr8(reg,temp); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x33: case 0x233: /*XOR reg,16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw^=regs[reg].w; - setznp16(tempw); - regs[reg].w=tempw; - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x133: case 0x333: /*XOR reg,32*/ - fetchea(); - templ=geteal(); if (abrt) break; - templ^=regs[reg].l; - setznp32(templ); - regs[reg].l=templ; - cycles -= (mod == 3) ? timing_rr : timing_rml; - break; - case 0x34: case 0x134: case 0x234: case 0x334: /*XOR AL,#8*/ - AL^=getbytef(); - setznp8(AL); - cycles -= timing_rr; - break; - case 0x35: case 0x235: /*XOR AX,#16*/ - AX^=getwordf(); - setznp16(AX); - cycles -= timing_rr; - break; - case 0x135: case 0x335: /*XOR EAX,#32*/ - templ=getlong(); if (abrt) break; - EAX^=templ; - setznp32(EAX); - cycles -= timing_rr; - break; - - case 0x36: case 0x136: case 0x236: case 0x336: /*SS:*/ - oldss=ss; - oldds=ds; - ds=ss=ss; - rds=SS; - ssegs=2; - cycles-=4; - goto opcodestart; -// break; - - case 0x37: case 0x137: case 0x237: case 0x337: /*AAA*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - AL+=6; - AH++; - flags|=(A_FLAG|C_FLAG); - } - else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=(is486)?3:4; - break; - - case 0x38: case 0x138: case 0x238: case 0x338: /*CMP 8,reg*/ - fetchea(); - temp=geteab(); if (abrt) break; - setsub8(temp,getr8(reg)); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x39: case 0x239: /*CMP 16,reg*/ - fetchea(); - tempw=geteaw(); if (abrt) break; -// if (output) pclog("CMP %04X %04X\n",tempw,regs[reg].w); - setsub16(tempw,regs[reg].w); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x139: case 0x339: /*CMP 32,reg*/ - fetchea(); - templ=geteal(); if (abrt) break; - setsub32(templ,regs[reg].l); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x3A: case 0x13A: case 0x23A: case 0x33A: /*CMP reg,8*/ - fetchea(); - temp=geteab(); if (abrt) break; -// if (output) pclog("CMP %02X-%02X\n",getr8(reg),temp); - setsub8(getr8(reg),temp); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x3B: case 0x23B: /*CMP reg,16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - setsub16(regs[reg].w,tempw); - cycles -= (mod == 3) ? timing_rr : timing_rm; - break; - case 0x13B: case 0x33B: /*CMP reg,32*/ - fetchea(); - templ=geteal(); if (abrt) break; - setsub32(regs[reg].l,templ); - cycles -= (mod == 3) ? timing_rr : timing_rml; - break; - case 0x3C: case 0x13C: case 0x23C: case 0x33C: /*CMP AL,#8*/ - temp=getbytef(); - setsub8(AL,temp); - cycles -= timing_rr; - break; - case 0x3D: case 0x23D: /*CMP AX,#16*/ - tempw=getwordf(); - setsub16(AX,tempw); - cycles -= timing_rr; - break; - case 0x13D: case 0x33D: /*CMP EAX,#32*/ - templ=getlong(); if (abrt) break; - setsub32(EAX,templ); - cycles -= timing_rr; - break; - - case 0x3E: case 0x13E: case 0x23E: case 0x33E: /*DS:*/ - oldss=ss; - oldds=ds; - ds=ss=ds; - ssegs=2; - cycles-=4; - goto opcodestart; -// break; - - case 0x3F: case 0x13F: case 0x23F: case 0x33F: /*AAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - AL-=6; - AH--; - flags|=(A_FLAG|C_FLAG); - } - else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=(is486)?3:4; - break; - - case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/ - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x240: case 0x241: case 0x242: case 0x243: - case 0x244: case 0x245: case 0x246: case 0x247: - setadd16nc(regs[opcode&7].w,1); - regs[opcode&7].w++; - cycles -= timing_rr; - break; - case 0x140: case 0x141: case 0x142: case 0x143: /*INC r32*/ - case 0x144: case 0x145: case 0x146: case 0x147: - case 0x340: case 0x341: case 0x342: case 0x343: - case 0x344: case 0x345: case 0x346: case 0x347: - setadd32nc(regs[opcode&7].l,1); - regs[opcode&7].l++; - cycles -= timing_rr; - break; - case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/ - case 0x4C: case 0x4D: case 0x4E: case 0x4F: - case 0x248: case 0x249: case 0x24A: case 0x24B: - case 0x24C: case 0x24D: case 0x24E: case 0x24F: - setsub16nc(regs[opcode&7].w,1); - regs[opcode&7].w--; - cycles -= timing_rr; - break; - case 0x148: case 0x149: case 0x14A: case 0x14B: /*DEC r32*/ - case 0x14C: case 0x14D: case 0x14E: case 0x14F: - case 0x348: case 0x349: case 0x34A: case 0x34B: - case 0x34C: case 0x34D: case 0x34E: case 0x34F: - setsub32nc(regs[opcode&7].l,1); - regs[opcode&7].l--; - cycles -= timing_rr; - break; - - case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ - case 0x54: case 0x55: case 0x56: case 0x57: - case 0x250: case 0x251: case 0x252: case 0x253: - case 0x254: case 0x255: case 0x256: case 0x257: - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,regs[opcode&7].w); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,(SP-2)&0xFFFF,regs[opcode&7].w); if (abrt) break; - SP-=2; - } -// if (pc>=0x1A1BED && pc<0x1A1C00) pclog("PUSH %02X! %08X\n",opcode,ESP); - cycles-=(is486)?1:2; - break; - case 0x150: case 0x151: case 0x152: case 0x153: /*PUSH r32*/ - case 0x154: case 0x155: case 0x156: case 0x157: - case 0x350: case 0x351: case 0x352: case 0x353: - case 0x354: case 0x355: case 0x356: case 0x357: - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,regs[opcode&7].l); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,(SP-4)&0xFFFF,regs[opcode&7].l); if (abrt) break; - SP-=4; - } - cycles-=(is486)?1:2; - break; - case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ - case 0x5C: case 0x5D: case 0x5E: case 0x5F: - case 0x258: case 0x259: case 0x25A: case 0x25B: - case 0x25C: case 0x25D: case 0x25E: case 0x25F: - if (ssegs) ss=oldss; - if (stack32) - { - ESP+=2; - tempw=readmemw(ss,ESP-2); if (abrt) { ESP-=2; break; } - } - else - { - SP+=2; - tempw=readmemw(ss,(SP-2)&0xFFFF); if (abrt) { SP-=2; break; } - } - regs[opcode&7].w=tempw; - cycles-=(is486)?1:4; - break; - case 0x158: case 0x159: case 0x15A: case 0x15B: /*POP r32*/ - case 0x15C: case 0x15D: case 0x15E: case 0x15F: - case 0x358: case 0x359: case 0x35A: case 0x35B: - case 0x35C: case 0x35D: case 0x35E: case 0x35F: - if (ssegs) ss=oldss; - if (stack32) - { - ESP+=4; - templ=readmeml(ss,ESP-4); if (abrt) { ESP-=4; break; } - } - else - { - SP+=4; - templ=readmeml(ss,(SP-4)&0xFFFF); if (abrt) { SP-=4; break; } - } - regs[opcode&7].l=templ; - cycles-=(is486)?1:4; - break; - - case 0x60: case 0x260: /*PUSHA*/ - if (stack32) - { - writememw(ss,ESP-2,AX); - writememw(ss,ESP-4,CX); - writememw(ss,ESP-6,DX); - writememw(ss,ESP-8,BX); - writememw(ss,ESP-10,SP); - writememw(ss,ESP-12,BP); - writememw(ss,ESP-14,SI); - writememw(ss,ESP-16,DI); - if (!abrt) ESP-=16; - } - else - { - writememw(ss,((SP-2)&0xFFFF),AX); - writememw(ss,((SP-4)&0xFFFF),CX); - writememw(ss,((SP-6)&0xFFFF),DX); - writememw(ss,((SP-8)&0xFFFF),BX); - writememw(ss,((SP-10)&0xFFFF),SP); - writememw(ss,((SP-12)&0xFFFF),BP); - writememw(ss,((SP-14)&0xFFFF),SI); - writememw(ss,((SP-16)&0xFFFF),DI); - if (!abrt) SP-=16; - } - cycles-=(is486)?11:18; - break; - case 0x61: case 0x261: /*POPA*/ - if (stack32) - { - DI=readmemw(ss,ESP); if (abrt) break; - SI=readmemw(ss,ESP+2); if (abrt) break; - BP=readmemw(ss,ESP+4); if (abrt) break; - BX=readmemw(ss,ESP+8); if (abrt) break; - DX=readmemw(ss,ESP+10); if (abrt) break; - CX=readmemw(ss,ESP+12); if (abrt) break; - AX=readmemw(ss,ESP+14); if (abrt) break; - ESP+=16; - } - else - { - DI=readmemw(ss,((SP)&0xFFFF)); if (abrt) break; - SI=readmemw(ss,((SP+2)&0xFFFF)); if (abrt) break; - BP=readmemw(ss,((SP+4)&0xFFFF)); if (abrt) break; - BX=readmemw(ss,((SP+8)&0xFFFF)); if (abrt) break; - DX=readmemw(ss,((SP+10)&0xFFFF)); if (abrt) break; - CX=readmemw(ss,((SP+12)&0xFFFF)); if (abrt) break; - AX=readmemw(ss,((SP+14)&0xFFFF)); if (abrt) break; - SP+=16; - } - cycles-=(is486)?9:24; - break; - case 0x160: case 0x360: /*PUSHA*/ - if (stack32) - { - writememl(ss,ESP-4,EAX); - writememl(ss,ESP-8,ECX); - writememl(ss,ESP-12,EDX); - writememl(ss,ESP-16,EBX); - writememl(ss,ESP-20,ESP); - writememl(ss,ESP-24,EBP); - writememl(ss,ESP-28,ESI); - writememl(ss,ESP-32,EDI); - if (!abrt) ESP-=32; - } - else - { - writememl(ss,((SP-4)&0xFFFF),EAX); - writememl(ss,((SP-8)&0xFFFF),ECX); - writememl(ss,((SP-12)&0xFFFF),EDX); - writememl(ss,((SP-16)&0xFFFF),EBX); - writememl(ss,((SP-20)&0xFFFF),ESP); - writememl(ss,((SP-24)&0xFFFF),EBP); - writememl(ss,((SP-28)&0xFFFF),ESI); - writememl(ss,((SP-32)&0xFFFF),EDI); - if (!abrt) SP-=32; - } - cycles-=(is486)?11:18; - break; - case 0x161: case 0x361: /*POPA*/ - if (stack32) - { - EDI=readmeml(ss,ESP); if (abrt) break; - ESI=readmeml(ss,ESP+4); if (abrt) break; - EBP=readmeml(ss,ESP+8); if (abrt) break; - EBX=readmeml(ss,ESP+16); if (abrt) break; - EDX=readmeml(ss,ESP+20); if (abrt) break; - ECX=readmeml(ss,ESP+24); if (abrt) break; - EAX=readmeml(ss,ESP+28); if (abrt) break; - ESP+=32; - } - else - { - EDI=readmeml(ss,((SP)&0xFFFF)); if (abrt) break; - ESI=readmeml(ss,((SP+4)&0xFFFF)); if (abrt) break; - EBP=readmeml(ss,((SP+8)&0xFFFF)); if (abrt) break; - EBX=readmeml(ss,((SP+16)&0xFFFF)); if (abrt) break; - EDX=readmeml(ss,((SP+20)&0xFFFF)); if (abrt) break; - ECX=readmeml(ss,((SP+24)&0xFFFF)); if (abrt) break; - EAX=readmeml(ss,((SP+28)&0xFFFF)); if (abrt) break; - SP+=32; - } - cycles-=(is486)?9:24; - break; - - case 0x62: case 0x262: /*BOUND*/ - fetchea(); - tempw=geteaw(); - tempw2=readmemw(easeg,eaaddr+2); if (abrt) break; - if (((int16_t)regs[reg].w<(int16_t)tempw) || ((int16_t)regs[reg].w>(int16_t)tempw2)) - { - x86_int(5); - } - cycles-=(is486)?7:10; - break; - case 0x162: case 0x362: /*BOUND*/ - fetchea(); - templ=geteal(); - templ2=readmeml(easeg,eaaddr+4); if (abrt) break; - if (((int32_t)regs[reg].l<(int32_t)templ) || ((int32_t)regs[reg].l>(int32_t)templ2)) - { - x86_int(5); - } - cycles-=(is486)?7:10; - break; - - - case 0x63: case 0x163: case 0x263: case 0x363: /*ARPL*/ - NOTRM - fetchea(); - tempw=geteaw(); if (abrt) break; - if ((tempw&3)<(regs[reg].w&3)) - { - tempw=(tempw&0xFFFC)|(regs[reg].w&3); - seteaw(tempw); if (abrt) break; - flags|=Z_FLAG; - } - else - flags&=~Z_FLAG; - cycles-=(is486)?9:20; - break; - case 0x64: case 0x164: case 0x264: case 0x364: /*FS:*/ - oldss=ss; - oldds=ds; - rds=FS; - ds=ss=fs; - ssegs=2; - cycles-=4; - goto opcodestart; - case 0x65: case 0x165: case 0x265: case 0x365: /*GS:*/ - oldss=ss; - oldds=ds; - rds=GS; - ds=ss=gs; - ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x66: case 0x166: case 0x266: case 0x366: /*Data size select*/ - op32=((use32&0x100)^0x100)|(op32&0x200); -// op32^=0x100; - cycles-=2; - goto opcodestart; - case 0x67: case 0x167: case 0x267: case 0x367: /*Address size select*/ - op32=((use32&0x200)^0x200)|(op32&0x100); -// op32^=0x200; - cycles-=2; - goto opcodestart; - - case 0x68: case 0x268: /*PUSH #w*/ - tempw=getword(); - if (stack32) - { - writememw(ss,ESP-2,tempw); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),tempw); if (abrt) break; - SP-=2; - } - cycles-=2; - break; - case 0x168: case 0x368: /*PUSH #l*/ - templ=getlong(); - if (stack32) - { - writememl(ss,ESP-4,templ); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),templ); if (abrt) break; - SP-=4; - } - cycles-=2; - break; - case 0x69: case 0x269: /*IMUL r16*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw2=getword(); if (abrt) break; - templ=((int)(int16_t)tempw)*((int)(int16_t)tempw2); - if ((templ>>16)!=0 && (templ>>16)!=0xFFFF) flags|=C_FLAG|V_FLAG; - else flags&=~(C_FLAG|V_FLAG); - regs[reg].w=templ&0xFFFF; - cycles-=((mod==3)?14:17); - break; - case 0x169: case 0x369: /*IMUL r32*/ - fetchea(); - templ=geteal(); if (abrt) break; - templ2=getlong(); if (abrt) break; - temp64=((int64_t)(int32_t)templ)*((int64_t)(int32_t)templ2); - if ((temp64>>32)!=0 && (temp64>>32)!=0xFFFFFFFF) flags|=C_FLAG|V_FLAG; - else flags&=~(C_FLAG|V_FLAG); - regs[reg].l=temp64&0xFFFFFFFF; - cycles-=25; - break; - case 0x6A: case 0x26A:/*PUSH #eb*/ - tempw=readmemb(cs,pc); pc++; - if (tempw&0x80) tempw|=0xFF00; - if (output) pclog("PUSH %04X %i\n",tempw,stack32); - if (stack32) - { - writememw(ss,ESP-2,tempw); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),tempw); if (abrt) break; - SP-=2; - } - cycles-=2; - break; - case 0x16A: case 0x36A:/*PUSH #eb*/ - templ=readmemb(cs,pc); pc++; - if (templ&0x80) templ|=0xFFFFFF00; - if (output) pclog("PUSH %08X %i\n",templ,stack32); - if (stack32) - { - writememl(ss,ESP-4,templ); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),templ); if (abrt) break; - SP-=4; - } - cycles-=2; - break; -// #if 0 - case 0x6B: case 0x26B: /*IMUL r8*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw2=readmemb(cs,pc); pc++; if (abrt) break; - if (tempw2&0x80) tempw2|=0xFF00; - templ=((int)(int16_t)tempw)*((int)(int16_t)tempw2); -// pclog("IMULr8 %08X %08X %08X\n",tempw,tempw2,templ); - if ((templ>>16)!=0 && ((templ>>16)&0xFFFF)!=0xFFFF) flags|=C_FLAG|V_FLAG; - else flags&=~(C_FLAG|V_FLAG); - regs[reg].w=templ&0xFFFF; - cycles-=((mod==3)?14:17); - break; - case 0x16B: case 0x36B: /*IMUL r8*/ - fetchea(); - templ=geteal(); if (abrt) break; - templ2=readmemb(cs,pc); pc++; if (abrt) break; - if (templ2&0x80) templ2|=0xFFFFFF00; - temp64=((int64_t)(int32_t)templ)*((int64_t)(int32_t)templ2); -// pclog("IMULr8 %08X %08X %i\n",templ,templ2,temp64i>>32); - if ((temp64>>32)!=0 && (temp64>>32)!=0xFFFFFFFF) flags|=C_FLAG|V_FLAG; - else flags&=~(C_FLAG|V_FLAG); - regs[reg].l=temp64&0xFFFFFFFF; - cycles-=20; - break; -//#endif - case 0x6C: case 0x16C: /*INSB*/ - checkio_perm(DX); - temp=inb(DX); - writememb(es,DI,temp); if (abrt) break; - if (flags&D_FLAG) DI--; - else DI++; - cycles-=15; - break; - case 0x26C: case 0x36C: /*INSB*/ - checkio_perm(DX); - temp=inb(DX); - writememb(es,EDI,temp); if (abrt) break; - if (flags&D_FLAG) EDI--; - else EDI++; - cycles-=15; - break; - case 0x6D: /*INSW*/ - checkio_perm(DX); - checkio_perm(DX+1); - tempw=inw(DX); - writememw(es,DI,tempw); if (abrt) break; - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=15; - break; - case 0x16D: /*INSL*/ - checkio_perm(DX); - checkio_perm(DX+1); - checkio_perm(DX+2); - checkio_perm(DX+3); - templ=inl(DX); - writememl(es,DI,templ); if (abrt) break; - if (flags&D_FLAG) DI-=4; - else DI+=4; - cycles-=15; - break; - case 0x26D: /*INSW*/ - checkio_perm(DX); - checkio_perm(DX+1); - tempw=inw(DX); - writememw(es,EDI,tempw); if (abrt) break; - if (flags&D_FLAG) EDI-=2; - else EDI+=2; - cycles-=15; - break; - case 0x36D: /*INSL*/ - checkio_perm(DX); - checkio_perm(DX+1); - checkio_perm(DX+2); - checkio_perm(DX+3); - templ=inl(DX); - writememl(es,EDI,templ); if (abrt) break; - if (flags&D_FLAG) EDI-=4; - else EDI+=4; - cycles-=15; - break; - case 0x6E: case 0x16E: /*OUTSB*/ - temp=readmemb(ds,SI); if (abrt) break; - checkio_perm(DX); - if (flags&D_FLAG) SI--; - else SI++; - outb(DX,temp); - cycles-=14; - break; - case 0x26E: case 0x36E: /*OUTSB*/ - checkio_perm(DX); - temp=readmemb(ds,ESI); if (abrt) break; - if (flags&D_FLAG) ESI--; - else ESI++; - outb(DX,temp); - cycles-=14; - break; - case 0x6F: /*OUTSW*/ - tempw=readmemw(ds,SI); if (abrt) break; - checkio_perm(DX); - checkio_perm(DX+1); - if (flags&D_FLAG) SI-=2; - else SI+=2; - outw(DX,tempw); -// outb(DX+1,tempw>>8); - cycles-=14; - break; - case 0x16F: /*OUTSL*/ - tempw=readmemw(ds,SI); if (abrt) break; - checkio_perm(DX); - checkio_perm(DX+1); - checkio_perm(DX+2); - checkio_perm(DX+3); - if (flags&D_FLAG) SI-=4; - else SI+=4; - outl(EDX,templ); - cycles-=14; - break; - case 0x26F: /*OUTSW*/ - tempw=readmemw(ds,ESI); if (abrt) break; - checkio_perm(DX); - checkio_perm(DX+1); - if (flags&D_FLAG) ESI-=2; - else ESI+=2; - outw(DX,tempw); - cycles-=14; - break; - case 0x36F: /*OUTSL*/ - tempw=readmemw(ds,ESI); if (abrt) break; - checkio_perm(DX); - checkio_perm(DX+1); - checkio_perm(DX+2); - checkio_perm(DX+3); - if (flags&D_FLAG) ESI-=4; - else ESI+=4; - outl(EDX,templ); - cycles-=14; - break; - - case 0x70: case 0x170: case 0x270: case 0x370: /*JO*/ - offset=(int8_t)getbytef(); - if (flags&V_FLAG) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x71: case 0x171: case 0x271: case 0x371: /*JNO*/ - offset=(int8_t)getbytef(); - if (!(flags&V_FLAG)) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x72: case 0x172: case 0x272: case 0x372: /*JB*/ - offset=(int8_t)getbytef(); - if (flags&C_FLAG) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x73: case 0x173: case 0x273: case 0x373: /*JNB*/ - offset=(int8_t)getbytef(); - if (!(flags&C_FLAG)) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x74: case 0x174: case 0x274: case 0x374: /*JZ*/ - offset=(int8_t)getbytef(); - if (flags&Z_FLAG) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x75: case 0x175: case 0x275: case 0x375: /*JNZ*/ - offset=(int8_t)getbytef(); - if (!(flags&Z_FLAG)) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x76: case 0x176: case 0x276: case 0x376: /*JBE*/ - offset=(int8_t)getbytef(); - if (flags&(C_FLAG|Z_FLAG)) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x77: case 0x177: case 0x277: case 0x377: /*JNBE*/ - offset=(int8_t)getbytef(); - if (!(flags&(C_FLAG|Z_FLAG))) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x78: case 0x178: case 0x278: case 0x378: /*JS*/ - offset=(int8_t)getbytef(); - if (flags&N_FLAG) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x79: case 0x179: case 0x279: case 0x379: /*JNS*/ - offset=(int8_t)getbytef(); - if (!(flags&N_FLAG)) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x7A: case 0x17A: case 0x27A: case 0x37A: /*JP*/ - offset=(int8_t)getbytef(); - if (flags&P_FLAG) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x7B: case 0x17B: case 0x27B: case 0x37B: /*JNP*/ - offset=(int8_t)getbytef(); - if (!(flags&P_FLAG)) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x7C: case 0x17C: case 0x27C: case 0x37C: /*JL*/ - offset=(int8_t)getbytef(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp!=temp2) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x7D: case 0x17D: case 0x27D: case 0x37D: /*JNL*/ - offset=(int8_t)getbytef(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp==temp2) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x7E: case 0x17E: case 0x27E: case 0x37E: /*JLE*/ - offset=(int8_t)getbytef(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if ((flags&Z_FLAG) || (temp!=temp2)) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - case 0x7F: case 0x17F: case 0x27F: case 0x37F: /*JNLE*/ - offset=(int8_t)getbytef(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (!((flags&Z_FLAG) || (temp!=temp2))) { pc += offset; cycles -= timing_bt; } - cycles -= timing_bnt; - break; - - - case 0x80: case 0x180: case 0x280: case 0x380: - case 0x82: case 0x182: case 0x282: case 0x382: - fetchea(); - temp=geteab(); if (abrt) break; - temp2=readmemb(cs,pc); pc++; if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*ADD b,#8*/ - seteab(temp+temp2); if (abrt) break; - setadd8(temp,temp2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x08: /*OR b,#8*/ - temp|=temp2; - seteab(temp); if (abrt) break; - setznp8(temp); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x10: /*ADC b,#8*/ - seteab(temp+temp2+tempc); if (abrt) break; - setadc8(temp,temp2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x18: /*SBB b,#8*/ - seteab(temp-(temp2+tempc)); if (abrt) break; - setsbc8(temp,temp2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x20: /*AND b,#8*/ - temp&=temp2; - seteab(temp); if (abrt) break; - setznp8(temp); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x28: /*SUB b,#8*/ - seteab(temp-temp2); if (abrt) break; - setsub8(temp,temp2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x30: /*XOR b,#8*/ - temp^=temp2; - seteab(temp); if (abrt) break; - setznp8(temp); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x38: /*CMP b,#8*/ - setsub8(temp,temp2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:7); - break; - } - break; - - case 0x81: case 0x281: - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw2=getword(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*ADD w,#16*/ - seteaw(tempw+tempw2); if (abrt) break; - setadd16(tempw,tempw2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x08: /*OR w,#16*/ - tempw|=tempw2; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x10: /*ADC w,#16*/ - seteaw(tempw+tempw2+tempc); if (abrt) break; - setadc16(tempw,tempw2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x20: /*AND w,#16*/ - tempw&=tempw2; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x18: /*SBB w,#16*/ - seteaw(tempw-(tempw2+tempc)); if (abrt) break; - setsbc16(tempw,tempw2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x28: /*SUB w,#16*/ - seteaw(tempw-tempw2); if (abrt) break; - setsub16(tempw,tempw2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x30: /*XOR w,#16*/ - tempw^=tempw2; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x38: /*CMP w,#16*/ - setsub16(tempw,tempw2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:7); - break; - } - break; - case 0x181: case 0x381: - fetchea(); - templ=geteal(); if (abrt) break; - templ2=getlong(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*ADD l,#32*/ - seteal(templ+templ2); if (abrt) break; - setadd32(templ,templ2); - cycles -= (mod == 3) ? timing_rr : timing_mrl; - break; - case 0x08: /*OR l,#32*/ - templ|=templ2; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= (mod == 3) ? timing_rr : timing_mrl; - break; - case 0x10: /*ADC l,#32*/ - seteal(templ+templ2+tempc); if (abrt) break; - setadc32(templ,templ2); - cycles -= (mod == 3) ? timing_rr : timing_mrl; - break; - case 0x20: /*AND l,#32*/ - templ&=templ2; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= (mod == 3) ? timing_rr : timing_mrl; - break; - case 0x18: /*SBB l,#32*/ - seteal(templ-(templ2+tempc)); if (abrt) break; - setsbc32(templ,templ2); - cycles -= (mod == 3) ? timing_rr : timing_mrl; - break; - case 0x28: /*SUB l,#32*/ - seteal(templ-templ2); if (abrt) break; - setsub32(templ,templ2); - cycles -= (mod == 3) ? timing_rr : timing_mrl; - break; - case 0x30: /*XOR l,#32*/ - templ^=templ2; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= (mod == 3) ? timing_rr : timing_mrl; - break; - case 0x38: /*CMP l,#32*/ - setsub32(templ,templ2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:7); - break; - } - break; - - case 0x83: case 0x283: - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw2=readmemb(cs,pc); pc++; if (abrt) break; - if (tempw2&0x80) tempw2|=0xFF00; - switch (rmdat&0x38) - { - case 0x00: /*ADD w,#8*/ - seteaw(tempw+tempw2); if (abrt) break; - setadd16(tempw,tempw2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x08: /*OR w,#8*/ - tempw|=tempw2; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x10: /*ADC w,#8*/ - seteaw(tempw+tempw2+tempc); if (abrt) break; - setadc16(tempw,tempw2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x18: /*SBB w,#8*/ - seteaw(tempw-(tempw2+tempc)); if (abrt) break; - setsbc16(tempw,tempw2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x20: /*AND w,#8*/ - tempw&=tempw2; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x28: /*SUB w,#8*/ - seteaw(tempw-tempw2); if (abrt) break; - setsub16(tempw,tempw2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x30: /*XOR w,#8*/ - tempw^=tempw2; - seteaw(tempw); if (abrt) break; - setznp16(tempw); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x38: /*CMP w,#8*/ - setsub16(tempw,tempw2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:7); - break; - } - break; - case 0x183: case 0x383: - fetchea(); - templ=geteal(); if (abrt) break; - templ2=readmemb(cs,pc); pc++; if (abrt) break; - if (templ2&0x80) templ2|=0xFFFFFF00; - switch (rmdat&0x38) - { - case 0x00: /*ADD l,#32*/ - seteal(templ+templ2); if (abrt) break; - setadd32(templ,templ2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x08: /*OR l,#32*/ - templ|=templ2; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x10: /*ADC l,#32*/ - seteal(templ+templ2+tempc); if (abrt) break; - setadc32(templ,templ2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x20: /*AND l,#32*/ - templ&=templ2; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x18: /*SBB l,#32*/ - seteal(templ-(templ2+tempc)); if (abrt) break; - setsbc32(templ,templ2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x28: /*SUB l,#32*/ - seteal(templ-templ2); if (abrt) break; - setsub32(templ,templ2); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x30: /*XOR l,#32*/ - templ^=templ2; - seteal(templ); if (abrt) break; - setznp32(templ); - cycles -= (mod == 3) ? timing_rr : timing_mr; - break; - case 0x38: /*CMP l,#32*/ - setsub32(templ,templ2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:7); - break; - } - break; - - case 0x84: case 0x184: case 0x284: case 0x384: /*TEST b,reg*/ - fetchea(); - temp=geteab(); if (abrt) break; - temp2=getr8(reg); - setznp8(temp&temp2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x85: case 0x285: /*TEST w,reg*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - tempw2=regs[reg].w; - setznp16(tempw&tempw2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x185: case 0x385: /*TEST l,reg*/ - fetchea(); - templ=geteal(); if (abrt) break; - templ2=regs[reg].l; - setznp32(templ&templ2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x86: case 0x186: case 0x286: case 0x386: /*XCHG b,reg*/ - fetchea(); - temp=geteab(); if (abrt) break; - seteab(getr8(reg)); if (abrt) break; - setr8(reg,temp); - cycles-=((mod==3)?3:5); - break; - case 0x87: case 0x287: /*XCHG w,reg*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - seteaw(regs[reg].w); if (abrt) break; - regs[reg].w=tempw; - cycles-=((mod==3)?3:5); - break; - case 0x187: case 0x387: /*XCHG l,reg*/ - fetchea(); - templ=geteal(); if (abrt) break; - seteal(regs[reg].l); if (abrt) break; - regs[reg].l=templ; - cycles-=((mod==3)?3:5); - break; - - case 0x88: case 0x188: case 0x288: case 0x388: /*MOV b,reg*/ - fetchea(); - seteab(getr8(reg)); - cycles-=(is486)?1:2; - break; - case 0x89: case 0x289: /*MOV w,reg*/ - fetchea(); - seteaw(regs[reg].w); - cycles-=(is486)?1:2; - break; - case 0x189: case 0x389: /*MOV l,reg*/ - fetchea(); - //if (output==3) pclog("Write %08X to %08X:%08X %08X %08X %08X\n",regs[reg].l,easeg,eaaddr,); - seteal(regs[reg].l); - cycles-=(is486)?1:2; - break; - case 0x8A: case 0x18A: case 0x28A: case 0x38A: /*MOV reg,b*/ - fetchea(); - temp=geteab(); if (abrt) break; - setr8(reg,temp); - if (is486) cycles--; - else cycles-=((mod==3)?2:4); - break; - case 0x8B: case 0x28B: /*MOV reg,w*/ - fetchea(); - tempw=geteaw(); if (abrt) break; - regs[reg].w=tempw; - if (is486) cycles--; - else cycles-=((mod==3)?2:4); - break; - case 0x18B: case 0x38B: /*MOV reg,l*/ - fetchea(); - templ=geteal(); if (abrt) break; - regs[reg].l=templ; - if (is486) cycles--; - else cycles-=((mod==3)?2:4); - break; - - case 0x8C: case 0x28C: /*MOV w,sreg*/ - fetchea(); -// if (output==3) pclog("MOV sreg %02X %08X\n",rmdat,fetchdat); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - seteaw(ES); - break; - case 0x08: /*CS*/ - seteaw(CS); - break; - case 0x18: /*DS*/ - if (ssegs) ds=oldds; - seteaw(DS); - break; - case 0x10: /*SS*/ - if (ssegs) ss=oldss; - seteaw(SS); - break; - case 0x20: /*FS*/ - seteaw(FS); - break; - case 0x28: /*GS*/ - seteaw(GS); - break; - } - cycles-=((mod==3)?2:3); - break; - case 0x18C: case 0x38C: /*MOV l,sreg*/ - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - if (mod==3) regs[rm].l=ES; - else seteaw(ES); - break; - case 0x08: /*CS*/ - if (mod==3) regs[rm].l=CS; - else seteaw(CS); - break; - case 0x18: /*DS*/ - if (ssegs) ds=oldds; - if (mod==3) regs[rm].l=DS; - else seteaw(DS); - break; - case 0x10: /*SS*/ - if (ssegs) ss=oldss; - if (mod==3) regs[rm].l=SS; - else seteaw(SS); - break; - case 0x20: /*FS*/ - if (mod==3) regs[rm].l=FS; - else seteaw(FS); - break; - case 0x28: /*GS*/ - if (mod==3) regs[rm].l=GS; - else seteaw(GS); - break; - } - cycles-=((mod==3)?2:3); - break; - - case 0x8D: case 0x28D: /*LEA*/ - fetchea(); - regs[reg].w=eaaddr; - cycles -= timing_rr; - break; - case 0x18D: /*LEA*/ - fetchea(); - regs[reg].l=eaaddr&0xFFFF; - cycles -= timing_rr; - break; - case 0x38D: /*LEA*/ - fetchea(); - regs[reg].l=eaaddr; - cycles -= timing_rr; - break; - - case 0x8E: case 0x18E: case 0x28E: case 0x38E: /*MOV sreg,w*/ - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - tempw=geteaw(); if (abrt) break; - loadseg(tempw,&_es); - break; - case 0x18: /*DS*/ - tempw=geteaw(); if (abrt) break; - loadseg(tempw,&_ds); - if (ssegs) oldds=ds; - break; - case 0x10: /*SS*/ -// if (output==3) pclog("geteaw\n"); - tempw=geteaw(); if (abrt) break; -// if (output==3) pclog("loadseg\n"); - loadseg(tempw,&_ss); -// if (output==3) pclog("done\n"); - if (ssegs) oldss=ss; - skipnextprint=1; - noint=1; - break; - case 0x20: /*FS*/ - tempw=geteaw(); if (abrt) break; - loadseg(tempw,&_fs); - break; - case 0x28: /*GS*/ - tempw=geteaw(); if (abrt) break; - loadseg(tempw,&_gs); - break; - } - cycles-=((mod==3)?2:5); - break; - - case 0x8F: case 0x28F: /*POPW*/ - if (ssegs) templ2=oldss; - else templ2=ss; - if (stack32) - { - tempw=readmemw(templ2,ESP); if (abrt) break; - ESP+=2; - } - else - { - tempw=readmemw(templ2,SP); if (abrt) break; - SP+=2; - } - fetchea(); - if (ssegs) ss=oldss; - seteaw(tempw); - if (abrt) - { - if (stack32) ESP-=2; - else SP-=2; - } - if (is486) cycles-=((mod==3)?1:6); - else cycles-=((mod==3)?4:5); - break; - case 0x18F: case 0x38F: /*POPL*/ - if (ssegs) templ2=oldss; - else templ2=ss; - if (stack32) - { - templ=readmeml(templ2,ESP); if (abrt) break; - ESP+=4; - } - else - { - templ=readmeml(templ2,SP); if (abrt) break; - SP+=4; - } - fetchea(); - if (ssegs) ss=oldss; - seteal(templ); - if (abrt) - { - if (stack32) ESP-=4; - else SP-=4; - } - if (is486) cycles-=((mod==3)?1:6); - else cycles-=((mod==3)?4:5); - break; - - case 0x90: case 0x190: case 0x290: case 0x390: /*NOP*/ - cycles-=(is486)?1:3; - break; - - case 0x91: case 0x92: case 0x93: /*XCHG AX*/ - case 0x94: case 0x95: case 0x96: case 0x97: - case 0x291: case 0x292: case 0x293: - case 0x294: case 0x295: case 0x296: case 0x297: - tempw=AX; - AX=regs[opcode&7].w; - regs[opcode&7].w=tempw; - cycles-=3; - break; - case 0x191: case 0x192: case 0x193: /*XCHG EAX*/ - case 0x194: case 0x195: case 0x196: case 0x197: - case 0x391: case 0x392: case 0x393: /*XCHG EAX*/ - case 0x394: case 0x395: case 0x396: case 0x397: - templ=EAX; - EAX=regs[opcode&7].l; - regs[opcode&7].l=templ; - cycles-=3; - break; - - case 0x98: case 0x298: /*CBW*/ - AH=(AL&0x80)?0xFF:0; - cycles-=3; - break; - case 0x198: case 0x398: /*CWDE*/ - EAX=(AX&0x8000)?(0xFFFF0000|AX):AX; - cycles-=3; - break; - case 0x99: case 0x299: /*CWD*/ - DX=(AX&0x8000)?0xFFFF:0; - cycles-=2; - break; - case 0x199: case 0x399: /*CDQ*/ - EDX=(EAX&0x80000000)?0xFFFFFFFF:0; - cycles-=2; - break; - case 0x9A: case 0x29A: /*CALL FAR*/ - tempw=getword(); - tempw2=getword(); if (abrt) break; - if (output == 3) pclog("Call far %04X:%04X\n",tempw2,tempw); - tempw3=CS; - templ2 = pc; - if (output) pclog("Call far %08X\n",templ2); - if (ssegs) ss=oldss; - oxpc=pc; - pc=tempw; - optype=CALL; - cgate32=0; - if (output == 3) pclog("Load CS\n"); - if (msw&1) loadcscall(tempw2); - else loadcs(tempw2); - if (output == 3) pclog("%i %i\n", abrt, cgate32); - optype=0; -// if (output==3) pclog("CALL FAR 16 complete\n"); - if (abrt) break; - oldss=ss; - if (cgate32) goto writecall32; - writecall16: - cgate16=0; - if (stack32) - { - writememw(ss,ESP-2,tempw3); - writememw(ss,ESP-4,templ2); if (abrt) break; - ESP-=4; - } - else - { - writememw(ss,(SP-2)&0xFFFF,tempw3); - if (output) pclog("Write CS to %04X:%04X\n",SS,SP-2); - writememw(ss,(SP-4)&0xFFFF,templ2); if (abrt) break; - if (output) pclog("Write PC %08X to %04X:%04X\n", templ2, SS,SP-4); - SP-=4; - } - cycles-=(is486)?18:17; - break; - case 0x19A: case 0x39A: /*CALL FAR*/ -// if (output==3) pclog("CF 1 %08X\n",pc); - templ=getword(); templ|=(getword()<<16); -// if (output==3) pclog("CF 2\n"); - tempw2=getword(); if (abrt) break; -// if (output==3) pclog("CF 3 %04X:%08X\n",tempw2,templ); - tempw3=CS; - templ2 = pc; - if (ssegs) ss=oldss; - oxpc=pc; - pc=templ; - optype=CALL; - cgate16=0; -// if (output==3) pclog("Load CS\n"); - if (msw&1) loadcscall(tempw2); - else loadcs(tempw2); -// if (output==3) pclog("%i %i\n",notpresent,abrt); - optype=0; -// if (output==3) pclog("CALL FAR 32 complete\n"); - if (abrt) break; - oldss=ss; - if (cgate16) goto writecall16; - writecall32: - cgate32=0; - if (stack32) - { - writememl(ss,ESP-4,tempw3); - writememl(ss,ESP-8,templ2); if (abrt) break; - if (output) pclog("Write PC %08X to %04X:%04X\n", templ2, SS,ESP-8); - ESP-=8; - } - else - { - writememl(ss,(SP-4)&0xFFFF,tempw3); - writememl(ss,(SP-8)&0xFFFF,templ2); if (abrt) break; - if (output) pclog("Write PC %08X to %04X:%04X\n", templ2, SS,SP-8); - SP-=8; - } - cycles-=(is486)?18:17; - break; - case 0x9B: case 0x19B: case 0x29B: case 0x39B: /*WAIT*/ - cycles-=4; - break; - case 0x9C: case 0x29C: /*PUSHF*/ - if (ssegs) ss=oldss; - if ((eflags&VM_FLAG) && (IOPL<3)) - { - x86gpf(NULL,0); - break; - } - if (stack32) - { - writememw(ss,ESP-2,flags); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),flags); if (abrt) break; - SP-=2; - } - cycles-=4; - break; - case 0x19C: case 0x39C: /*PUSHFD*/ -// pclog("PUSHFD %04X(%08X):%08X\n",CS,cs,pc); - if (ssegs) ss=oldss; - if ((eflags&VM_FLAG) && (IOPL<3)) - { - x86gpf(NULL,0); - break; - } - if (CPUID) tempw=eflags&0x24; - else tempw=eflags&4; - if (stack32) - { - writememw(ss,ESP-2,tempw); - writememw(ss,ESP-4,flags); if (abrt) break; - ESP-=4; -// if (output==3) pclog("Pushing %04X %04X\n",eflags,flags); - } - else - { - writememw(ss,((SP-2)&0xFFFF),tempw); - writememw(ss,((SP-4)&0xFFFF),flags); if (abrt) break; - SP-=4; - } - cycles-=4; - break; - case 0x9D: case 0x29D: /*POPF*/ -// if (CS!=0x21 && CS!=0xF000) pclog("POPF %04X:%04X\n",CS,pc); - if (ssegs) ss=oldss; - if ((eflags&VM_FLAG) && (IOPL<3)) - { - x86gpf(NULL,0); - break; - } - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - ESP+=2; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - SP+=2; - } -// pclog("POPF! %i %i %i\n",CPL,msw&1,IOPLp); - if (!(CPL) || !(msw&1)) flags=(tempw&0xFFD5)|2; - else if (IOPLp) flags=(flags&0x3000)|(tempw&0xCFD5)|2; - else flags=(flags&0xF200)|(tempw&0x0DD5)|2; -// if (flags==0xF000) pclog("POPF - flags now F000 %04X(%06X):%04X %08X %08X %08X\n",CS,cs,pc,old8,old82,old83); - cycles-=5; - break; - case 0x19D: case 0x39D: /*POPFD*/ - if (ssegs) ss=oldss; - if ((eflags&VM_FLAG) && (IOPL<3)) - { - x86gpf(NULL,0); - break; - } - if (stack32) - { - tempw=readmemw(ss,ESP); - tempw2=readmemw(ss,ESP+2); if (abrt) break; - ESP+=4; - } - else - { - tempw=readmemw(ss,SP); - tempw2=readmemw(ss,SP+2); if (abrt) break; - SP+=4; - } -// eflags|=0x200000; - if (!(CPL) || !(msw&1)) flags=(tempw&0xFFD5)|2; - else if (IOPLp) flags=(flags&0x3000)|(tempw&0xCFD5)|2; - else flags=(flags&0xF200)|(tempw&0x0DD5)|2; - tempw2&=(is486)?0x24:0; - tempw2|=(eflags&3); - if (CPUID) eflags=tempw2&0x27; - else if (is486) eflags=tempw2&7; - else eflags=tempw2&3; -// if (flags==0xF000) pclog("POPF - flags now F000 %04X(%06X):%04X %08X %08X %08X\n",CS,cs,pc,old8,old82,old83); - cycles-=5; - break; - case 0x9E: case 0x19E: case 0x29E: case 0x39E: /*SAHF*/ - flags=(flags&0xFF00)|(AH&0xD5)|2; - cycles-=3; - break; - case 0x9F: case 0x19F: case 0x29F: case 0x39F: /*LAHF*/ - AH=flags&0xFF; - cycles-=3; - break; - - case 0xA0: case 0x1A0: /*MOV AL,(w)*/ - addr=getword(); if (abrt) break; - temp=readmemb(ds,addr); if (abrt) break; - AL=temp; - cycles-=(is486)?1:4; - break; - case 0x2A0: case 0x3A0: /*MOV AL,(l)*/ - addr=getlong(); if (abrt) break; - temp=readmemb(ds,addr); if (abrt) break; - AL=temp; - cycles-=(is486)?1:4; - break; - case 0xA1: /*MOV AX,(w)*/ - addr=getword(); if (abrt) break; - tempw=readmemw(ds,addr); if (abrt) break; - AX=tempw; - cycles-=(is486)?1:4; - break; - case 0x1A1: /*MOV EAX,(w)*/ - addr=getword(); if (abrt) break; - templ=readmeml(ds,addr); if (abrt) break; - EAX=templ; - cycles-=(is486)?1:4; - break; - case 0x2A1: /*MOV AX,(l)*/ - addr=getlong(); if (abrt) break; - tempw=readmemw(ds,addr); if (abrt) break; - AX=tempw; - cycles-=(is486)?1:4; - break; - case 0x3A1: /*MOV EAX,(l)*/ - addr=getlong(); if (abrt) break; - templ=readmeml(ds,addr); if (abrt) break; - EAX=templ; - cycles-=(is486)?1:4; - break; - case 0xA2: case 0x1A2: /*MOV (w),AL*/ - addr=getword(); if (abrt) break; - writememb(ds,addr,AL); - cycles-=(is486)?1:2; - break; - case 0x2A2: case 0x3A2: /*MOV (l),AL*/ - addr=getlong(); if (abrt) break; - writememb(ds,addr,AL); - cycles-=(is486)?1:2; - break; - case 0xA3: /*MOV (w),AX*/ - addr=getword(); if (abrt) break; - writememw(ds,addr,AX); - cycles-=(is486)?1:2; - break; - case 0x1A3: /*MOV (w),EAX*/ - addr=getword(); if (abrt) break; - writememl(ds,addr,EAX); - cycles-=(is486)?1:2; - break; - case 0x2A3: /*MOV (l),AX*/ - addr=getlong(); if (abrt) break; - writememw(ds,addr,AX); - cycles-=(is486)?1:2; - break; - case 0x3A3: /*MOV (l),EAX*/ - addr=getlong(); if (abrt) break; - writememl(ds,addr,EAX); - cycles-=(is486)?1:2; - break; - - case 0xA4: case 0x1A4: /*MOVSB*/ - temp=readmemb(ds,SI); if (abrt) break; - writememb(es,DI,temp); if (abrt) break; - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - cycles-=7; - break; - case 0x2A4: case 0x3A4: /*MOVSB*/ - temp=readmemb(ds,ESI); if (abrt) break; - writememb(es,EDI,temp); if (abrt) break; - if (flags&D_FLAG) { EDI--; ESI--; } - else { EDI++; ESI++; } - cycles-=7; - break; - case 0xA5: /*MOVSW*/ - tempw=readmemw(ds,SI); if (abrt) break; - writememw(es,DI,tempw); if (abrt) break; - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - cycles-=7; - break; - case 0x2A5: /*MOVSW*/ - tempw=readmemw(ds,ESI); if (abrt) break; - writememw(es,EDI,tempw); if (abrt) break; - if (flags&D_FLAG) { EDI-=2; ESI-=2; } - else { EDI+=2; ESI+=2; } - cycles-=7; - break; - case 0x1A5: /*MOVSL*/ - templ=readmeml(ds,SI); if (abrt) break; - writememl(es,DI,templ); if (abrt) break; - if (flags&D_FLAG) { DI-=4; SI-=4; } - else { DI+=4; SI+=4; } - cycles-=7; - break; - case 0x3A5: /*MOVSL*/ - templ=readmeml(ds,ESI); if (abrt) break; - writememl(es,EDI,templ); if (abrt) break; - if (flags&D_FLAG) { EDI-=4; ESI-=4; } - else { EDI+=4; ESI+=4; } - cycles-=7; - break; - case 0xA6: case 0x1A6: /*CMPSB*/ - temp =readmemb(ds,SI); - temp2=readmemb(es,DI); - if (abrt) break; - setsub8(temp,temp2); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - cycles-=(is486)?8:10; - break; - case 0x2A6: case 0x3A6: /*CMPSB*/ - temp =readmemb(ds,ESI); - temp2=readmemb(es,EDI); - if (abrt) break; - setsub8(temp,temp2); - if (flags&D_FLAG) { EDI--; ESI--; } - else { EDI++; ESI++; } - cycles-=(is486)?8:10; - break; - case 0xA7: /*CMPSW*/ - tempw =readmemw(ds,SI); - tempw2=readmemw(es,DI); - if (abrt) break; - setsub16(tempw,tempw2); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - cycles-=(is486)?8:10; - break; - case 0x1A7: /*CMPSL*/ - templ =readmeml(ds,SI); - templ2=readmeml(es,DI); - if (abrt) break; - setsub32(templ,templ2); - if (flags&D_FLAG) { DI-=4; SI-=4; } - else { DI+=4; SI+=4; } - cycles-=(is486)?8:10; - break; - case 0x2A7: /*CMPSW*/ - tempw =readmemw(ds,ESI); - tempw2=readmemw(es,EDI); - if (abrt) break; - setsub16(tempw,tempw2); - if (flags&D_FLAG) { EDI-=2; ESI-=2; } - else { EDI+=2; ESI+=2; } - cycles-=(is486)?8:10; - break; - case 0x3A7: /*CMPSL*/ - templ =readmeml(ds,ESI); - templ2=readmeml(es,EDI); - if (abrt) break; - setsub32(templ,templ2); - if (flags&D_FLAG) { EDI-=4; ESI-=4; } - else { EDI+=4; ESI+=4; } - cycles-=(is486)?8:10; - break; - case 0xA8: case 0x1A8: case 0x2A8: case 0x3A8: /*TEST AL,#8*/ - temp=getbytef(); - setznp8(AL&temp); - cycles -= timing_rr; - break; - case 0xA9: case 0x2A9: /*TEST AX,#16*/ - tempw=getwordf(); - setznp16(AX&tempw); - cycles -= timing_rr; - break; - case 0x1A9: case 0x3A9: /*TEST EAX,#32*/ - templ=getlong(); if (abrt) break; - setznp32(EAX&templ); - cycles -= timing_rr; - break; - case 0xAA: case 0x1AA: /*STOSB*/ - writememb(es,DI,AL); if (abrt) break; - if (flags&D_FLAG) DI--; - else DI++; - cycles-=4; - break; - case 0x2AA: case 0x3AA: /*STOSB*/ - writememb(es,EDI,AL); if (abrt) break; - if (flags&D_FLAG) EDI--; - else EDI++; - cycles-=4; - break; - case 0xAB: /*STOSW*/ - writememw(es,DI,AX); if (abrt) break; - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=4; - break; - case 0x1AB: /*STOSL*/ - writememl(es,DI,EAX); if (abrt) break; - if (flags&D_FLAG) DI-=4; - else DI+=4; - cycles-=4; - break; - case 0x2AB: /*STOSW*/ - writememw(es,EDI,AX); if (abrt) break; - if (flags&D_FLAG) EDI-=2; - else EDI+=2; - cycles-=4; - break; - case 0x3AB: /*STOSL*/ - writememl(es,EDI,EAX); if (abrt) break; - if (flags&D_FLAG) EDI-=4; - else EDI+=4; - cycles-=4; - break; - case 0xAC: case 0x1AC: /*LODSB*/ - temp=readmemb(ds,SI); - if (abrt) break; - AL=temp; -// if (output==3) pclog("LODSB %02X from %05X:%04X\n",AL,ds,SI); - if (flags&D_FLAG) SI--; - else SI++; - cycles-=5; - break; - case 0x2AC: case 0x3AC: /*LODSB*/ - temp=readmemb(ds,ESI); - if (abrt) break; - AL=temp; - if (flags&D_FLAG) ESI--; - else ESI++; - cycles-=5; - break; - case 0xAD: /*LODSW*/ - tempw=readmemw(ds,SI); - if (abrt) break; - AX=tempw; -// if (output) pclog("Load from %05X:%04X\n",ds,SI); - if (flags&D_FLAG) SI-=2; - else SI+=2; - cycles-=5; - break; - case 0x1AD: /*LODSL*/ - templ=readmeml(ds,SI); - if (abrt) break; - EAX=templ; - if (flags&D_FLAG) SI-=4; - else SI+=4; - cycles-=5; - break; - case 0x2AD: /*LODSW*/ - tempw=readmemw(ds,ESI); - if (abrt) break; - AX=tempw; - if (flags&D_FLAG) ESI-=2; - else ESI+=2; - cycles-=5; - break; - case 0x3AD: /*LODSL*/ - templ=readmeml(ds,ESI); - if (abrt) break; - EAX=templ; - if (flags&D_FLAG) ESI-=4; - else ESI+=4; - cycles-=5; - break; - case 0xAE: case 0x1AE: /*SCASB*/ - temp=readmemb(es,DI); - if (abrt) break; - setsub8(AL,temp); - if (flags&D_FLAG) DI--; - else DI++; - cycles-=7; - break; - case 0x2AE: case 0x3AE: /*SCASB*/ - temp=readmemb(es,EDI); - if (abrt) break; - setsub8(AL,temp); - if (flags&D_FLAG) EDI--; - else EDI++; - cycles-=7; - break; - case 0xAF: /*SCASW*/ - tempw=readmemw(es,DI); - if (abrt) break; - setsub16(AX,tempw); - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=7; - break; - case 0x1AF: /*SCASL*/ - templ=readmeml(es,DI); - if (abrt) break; - setsub32(EAX,templ); - if (flags&D_FLAG) DI-=4; - else DI+=4; - cycles-=7; - break; - case 0x2AF: /*SCASW*/ - tempw=readmemw(es,EDI); - if (abrt) break; - setsub16(AX,tempw); - if (flags&D_FLAG) EDI-=2; - else EDI+=2; - cycles-=7; - break; - case 0x3AF: /*SCASL*/ - templ=readmeml(es,EDI); - if (abrt) break; - setsub32(EAX,templ); - if (flags&D_FLAG) EDI-=4; - else EDI+=4; - cycles-=7; - break; - - case 0xB0: case 0x1B0: case 0x2B0: case 0x3B0: /*MOV AL,#8*/ - AL=getbytef(); - cycles -= timing_rr; - break; - case 0xB1: case 0x1B1: case 0x2B1: case 0x3B1: /*MOV CL,#8*/ - CL=getbytef(); - cycles -= timing_rr; - break; - case 0xB2: case 0x1B2: case 0x2B2: case 0x3B2: /*MOV DL,#8*/ - DL=getbytef(); - cycles -= timing_rr; - break; - case 0xB3: case 0x1B3: case 0x2B3: case 0x3B3: /*MOV BL,#8*/ - BL=getbytef(); - cycles -= timing_rr; - break; - case 0xB4: case 0x1B4: case 0x2B4: case 0x3B4: /*MOV AH,#8*/ - AH=getbytef(); - cycles -= timing_rr; - break; - case 0xB5: case 0x1B5: case 0x2B5: case 0x3B5: /*MOV CH,#8*/ - CH=getbytef(); - cycles -= timing_rr; - break; - case 0xB6: case 0x1B6: case 0x2B6: case 0x3B6: /*MOV DH,#8*/ - DH=getbytef(); - cycles -= timing_rr; - break; - case 0xB7: case 0x1B7: case 0x2B7: case 0x3B7: /*MOV BH,#8*/ - BH=getbytef(); - cycles -= timing_rr; - break; - case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV reg,#16*/ - case 0xBC: case 0xBD: case 0xBE: case 0xBF: - case 0x2B8: case 0x2B9: case 0x2BA: case 0x2BB: - case 0x2BC: case 0x2BD: case 0x2BE: case 0x2BF: - regs[opcode&7].w=getwordf(); - cycles -= timing_rr; - break; - case 0x1B8: case 0x1B9: case 0x1BA: case 0x1BB: /*MOV reg,#32*/ - case 0x1BC: case 0x1BD: case 0x1BE: case 0x1BF: - case 0x3B8: case 0x3B9: case 0x3BA: case 0x3BB: - case 0x3BC: case 0x3BD: case 0x3BE: case 0x3BF: - templ=getlong(); if (abrt) break; - regs[opcode&7].l=templ; - cycles -= timing_rr; - break; - - case 0xC0: case 0x1C0: case 0x2C0: case 0x3C0: - fetchea(); - c=readmemb(cs,pc); pc++; - temp=geteab(); if (abrt) break; - c&=31; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL b,CL*/ - while (c>0) - { - temp2=(temp&0x80)?1:0; - temp=(temp<<1)|temp2; - c--; - } - seteab(temp); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x08: /*ROR b,CL*/ - while (c>0) - { - temp2=temp&1; - temp>>=1; - if (temp2) temp|=0x80; - c--; - } - seteab(temp); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x10: /*RCL b,CL*/ - temp2=flags&C_FLAG; - while (c>0) - { - tempc=(temp2)?1:0; - temp2=temp&0x80; - temp=(temp<<1)|tempc; - c--; - if (is486) cycles--; - } - seteab(temp); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - cycles-=((mod==3)?9:10); - break; - case 0x18: /*RCR b,CL*/ - temp2=flags&C_FLAG; - while (c>0) - { - tempc=(temp2)?0x80:0; - temp2=temp&1; - temp=(temp>>1)|tempc; - c--; - if (is486) cycles--; - } - seteab(temp); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - cycles-=((mod==3)?9:10); - break; - case 0x20: case 0x30: /*SHL b,CL*/ - seteab(temp<>c); if (abrt) break; - setznp8(temp>>c); - if ((temp>>(c-1))&1) flags|=C_FLAG; - if (c==1 && temp&0x80) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x38: /*SAR b,CL*/ - tempc=((temp>>(c-1))&1); - while (c>0) - { - temp>>=1; - if (temp&0x40) temp|=0x80; - c--; - } - seteab(temp); if (abrt) break; - setznp8(temp); - if (tempc) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - } - break; - - case 0xC1: case 0x2C1: - fetchea(); - c=readmemb(cs,pc)&31; pc++; - tempw=geteaw(); if (abrt) break; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL w,CL*/ - while (c>0) - { - temp=(tempw&0x8000)?1:0; - tempw=(tempw<<1)|temp; - c--; - } - seteaw(tempw); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp) flags|=C_FLAG; - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x08: /*ROR w,CL*/ - while (c>0) - { - tempw2=(tempw&1)?0x8000:0; - tempw=(tempw>>1)|tempw2; - c--; - } - seteaw(tempw); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (tempw2) flags|=C_FLAG; - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x10: /*RCL w,CL*/ - temp2=flags&C_FLAG; - while (c>0) - { - tempc=(temp2)?1:0; - temp2=(tempw>>15); - tempw=(tempw<<1)|tempc; - c--; - if (is486) cycles--; - } - seteaw(tempw); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - cycles-=((mod==3)?9:10); - break; - case 0x18: /*RCR w,CL*/ - temp2=flags&C_FLAG; - while (c>0) - { - tempc=(temp2)?0x8000:0; - temp2=tempw&1; - tempw=(tempw>>1)|tempc; - c--; - if (is486) cycles--; - } - seteaw(tempw); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - cycles-=((mod==3)?9:10); - break; - - case 0x20: case 0x30: /*SHL w,CL*/ - seteaw(tempw<>c); if (abrt) break; - setznp16(tempw>>c); - if ((tempw>>(c-1))&1) flags|=C_FLAG; - if (c==1 && tempw&0x8000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - - case 0x38: /*SAR w,CL*/ - tempw2=tempw&0x8000; - tempc=(tempw>>(c-1))&1; - while (c>0) - { - tempw=(tempw>>1)|tempw2; - c--; - } - seteaw(tempw); if (abrt) break; - setznp16(tempw); - if (tempc) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - } - break; - case 0x1C1: case 0x3C1: - fetchea(); - c=readmemb(cs,pc); pc++; - c&=31; - templ=geteal(); if (abrt) break; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL l,CL*/ - while (c>0) - { - temp=(templ&0x80000000)?1:0; - templ=(templ<<1)|temp; - c--; - } - seteal(templ); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp) flags|=C_FLAG; - if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG; - cycles-=((mod==3)?9:10); - break; - case 0x08: /*ROR l,CL*/ - while (c>0) - { - templ2=(templ&1)?0x80000000:0; - templ=(templ>>1)|templ2; - c--; - } - seteal(templ); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (templ2) flags|=C_FLAG; - if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG; - cycles-=((mod==3)?9:10); - break; - case 0x10: /*RCL l,CL*/ - temp2=flags&C_FLAG; - while (c>0) - { - tempc=(flags&C_FLAG)?1:0; - temp2=templ>>31; - templ=(templ<<1)|tempc; - c--; - if (is486) cycles--; - } - seteal(templ); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG; - cycles-=((mod==3)?9:10); - break; - case 0x18: /*RCR l,CL*/ - temp2=flags&C_FLAG; - while (c>0) - { - tempc=(temp2)?0x80000000:0; - temp2=templ&1; - templ=(templ>>1)|tempc; - c--; - if (is486) cycles--; - } - seteal(templ); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG; - cycles-=((mod==3)?9:10); - break; - - case 0x20: case 0x30: /*SHL l,CL*/ - seteal(templ<>c); if (abrt) break; - setznp32(templ>>c); - if ((templ>>(c-1))&1) flags|=C_FLAG; - if (c==1 && templ&0x80000000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - - case 0x38: /*SAR l,CL*/ - templ2=templ&0x80000000; - tempc=(templ>>(c-1))&1; - while (c>0) - { - templ=(templ>>1)|templ2; - c--; - } - seteal(templ); if (abrt) break; - setznp32(templ); - if (tempc) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - } - break; - - - case 0xC2: case 0x2C2: /*RET*/ - tempw=getword(); - if (ssegs) ss=oldss; - if (stack32) - { - tempw2=readmemw(ss,ESP); if (abrt) break; - ESP+=2+tempw; - } - else - { - tempw2=readmemw(ss,SP); if (abrt) break; - SP+=2+tempw; - } - pc=tempw2; - cycles-=(is486)?5:10; - break; - case 0x1C2: case 0x3C2: /*RET*/ - tempw=getword(); - if (ssegs) ss=oldss; - if (stack32) - { - templ=readmeml(ss,ESP); if (abrt) break; - ESP+=4+tempw; - } - else - { - templ=readmeml(ss,SP); if (abrt) break; - SP+=4+tempw; - } - pc=templ; - cycles-=(is486)?5:10; - break; - case 0xC3: case 0x2C3: /*RET*/ - if (ssegs) ss=oldss; - if (stack32) - { - tempw=readmemw(ss,ESP); if (abrt) break; - ESP+=2; - } - else - { - tempw=readmemw(ss,SP); if (abrt) break; - SP+=2; - } - pc=tempw; - cycles-=(is486)?5:10; - break; - case 0x1C3: case 0x3C3: /*RET*/ - if (ssegs) ss=oldss; - if (stack32) - { - templ=readmeml(ss,ESP); if (abrt) break; - ESP+=4; - } - else - { - templ=readmeml(ss,SP); if (abrt) break; - SP+=4; - } - pc=templ; - cycles-=(is486)?5:10; - break; - case 0xC4: case 0x2C4: /*LES*/ - fetchea(); - tempw2=readmemw(easeg,eaaddr); - tempw=readmemw(easeg,eaaddr+2); -// if (output==3) pclog("LES %04X:%08X %04X:%08X\n",easeg,eaaddr,tempw,tempw2); - if (abrt) break; - loadseg(tempw,&_es); - if (abrt) break; - regs[reg].w=tempw2; -// if (output==3) pclog("LES complete\n"); -// if (!ES) pclog("LES=0 %04X(%06X):%04X\n",CS,cs,pc); -// if (cr0&1) pclog("ES loaded with %04X %04X(%08X):%08X\n",tempw,CS,cs,pc); - cycles-=7; - break; - case 0x1C4: case 0x3C4: /*LES*/ - fetchea(); - templ=readmeml(easeg,eaaddr); - tempw=readmemw(easeg,eaaddr+4); - if (abrt) break; - loadseg(tempw,&_es); - if (abrt) break; - regs[reg].l=templ; - cycles-=7; - break; - case 0xC5: case 0x2C5: /*LDS*/ - fetchea(); - tempw2=readmemw(easeg,eaaddr); - tempw=readmemw(easeg,eaaddr+2); - if (abrt) break; - loadseg(tempw,&_ds); - if (abrt) break; - if (ssegs) oldds=ds; - regs[reg].w=tempw2; - cycles-=7; - break; - case 0x1C5: case 0x3C5: /*LDS*/ - fetchea(); - templ=readmeml(easeg,eaaddr); - tempw=readmemw(easeg,eaaddr+4); - if (abrt) break; - loadseg(tempw,&_ds); - if (abrt) break; - if (ssegs) oldds=ds; - regs[reg].l=templ; - cycles-=7; - break; - case 0xC6: case 0x1C6: case 0x2C6: case 0x3C6: /*MOV b,#8*/ - fetchea(); - temp=readmemb(cs,pc); pc++; if (abrt) break; - seteab(temp); - cycles -= timing_rr; - break; - case 0xC7: case 0x2C7: /*MOV w,#16*/ - fetchea(); - tempw=getword(); if (abrt) break; - seteaw(tempw); - cycles -= timing_rr; - break; - case 0x1C7: case 0x3C7: /*MOV l,#32*/ - fetchea(); - templ=getlong(); if (abrt) break; - seteal(templ); - cycles -= timing_rr; - break; - case 0xC8: case 0x2C8: /*ENTER*/ - tempw2=getword(); - tempi=readmemb(cs,pc); pc++; - templ=EBP; - if (stack32) { writememw(ss,(ESP-2),BP); if (abrt) break; ESP-=2; } - else { writememw(ss,((SP-2)&0xFFFF),BP); if (abrt) break; SP-=2; } - templ2=ESP; - if (tempi>0) - { - while (--tempi) - { - EBP-=2; - if (stack32) tempw=readmemw(ss,EBP); - else tempw=readmemw(ss,BP); - if (abrt) { ESP=templ2; EBP=templ; break; } - if (stack32) { writememw(ss,(ESP-2),tempw); ESP-=2; } - else { writememw(ss,((SP-2)&0xFFFF),tempw); SP-=2; } - if (abrt) { ESP=templ2; EBP=templ; break; } - cycles-=(is486)?3:4; - } - if (stack32) { writememw(ss,(ESP-2),templ2); ESP-=2; } - else { writememw(ss,((SP-2)&0xFFFF),templ2); SP-=2; } - if (abrt) { ESP=templ2; EBP=templ; break; } - cycles-=(is486)?3:5; - } - BP = templ2; - if (stack32) ESP-=tempw2; - else SP-=tempw2; - cycles-=(is486)?14:10; -// if (cr0&1) pclog("BP %04X\n",BP); -// if (output==3) pclog("\n"); - break; - case 0x1C8: case 0x3C8: /*ENTER*/ -// if (output==1 && SS==0xA0) -// { -// enters++; -// for (ec=0;ec0) - { - while (--tempi) - { - EBP-=4; - if (stack32) templ=readmeml(ss,EBP); - else templ=readmeml(ss,BP); - if (abrt) { ESP=templ2; EBP=templ3; break; } - if (stack32) { writememl(ss,(ESP-4),templ); ESP-=4; } - else { writememl(ss,((SP-4)&0xFFFF),templ); SP-=4; } - if (abrt) { ESP=templ2; EBP=templ3; break; } - cycles-=(is486)?3:4; - } - if (stack32) { writememl(ss,(ESP-4),templ2); ESP-=4; } - else { writememl(ss,((SP-4)&0xFFFF),templ2); SP-=4; } - if (abrt) { ESP=templ2; EBP=templ3; break; } - cycles-=(is486)?3:5; - } - EBP=templ2; - if (stack32) ESP-=tempw; - else SP-=tempw; - cycles-=(is486)?14:10; -// if (output==3) pclog("\n"); - break; - case 0xC9: case 0x2C9: /*LEAVE*/ - templ=ESP; - SP=BP; - if (stack32) { tempw=readmemw(ss,ESP); ESP+=2; } - else { tempw=readmemw(ss,SP); SP+=2; } - if (abrt) { ESP=templ; break; } - BP=tempw; - cycles-=4; -// if (output==1 && SS==0xA0) -// { -// for (ec=0;ectempw2) - { - if (stack32) - { - templ=readmeml(ss,ESP); - loadseg(readmeml(ss,ESP+4),&_ss); - ESP=templ; - } - else - { - templ=readmeml(ss,SP); - loadseg(readmeml(ss,SP+4),&_ss); - ESP=templ; - } - } - cycles-=(is486)?13:18; - break; - case 0xCC: case 0x1CC: case 0x2CC: case 0x3CC: /*INT 3*/ - if (msw&1) - { - pmodeint(3,1); - cycles-=(is486)?44:59; - } - else - { - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,flags); - writememw(ss,ESP-4,CS); - writememw(ss,ESP-6,pc); - ESP-=6; - } - else - { - writememw(ss,((SP-2)&0xFFFF),flags); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),pc); - SP-=6; - } - addr=3<<2; -// flags&=~I_FLAG; - flags&=~T_FLAG; - oxpc=pc; - pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - cycles-=(is486)?26:33; - } - cycles-=23; - break; - case 0xCD: case 0x1CD: case 0x2CD: case 0x3CD: /*INT*/ - /*if (msw&1) pclog("INT %i %i %i\n",cr0&1,eflags&VM_FLAG,IOPL);*/ - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - break; - } - lastpc=pc; - lastcs=CS; - temp=readmemb(cs,pc); pc++; - intrt: - -// if (temp == 0x15 && AX == 0xc203) output = 3; -// /*if (temp == 0x13) */pclog("INT %02X %04X %04X %04X %04X:%04X %04X:%04X %c %i %i\n",temp,AX,BX,CX,DS,DX,CS,pc,(AL>31)?AL:' ', ins, ins2); - if (1) - { - if (msw&1) - { -// pclog("PMODE int %02X %04X at %04X:%04X ",temp,AX,CS,pc); - pmodeint(temp,1); - cycles-=(is486)?44:59; -// pclog("to %04X:%04X\n",CS,pc); - } - else - { - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,flags); - writememw(ss,ESP-4,CS); - writememw(ss,ESP-6,pc); - ESP-=6; - } - else - { - writememw(ss,((SP-2)&0xFFFF),flags); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),pc); - SP-=6; - } - addr=temp<<2; -// flags&=~I_FLAG; - flags&=~T_FLAG; - oxpc=pc; -// pclog("%04X:%04X : ",CS,pc); - pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - cycles-=(is486)?30:37; -// pclog("INT %02X - %04X %04X:%04X\n",temp,addr,CS,pc); - } - } - break; - case 0xCE: /*INTO*/ - if (flags&V_FLAG) - { - temp=4; - goto intrt; - } - cycles-=3; - break; - case 0xCF: case 0x2CF: /*IRET*/ -// if (CS == 0xc000) output = 0; -// pclog("IRET\n"); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - break; - } -// output=0; - if (ssegs) ss=oldss; - if (msw&1) - { - optype=IRET; - pmodeiret(0); - optype=0; - } - else - { - tempw=CS; - tempw2=pc; - inint=0; - oxpc=pc; - if (stack32) - { - pc=readmemw(ss,ESP); - loadcs(readmemw(ss,ESP+2)); - } - else - { - pc=readmemw(ss,SP); - loadcs(readmemw(ss,((SP+2)&0xFFFF))); - } - if (stack32) - { - flags=(readmemw(ss,ESP+4)&0xFFD5)|2; - ESP+=6; - } - else - { - flags=(readmemw(ss,((SP+4)&0xFFFF))&0xFFD5)|2; - SP+=6; - } - } - cycles-=(is486)?15:22; - break; - case 0x1CF: case 0x3CF: /*IRETD*/ -// if (output==3) output=1; -// pclog("IRET\n"); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - break; - } -// output=0; - if (ssegs) ss=oldss; - if (msw&1) - { - optype=IRET; - pmodeiret(1); - optype=0; - } - else - { - tempw=CS; - tempw2=pc; - inint=0; - oxpc=pc; - if (stack32) - { - pc=readmeml(ss,ESP); - templ=readmeml(ss,ESP+4); - } - else - { - pc=readmeml(ss,SP); - templ=readmeml(ss,((SP+4)&0xFFFF)); - } - if (stack32) - { - flags=(readmemw(ss,ESP+8)&0xFFD5)|2; - eflags=readmemw(ss,ESP+10); - ESP+=12; - } - else - { - flags=(readmemw(ss,(SP+8)&0xFFFF)&0xFFD5)|2; - eflags=readmemw(ss,(SP+10)&0xFFFF); - SP+=12; - } - loadcs(templ); - } - cycles-=(is486)?15:22; - break; - - case 0xD0: case 0x1D0: case 0x2D0: case 0x3D0: - fetchea(); - temp=geteab(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL b,1*/ - seteab((temp<<1)|((temp&0x80)?1:0)); if (abrt) break; - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=1; - if (flags&C_FLAG) temp|=1; - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x08: /*ROR b,1*/ - seteab((temp>>1)|((temp&1)?0x80:0)); if (abrt) break; - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (flags&C_FLAG) temp|=0x80; - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x10: /*RCL b,1*/ - temp2=flags&C_FLAG; - seteab((temp<<1)|temp2); if (abrt) break; - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=1; - if (temp2) temp|=1; - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x18: /*RCR b,1*/ - temp2=flags&C_FLAG; - seteab((temp>>1)|(temp2?0x80:0)); if (abrt) break; - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (temp2) temp|=0x80; - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x20: case 0x30: /*SHL b,1*/ - seteab(temp<<1); if (abrt) break; - setznp8(temp<<1); - if (temp&0x80) flags|=C_FLAG; - if ((temp^(temp<<1))&0x80) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x28: /*SHR b,1*/ - seteab(temp>>1); if (abrt) break; - setznp8(temp>>1); - if (temp&1) flags|=C_FLAG; - if (temp&0x80) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x38: /*SAR b,1*/ - seteab((temp>>1)|(temp&0x80)); if (abrt) break; - setznp8((temp>>1)|(temp&0x80)); - if (temp&1) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - } - break; - case 0xD1: case 0x2D1: - fetchea(); - tempw=geteaw(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL w,1*/ - seteaw((tempw<<1)|(tempw>>15)); if (abrt) break; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=1; - if (flags&C_FLAG) tempw|=1; - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x08: /*ROR w,1*/ - seteaw((tempw>>1)|(tempw<<15)); if (abrt) break; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (flags&C_FLAG) tempw|=0x8000; - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x10: /*RCL w,1*/ - temp2=flags&C_FLAG; - seteaw((tempw<<1)|temp2); if (abrt) break; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=1; - if (temp2) tempw|=1; - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x18: /*RCR w,1*/ - temp2=flags&C_FLAG; - seteaw((tempw>>1)|(temp2?0x8000:0)); if (abrt) break; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (temp2) tempw|=0x8000; - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x20: case 0x30: /*SHL w,1*/ - seteaw(tempw<<1); if (abrt) break; - setznp16(tempw<<1); - if (tempw&0x8000) flags|=C_FLAG; - if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x28: /*SHR w,1*/ - seteaw(tempw>>1); if (abrt) break; - setznp16(tempw>>1); - if (tempw&1) flags|=C_FLAG; - if (tempw&0x8000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x38: /*SAR w,1*/ - seteaw((tempw>>1)|(tempw&0x8000)); if (abrt) break; - setznp16((tempw>>1)|(tempw&0x8000)); - if (tempw&1) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - - default: - pclog("Bad D1 opcode %02X\n",rmdat&0x38); - } - break; - case 0x1D1: case 0x3D1: - fetchea(); - templ=geteal(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL l,1*/ - seteal((templ<<1)|(templ>>31)); if (abrt) break; - if (templ&0x80000000) flags|=C_FLAG; - else flags&=~C_FLAG; - templ<<=1; - if (flags&C_FLAG) templ|=1; - if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x08: /*ROR l,1*/ - seteal((templ>>1)|(templ<<31)); if (abrt) break; - if (templ&1) flags|=C_FLAG; - else flags&=~C_FLAG; - templ>>=1; - if (flags&C_FLAG) templ|=0x80000000; - if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x10: /*RCL l,1*/ - temp2=flags&C_FLAG; - seteal((templ<<1)|temp2); if (abrt) break; - if (templ&0x80000000) flags|=C_FLAG; - else flags&=~C_FLAG; - templ<<=1; - if (temp2) templ|=1; - if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x18: /*RCR l,1*/ - temp2=flags&C_FLAG; - seteal((templ>>1)|(temp2?0x80000000:0)); if (abrt) break; - temp2=flags&C_FLAG; - if (templ&1) flags|=C_FLAG; - else flags&=~C_FLAG; - templ>>=1; - if (temp2) templ|=0x80000000; - if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x20: case 0x30: /*SHL l,1*/ - seteal(templ<<1); if (abrt) break; - setznp32(templ<<1); - if (templ&0x80000000) flags|=C_FLAG; - if ((templ^(templ<<1))&0x80000000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x28: /*SHR l,1*/ - seteal(templ>>1); if (abrt) break; - setznp32(templ>>1); - if (templ&1) flags|=C_FLAG; - if (templ&0x80000000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x38: /*SAR l,1*/ - seteal((templ>>1)|(templ&0x80000000)); if (abrt) break; - setznp32((templ>>1)|(templ&0x80000000)); - if (templ&1) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - - default: - pclog("Bad D1 opcode %02X\n",rmdat&0x38); - } - break; - - case 0xD2: case 0x1D2: case 0x2D2: case 0x3D2: - fetchea(); - temp=geteab(); if (abrt) break; - c=CL&31; -// cycles-=c; - if (!c) break; -// if (c>7) pclog("Shiftb %i %02X\n",rmdat&0x38,c); - switch (rmdat&0x38) - { - case 0x00: /*ROL b,CL*/ - while (c>0) - { - temp2=(temp&0x80)?1:0; - temp=(temp<<1)|temp2; - c--; - } - seteab(temp); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x08: /*ROR b,CL*/ - while (c>0) - { - temp2=temp&1; - temp>>=1; - if (temp2) temp|=0x80; - c--; - } - seteab(temp); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp2) flags|=C_FLAG; - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x10: /*RCL b,CL*/ - tempc=flags&C_FLAG; - while (c>0) - { - templ=tempc; - tempc=temp&0x80; - temp<<=1; - if (templ) temp|=1; - c--; - } - seteab(temp); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (tempc) flags|=C_FLAG; - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x18: /*RCR b,CL*/ - tempc=flags&C_FLAG; - while (c>0) - { - templ=tempc; - tempc=temp&1; - temp>>=1; - if (templ) temp|=0x80; - c--; - } - seteab(temp); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (tempc) flags|=C_FLAG; - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x20: case 0x30: /*SHL b,CL*/ - seteab(temp<>c); if (abrt) break; - setznp8(temp>>c); - if ((temp>>(c-1))&1) flags|=C_FLAG; - if (c==1 && temp&0x80) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x38: /*SAR b,CL*/ - tempc=(temp>>(c-1))&1; - while (c>0) - { - temp>>=1; - if (temp&0x40) temp|=0x80; - c--; - } - seteab(temp); if (abrt) break; - setznp8(temp); - if (tempc) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - } - break; - - case 0xD3: case 0x2D3: - fetchea(); - tempw=geteaw(); if (abrt) break; - c=CL&31; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL w,CL*/ - while (c>0) - { - temp=(tempw&0x8000)?1:0; - tempw=(tempw<<1)|temp; - c--; - } - seteaw(tempw); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp) flags|=C_FLAG; - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x08: /*ROR w,CL*/ - while (c>0) - { - tempw2=(tempw&1)?0x8000:0; - tempw=(tempw>>1)|tempw2; - c--; - } - seteaw(tempw); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (tempw2) flags|=C_FLAG; - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x10: /*RCL w,CL*/ - tempc=flags&C_FLAG; - while (c>0) - { - templ=tempc; - tempc=tempw&0x8000; - tempw=(tempw<<1)|templ; - c--; - } - seteaw(tempw); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (tempc) flags|=C_FLAG; - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x18: /*RCR w,CL*/ - tempc=flags&C_FLAG; - while (c>0) - { - templ=tempc; - tempw2=(templ&1)?0x8000:0; - tempc=tempw&1; - tempw=(tempw>>1)|tempw2; - c--; - } - seteaw(tempw); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (tempc) flags|=C_FLAG; - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - - case 0x20: case 0x30: /*SHL w,CL*/ - seteaw(tempw<>c); if (abrt) break; - setznp16(tempw>>c); - if ((tempw>>(c-1))&1) flags|=C_FLAG; - if (c==1 && tempw&0x8000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - - case 0x38: /*SAR w,CL*/ - tempw2=tempw&0x8000; - tempc=((int16_t)tempw>>(c-1))&1; - while (c>0) - { - tempw=(tempw>>1)|tempw2; - c--; - } - seteaw(tempw); if (abrt) break; - setznp16(tempw); - if (tempc) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - } - break; - case 0x1D3: case 0x3D3: - fetchea(); - templ=geteal(); if (abrt) break; - c=CL&31; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL l,CL*/ - while (c>0) - { - temp=(templ&0x80000000)?1:0; - templ=(templ<<1)|temp; - c--; - } - seteal(templ); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (temp) flags|=C_FLAG; - if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x08: /*ROR l,CL*/ - while (c>0) - { - templ2=(templ&1)?0x80000000:0; - templ=(templ>>1)|templ2; - c--; - } - seteal(templ); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (templ2) flags|=C_FLAG; - if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x10: /*RCL l,CL*/ - tempc=flags&C_FLAG; - while (c>0) - { - templ2=tempc; - tempc=(templ>>31); - templ=(templ<<1)|templ2; - c--; - } - seteal(templ); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (templ2) flags|=C_FLAG; - if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - case 0x18: /*RCR l,CL*/ - tempc=flags&C_FLAG; - while (c>0) - { - templ2=(tempc)?0x80000000:0; - tempc=templ&1; - templ=(templ>>1)|templ2; - c--; - } - seteal(templ); if (abrt) break; - flags&=~(C_FLAG|V_FLAG); - if (templ2) flags|=C_FLAG; - if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - - case 0x20: case 0x30: /*SHL l,CL*/ - seteal(templ<>c); if (abrt) break; - setznp32(templ>>c); - if ((templ>>(c-1))&1) flags|=C_FLAG; - if (c==1 && templ&0x80000000) flags|=V_FLAG; - cycles-=((mod==3)?3:7); - break; - - case 0x38: /*SAR w,CL*/ - templ2=templ&0x80000000; - tempc=(templ>>(c-1))&1; - while (c>0) - { - templ=(templ>>1)|templ2; - c--; - } - seteal(templ); if (abrt) break; - setznp32(templ); - if (tempc) flags|=C_FLAG; - cycles-=((mod==3)?3:7); - break; - } - break; - - - case 0xD4: case 0x1D4: case 0x2D4: case 0x3D4: /*AAM*/ - tempws=readmemb(cs,pc); pc++; - if (!tempws || cpu_manufacturer != MANU_INTEL) tempws = 10; - AH=AL/tempws; - AL%=tempws; - setznp16(AX); - cycles-=(is486)?15:17; - break; - case 0xD5: case 0x1D5: case 0x2D5: case 0x3D5: /*AAD*/ - tempws=readmemb(cs,pc); pc++; - if (cpu_manufacturer != MANU_INTEL) tempws = 10; - AL=(AH*tempws)+AL; - AH=0; - setznp16(AX); - cycles-=(is486)?14:19; - break; - case 0xD6: case 0x1D6: case 0x2D6: case 0x3D6: /*SETALC*/ - AL=(flags&C_FLAG)?0xFF:0; - cycles -= timing_rr; - break; - case 0xD7: case 0x1D7: /*XLAT*/ - addr=(BX+AL)&0xFFFF; - temp=readmemb(ds,addr); if (abrt) break; - AL=temp; - cycles-=5; - break; - case 0x2D7: case 0x3D7: /*XLAT*/ - addr=EBX+AL; - temp=readmemb(ds,addr); if (abrt) break; - AL=temp; - cycles-=5; - break; - case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/ - case 0x1D9: case 0x1DA: case 0x1DB: case 0x1DD: /*ESCAPE*/ - case 0x2D9: case 0x2DA: case 0x2DB: case 0x2DD: /*ESCAPE*/ - case 0x3D9: case 0x3DA: case 0x3DB: case 0x3DD: /*ESCAPE*/ - case 0xD8: case 0x1D8: case 0x2D8: case 0x3D8: - case 0xDC: case 0x1DC: case 0x2DC: case 0x3DC: - case 0xDE: case 0x1DE: case 0x2DE: case 0x3DE: - case 0xDF: case 0x1DF: case 0x2DF: case 0x3DF: - if ((cr0&6)==4) - { - pc=oldpc; - pmodeint(7,0); - cycles-=59; - } - else - { - fpucount++; - fetchea(); - if (hasfpu) - { - x87_pc_off=oldpc; - x87_pc_seg=CS; - x87_op_off=eaaddr; - x87_op_seg=ea_rseg; - switch (opcode) - { - case 0xD8: x87_d8(); break; - case 0xD9: x87_d9(); break; - case 0xDA: x87_da(); break; - case 0xDB: x87_db(); break; - case 0xDC: x87_dc(); break; - case 0xDD: x87_dd(); break; - case 0xDE: x87_de(); break; - case 0xDF: x87_df(); break; - } - } - //cycles-=8; - } - break; - - case 0xE0: case 0x1E0: /*LOOPNE*/ - offset=(int8_t)readmemb(cs,pc); pc++; - CX--; - if (CX && !(flags&Z_FLAG)) { pc+=offset; } - cycles-=(is486)?7:11; - break; - case 0x2E0: case 0x3E0: /*LOOPNE*/ - offset=(int8_t)readmemb(cs,pc); pc++; - ECX--; - if (ECX && !(flags&Z_FLAG)) { pc+=offset; } - cycles-=(is486)?7:11; - break; - case 0xE1: case 0x1E1: /*LOOPE*/ - offset=(int8_t)readmemb(cs,pc); pc++; - CX--; - if (CX && (flags&Z_FLAG)) { pc+=offset; } - cycles-=(is486)?7:11; - break; - case 0x2E1: case 0x3E1: /*LOOPE*/ - offset=(int8_t)readmemb(cs,pc); pc++; - ECX--; - if (ECX && (flags&Z_FLAG)) { pc+=offset; } - cycles-=(is486)?7:11; - break; - case 0xE2: case 0x1E2: /*LOOP*/ - offset=(int8_t)readmemb(cs,pc); pc++; - CX--; - if (CX) { pc+=offset; } - cycles-=(is486)?7:11; - break; - case 0x2E2: case 0x3E2: /*LOOP*/ - offset=(int8_t)readmemb(cs,pc); pc++; - ECX--; - if (ECX) { pc+=offset; } - cycles-=(is486)?7:11; - break; - case 0xE3: case 0x1E3: /*JCXZ*/ - offset=(int8_t)readmemb(cs,pc); pc++; - if (!CX) { pc+=offset; cycles-=4; } - cycles-=5; - break; - case 0x2E3: case 0x3E3: /*JECXZ*/ - offset=(int8_t)readmemb(cs,pc); pc++; - if (!ECX) { pc+=offset; cycles-=4; } - cycles-=5; - break; - - case 0xE4: case 0x1E4: case 0x2E4: case 0x3E4: /*IN AL*/ - temp=readmemb(cs,pc); - checkio_perm(temp); - pc++; - AL=inb(temp); - cycles-=12; - break; - case 0xE5: case 0x2E5: /*IN AX*/ - temp=readmemb(cs,pc); - checkio_perm(temp); - checkio_perm(temp+1); - pc++; - AX=inw(temp); - cycles-=12; - break; - case 0x1E5: case 0x3E5: /*IN EAX*/ - temp=readmemb(cs,pc); - checkio_perm(temp); - checkio_perm(temp+1); - checkio_perm(temp+2); - checkio_perm(temp+3); - pc++; - EAX=inl(temp); - cycles-=12; - break; - case 0xE6: case 0x1E6: case 0x2E6: case 0x3E6: /*OUT AL*/ - temp=readmemb(cs,pc); -// if (output) pclog("OUT %02X,%02X - %08X\n",temp,AL,writelookup2); - checkio_perm(temp); - // if (output) pclog(" - %08X\n",writelookup2); - pc++; - outb(temp,AL); -// if (output) pclog(" - %08X\n",writelookup2); - cycles-=10; - break; - case 0xE7: case 0x2E7: /*OUT AX*/ - temp=readmemb(cs,pc); - checkio_perm(temp); - checkio_perm(temp+1); - pc++; - outw(temp,AX); - cycles-=10; - break; - case 0x1E7: case 0x3E7: /*OUT EAX*/ - temp=readmemb(cs,pc); - checkio_perm(temp); - checkio_perm(temp+1); - checkio_perm(temp+2); - checkio_perm(temp+3); - pc++; - outl(temp,EAX); - cycles-=10; - break; - - case 0xE8: /*CALL rel 16*/ - tempw=getword(); if (abrt) break; - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,pc); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,((SP-2)&0xFFFF),pc); if (abrt) break; - SP-=2; - } - pc+=(int16_t)tempw; - cycles-=(is486)?3:7; - break; - case 0x3E8: /*CALL rel 16*/ - templ=getlong(); if (abrt) break; - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,pc); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),pc); if (abrt) break; - SP-=4; - } - pc+=templ; - cycles-=(is486)?3:7; - break; - case 0xE9: case 0x2E9: /*JMP rel 16*/ - tempw=getword(); if (abrt) break; - pc+=(int16_t)tempw; - cycles-=(is486)?3:7; - break; - case 0x1E9: case 0x3E9: /*JMP rel 32*/ - templ=getlong(); if (abrt) break; - pc+=templ; - cycles-=(is486)?3:7; - break; - case 0xEA: case 0x2EA: /*JMP far*/ - addr=getword(); - tempw=getword(); if (abrt) { if (output==3) pclog("JMP ABRT\n"); break; } - oxpc=pc; - pc=addr; - loadcsjmp(tempw,oxpc); - cycles-=(is486)?17:12; - break; - case 0x1EA: case 0x3EA: /*JMP far*/ - templ=getlong(); - tempw=getword(); if (abrt) break; - oxpc=pc; - pc=templ; - loadcsjmp(tempw,oxpc); - cycles-=(is486)?17:12; - break; - case 0xEB: case 0x1EB: case 0x2EB: case 0x3EB: /*JMP rel*/ - offset=(int8_t)readmemb(cs,pc); pc++; - pc+=offset; - cycles-=(is486)?3:7; - break; - case 0xEC: case 0x1EC: case 0x2EC: case 0x3EC: /*IN AL,DX*/ - checkio_perm(DX); - AL=inb(DX); - cycles-=13; - break; - case 0xED: case 0x2ED: /*IN AX,DX*/ - checkio_perm(DX); - checkio_perm(DX+1); - AX=inw(DX); - cycles-=13; - break; - case 0x1ED: case 0x3ED: /*IN EAX,DX*/ - checkio_perm(DX); - checkio_perm(DX+1); - checkio_perm(DX+2); - checkio_perm(DX+3); - EAX=inl(DX); - cycles-=13; - break; - case 0xEE: case 0x1EE: case 0x2EE: case 0x3EE: /*OUT DX,AL*/ - checkio_perm(DX); - outb(DX,AL); - cycles-=11; - break; - case 0xEF: case 0x2EF: /*OUT DX,AX*/ - checkio_perm(DX); - checkio_perm(DX+1); - outw(DX,AX); - cycles-=11; - break; - case 0x1EF: case 0x3EF: /*OUT DX,EAX*/ - checkio_perm(DX); - checkio_perm(DX+1); - checkio_perm(DX+2); - checkio_perm(DX+3); - outl(DX,EAX); - cycles-=11; - break; - - case 0xF0: case 0x1F0: case 0x2F0: case 0x3F0: /*LOCK*/ - cycles-=4; - break; - - case 0xF2: case 0x1F2: case 0x2F2: case 0x3F2: /*REPNE*/ - rep386(0); - break; - case 0xF3: case 0x1F3: case 0x2F3: case 0x3F3: /*REPE*/ - rep386(1); - break; - - case 0xF4: case 0x1F4: case 0x2F4: case 0x3F4: /*HLT*/ - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) - { -// pclog("Can't HLT\n"); - x86gpf(NULL,0); - //output=3; - break; - } - inhlt=1; - pc--; - if (!((flags&I_FLAG) && (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2)) && !ssegs && !noint)) cycles = oldcyc - 100; - else cycles-=5; - break; - case 0xF5: case 0x1F5: case 0x2F5: case 0x3F5: /*CMC*/ - flags^=C_FLAG; - cycles-=2; - break; - - case 0xF6: case 0x1F6: case 0x2F6: case 0x3F6: - fetchea(); - temp=geteab(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*TEST b,#8*/ - temp2=readmemb(cs,pc); pc++; if (abrt) break; -// pclog("TEST %02X,%02X\n",temp,temp2); - temp&=temp2; - setznp8(temp); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x10: /*NOT b*/ - temp=~temp; - seteab(temp); - cycles -= (mod == 3) ? timing_rr : timing_mm; - break; - case 0x18: /*NEG b*/ - setsub8(0,temp); - temp=0-temp; - seteab(temp); - cycles -= (mod == 3) ? timing_rr : timing_mm; - break; - case 0x20: /*MUL AL,b*/ -// setznp8(AL); - AX=AL*temp; -// if (AX) flags&=~Z_FLAG; -// else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=13; - break; - case 0x28: /*IMUL AL,b*/ -// setznp8(AL); - tempws=(int)((int8_t)AL)*(int)((int8_t)temp); - AX=tempws&0xFFFF; -// if (AX) flags&=~Z_FLAG; -// else flags|=Z_FLAG; - if (AH && AH!=0xFF) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=14; - break; - case 0x30: /*DIV AL,b*/ - tempw=AX; - if (temp) tempw2=tempw/temp; -// pclog("DIV %04X/%02X %04X:%04X\n",tempw,temp,CS,pc); - if (temp && !(tempw2&0xFF00)) - { - tempw2=tempw%temp; - AH=tempw2; - tempw/=temp; - AL=tempw&0xFF; - if (!cpu_iscyrix) flags|=0x8D5; /*Not a Cyrix*/ - } - else - { -// fatal("DIVb BY 0\n"); - pc=oldpc; - if (msw&1) pmodeint(0,0); - else - { -// pclog("%04X:%04X\n",cs>>4,pc); - writememw(ss,(SP-2)&0xFFFF,flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,pc); - SP-=6; - flags&=~I_FLAG; - oxpc=pc; - pc=readmemw(0,0); - loadcs(readmemw(0,2)); - } -// cs=loadcs(CS); -// cs=CS<<4; - } - cycles-=(is486)?16:14; - break; - case 0x38: /*IDIV AL,b*/ -// pclog("IDIV %04X/%02X\n",tempw,temp); - tempws=(int)(int16_t)AX; - if (temp!=0) tempws2=tempws/(int)((int8_t)temp); - temps=tempws2&0xFF; - if ((temp!=0) && ((int)temps==tempws2)) - { - tempw2=tempws%(int)((int8_t)temp); - AH=tempw2&0xFF; - AL=tempws2&0xFF; - if (!cpu_iscyrix) flags|=0x8D5; /*Not a Cyrix*/ - } - else - { - pclog("IDIVb exception - %X / %08X = %X\n",tempws,temp,tempws2); -// pclog("IDIVb BY 0 %04X:%04X\n",cs>>4,pc); - pc=oldpc; - if (msw&1) pmodeint(0,0); - else - { - writememw(ss,(SP-2)&0xFFFF,flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,pc); - SP-=6; - flags&=~I_FLAG; - oxpc=pc; - pc=readmemw(0,0); - loadcs(readmemw(0,2)); - } -// cs=loadcs(CS); -// cs=CS<<4; -// pclog("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x38); - } - cycles-=19; - break; - - default: - pclog("Bad F6 opcode %02X\n",rmdat&0x38); - x86illegal(); - } - break; - - case 0xF7: case 0x2F7: - fetchea(); - tempw=geteaw(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*TEST w*/ - tempw2=getword(); if (abrt) break; -// if (output==3) pclog("TEST %04X %04X\n",tempw,tempw2); - setznp16(tempw&tempw2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x10: /*NOT w*/ - seteaw(~tempw); - cycles -= (mod == 3) ? timing_rr : timing_mm; - break; - case 0x18: /*NEG w*/ - setsub16(0,tempw); - tempw=0-tempw; - seteaw(tempw); - cycles -= (mod == 3) ? timing_rr : timing_mm; - break; - case 0x20: /*MUL AX,w*/ -// setznp16(AX); - templ=AX*tempw; - AX=templ&0xFFFF; - DX=templ>>16; -// if (AX|DX) flags&=~Z_FLAG; -// else flags|=Z_FLAG; - if (DX) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=21; - break; - case 0x28: /*IMUL AX,w*/ -// setznp16(AX); -// pclog("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw)); - templ=(int)((int16_t)AX)*(int)((int16_t)tempw); -// pclog("%i ",tempws); - AX=templ&0xFFFF; - DX=templ>>16; - if (DX && DX!=0xFFFF) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=22; - break; - case 0x30: /*DIV AX,w*/ - templ=(DX<<16)|AX; - if (tempw) templ2=templ/tempw; - if (tempw && !(templ2&0xFFFF0000)) - { - tempw2=templ%tempw; - DX=tempw2; - templ/=tempw; - AX=templ&0xFFFF; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { -// fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins); - pc=oldpc; - if (msw&1) pmodeint(0,0); - else - { -// pclog("%04X:%04X\n",cs>>4,pc); - writememw(ss,(SP-2)&0xFFFF,flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,pc); - SP-=6; - flags&=~I_FLAG; - oxpc=pc; - pc=readmemw(0,0); - loadcs(readmemw(0,2)); - } -// cs=loadcs(CS); -// cs=CS<<4; -// pclog("Div by zero %04X:%04X %02X %02X 1\n",cs>>4,pc,0xf7,0x30); - } - cycles-=(is486)?24:22; - break; - case 0x38: /*IDIV AX,w*/ - tempws=(int)((DX<<16)|AX); - if (tempw!=0) tempws2=tempws/(int)((int16_t)tempw); - temps16=tempws2&0xFFFF; -// pclog("IDIV %i %i ",tempws,tempw); - if ((tempw!=0) && ((int)temps16==tempws2)) - { - DX=tempws%(int)((int16_t)tempw); - AX=tempws2&0xFFFF; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { - pclog("IDIVw exception - %X / %08X = %X\n",tempws,tempw,tempws2); -// pclog("IDIVw BY 0 %04X:%04X\n",cs>>4,pc); -// DX=0; -// AX=0xFFFF; - pc=oldpc; - if (msw&1) pmodeint(0,0); - else - { -// pclog("%04X:%04X\n",cs>>4,pc); - writememw(ss,(SP-2)&0xFFFF,flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,pc); - SP-=6; - flags&=~I_FLAG; - oxpc=pc; - pc=readmemw(0,0); - loadcs(readmemw(0,2)); - } -// cs=loadcs(CS); -// cs=CS<<4; -// pclog("Div by zero %04X:%04X %02X %02X 1\n",cs>>4,pc,0xf7,0x38); - } - cycles-=27; - break; - - default: - pclog("Bad F7 opcode %02X\n",rmdat&0x38); - x86illegal(); - } - break; - case 0x1F7: case 0x3F7: - fetchea(); - templ=geteal(); if (abrt) break; - switch (rmdat&0x38) - { - case 0x00: /*TEST l*/ - templ2=getlong(); if (abrt) break; - setznp32(templ&templ2); - if (is486) cycles-=((mod==3)?1:2); - else cycles-=((mod==3)?2:5); - break; - case 0x10: /*NOT l*/ - seteal(~templ); - cycles -= (mod == 3) ? timing_rr : timing_mml; - break; - case 0x18: /*NEG l*/ - setsub32(0,templ); - templ=0-templ; - seteal(templ); - cycles -= (mod == 3) ? timing_rr : timing_mml; - break; - case 0x20: /*MUL EAX,l*/ - temp64=(uint64_t)EAX*(uint64_t)templ; - EAX=temp64&0xFFFFFFFF; - EDX=temp64>>32; - if (EDX) flags|= (C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=21; - break; - case 0x28: /*IMUL EAX,l*/ - temp64=(int64_t)(int32_t)EAX*(int64_t)(int32_t)templ; - EAX=temp64&0xFFFFFFFF; - EDX=temp64>>32; - if (EDX && EDX!=0xFFFFFFFF) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=38; - break; - case 0x30: /*DIV EAX,l*/ - divl(templ); - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - cycles-=(is486)?40:38; - break; - case 0x38: /*IDIV EAX,l*/ - idivl((int32_t)templ); - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - cycles-=43; - break; - - default: - pclog("Bad F7 opcode %02X\n",rmdat&0x38); - x86illegal(); - } - break; - - case 0xF8: case 0x1F8: case 0x2F8: case 0x3F8: /*CLC*/ - flags&=~C_FLAG; - cycles-=2; - break; - case 0xF9: case 0x1F9: case 0x2F9: case 0x3F9: /*STC*/ -// pclog("STC %04X\n",pc); - flags|=C_FLAG; - cycles-=2; - break; - case 0xFA: case 0x1FA: case 0x2FA: case 0x3FA: /*CLI*/ - if (!IOPLp) - { -// output=3; -// pclog("Can't CLI %i %i %04X:%08X\n",IOPL,CPL,CS,pc); -// if (CS==0x1C7 && pc==0x5BE) output=3; - x86gpf(NULL,0); - } - else - flags&=~I_FLAG; -// pclog("CLI at %04X:%04X\n",cs>>4,pc); - cycles-=3; - break; - case 0xFB: case 0x1FB: case 0x2FB: case 0x3FB: /*STI*/ - if (!IOPLp) - { -// pclog("Can't STI %04X:%08X\n",CS,pc); -// output=3; - x86gpf(NULL,0); - } - else - flags|=I_FLAG; -// pclog("STI at %04X:%04X\n",cs>>4,pc); - cycles-=2; - break; - case 0xFC: case 0x1FC: case 0x2FC: case 0x3FC: /*CLD*/ - flags&=~D_FLAG; - cycles-=2; - break; - case 0xFD: case 0x1FD: case 0x2FD: case 0x3FD: /*STD*/ - flags|=D_FLAG; - cycles-=2; - break; - - case 0xFE: case 0x1FE: case 0x2FE: case 0x3FE: /*INC/DEC b*/ - fetchea(); - temp=geteab(); if (abrt) break; - if (rmdat&0x38) - { - seteab(temp-1); if (abrt) break; - flags&=~V_FLAG; - setsub8nc(temp,1); - temp2=temp-1; - if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG; - } - else - { - seteab(temp+1); if (abrt) break; - flags&=~V_FLAG; - setadd8nc(temp,1); - temp2=temp+1; - if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG; - } - cycles -= (mod == 3) ? timing_rr : timing_mm; - break; - - case 0xFF: case 0x2FF: - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*INC w*/ - tempw=geteaw(); if (abrt) break; - seteaw(tempw+1); if (abrt) break; - setadd16nc(tempw,1); - cycles -= (mod == 3) ? timing_rr : timing_mm; - break; - case 0x08: /*DEC w*/ - tempw=geteaw(); if (abrt) break; - seteaw(tempw-1); if (abrt) break; - setsub16nc(tempw,1); - cycles -= (mod == 3) ? timing_rr : timing_mm; - break; - case 0x10: /*CALL*/ - tempw=geteaw(); - if (output) pclog("CALL %04X %08X:%08X\n", tempw, easeg, eaaddr); - if (abrt) break; - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,pc); if (abrt) break; - ESP-=2; - } - else - { - writememw(ss,(SP-2)&0xFFFF,pc); if (abrt) break; - SP-=2; - } - pc=tempw; - if (is486) cycles-=5; - else cycles-=((mod==3)?7:10); - break; - case 0x18: /*CALL far*/ - tempw=readmemw(easeg,eaaddr); - tempw2=readmemw(easeg,(eaaddr+2)); if (output==3) pclog("CALL FAR %04X:%04X\n",tempw,tempw2); if (abrt) break; - tempw3=CS; - templ2=pc; - if (ssegs) ss=oldss; - oxpc=pc; - pc=tempw; - optype=CALL; - cgate32=0; - if (msw&1) loadcscall(tempw2); - else loadcs(tempw2); - optype=0; - if (abrt) break; - oldss=ss; - if (cgate32) goto writecall32_2; - writecall16_2: - if (stack32) - { - writememw(ss,ESP-2,tempw3); - writememw(ss,ESP-4,templ2); - ESP-=4; - } - else - { - writememw(ss,(SP-2)&0xFFFF,tempw3); - writememw(ss,((SP-4)&0xFFFF),templ2); - SP-=4; - } - cycles-=(is486)?17:22; - break; - case 0x20: /*JMP*/ - tempw=geteaw(); if (abrt) break; - pc=tempw; - if (is486) cycles-=5; - else cycles-=((mod==3)?7:10); - break; - case 0x28: /*JMP far*/ - oxpc=pc; - tempw=readmemw(easeg,eaaddr); - tempw2=readmemw(easeg,eaaddr+2); if (abrt) break; - pc=tempw; - loadcsjmp(tempw2,oxpc); if (abrt) break; - cycles-=(is486)?13:12; - break; - case 0x30: /*PUSH w*/ - tempw=geteaw(); if (abrt) break; - if (ssegs) ss=oldss; - if (stack32) - { - writememw(ss,ESP-2,tempw); if (abrt) break; - ESP-=2; - } - else - { -// if (output) pclog("PUSH %04X to %04X\n",tempw,SP-2); - writememw(ss,((SP-2)&0xFFFF),tempw); if (abrt) break; - SP-=2; - } - cycles-=((mod==3)?2:5); - break; - - default: - pclog("Bad FF opcode %02X\n",rmdat&0x38); - x86illegal(); - } - break; - case 0x1FF: case 0x3FF: - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*INC l*/ - templ=geteal(); if (abrt) break; - seteal(templ+1); if (abrt) break; - setadd32nc(templ,1); - cycles -= (mod == 3) ? timing_rr : timing_mml; - break; - case 0x08: /*DEC l*/ - templ=geteal(); if (abrt) break; - seteal(templ-1); if (abrt) break; - setsub32nc(templ,1); - cycles -= (mod == 3) ? timing_rr : timing_mml; - break; - case 0x10: /*CALL*/ - templ=geteal(); if (abrt) break; - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,pc); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,(SP-4)&0xFFFF,pc); if (abrt) break; - SP-=4; - } - pc=templ; - if (pc==0xFFFFFFFF) pclog("Failed CALL!\n"); - if (is486) cycles-=5; - else cycles-=((mod==3)?7:10); - break; - case 0x18: /*CALL far*/ - templ=readmeml(easeg,eaaddr); - tempw2=readmemw(easeg,(eaaddr+4)); if (abrt) break; - tempw3=CS; - templ2=pc; - if (ssegs) ss=oldss; - oxpc=pc; - pc=templ; - optype=CALL; - cgate16=0; - if (msw&1) loadcscall(tempw2); - else loadcs(tempw2); - optype=0; - if (abrt) break; - oldss=ss; - if (cgate16) goto writecall16_2; - writecall32_2: - if (stack32) - { - writememl(ss,ESP-4,tempw3); - writememl(ss,ESP-8,templ2); - ESP-=8; - } - else - { - writememl(ss,(SP-4)&0xFFFF,tempw3); - writememl(ss,(SP-8)&0xFFFF,templ2); - SP-=8; - } - if (pc==0xFFFFFFFF) pclog("Failed CALL far!\n"); - cycles-=(is486)?17:22; - break; - case 0x20: /*JMP*/ - templ=geteal(); if (abrt) break; - pc=templ; - if (is486) cycles-=5; - else cycles-=((mod==3)?7:12); - if (pc==0xFFFFFFFF) pclog("Failed JMP!\n"); - break; - case 0x28: /*JMP far*/ - oxpc=pc; - templ=readmeml(easeg,eaaddr); - templ2=readmeml(easeg,eaaddr+4); if (abrt) break; - pc=templ; - loadcsjmp(templ2,oxpc); - if (pc==0xFFFFFFFF) pclog("Failed JMP far!\n"); - cycles-=(is486)?13:12; - break; - case 0x30: /*PUSH l*/ - templ=geteal(); if (abrt) break; - if (ssegs) ss=oldss; - if (stack32) - { - writememl(ss,ESP-4,templ); if (abrt) break; - ESP-=4; - } - else - { - writememl(ss,((SP-4)&0xFFFF),templ); if (abrt) break; - SP-=4; - } - cycles-=((mod==3)?2:5); - break; - - default: - pclog("Bad 32-bit FF opcode %02X\n",rmdat&0x38); - x86illegal(); - } - break; - - default: -// pc--; -// cycles-=8; -// break; - pclog("Bad opcode %02X %i %03X at %04X:%04X from %04X:%04X %08X\n",opcode,op32>>8,opcode|op32,cs>>4,pc,old8>>16,old8&0xFFFF,old82); - x86illegal(); - } - opcodeend: - if (!use32) pc&=0xFFFF; - + pclog("Output on\n"); + output = 3; + }*/ + if ((cs + pc) == 0xc) + fatal("Dead\n"); if (ssegs) { ds=oldds; @@ -8164,7 +1297,8 @@ dontprint=0; } if (abrt) { - + flags_rebuild(); +// pclog("Abort\n"); // if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt); /* if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc); if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc); @@ -8173,8 +1307,8 @@ dontprint=0; if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc); if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc); if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc); - if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc); - if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/ + if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);*/ +/* if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/ tempi = abrt; abrt = 0; x86_doabrt(tempi); @@ -8183,7 +1317,7 @@ dontprint=0; abrt = 0; CS = oldcs; pc = oldpc; - pclog("Double fault %i %i\n", ins, resets); + pclog("Double fault %i\n", ins); pmodeint(8, 0); if (abrt) { @@ -8195,11 +1329,12 @@ dontprint=0; } cycdiff=oldcyc-cycles; - if (trap && (flags&T_FLAG) && !noint) + if (trap && (flags&T_FLAG)) { + flags_rebuild(); // oldpc=pc; // oldcs=CS; -// printf("TRAP!!! %04X:%04X\n",CS,pc); +// pclog("TRAP!!! %04X:%04X\n",CS,pc); if (msw&1) { pmodeint(1,0); @@ -8217,16 +1352,24 @@ dontprint=0; loadcs(readmemw(0,addr+2)); } } - else if ((flags&I_FLAG) && (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2)) && !noint) + else if (nmi && nmi_enable) + { + oldpc = pc; + oldcs = CS; +// pclog("NMI\n"); + x86_int(2); + nmi_enable = 0; + } + else if ((flags&I_FLAG) && pic_intpending) { temp=picinterrupt(); if (temp!=0xFF) { // if (temp == 0x54) pclog("Take int 54\n"); // if (output) output=3; -// pclog("Hardware int %02X %i %i %04X(%08X):%08X\n",temp,ins, ins2, CS,cs,pc); +// if (temp == 0xd) pclog("Hardware int %02X %i %04X(%08X):%08X\n",temp,ins, CS,cs,pc); // if (temp==0x54) output=3; - if (inhlt) pc++; + flags_rebuild(); if (msw&1) { pmodeint(temp,0); @@ -8245,133 +1388,42 @@ dontprint=0; loadcs(readmemw(0,addr+2)); // if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc); } - inint=1; +// pclog("Now at %04X(%08X):%08X\n", CS, cs, pc); } } - if (noint) noint=0; + +// tempi = ZF_SET() ? Z_FLAG : 0; +// if (tempi != (flags & Z_FLAG)) +// fatal("Z flag mismatch %02X %08X\n", opcode, fetchdat); ins++; insc++; - -/* if (times && ins == 9000000) output = 3; - if (CS == 0x1000 && pc == 0x1200) - fatal("Hit it\n");*/ -// if (!ins) ins2++; - +/*output = 3; + if (ins == 1372108) + fatal("here2\n"); + if (ins == 50966339) + fatal("here\n");*/ + if (timetolive) + { + timetolive--; + if (!timetolive) + fatal("Life expired\n"); + } +// if (ins == 97300000) output = 3; } - keybsenddelay -= cycdiff; + tsc += cycdiff; + +/* keybsenddelay -= cycdiff; if (keybsenddelay<1) { keybsenddelay = 1000; keyboard_at_poll(); - } + }*/ pit.c[0]-=cycdiff; pit.c[1]-=cycdiff; if (ppi.pb&1) pit.c[2]-=cycdiff; if ((pit.c[0]<1)||(pit.c[1]<1)||(pit.c[2]<1)) pit_poll(); - spktime-=cycdiff; - if (spktime<=0.0) - { - spktime+=SPKCONST; -// pclog("1Poll spk\n"); - pollspk(); - pollgussamp(); - getsbsamp(); - polladlib(); - getdacsamp(); -// pclog("2Poll spk\n"); - } - soundtime-=cycdiff; - if (soundtime<=0.0) - { - soundtime+=SOUNDCONST; -// pclog("1Poll sound60hz\n"); - pollsound60hz(); -// pclog("2Poll sound60hz\n"); - } - gustime-=cycdiff; - while (gustime<=0.0) - { - gustime+=GUSCONST; - pollgus(); - } - gustime2-=cycdiff; - while (gustime2<=0.0) - { - gustime2+=GUSCONST2; - pollgus2(); - } - vidtime-=cycdiff; - if (vidtime<=0.0) - { -// pclog("1Poll video\n"); - pollvideo(); -// pclog("2Poll video\n"); - } - if (disctime) - { - disctime-=(cycdiff); - if (disctime<=0) - { -// pclog("1Poll disc\n"); - disctime=0; - fdc_poll(); -// pclog("2Poll disc\n"); - } - } - if (mousedelay) - { - mousedelay-=20; - if (!mousedelay) - { -// pclog("1Poll mouse\n"); - mousecallback(); -// pclog("2Poll disc\n"); - } - } - if (sbenable) - { - sbcount-=cycdiff; - if (sbcount<0) - { - sbcount+=sblatcho; - pollsb(); - } - } - if (sb_enable_i) - { - sb_count_i-=cycdiff; - if (sb_count_i<0) - { - sb_count_i+=sblatchi; - sb_poll_i(); - } - } - if (idecallback[0]) - { - idecallback[0]--; - if (idecallback[0]<=0) - { -// pclog("IDE time over\n"); - idecallback[0]=0; - callbackide(0); - } - } - if (idecallback[1]) - { - idecallback[1]--; - if (idecallback[1]<=0) - { -// pclog("IDE time over\n"); - idecallback[1]=0; - callbackide(1); - } - } - rtctime-=cycdiff; - if (rtctime<0) - { - nvr_rtc(); - } + timer_clock(cycdiff); } } diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 8f48c1a..29b6448 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -3,20 +3,22 @@ CPP = g++.exe CC = gcc.exe WINDRES = windres.exe CFLAGS = -O3 -march=i686 -fomit-frame-pointer -OBJ = 286.o 386.o acer386sx.o adlib.o ali1429.o amstrad.o cdrom-ioctl.o cms.o \ - config.o cpu.o dac.o dma.o ega.o fdc.o gus.o harddisk.o \ - headland.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \ +OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \ + config.o cpu.o dac.o device.o dma.o ega.o fdc.o harddisk.o \ + headland.o i430vx.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_xt.o lpt.o mcr.o mem.o model.o \ mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \ - opti.o pc.o pci.o pic.o pit.o \ - ppi.o psg.o sblaster.o serial.o sound.o soundopenal.o um8881f.o \ - vid_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \ - vid_et4000w32i.o vid_hercules.o vid_icd2061.o vid_mda.o vid_olivetti_m24.o \ - vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o \ - vid_pc200.o vid_s3.o vid_sdac_ramdac.o vid_stg_ramdac.o \ - vid_svga.o vid_tandy.o vid_tkd8001_ramdac.o vid_tvga.o \ - vid_unk_ramdac.o video.o wd76c10.o win.o win-ddraw.o \ - win-keyboard.o win-mouse.o win-timer.o win-video.o x86.o \ + opti.o pc.o pci.o pic.o piix.o pit.o ppi.o serial.o sound.o sound_adlib.o \ + sound_adlibgold.o sound_cms.o sound_gus.o sound_opl.o sound_pas16.o sound_sb.o \ + sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_wss.o soundopenal.o timer.o \ + um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ + vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o \ + vid_et4000.o vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o \ + vid_ics2595.o vid_mda.o vid_olivetti_m24.o vid_oti067.o vid_paradise.o \ + vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o \ + vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_tandy.o vid_tkd8001_ramdac.o \ + vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o video.o wd76c10.o \ + win.o win-ddraw.o win-keyboard.o win-mouse.o win-timer.o win-video.o \ x86seg.o x87.o xtide.o pc.res FMOBJ = fmopl.o ymf262.o diff --git a/src/acer386sx.c b/src/acer386sx.c index 3e03ed7..77a7ef2 100644 --- a/src/acer386sx.c +++ b/src/acer386sx.c @@ -7,7 +7,7 @@ static int acer_index = 0; static uint8_t acer_regs[256]; -void acer386sx_write(uint16_t addr, uint8_t val) +void acer386sx_write(uint16_t addr, uint8_t val, void *priv) { if (addr & 1) acer_regs[acer_index] = val; @@ -15,7 +15,7 @@ void acer386sx_write(uint16_t addr, uint8_t val) acer_index = val; } -uint8_t acer386sx_read(uint16_t addr) +uint8_t acer386sx_read(uint16_t addr, void *priv) { if (addr & 1) { @@ -29,5 +29,5 @@ uint8_t acer386sx_read(uint16_t addr) void acer386sx_init() { - io_sethandler(0x0022, 0x0002, acer386sx_read, NULL, NULL, acer386sx_write, NULL, NULL); + io_sethandler(0x0022, 0x0002, acer386sx_read, NULL, NULL, acer386sx_write, NULL, NULL, NULL); } diff --git a/src/ali1429.c b/src/ali1429.c index 9cead39..2ced211 100644 --- a/src/ali1429.c +++ b/src/ali1429.c @@ -9,7 +9,7 @@ static int ali1429_index; static uint8_t ali1429_regs[256]; -void ali1429_write(uint16_t port, uint8_t val) +void ali1429_write(uint16_t port, uint8_t val, void *priv) { // return; if (!(port&1)) ali1429_index=val; @@ -31,9 +31,9 @@ void ali1429_write(uint16_t port, uint8_t val) { shadowbios=0; if (!shadowbios_write) - mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL ); + mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL, NULL); else - mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); flushmmucache(); } break; @@ -42,10 +42,10 @@ void ali1429_write(uint16_t port, uint8_t val) shadowbios_write=val&2; switch (val & 3) { - case 0: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL ); break; - case 1: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL ); break; - case 2: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); break; - case 3: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); break; + case 0: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL, NULL); break; + case 1: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL, NULL); break; + case 2: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); break; + case 3: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); break; } // if (val==0x43) shadowbios=1; @@ -56,7 +56,7 @@ void ali1429_write(uint16_t port, uint8_t val) } } -uint8_t ali1429_read(uint16_t port) +uint8_t ali1429_read(uint16_t port, void *priv) { if (!(port&1)) return ali1429_index; if ((ali1429_index >= 0xc0 || ali1429_index == 0x20) && cpu_iscyrix) @@ -72,5 +72,5 @@ void ali1429_reset() void ali1429_init() { - io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL); + io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, NULL); } diff --git a/src/amstrad.c b/src/amstrad.c index 2f5dee8..276706a 100644 --- a/src/amstrad.c +++ b/src/amstrad.c @@ -8,7 +8,7 @@ static uint8_t amstrad_dead; -uint8_t amstrad_read(uint16_t port) +uint8_t amstrad_read(uint16_t port, void *priv) { pclog("amstrad_read : %04X\n",port); switch (port) @@ -25,7 +25,7 @@ uint8_t amstrad_read(uint16_t port) return 0xff; } -void amstrad_write(uint16_t port, uint8_t val) +void amstrad_write(uint16_t port, uint8_t val, void *priv) { switch (port) { @@ -37,16 +37,15 @@ void amstrad_write(uint16_t port, uint8_t val) static uint8_t mousex,mousey; -void amstrad_mouse_write(uint16_t addr, uint8_t val) +void amstrad_mouse_write(uint16_t addr, uint8_t val, void *priv) { // pclog("Write mouse %04X %02X %04X:%04X\n", addr, val, CS, pc); if (addr==0x78) mousex=0; else mousey=0; } -uint8_t amstrad_mouse_read(uint16_t addr) +uint8_t amstrad_mouse_read(uint16_t addr, void *priv) { - uint8_t temp; // printf("Read mouse %04X %04X:%04X %02X\n", addr, CS, pc, (addr == 0x78) ? mousex : mousey); if (addr==0x78) return mousex; return mousey; @@ -73,12 +72,12 @@ void amstrad_mouse_poll(int x, int y, int b) void amstrad_init() { - lpt2_remove(); + lpt2_remove_ams(); - io_sethandler(0x0078, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL); - io_sethandler(0x007a, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL); - io_sethandler(0x0379, 0x0002, amstrad_read, NULL, NULL, NULL, NULL, NULL); - io_sethandler(0xdead, 0x0001, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL); + io_sethandler(0x0078, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL); + io_sethandler(0x007a, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL); + io_sethandler(0x0379, 0x0002, amstrad_read, NULL, NULL, NULL, NULL, NULL, NULL); + io_sethandler(0xdead, 0x0001, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, NULL); mouse_poll = amstrad_mouse_poll; } diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c index 59e8bb6..e60924d 100644 --- a/src/cdrom-ioctl.c +++ b/src/cdrom-ioctl.c @@ -44,7 +44,7 @@ void ioctl_audio_callback(int16_t *output, int len) { RAW_READ_INFO in; DWORD count; - int c; + // return; // pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount()); if (ioctl_cd_state != CD_PLAYING) @@ -143,7 +143,6 @@ static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf) static void ioctl_pause(void) { - long size; if (!cdrom_drive) return; if (ioctl_cd_state == CD_PLAYING) ioctl_cd_state = CD_PAUSED; @@ -154,7 +153,6 @@ static void ioctl_pause(void) static void ioctl_resume(void) { - long size; if (!cdrom_drive) return; if (ioctl_cd_state == CD_PAUSED) ioctl_cd_state = CD_PLAYING; @@ -165,7 +163,6 @@ static void ioctl_resume(void) static void ioctl_stop(void) { - long size; if (!cdrom_drive) return; ioctl_cd_state = CD_STOPPED; // ioctl_open(0); @@ -175,7 +172,6 @@ static void ioctl_stop(void) static void ioctl_seek(uint32_t pos) { - long size; if (!cdrom_drive) return; // ioctl_cd_state = CD_STOPPED; pclog("Seek %08X\n", pos); @@ -229,8 +225,7 @@ static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf) SUB_Q_CHANNEL_DATA sub; long size; int pos=0; - int c; - uint32_t temp, cdpos; + uint32_t cdpos; if (!cdrom_drive) return 0; insub.Format = IOCTL_CDROM_CURRENT_POSITION; ioctl_open(0); diff --git a/src/config.c b/src/config.c index bf2f86d..a0bb05d 100644 --- a/src/config.c +++ b/src/config.c @@ -26,7 +26,7 @@ int get_config_int(char *head, char *name, int def) if (!f) return def; - pclog("Searching for %s\n", name); +// pclog("Searching for %s\n", name); while (1) { @@ -46,9 +46,9 @@ int get_config_int(char *head, char *name, int def) if (!buffer[c]) continue; name2[d] = 0; - pclog("Comparing %s and %s\n", name, name2); +// pclog("Comparing %s and %s\n", name, name2); if (strcmp(name, name2)) continue; - pclog("Found!\n"); +// pclog("Found!\n"); while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c]) c++; @@ -56,7 +56,7 @@ int get_config_int(char *head, char *name, int def) if (!buffer[c]) continue; sscanf(&buffer[c], "%i", &res); - pclog("Reading value - %i\n", res); +// pclog("Reading value - %i\n", res); break; } @@ -78,7 +78,7 @@ char *get_config_string(char *head, char *name, char *def) if (!f) return config_return_string; - pclog("Searching for %s\n", name); +// pclog("Searching for %s\n", name); while (1) { @@ -98,9 +98,9 @@ char *get_config_string(char *head, char *name, char *def) if (!buffer[c]) continue; name2[d] = 0; - pclog("Comparing %s and %s\n", name, name2); +// pclog("Comparing %s and %s\n", name, name2); if (strcmp(name, name2)) continue; - pclog("Found!\n"); +// pclog("Found!\n"); while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c]) c++; @@ -110,11 +110,11 @@ char *get_config_string(char *head, char *name, char *def) strcpy(config_return_string, &buffer[c]); c = strlen(config_return_string) - 1; - pclog("string len %i\n", c); +// pclog("string len %i\n", c); while (config_return_string[c] <= 32 && config_return_string[c]) config_return_string[c--] = 0; - pclog("Reading value - %s\n", config_return_string); +// pclog("Reading value - %s\n", config_return_string); break; } @@ -125,19 +125,19 @@ char *get_config_string(char *head, char *name, char *def) void set_config_int(char *head, char *name, int val) { FILE *f = fopen(config_file, "at"); - if (!f) pclog("set_config_int - !f\n"); +// if (!f) pclog("set_config_int - !f\n"); fprintf(f, "%s = %i\n", name, val); - pclog("Write %s = %i\n", name, val); +// pclog("Write %s = %i\n", name, val); fclose(f); - pclog("fclose\n"); +// pclog("fclose\n"); } void set_config_string(char *head, char *name, char *val) { FILE *f = fopen(config_file, "at"); - if (!f) pclog("set_config_string - !f\n"); +// if (!f) pclog("set_config_string - !f\n"); fprintf(f, "%s = %s\n", name, val); - pclog("Write %s = %s\n", name, val); +// pclog("Write %s = %s\n", name, val); fclose(f); } diff --git a/src/config.h b/src/config.h index 4f681bd..1cc294e 100644 --- a/src/config.h +++ b/src/config.h @@ -3,3 +3,7 @@ int get_config_int(char *head, char *name, int def); char *get_config_string(char *head, char *name, char *def); void set_config_int(char *head, char *name, int val); void set_config_string(char *head, char *name, char *val); + +char *get_filename(char *s); +void append_filename(char *dest, char *s1, char *s2, int size); +void put_backslash(char *s); diff --git a/src/cpu.c b/src/cpu.c index 012ee01..9fd6103 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -2,6 +2,7 @@ #include "cpu.h" #include "model.h" #include "io.h" +#include "x86_ops.h" int cpu = 3, cpu_manufacturer = 0; CPU *cpu_s; @@ -9,6 +10,7 @@ int cpu_multi; int cpu_iscyrix; int cpu_16bitbus; int cpu_busspeed; +int cpu_hasrdtsc; int timing_rr; int timing_mr, timing_mrl; @@ -32,6 +34,9 @@ int timing_bt, timing_bnt; 12 = 133 MHz 13 = 150 MHz 14 = 160 MHz + 15 = 166 MHz + 16 = 180 MHz + 17 = 200 MHz */ CPU cpus_8088[] = @@ -197,6 +202,23 @@ CPU cpus_Cx486[] = {"", -1, 0, 0, 0} }; +CPU cpus_WinChip[] = +{ + /*IDT WinChip*/ + {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 0x540, 0x540, 0}, + {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 0x540, 0x540, 0}, + {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 0x540, 0x540, 0}, + {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 0x540, 0x540, 0}, + {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 0x540, 0x540, 0}, + {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 0x540, 0x540, 0}, + {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 0x540, 0x540, 0}, + {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 0x540, 0x540, 0}, + {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 0x540, 0x540, 0}, + {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 0x540, 0x540, 0}, + {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 0x540, 0x540, 0}, + {"", -1, 0, 0, 0} +}; + void cpu_set_edx() { EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset; @@ -216,17 +238,37 @@ void cpu_set() if (cpu_s->multi) cpu_busspeed = cpu_s->rspeed / cpu_s->multi; cpu_multi = cpu_s->multi; + cpu_hasrdtsc = 0; if (cpu_iscyrix) - io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL); + io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL); else - io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL); + io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL); pclog("hasfpu - %i\n",hasfpu); pclog("is486 - %i %i\n",is486,cpu_s->cpu_type); - + + x86_setopcodes(ops_386, ops_386_0f); + switch (cpu_s->cpu_type) { + case CPU_8088: + case CPU_8086: + break; + + case CPU_286: + x86_setopcodes(ops_286, ops_286_0f); + timing_rr = 2; /*register dest - register src*/ + timing_rm = 7; /*register dest - memory src*/ + timing_mr = 7; /*memory dest - register src*/ + timing_mm = 7; /*memory dest - memory src*/ + timing_rml = 9; /*register dest - memory src long*/ + timing_mrl = 11; /*memory dest - register src long*/ + timing_mml = 11; /*memory dest - memory src*/ + timing_bt = 7-3; /*branch taken*/ + timing_bnt = 3; /*branch not taken*/ + break; + case CPU_386SX: timing_rr = 2; /*register dest - register src*/ timing_rm = 6; /*register dest - memory src*/ @@ -326,6 +368,22 @@ void cpu_set() timing_bt = 5-1; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ break; + + case CPU_WINCHIP: + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 3-1; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + cpu_hasrdtsc = 1; + break; + + default: + fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type); } } @@ -354,6 +412,7 @@ void cpu_CPUID() case CPU_Am486SX: if (!EAX) { + EAX = 1; EBX = 0x68747541; ECX = 0x444D4163; EDX = 0x69746E65; @@ -370,6 +429,7 @@ void cpu_CPUID() case CPU_Am486DX: if (!EAX) { + EAX = 1; EBX = 0x68747541; ECX = 0x444D4163; EDX = 0x69746E65; @@ -383,19 +443,37 @@ void cpu_CPUID() else EAX = 0; break; + + case CPU_WINCHIP: + if (!EAX) + { + EAX = 1; + EBX = 0x746e6543; /*CentaurHauls*/ + ECX = 0x736c7561; + EDX = 0x48727561; + } + else if (EAX == 1) + { + EAX = CPUID; + EBX = ECX = 0; + EDX = 1; /*FPU*/ + } + else + EAX = 0; + break; } } static int cyrix_addr; -void cyrix_write(uint16_t addr, uint8_t val) +void cyrix_write(uint16_t addr, uint8_t val, void *priv) { if (!(addr & 1)) cyrix_addr = val; // else pclog("Write Cyrix %02X %02X\n",cyrix_addr,val); } -uint8_t cyrix_read(uint16_t addr) +uint8_t cyrix_read(uint16_t addr, void *priv) { if (addr & 1) { diff --git a/src/cpu.h b/src/cpu.h index 340928a..83757da 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -22,9 +22,13 @@ extern int cpu, cpu_manufacturer; #define CPU_Cx486DX 12 #define CPU_Cx5x86 13 +/*586 class CPUs*/ +#define CPU_WINCHIP 14 + #define MANU_INTEL 0 #define MANU_AMD 1 #define MANU_CYRIX 2 +#define MANU_IDT 3 extern int timing_rr; extern int timing_mr, timing_mrl; @@ -55,6 +59,7 @@ extern CPU cpus_486SDLC[]; extern CPU cpus_i486[]; extern CPU cpus_Am486[]; extern CPU cpus_Cx486[]; +extern CPU cpus_WinChip[]; extern CPU cpus_pc1512[]; extern CPU cpus_ibmat[]; @@ -65,7 +70,9 @@ extern int cpu_16bitbus; extern int cpu_busspeed; extern int cpu_multi; -void cyrix_write(uint16_t addr, uint8_t val); -uint8_t cyrix_read(uint16_t addr); +extern int cpu_hasrdtsc; + +void cyrix_write(uint16_t addr, uint8_t val, void *priv); +uint8_t cyrix_read(uint16_t addr, void *priv); extern int is8086; diff --git a/src/dma.c b/src/dma.c index e37c826..8e4dcb1 100644 --- a/src/dma.c +++ b/src/dma.c @@ -1,7 +1,9 @@ #include "ibm.h" -#include "video.h" -#include "io.h" + #include "dma.h" +#include "fdc.h" +#include "io.h" +#include "video.h" extern int ins; int output; @@ -38,10 +40,10 @@ void dma_reset() dma16.m=0; } -uint8_t dma_read(uint16_t addr) +uint8_t dma_read(uint16_t addr, void *priv) { uint8_t temp; -// printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc); +// printf("Read DMA %04X %04X:%04X %i %02X\n",addr,CS,pc, pic_intpending, pic.pend); switch (addr&0xF) { case 0: @@ -69,7 +71,8 @@ uint8_t dma_read(uint16_t addr) case 8: /*Status register*/ temp=dma.stat; dma.stat=0; - return temp|1; +// pclog("Read DMA status %02X\n", temp); + return temp; case 0xD: return 0; } @@ -77,9 +80,9 @@ uint8_t dma_read(uint16_t addr) return dmaregs[addr&0xF]; } -void dma_write(uint16_t addr, uint8_t val) +void dma_write(uint16_t addr, uint8_t val, void *priv) { -// printf("Write DMA %04X %02X %04X:%04X\n",addr,val,CS,pc); + printf("Write DMA %04X %02X %04X:%04X\n",addr,val,CS,pc); dmaregs[addr&0xF]=val; switch (addr&0xF) { @@ -122,7 +125,7 @@ void dma_write(uint16_t addr, uint8_t val) } } -uint8_t dma16_read(uint16_t addr) +uint8_t dma16_read(uint16_t addr, void *priv) { uint8_t temp; // printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc); @@ -154,12 +157,12 @@ uint8_t dma16_read(uint16_t addr) case 8: /*Status register*/ temp=dma16.stat; dma16.stat=0; - return temp|1; + return temp; } return dma16regs[addr&0xF]; } -void dma16_write(uint16_t addr, uint8_t val) +void dma16_write(uint16_t addr, uint8_t val, void *priv) { // printf("Write dma16 %04X %02X %04X:%04X\n",addr,val,CS,pc); addr>>=1; @@ -205,14 +208,14 @@ void dma16_write(uint16_t addr, uint8_t val) } uint8_t dmapages[16]; -static int primed = 0; -void dma_page_write(uint16_t addr, uint8_t val) + +void dma_page_write(uint16_t addr, uint8_t val, void *priv) { - if (!(addr&0xF)) - { -// printf("Write page %03X %02X %04X:%04X\n",addr,val,CS,pc); +/* if (!(addr&0xF)) + {*/ + pclog("Write page %03X %02X %04X:%04X\n",addr,val,CS,pc); // if (val==0x29 && pc==0xD25) output=1; - } +// } dmapages[addr&0xF]=val; switch (addr&0xF) { @@ -233,21 +236,21 @@ void dma_page_write(uint16_t addr, uint8_t val) // printf("Page write %04X %02X\n",addr,val); } -uint8_t dma_page_read(uint16_t addr) +uint8_t dma_page_read(uint16_t addr, void *priv) { return dmapages[addr&0xF]; } void dma_init() { - io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL); - io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL); + io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL, NULL); + io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } void dma16_init() { - io_sethandler(0x00C0, 0x0020, dma16_read, NULL, NULL, dma16_write, NULL, NULL); - io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL); + io_sethandler(0x00C0, 0x0020, dma16_read, NULL, NULL, dma16_write, NULL, NULL, NULL); + io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } @@ -256,11 +259,11 @@ uint8_t _dma_read(uint32_t addr) switch (addr&0xFFFF8000) { case 0xA0000: case 0xA8000: - return video_read_a000(addr); + return video_read_a000(addr, NULL); case 0xB0000: - return video_read_b000(addr); + return video_read_b000(addr, NULL); case 0xB8000: - return video_read_b800(addr); + return video_read_b800(addr, NULL); } if (isram[addr>>16]) return ram[addr]; return 0xff; @@ -271,19 +274,20 @@ void _dma_write(uint32_t addr, uint8_t val) switch (addr&0xFFFF8000) { case 0xA0000: case 0xA8000: - video_write_a000(addr,val); + video_write_a000(addr,val, NULL); return; case 0xB0000: - video_write_b000(addr,val); + video_write_b000(addr,val, NULL); return; case 0xB8000: - video_write_b800(addr,val); + video_write_b800(addr,val, NULL); return; case 0xC0000: case 0xC8000: case 0xD0000: case 0xD8000: case 0xE0000: case 0xE8000: case 0xF0000: case 0xF8000: return; } - if (isram[addr>>16]) ram[addr]=val; + if (isram[addr >> 16]) + ram[addr] = val; } /*void writedma2(uint8_t val) { @@ -301,10 +305,144 @@ void _dma_write(uint32_t addr, uint8_t val) } }*/ +int dma_channel_read(int channel) +{ + uint16_t temp; + + if (channel < 4) + { +// pclog("Read DMA channel %i\n", channel); + if (dma.m & (1 << channel)) + return DMA_NODATA; + if ((dma.mode[channel] & 0xC) != 8) + return DMA_NODATA; + temp = _dma_read(dma.ac[channel] + (dma.page[channel] << 16)); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]; +// pclog(" - %02X %05X\n", temp, dma.ac[channel] + (dma.page[channel] << 16)); + if (dma.mode[channel] & 0x20) dma.ac[channel]--; + else dma.ac[channel]++; + dma.cc[channel]--; + if (!dma.cc[channel] && (dma.mode[channel] & 0x10)) + { + dma.cc[channel] = dma.cb[channel] + 1; + dma.ac[channel] = dma.ab[channel]; + dma.stat |= (1 << channel); + } + else if (dma.cc[channel]<=-1) + { + dma.m |= (1 << channel); + dma.stat |= (1 << channel); + } + return temp; + } + else + { + channel &= 3; + if (dma16.m & (1 << channel)) + return DMA_NODATA; + if ((dma16.mode[channel] & 0xC) != 8) + return DMA_NODATA; + temp = _dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16)) | + (_dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1) << 8); + if (dma16.mode[channel] & 0x20) dma16.ac[channel]--; + else dma16.ac[channel]++; + dma16.cc[channel]--; + if (!dma16.cc[channel] && (dma16.mode[channel] & 0x10)) + { + dma16.cc[channel] = dma16.cb[channel] + 1; + dma16.ac[channel] = dma16.ab[channel]; + dma16.stat |= (1 << channel); + } + else if (dma16.cc[channel]<=-1) + { + dma16.m |= (1 << channel); + dma16.stat |= (1 << channel); + } + return temp; + } +} + +int dma_channel_write(int channel, uint16_t val) +{ + if (channel < 4) + { + if (dma.m & (1 << channel)) + return DMA_NODATA; + if ((dma.mode[channel] & 0xC) != 4) + return DMA_NODATA; + _dma_write(dma.ac[channel] + (dma.page[channel] << 16), val); + if (dma.mode[channel]&0x20) dma.ac[channel]--; + else dma.ac[channel]++; + dma.cc[channel]--; + if (!dma.cc[channel] && (dma.mode[channel] & 0x10)) + { + dma.cc[channel] = dma.cb[channel] + 1; + dma.ac[channel] = dma.ab[channel]; + dma.stat |= (1 << channel); + } + else if (dma.cc[channel]<=-1) + { + dma.m |= (1 << channel); + dma.stat |= (1 << channel); + } + } + else + { + channel &= 3; + if (dma16.m & (1 << channel)) + return DMA_NODATA; + if ((dma16.mode[channel] & 0xC) != 4) + return DMA_NODATA; + _dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16), val); + _dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1, val >> 8); + if (dma16.mode[channel]&0x20) dma16.ac[channel]--; + else dma16.ac[channel]++; + dma16.cc[channel]--; + if (!dma16.cc[channel] && (dma16.mode[channel] & 0x10)) + { + dma16.cc[channel] = dma16.cb[channel] + 1; + dma16.ac[channel] = dma16.ab[channel]; + dma16.stat |= (1 << channel); + } + else if (dma16.cc[channel] <= -1) + { + dma16.m |= (1 << channel); + dma16.stat |= (1 << channel); + } + } + return 0; +} + +extern int sbbufferpos; +int readdma1() +{ + uint8_t temp; + pclog("readdma1 : Read DMA1 %02X %02X %i\n",dma.m,dma.mode[1], dma.cc[1]); + if (dma.m & (1 << 1)) + return DMA_NODATA; + if ((dma.mode[1]&0xC)!=8) + return DMA_NODATA; + temp=_dma_read((dma.ac[1]+(dma.page[1]<<16))&rammask); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]; + pclog("readdma1 : DMA1 %02X %05X\n",temp,(dma.ac[1]+(dma.page[1]<<16))&rammask); + if (dma.mode[1]&0x20) dma.ac[1]--; + else dma.ac[1]++; + dma.cc[1]--; + if (!dma.cc[1] && (dma.mode[1]&0x10)) + { + dma.cc[1]=dma.cb[1]+1; + dma.ac[1]=dma.ab[1]; + dma.stat |= (1 << 1); + } + else if (dma.cc[1]<=-1) + { + dma.m |= (1 << 1); + dma.stat |= (1 << 1); + } + return temp; +} uint8_t readdma2() { uint8_t temp; -// pclog("Read DMA2 %02X %02X\n",dma.m,dma.mode[2]); +// pclog("Read DMA2 %02X %02X %i\n",dma.m,dma.mode[2], dma.cc[2]); if (dma.m&4) { fdc_abort(); @@ -324,12 +462,68 @@ uint8_t readdma2() { dma.cc[2]=dma.cb[2]+1; dma.ac[2]=dma.ab[2]; + dma.stat |= (1 << 2); } else if (dma.cc[2]<=-1) - dma.m|=4; + { + dma.m|=4; + dma.stat |= (1 << 2); + } + return temp; +} +int readdma3() +{ + uint8_t temp; +// pclog("Read DMA1 %02X %02X %i\n",dma.m,dma.mode[1], dma.cc[1]); + if (dma.m & (1 << 3)) + return DMA_NODATA; + if ((dma.mode[3]&0xC)!=8) + return DMA_NODATA; + temp=_dma_read((dma.ac[3]+(dma.page[3]<<16))&rammask); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]; + //pclog("DMA3 %02X %05X\n",temp,(dma.ac[3]+(dma.page[3]<<16))&rammask); + if (dma.mode[3]&0x20) dma.ac[3]--; + else dma.ac[3]++; + dma.cc[3]--; + if (!dma.cc[3] && (dma.mode[3]&0x10)) + { + dma.cc[3]=dma.cb[3]+1; + dma.ac[3]=dma.ab[3]; + dma.stat |= (1 << 3); + } + else if (dma.cc[3]<=-1) + { + dma.m |= (1 << 3); + dma.stat |= (1 << 3); + } return temp; } +void writedma1(uint8_t temp) +{ +// pclog("Write DMA1 %02X %02X %04X\n",dma.m,dma.mode[1],dma.cc[1]); + if (dma.m & (1 << 1)) + return; + if ((dma.mode[1] & 0xC) != 4) + return; +// pclog("Write %05X %05X %02X\n",(dma.ac[2]+(dma.page[2]<<16)),rammask,temp); +// ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]=temp; + _dma_write((dma.ac[1]+(dma.page[1]<<16))&rammask,temp); + if (dma.mode[1]&0x20) dma.ac[1]--; + else dma.ac[1]++; + dma.cc[1]--; + if (!dma.cc[1] && (dma.mode[1]&0x10)) + { + dma.cc[1]=dma.cb[1]+1; + dma.ac[1]=dma.ab[1]; + dma.stat |= (1 << 1); + } + else if (dma.cc[1]<=-1) + { +// pclog("Reached TC\n"); + dma.m |= (1 << 1); + dma.stat |= (1 << 1); + } +} void writedma2(uint8_t temp) { // pclog("Write DMA2 %02X %02X %04X\n",dma.m,dma.mode[2],dma.cc[2]); @@ -353,35 +547,41 @@ void writedma2(uint8_t temp) { dma.cc[2]=dma.cb[2]+1; dma.ac[2]=dma.ab[2]; + dma.stat |= (1 << 2); } else if (dma.cc[2]<=-1) { // pclog("Reached TC\n"); fdc_abort(); dma.m|=4; + dma.stat |= (1 << 2); } } - -uint8_t readdma1() +void writedma3(uint8_t temp) { - uint8_t temp=0; - /*if ((dma.ac[1]+(dma.page[1]<<16))<0x800000) */temp=ram[(dma.ac[1]+(dma.page[1]<<16))&rammask]; -// printf("Read DMA1 from %05X %02X %04X %02X %i\n",dma.ac[1]+(dma.page[1]<<16),dma.mode[1],dma.cc[1],temp,dmaon[1]); - if (!dmaon[1]) +// pclog("Write DMA3 %02X %02X %04X\n",dma.m,dma.mode[3],dma.cc[3]); + if (dma.m & (1 << 3)) + return; + if ((dma.mode[3] & 0xC) != 4) + return; +// pclog("Write %05X %05X %02X\n",(dma.ac[2]+(dma.page[2]<<16)),rammask,temp); +// ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]=temp; + _dma_write((dma.ac[3]+(dma.page[3]<<16))&rammask,temp); + if (dma.mode[3]&0x20) dma.ac[3]--; + else dma.ac[3]++; + dma.cc[3]--; + if (!dma.cc[3] && (dma.mode[3]&0x10)) { -// printf("DMA off!\n"); - return temp; + dma.cc[3]=dma.cb[3]+1; + dma.ac[3]=dma.ab[3]; + dma.stat |= (1 << 3); } - dma.ac[1]++; - dma.cc[1]--; - if (dma.cc[1]<=-1 && (dma.mode[1]&0x10)) + else if (dma.cc[3]<=-1) { - dma.cc[1]=dma.cb[1]; - dma.ac[1]=dma.ab[1]; +// pclog("Reached TC\n"); + dma.m |= (1 << 3); + dma.stat |= (1 << 3); } - else if (dma.cc[1]<=-1) - dmaon[1]=0; - return temp; } uint16_t readdma5() @@ -402,26 +602,16 @@ uint16_t readdma5() { dma16.cc[1]=dma16.cb[1]; dma16.ac[1]=dma16.ab[1]; + dma16.stat |= (1 << 1); } else if (dma16.cc[1]<=-1) - dma16on[1]=0; + { + dma16on[1]=0; + dma16.stat |= (1 << 1); + } return temp; } -void writedma1(uint8_t temp) -{ - if (!dmaon[1]) return; - ram[(dma.ac[1]+(dma.page[1]<<16))&rammask]=temp; - dma.ac[1]++; - dma.cc[1]--; - if (!dma.cc[1] && (dma.mode[1]&0x10)) - { - dma.cc[1]=dma.cb[1]+1; - dma.ac[1]=dma.ab[1]; - } - else if (dma.cc[1]<=-1) - dmaon[1]=0; -} void writedma5(uint16_t temp) { if (!dma16on[1]) return; @@ -434,31 +624,15 @@ void writedma5(uint16_t temp) { dma16.cc[1]=dma16.cb[1]; dma16.ac[1]=dma16.ab[1]; + dma16.stat |= (1 << 1); } else if (dma16.cc[1]<=-1) - dma16on[1]=0; + { + dma16on[1]=0; + dma16.stat |= (1 << 1); + } } -int readdma3() -{ - uint8_t temp=ram[((dma.page[3]<<16)+dma.ac[3])&rammask]; - if (dma.m&8) - { - return -1; - } -// printf("Read DMA 3 - %02X %05X %i\n",temp,(dma.page[3]<<16)+dma.ac[3],dma.cc[3]); - if (!(dma.m&8)) - { - dma.ac[3]++; - dma.cc[3]--; - if (dma.cc[3]==-1) - { - dma.m|=8; - dma.stat|=8; - } - } - return temp; -} void readdma0() { if (AT) ppi.pb^=0x10; @@ -474,9 +648,9 @@ void readdma0() dma.cc[0]--; if (dma.cc[0]==-1) { - dma.stat|=1; dma.ac[0]=dma.ab[0]; dma.cc[0]=dma.cb[0]; + dma.stat |= 1; } // } // ppi.pb^=0x10; diff --git a/src/dma.h b/src/dma.h index e8209d7..8f9acf0 100644 --- a/src/dma.h +++ b/src/dma.h @@ -1,3 +1,15 @@ void dma_init(); void dma16_init(); void dma_reset(); + +#define DMA_NODATA -1 + +void readdma0(); +int readdma1(); +uint8_t readdma2(); +int readdma3(); + +void writedma2(uint8_t temp); + +int dma_channel_read(int channel); +int dma_channel_write(int channel, uint16_t val); diff --git a/src/ega.c b/src/ega.c index e7c22d0..a87bc21 100644 --- a/src/ega.c +++ b/src/ega.c @@ -16,7 +16,6 @@ uint8_t svga3d8; uint8_t oldvram=0; int frames; -int incga=1; int hsync; uint8_t cgastat; @@ -36,7 +35,7 @@ uint8_t *vram; int egares; -uint8_t seqregs[32]; +uint8_t seqregs[64]; int seqaddr; uint8_t oak_regs[32]; @@ -54,7 +53,8 @@ int palchange=1; int fullchange; -float dispontime,dispofftime,disptime; +int dispontime,dispofftime; +double disptime; int ega_vtotal,ega_dispend,ega_vsyncstart,ega_split,ega_hdisp,ega_rowoffset; int vidclock; @@ -135,8 +135,6 @@ void initega() } } crtc[0xC]=crtc[0xD]=0; - if (romset==ROM_PC1640 || romset==ROM_PC1512) incga=1; - else incga=0; for (c=0;c<4;c++) { for (d=0;d<4;d++) @@ -277,6 +275,7 @@ int ega_getdepth() if (TRIDENT || ET4000W32) return bpp; return 8; } + return 0; } int ega_getx() diff --git a/src/fdc.c b/src/fdc.c index 907856c..ba86f6d 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -2,6 +2,11 @@ #include #include "ibm.h" +#include "dma.h" +#include "io.h" +#include "pic.h" +#include "timer.h" + void fdc_poll(); int timetolive; int TRACKS[2] = {80, 80}; @@ -105,9 +110,8 @@ void fdc_reset() } int ins; -void fdc_write(uint16_t addr, uint8_t val) +void fdc_write(uint16_t addr, uint8_t val, void *priv) { - int c; // printf("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate); switch (addr&7) { @@ -122,7 +126,9 @@ void fdc_write(uint16_t addr, uint8_t val) } if ((val&4) && !(fdc.dor&4)) { - disctime=128; + timer_process(); + disctime = 128 * (1 << TIMER_SHIFT); + timer_update_outstanding(); discint=-1; fdc_reset(); } @@ -132,7 +138,9 @@ void fdc_write(uint16_t addr, uint8_t val) case 4: if (val & 0x80) { - disctime=128; + timer_process(); + disctime = 128 * (1 << TIMER_SHIFT); + timer_update_outstanding(); discint=-1; fdc_reset(); } @@ -247,7 +255,9 @@ void fdc_write(uint16_t addr, uint8_t val) // exit(-1); fdc.stat=0x10; discint=0xfc; - disctime=200; + timer_process(); + disctime = 200 * (1 << TIMER_SHIFT); + timer_update_outstanding(); break; } } @@ -259,7 +269,8 @@ void fdc_write(uint16_t addr, uint8_t val) // pclog("Got all params\n"); fdc.stat=0x30; discint=fdc.command&0x1F; - disctime=1024; + timer_process(); + disctime = 1024 * (1 << TIMER_SHIFT); fdc.drive=fdc.params[0]&1; if (discint==2 || discint==5 || discint==6) { @@ -285,13 +296,13 @@ void fdc_write(uint16_t addr, uint8_t val) { // pclog("Wrong rate %i %i\n",fdc.rate,discrate[fdc.drive]); discint=0xFF; - disctime=1024; + disctime = 1024 * (1 << TIMER_SHIFT); } if (driveempty[fdc.drive]) { // pclog("Drive empty\n"); discint=0xFE; - disctime=1024; + disctime = 1024 * (1 << TIMER_SHIFT); } } if (discint == 7 || discint == 0xf) @@ -303,6 +314,7 @@ void fdc_write(uint16_t addr, uint8_t val) { fdc.head = (fdc.params[0] & 4) ? 1 : 0; } + timer_update_outstanding(); // if (discint==5) fdc.pos=512; } } @@ -320,7 +332,7 @@ void fdc_write(uint16_t addr, uint8_t val) } int paramstogo=0; -uint8_t fdc_read(uint16_t addr) +uint8_t fdc_read(uint16_t addr, void *priv) { uint8_t temp; // /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,ins); @@ -360,7 +372,12 @@ uint8_t fdc_read(uint16_t addr) lastbyte=0; temp=fdc.dat; } - if (discint==0xA) disctime=1024; + if (discint==0xA) + { + timer_process(); + disctime = 1024 * (1 << TIMER_SHIFT); + timer_update_outstanding(); + } fdc.stat &= 0xf0; break; case 7: /*Disk change*/ @@ -395,6 +412,7 @@ static int fdc_reset_stat = 0; void fdc_poll() { int temp; + disctime = 0; // pclog("fdc_poll %08X %i %02X\n", discint, fdc.drive, fdc.st0); switch (discint) { @@ -420,7 +438,9 @@ void fdc_poll() fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]; // pclog("Read %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat); writedma2(fdc.dat); - disctime=60; + timer_process(); + disctime = 60 * (1 << TIMER_SHIFT); + timer_update_outstanding(); } else { @@ -437,17 +457,6 @@ void fdc_poll() fdc.res[9]=fdc.params[4]; paramstogo=7; return; - disctime=1024; - picint(0x40); - fdc.stat=0xD0; - switch (fdc.pos-512) - { - case 0: case 1: case 2: fdc.dat=0; break; - case 3: fdc.dat=fdc.track[fdc.drive]; break; - case 4: fdc.dat=fdc.head; break; - case 5: fdc.dat=fdc.sector; break; - case 6: fdc.dat=fdc.params[4]; discint=-2; lastbyte=1; break; - } } fdc.pos++; if (fdc.pos==512 && fdc.params[5]!=1) @@ -491,14 +500,18 @@ void fdc_poll() { fdc_abort_f=0; discint=0xFD; - disctime=50; + timer_process(); + disctime = 50 * (1 << TIMER_SHIFT); + timer_update_outstanding(); return; } else { fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]=temp; // printf("Write data %i %i %02X %i:%i:%i:%i\n",fdc.sector-1,fdc.pos,fdc.dat,fdc.head,fdc.track[fdc.drive],fdc.sector-1,fdc.pos); - disctime=60; + timer_process(); + disctime = 60 * (1 << TIMER_SHIFT); + timer_update_outstanding(); } } else @@ -517,19 +530,6 @@ void fdc_poll() fdc.res[10]=fdc.params[4]; paramstogo=7; return; - disctime=1024; - picint(0x40); - fdc.stat=0xD0; - switch (fdc.pos-512) - { - case 0: fdc.dat=0x40; break; - case 1: fdc.dat=2; break; - case 2: fdc.dat=0; break; - case 3: fdc.dat=fdc.track[fdc.drive]; break; - case 4: fdc.dat=fdc.head; break; - case 5: fdc.dat=fdc.sector; break; - case 6: fdc.dat=fdc.params[4]; discint=-2; break; - } } fdc.pos++; if (fdc.pos==512 && fdc.sector!=fdc.params[5]) @@ -548,7 +548,9 @@ void fdc_poll() fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]; // printf("Read disc %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat); writedma2(fdc.dat); - disctime=60; + timer_process(); + disctime = 60 * (1 << TIMER_SHIFT); + timer_update_outstanding(); } else { @@ -579,12 +581,12 @@ void fdc_poll() fdc.pos++; if (fdc.pos==512)// && fdc.sector!=fdc.params[5]) { -// printf("Sector complete! %02X\n",fdc.params[5]); +// pclog("Sector complete! %02X\n",fdc.params[5]); fdc.pos=0; fdc.sector++; if (fdc.sector > fdc.params[5]) { -// printf("Overrunnit!\n"); +// pclog("Overrunnit! %02X\n", fdc.command & 0x80); // dumpregs(); // exit(-1); fdc.sector=1; @@ -617,7 +619,9 @@ void fdc_poll() if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0; fdc.st0=0x20|fdc.drive|(fdc.head?4:0); discint=-3; - disctime=2048; + timer_process(); + disctime = 2048 * (1 << TIMER_SHIFT); + timer_update_outstanding(); // printf("Recalibrate complete!\n"); fdc.stat = 0x80 | (1 << fdc.drive); return; @@ -663,7 +667,9 @@ void fdc_poll() // printf("Seeked to track %i %i\n",fdc.track[fdc.drive], fdc.drive); fdc.st0=0x20|fdc.drive|(fdc.head?4:0); discint=-3; - disctime=2048; + timer_process(); + disctime = 2048 * (1 << TIMER_SHIFT); + timer_update_outstanding(); fdc.stat = 0x80 | (1 << fdc.drive); // pclog("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0); return; @@ -792,15 +798,19 @@ void fdc_poll() // exit(-1); } - void fdc_init() { - io_sethandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL); - io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL); + timer_add(fdc_poll, &disctime, &disctime, NULL); +} + +void fdc_add() +{ + io_sethandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); + io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); } void fdc_remove() { - io_removehandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL); - io_removehandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL); + io_removehandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); + io_removehandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); } diff --git a/src/fdc.h b/src/fdc.h index 9d2592f..4458155 100644 --- a/src/fdc.h +++ b/src/fdc.h @@ -1,4 +1,6 @@ void fdc_init(); +void fdc_add(); void fdc_remove(); void fdc_reset(); void fdc_poll(); +void fdc_abort(); diff --git a/src/headland.c b/src/headland.c index 5e68b5d..c7e9312 100644 --- a/src/headland.c +++ b/src/headland.c @@ -8,7 +8,7 @@ static int headland_index; static uint8_t headland_regs[256]; -void headland_write(uint16_t addr, uint8_t val) +void headland_write(uint16_t addr, uint8_t val, void *priv) { if (addr & 1) { @@ -20,15 +20,15 @@ void headland_write(uint16_t addr, uint8_t val) shadowbios = val & 0x10; shadowbios_write = !(val & 0x10); if (shadowbios) - mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL ); + mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL , NULL); else - mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); } } else headland_index = val; } -uint8_t headland_read(uint16_t addr) +uint8_t headland_read(uint16_t addr, void *priv) { if (addr & 1) { @@ -41,5 +41,5 @@ uint8_t headland_read(uint16_t addr) void headland_init() { - io_sethandler(0x0022, 0x0002, headland_read, NULL, NULL, headland_write, NULL, NULL); + io_sethandler(0x0022, 0x0002, headland_read, NULL, NULL, headland_write, NULL, NULL, NULL); } diff --git a/src/ibm.h b/src/ibm.h index 5917f13..889ddd7 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -1,5 +1,6 @@ #include #include +#include #define printf pclog /*Memory*/ @@ -291,9 +292,8 @@ int driveempty[2]; #define PCI (romset == ROM_PCI486) #define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486) -int FASTDISC; -int ADLIB; -int GAMEBLASTER; + +int GAMEBLASTER, GUS; enum { @@ -320,7 +320,8 @@ enum ROM_AMI386, ROM_AMI486, ROM_WIN486, - ROM_PCI486 + ROM_PCI486, + ROM_430VX }; //#define ROM_IBMPCJR 5 /*Not working! ROMs are corrupt*/ @@ -337,10 +338,18 @@ int romset; //#define GFX_OTI067 3 /*Using BIOS from Acer 386SX/25N - edit - only works with Acer BIOS! Stupid integrated systems*/ #define GFX_TVGA 4 /*Using Trident 8900D BIOS*/ #define GFX_ET4000 5 /*Tseng ET4000*/ -#define GFX_ET4000W32 6 /*Tseng ET4000/W32p (Diamond Stealth 32)*/ -#define GFX_BAHAMAS64 7 /*S3 Vision864 (Paradise Bahamas 64)*/ -#define GFX_N9_9FX 8 /*S3 764/Trio64 (Number Nine 9FX)*/ -#define GFX_STEALTH64 9 /*S3 Vision964 (Diamond Stealth 64 VRAM PCI)*/ +#define GFX_ET4000W32 6 /*Tseng ET4000/W32p (Diamond Stealth 32)*/ +#define GFX_BAHAMAS64 7 /*S3 Vision864 (Paradise Bahamas 64)*/ +#define GFX_N9_9FX 8 /*S3 764/Trio64 (Number Nine 9FX)*/ +#define GFX_STEALTH64 9 /*S3 Vision964 (Diamond Stealth 64 VRAM PCI)*/ +#define GFX_VIRGE 10 /*S3 Virge*/ +#define GFX_TGUI9440 11 /*Trident TGUI9440*/ +#define GFX_VGA 12 /*IBM VGA*/ +#define GFX_VGAEDGE16 13 /*ATI VGA Edge-16 (18800-1)*/ +#define GFX_VGACHARGER 14 /*ATI VGA Charger (28800-5)*/ +#define GFX_OTI067 15 /*Oak OTI-067*/ +#define GFX_MACH64GX 16 /*ATI Graphics Pro Turbo (Mach64)*/ +#define GFX_CL_GD5429 17 /*Cirrus Logic CL-GD5429*/ int gfxcard; @@ -354,7 +363,6 @@ int readflash; uint8_t hercctrl; int slowega,egacycles,egacycles2; extern uint8_t gdcreg[16]; -extern int incga; extern int egareads,egawrites; extern int cga_comp; extern int vid_resize; @@ -383,13 +391,10 @@ extern int mousedelay; /*Sound*/ uint8_t spkstat; -float spktime,soundtime,gustime,gustime2,vidtime,rtctime; +float spktime; +int rtctime; +int soundtime,gustime,gustime2,vidtime; int ppispeakon; -//#define SPKCONST (8000000.0/44100.0) -float SPKCONST; -float SOUNDCONST; -float CASCONST; -float GUSCONST,GUSCONST2; float CGACONST; float MDACONST; float VGACONST1,VGACONST2; @@ -400,38 +405,23 @@ int gated,speakval,speakon; /*Sound Blaster*/ -int sbenable,sblatchi,sblatcho,sbcount,sb_enable_i,sb_count_i; -int16_t sbdat; +/*int sbenable,sblatchi,sblatcho,sbcount,sb_enable_i,sb_count_i; +int16_t sbdat;*/ void setsbclock(float clock); -#define SADLIB 1 /*No DSP*/ -#define SB1 2 /*DSP v1.05*/ -#define SB15 3 /*DSP v2.00*/ -#define SB2 4 /*DSP v2.01 - needed for high-speed DMA*/ -#define SBPRO 5 /*DSP v3.00*/ -#define SBPRO2 6 /*DSP v3.02 + OPL3*/ -#define SB16 7 /*DSP v4.05 + OPL3*/ +#define SADLIB 1 /*No DSP*/ +#define SB1 2 /*DSP v1.05*/ +#define SB15 3 /*DSP v2.00*/ +#define SB2 4 /*DSP v2.01 - needed for high-speed DMA*/ +#define SBPRO 5 /*DSP v3.00*/ +#define SBPRO2 6 /*DSP v3.02 + OPL3*/ +#define SB16 7 /*DSP v4.05 + OPL3*/ +#define SADGOLD 8 /*AdLib Gold*/ +#define SND_WSS 9 /*Windows Sound System*/ +#define SND_PAS16 10 /*Pro Audio Spectrum 16*/ + int sbtype; -struct -{ - int vocl,vocr,voc; - int midl,midr,mid; - int masl,masr,mas; -} sbpmixer; -extern int sb_freq; - -struct -{ - int master_l,master_r; - int voice_l,voice_r; - int fm_l,fm_r; - int bass_l,bass_r; - int treble_l,treble_r; - int filter; -} mixer; - - int clocks[3][12][4]; int at70hz; @@ -466,3 +456,5 @@ extern int times; extern float isa_timing, bus_timing; + +extern int frame; diff --git a/src/ide.c b/src/ide.c index 46c6dee..40549d4 100644 --- a/src/ide.c +++ b/src/ide.c @@ -2,7 +2,7 @@ IDE emulation*/ //#define RPCEMU_IDE -#define IDE_TIME 5 +#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE @@ -20,6 +20,9 @@ #include "arm.h" #else #include "ibm.h" + #include "io.h" + #include "pic.h" + #include "timer.h" #endif #include "ide.h" @@ -50,6 +53,11 @@ #define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */ #define WIN_PACKETCMD 0xA0 /* Send a packet command. */ #define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */ +#define WIN_READ_MULTIPLE 0xC4 +#define WIN_WRITE_MULTIPLE 0xC5 +#define WIN_SET_MULTIPLE_MODE 0xC6 +#define WIN_READ_DMA 0xC8 +#define WIN_WRITE_DMA 0xCA #define WIN_SETIDLE1 0xE3 #define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */ @@ -134,6 +142,7 @@ typedef struct IDE int lba; uint32_t lba_addr; int skip512; + int blocksize, blockcount; } IDE; IDE ide_drives[4]; @@ -142,6 +151,10 @@ IDE *ext_ide; char ide_fn[2][512]; +int (*ide_bus_master_read_sector)(int channel, uint8_t *data); +int (*ide_bus_master_write_sector)(int channel, uint8_t *data); +void (*ide_bus_master_set_irq)(int channel); + static void callreadcd(IDE *ide); static void atapicommand(int ide_board); @@ -272,8 +285,15 @@ static void ide_identify(IDE *ide) #else ide_padstr((char *) (ide->buffer + 27), "PCemHD", 40); /* Model */ #endif - ide->buffer[49] = (1<<9); /* LBA supported */ + ide->buffer[20] = 3; /*Buffer type*/ + ide->buffer[21] = 512; /*Buffer size*/ + ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/ + ide->buffer[48] = 1; /*Dword transfers supported*/ + ide->buffer[49] = (1 << 9) | (1 << 8); /* LBA and DMA supported */ ide->buffer[50] = 0x4000; /* Capabilities */ + ide->buffer[51] = 2 << 8; /*PIO timing mode*/ + ide->buffer[52] = 2 << 8; /*DMA timing mode*/ + ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; #ifdef RPCEMU_IDE ide->buffer[60] = (65535 * 16 * 63) & 0xFFFF; /* Total addressable sectors (LBA) */ ide->buffer[61] = (65535 * 16 * 63) >> 16; @@ -281,6 +301,8 @@ static void ide_identify(IDE *ide) ide->buffer[60] = (hdc[cur_ide[0]].tracks * hdc[cur_ide[0]].hpc * hdc[cur_ide[0]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */ ide->buffer[61] = (hdc[cur_ide[0]].tracks * hdc[cur_ide[0]].hpc * hdc[cur_ide[0]].spt) >> 16; #endif + ide->buffer[63] = 7; /*Multiword DMA*/ + ide->buffer[80] = 0xe; /*ATA-1 to ATA-3 supported*/ } /** @@ -571,7 +593,9 @@ void writeidew(int ide_board, uint16_t val) if (ide->pos>=(ide->packlen+2)) { ide->packetstatus=5; + timer_process(); idecallback[ide_board]=6*IDE_TIME; + timer_update_outstanding(); // pclog("Packet over!\n"); ide_irq_lower(ide); } @@ -583,8 +607,10 @@ void writeidew(int ide_board, uint16_t val) ide->pos=0; ide->atastat = BUSY_STAT; ide->packetstatus=1; - idecallback[ide_board]=6*IDE_TIME; +/* idecallback[ide_board]=6*IDE_TIME;*/ + timer_process(); callbackide(ide_board); + timer_update_outstanding(); // idecallback[ide_board]=60*IDE_TIME; // if ((ide->buffer[0]&0xFF)==0x43) idecallback[ide_board]=1*IDE_TIME; // pclog("Packet now waiting!\n"); @@ -598,15 +624,25 @@ void writeidew(int ide_board, uint16_t val) { ide->pos=0; ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; -// callbackide(ide_board); + timer_process(); + if (ide->command == WIN_WRITE_MULTIPLE) + callbackide(ide_board); + else + idecallback[ide_board]=6*IDE_TIME; + timer_update_outstanding(); } } +void writeidel(int ide_board, uint32_t val) +{ +// pclog("WriteIDEl %08X\n", val); + writeidew(ide_board, val); + writeidew(ide_board, val >> 16); +} + void writeide(int ide_board, uint16_t addr, uint8_t val) { IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint8_t *idebufferb = (uint8_t *) ide->buffer; #ifndef RPCEMU_IDE /* if (ide_board && (cr0&1) && !(eflags&VM_FLAG)) { @@ -614,6 +650,8 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; }*/ #endif +// if ((cr0&1) && !(eflags&VM_FLAG)) +// pclog("WriteIDE %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, pc); // return; addr|=0x80; // if (ide_board) pclog("Write IDEb %04X %02X %04X(%08X):%04X %i %02X %02X\n",addr,val,CS,cs,pc,ins,ide->atastat,ide_drives[0].atastat); @@ -660,9 +698,26 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) dumpregs(); exit(-1); }*/ - cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1); - ide = &ide_drives[cur_ide[ide_board]]; - + + if (cur_ide[ide_board] != ((val>>4)&1)+(ide_board<<1)) + { + cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1); + + if (ide->reset) + { + ide->atastat = READY_STAT | DSC_STAT; + ide->error=1; + ide->secount=1; + ide->sector=1; + ide->head=0; + ide->cylinder=0; + ide->reset = 0; + return; + } + + ide = &ide_drives[cur_ide[ide_board]]; + } + ide->head=val&0xF; ide->lba=val&0x40; @@ -684,17 +739,32 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SRST: /* ATAPI Device Reset */ if (IDE_DRIVE_IS_CDROM(ide)) ide->atastat = BUSY_STAT; else ide->atastat = READY_STAT; + timer_process(); idecallback[ide_board]=100*IDE_TIME; + timer_update_outstanding(); return; case WIN_RESTORE: case WIN_SEEK: +// pclog("WIN_RESTORE start\n"); ide->atastat = READY_STAT; + timer_process(); idecallback[ide_board]=100*IDE_TIME; + timer_update_outstanding(); return; + case WIN_READ_MULTIPLE: + if (!ide->blocksize) + fatal("READ_MULTIPLE - blocksize = 0\n"); +#if 0 + if (ide->lba) pclog("Read Multiple %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); + else pclog("Read Multiple %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins); +#endif + ide->blockcount = 0; + case WIN_READ: case WIN_READ_NORETRY: + case WIN_READ_DMA: /* if (ide.secount>1) { fatal("Read %i sectors from sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head); @@ -704,12 +774,23 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) else pclog("Read %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins); #endif ide->atastat = BUSY_STAT; + timer_process(); idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); return; - + + case WIN_WRITE_MULTIPLE: + if (!ide->blocksize) + fatal("Write_MULTIPLE - blocksize = 0\n"); +#if 0 + if (ide->lba) pclog("Write Multiple %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); + else pclog("Write Multiple %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); +#endif + ide->blockcount = 0; + case WIN_WRITE: - case WIN_WRITE_NORETRY: -/* if (ide.secount>1) + case WIN_WRITE_NORETRY: + /* if (ide.secount>1) { fatal("Write %i sectors to sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head); }*/ @@ -721,13 +802,26 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->pos=0; return; + case WIN_WRITE_DMA: +#if 0 + if (ide->lba) pclog("Write %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); + else pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); +#endif + ide->atastat = BUSY_STAT; + timer_process(); + idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); + return; + case WIN_VERIFY: #if 0 if (ide->lba) pclog("Read verify %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); else pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); #endif ide->atastat = BUSY_STAT; + timer_process(); idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); return; case WIN_FORMAT: @@ -739,17 +833,22 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SPECIFY: /* Initialize Drive Parameters */ ide->atastat = BUSY_STAT; + timer_process(); idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); // pclog("SPECIFY\n"); // output=1; return; case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ case WIN_PIDENTIFY: /* Identify Packet Device */ + case WIN_SET_MULTIPLE_MODE: /*Set Multiple Mode*/ // output=1; case WIN_SETIDLE1: /* Idle */ ide->atastat = BUSY_STAT; + timer_process(); idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); return; case WIN_IDENTIFY: /* Identify Device */ @@ -757,13 +856,17 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) // output=3; // timetolive=500; ide->atastat = BUSY_STAT; + timer_process(); idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); return; case WIN_PACKETCMD: /* ATAPI Packet */ ide->packetstatus=0; ide->atastat = BUSY_STAT; + timer_process(); idecallback[ide_board]=1;//30*IDE_TIME; + timer_update_outstanding(); ide->pos=0; return; @@ -772,15 +875,18 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; ide->error = ABRT_ERR; ide_irq_raise(ide); +/* fatal("Bad IDE command %02X\n", val);*/ return; } -// fatal("Bad IDE command %02X\n", val); + return; case 0x3F6: /* Device control */ if ((ide->fdisk&4) && !(val&4) && (ide->type != IDE_NONE)) { + timer_process(); idecallback[ide_board]=500*IDE_TIME; + timer_update_outstanding(); ide->reset = 1; ide->atastat = BUSY_STAT; // pclog("IDE Reset\n"); @@ -795,7 +901,6 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) uint8_t readide(int ide_board, uint16_t addr) { IDE *ide = &ide_drives[cur_ide[ide_board]]; - const uint8_t *idebufferb = (const uint8_t *) ide->buffer; uint8_t temp; uint16_t tempw; @@ -807,6 +912,8 @@ uint8_t readide(int ide_board, uint16_t addr) return 0xFF; }*/ #endif +// if ((cr0&1) && !(eflags&VM_FLAG)) +// pclog("ReadIDE %04X from %04X(%08X):%08X\n", addr, CS, cs, pc); // return 0xFF; if (ide->type == IDE_NONE && addr != 0x1f6) return 0xff; @@ -866,7 +973,7 @@ uint8_t readide(int ide_board, uint16_t addr) else { // && ide->service) return ide.atastat[ide.board]|SERVICE_STAT; -// pclog("Return status %02X\n",ide->atastat); +// pclog("Return status %02X %04X:%04X %02X %02X\n",ide->atastat, CS ,pc, AH, BH); temp = ide->atastat; } break; @@ -910,7 +1017,7 @@ uint16_t readidew(int ide_board) }*/ #endif // return 0xFFFF; -// pclog("Read IDEw %04X %04X:%04X %02X %i\n",ide->buffer[ide->pos >> 1],CS,pc,opcode,ins); +// pclog("Read IDEw %04X %04X:%04X %02X %i %i\n",ide->buffer[ide->pos >> 1],CS,pc,opcode,ins, ide->pos); //if (idedebug) pclog("Read IDEW %08X\n",PC); @@ -921,7 +1028,7 @@ uint16_t readidew(int ide_board) ide->pos+=2; if ((ide->pos>=512 && ide->command != WIN_PACKETCMD) || (ide->command == WIN_PACKETCMD && ide->pos>=ide->packlen)) { -// pclog("Over! packlen %i %i\n",ide.packlen,ide.pos); +// pclog("Over! packlen %i %i\n",ide->packlen,ide->pos); ide->pos=0; if (ide->command == WIN_PACKETCMD)// && ide.packetstatus==6) { @@ -932,16 +1039,24 @@ uint16_t readidew(int ide_board) { ide->atastat = READY_STAT | DSC_STAT; ide->packetstatus=0; - if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY) + if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE) { ide->secount--; if (ide->secount) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; + timer_process(); + if (ide->command == WIN_READ_MULTIPLE) + callbackide(ide_board); + else + idecallback[ide_board]=6*IDE_TIME; + timer_update_outstanding(); +// pclog("set idecallback\n"); // callbackide(ide_board); } +// else +// pclog("readidew done %02X\n", ide->atastat); } } } @@ -949,6 +1064,12 @@ uint16_t readidew(int ide_board) return temp; } +uint32_t readidel(int ide_board) +{ + uint16_t temp = readidew(ide_board); + return temp | (readidew(ide_board) << 16); +} + int times30=0; void callbackide(int ide_board) { @@ -972,6 +1093,7 @@ void callbackide(int ide_board) ide->head=0; ide->cylinder=0; ide->reset = 0; + ide->blocksize = 0; // pclog("Reset callback\n"); return; } @@ -996,9 +1118,10 @@ void callbackide(int ide_board) case WIN_RESTORE: case WIN_SEEK: if (IDE_DRIVE_IS_CDROM(ide)) { + pclog("WIN_RESTORE callback on CD-ROM\n"); goto abort_cmd; } -// pclog("Restore callback\n"); +// pclog("WIN_RESTORE callback\n"); ide->atastat = READY_STAT | DSC_STAT; ide_irq_raise(ide); return; @@ -1026,6 +1149,66 @@ void callbackide(int ide_board) #endif return; + case WIN_READ_DMA: + if (IDE_DRIVE_IS_CDROM(ide)) { + goto abort_cmd; + } + addr = ide_get_sector(ide) * 512; + fseeko64(ide->hdfile, addr, SEEK_SET); + fread(ide->buffer, 512, 1, ide->hdfile); + ide->pos=0; + + if (ide_bus_master_read_sector) + { + if (ide_bus_master_read_sector(ide_board, (uint8_t *)ide->buffer)) + idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + else + { + /*DMA successful*/ + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + + ide->secount--; + if (ide->secount) + { + ide_next_sector(ide); + ide->atastat = BUSY_STAT; + idecallback[ide_board]=6*IDE_TIME; + } + else + { + ide_irq_raise(ide); + ide_bus_master_set_irq(ide_board); + } + } + } +#ifndef RPCEMU_IDE + readflash=1; +#endif + return; + + case WIN_READ_MULTIPLE: + if (IDE_DRIVE_IS_CDROM(ide)) { + goto abort_cmd; + } + addr = ide_get_sector(ide) * 512; +// pclog("Read multiple from %08X %i (%i) %i\n", addr, ide->blockcount, ide->blocksize, ide->secount); + fseeko64(ide->hdfile, addr, SEEK_SET); + fread(ide->buffer, 512, 1, ide->hdfile); + ide->pos=0; + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + if (!ide->blockcount)// || ide->secount == 1) + { +// pclog("Read multiple int\n"); + ide_irq_raise(ide); + } + ide->blockcount++; + if (ide->blockcount >= ide->blocksize) + ide->blockcount = 0; +#ifndef RPCEMU_IDE + readflash=1; +#endif + return; + case WIN_WRITE: case WIN_WRITE_NORETRY: if (IDE_DRIVE_IS_CDROM(ide)) { @@ -1049,6 +1232,71 @@ void callbackide(int ide_board) readflash=1; #endif return; + + case WIN_WRITE_DMA: + if (IDE_DRIVE_IS_CDROM(ide)) { + goto abort_cmd; + } + + if (ide_bus_master_write_sector) + { + if (ide_bus_master_write_sector(ide_board, (uint8_t *)ide->buffer)) + idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + else + { + /*DMA successful*/ + addr = ide_get_sector(ide) * 512; + fseeko64(ide->hdfile, addr, SEEK_SET); + fwrite(ide->buffer, 512, 1, ide->hdfile); + + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + + ide->secount--; + if (ide->secount) + { + ide_next_sector(ide); + ide->atastat = BUSY_STAT; + idecallback[ide_board]=6*IDE_TIME; + } + else + { + ide_irq_raise(ide); + ide_bus_master_set_irq(ide_board); + } + } + } +#ifndef RPCEMU_IDE + readflash=1; +#endif + return; + + case WIN_WRITE_MULTIPLE: + if (IDE_DRIVE_IS_CDROM(ide)) { + goto abort_cmd; + } + addr = ide_get_sector(ide) * 512; +// pclog("Write sector callback %i %i %i offset %08X %i left %i\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt); + fseeko64(ide->hdfile, addr, SEEK_SET); + fwrite(ide->buffer, 512, 1, ide->hdfile); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize || ide->secount == 1) + { + ide->blockcount = 0; + ide_irq_raise(ide); + } + ide->secount--; + if (ide->secount) + { + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + ide->pos=0; + ide_next_sector(ide); + } + else + ide->atastat = READY_STAT | DSC_STAT; +#ifndef RPCEMU_IDE + readflash=1; +#endif + return; case WIN_VERIFY: if (IDE_DRIVE_IS_CDROM(ide)) { @@ -1117,6 +1365,21 @@ void callbackide(int ide_board) // pclog("Not ATAPI\n"); goto abort_cmd; + case WIN_SET_MULTIPLE_MODE: + if (IDE_DRIVE_IS_CDROM(ide)) { +#ifndef RPCEMU_IDE + pclog("IS CDROM - ABORT\n"); +#endif + goto abort_cmd; + } + ide->blocksize = ide->secount; + ide->atastat = READY_STAT | DSC_STAT; +#ifndef RPCEMU_IDE + pclog("Set multiple mode - %i\n", ide->blocksize); +#endif + ide_irq_raise(ide); + return; + case WIN_SETIDLE1: /* Idle */ case 0xEF: goto abort_cmd; @@ -1207,6 +1470,18 @@ abort_cmd: ide_irq_raise(ide); } +void ide_callback_pri() +{ + idecallback[0] = 0; + callbackide(0); +} + +void ide_callback_sec() +{ + idecallback[1] = 0; + callbackide(1); +} + /*ATAPI CD-ROM emulation This mostly seems to work. It is implemented only on Windows at the moment as I haven't had time to implement any interfaces for it in the generic gui. @@ -1714,44 +1989,93 @@ static void callreadcd(IDE *ide) -void ide_write_pri(uint16_t addr, uint8_t val) +void ide_write_pri(uint16_t addr, uint8_t val, void *priv) { writeide(0, addr, val); } -void ide_write_pri_w(uint16_t addr, uint16_t val) +void ide_write_pri_w(uint16_t addr, uint16_t val, void *priv) { writeidew(0, val); } -uint8_t ide_read_pri(uint16_t addr) +void ide_write_pri_l(uint16_t addr, uint32_t val, void *priv) +{ + writeidel(0, val); +} +uint8_t ide_read_pri(uint16_t addr, void *priv) { return readide(0, addr); } -uint16_t ide_read_pri_w(uint16_t addr) +uint16_t ide_read_pri_w(uint16_t addr, void *priv) { return readidew(0); } +uint32_t ide_read_pri_l(uint16_t addr, void *priv) +{ + return readidel(0); +} -void ide_write_sec(uint16_t addr, uint8_t val) +void ide_write_sec(uint16_t addr, uint8_t val, void *priv) { writeide(1, addr, val); } -void ide_write_sec_w(uint16_t addr, uint16_t val) +void ide_write_sec_w(uint16_t addr, uint16_t val, void *priv) { writeidew(1, val); } -uint8_t ide_read_sec(uint16_t addr) +void ide_write_sec_l(uint16_t addr, uint32_t val, void *priv) +{ + writeidel(1, val); +} +uint8_t ide_read_sec(uint16_t addr, void *priv) { return readide(1, addr); } -uint16_t ide_read_sec_w(uint16_t addr) +uint16_t ide_read_sec_w(uint16_t addr, void *priv) { return readidew(1); } +uint32_t ide_read_sec_l(uint16_t addr, void *priv) +{ + return readidel(1); +} + +void ide_pri_enable() +{ + io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); + io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); +} + +void ide_pri_disable() +{ + io_removehandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); + io_removehandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); +} + +void ide_sec_enable() +{ + io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); + io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); +} + +void ide_sec_disable() +{ + io_removehandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); + io_removehandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); +} void ide_init() { - io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, NULL, ide_write_pri, ide_write_pri_w, NULL); - io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL); - io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, NULL, ide_write_sec, ide_write_sec_w, NULL); - io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL); + ide_pri_enable(); + ide_sec_enable(); + ide_bus_master_read_sector = ide_bus_master_write_sector = NULL; + + timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL); + timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL); +} + +void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), int (*write_sector)(int channel, uint8_t *data), void (*set_irq)(int channel)) +{ + ide_bus_master_read_sector = read_sector; + ide_bus_master_write_sector = write_sector; + ide_bus_master_set_irq = set_irq; } diff --git a/src/ide.h b/src/ide.h index a1f47a6..7311aa9 100644 --- a/src/ide.h +++ b/src/ide.h @@ -10,6 +10,11 @@ extern uint16_t readidew(int ide_board); extern void callbackide(int ide_board); extern void resetide(void); extern void ide_init(); +extern void ide_pri_enable(); +extern void ide_sec_enable(); +extern void ide_pri_disable(); +extern void ide_sec_disable(); +extern void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), int (*write_sector)(int channel, uint8_t *data), void (*set_irq)(int channel)); /*ATAPI stuff*/ typedef struct ATAPI diff --git a/src/io.c b/src/io.c index 14fa12d..fe5e818 100644 --- a/src/io.c +++ b/src/io.c @@ -1,89 +1,112 @@ #include "ibm.h" #include "ide.h" +#include "io.h" #include "video.h" #include "cpu.h" -uint8_t (*port_inb[0x10000][2])(uint16_t addr); -uint16_t (*port_inw[0x10000][2])(uint16_t addr); -uint32_t (*port_inl[0x10000][2])(uint16_t addr); +uint8_t (*port_inb[0x10000][2])(uint16_t addr, void *priv); +uint16_t (*port_inw[0x10000][2])(uint16_t addr, void *priv); +uint32_t (*port_inl[0x10000][2])(uint16_t addr, void *priv); -void (*port_outb[0x10000][2])(uint16_t addr, uint8_t val); -void (*port_outw[0x10000][2])(uint16_t addr, uint16_t val); -void (*port_outl[0x10000][2])(uint16_t addr, uint32_t val); +void (*port_outb[0x10000][2])(uint16_t addr, uint8_t val, void *priv); +void (*port_outw[0x10000][2])(uint16_t addr, uint16_t val, void *priv); +void (*port_outl[0x10000][2])(uint16_t addr, uint32_t val, void *priv); + +void *port_priv[0x10000][2]; void io_init() { int c; + pclog("io_init\n"); for (c = 0; c < 0x10000; c++) { port_inb[c][0] = port_inw[c][0] = port_inl[c][0] = NULL; port_outb[c][0] = port_outw[c][0] = port_outl[c][0] = NULL; port_inb[c][1] = port_inw[c][1] = port_inl[c][1] = NULL; port_outb[c][1] = port_outw[c][1] = port_outl[c][1] = NULL; + port_priv[c][0] = port_priv[c][1] = NULL; } } void io_sethandler(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr), - uint16_t (*inw)(uint16_t addr), - uint32_t (*inl)(uint16_t addr), - void (*outb)(uint16_t addr, uint8_t val), - void (*outw)(uint16_t addr, uint16_t val), - void (*outl)(uint16_t addr, uint32_t val)) + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) { int c; for (c = 0; c < size; c++) { - if (!port_inb[ base + c][0]) port_inb[ base + c][0] = inb; - else if (!port_inb[ base + c][1]) port_inb[ base + c][1] = inb; - if (!port_inw[ base + c][0]) port_inw[ base + c][0] = inw; - else if (!port_inw[ base + c][1]) port_inw[ base + c][1] = inw; - if (!port_inl[ base + c][0]) port_inl[ base + c][0] = inl; - else if (!port_inl[ base + c][1]) port_inl[ base + c][1] = inl; - if (!port_outb[base + c][0]) port_outb[base + c][0] = outb; - else if (!port_outb[base + c][1]) port_outb[base + c][1] = outb; - if (!port_outw[base + c][0]) port_outw[base + c][0] = outw; - else if (!port_outw[base + c][1]) port_outw[base + c][1] = outw; - if (!port_outl[base + c][0]) port_outl[base + c][0] = outl; - else if (!port_outl[base + c][1]) port_outl[base + c][1] = outl; + if (!port_inb[ base + c][0] && !port_inw[ base + c][0] && !port_inl[ base + c][0] && + !port_outb[base + c][0] && !port_outw[base + c][0] && !port_outl[base + c][0]) + { + port_inb[ base + c][0] = inb; + port_inw[ base + c][0] = inw; + port_inl[ base + c][0] = inl; + port_outb[base + c][0] = outb; + port_outw[base + c][0] = outw; + port_outl[base + c][0] = outl; + port_priv[base + c][0] = priv; + } + else if (!port_inb[ base + c][1] && !port_inw[ base + c][1] && !port_inl[ base + c][1] && + !port_outb[base + c][1] && !port_outw[base + c][1] && !port_outl[base + c][1]) + { + port_inb[ base + c][1] = inb; + port_inw[ base + c][1] = inw; + port_inl[ base + c][1] = inl; + port_outb[base + c][1] = outb; + port_outw[base + c][1] = outw; + port_outl[base + c][1] = outl; + port_priv[base + c][1] = priv; + } } } void io_removehandler(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr), - uint16_t (*inw)(uint16_t addr), - uint32_t (*inl)(uint16_t addr), - void (*outb)(uint16_t addr, uint8_t val), - void (*outw)(uint16_t addr, uint16_t val), - void (*outl)(uint16_t addr, uint32_t val)) + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) { int c; for (c = 0; c < size; c++) { - if (port_inb[ base + c][0] == inb) - port_inb[ base + c][0] = NULL; - if (port_inb[ base + c][1] == inb) - port_inb[ base + c][1] = NULL; - if (port_inw[ base + c][0] == inw) - port_inw[ base + c][0] = NULL; - if (port_inw[ base + c][1] == inw) - port_inw[ base + c][1] = NULL; - if (port_inl[ base + c][0] == inl) - port_inl[ base + c][0] = NULL; - if (port_inl[ base + c][1] == inl) - port_inl[ base + c][1] = NULL; - if (port_outb[ base + c][0] == outb) - port_outb[ base + c][0] = NULL; - if (port_outb[ base + c][1] == outb) - port_outb[ base + c][1] = NULL; - if (port_outw[ base + c][0] == outw) - port_outw[ base + c][0] = NULL; - if (port_outw[ base + c][1] == outw) - port_outw[ base + c][1] = NULL; - if (port_outl[ base + c][0] == outl) - port_outl[ base + c][0] = NULL; - if (port_outl[ base + c][1] == outl) - port_outl[ base + c][1] = NULL; + if (port_priv[base + c][0] == priv) + { + if (port_inb[ base + c][0] == inb) + port_inb[ base + c][0] = NULL; + if (port_inw[ base + c][0] == inw) + port_inw[ base + c][0] = NULL; + if (port_inl[ base + c][0] == inl) + port_inl[ base + c][0] = NULL; + if (port_outb[ base + c][0] == outb) + port_outb[ base + c][0] = NULL; + if (port_outw[ base + c][0] == outw) + port_outw[ base + c][0] = NULL; + if (port_outl[ base + c][0] == outl) + port_outl[ base + c][0] = NULL; + } + if (port_priv[base + c][1] == priv) + { + if (port_inb[ base + c][1] == inb) + port_inb[ base + c][1] = NULL; + if (port_inw[ base + c][1] == inw) + port_inw[ base + c][1] = NULL; + if (port_inl[ base + c][1] == inl) + port_inl[ base + c][1] = NULL; + if (port_outb[ base + c][1] == outb) + port_outb[ base + c][1] = NULL; + if (port_outw[ base + c][1] == outw) + port_outw[ base + c][1] = NULL; + if (port_outl[ base + c][1] == outl) + port_outl[ base + c][1] = NULL; + } } } @@ -95,63 +118,39 @@ int t237=0; uint8_t inb(uint16_t port) { uint8_t temp = 0xff; - int tempi; - if (port_inb[port][0]) - temp &= port_inb[port][0](port); - if (port_inb[port][1]) - temp &= port_inb[port][1](port); - return temp; - - if (port&0x80) sw9=2; -// if ((port&0x3F0)==0x3D0) printf("Video access read %03X %04X:%04X\n",port,cs>>4,pc); -// if (cs<0xF0000 || cs>0x100000) printf("IN %04X %04X(%06X):%08X\n",port,CS,cs,pc); -// /*if (output==3) */printf("IN %04X %04X:%04X\n",port,CS,pc); -// if (port == 0x23) pclog("IN %04X %04X:%08X\n", port, CS, pc); - switch (port) - { - case 0x220: case 0x221: case 0x222: case 0x223: /*Gameblaster*/ - if (sbtype>=SBPRO) return readsb(port); - if (GAMEBLASTER) return readcms(port); - return 0xFF; - } -// printf("Bad IN port %04X %04X:%04X\n",port,cs>>4,pc); - return 0xff; - /*dumpregs(); - exit(-1);*/ -} -/*uint8_t inb(uint16_t port) -{ - uint8_t temp = _inb(port); -// if (port != 0x61) pclog("IN %04X %02X %04X(%08X):%08X %f %04X %i %i\n", port, temp, CS, cs, pc, pit.c[1], CX, keybsenddelay, GetTickCount()); + if (port_inb[port][0]) + temp &= port_inb[port][0](port, port_priv[port][0]); + if (port_inb[port][1]) + temp &= port_inb[port][1](port, port_priv[port][1]); + +/* if (!port_inb[port][0] && !port_inb[port][1]) + pclog("Bad INB %04X %04X:%04X\n", port, CS, pc);*/ + return temp; -}*/ +} uint8_t cpu_readport(uint32_t port) { return inb(port); } void outb(uint16_t port, uint8_t val) { -// /*if (output==3) */printf("OUT %04X %02X %04X(%08X):%08X %i %i\n", port, val, CS, cs, pc, ins, GetTickCount()); if (port_outb[port][0]) - port_outb[port][0](port, val); + port_outb[port][0](port, val, port_priv[port][0]); if (port_outb[port][1]) - port_outb[port][1](port, val); + port_outb[port][1](port, val, port_priv[port][1]); + +/* if (!port_outb[port][0] && !port_outb[port][1]) + pclog("Bad OUTB %04X %02X %04X:%08X\n", port, val, CS, pc);*/ return; - switch (port) - { - case 0x220: case 0x221: case 0x222: case 0x223: /*Gameblaster*/ - if (GAMEBLASTER) writecms(port,val); - return; - } - pclog("OUT %04X %02X %04X:%08X\n",port,val,CS,pc); } uint16_t inw(uint16_t port) { +// pclog("INW %04X\n", port); if (port_inw[port][0]) - return port_inw[port][0](port); + return port_inw[port][0](port, port_priv[port][0]); if (port_inw[port][1]) - return port_inw[port][1](port); + return port_inw[port][1](port, port_priv[port][1]); return inb(port) | (inb(port + 1) << 8); } @@ -159,10 +158,13 @@ uint16_t inw(uint16_t port) void outw(uint16_t port, uint16_t val) { // printf("OUTW %04X %04X %04X:%08X\n",port,val, CS, pc); +/* if ((port & ~0xf) == 0xf000) + pclog("OUTW %04X %04X\n", port, val);*/ + if (port_outw[port][0]) - port_outw[port][0](port, val); + port_outw[port][0](port, val, port_priv[port][0]); if (port_outw[port][1]) - port_outw[port][1](port, val); + port_outw[port][1](port, val, port_priv[port][1]); if (port_outw[port][0] || port_outw[port][1]) return; @@ -173,20 +175,24 @@ void outw(uint16_t port, uint16_t val) uint32_t inl(uint16_t port) { +// pclog("INL %04X\n", port); if (port_inl[port][0]) - return port_inl[port][0](port); + return port_inl[port][0](port, port_priv[port][0]); if (port_inl[port][1]) - return port_inl[port][1](port); + return port_inl[port][1](port, port_priv[port][1]); return inw(port) | (inw(port + 2) << 16); } void outl(uint16_t port, uint32_t val) { +/* if ((port & ~0xf) == 0xf000) + pclog("OUTL %04X %08X\n", port, val);*/ + if (port_outl[port][0]) - port_outl[port][0](port, val); + port_outl[port][0](port, val, port_priv[port][0]); if (port_outl[port][1]) - port_outl[port][1](port, val); + port_outl[port][1](port, val, port_priv[port][1]); if (port_outl[port][0] || port_outl[port][1]) return; diff --git a/src/io.h b/src/io.h index 3697cd5..c7d9ea0 100644 --- a/src/io.h +++ b/src/io.h @@ -1,17 +1,19 @@ void io_init(); void io_sethandler(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr), - uint16_t (*inw)(uint16_t addr), - uint32_t (*inl)(uint16_t addr), - void (*outb)(uint16_t addr, uint8_t val), - void (*outw)(uint16_t addr, uint16_t val), - void (*outl)(uint16_t addr, uint32_t val)); + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); void io_removehandler(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr), - uint16_t (*inw)(uint16_t addr), - uint32_t (*inl)(uint16_t addr), - void (*outb)(uint16_t addr, uint8_t val), - void (*outw)(uint16_t addr, uint16_t val), - void (*outl)(uint16_t addr, uint32_t val)); + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); diff --git a/src/jim.c b/src/jim.c index 43a1b60..672278a 100644 --- a/src/jim.c +++ b/src/jim.c @@ -1,6 +1,7 @@ #include #include #include "ibm.h" +#include "io.h" uint8_t europcdat[16]; struct @@ -10,7 +11,7 @@ struct int addr; } europc_rtc; -void writejim(uint16_t addr, uint8_t val) +void writejim(uint16_t addr, uint8_t val, void *p) { if ((addr&0xFF0)==0x250) europcdat[addr&0xF]=val; switch (addr) @@ -38,7 +39,7 @@ void writejim(uint16_t addr, uint8_t val) // printf("Write JIM %04X %02X\n",addr,val); } -uint8_t readjim(uint16_t addr) +uint8_t readjim(uint16_t addr, void *p) { // printf("Read JIM %04X\n",addr); switch (addr) @@ -74,5 +75,5 @@ void jim_init() else viddat=0x10; europc_rtc.dat[0xB]=viddat; europc_rtc.dat[0xD]=viddat; /*Checksum*/ - io_sethandler(0x250, 0x10, readjim, NULL, NULL, writejim, NULL, NULL); + io_sethandler(0x250, 0x10, readjim, NULL, NULL, writejim, NULL, NULL, NULL); } diff --git a/src/keyboard.c b/src/keyboard.c index cb830b0..0b689d6 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -248,7 +248,7 @@ void keyboard_process() continue; if (!key[c] && scancodes[c].scancodes_break[0] == -1) continue; - pclog("Key %02X start\n", c); +// pclog("Key %02X start\n", c); d = 0; if (key[c]) { diff --git a/src/keyboard_amstrad.c b/src/keyboard_amstrad.c index 4bdea88..903de83 100644 --- a/src/keyboard_amstrad.c +++ b/src/keyboard_amstrad.c @@ -1,6 +1,7 @@ #include "ibm.h" #include "io.h" #include "mem.h" +#include "pic.h" #include "sound.h" #include "keyboard.h" @@ -53,7 +54,7 @@ void keyboard_amstrad_adddata(uint8_t val) return; } -void keyboard_amstrad_write(uint16_t port, uint8_t val) +void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv) { pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, keyboard_amstrad.pb); /* if (ram[8] == 0xc3) @@ -102,7 +103,7 @@ void keyboard_amstrad_write(uint16_t port, uint8_t val) } } -uint8_t keyboard_amstrad_read(uint16_t port) +uint8_t keyboard_amstrad_read(uint16_t port, void *priv) { uint8_t temp; // pclog("keyboard_amstrad : read %04X ", port); @@ -161,7 +162,7 @@ void keyboard_amstrad_init() { //return; pclog("keyboard_amstrad_init\n"); - io_sethandler(0x0060, 0x0006, keyboard_amstrad_read, NULL, NULL, keyboard_amstrad_write, NULL, NULL); + io_sethandler(0x0060, 0x0006, keyboard_amstrad_read, NULL, NULL, keyboard_amstrad_write, NULL, NULL, NULL); keyboard_amstrad_reset(); keyboard_send = keyboard_amstrad_adddata; keyboard_poll = keyboard_amstrad_poll; diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 02dfd78..1115909 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -1,7 +1,9 @@ #include "ibm.h" #include "io.h" #include "mem.h" +#include "pic.h" #include "sound.h" +#include "timer.h" #include "keyboard.h" #include "keyboard_at.h" @@ -44,22 +46,23 @@ int mouse_queue_start = 0, mouse_queue_end = 0; void keyboard_at_poll() { + keybsenddelay += (1000 * TIMER_USEC); if (keyboard_at.wantirq) { keyboard_at.wantirq = 0; picint(2); - pclog("keyboard_at : take IRQ\n"); +// pclog("keyboard_at : take IRQ\n"); } else if (keyboard_at.wantirq12) { keyboard_at.wantirq12 = 0; picint(0x1000); - pclog("keyboard_at : take IRQ 12\n"); +// pclog("keyboard_at : take IRQ 12\n"); } if (!(keyboard_at.status & STAT_OFULL) && !(keyboard_at.mem[0] & 0x10) && mouse_queue_start != mouse_queue_end) { - pclog("Reading %02X from the mouse queue at %i\n", keyboard_at.out, key_queue_start); +// pclog("Reading %02X from the mouse queue at %i\n", keyboard_at.out, key_queue_start); keyboard_at.out = mouse_queue[mouse_queue_start]; mouse_queue_start = (mouse_queue_start + 1) & 0xf; keyboard_at.status |= STAT_OFULL | STAT_MFULL; @@ -70,7 +73,7 @@ void keyboard_at_poll() else if (!(keyboard_at.status & STAT_OFULL) && !(keyboard_at.mem[0] & 0x10) && key_queue_start != key_queue_end) { - pclog("Reading %02X from the key queue at %i\n", keyboard_at.out, key_queue_start); +// pclog("Reading %02X from the key queue at %i\n", keyboard_at.out, key_queue_start); keyboard_at.out = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; keyboard_at.status |= STAT_OFULL; @@ -81,7 +84,7 @@ void keyboard_at_poll() else if (!(keyboard_at.status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { - pclog("Reading %02X from the key ctrl_queue at %i\n", keyboard_at.out, key_ctrl_queue_start); +// pclog("Reading %02X from the key ctrl_queue at %i\n", keyboard_at.out, key_ctrl_queue_start); keyboard_at.out = key_ctrl_queue[key_ctrl_queue_start]; key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; keyboard_at.status |= STAT_OFULL; @@ -97,7 +100,7 @@ void keyboard_at_adddata(uint8_t val) // { key_ctrl_queue[key_ctrl_queue_end] = val; key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; - pclog("keyboard_at : %02X added to queue\n", val); +// pclog("keyboard_at : %02X added to queue\n", val); /* return; } keyboard_at.out = val; @@ -110,9 +113,15 @@ void keyboard_at_adddata(uint8_t val) void keyboard_at_adddata_keyboard(uint8_t val) { +/* if (val == 0x1c) + { + key_1c++; + if (key_1c == 4) + output = 3; + }*/ key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; - pclog("keyboard_at : %02X added to key queue\n", val); +// pclog("keyboard_at : %02X added to key queue\n", val); return; } @@ -120,13 +129,13 @@ void keyboard_at_adddata_mouse(uint8_t val) { mouse_queue[mouse_queue_end] = val; mouse_queue_end = (mouse_queue_end + 1) & 0xf; - pclog("keyboard_at : %02X added to mouse queue\n", val); +// pclog("keyboard_at : %02X added to mouse queue\n", val); return; } -void keyboard_at_write(uint16_t port, uint8_t val) +void keyboard_at_write(uint16_t port, uint8_t val, void *priv) { - pclog("keyboard_at : write %04X %02X %i %02X\n", port, val, keyboard_at.key_wantdata, ram[8]); +// pclog("keyboard_at : write %04X %02X %i %02X\n", port, val, keyboard_at.key_wantdata, ram[8]); /* if (ram[8] == 0xc3) { output = 3; @@ -165,7 +174,7 @@ void keyboard_at_write(uint16_t port, uint8_t val) break; case 0xd1: /*Write output port*/ - pclog("Write output port - %02X %02X %04X:%04X\n", keyboard_at.output_port, val, CS, pc); +// pclog("Write output port - %02X %02X %04X:%04X\n", keyboard_at.output_port, val, CS, pc); if ((keyboard_at.output_port ^ val) & 0x02) /*A20 enable change*/ { mem_a20_key = val & 0x02; @@ -384,7 +393,7 @@ void keyboard_at_write(uint16_t port, uint8_t val) } } -uint8_t keyboard_at_read(uint16_t port) +uint8_t keyboard_at_read(uint16_t port, void *priv) { uint8_t temp = 0xff; cycles -= 4; @@ -428,9 +437,11 @@ void keyboard_at_reset() void keyboard_at_init() { //return; - io_sethandler(0x0060, 0x0005, keyboard_at_read, NULL, NULL, keyboard_at_write, NULL, NULL); + io_sethandler(0x0060, 0x0005, keyboard_at_read, NULL, NULL, keyboard_at_write, NULL, NULL, NULL); keyboard_at_reset(); keyboard_send = keyboard_at_adddata_keyboard; keyboard_poll = keyboard_at_poll; mouse_write = NULL; + + timer_add(keyboard_at_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); } diff --git a/src/keyboard_olim24.c b/src/keyboard_olim24.c index 1072402..da42395 100644 --- a/src/keyboard_olim24.c +++ b/src/keyboard_olim24.c @@ -2,6 +2,7 @@ #include "io.h" #include "mem.h" #include "mouse.h" +#include "pic.h" #include "keyboard.h" #include "keyboard_olim24.h" @@ -63,7 +64,7 @@ void keyboard_olim24_adddata(uint8_t val) return; } -void keyboard_olim24_write(uint16_t port, uint8_t val) +void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv) { pclog("keyboard_olim24 : write %04X %02X\n", port, val); /* if (ram[8] == 0xc3) @@ -138,7 +139,7 @@ void keyboard_olim24_write(uint16_t port, uint8_t val) } } -uint8_t keyboard_olim24_read(uint16_t port) +uint8_t keyboard_olim24_read(uint16_t port, void *priv) { uint8_t temp; // pclog("keyboard_olim24 : read %04X ", port); @@ -276,8 +277,8 @@ void mouse_olim24_poll(int x, int y, int b) void keyboard_olim24_init() { //return; - io_sethandler(0x0060, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL); - io_sethandler(0x0064, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL); + io_sethandler(0x0060, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL, NULL); + io_sethandler(0x0064, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL, NULL); keyboard_olim24_reset(); keyboard_send = keyboard_olim24_adddata; keyboard_poll = keyboard_olim24_poll; diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index 1cc04a9..a098098 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -1,7 +1,9 @@ #include "ibm.h" #include "io.h" #include "mem.h" +#include "pic.h" #include "sound.h" +#include "timer.h" #include "keyboard.h" #include "keyboard_xt.h" @@ -28,6 +30,7 @@ static int key_queue_start = 0, key_queue_end = 0; void keyboard_xt_poll() { + keybsenddelay += (1000 * TIMER_USEC); if (keyboard_xt.wantirq) { keyboard_xt.wantirq = 0; @@ -51,7 +54,7 @@ void keyboard_xt_adddata(uint8_t val) return; } -void keyboard_xt_write(uint16_t port, uint8_t val) +void keyboard_xt_write(uint16_t port, uint8_t val, void *priv) { pclog("keyboard_xt : write %04X %02X %02X\n", port, val, keyboard_xt.pb); /* if (ram[8] == 0xc3) @@ -86,10 +89,10 @@ void keyboard_xt_write(uint16_t port, uint8_t val) } } -uint8_t keyboard_xt_read(uint16_t port) +uint8_t keyboard_xt_read(uint16_t port, void *priv) { uint8_t temp; -// pclog("keyboard_xt : read %04X ", port); + pclog("keyboard_xt : read %04X ", port); switch (port) { case 0x60: @@ -142,7 +145,7 @@ uint8_t keyboard_xt_read(uint16_t port) //dumpregs(); //exit(-1); } -// pclog("%02X\n", temp); + pclog("%02X\n", temp); return temp; } @@ -156,8 +159,10 @@ void keyboard_xt_reset() void keyboard_xt_init() { //return; - io_sethandler(0x0060, 0x0004, keyboard_xt_read, NULL, NULL, keyboard_xt_write, NULL, NULL); + io_sethandler(0x0060, 0x0004, keyboard_xt_read, NULL, NULL, keyboard_xt_write, NULL, NULL, NULL); keyboard_xt_reset(); keyboard_send = keyboard_xt_adddata; keyboard_poll = keyboard_xt_poll; + + timer_add(keyboard_xt_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); } diff --git a/src/lpt.c b/src/lpt.c index dbbe1a5..f4d1e8d 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -4,7 +4,7 @@ #include "lpt.h" static uint8_t lpt1_dat, lpt2_dat; -void lpt1_write(uint16_t port, uint8_t val) +void lpt1_write(uint16_t port, uint8_t val, void *priv) { switch (port & 3) { @@ -17,7 +17,7 @@ void lpt1_write(uint16_t port, uint8_t val) break; } } -uint8_t lpt1_read(uint16_t port) +uint8_t lpt1_read(uint16_t port, void *priv) { switch (port & 3) { @@ -29,7 +29,7 @@ uint8_t lpt1_read(uint16_t port) return 0xff; } -void lpt2_write(uint16_t port, uint8_t val) +void lpt2_write(uint16_t port, uint8_t val, void *priv) { switch (port & 3) { @@ -42,7 +42,7 @@ void lpt2_write(uint16_t port, uint8_t val) break; } } -uint8_t lpt2_read(uint16_t port) +uint8_t lpt2_read(uint16_t port, void *priv) { switch (port & 3) { @@ -56,11 +56,32 @@ uint8_t lpt2_read(uint16_t port) void lpt_init() { - io_sethandler(0x0278, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL); - io_sethandler(0x0378, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL); + io_sethandler(0x0278, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); + io_sethandler(0x0378, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); } +void lpt1_init(uint16_t port) +{ + io_sethandler(port, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); +} +void lpt1_remove() +{ + io_removehandler(0x0278, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); + io_removehandler(0x0378, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); + io_removehandler(0x03bc, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL); +} +void lpt2_init(uint16_t port) +{ + io_sethandler(port, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); +} void lpt2_remove() { - io_removehandler(0x0379, 0x0002, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL); + io_removehandler(0x0278, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); + io_removehandler(0x0378, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); + io_removehandler(0x03bc, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); +} + +void lpt2_remove_ams() +{ + io_removehandler(0x0379, 0x0002, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL); } diff --git a/src/lpt.h b/src/lpt.h index ad690bd..0ff2e7b 100644 --- a/src/lpt.h +++ b/src/lpt.h @@ -1,2 +1,6 @@ -void lpt_init(); -void lpt2_remove(); +extern void lpt_init(); +extern void lpt1_init(uint16_t port); +extern void lpt1_remove(); +extern void lpt2_init(uint16_t port); +extern void lpt2_remove(); +extern void lpt2_remove_ams(); diff --git a/src/mem.c b/src/mem.c index 9350217..c5dad88 100644 --- a/src/mem.c +++ b/src/mem.c @@ -8,17 +8,20 @@ #include #include #include "ibm.h" + +#include "config.h" #include "mem.h" #include "video.h" #include "x86.h" #include "cpu.h" -static uint8_t (*_mem_read_b[0x20000])(uint32_t addr); -static uint16_t (*_mem_read_w[0x20000])(uint32_t addr); -static uint32_t (*_mem_read_l[0x20000])(uint32_t addr); -static void (*_mem_write_b[0x20000])(uint32_t addr, uint8_t val); -static void (*_mem_write_w[0x20000])(uint32_t addr, uint16_t val); -static void (*_mem_write_l[0x20000])(uint32_t addr, uint32_t val); +static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv); +static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv); +static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv); +static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv); +static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv); +static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv); +static void *_mem_priv[0x40000]; int shadowbios,shadowbios_write; @@ -40,14 +43,14 @@ uint8_t romext[32768]; FILE *romfopen(char *fn, char *mode) { char s[512]; - pclog("romfopen %s\n", fn); +// pclog("romfopen %s\n", fn); strcpy(s,pcempath); - pclog("s = %s\n", s); +// pclog("s = %s\n", s); put_backslash(s); - pclog("s = %s\n", s); - pclog("strcat %s %s\n", s, fn); +// pclog("s = %s\n", s); +// pclog("strcat %s %s\n", s, fn); strcat(s,fn); - pclog("s = %s\n", s); +// pclog("s = %s\n", s); return fopen(s,mode); } @@ -76,18 +79,14 @@ static void mem_load_atide_bios() fclose(f); } } - -int loadbios() + +int mem_load_video_bios() { - FILE *f=NULL,*ff=NULL; + FILE *f = NULL; int c; - - loadfont("mda.rom", 0); - - memset(vrom,0x63,0x8000); -// printf("Loadrom - VGA %i\n",VGA); - if (VID_EGA) + switch (gfxcard) { + case GFX_EGA: f=romfopen("roms/ibm_6277356_ega_card_u44_27128.bin","rb"); if (f) { @@ -101,67 +100,170 @@ int loadbios() vrom[c]=getc(f); } fclose(f); + return 1; } - } - if (VGA) - { + break; + + case GFX_TVGA: f=romfopen("roms/trident.bin","rb"); if (f) { fread(vrom,32768,1,f); fclose(f); + return 1; } - } - if (ET4000) - { + break; + + case GFX_ET4000: f=romfopen("roms/et4000.bin","rb"); if (f) { fread(vrom,32768,1,f); fclose(f); + return 1; } - } - if (ET4000W32) - { + break; + + case GFX_ET4000W32: f=romfopen("roms/et4000w32.bin","rb"); if (f) { fread(vrom,32768,1,f); fclose(f); + return 1; } - } - if (gfxcard == GFX_BAHAMAS64) - { + break; + + case GFX_BAHAMAS64: f=romfopen("roms/bahamas64.bin","rb"); if (f) { fread(vrom,32768,1,f); fclose(f); + return 1; } - } - if (gfxcard == GFX_N9_9FX) - { + break; + + case GFX_N9_9FX: f=romfopen("roms/s3_764.bin","rb"); if (f) { fread(vrom,32768,1,f); fclose(f); + return 1; } - } - if (gfxcard == GFX_STEALTH64) - { + break; + + case GFX_STEALTH64: f=romfopen("roms/TRIO64 (Ver. 1.5-07) [VGA] (S3 Incorporated).bin","rb"); if (f) { fread(vrom,32768,1,f); fclose(f); + return 1; } - } + break; + + case GFX_VIRGE: + f=romfopen("roms/s3virge.bin","rb"); + if (f) + { + fread(vrom,32768,1,f); + fclose(f); + return 1; + } + break; - memset(romext,0x63,0x8000); + case GFX_TGUI9440: + f=romfopen("roms/9440.vbi","rb"); + if (f) + { + fread(vrom,32768,1,f); + fclose(f); + return 1; + } + break; + + case GFX_VGA: + f=romfopen("roms/ibm_vga.bin","rb"); + if (f) + { + fread(vrom,32768,1,f); + fclose(f); + return 1; + } + break; + + case GFX_VGAEDGE16: + f=romfopen("roms/vgaedge16.vbi","rb"); + if (f) + { + fread(vrom,32768,1,f); + fclose(f); + return 1; + } + break; + + case GFX_VGACHARGER: + f=romfopen("roms/bios.bin","rb"); + if (f) + { + fread(vrom,32768,1,f); + fclose(f); + return 1; + } + break; + + case GFX_OTI067: + f=romfopen("roms/oti067/bios.bin","rb"); + if (f) + { + fread(vrom,32768,1,f); + fclose(f); + return 1; + } + break; + + case GFX_MACH64GX: + f=romfopen("roms/mach64gx/bios.bin","rb"); + if (f) + { + fread(vrom,32768,1,f); + fclose(f); + return 1; + } + break; + + case GFX_CL_GD5429: + f=romfopen("roms/5429.vbi","rb"); + if (f) + { + fread(vrom,32768,1,f); + fclose(f); + return 1; + } + break; + + default: + memset(vrom,0x63,0x8000); + return 1; + } + pclog("mem_load_video_bios : failed to load video BIOS for gfxcard %i\n", gfxcard); + memset(vrom,0x63,0x8000); + return 0; +} + +int loadbios() +{ + FILE *f=NULL,*ff=NULL; + int c; + + loadfont("mda.rom", 0); biosmask = 0xffff; + memset(romext,0x63,0x4000); + pclog("Starting with romset %i\n", romset); switch (romset) @@ -484,6 +586,17 @@ int loadbios() //is486=1; return 1; + case ROM_430VX: +// f = romfopen("roms/430vx/Ga586atv.bin", "rb"); +// f = fopen("roms/430vx/vx29.BIN", "rb"); + f = romfopen("roms/430vx/55XWUQ0E.BIN", "rb"); +// f=romfopen("roms/430vx/430vx","rb"); + if (!f) break; + fread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + //is486=1; + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); @@ -663,20 +776,23 @@ extern uint32_t testr[9]; uint32_t mmutranslatereal(uint32_t addr, int rw) { - int mmuout=0; uint32_t addr2; uint32_t temp,temp2,temp3; - if (abrt) return -1; + if (abrt) + { +// pclog("Translate recursive abort\n"); + return -1; + } /* if ((addr&~0xFFFFF)==0x77f00000) pclog("Do translate %08X %i %08X %08X\n",addr,rw,EAX,pc); if (addr==0x77f61000) output = 3; if (addr==0x77f62000) { dumpregs(); exit(-1); } if (addr==0x77f9a000) { dumpregs(); exit(-1); }*/ addr2=(cr3+((addr>>20)&0xFFC)); temp=temp2=((uint32_t *)ram)[addr2>>2]; -// pclog("Do translate %08X %i %08X\n", addr, rw, temp); +// if (output == 3) pclog("Do translate %08X %i %08X\n", addr, rw, temp); if (!(temp&1))// || (CPL==3 && !(temp&4) && !cpl_override) || (rw && !(temp&2) && (CPL==3 || cr0&WP_FLAG))) { -// if (/*output==3 && */!nopageerrors) pclog("Section not present! %08X %08X %02X %04X:%08X %i %i\n",addr,temp,opcode,CS,pc,CPL,rw); +// /*if (!nopageerrors && opcode != 0xf3 && opcode != 0x89) */pclog("Section not present! %08X %08X %02X %04X:%08X %i %i\n",addr,temp,opcode,CS,pc,CPL,rw); cr2=addr; temp&=1; @@ -693,13 +809,16 @@ uint32_t mmutranslatereal(uint32_t addr, int rw) } temp=((uint32_t *)ram)[((temp&~0xFFF)+((addr>>10)&0xFFC))>>2]; temp3=temp&temp2; -// pclog("Do translate %08X %08X\n", temp, temp3); +// if (output == 3) pclog("Do translate %08X %08X\n", temp, temp3); if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG))) { -// if (!nopageerrors) pclog("Page not present! %08X %08X %02X %02X %04X:%08X %04X:%08X %i %i %i\n",addr,temp,opcode,opcode2,CS,pc,SS,ESP,ins,CPL,rw); +// /*if (!nopageerrors && opcode != 0xf3 && opcode != 0x89) */pclog("Page not present! %08X %08X %02X %02X %i %08X %04X:%08X %04X:%08X %i %i %i\n",addr,temp,opcode,opcode2,frame,rmdat32, CS,pc,SS,ESP,ins,CPL,rw); + +// dumpregs(); +// exit(-1); // if (addr == 0x815F6E90) output = 3; -/* if (addr == 0x10ADE020) output = 3; - if (addr == 0x10000008) +/* if (addr == 0x10ADE020) output = 3;*/ +/* if (addr == 0x10150010 && !nopageerrors) { dumpregs(); exit(-1); @@ -816,7 +935,7 @@ uint8_t *getpccache(uint32_t a) { // int logit=(a>0xFFFFF); uint32_t a2=a; - if (readlookup2[a>>12]!=0xFFFFFFFF) return &ram[(uint8_t *)readlookup2[a>>12] - (uint8_t *)(a&~0xFFF)]; + //if (readlookup2[a>>12]!=0xFFFFFFFF) return &ram[(uint8_t *)readlookup2[a>>12] - (uint8_t *)(a&~0xFFF)]; if (cr0>>31) { // if (output==3) pclog("Translate GetPCCache %08X\n",a); @@ -870,12 +989,8 @@ uint8_t readmembl(uint32_t addr) } addr &= rammask; - switch (addr>>16) - { - case 13: if (romset==ROM_AMI286) return neat_readems(addr); return 0xFF; -// case 14: pclog("Read %06X\n", addr); if (shadowbios) { /*printf("Read shadow RAM %08X %02X\n",addr,ram[addr]);*/ return ram[addr]; } - } - if (_mem_read_b[addr >> 15]) return _mem_read_b[addr >> 15](addr); + if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv[addr >> 14]); +// pclog("Bad readmembl %08X %04X:%08X\n", addr, CS, pc); return 0xFF; } @@ -890,15 +1005,8 @@ void writemembl(uint32_t addr, uint8_t val) } addr &= rammask; - switch (addr>>16) - { - case 13: if (romset==ROM_AMI286) neat_writeems(addr,val); return; -// case 14: printf("Write %08X %02X\n",addr,val); //ram[addr]=val; -// if (isram[(addr>>16)&0xFF]) ram[addr]=val; -// return; - } - if (_mem_write_b[addr >> 15]) _mem_write_b[addr >> 15](addr, val); -// else pclog("Bad write %08X %02X\n", addr, val); + if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv[addr >> 14]); +// else pclog("Bad write %08X %02X %04X:%08X\n", addr, val, CS, pc); } uint8_t readmemb386l(uint32_t seg, uint32_t addr) @@ -910,10 +1018,10 @@ uint8_t readmemb386l(uint32_t seg, uint32_t addr) return -1; } mem_logical_addr = addr = addr + seg; - if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF) +/* if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF) { return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)]; - } + }*/ if (cr0 >> 31) { @@ -923,7 +1031,8 @@ uint8_t readmemb386l(uint32_t seg, uint32_t addr) addr &= rammask; - if (_mem_read_b[addr >> 15]) return _mem_read_b[addr >> 15](addr); + if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv[addr >> 14]); +// pclog("Bad readmemb386l %08X %04X:%08X\n", addr, CS, pc); return 0xFF; } @@ -945,8 +1054,11 @@ void writememb386l(uint32_t seg, uint32_t addr, uint8_t val) addr &= rammask; - if (_mem_write_b[addr >> 15]) _mem_write_b[addr >> 15](addr, val); -// else pclog("Bad write %08X %02X\n", addr, val); +/* if (addr >= 0xa0000 && addr < 0xc0000) + pclog("writemembl %08X %02X\n", addr, val);*/ + + if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv[addr >> 14]); +// else pclog("Bad write %08X %02X %04X:%08X\n", addr, val, CS, pc); } uint16_t readmemwl(uint32_t seg, uint32_t addr) @@ -956,8 +1068,8 @@ uint16_t readmemwl(uint32_t seg, uint32_t addr) { if (cr0>>31) { - if (mmutranslate(addr2, 0) == 0xffffffff) return; - if (mmutranslate(addr2+1, 0) == 0xffffffff) return; + if (mmutranslate(addr2, 0) == 0xffffffff) return 0xffff; + if (mmutranslate(addr2+1, 0) == 0xffffffff) return 0xffff; } if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8); else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8); @@ -976,12 +1088,12 @@ uint16_t readmemwl(uint32_t seg, uint32_t addr) addr2 &= rammask; - if (_mem_read_w[addr2 >> 15]) return _mem_read_w[addr2 >> 15](addr2); + if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]); - if (_mem_read_b[addr2 >> 15]) + if (_mem_read_b[addr2 >> 14]) { - if (AT) return _mem_read_b[addr2 >> 15](addr2) | (_mem_read_b[(addr2 + 1) >> 15](addr2 + 1) << 8); - else return _mem_read_b[addr2 >> 15](addr2) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 15](seg + ((addr + 1) & 0xffff)) << 8); + if (AT) return _mem_read_b[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv[addr2 >> 14]) << 8); + else return _mem_read_b[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv[addr2 >> 14]) << 8); } return 0xffff; } @@ -1022,19 +1134,20 @@ void writememwl(uint32_t seg, uint32_t addr, uint16_t val) } addr2 &= rammask; + +/* if (addr2 >= 0xa0000 && addr2 < 0xc0000) + pclog("writememwl %08X %02X\n", addr2, val);*/ - if (_mem_write_w[addr2 >> 15]) + if (_mem_write_w[addr2 >> 14]) { - _mem_write_w[addr2 >> 15](addr2, val); + _mem_write_w[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); return; } - if (_mem_write_b[addr2 >> 15]) + if (_mem_write_b[addr2 >> 14]) { - _mem_write_b[addr2 >> 15](addr2, val); - _mem_write_b[(addr2 + 1) >> 15](addr2 + 1, val >> 8); -// if (AT) _ -// else _mem_write_b[(seg + ((addr + 1) & 0xffff)) >> 15](seg + ((addr + 1) & 0xffff), val >> 8); + _mem_write_b[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); + _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv[addr2 >> 14]); return; } // pclog("Bad write %08X %04X\n", addr, val); @@ -1047,8 +1160,8 @@ uint32_t readmemll(uint32_t seg, uint32_t addr) { if (cr0>>31) { - if (mmutranslate(addr2, 0) == 0xffffffff) return; - if (mmutranslate(addr2+3, 0) == 0xffffffff) return; + if (mmutranslate(addr2, 0) == 0xffffffff) return 0xffffffff; + if (mmutranslate(addr2+3, 0) == 0xffffffff) return 0xffffffff; } return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); } @@ -1068,11 +1181,11 @@ uint32_t readmemll(uint32_t seg, uint32_t addr) addr2&=rammask; - if (_mem_read_l[addr2 >> 15]) return _mem_read_l[addr2 >> 15](addr2); + if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]); - if (_mem_read_w[addr2 >> 15]) return _mem_read_w[addr2 >> 15](addr2) | (_mem_read_w[addr2 >> 15](addr2 + 2) << 16); + if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv[addr2 >> 14]) << 16); - if (_mem_read_b[addr2 >> 15]) return _mem_read_b[addr2 >> 15](addr2) | (_mem_read_b[addr2 >> 15](addr2 + 1) << 8) | (_mem_read_b[addr2 >> 15](addr2 + 2) << 16) | (_mem_read_b[addr2 >> 15](addr2 + 3) << 24); + if (_mem_read_b[addr2 >> 14]) return _mem_read_b[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv[addr2 >> 14]) << 24); return 0xffffffff; } @@ -1106,67 +1219,70 @@ void writememll(uint32_t seg, uint32_t addr, uint32_t val) addr2&=rammask; - if (_mem_write_l[addr2 >> 15]) +/* if (addr >= 0xa0000 && addr < 0xc0000) + pclog("writememll %08X %08X\n", addr, val);*/ + + if (_mem_write_l[addr2 >> 14]) { - _mem_write_l[addr2 >> 15](addr2, val); + _mem_write_l[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); return; } - if (_mem_write_w[addr2 >> 15]) + if (_mem_write_w[addr2 >> 14]) { - _mem_write_w[addr2 >> 15](addr2, val); - _mem_write_w[addr2 >> 15](addr2 + 2, val >> 16); + _mem_write_w[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv[addr2 >> 14]); return; } - if (_mem_write_b[addr2 >> 15]) + if (_mem_write_b[addr2 >> 14]) { - _mem_write_b[addr2 >> 15](addr2, val); - _mem_write_b[addr2 >> 15](addr2 + 1, val >> 8); - _mem_write_b[addr2 >> 15](addr2 + 2, val >> 16); - _mem_write_b[addr2 >> 15](addr2 + 3, val >> 24); + _mem_write_b[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv[addr2 >> 14]); return; } // pclog("Bad write %08X %08X\n", addr, val); } -uint8_t mem_read_ram(uint32_t addr) +uint8_t mem_read_ram(uint32_t addr, void *priv) { -// if (addr < 0xa0000) pclog("Read RAMb %08X\n", addr); +// if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMb %08X\n", addr); addreadlookup(mem_logical_addr, addr); return ram[addr]; } -uint16_t mem_read_ramw(uint32_t addr) +uint16_t mem_read_ramw(uint32_t addr, void *priv) { -// if (addr < 0xa0000) pclog("Read RAMw %08X\n", addr); +// if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMw %08X\n", addr); addreadlookup(mem_logical_addr, addr); return *(uint16_t *)&ram[addr]; } -uint32_t mem_read_raml(uint32_t addr) +uint32_t mem_read_raml(uint32_t addr, void *priv) { -// if (addr < 0xa0000) pclog("Read RAMl %08X\n", addr); +// if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMl %08X\n", addr); addreadlookup(mem_logical_addr, addr); return *(uint32_t *)&ram[addr]; } -void mem_write_ram(uint32_t addr, uint8_t val) +void mem_write_ram(uint32_t addr, uint8_t val, void *priv) { addwritelookup(mem_logical_addr, addr); ram[addr] = val; // if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMb %08X\n", addr); } -void mem_write_ramw(uint32_t addr, uint16_t val) +void mem_write_ramw(uint32_t addr, uint16_t val, void *priv) { addwritelookup(mem_logical_addr, addr); *(uint16_t *)&ram[addr] = val; -// if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMw %08X %04X:%04X\n", addr, CS, pc); +// if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMw %08X %04X:%04X %i %04X %04X:%04X %04X:%04X\n", addr, CS, pc, ins, val, DS,SI, ES,DI); } -void mem_write_raml(uint32_t addr, uint32_t val) +void mem_write_raml(uint32_t addr, uint32_t val, void *priv) { addwritelookup(mem_logical_addr, addr); *(uint32_t *)&ram[addr] = val; // if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMl %08X %04X:%04X %04X:%04X %04X:%04X\n", addr, CS, pc, DS,SI, ES,DI); } -uint8_t mem_read_bios(uint32_t addr) +uint8_t mem_read_bios(uint32_t addr, void *priv) { if (AMIBIOS && (addr&0xFFFFF)==0xF8281) /*This is read constantly during AMIBIOS POST, but is never written to. It's clearly a status register of some kind, but for what?*/ { @@ -1177,39 +1293,39 @@ uint8_t mem_read_bios(uint32_t addr) // if (output) pclog("Read BIOS %08X %02X %04X:%04X\n", addr, rom[addr & biosmask], CS, pc); return rom[addr & biosmask]; } -uint16_t mem_read_biosw(uint32_t addr) +uint16_t mem_read_biosw(uint32_t addr, void *priv) { -// if (output) pclog("Read BIOS %08X %04X %04X:%04X\n", addr, *(uint16_t *)&rom[addr & biosmask], CS, pc); +// /*if (output) */pclog("Read BIOS %08X %04X %04X:%04X\n", addr, *(uint16_t *)&rom[addr & biosmask], CS, pc); return *(uint16_t *)&rom[addr & biosmask]; } -uint32_t mem_read_biosl(uint32_t addr) +uint32_t mem_read_biosl(uint32_t addr, void *priv) { -// if (output) pclog("Read BIOS %08X %02X %04X:%04X\n", addr, *(uint32_t *)&rom[addr & biosmask], CS, pc); +// pclog("Read BIOS %08X %02X %04X:%04X\n", addr, *(uint32_t *)&rom[addr & biosmask], CS, pc); return *(uint32_t *)&rom[addr & biosmask]; } -uint8_t mem_read_vrom(uint32_t addr) +uint8_t mem_read_vrom(uint32_t addr, void *priv) { return vrom[addr & 0x7fff]; } -uint16_t mem_read_vromw(uint32_t addr) +uint16_t mem_read_vromw(uint32_t addr, void *priv) { return *(uint16_t *)&vrom[addr & 0x7fff]; } -uint32_t mem_read_vroml(uint32_t addr) +uint32_t mem_read_vroml(uint32_t addr, void *priv) { return *(uint32_t *)&vrom[addr & 0x7fff]; } -uint8_t mem_read_romext(uint32_t addr) +uint8_t mem_read_romext(uint32_t addr, void *priv) { return romext[addr & 0x7fff]; } -uint16_t mem_read_romextw(uint32_t addr) +uint16_t mem_read_romextw(uint32_t addr, void *priv) { return *(uint16_t *)&romext[addr & 0x7fff]; } -uint32_t mem_read_romextl(uint32_t addr) +uint32_t mem_read_romextl(uint32_t addr, void *priv) { return *(uint32_t *)&romext[addr & 0x7fff]; } @@ -1233,16 +1349,16 @@ void mem_init() isram[c]=1; if (c >= 0xa && c<=0xF) isram[c]=0; } - for (c = 0; c < 0x20000; c++) - _mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = NULL; + for (c = 0; c < 0x40000; c++) + _mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = _mem_priv[c] = NULL; - mem_sethandler(0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); if (mem_size > 1) - mem_sethandler(0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_sethandler(0xc0000, 0x08000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL); - mem_sethandler(0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL); - mem_sethandler(0xe0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0xc0000, 0x08000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL, NULL); + mem_sethandler(0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, NULL); + mem_sethandler(0xe0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); // pclog("Mem resize %i %i\n",mem_size,c); } @@ -1258,16 +1374,16 @@ void mem_resize() isram[c]=1; if (c >= 0xa && c<=0xF) isram[c]=0; } - for (c = 0; c < 0x20000; c++) - _mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = NULL; + for (c = 0; c < 0x40000; c++) + _mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = _mem_priv[c] = NULL; - mem_sethandler(0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); if (mem_size > 1) - mem_sethandler(0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_sethandler(0xc0000, 0x8000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL); - mem_sethandler(0xc8000, 0x8000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL); - mem_sethandler(0xe0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0xc0000, 0x8000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL, NULL); + mem_sethandler(0xc8000, 0x8000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, NULL); + mem_sethandler(0xe0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); // pclog("Mem resize %i %i\n",mem_size,c); } @@ -1295,44 +1411,62 @@ void mem_updatecache() } void mem_sethandler(uint32_t base, uint32_t size, - uint8_t (*read_b)(uint32_t addr), - uint16_t (*read_w)(uint32_t addr), - uint32_t (*read_l)(uint32_t addr), - void (*write_b)(uint32_t addr, uint8_t val), - void (*write_w)(uint32_t addr, uint16_t val), - void (*write_l)(uint32_t addr, uint32_t val)) + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv), + void *priv) { uint32_t c; - for (c = base; c < base + size; c += 0x8000) +// printf("mem_sethandler : %05X %04X %08X %08X %08X %08X %08X\n", base, size, read_w, write_w, mem_read_biosw, mem_read_ramw, mem_write_ramw); + for (c = base; c < base + size; c += 0x4000) { - _mem_read_b[ c >> 15] = read_b; - _mem_read_w[ c >> 15] = read_w; - _mem_read_l[ c >> 15] = read_l; - _mem_write_b[c >> 15] = write_b; - _mem_write_w[c >> 15] = write_w; - _mem_write_l[c >> 15] = write_l; + _mem_read_b[ c >> 14] = read_b; + _mem_read_w[ c >> 14] = read_w; + _mem_read_l[ c >> 14] = read_l; + _mem_write_b[c >> 14] = write_b; + _mem_write_w[c >> 14] = write_w; + _mem_write_l[c >> 14] = write_l; + _mem_priv[c >> 14] = priv; + } + for (c = base; c < base + size; c += 0x1000) + { + readlookup2[c >> 12] = 0xFFFFFFFF; + writelookup2[c >> 12] = 0xFFFFFFFF; } } void mem_removehandler(uint32_t base, uint32_t size, - uint8_t (*read_b)(uint32_t addr), - uint16_t (*read_w)(uint32_t addr), - uint32_t (*read_l)(uint32_t addr), - void (*write_b)(uint32_t addr, uint8_t val), - void (*write_w)(uint32_t addr, uint16_t val), - void (*write_l)(uint32_t addr, uint32_t val)) + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv), + void *priv) { uint32_t c; if ((base + size) > 0xffff8000) size = 0xffff0000 - base; - for (c = base; c < base + size; c += 0x8000) + for (c = base; c < base + size; c += 0x4000) { - if ( _mem_read_b[c >> 15] == read_b) _mem_read_b[c >> 15] = NULL; - if ( _mem_read_w[c >> 15] == read_w) _mem_read_w[c >> 15] = NULL; - if ( _mem_read_l[c >> 15] == read_l) _mem_read_l[c >> 15] = NULL; - if (_mem_write_b[c >> 15] == write_b) _mem_write_b[c >> 15] = NULL; - if (_mem_write_w[c >> 15] == write_w) _mem_write_w[c >> 15] = NULL; - if (_mem_write_l[c >> 15] == write_l) _mem_write_l[c >> 15] = NULL; + if (_mem_priv[c >> 14] == priv) + { + if ( _mem_read_b[c >> 14] == read_b) _mem_read_b[c >> 14] = NULL; + if ( _mem_read_w[c >> 14] == read_w) _mem_read_w[c >> 14] = NULL; + if ( _mem_read_l[c >> 14] == read_l) _mem_read_l[c >> 14] = NULL; + if (_mem_write_b[c >> 14] == write_b) _mem_write_b[c >> 14] = NULL; + if (_mem_write_w[c >> 14] == write_w) _mem_write_w[c >> 14] = NULL; + if (_mem_write_l[c >> 14] == write_l) _mem_write_l[c >> 14] = NULL; + _mem_priv[c >> 14] = NULL; + } + } + for (c = base; c < base + size; c += 0x1000) + { + readlookup2[c >> 12] = 0xFFFFFFFF; + writelookup2[c >> 12] = 0xFFFFFFFF; } } @@ -1342,7 +1476,7 @@ static int mem_a20_state = 0; void mem_a20_recalc() { int state = mem_a20_key | mem_a20_alt; - pclog("A20 recalc %i %i\n", state, mem_a20_state); +// pclog("A20 recalc %i %i\n", state, mem_a20_state); if (state && !mem_a20_state) { rammask = 0xffffffff; @@ -1353,6 +1487,6 @@ void mem_a20_recalc() rammask = 0xffefffff; flushmmucache(); } - pclog("rammask now %08X\n", rammask); +// pclog("rammask now %08X\n", rammask); mem_a20_state = state; } diff --git a/src/mem.h b/src/mem.h index dd496a7..139bb1c 100644 --- a/src/mem.h +++ b/src/mem.h @@ -7,34 +7,38 @@ extern int cache; extern int memwaitstate; void mem_sethandler(uint32_t base, uint32_t size, - uint8_t (*read_b)(uint32_t addr), - uint16_t (*read_w)(uint32_t addr), - uint32_t (*read_l)(uint32_t addr), - void (*write_b)(uint32_t addr, uint8_t val), - void (*write_w)(uint32_t addr, uint16_t val), - void (*write_l)(uint32_t addr, uint32_t val)); + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv), + void *priv); void mem_removehandler(uint32_t base, uint32_t size, - uint8_t (*read_b)(uint32_t addr), - uint16_t (*read_w)(uint32_t addr), - uint32_t (*read_l)(uint32_t addr), - void (*write_b)(uint32_t addr, uint8_t val), - void (*write_w)(uint32_t addr, uint16_t val), - void (*write_l)(uint32_t addr, uint32_t val)); + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv), + void *priv); extern int mem_a20_alt; extern int mem_a20_key; void mem_a20_recalc(); -uint8_t mem_read_ram(uint32_t addr); -uint16_t mem_read_ramw(uint32_t addr); -uint32_t mem_read_raml(uint32_t addr); +uint8_t mem_read_ram(uint32_t addr, void *priv); +uint16_t mem_read_ramw(uint32_t addr, void *priv); +uint32_t mem_read_raml(uint32_t addr, void *priv); -void mem_write_ram(uint32_t addr, uint8_t val); -void mem_write_ramw(uint32_t addr, uint16_t val); -void mem_write_raml(uint32_t addr, uint32_t val); +void mem_write_ram(uint32_t addr, uint8_t val, void *priv); +void mem_write_ramw(uint32_t addr, uint16_t val, void *priv); +void mem_write_raml(uint32_t addr, uint32_t val, void *priv); -uint8_t mem_read_bios(uint32_t addr); -uint16_t mem_read_biosw(uint32_t addr); -uint32_t mem_read_biosl(uint32_t addr); +uint8_t mem_read_bios(uint32_t addr, void *priv); +uint16_t mem_read_biosw(uint32_t addr, void *priv); +uint32_t mem_read_biosl(uint32_t addr, void *priv); FILE *romfopen(char *fn, char *mode); + +int mem_load_video_bios(); diff --git a/src/model.c b/src/model.c index 4c4024c..db5e0d8 100644 --- a/src/model.c +++ b/src/model.c @@ -6,14 +6,17 @@ #include "acer386sx.h" #include "ali1429.h" #include "amstrad.h" +#include "device.h" #include "dma.h" #include "fdc.h" #include "headland.h" +#include "i430vx.h" #include "ide.h" #include "jim.h" -#include "keyboard_xt.h" +#include "keyboard_amstrad.h" #include "keyboard_at.h" #include "keyboard_olim24.h" +#include "keyboard_xt.h" #include "lpt.h" #include "mouse_ps2.h" #include "mouse_serial.h" @@ -22,9 +25,11 @@ #include "olivetti_m24.h" #include "pci.h" #include "pic.h" +#include "piix.h" #include "pit.h" -#include "psg.h" #include "serial.h" +#include "sound_sn76489.h" +#include "um8669f.h" #include "um8881f.h" #include "wd76c10.h" #include "xtide.h" @@ -41,33 +46,35 @@ void at_wd76c10_init(); void at_ali1429_init(); void at_headland_init(); void at_um8881f_init(); +void at_i430vx_init(); int model; MODEL models[] = { - {"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, - {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, - {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, - {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, - {"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, tandy1k_init}, - {"Amstrad PC1512", ROM_PC1512, { "", cpus_pc1512,"", NULL, "", NULL}, 1, ams_init}, - {"Sinclair PC200", ROM_PC200, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, - {"Euro PC", ROM_EUROPC, { "", cpus_8086, "", NULL, "", NULL}, 0, europc_init}, - {"Olivetti M24", ROM_OLIM24, { "", cpus_8086, "", NULL, "", NULL}, 1, olim24_init}, - {"Amstrad PC1640", ROM_PC1640, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, - {"Amstrad PC2086", ROM_PC2086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, - {"Amstrad PC3086", ROM_PC3086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, - {"IBM AT", ROM_IBMAT, { "", cpus_ibmat, "", NULL, "", NULL}, 0, at_init}, - {"Commodore PC 30 III", ROM_CMDPC30, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, - {"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, at_neat_init}, - {"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, - {"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, at_acer386sx_init}, - {"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, at_wd76c10_init}, - {"AMI 386 clone", ROM_AMI386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, at_headland_init}, - {"AMI 486 clone", ROM_AMI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, - {"AMI WinBIOS 486", ROM_WIN486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, - {"AMI WinBIOS 486 PCI", ROM_PCI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_um8881f_init}, + {"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, + {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, + {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, + {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, + {"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, tandy1k_init}, + {"Amstrad PC1512", ROM_PC1512, { "", cpus_pc1512, "", NULL, "", NULL}, 1, ams_init}, + {"Sinclair PC200", ROM_PC200, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, + {"Euro PC", ROM_EUROPC, { "", cpus_8086, "", NULL, "", NULL}, 0, europc_init}, + {"Olivetti M24", ROM_OLIM24, { "", cpus_8086, "", NULL, "", NULL}, 1, olim24_init}, + {"Amstrad PC1640", ROM_PC1640, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, + {"Amstrad PC2086", ROM_PC2086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, + {"Amstrad PC3086", ROM_PC3086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, + {"IBM AT", ROM_IBMAT, { "", cpus_ibmat, "", NULL, "", NULL}, 0, at_init}, + {"Commodore PC 30 III", ROM_CMDPC30, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, + {"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, at_neat_init}, + {"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, + {"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, at_acer386sx_init}, + {"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, at_wd76c10_init}, + {"AMI 386 clone", ROM_AMI386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, at_headland_init}, + {"AMI 486 clone", ROM_AMI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, + {"AMI WinBIOS 486", ROM_WIN486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, + {"AMI WinBIOS 486 PCI", ROM_PCI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_um8881f_init}, + {"Award 430VX PCI", ROM_430VX, { "IDT", cpus_WinChip, "", NULL, "", NULL}, 0, at_i430vx_init}, {"", -1, {"", 0, "", 0, "", 0}, 0} }; @@ -84,7 +91,7 @@ char *model_getname() void common_init() { dma_init(); - fdc_init(); + fdc_add(); lpt_init(); pic_init(); pit_init(); @@ -105,7 +112,7 @@ void tandy1k_init() common_init(); keyboard_xt_init(); mouse_serial_init(); - psg_init(); + device_add(&sn76489_device); xtide_init(); } @@ -191,6 +198,16 @@ void at_um8881f_init() um8881f_init(); } +void at_i430vx_init() +{ + at_init(); + mouse_serial_init(); + pci_init(); + i430vx_init(); + piix_init(7); + um8669f_init(); +} + void model_init() { pclog("Initting as %s\n", model_getname()); diff --git a/src/model.h b/src/model.h index 2c26c77..9931164 100644 --- a/src/model.h +++ b/src/model.h @@ -14,3 +14,7 @@ typedef struct extern MODEL models[]; extern int model; + +int model_getromset(); +char *model_getname(); +void model_init(); diff --git a/src/mouse_serial.c b/src/mouse_serial.c index 2aab639..7f49749 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -1,6 +1,8 @@ #include "ibm.h" #include "mouse.h" +#include "pic.h" #include "serial.h" +#include "timer.h" static int oldb=0; @@ -37,11 +39,12 @@ void mouse_serial_poll(int x, int y, int b) void mouse_serial_rcr() { mousepos=-1; - mousedelay=1000; + mousedelay=5000 * (1 << TIMER_SHIFT); } void mousecallback() { + mousedelay = 0; if (mousepos == -1) { mousepos = 0; @@ -62,5 +65,6 @@ void mouse_serial_init() { mouse_poll = mouse_serial_poll; serial_rcr = mouse_serial_rcr; + timer_add(mousecallback, &mousedelay, &mousedelay, NULL); } diff --git a/src/neat.c b/src/neat.c index 3861c4f..6dca3be 100644 --- a/src/neat.c +++ b/src/neat.c @@ -7,7 +7,7 @@ static uint8_t neat_regs[256]; static int neat_index; static int neat_emspage[4]; -void neat_write(uint16_t port, uint8_t val) +void neat_write(uint16_t port, uint8_t val, void *priv) { switch (port) { @@ -35,7 +35,7 @@ void neat_write(uint16_t port, uint8_t val) } } -uint8_t neat_read(uint16_t port) +uint8_t neat_read(uint16_t port, void *priv) { switch (port) { @@ -60,9 +60,9 @@ uint8_t neat_readems(uint32_t addr) void neat_init() { - io_sethandler(0x0022, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); - io_sethandler(0x0208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); - io_sethandler(0x4208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); - io_sethandler(0x8208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); - io_sethandler(0xc208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); + io_sethandler(0x0022, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); + io_sethandler(0x0208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); + io_sethandler(0x4208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); + io_sethandler(0x8208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); + io_sethandler(0xc208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); } diff --git a/src/nvr.c b/src/nvr.c index 0fd89b6..e323ed0 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -1,7 +1,10 @@ #include #include #include "ibm.h" +#include "io.h" #include "nvr.h" +#include "pic.h" +#include "timer.h" int oldromset; int nvrmask=63; @@ -10,6 +13,8 @@ int nvraddr; SYSTEMTIME systemtime; +int nvr_dosave = 0; + void getnvrtime() { int c,d; @@ -51,9 +56,9 @@ void getnvrtime() void nvr_recalc() { int c; - float newrtctime; + int newrtctime; c=1<<((nvrram[0xA]&0xF)-1); - newrtctime=RTCCONST*(float)c; + newrtctime=(int)(RTCCONST * c * (1 << TIMER_SHIFT)); if (rtctime>newrtctime) rtctime=newrtctime; } @@ -62,11 +67,11 @@ void nvr_rtc() int c; if (!(nvrram[0xA]&0xF)) { - rtctime=99999999; + rtctime=0x7fffffff; return; } c=1<<((nvrram[0xA]&0xF)-1); - rtctime+=RTCCONST*(float)c; + rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); // pclog("RTCtime now %f\n",rtctime); nvrram[0xC]=0x40; if (nvrram[0xB]&0x40) @@ -78,7 +83,7 @@ void nvr_rtc() } } -void writenvr(uint16_t addr, uint8_t val) +void writenvr(uint16_t addr, uint8_t val, void *priv) { int c; // printf("Write NVR %03X %02X %02X %04X:%04X %i\n",addr,nvraddr,val,cs>>4,pc,ins); @@ -86,7 +91,7 @@ void writenvr(uint16_t addr, uint8_t val) { // if (nvraddr == 0x33) pclog("NVRWRITE33 %02X %04X:%04X %i\n",val,CS,pc,ins); if (nvraddr >= 0xe && nvrram[nvraddr] != val) - savenvr(); + nvr_dosave = 1; if (nvraddr!=0xC && nvraddr!=0xD) nvrram[nvraddr]=val; if (nvraddr==0xA) @@ -95,16 +100,16 @@ void writenvr(uint16_t addr, uint8_t val) if (val&0xF) { c=1<<((val&0xF)-1); - rtctime+=RTCCONST*(float)c; + rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); } else - rtctime=99999999; + rtctime = 0x7fffffff; } } else nvraddr=val&nvrmask; } -uint8_t readnvr(uint16_t addr) +uint8_t readnvr(uint16_t addr, void *priv) { uint8_t temp; // printf("Read NVR %03X %02X %02X %04X:%04X\n",addr,nvraddr,nvrram[nvraddr],cs>>4,pc); @@ -157,6 +162,7 @@ void loadnvr() case ROM_AMI486: f = romfopen("ami486.nvr", "rb"); nvrmask = 127; break; case ROM_WIN486: f = romfopen("win486.nvr", "rb"); nvrmask = 127; break; case ROM_PCI486: f = romfopen("hot-433.nvr", "rb"); nvrmask = 127; break; + case ROM_430VX: f = romfopen("hot-433.nvr", "rb"); nvrmask = 127; break; default: return; } if (!f) @@ -169,7 +175,7 @@ void loadnvr() nvrram[0xA]=6; nvrram[0xB]=0; c=1<<((6&0xF)-1); - rtctime+=RTCCONST*(float)c; + rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); } void savenvr() { @@ -178,7 +184,7 @@ void savenvr() { case ROM_PC1512: f = romfopen("pc1512.nvr" , "wb"); break; case ROM_PC1640: f = romfopen("pc1640.nvr" , "wb"); break; - case ROM_PC200: f = romfopen("pc200.nvr" , "wb"); break; + case ROM_PC200: f = romfopen("pc200.nvr" , "wb"); break; case ROM_PC2086: f = romfopen("pc2086.nvr" , "wb"); break; case ROM_PC3086: f = romfopen("pc3086.nvr" , "wb"); break; case ROM_IBMAT: f = romfopen("at.nvr" , "wb"); break; @@ -192,6 +198,7 @@ void savenvr() case ROM_AMI486: f = romfopen("ami486.nvr" , "wb"); break; case ROM_WIN486: f = romfopen("win486.nvr" , "wb"); break; case ROM_PCI486: f = romfopen("hot-433.nvr", "wb"); break; + case ROM_430VX: f = romfopen("hot-433.nvr", "wb"); break; default: return; } fwrite(nvrram,128,1,f); @@ -200,5 +207,6 @@ void savenvr() void nvr_init() { - io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL); + io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, NULL); + timer_add(nvr_rtc, &rtctime, TIMER_ALWAYS_ENABLED, NULL); } diff --git a/src/nvr.h b/src/nvr.h index 868b457..45a5fff 100644 --- a/src/nvr.h +++ b/src/nvr.h @@ -1 +1,3 @@ void nvr_init(); + +extern int nvr_dosave; diff --git a/src/olivetti_m24.c b/src/olivetti_m24.c index d721d7c..33b1478 100644 --- a/src/olivetti_m24.c +++ b/src/olivetti_m24.c @@ -2,7 +2,7 @@ #include "io.h" #include "olivetti_m24.h" -uint8_t olivetti_m24_read(uint16_t port) +uint8_t olivetti_m24_read(uint16_t port, void *priv) { switch (port) { @@ -16,5 +16,5 @@ uint8_t olivetti_m24_read(uint16_t port) void olivetti_m24_init() { - io_sethandler(0x0066, 0x0002, olivetti_m24_read, NULL, NULL, NULL, NULL, NULL); + io_sethandler(0x0066, 0x0002, olivetti_m24_read, NULL, NULL, NULL, NULL, NULL, NULL); } diff --git a/src/pc.c b/src/pc.c index 447598b..b8d090b 100644 --- a/src/pc.c +++ b/src/pc.c @@ -1,19 +1,36 @@ #include +#include #include #include "ibm.h" -#include "video.h" +#include "device.h" + +#include "ali1429.h" #include "amstrad.h" +#include "cdrom-ioctl.h" +#include "config.h" +#include "cpu.h" #include "dma.h" -#include "mem.h" +#include "fdc.h" +#include "sound_gus.h" #include "ide.h" +#include "keyboard.h" +#include "mem.h" +#include "model.h" #include "mouse.h" +#include "nvr.h" #include "pic.h" #include "pit.h" -#include "serial.h" -#include "cdrom-ioctl.h" -#include "cpu.h" -#include "model.h" #include "plat-mouse.h" +#include "serial.h" +#include "sound.h" +#include "sound_cms.h" +#include "sound_opl.h" +#include "sound_sb.h" +#include "timer.h" +#include "vid_voodoo.h" +#include "video.h" + +int frame = 0; int cdrom_enabled; int CPUID; @@ -42,8 +59,8 @@ int mousecapture; FILE *pclogf; void pclog(const char *format, ...) { - char buf[256]; - return; + char buf[1024]; + //return; if (!pclogf) pclogf=fopen("pclog.txt","wt"); //return; @@ -79,6 +96,7 @@ int pollmouse_delay = 2; void pollmouse() { int x,y; +// return; pollmouse_delay--; if (pollmouse_delay) return; pollmouse_delay = 2; @@ -149,6 +167,7 @@ void pc_reset() { resetx86(); cpu_set(); + //timer_reset(); dma_reset(); fdc_reset(); pic_reset(); @@ -157,8 +176,7 @@ void pc_reset() setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed); - adlib_reset(); - sb_reset(); +// sb_reset(); ali1429_reset(); et4000w32_reset(); @@ -185,31 +203,39 @@ void initpc() cpuspeed2=(AT)?2:1; // cpuspeed2=cpuspeed; atfullspeed=0; - + + device_init(); pclog("Initvideo\n"); initvideo(); mem_init(); loadbios(); + mem_load_video_bios(); loaddisc(0,discfns[0]); loaddisc(1,discfns[1]); + + timer_reset(); + sound_reset(); + fdc_init(); + //loadfont(); loadnvr(); resetvideo(); - initsound(); - initpsg(); + sound_init(); inithdc(); initega(); - initgus(); resetide(); ioctl_open(cdrom_drive); model_init(); video_init(); - adlib_init(); - sb_init(); - gus_init(); - + speaker_init(); + sound_card_init(sound_card_current); + if (GUS) + device_add(&gus_device); + if (GAMEBLASTER) + device_add(&cms_device); + pc_reset(); pit_reset(); @@ -222,7 +248,7 @@ void initpc() // CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9)); // pclog("Init - CPUID %i %i\n",CPUID,cpuspeed); shadowbios=0; - + voodoo_init(); } void resetpc() @@ -236,13 +262,22 @@ void resetpc() void resetpchard() { + device_close_all(); + device_init(); + + timer_reset(); + sound_reset(); mem_resize(); + fdc_init(); model_init(); pclog("Video_init\n"); video_init(); - adlib_init(); - sb_init(); - gus_init(); + speaker_init(); + sound_card_init(sound_card_current); + if (GUS) + device_add(&gus_device); + if (GAMEBLASTER) + device_add(&cms_device); pc_reset(); @@ -278,14 +313,14 @@ int sreadlnum,swritelnum,segareads,segawrites, scycles_lost; int serial_fifo_read, serial_fifo_write; int emu_fps = 0; - +extern int totaldiff; void runpc() { char s[200]; int done=0; clockrate = models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed; if (is386) exec386(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); - else if (AT) exec286(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); + else if (AT) exec386(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); else execx86(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); keyboard_poll_host(); keyboard_process(); @@ -320,10 +355,12 @@ void runpc() if (win_title_update) { win_title_update=0; - sprintf(s, "PCem v0.7 - %s - %s - %s - %i%% %i %04X %i", model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : "Press CTRL-END to release mouse", fps, et4000w32p_getclock(), ECX, ins); + sprintf(s, "PCem v0.7 - %s - %s - %s - %i%% - %i", model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : "Press CTRL-END to release mouse", fps, totaldiff); + totaldiff = 0; set_window_title(s); } done++; + frame++; /* if ((at70hz && VGA)!=oldat70hz) { oldat70hz=(at70hz && VGA); @@ -369,7 +406,6 @@ void closepc() // ioctl_close(); dumpegaregs(); dumppic(); - dumpgus(); // output=7; // setpitclock(clocks[0][0][0]); // while (1) runpc(); @@ -377,6 +413,7 @@ void closepc() savedisc(1); dumpregs(); closevideo(); + device_close_all(); } /*int main() @@ -398,94 +435,86 @@ void loadconfig() { char s[512]; char *p; - append_filename(s,pcempath,"pcem.cfg",511); + append_filename(s, pcempath, "pcem.cfg", 511); set_config_file(s); - ADLIB=get_config_int(NULL,"adlib",1); - GAMEBLASTER=get_config_int(NULL,"gameblaster",0); - FASTDISC=get_config_int(NULL,"fast_disc",1); + GAMEBLASTER = get_config_int(NULL, "gameblaster", 0); + GUS = get_config_int(NULL, "gus", 0); model = get_config_int(NULL, "model", 14); - pclog("Model %i\n", model); + romset = model_getromset(); cpu_manufacturer = get_config_int(NULL, "cpu_manufacturer", 0); cpu = get_config_int(NULL, "cpu", 0); - gfxcard=get_config_int(NULL,"gfxcard",0); + gfxcard = get_config_int(NULL, "gfxcard", 0); video_speed = get_config_int(NULL, "video_speed", 3); - sbtype=get_config_int(NULL,"sndcard",SB2); - pclog("Model1 %i\n", model); - p=(char *)get_config_string(NULL,"disc_a",""); - if (p) strcpy(discfns[0],p); - else strcpy(discfns[0],""); - pclog("Model2 %i\n", model); - p=(char *)get_config_string(NULL,"disc_b",""); - if (p) strcpy(discfns[1],p); - else strcpy(discfns[1],""); - pclog("Model3 %i\n", model); - mem_size=get_config_int(NULL,"mem_size",4); - cdrom_drive=get_config_int(NULL,"cdrom_drive",0); - cdrom_enabled=get_config_int(NULL,"cdrom_enabled",0); - - slowega=get_config_int(NULL,"slow_video",1); - cache=get_config_int(NULL,"cache",3); - cga_comp=get_config_int(NULL,"cga_composite",0); - - kb_win=get_config_int(NULL,"kb_win",0); - vid_resize=get_config_int(NULL,"vid_resize",0); -// cpuspeed=2; + sound_card_current = get_config_int(NULL, "sndcard", SB2); - hdc[0].spt=get_config_int(NULL,"hdc_sectors",0); - hdc[0].hpc=get_config_int(NULL,"hdc_heads",0); - hdc[0].tracks=get_config_int(NULL,"hdc_cylinders",0); + p = (char *)get_config_string(NULL, "disc_a", ""); + if (p) strcpy(discfns[0], p); + else strcpy(discfns[0], ""); + + p = (char *)get_config_string(NULL, "disc_b", ""); + if (p) strcpy(discfns[1], p); + else strcpy(discfns[1], ""); + + mem_size = get_config_int(NULL, "mem_size", 4); + cdrom_drive = get_config_int(NULL, "cdrom_drive", 0); + cdrom_enabled = get_config_int(NULL, "cdrom_enabled", 0); + + slowega = get_config_int(NULL, "slow_video", 1); + cache = get_config_int(NULL, "cache", 3); + cga_comp = get_config_int(NULL, "cga_composite", 0); + + kb_win = get_config_int(NULL, "kb_win", 0); + vid_resize = get_config_int(NULL, "vid_resize", 0); + + hdc[0].spt = get_config_int(NULL, "hdc_sectors", 0); + hdc[0].hpc = get_config_int(NULL, "hdc_heads", 0); + hdc[0].tracks = get_config_int(NULL, "hdc_cylinders", 0); p = (char *)get_config_string(NULL, "hdc_fn", ""); if (p) strcpy(ide_fn[0], p); else strcpy(ide_fn[0], ""); - hdc[1].spt=get_config_int(NULL,"hdd_sectors",0); - hdc[1].hpc=get_config_int(NULL,"hdd_heads",0); - hdc[1].tracks=get_config_int(NULL,"hdd_cylinders",0); + hdc[1].spt = get_config_int(NULL, "hdd_sectors", 0); + hdc[1].hpc = get_config_int(NULL, "hdd_heads", 0); + hdc[1].tracks = get_config_int(NULL, "hdd_cylinders", 0); p = (char *)get_config_string(NULL, "hdd_fn", ""); if (p) strcpy(ide_fn[1], p); else strcpy(ide_fn[1], ""); - pclog("Model4 %i\n", model); } void saveconfig() { - pclog("saveconfig\n"); config_new(); - pclog("config_new\n"); - set_config_int(NULL,"adlib",ADLIB); - pclog("sci 1\n"); - set_config_int(NULL,"gameblaster",GAMEBLASTER); - set_config_int(NULL,"fast_disc",FASTDISC); + set_config_int(NULL, "gameblaster", GAMEBLASTER); + set_config_int(NULL, "gus", GUS); set_config_int(NULL, "model", model); set_config_int(NULL, "cpu_manufacturer", cpu_manufacturer); set_config_int(NULL, "cpu", cpu); - set_config_int(NULL,"gfxcard",gfxcard); - set_config_int(NULL,"video_speed", video_speed); - set_config_int(NULL,"sndcard",sbtype); - set_config_int(NULL,"cpu_speed",cpuspeed); - set_config_int(NULL,"has_fpu",hasfpu); - set_config_int(NULL,"slow_video",slowega); - set_config_int(NULL,"cache",cache); - set_config_int(NULL,"cga_composite",cga_comp); - set_config_string(NULL,"disc_a",discfns[0]); - set_config_string(NULL,"disc_b",discfns[1]); - set_config_int(NULL,"mem_size",mem_size); - set_config_int(NULL,"cdrom_drive",cdrom_drive); - set_config_int(NULL,"cdrom_enabled",cdrom_enabled); - set_config_int(NULL,"kb_win",kb_win); - set_config_int(NULL,"vid_resize",vid_resize); + set_config_int(NULL, "gfxcard", gfxcard); + set_config_int(NULL, "video_speed", video_speed); + set_config_int(NULL, "sndcard", sound_card_current); + set_config_int(NULL, "cpu_speed", cpuspeed); + set_config_int(NULL, "has_fpu", hasfpu); + set_config_int(NULL, "slow_video", slowega); + set_config_int(NULL, "cache", cache); + set_config_int(NULL, "cga_composite", cga_comp); + set_config_string(NULL, "disc_a", discfns[0]); + set_config_string(NULL, "disc_b", discfns[1]); + set_config_int(NULL, "mem_size", mem_size); + set_config_int(NULL, "cdrom_drive", cdrom_drive); + set_config_int(NULL, "cdrom_enabled", cdrom_enabled); + set_config_int(NULL, "kb_win", kb_win); + set_config_int(NULL, "vid_resize", vid_resize); - set_config_int(NULL,"hdc_sectors",hdc[0].spt); - set_config_int(NULL,"hdc_heads",hdc[0].hpc); - set_config_int(NULL,"hdc_cylinders",hdc[0].tracks); + set_config_int(NULL, "hdc_sectors", hdc[0].spt); + set_config_int(NULL, "hdc_heads", hdc[0].hpc); + set_config_int(NULL, "hdc_cylinders", hdc[0].tracks); set_config_string(NULL, "hdc_fn", ide_fn[0]); - set_config_int(NULL,"hdd_sectors",hdc[1].spt); - set_config_int(NULL,"hdd_heads",hdc[1].hpc); - set_config_int(NULL,"hdd_cylinders",hdc[1].tracks); + set_config_int(NULL, "hdd_sectors", hdc[1].spt); + set_config_int(NULL, "hdd_heads", hdc[1].hpc); + set_config_int(NULL, "hdd_cylinders", hdc[1].tracks); set_config_string(NULL, "hdd_fn", ide_fn[1]); - pclog("saveconfig done\n"); } diff --git a/src/pci.c b/src/pci.c index 1c8d7b8..309edec 100644 --- a/src/pci.c +++ b/src/pci.c @@ -4,13 +4,12 @@ #include "pci.h" -void (*pci_card_write[32])(int func, int addr, uint8_t val); -uint8_t (*pci_card_read[32])(int func, int addr); +void (*pci_card_write[32])(int func, int addr, uint8_t val, void *priv); +uint8_t (*pci_card_read[32])(int func, int addr, void *priv); +void *pci_priv[32]; static int pci_index, pci_func, pci_card, pci_bus, pci_enable; -static uint8_t card_16[256]; -static uint8_t card_18[256]; -void pci_write(uint16_t port, uint8_t val) +void pci_write(uint16_t port, uint8_t val, void *priv) { switch (port) { @@ -32,16 +31,16 @@ void pci_write(uint16_t port, uint8_t val) if (!pci_enable) return; - pclog("PCI write bus %i card %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_index | (port & 3), val, CS, pc); +// pclog("PCI write bus %i card %i func %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), val, CS, pc); if (!pci_bus && pci_card_write[pci_card]) - pci_card_write[pci_card](pci_func, pci_index | (port & 3), val); + pci_card_write[pci_card](pci_func, pci_index | (port & 3), val, pci_priv[pci_card]); break; } } -uint8_t pci_read(uint16_t port) +uint8_t pci_read(uint16_t port, void *priv) { switch (port) { @@ -58,10 +57,10 @@ uint8_t pci_read(uint16_t port) if (!pci_enable) return 0xff; - pclog("PCI read bus %i card %i index %02X\n", pci_bus, pci_card, pci_index | (port & 3)); +// pclog("PCI read bus %i card %i func %i index %02X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3)); if (!pci_bus && pci_card_read[pci_card]) - return pci_card_read[pci_card](pci_func, pci_index | (port & 3)); + return pci_card_read[pci_card](pci_func, pci_index | (port & 3), pci_priv[pci_card]); return 0xff; } @@ -71,19 +70,20 @@ void pci_init() { int c; - io_sethandler(0x0cf8, 0x0008, pci_read, NULL, NULL, pci_write, NULL, NULL); + io_sethandler(0x0cf8, 0x0008, pci_read, NULL, NULL, pci_write, NULL, NULL, NULL); for (c = 0; c < 32; c++) - pci_card_read[c] = pci_card_write[c] = NULL; + pci_card_read[c] = pci_card_write[c] = pci_priv[c] = NULL; } -void pci_add_specific(int card, uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val)) +void pci_add_specific(int card, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv) { pci_card_read[card] = read; pci_card_write[card] = write; + pci_priv[card] = priv; } -void pci_add(uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val)) +void pci_add(uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv) { int c; @@ -93,6 +93,7 @@ void pci_add(uint8_t (*read)(int func, int addr), void (*write)(int func, int ad { pci_card_read[c] = read; pci_card_write[c] = write; + pci_priv[c] = priv; return; } } diff --git a/src/pci.h b/src/pci.h index 457f65a..eec1f33 100644 --- a/src/pci.h +++ b/src/pci.h @@ -1,3 +1,3 @@ void pci_init(); -void pci_add_specific(int card, uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val)); -void pci_add(uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val)); +void pci_add_specific(int card, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); +void pci_add(uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); diff --git a/src/pic.c b/src/pic.c index 76c2f59..924a482 100644 --- a/src/pic.c +++ b/src/pic.c @@ -1,14 +1,16 @@ #include "ibm.h" +#include "io.h" +#include "pic.h" int output; int intclear; int keywaiting=0; -int pit0; int pic_intpending; void pic_updatepending() { pic_intpending = (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2)); +// pclog("pic_intpending = %i %02X %02X %02X\n", pic_intpending, pic.pend, pic.mask, pic.mask2); } @@ -27,7 +29,7 @@ void pic_reset() pic_intpending = 0; } -void pic_write(uint16_t addr, uint8_t val) +void pic_write(uint16_t addr, uint8_t val, void *priv) { int c; // pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,pc); @@ -87,7 +89,6 @@ void pic_write(uint16_t addr, uint8_t val) pic.ins&=~(1<0xFF) { @@ -222,6 +225,7 @@ void picint(uint16_t num) { pic.pend|=num; } +// pclog("picint : PEND now %02X %02X\n", pic.pend, pic2.pend); pic_updatepending(); } @@ -248,7 +252,7 @@ void picintc(uint16_t num) { int c = 0; while (!(num & (1 << c))) c++; -// pclog("INTC %04X %i\n", num, c); + //pclog("INTC %04X %i\n", num, c); pic_current[c]=0; if (num>0xFF) pic2.pend&=~(num>>8); else @@ -270,6 +274,7 @@ uint8_t picinterrupt() pic.mask2|=(1< #include "ibm.h" -#include "pit.h" -#include "video.h" + #include "cpu.h" +#include "dma.h" +#include "io.h" +#include "pic.h" +#include "pit.h" +#include "timer.h" +#include "video.h" + /*B0 to 40, two writes to 43, then two reads - value does not change!*/ /*B4 to 40, two writes to 43, then two reads - value _does_ change!*/ //Tyrian writes 4300 or 17512 @@ -21,31 +27,25 @@ float isa_timing, bus_timing; int firsttime=1; void setpitclock(float clock) { - float temp; // printf("PIT clock %f\n",clock); cpuclock=clock; PITCONST=clock/1193182.0; - SPKCONST=clock/48000.0; CGACONST=(clock/(19687500.0/11.0)); MDACONST=(clock/1813000.0); VGACONST1=(clock/25175000.0); VGACONST2=(clock/28322000.0); - setsbclock(clock); - SOUNDCONST=clock/200.0; - CASCONST=PITCONST*1192; isa_timing = clock/8000000.0; bus_timing = clock/(double)cpu_busspeed; video_updatetiming(); // pclog("egacycles %i egacycles2 %i temp %f clock %f\n",egacycles,egacycles2,temp,clock); - GUSCONST=(clock/3125.0)/4.0; - GUSCONST2=(clock/3125.0)/4.0; //Timer 2 at different rate to 1? video_recalctimings(); RTCCONST=clock/32768.0; + TIMER_USEC = (int)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); + device_speed_changed(); } //#define PITCONST (8000000.0/1193000.0) //#define PITCONST (cpuclock/1193000.0) -int pit0; void pit_reset() { memset(&pit,0,sizeof(PIT)); @@ -69,12 +69,10 @@ float pit_timer0_freq() return 1193182.0f/(float)pit.l[0]; } extern int ins; -void pit_write(uint16_t addr, uint8_t val) +void pit_write(uint16_t addr, uint8_t val, void *priv) { int t; - uint8_t oldctrl=pit.ctrl; cycles -= (int)PITCONST; - pit0=1; // printf("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins); switch (addr&3) { @@ -135,13 +133,15 @@ void pit_write(uint16_t addr, uint8_t val) pit.l[t]=val; pit.thit[t]=0; pit.c[t]=pit.l[t]*PITCONST; - picintc(1); + if (!t) + picintc(1); break; case 2: pit.l[t]=(val<<8); pit.thit[t]=0; pit.c[t]=pit.l[t]*PITCONST; - picintc(1); + if (!t) + picintc(1); break; case 0: pit.l[t]&=0xFF; @@ -150,7 +150,8 @@ void pit_write(uint16_t addr, uint8_t val) // pclog("%04X %f\n",pit.l[t],pit.c[t]); pit.thit[t]=0; pit.wm[t]=3; - picintc(1); + if (!t) + picintc(1); break; case 3: pit.l[t]&=0xFF00; @@ -190,7 +191,7 @@ void pit_write(uint16_t addr, uint8_t val) } } -uint8_t pit_read(uint16_t addr) +uint8_t pit_read(uint16_t addr, void *priv) { uint8_t temp; cycles -= (int)PITCONST; @@ -250,8 +251,8 @@ void pit_poll() else pit.c[0]+=((float)(0x10000*PITCONST)); } // pit.c[0]+=(pit.l[0]*PITCONST); -// printf("PIT over! %f %i\n",pit.c[0],pit.m[0]); - if (!pit.thit[0] && (pit.l[0]>0x14)) +// if (output) printf("PIT over! %f %i\n",pit.c[0],pit.m[0]); + if (!pit.thit[0])// && (pit.l[0]>0x14)) { // printf("PIT int!\n"); /// printf("%05X %05X %02X\n",pit.c[0],pit.l[0],pit.ctrls[0]); @@ -259,7 +260,6 @@ void pit_poll() } if (!pit.m[0] || pit.m[0]==4) pit.thit[0]=1; // if ((pit.ctrls[0]&0xE)==2) pit.thit[0]=1; - pit0=0; pitcount++; } if (pit.c[1]<1) @@ -301,5 +301,5 @@ void pit_poll() void pit_init() { - io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL); + io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL, NULL); } diff --git a/src/resources.h b/src/resources.h index b718a20..740c950 100644 --- a/src/resources.h +++ b/src/resources.h @@ -31,6 +31,7 @@ #define IDC_CHECK2 1011 #define IDC_CHECK3 1012 #define IDC_CHECK4 1013 +#define IDC_CHECKGUS 1014 #define IDC_STATIC 1020 #define IDC_EDIT1 1030 #define IDC_EDIT2 1031 diff --git a/src/serial.c b/src/serial.c index 294b536..69b3e7a 100644 --- a/src/serial.c +++ b/src/serial.c @@ -1,7 +1,9 @@ #include "ibm.h" #include "io.h" #include "mouse.h" +#include "pic.h" #include "serial.h" +#include "timer.h" SERIAL serial,serial2; @@ -48,7 +50,7 @@ void sendserial(uint8_t dat) serial.iir=4; } -void serial_write(uint16_t addr, uint8_t val) +void serial_write(uint16_t addr, uint8_t val, void *priv) { // printf("Write serial %03X %02X %04X:%04X\n",addr,val,CS,pc); switch (addr&7) @@ -89,7 +91,7 @@ void serial_write(uint16_t addr, uint8_t val) } } -uint8_t serial_read(uint16_t addr) +uint8_t serial_read(uint16_t addr, void *priv) { uint8_t temp; // printf("Read serial %03X %04X(%08X):%04X %i %i ", addr, CS, cs, pc, mousedelay, ins); @@ -104,7 +106,7 @@ uint8_t serial_read(uint16_t addr) if (serial_fifo_read != serial_fifo_write) { mousepos = 0; - mousedelay = 1000; + mousedelay = 5000 * (1 << TIMER_SHIFT); // pclog("Next FIFO\n"); } break; @@ -122,7 +124,7 @@ uint8_t serial_read(uint16_t addr) return temp; } -void serial2_write(uint16_t addr, uint8_t val) +void serial2_write(uint16_t addr, uint8_t val, void *priv) { // printf("Write serial2 %03X %02X %04X:%04X\n",addr,val,cs>>4,pc); switch (addr&7) @@ -156,7 +158,7 @@ void serial2_write(uint16_t addr, uint8_t val) } } -uint8_t serial2_read(uint16_t addr) +uint8_t serial2_read(uint16_t addr, void *priv) { uint8_t temp; // printf("Read serial2 %03X %04X:%04X\n",addr,cs>>4,pc); @@ -186,25 +188,25 @@ uint8_t serial2_read(uint16_t addr) /*Tandy might need COM1 at 2f8*/ void serial1_init(uint16_t addr) { - io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); + io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL); serial_rcr = NULL; } void serial1_remove() { - io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); - io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); - io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); - io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); + io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL); + io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL); + io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL); + io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL); } void serial2_init(uint16_t addr) { - io_sethandler(addr, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); + io_sethandler(addr, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL); } void serial2_remove() { - io_removehandler(0x2e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); - io_removehandler(0x2f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); - io_removehandler(0x3e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); - io_removehandler(0x3f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); + io_removehandler(0x2e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL); + io_removehandler(0x2f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL); + io_removehandler(0x3e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL); + io_removehandler(0x3f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL); } diff --git a/src/sound.c b/src/sound.c index f196371..f771e96 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1,180 +1,146 @@ #include +#include #include "ibm.h" +#include "device.h" + #include "filters.h" -int soundon = 1; -int16_t *adbuffer,*adbuffer2; -int16_t *psgbuffer; -uint16_t *cmsbuffer; -int16_t *spkbuffer; -int16_t *outbuffer; -uint16_t *gusbuffer; +#include "sound_opl.h" -void initsound() +#include "sound.h" +#include "sound_adlib.h" +#include "sound_adlibgold.h" +#include "sound_pas16.h" +#include "sound_sb.h" +#include "sound_sb_dsp.h" +#include "sound_wss.h" + +#include "timer.h" + +int sound_card_current = 0; +static int sound_card_last = 0; + +typedef struct +{ + char name[32]; + device_t *device; +} SOUND_CARD; + +static SOUND_CARD sound_cards[] = +{ + {"None", NULL}, + {"Adlib", &adlib_device}, + {"Sound Blaster 1.0", &sb_1_device}, + {"Sound Blaster 1.5", &sb_15_device}, + {"Sound Blaster 2.0", &sb_2_device}, + {"Sound Blaster Pro v1", &sb_pro_v1_device}, + {"Sound Blaster Pro v2", &sb_pro_v1_device}, + {"Sound Blaster 16", &sb_16_device}, + {"Adlib Gold", &adgold_device}, + {"Windows Sound System", &wss_device}, + {"Pro Audio Spectrum 16", &pas16_device}, + {"", NULL} +}; + +char *sound_card_getname(int card) +{ + return sound_cards[card].name; +} + +void sound_card_init() +{ + if (sound_cards[sound_card_current].device) + device_add(sound_cards[sound_card_current].device); + sound_card_last = sound_card_current; +} + +static struct +{ + void (*poll)(void *p); + void (*get_buffer)(int16_t *buffer, int len, void *p); + void *priv; +} sound_handlers[8]; + +static int sound_handlers_num; + +static int sound_poll_time = 0, sound_get_buffer_time = 0; + +int soundon = 1; + + +static int16_t cd_buffer[SOUNDBUFLEN * 2]; + +void sound_cd_poll(void *p) +{ +} + +void sound_cd_get_buffer(int16_t *buffer, int len, void *p) +{ + int pos, c; + ioctl_audio_callback(cd_buffer, (len * 2 * 441) / 480); + pos = 0; + + for (c = 0; c < len * 2; c+=2) + { + buffer[c] += cd_buffer[((pos >> 16) << 1)] / 2; + buffer[c + 1] += cd_buffer[((pos >> 16) << 1) + 1] / 2; + pos += 60211; //(44100 * 65536) / 48000; + } +} + +static uint16_t *outbuffer; + +void sound_init() { initalmain(0,NULL); inital(); -// install_sound(DIGI_AUTODETECT,MIDI_NONE,0); -// as=play_audio_stream(SOUNDBUFLEN,16,1,48000,255,128); - adbuffer=malloc((SOUNDBUFLEN)*2); - adbuffer2=malloc((SOUNDBUFLEN)*2); - psgbuffer=malloc((SOUNDBUFLEN)*2); - cmsbuffer=malloc((SOUNDBUFLEN)*2*2); - gusbuffer=malloc((SOUNDBUFLEN)*2*2); - spkbuffer=malloc(((SOUNDBUFLEN)*2)+32); - outbuffer=malloc((SOUNDBUFLEN)*2*2); + + outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int16_t)); + + sound_add_handler(sound_cd_poll, sound_cd_get_buffer, NULL); } -int adpoll=0; -void pollad() +void sound_add_handler(void (*poll)(void *p), void (*get_buffer)(int16_t *buffer, int len, void *p), void *p) { -/* if (adpoll>=20) return; - getadlibl(adbuffer+(adpoll*(48000/200)),48000/200); - getadlibr(adbuffer2+(adpoll*(48000/200)),48000/200); - adpoll++;*/ -// printf("ADPOLL %i\n",adpoll); + sound_handlers[sound_handlers_num].poll = poll; + sound_handlers[sound_handlers_num].get_buffer = get_buffer; + sound_handlers[sound_handlers_num].priv = p; + sound_handlers_num++; } -void polladlib() +void sound_poll(void *priv) { - getadlib(adbuffer+(adpoll),adbuffer2+(adpoll),1); - adpoll++; -} + int c; -int psgpoll=0; -void pollpsg() -{ - if (psgpoll>=20) return; - getpsg(psgbuffer+(psgpoll*(48000/200)),48000/200); - psgpoll++; -} - -int cmspoll=0; -void pollcms() -{ - if (cmspoll>=20) return; - getcms(cmsbuffer+(cmspoll*(48000/200)*2),48000/200); - cmspoll++; -} - -int guspoll=0; -void pollgussnd() -{ - if (guspoll>=20) return; - getgus(gusbuffer+(guspoll*(48000/200)*2),48000/200); - guspoll++; -} - -int spkpos=0; -int wasgated = 0; -void pollspk() -{ - if (spkpos>=SOUNDBUFLEN) return; -// printf("SPeaker - %i %i %i %02X\n",speakval,gated,speakon,pit.m[2]); - if (gated) - { - if (!pit.m[2] || pit.m[2]==4) - spkbuffer[spkpos]=speakval; - else - spkbuffer[spkpos]=(speakon)?0x1400:0; - } - else - spkbuffer[spkpos]=(wasgated)?0x1400:0; - spkpos++; - wasgated=0; + sound_poll_time += (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); + + for (c = 0; c < sound_handlers_num; c++) + sound_handlers[c].poll(sound_handlers[c].priv); } FILE *soundf; -static int16_t cd_buffer[(SOUNDBUFLEN) * 2]; -void pollsound() +void sound_get_buffer(void *priv) { int c; - int16_t t[4]; - uint32_t pos; -// printf("Pollsound! %i\n",soundon); -// if (soundon) -// { - for (c=0;c<(SOUNDBUFLEN);c++) outbuffer[c<<1]=outbuffer[(c<<1)+1]=0; - for (c=0;c<(SOUNDBUFLEN);c++) - { - outbuffer[c<<1]+=((adbuffer[c]*mixer.fm_l)>>16); - outbuffer[(c<<1)+1]+=((adbuffer[c]*mixer.fm_r)>>16); -// if (!c) pclog("F %04X %04X %04X\n",adbuffer[c],outbuffer[c<<1],mixer.fm_l); - } - addsb(outbuffer); - for (c=0;c<(SOUNDBUFLEN);c++) - { -// if (!c) pclog("M %04X ",outbuffer[c<<1]); - outbuffer[c<<1]=(outbuffer[c<<1]*mixer.master_l)>>16; - outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]*mixer.master_r)>>16; -// if (!c) pclog("%04X %04X\n",outbuffer[c<<1],mixer.master_l); - } - if (mixer.bass_l!=8 || mixer.bass_r!=8 || mixer.treble_l!=8 || mixer.treble_r!=8) - { - for (c=0;c<(SOUNDBUFLEN);c++) - { - if (mixer.bass_l>8) outbuffer[c<<1] =(outbuffer[c<<1] +(((int16_t)low_iir(0,(float)outbuffer[c<<1]) *(mixer.bass_l-8))>>1))*((15-mixer.bass_l)+16)>>5; - if (mixer.bass_r>8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)low_iir(1,(float)outbuffer[(c<<1)+1]) *(mixer.bass_r-8))>>1))*((15-mixer.bass_r)+16)>>5; - if (mixer.treble_l>8) outbuffer[c<<1] =(outbuffer[c<<1] +(((int16_t)high_iir(0,(float)outbuffer[c<<1]) *(mixer.treble_l-8))>>1))*((15-mixer.treble_l)+16)>>5; - if (mixer.treble_r>8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)high_iir(1,(float)outbuffer[(c<<1)+1]) *(mixer.treble_r-8))>>1))*((15-mixer.treble_r)+16)>>5; - if (mixer.bass_l<8) outbuffer[c<<1] =(outbuffer[c<<1] +(((int16_t)low_cut_iir(0,(float)outbuffer[c<<1]) *(8-mixer.bass_l))>>1))*(mixer.bass_l+16)>>5; - if (mixer.bass_r<8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)low_cut_iir(1,(float)outbuffer[(c<<1)+1]) *(8-mixer.bass_r))>>1))*(mixer.bass_r+16)>>5; - if (mixer.treble_l<8) outbuffer[c<<1] =(outbuffer[c<<1] +(((int16_t)high_cut_iir(0,(float)outbuffer[c<<1]) *(8-mixer.treble_l))>>1))*(mixer.treble_l+16)>>5; - if (mixer.treble_r<8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)high_cut_iir(1,(float)outbuffer[(c<<1)+1])*(8-mixer.treble_r))>>1))*(mixer.treble_r+16)>>5; - } - } - for (c=0;c<(SOUNDBUFLEN);c++) - { - outbuffer[c<<1]+=(spkbuffer[c]/2); - outbuffer[(c<<1)+1]+=(spkbuffer[c]/2); - } - for (c=0;c<(SOUNDBUFLEN);c++) - { - outbuffer[c<<1]+=(psgbuffer[c]/2); - outbuffer[(c<<1)+1]+=(psgbuffer[c]/2); - } - for (c=0;c<((SOUNDBUFLEN)*2);c++) - outbuffer[c]+=(cmsbuffer[c]/2); - for (c=0;c<((SOUNDBUFLEN)*2);c++) - outbuffer[c]+=(gusbuffer[c]); - adddac(outbuffer); - ioctl_audio_callback(cd_buffer, ((SOUNDBUFLEN) * 2 * 441) / 480); - pos = 0; - for (c = 0; c < (SOUNDBUFLEN) * 2; c+=2) - { - outbuffer[c] += cd_buffer[((pos >> 16) << 1)] / 2; - outbuffer[c + 1] += cd_buffer[((pos >> 16) << 1) + 1] / 2; -// outbuffer[c] += (int16_t)((int32_t)cd_buffer[pos >> 16] * (65536 - (pos & 0xffff))) / 65536; -// outbuffer[c] += (int16_t)((int32_t)cd_buffer[(pos >> 16) + 1] * (pos & 0xffff)) / 65536; - pos += 60211; //(44100 * 65536) / 48000; - } - -// if (!soundf) soundf=fopen("sound.pcm","wb"); -// fwrite(outbuffer,(SOUNDBUFLEN)*2*2,1,soundf); - if (soundon) givealbuffer(outbuffer); -// } -// addsb(outbuffer); -// adddac(outbuffer); - adpoll=0; - psgpoll=0; - cmspoll=0; - spkpos=0; - guspoll=0; + + sound_get_buffer_time += (TIMER_USEC * (1000000 / 10)); + + memset(outbuffer, 0, SOUNDBUFLEN * 2 * sizeof(int16_t)); + + for (c = 0; c < sound_handlers_num; c++) + sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv); + +/* if (!soundf) soundf=fopen("sound.pcm","wb"); + fwrite(outbuffer,(SOUNDBUFLEN)*2*2,1,soundf);*/ + + if (soundon) givealbuffer(outbuffer); } -int sndcount; -void pollsound60hz() +void sound_reset() { -// printf("Poll sound %i\n",sndcount); -// pollad(); - pollpsg(); - pollcms(); - pollgussnd(); - sndcount++; - if (sndcount==20) - { - sndcount=0; - pollsound(); - } + timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(sound_get_buffer, &sound_get_buffer_time, TIMER_ALWAYS_ENABLED, NULL); + + sound_handlers_num = 0; } diff --git a/src/sound.h b/src/sound.h index 2bdff7c..af0f0d3 100644 --- a/src/sound.h +++ b/src/sound.h @@ -1 +1,9 @@ +void sound_add_handler(void (*poll)(void *p), void (*get_buffer)(int16_t *buffer, int len, void *p), void *p); + extern int wasgated; +extern int sbtype; + +extern int sound_card_current; + +char *sound_card_getname(int card); +void sound_card_init(); diff --git a/src/soundopenal.c b/src/soundopenal.c index 6bd8d6d..ecad5b2 100644 --- a/src/soundopenal.c +++ b/src/soundopenal.c @@ -1,6 +1,7 @@ #define USE_OPENAL #include #include +#include #ifdef USE_OPENAL #include #include @@ -91,7 +92,6 @@ void givealbuffer(int16_t *buf) #ifdef USE_OPENAL int processed; int state; - int c; //return; diff --git a/src/um8881f.c b/src/um8881f.c index e2bffc1..0f9aa7a 100644 --- a/src/um8881f.c +++ b/src/um8881f.c @@ -1,22 +1,23 @@ #include "ibm.h" #include "io.h" #include "mem.h" +#include "pci.h" #include "um8881f.h" static uint8_t card_16[256]; static uint8_t card_18[256]; -void um8881f_write(int func, int addr, uint8_t val) +void um8881f_write(int func, int addr, uint8_t val, void *priv) { if (addr == 0x54) { if ((card_16[0x54] ^ val) & 0x01) { if (val & 1) - mem_sethandler(0xe0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); + mem_sethandler(0xe0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); else - mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL ); + mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL , NULL); } flushmmucache_nopc(); } @@ -26,10 +27,10 @@ void um8881f_write(int func, int addr, uint8_t val) { switch (val & 0xc0) { - case 0x00: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); break; - case 0x40: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL ); break; - case 0x80: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); break; - case 0xc0: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL ); break; + case 0x00: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); break; + case 0x40: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL , NULL); break; + case 0x80: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); break; + case 0xc0: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL , NULL); break; } shadowbios = val & 0x80; shadowbios_write = !(val & 0x40); @@ -40,18 +41,18 @@ void um8881f_write(int func, int addr, uint8_t val) card_16[addr] = val; } -uint8_t um8881f_read(int func, int addr) +uint8_t um8881f_read(int func, int addr, void *priv) { return card_16[addr]; } -void um8886f_write(int func, int addr, uint8_t val) +void um8886f_write(int func, int addr, uint8_t val, void *priv) { if (addr >= 4) card_18[addr] = val; } -uint8_t um8886f_read(int func, int addr) +uint8_t um8886f_read(int func, int addr, void *priv) { return card_18[addr]; } @@ -60,8 +61,8 @@ uint8_t um8886f_read(int func, int addr) void um8881f_init() { - pci_add_specific(16, um8881f_read, um8881f_write); - pci_add_specific(18, um8886f_read, um8886f_write); + pci_add_specific(16, um8881f_read, um8881f_write, NULL); + pci_add_specific(18, um8886f_read, um8886f_write, NULL); card_16[0] = card_18[0] = 0x60; /*UMC*/ card_16[1] = card_18[1] = 0x10; diff --git a/src/vid_cga.c b/src/vid_cga.c index 054894f..662a38f 100644 --- a/src/vid_cga.c +++ b/src/vid_cga.c @@ -1,8 +1,15 @@ /*CGA emulation*/ +#include #include "ibm.h" +#include "io.h" +#include "mem.h" +#include "timer.h" #include "video.h" +#include "vid_cga.h" -void cga_out(uint16_t addr, uint8_t val) +void cga_recalctimings(); + +void cga_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; // pclog("CGA_OUT %04X %02X\n", addr, val); @@ -32,7 +39,7 @@ void cga_out(uint16_t addr, uint8_t val) } } -uint8_t cga_in(uint16_t addr) +uint8_t cga_in(uint16_t addr, void *priv) { // pclog("CGA_IN %04X\n", addr); switch (addr) @@ -49,7 +56,7 @@ uint8_t cga_in(uint16_t addr) extern uint8_t charbuffer[256]; -void cga_write(uint32_t addr, uint8_t val) +void cga_write(uint32_t addr, uint8_t val, void *priv) { // pclog("CGA_WRITE %04X %02X\n", addr, val); vram[addr&0x3FFF]=val; @@ -58,7 +65,7 @@ void cga_write(uint32_t addr, uint8_t val) cycles -= 4; } -uint8_t cga_read(uint32_t addr) +uint8_t cga_read(uint32_t addr, void *priv) { cycles -= 4; charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = vram[addr&0x3FFF]; @@ -69,22 +76,25 @@ uint8_t cga_read(uint32_t addr) void cga_recalctimings() { + double _dispontime, _dispofftime; pclog("Recalc - %i %i %i\n", crtc[0], crtc[1], cgamode & 1); if (cgamode&1) { disptime=crtc[0]+1; - dispontime=crtc[1]; + _dispontime=crtc[1]; } else { disptime=(crtc[0]+1)<<1; - dispontime=crtc[1]<<1; + _dispontime=crtc[1]<<1; } - dispofftime=disptime-dispontime; + _dispofftime=disptime-_dispontime; // printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]); - dispontime*=CGACONST; - dispofftime*=CGACONST; + _dispontime*=CGACONST; + _dispofftime*=CGACONST; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); + dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); } static int linepos,displine; @@ -92,7 +102,7 @@ static int sc,vc; static int cgadispon; static int con,coff,cursoron,cgablink; static int vsynctime,vadj; -static uint16_t ma,maback,ca; +static uint16_t ma,maback; static int oddeven = 0; static int ntsc_col[8][8]= @@ -117,7 +127,7 @@ void cga_poll() int x,c; int oldvc; uint8_t chr,attr; - uint16_t dat,dat2,dat3,dat4; + uint16_t dat; int cols[4]; int col; int oldsc; @@ -467,7 +477,7 @@ int cga_init() i_filt[c]=512.0*cos((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0); q_filt[c]=512.0*sin((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0); } - mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL); return 0; } diff --git a/src/vid_cga.h b/src/vid_cga.h index f847400..6e2afdc 100644 --- a/src/vid_cga.h +++ b/src/vid_cga.h @@ -1,7 +1,7 @@ int cga_init(); -void cga_out(uint16_t addr, uint8_t val); -uint8_t cga_in(uint16_t addr); +void cga_out(uint16_t addr, uint8_t val, void *priv); +uint8_t cga_in(uint16_t addr, void *priv); void cga_poll(); -void cga_write(uint32_t addr, uint8_t val); -uint8_t cga_read(uint32_t addr); +void cga_write(uint32_t addr, uint8_t val, void *priv); +uint8_t cga_read(uint32_t addr, void *priv); void cga_recalctimings(); diff --git a/src/vid_ega.c b/src/vid_ega.c index 2afe346..7b95438 100644 --- a/src/vid_ega.c +++ b/src/vid_ega.c @@ -1,10 +1,11 @@ /*EGA emulation*/ #include "ibm.h" +#include "io.h" +#include "mem.h" +#include "timer.h" #include "video.h" - -void ega_recalctimings(); -void ega_write(uint32_t addr, uint8_t val); -uint8_t ega_read(uint32_t addr); +#include "vid_ega.h" +#include "vid_svga.h" extern uint8_t edatlookup[4][4]; @@ -16,7 +17,7 @@ static uint8_t ega_rotate[8][256]; /*3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour)*/ int egaswitchread,egaswitches=9; /*7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines)*/ -void ega_out(uint16_t addr, uint8_t val) +void ega_out(uint16_t addr, uint8_t val, void *priv) { int c; uint8_t o,old; @@ -73,21 +74,21 @@ void ega_out(uint16_t addr, uint8_t val) case 4: readplane=val&3; break; case 5: writemode=val&3; readmode=val&8; break; case 6: - mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); // pclog("Write mapping %02X\n", val); switch (val&0xC) { case 0x0: /*128k at A0000*/ - mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); break; case 0x4: /*64k at A0000*/ - mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); break; case 0x8: /*32k at B0000*/ - mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); break; case 0xC: /*32k at B8000*/ - mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); break; } @@ -114,9 +115,8 @@ void ega_out(uint16_t addr, uint8_t val) } } -uint8_t ega_in(uint16_t addr) +uint8_t ega_in(uint16_t addr, void *priv) { - uint8_t temp; if ((addr&0xFFF0) == 0x3B0) addr |= 0x20; switch (addr) { @@ -161,8 +161,9 @@ static int scrollcache; void ega_recalctimings() { - float crtcconst; - int temp; + double _dispontime, _dispofftime; + double crtcconst; + ega_vtotal=crtc[6]; ega_dispend=crtc[0x12]; ega_vsyncstart=crtc[0x10]; @@ -195,14 +196,16 @@ void ega_recalctimings() else crtcconst=(seqregs[1]&1)?(CGACONST*(8.0/9.0)):CGACONST; disptime=crtc[0]+2; - dispontime=crtc[1]+1; + _dispontime=crtc[1]+1; - printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8); - if (seqregs[1]&8) { disptime*=2; dispontime*=2; } - dispofftime=disptime-dispontime; - dispontime*=crtcconst; - dispofftime*=crtcconst; + printf("Disptime %f dispontime %f hdisp %i\n",disptime,_dispontime,crtc[1]*8); + if (seqregs[1]&8) { disptime*=2; _dispontime*=2; } + _dispofftime=disptime-_dispontime; + _dispontime*=crtcconst; + _dispofftime*=crtcconst; + dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); // printf("EGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4)); // printf("EGA vert total %i display end %i max row %i vsync %i\n",ega_vtotal,ega_dispend,(crtc[9]&31)+1,ega_vsyncstart); @@ -525,11 +528,9 @@ void ega_poll() } -void ega_write(uint32_t addr, uint8_t val) +void ega_write(uint32_t addr, uint8_t val, void *priv) { - int x,y; - char s[2]={0,0}; - uint8_t vala,valb,valc,vald,wm=writemask; + uint8_t vala,valb,valc,vald; egawrites++; cycles -= video_timing_b; @@ -647,10 +648,9 @@ void ega_write(uint32_t addr, uint8_t val) } } -uint8_t ega_read(uint32_t addr) +uint8_t ega_read(uint32_t addr, void *priv) { uint8_t temp,temp2,temp3,temp4; - uint32_t addr2; egareads++; cycles -= video_timing_b; cycles_lost += video_timing_b; diff --git a/src/vid_ega.h b/src/vid_ega.h index 6258e7c..ea8c286 100644 --- a/src/vid_ega.h +++ b/src/vid_ega.h @@ -1,7 +1,7 @@ int ega_init(); -void ega_out(uint16_t addr, uint8_t val); -uint8_t ega_in(uint16_t addr); +void ega_out(uint16_t addr, uint8_t val, void *priv); +uint8_t ega_in(uint16_t addr, void *priv); void ega_poll(); void ega_recalctimings(); -void ega_write(uint32_t addr, uint8_t val); -uint8_t ega_read(uint32_t addr); +void ega_write(uint32_t addr, uint8_t val, void *priv); +uint8_t ega_read(uint32_t addr, void *priv); diff --git a/src/vid_et4000.c b/src/vid_et4000.c index e4259a6..a2966b8 100644 --- a/src/vid_et4000.c +++ b/src/vid_et4000.c @@ -1,5 +1,6 @@ /*ET4000 emulation*/ #include "ibm.h" +#include "io.h" #include "video.h" #include "vid_svga.h" #include "vid_unk_ramdac.h" @@ -7,7 +8,7 @@ int et4k_b8000; -void et4000_out(uint16_t addr, uint8_t val) +void et4000_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; @@ -18,7 +19,7 @@ void et4000_out(uint16_t addr, uint8_t val) switch (addr) { case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - unk_ramdac_out(addr,val); + unk_ramdac_out(addr, val, NULL); return; case 0x3CD: /*Banking*/ @@ -57,13 +58,11 @@ void et4000_out(uint16_t addr, uint8_t val) if (val==0x29) svgaon=0; break; } - svga_out(addr,val); + svga_out(addr, val, priv); } -uint8_t et4000_in(uint16_t addr) +uint8_t et4000_in(uint16_t addr, void *priv) { - uint8_t temp; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr); @@ -75,7 +74,7 @@ uint8_t et4000_in(uint16_t addr) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return unk_ramdac_in(addr); + return unk_ramdac_in(addr, NULL); case 0x3CD: /*Banking*/ return svgaseg; @@ -84,7 +83,7 @@ uint8_t et4000_in(uint16_t addr) case 0x3D5: return crtc[crtcreg]; } - return svga_in(addr); + return svga_in(addr, priv); } void et4000_recalctimings() @@ -98,6 +97,7 @@ void et4000_recalctimings() // if (crtc[0x3F]&0x80) svga_rowoffset+=0x100; if (crtc[0x3F]&1) svga_htotal+=256; if (attrregs[0x16]&0x20) svga_hdisp<<=1; + // pclog("Rowoffset %i\n",svga_rowoffset); switch (((svga_miscout >> 2) & 3) | ((crtc[0x34] << 1) & 4)) diff --git a/src/vid_et4000w32.c b/src/vid_et4000w32.c index 7e40ebd..47493c2 100644 --- a/src/vid_et4000w32.c +++ b/src/vid_et4000w32.c @@ -5,6 +5,8 @@ */ #include "ibm.h" +#include "io.h" +#include "pci.h" #include "video.h" #include "vid_svga.h" #include "vid_icd2061.h" @@ -15,14 +17,14 @@ int et4k_b8000; void et4000w32p_recalcmapping(); -uint8_t et4000w32p_mmu_read(uint32_t addr); -void et4000w32p_mmu_write(uint32_t addr, uint8_t val); +uint8_t et4000w32p_mmu_read(uint32_t addr, void *priv); +void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv); static int et4000w32p_index; static uint8_t et4000w32p_regs[256]; static uint32_t et4000w32p_linearbase, et4000w32p_linearbase_old; -void et4000w32p_out(uint16_t addr, uint8_t val) +void et4000w32p_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; @@ -39,7 +41,7 @@ void et4000w32p_out(uint16_t addr, uint8_t val) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - stg_ramdac_out(addr,val); + stg_ramdac_out(addr, val, NULL); return; case 0x3CB: /*Banking extension*/ @@ -111,10 +113,10 @@ void et4000w32p_out(uint16_t addr, uint8_t val) return; } - svga_out(addr,val); + svga_out(addr, val, NULL); } -uint8_t et4000w32p_in(uint16_t addr) +uint8_t et4000w32p_in(uint16_t addr, void *priv) { uint8_t temp; // if (addr==0x3DA) pclog("In 3DA %04X(%06X):%04X\n",CS,cs,pc); @@ -132,7 +134,7 @@ uint8_t et4000w32p_in(uint16_t addr) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return stg_ramdac_in(addr); + return stg_ramdac_in(addr, NULL); case 0x3CB: return svgaseg2; @@ -166,15 +168,14 @@ uint8_t et4000w32p_in(uint16_t addr) } return et4000w32p_regs[et4000w32p_index]; } - return svga_in(addr); + return svga_in(addr, NULL); } void et4000w32p_recalctimings() { - double clk; // pclog("Recalc %08X ",svga_ma); svga_ma|=(crtc[0x33]&0x7)<<16; - pclog("SVGA_MA %08X %i\n", svga_ma, (svga_miscout >> 2) & 3); +// pclog("SVGA_MA %08X %i\n", svga_ma, (svga_miscout >> 2) & 3); if (crtc[0x35]&2) svga_vtotal+=0x400; if (crtc[0x35]&4) svga_dispend+=0x400; if (crtc[0x35]&8) svga_vsyncstart+=0x400; @@ -205,12 +206,12 @@ void et4000w32p_recalcmapping() { int map; - mem_removehandler(et4000w32p_linearbase_old, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); - mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_removehandler(0xb0000, 0x10000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL); + mem_removehandler(et4000w32p_linearbase_old, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); + mem_removehandler( 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); + mem_removehandler( 0xb0000, 0x10000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL); if (crtc[0x36] & 0x10) /*Linear frame buffer*/ { - mem_sethandler(et4000w32p_linearbase, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); + mem_sethandler(et4000w32p_linearbase, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); } else { @@ -220,28 +221,28 @@ void et4000w32p_recalcmapping() switch (map) { case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/ - mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x1: /*64k at A0000*/ - mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x2: /*32k at B0000*/ - mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x3: /*32k at B8000*/ - mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x5: case 0x9: case 0xD: /*64k at A0000, MMU at B8000*/ - mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_sethandler(0xb8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL); + mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); + mem_sethandler(0xb8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL); break; case 0x6: case 0xA: case 0xE: /*32k at B0000, MMU at A8000*/ - mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL); - mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL); + mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x7: case 0xB: case 0xF: /*32k at B8000, MMU at A8000*/ - mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL); - mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; } // pclog("ET4K map %02X\n", map); @@ -295,7 +296,7 @@ void et4000w32_reset() void et4000w32_blit_start(); void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input); -void et4000w32p_mmu_write(uint32_t addr, uint8_t val) +void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv) { int bank; // pclog("ET4K write %08X %02X %02X %04X(%08X):%08X\n",addr,val,acl.status,acl.internal.ctrl_routing,CS,cs,pc); @@ -402,7 +403,7 @@ void et4000w32p_mmu_write(uint32_t addr, uint8_t val) } } -uint8_t et4000w32p_mmu_read(uint32_t addr) +uint8_t et4000w32p_mmu_read(uint32_t addr, void *priv) { int bank; uint8_t temp; @@ -482,6 +483,7 @@ uint8_t et4000w32p_mmu_read(uint32_t addr) } return 0xFF; } + return 0xff; } int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000}; @@ -846,7 +848,7 @@ void et4000w32p_cursor_draw(int displine) svga_hwcursor_latch.addr += 16; } -uint8_t et4000w32p_pci_read(int func, int addr) +uint8_t et4000w32p_pci_read(int func, int addr, void *priv) { pclog("ET4000 PCI read %08X\n", addr); switch (addr) @@ -880,7 +882,7 @@ uint8_t et4000w32p_pci_read(int func, int addr) return 0; } -void et4000w32p_pci_write(int func, int addr, uint8_t val) +void et4000w32p_pci_write(int func, int addr, uint8_t val, void *priv) { switch (addr) { @@ -893,16 +895,16 @@ int et4000w32p_init() svga_recalctimings_ex = et4000w32p_recalctimings; svga_hwcursor_draw = et4000w32p_cursor_draw; - io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); - io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); - io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); - io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); - io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); - io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); - io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); - io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); + io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL); + io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL); + io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL); + io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL); + io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL); + io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL); + io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL); + io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL); - pci_add(et4000w32p_pci_read, et4000w32p_pci_write); + pci_add(et4000w32p_pci_read, et4000w32p_pci_write, NULL); svga_vram_limit = 2 << 20; /*2mb - chip supports 4mb but can't map both 4mb linear frame buffer and accelerator registers*/ diff --git a/src/vid_hercules.c b/src/vid_hercules.c index 86a0414..6cc1826 100644 --- a/src/vid_hercules.c +++ b/src/vid_hercules.c @@ -1,15 +1,17 @@ /*Hercules emulation*/ #include "ibm.h" +#include "mem.h" +#include "timer.h" #include "video.h" void hercules_recalctimings(); -void hercules_write(uint32_t addr, uint8_t val); -uint8_t hercules_read(uint32_t addr); +void hercules_write(uint32_t addr, uint8_t val, void *priv); +uint8_t hercules_read(uint32_t addr, void *priv); static uint8_t hercules_ctrl, hercules_ctrl2, hercules_stat; uint8_t crtcm[32],crtcmreg; -void hercules_out(uint16_t addr, uint8_t val) +void hercules_out(uint16_t addr, uint8_t val, void *priv) { // pclog("Herc out %04X %02X\n",addr,val); switch (addr) @@ -37,7 +39,7 @@ void hercules_out(uint16_t addr, uint8_t val) } } -uint8_t hercules_in(uint16_t addr) +uint8_t hercules_in(uint16_t addr, void *priv) { // pclog("Herc in %04X %02X %04X:%04X %04X\n",addr,(hercules_stat & 0xF) | ((hercules_stat & 8) << 4),CS,pc,CX); switch (addr) @@ -49,33 +51,37 @@ uint8_t hercules_in(uint16_t addr) case 0x3BA: return (hercules_stat & 0xF) | ((hercules_stat & 8) << 4); } + return 0xff; } -void hercules_write(uint32_t addr, uint8_t val) +void hercules_write(uint32_t addr, uint8_t val, void *priv) { // pclog("Herc write %08X %02X\n",addr,val); vram[addr&0xFFFF]=val; } -uint8_t hercules_read(uint32_t addr) +uint8_t hercules_read(uint32_t addr, void *priv) { return vram[addr&0xFFFF]; } void hercules_recalctimings() { + double _dispontime, _dispofftime; disptime=crtc[0]+1; - dispontime=crtc[1]; - dispofftime=disptime-dispontime; - dispontime*=MDACONST; - dispofftime*=MDACONST; + _dispontime=crtc[1]; + _dispofftime=disptime-_dispontime; + _dispontime*=MDACONST; + _dispofftime*=MDACONST; + dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); } int mdacols[256][2][2]; static int linepos,displine; static int vc,sc; -static uint16_t ma,maback,ca; +static uint16_t ma,maback; static int con,coff,cursoron; static int cgadispon,cgablink; static int vsynctime,vadj; @@ -87,9 +93,8 @@ void hercules_poll() int x,c; int oldvc; uint8_t chr,attr; - uint16_t dat,dat2,dat3,dat4; + uint16_t dat; int cols[4]; - int col; int oldsc; int blink; if (!linepos) @@ -264,7 +269,7 @@ void hercules_poll() int hercules_init() { - mem_sethandler(0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL); + mem_sethandler(0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL); return 0; } diff --git a/src/vid_mda.c b/src/vid_mda.c index 2fb6aa0..42c2ed4 100644 --- a/src/vid_mda.c +++ b/src/vid_mda.c @@ -1,5 +1,8 @@ /*MDA emulation*/ #include "ibm.h" +#include "io.h" +#include "mem.h" +#include "timer.h" #include "video.h" void mda_recalctimings(); @@ -7,7 +10,7 @@ void mda_recalctimings(); static uint8_t mda_ctrl,mda_stat; uint8_t crtcm[32],crtcmreg; -void mda_out(uint16_t addr, uint8_t val) +void mda_out(uint16_t addr, uint8_t val, void *priv) { switch (addr) { @@ -29,7 +32,7 @@ void mda_out(uint16_t addr, uint8_t val) } } -uint8_t mda_in(uint16_t addr) +uint8_t mda_in(uint16_t addr, void *priv) { switch (addr) { @@ -40,32 +43,36 @@ uint8_t mda_in(uint16_t addr) case 0x3BA: return mda_stat | 0xF0; } + return 0xff; } -void mda_write(uint32_t addr, uint8_t val) +void mda_write(uint32_t addr, uint8_t val, void *priv) { vram[addr&0xFFF]=val; } -uint8_t mda_read(uint32_t addr) +uint8_t mda_read(uint32_t addr, void *priv) { return vram[addr&0xFFF]; } void mda_recalctimings() { + double _dispontime, _dispofftime; disptime=crtc[0]+1; - dispontime=crtc[1]; - dispofftime=disptime-dispontime; - dispontime*=MDACONST; - dispofftime*=MDACONST; + _dispontime=crtc[1]; + _dispofftime=disptime-_dispontime; + _dispontime*=MDACONST; + _dispofftime*=MDACONST; + dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); } int mdacols[256][2][2]; static int linepos,displine; static int vc,sc; -static uint16_t ma,maback,ca; +static uint16_t ma,maback; static int con,coff,cursoron; static int cgadispon,cgablink; static int vsynctime,vadj; @@ -77,9 +84,7 @@ void mda_poll() int x,c; int oldvc; uint8_t chr,attr; - uint16_t dat,dat2,dat3,dat4; int cols[4]; - int col; int oldsc; int blink; if (!linepos) @@ -227,7 +232,7 @@ void mda_poll() int mda_init() { - mem_sethandler(0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL); + mem_sethandler(0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL); return 0; } diff --git a/src/vid_olivetti_m24.c b/src/vid_olivetti_m24.c index 9b63ba4..3097ebd 100644 --- a/src/vid_olivetti_m24.c +++ b/src/vid_olivetti_m24.c @@ -1,12 +1,17 @@ /*Olivetti M24 video emulation Essentially double-res CGA*/ #include "ibm.h" +#include "io.h" +#include "mem.h" +#include "timer.h" #include "video.h" +void m24_recalctimings(); + static uint8_t m24_ctrl; static uint32_t m24_base; -void m24_out(uint16_t addr, uint8_t val) +void m24_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; switch (addr) @@ -39,7 +44,7 @@ void m24_out(uint16_t addr, uint8_t val) } } -uint8_t m24_in(uint16_t addr) +uint8_t m24_in(uint16_t addr, void *priv) { switch (addr) { @@ -55,35 +60,38 @@ uint8_t m24_in(uint16_t addr) static uint8_t charbuffer[256]; -void m24_write(uint32_t addr, uint8_t val) +void m24_write(uint32_t addr, uint8_t val, void *priv) { vram[addr & 0x7FFF]=val; charbuffer[ ((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val; charbuffer[(((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val; } -uint8_t m24_read(uint32_t addr) +uint8_t m24_read(uint32_t addr, void *priv) { return vram[addr & 0x7FFF]; } void m24_recalctimings() { + double _dispontime, _dispofftime; if (cgamode & 1) { disptime = crtc[0] + 1; - dispontime = crtc[1]; + _dispontime = crtc[1]; } else { disptime = (crtc[0] + 1) << 1; - dispontime = crtc[1] << 1; + _dispontime = crtc[1] << 1; } - dispofftime = disptime - dispontime; + _dispofftime = disptime - _dispontime; // printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]); - dispontime *= CGACONST / 2; - dispofftime *= CGACONST / 2; + _dispontime *= CGACONST / 2; + _dispofftime *= CGACONST / 2; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); + dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); } static int linepos,displine; @@ -92,7 +100,7 @@ static int cgadispon; static int con,coff,cursoron,cgablink; static int vsynctime,vadj; static int m24_lineff = 0; -static uint16_t ma,maback,ca; +static uint16_t ma,maback; void m24_poll() { @@ -101,7 +109,7 @@ void m24_poll() int x,c; int oldvc; uint8_t chr,attr; - uint16_t dat,dat2,dat3,dat4; + uint16_t dat,dat2; int cols[4]; int col; int oldsc; @@ -401,7 +409,7 @@ endblit(); int m24_init() { - mem_sethandler(0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL, NULL); return 0; } diff --git a/src/vid_oti067.c b/src/vid_oti067.c index 06688cf..d36fc07 100644 --- a/src/vid_oti067.c +++ b/src/vid_oti067.c @@ -1,16 +1,19 @@ /*Oak OTI067 emulation*/ #include "ibm.h" +#include "io.h" #include "video.h" #include "vid_svga.h" static int oti067_index; static uint8_t oti067_regs[32]; -void oti067_out(uint16_t addr, uint8_t val) +void oti067_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; - - if ((addr&0xFFF0) == 0x3B0) addr |= 0x20; + +// pclog("oti067_out : %04X %02X %02X %i\n", addr, val, ram[0x489], ins); + + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga_miscout&1)) addr ^= 0x60; switch (addr) { @@ -46,28 +49,41 @@ void oti067_out(uint16_t addr, uint8_t val) } return; } - svga_out(addr,val); + svga_out(addr, val, NULL); } -uint8_t oti067_in(uint16_t addr) +uint8_t oti067_in(uint16_t addr, void *priv) { uint8_t temp; - if ((addr&0xFFF0) == 0x3B0) addr |= 0x20; +// if (addr != 0x3da && addr != 0x3ba) pclog("oti067_in : %04X ", addr); + + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga_miscout&1)) addr ^= 0x60; switch (addr) { case 0x3D4: - return crtcreg; + temp = crtcreg; + break; case 0x3D5: - return crtc[crtcreg]; - case 0x3DE: return oti067_index|(2<<5); + temp = crtc[crtcreg]; + break; + + case 0x3DE: + temp = oti067_index|(2<<5); + break; case 0x3DF: - if (oti067_index==0x10) return 0x40; - if (oti067_index==0xD) return oti067_regs[oti067_index]|0xC0; - return oti067_regs[oti067_index]; + if (oti067_index==0x10) temp = 0x18; + else if (oti067_index==0xD) temp = oti067_regs[oti067_index]|0xC0; + else temp = oti067_regs[oti067_index]; + break; + + default: + temp = svga_in(addr, NULL); + break; } - return svga_in(addr); +// if (addr != 0x3da && addr != 0x3ba) pclog("%02X %04X:%04X\n", temp, CS,pc); + return temp; } void oti067_recalctimings() @@ -82,6 +98,8 @@ int oti067_init() svga_recalctimings_ex = oti067_recalctimings; svga_vram_limit = 1 << 19; /*512kb*/ vrammask = 0x7ffff; + bpp = 8; + svga_miscout = 1; return svga_init(); } diff --git a/src/vid_paradise.c b/src/vid_paradise.c index c3cc813..b7fd63a 100644 --- a/src/vid_paradise.c +++ b/src/vid_paradise.c @@ -4,12 +4,14 @@ MegaPC uses W90C11A */ #include "ibm.h" +#include "mem.h" #include "video.h" #include "vid_svga.h" #include "vid_unk_ramdac.h" -void paradise_write(uint32_t addr, uint8_t val); -uint8_t paradise_read(uint32_t addr); +void paradise_write(uint32_t addr, uint8_t val, void *priv); +uint8_t paradise_read(uint32_t addr, void *priv); +void paradise_remap(); enum { @@ -21,7 +23,7 @@ static int paradise_type; static uint32_t paradise_bank_r[4], paradise_bank_w[4]; -void paradise_out(uint16_t addr, uint8_t val) +void paradise_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; @@ -52,21 +54,21 @@ void paradise_out(uint16_t addr, uint8_t val) { if ((gdcreg[6] & 0xc) != (val & 0xc)) { - mem_removehandler(0xa0000, 0x20000, paradise_read, NULL, NULL, svga_write, NULL, NULL); + mem_removehandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL); // pclog("Write mapping %02X\n", val); switch (val&0xC) { case 0x0: /*128k at A0000*/ - mem_sethandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL); + mem_sethandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL); break; case 0x4: /*64k at A0000*/ - mem_sethandler(0xa0000, 0x10000, paradise_read, NULL, NULL, paradise_write, NULL, NULL); + mem_sethandler(0xa0000, 0x10000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL); break; case 0x8: /*32k at B0000*/ - mem_sethandler(0xb0000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL); + mem_sethandler(0xb0000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL); break; case 0xC: /*32k at B8000*/ - mem_sethandler(0xb8000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL); break; } } @@ -114,13 +116,11 @@ void paradise_out(uint16_t addr, uint8_t val) } break; } - svga_out(addr,val); + svga_out(addr, val, NULL); } -uint8_t paradise_in(uint16_t addr) +uint8_t paradise_in(uint16_t addr, void *priv) { - uint8_t temp; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; // if (addr != 0x3da) pclog("Paradise in %04X\n", addr); @@ -157,7 +157,7 @@ uint8_t paradise_in(uint16_t addr) return 0xff; return crtc[crtcreg]; } - return svga_in(addr); + return svga_in(addr, NULL); } void paradise_remap() @@ -185,8 +185,8 @@ void paradise_remap() // pclog("Remap 3\n"); paradise_bank_r[0] = paradise_bank_w[0] = (gdcreg[0xa] & 0x7f) << 12; paradise_bank_r[1] = paradise_bank_w[1] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise_bank_w[2] = paradise_bank_w[2] = (gdcreg[0x9] & 0x7f) << 12; - paradise_bank_w[3] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise_bank_r[2] = paradise_bank_w[2] = (gdcreg[0x9] & 0x7f) << 12; + paradise_bank_r[3] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); } } else @@ -207,20 +207,20 @@ void paradise_recalctimings() #define egacycles 1 #define egacycles2 1 -void paradise_write(uint32_t addr, uint8_t val) +void paradise_write(uint32_t addr, uint8_t val, void *priv) { // pclog("paradise_write : %05X %02X ", addr, val); addr = (addr & 0x7fff) + paradise_bank_w[(addr >> 15) & 3]; // pclog("%08X\n", addr); - svga_write_linear(addr, val); + svga_write_linear(addr, val, priv); } -uint8_t paradise_read(uint32_t addr) +uint8_t paradise_read(uint32_t addr, void *priv) { // pclog("paradise_read : %05X ", addr); addr = (addr & 0x7fff) + paradise_bank_r[(addr >> 15) & 3]; // pclog("%08X\n", addr); - return svga_read_linear(addr); + return svga_read_linear(addr, priv); } int paradise_init() diff --git a/src/vid_pc1512.c b/src/vid_pc1512.c index e03cf21..de0c01e 100644 --- a/src/vid_pc1512.c +++ b/src/vid_pc1512.c @@ -8,6 +8,9 @@ and 46 cycles. PCem currently always uses the lower number.*/ #include "ibm.h" +#include "io.h" +#include "mem.h" +#include "timer.h" #include "video.h" #include "vid_cga.h" @@ -15,7 +18,7 @@ static uint8_t pc1512_plane_write,pc1512_plane_read,pc1512_border; void pc1512_recalctimings(); -void pc1512_out(uint16_t addr, uint8_t val) +void pc1512_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; // pclog("PC1512 out %04X %02X %04X:%04X\n",addr,val,CS,pc); @@ -59,7 +62,7 @@ void pc1512_out(uint16_t addr, uint8_t val) } } -uint8_t pc1512_in(uint16_t addr) +uint8_t pc1512_in(uint16_t addr, void *priv) { // pclog("PC1512 in %04X %02X %04X:%04X\n",addr,CS,pc); switch (addr) @@ -74,7 +77,7 @@ uint8_t pc1512_in(uint16_t addr) return 0xFF; } -void pc1512_write(uint32_t addr, uint8_t val) +void pc1512_write(uint32_t addr, uint8_t val, void *priv) { /* if (CS==0x023E && pc==0x524E) { @@ -95,7 +98,7 @@ void pc1512_write(uint32_t addr, uint8_t val) vram[addr]=val; } -uint8_t pc1512_read(uint32_t addr) +uint8_t pc1512_read(uint32_t addr, void *priv) { // pclog("PC1512 read %08X %02X %01X\n",addr,cgamode&0x12,pc1512_plane_read); cycles-=12; @@ -111,32 +114,23 @@ static int sc,vc; static int cgadispon; static int con,coff,cursoron,cgablink; static int vsynctime,vadj; -static uint16_t ma,maback,ca; - -static int ntsc_col[8][8]= -{ - {0,0,0,0,0,0,0,0}, /*Black*/ - {0,0,1,1,1,1,0,0}, /*Blue*/ - {1,0,0,0,0,1,1,1}, /*Green*/ - {0,0,0,0,1,1,1,1}, /*Cyan*/ - {1,1,1,1,0,0,0,0}, /*Red*/ - {0,1,1,1,1,0,0,0}, /*Magenta*/ - {1,1,0,0,0,0,1,1}, /*Yellow*/ - {1,1,1,1,1,1,1,1} /*White*/ -}; +static uint16_t ma,maback; int i_filt[8],q_filt[8]; void pc1512_recalctimings() { + double _dispontime, _dispofftime; disptime = 128; /*Fixed on PC1512*/ - dispontime = 80; - dispofftime=disptime-dispontime; + _dispontime = 80; + _dispofftime=disptime-_dispontime; // printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]); - dispontime*=CGACONST; - dispofftime*=CGACONST; + _dispontime*=CGACONST; + _dispofftime*=CGACONST; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); + dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); } void pc1512_poll() @@ -417,7 +411,7 @@ endblit(); int pc1512_init() { - mem_sethandler(0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, NULL); return 0; } diff --git a/src/vid_pc1640.c b/src/vid_pc1640.c index 8aff1ea..7b5888e 100644 --- a/src/vid_pc1640.c +++ b/src/vid_pc1640.c @@ -1,54 +1,56 @@ /*PC1640 video emulation. Mostly standard EGA, but with CGA & Hercules emulation*/ #include "ibm.h" +#include "io.h" +#include "mem.h" #include "video.h" #include "vid_cga.h" #include "vid_ega.h" static int pc1640_cga=1; -void pc1640_out(uint16_t addr, uint8_t val) +void pc1640_out(uint16_t addr, uint8_t val, void *priv) { switch (addr) { case 0x3DB: pc1640_cga=val&0x40; - mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL); - mem_removehandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); + mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); + mem_removehandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL); if (pc1640_cga) - mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL); else { switch (gdcreg[6] & 0xC) { case 0x0: /*128k at A0000*/ - mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); break; case 0x4: /*64k at A0000*/ - mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); break; case 0x8: /*32k at B0000*/ - mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); break; case 0xC: /*32k at B8000*/ - mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); break; } } pclog("3DB write %02X\n", val); return; } - if (pc1640_cga) cga_out(addr,val); - else ega_out(addr,val); + if (pc1640_cga) cga_out(addr, val, NULL); + else ega_out(addr, val, NULL); } -uint8_t pc1640_in(uint16_t addr) +uint8_t pc1640_in(uint16_t addr, void *priv) { switch (addr) { } - if (pc1640_cga) return cga_in(addr); - else return ega_in(addr); + if (pc1640_cga) return cga_in(addr, NULL); + else return ega_in(addr, NULL); } void pc1640_recalctimings() @@ -69,7 +71,7 @@ int pc1640_init() pc1640_cga = 1; - mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL); return r; } diff --git a/src/vid_pc200.c b/src/vid_pc200.c index bf29121..d37b904 100644 --- a/src/vid_pc200.c +++ b/src/vid_pc200.c @@ -2,12 +2,14 @@ CGA with some NMI stuff. But we don't need that as it's only used for TV and LCD displays, and we're emulating a CRT*/ #include "ibm.h" +#include "io.h" +#include "mem.h" #include "video.h" #include "vid_cga.h" uint8_t pc200_3dd, pc200_3de, pc200_3df; -void pc200_out(uint16_t addr, uint8_t val) +void pc200_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; switch (addr) @@ -48,10 +50,10 @@ void pc200_out(uint16_t addr, uint8_t val) if (val&0x80) pc200_3dd|=0x40; return; } - cga_out(addr,val); + cga_out(addr, val, NULL); } -uint8_t pc200_in(uint16_t addr) +uint8_t pc200_in(uint16_t addr, void *priv) { uint8_t temp; switch (addr) @@ -70,12 +72,12 @@ uint8_t pc200_in(uint16_t addr) case 0x3DF: return pc200_3df; } - return cga_in(addr); + return cga_in(addr, NULL); } int pc200_init() { - mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); + mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL); return cga_init(); } diff --git a/src/vid_s3.c b/src/vid_s3.c index cd3ae4d..7e54dbc 100644 --- a/src/vid_s3.c +++ b/src/vid_s3.c @@ -1,17 +1,19 @@ /*S3 emulation*/ #include "ibm.h" +#include "io.h" #include "mem.h" #include "pci.h" #include "video.h" #include "vid_svga.h" +#include "vid_svga_render.h" #include "vid_sdac_ramdac.h" void s3_updatemapping(); -void s3_accel_write(uint32_t addr, uint8_t val); -void s3_accel_write_w(uint32_t addr, uint16_t val); -void s3_accel_write_l(uint32_t addr, uint32_t val); -uint8_t s3_accel_read(uint32_t addr); +void s3_accel_write(uint32_t addr, uint8_t val, void *priv); +void s3_accel_write_w(uint32_t addr, uint16_t val, void *priv); +void s3_accel_write_l(uint32_t addr, uint32_t val, void *priv); +uint8_t s3_accel_read(uint32_t addr, void *priv); static uint8_t s3_bank; static uint8_t s3_ma_ext; @@ -20,7 +22,7 @@ static int s3_bpp = 0; static uint8_t s3_id, s3_id_ext; -void s3_out(uint16_t addr, uint8_t val) +void s3_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; @@ -40,7 +42,7 @@ void s3_out(uint16_t addr, uint8_t val) case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: // pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc); - sdac_ramdac_out(addr,val); + sdac_ramdac_out(addr, val, NULL); return; case 0x3D4: @@ -141,13 +143,11 @@ void s3_out(uint16_t addr, uint8_t val) } break; } - svga_out(addr,val); + svga_out(addr, val, NULL); } -uint8_t s3_in(uint16_t addr) +uint8_t s3_in(uint16_t addr, void *priv) { - uint8_t temp; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; // if (addr != 0x3da) pclog("S3 in %04X\n", addr); @@ -155,7 +155,7 @@ uint8_t s3_in(uint16_t addr) { case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: // pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc); - return sdac_ramdac_in(addr); + return sdac_ramdac_in(addr, NULL); case 0x3D4: return crtcreg; @@ -174,7 +174,7 @@ uint8_t s3_in(uint16_t addr) } return crtc[crtcreg]; } - return svga_in(addr); + return svga_in(addr, NULL); } void s3_recalctimings() @@ -182,7 +182,27 @@ void s3_recalctimings() // pclog("recalctimings\n"); svga_ma |= (s3_ma_ext << 16); // pclog("SVGA_MA %08X\n", svga_ma); - if (gdcreg[5] & 0x40) svga_lowres = !(crtc[0x3a] & 0x10); + if ((gdcreg[5] & 0x40) && (crtc[0x3a] & 0x10)) + { + switch (bpp) + { + case 8: + svga_render = svga_render_8bpp_highres; + break; + case 15: + svga_render = svga_render_15bpp_highres; + break; + case 16: + svga_render = svga_render_16bpp_highres; + break; + case 24: + svga_render = svga_render_24bpp_highres; + break; + case 32: + svga_render = svga_render_32bpp_highres; + break; + } + } if (crtc[0x5d] & 0x01) svga_htotal += 0x100; if (crtc[0x5d] & 0x02) svga_hdisp += 0x100; if (crtc[0x5e] & 0x01) svga_vtotal += 0x400; @@ -201,25 +221,25 @@ void s3_recalctimings() static uint32_t s3_linear_base = 0, s3_linear_size = 0; void s3_updatemapping() { - mem_removehandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); + mem_removehandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); // video_write_a000_w = video_write_a000_l = NULL; - mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); // pclog("Update mapping - bank %02X ", gdcreg[6] & 0xc); switch (gdcreg[6] & 0xc) /*Banked framebuffer*/ { case 0x0: /*128k at A0000*/ - mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x4: /*64k at A0000*/ - mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x8: /*32k at B0000*/ - mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0xC: /*32k at B8000*/ - mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; } @@ -246,15 +266,15 @@ void s3_updatemapping() // pclog("%08X %08X %02X %02X %02X\n", linear_base, linear_size, crtc[0x58], crtc[0x59], crtc[0x5a]); // pclog("Linear framebuffer at %08X size %08X\n", linear_base, linear_size); if (s3_linear_base == 0xa0000) - mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); else - mem_sethandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); + mem_sethandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); } // pclog("Memory mapped IO %02X\n", crtc[0x53] & 0x10); if (crtc[0x53] & 0x10) /*Memory mapped IO*/ { - mem_sethandler(0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l); + mem_sethandler(0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL); /* video_write_a000 = s3_accel_write; video_write_a000_w = s3_accel_write_w; video_write_a000_l = s3_accel_write_l; @@ -299,7 +319,7 @@ struct void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat); -void s3_accel_out(uint16_t port, uint8_t val) +void s3_accel_out(uint16_t port, uint8_t val, void *priv) { // pclog("Accel out %04X %02X\n", port, val); switch (port) @@ -503,7 +523,7 @@ void s3_accel_out(uint16_t port, uint8_t val) } } -void s3_accel_out_w(uint16_t port, uint16_t val) +void s3_accel_out_w(uint16_t port, uint16_t val, void *priv) { // pclog("Accel out w %04X %04X\n", port, val); if (s3_accel.cmd & 0x100) @@ -519,7 +539,7 @@ void s3_accel_out_w(uint16_t port, uint16_t val) } } -void s3_accel_out_l(uint16_t port, uint32_t val) +void s3_accel_out_l(uint16_t port, uint32_t val, void *priv) { // pclog("Accel out l %04X %08X\n", port, val); if (s3_accel.cmd & 0x100) @@ -563,7 +583,7 @@ void s3_accel_out_l(uint16_t port, uint32_t val) } } -uint8_t s3_accel_in(uint16_t port) +uint8_t s3_accel_in(uint16_t port, void *priv) { int temp; // pclog("Accel in %04X\n", port); @@ -682,11 +702,11 @@ uint8_t s3_accel_in(uint16_t port) return 0; } -void s3_accel_write(uint32_t addr, uint8_t val) +void s3_accel_write(uint32_t addr, uint8_t val, void *priv) { // pclog("Write S3 accel %08X %02X\n", addr, val); if (addr & 0x8000) - s3_accel_out(addr & 0xffff, val); + s3_accel_out(addr & 0xffff, val, priv); else { if (s3_accel.cmd & 0x100) @@ -699,13 +719,13 @@ void s3_accel_write(uint32_t addr, uint8_t val) } } -void s3_accel_write_w(uint32_t addr, uint16_t val) +void s3_accel_write_w(uint32_t addr, uint16_t val, void *priv) { // pclog("Write S3 accel w %08X %04X\n", addr, val); if (addr & 0x8000) { - s3_accel_out( addr & 0xffff, val); - s3_accel_out((addr & 0xffff) + 1, val >> 8); + s3_accel_out( addr & 0xffff, val, priv); + s3_accel_out((addr & 0xffff) + 1, val >> 8, priv); } else { @@ -723,15 +743,15 @@ void s3_accel_write_w(uint32_t addr, uint16_t val) } } -void s3_accel_write_l(uint32_t addr, uint32_t val) +void s3_accel_write_l(uint32_t addr, uint32_t val, void *priv) { // pclog("Write S3 accel l %08X %08X\n", addr, val); if (addr & 0x8000) { - s3_accel_out( addr & 0xffff, val); - s3_accel_out((addr & 0xffff) + 1, val >> 8); - s3_accel_out((addr & 0xffff) + 2, val >> 16); - s3_accel_out((addr & 0xffff) + 3, val >> 24); + s3_accel_out( addr & 0xffff, val, priv); + s3_accel_out((addr & 0xffff) + 1, val >> 8, priv); + s3_accel_out((addr & 0xffff) + 2, val >> 16, priv); + s3_accel_out((addr & 0xffff) + 3, val >> 24, priv); } else { @@ -777,11 +797,11 @@ void s3_accel_write_l(uint32_t addr, uint32_t val) } } -uint8_t s3_accel_read(uint32_t addr) +uint8_t s3_accel_read(uint32_t addr, void *priv) { // pclog("Read S3 accel %08X\n", addr); if (addr & 0x8000) - return s3_accel_in(addr & 0xffff); + return s3_accel_in(addr & 0xffff, priv); return 0; } @@ -828,12 +848,8 @@ uint8_t s3_accel_read(uint32_t addr) void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat) { - uint32_t dest, destbak; - int sx, sy, cx, cy; - int x, y; uint32_t src_dat, dest_dat; int frgd_mix, bkgd_mix; - int mix; int clip_t = s3_accel.multifunc[1] & 0xfff; int clip_l = s3_accel.multifunc[2] & 0xfff; int clip_b = s3_accel.multifunc[3] & 0xfff; @@ -1390,6 +1406,7 @@ void s3_hwcursor_draw(int displine) int xx; int offset = svga_hwcursor_latch.x - svga_hwcursor_latch.xoff; + pclog("HWcursor %i %i\n", svga_hwcursor_latch.x, svga_hwcursor_latch.y); for (x = 0; x < 64; x += 16) { dat[0] = (vram[svga_hwcursor_latch.addr] << 8) | vram[svga_hwcursor_latch.addr + 1]; @@ -1414,9 +1431,9 @@ void s3_hwcursor_draw(int displine) } -uint8_t s3_pci_read(int func, int addr) +uint8_t s3_pci_read(int func, int addr, void *priv) { - pclog("S3 PCI read %08X\n", addr); +// pclog("S3 PCI read %08X\n", addr); switch (addr) { case 0x00: return 0x33; /*'S3'*/ @@ -1448,7 +1465,7 @@ uint8_t s3_pci_read(int func, int addr) return 0; } -void s3_pci_write(int func, int addr, uint8_t val) +void s3_pci_write(int func, int addr, uint8_t val, void *priv) { switch (addr) { @@ -1482,28 +1499,28 @@ int s3_init() vrammask = 0x3fffff; - io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xa2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xa6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xaae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xaee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); - io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l); + io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xa2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xa6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xaae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xaee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL); + io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, NULL); - pci_add(s3_pci_read, s3_pci_write); + pci_add(s3_pci_read, s3_pci_write, NULL); svga_vram_limit = 4 << 20; /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/ return svga_init(); diff --git a/src/vid_sdac_ramdac.c b/src/vid_sdac_ramdac.c index b92f60a..156f0f7 100644 --- a/src/vid_sdac_ramdac.c +++ b/src/vid_sdac_ramdac.c @@ -15,9 +15,8 @@ struct int rs2; } sdac_ramdac; -void sdac_ramdac_out(uint16_t addr, uint8_t val) +void sdac_ramdac_out(uint16_t addr, uint8_t val, void *priv) { - int didwrite; // /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2); switch (addr) { @@ -68,10 +67,10 @@ void sdac_ramdac_out(uint16_t addr, uint8_t val) } break; } - svga_out(addr,val); + svga_out(addr, val, NULL); } -uint8_t sdac_ramdac_in(uint16_t addr) +uint8_t sdac_ramdac_in(uint16_t addr, void *priv) { uint8_t temp; // /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, sdac_ramdac.rs2); @@ -128,7 +127,7 @@ uint8_t sdac_ramdac_in(uint16_t addr) } break; } - return svga_in(addr); + return svga_in(addr, NULL); } float sdac_getclock(int clock) diff --git a/src/vid_sdac_ramdac.h b/src/vid_sdac_ramdac.h index 391b6fa..e5f2756 100644 --- a/src/vid_sdac_ramdac.h +++ b/src/vid_sdac_ramdac.h @@ -1,4 +1,4 @@ -void sdac_ramdac_out(uint16_t addr, uint8_t val); -uint8_t sdac_ramdac_in(uint16_t addr); +void sdac_ramdac_out(uint16_t addr, uint8_t val, void *priv); +uint8_t sdac_ramdac_in(uint16_t addr, void *priv); float sdac_getclock(int clock); diff --git a/src/vid_stg_ramdac.c b/src/vid_stg_ramdac.c index f47ec76..7ec7b41 100644 --- a/src/vid_stg_ramdac.c +++ b/src/vid_stg_ramdac.c @@ -15,7 +15,7 @@ struct int stg_state_read[2][8]={{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}}; int stg_state_write[8]={0,0,0,0,0,6,7,7}; -void stg_ramdac_out(uint16_t addr, uint8_t val) +void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv) { int didwrite; //if (CS!=0xC000) pclog("OUT RAMDAC %04X %02X %i %04X:%04X\n",addr,val,stg_ramdac.magic_count,CS,pc); @@ -64,10 +64,10 @@ void stg_ramdac_out(uint16_t addr, uint8_t val) stg_ramdac.magic_count=0; break; } - svga_out(addr,val); + svga_out(addr, val, NULL); } -uint8_t stg_ramdac_in(uint16_t addr) +uint8_t stg_ramdac_in(uint16_t addr, void *priv) { uint8_t temp; //if (CS!=0xC000) pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc); @@ -100,5 +100,5 @@ uint8_t stg_ramdac_in(uint16_t addr) stg_ramdac.magic_count=0; break; } - return svga_in(addr); + return svga_in(addr, NULL); } diff --git a/src/vid_stg_ramdac.h b/src/vid_stg_ramdac.h index 84d9cf7..64394af 100644 --- a/src/vid_stg_ramdac.h +++ b/src/vid_stg_ramdac.h @@ -1,2 +1,2 @@ -void stg_ramdac_out(uint16_t addr, uint8_t val); -uint8_t stg_ramdac_in(uint16_t addr); +void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv); +uint8_t stg_ramdac_in(uint16_t addr, void *priv); diff --git a/src/vid_svga.c b/src/vid_svga.c index 4571c2e..df0e1d5 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -1,9 +1,14 @@ /*Generic SVGA handling*/ /*This is intended to be used by another SVGA driver, and not as a card in it's own right*/ #include "ibm.h" +#include "mem.h" #include "video.h" #include "vid_svga.h" +#include "vid_svga_render.h" #include "io.h" +#include "timer.h" + +#define svga_output 0 uint32_t svga_vram_limit; @@ -11,15 +16,19 @@ extern uint8_t edatlookup[4][4]; uint8_t svga_miscout; static uint8_t la, lb, lc, ld; -static uint8_t svga_rotate[8][256]; +uint8_t svga_rotate[8][256]; static int svga_fast; -void svga_out(uint16_t addr, uint8_t val) +void (*svga_render)(); + +static uint8_t dacmask, dacstatus; + +void svga_out(uint16_t addr, uint8_t val, void *priv) { int c; uint8_t o; - //printf("OUT SVGA %03X %02X %04X:%04X %i %08X\n",addr,val,CS,pc,TRIDENT,svgawbank); +// printf("OUT SVGA %03X %02X %04X:%04X %i %08X\n",addr,val,CS,pc,TRIDENT,svgawbank); switch (addr) { case 0x3C0: @@ -45,10 +54,16 @@ void svga_out(uint16_t addr, uint8_t val) svga_miscout = val; vres = 0; pallook = pallook256; vidclock = val & 4; printf("3C2 write %02X\n",val); - if (val&1) - io_sethandler(0x03a0, 0x0020, video_in, NULL, NULL, video_out, NULL, NULL); + if (val & 1) + { + pclog("Remove mono handler\n"); + io_removehandler(0x03a0, 0x0020, video_in, NULL, NULL, video_out, NULL, NULL, NULL); + } else - io_sethandler(0x03a0, 0x0020, video_in_null, NULL, NULL, video_out_null, NULL, NULL); + { + pclog("Set mono handler\n"); + io_sethandler(0x03a0, 0x0020, video_in, NULL, NULL, video_out, NULL, NULL, NULL); + } break; case 0x3C4: seqaddr=val; break; case 0x3C5: @@ -58,7 +73,12 @@ void svga_out(uint16_t addr, uint8_t val) if (o!=val && (seqaddr&0xF)==1) svga_recalctimings(); switch (seqaddr&0xF) { - case 1: if (scrblank && !(val&0x20)) fullchange=3; scrblank=(scrblank&~0x20)|(val&0x20); break; + case 1: + if (scrblank && !(val&0x20)) + fullchange=3; + scrblank=(scrblank&~0x20)|(val&0x20); + svga_recalctimings(); + break; case 2: writemask=val&0xF; break; case 3: charset=val&0xF; @@ -71,9 +91,16 @@ void svga_out(uint16_t addr, uint8_t val) break; } break; + case 0x3c6: dacmask=val; break; case 0x3C7: dacread=val; dacpos=0; break; case 0x3C8: dacwrite=val; dacpos=0; break; case 0x3C9: + dacstatus = 0; +/* if (pc == 0x68AD) + { + dumpregs(); + exit(-1); + }*/ palchange=1; fullchange=changeframecount; switch (dacpos) @@ -85,6 +112,7 @@ void svga_out(uint16_t addr, uint8_t val) break; case 0x3CE: gdcaddr=val; break; case 0x3CF: + o = gdcreg[gdcaddr & 15]; switch (gdcaddr&15) { case 2: colourcompare=val; break; @@ -93,21 +121,21 @@ void svga_out(uint16_t addr, uint8_t val) case 6: if ((gdcreg[6] & 0xc) != (val & 0xc)) { - mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); -// pclog("Write mapping %02X\n", val); + mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); + pclog("Write mapping %02X\n", val); switch (val&0xC) { case 0x0: /*128k at A0000*/ - mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x4: /*64k at A0000*/ - mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0x8: /*32k at B0000*/ - mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; case 0xC: /*32k at B8000*/ - mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); break; } } @@ -116,11 +144,13 @@ void svga_out(uint16_t addr, uint8_t val) } gdcreg[gdcaddr&15]=val; svga_fast = (gdcreg[8]==0xFF && !(gdcreg[3]&0x18) && !gdcreg[1]) && chain4; + if (((gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((gdcaddr & 15) == 6 && (val ^ o) & 1)) + svga_recalctimings(); break; } } -uint8_t svga_in(uint16_t addr) +uint8_t svga_in(uint16_t addr, void *priv) { uint8_t temp; // if (addr!=0x3da) pclog("Read port %04X\n",addr); @@ -128,12 +158,20 @@ uint8_t svga_in(uint16_t addr) { case 0x3C0: return attraddr; case 0x3C1: return attrregs[attraddr]; - case 0x3C2: return 0x10; + case 0x3c2: + if ((vgapal[0].r + vgapal[0].g + vgapal[0].b) >= 0x50) + temp = 0; + else + temp = 0x10; + return temp; case 0x3C4: return seqaddr; case 0x3C5: return seqregs[seqaddr&0xF]; + case 0x3c6: return dacmask; + case 0x3c7: return dacstatus; case 0x3C8: return dacwrite; case 0x3C9: + dacstatus=3; palchange=1; switch (dacpos) { @@ -156,8 +194,9 @@ uint8_t svga_in(uint16_t addr) } int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split; -int svga_hdisp, svga_htotal, svga_rowoffset; +int svga_hdisp, svga_htotal, svga_hdisp_time, svga_rowoffset; int svga_lowres, svga_interlace; +int svga_linedbl, svga_rowcount; double svga_clock; uint32_t svga_ma; void (*svga_recalctimings_ex)() = NULL; @@ -166,7 +205,8 @@ void (*svga_hwcursor_draw)(int displine) = NULL; void svga_recalctimings() { double crtcconst; - int temp; + double _dispontime, _dispofftime; + svga_vtotal=crtc[6]; svga_dispend=crtc[0x12]; svga_vsyncstart=crtc[0x10]; @@ -204,32 +244,131 @@ void svga_recalctimings() svga_interlace = 0; svga_ma = (crtc[0xC]<<8)|crtc[0xD]; + + svga_hdisp_time = svga_hdisp; + svga_render = svga_render_blank; + if (!scrblank) + { + if (!(gdcreg[6]&1)) /*Text mode*/ + { + if (seqregs[1]&8) /*40 column*/ + { + svga_render = svga_render_text_40; + svga_hdisp *= (seqregs[1] & 1) ? 16 : 18; + } + else + { + svga_render = svga_render_text_80; + svga_hdisp *= (seqregs[1] & 1) ? 8 : 9; + } + } + else + { + svga_hdisp *= (seqregs[1] & 8) ? 16 : 8; + + switch (gdcreg[5]&0x60) + { + case 0x00: /*16 colours*/ + if (seqregs[1]&8) /*Low res (320)*/ + svga_render = svga_render_4bpp_lowres; + else + svga_render = svga_render_4bpp_highres; + break; + case 0x20: /*4 colours*/ + svga_render = svga_render_2bpp_lowres; + break; + case 0x40: case 0x60: /*256+ colours*/ + switch (bpp) + { + case 8: + if (svga_lowres) + svga_render = svga_render_8bpp_lowres; + else + { + svga_render = svga_render_8bpp_highres; +// svga_hdisp <<= 1; + } + break; + case 15: + if (svga_lowres) + svga_render = svga_render_15bpp_lowres; + else + { + svga_render = svga_render_15bpp_highres; + svga_hdisp <<= 1; + } + break; + case 16: + if (svga_lowres) + svga_render = svga_render_16bpp_lowres; + else + { + svga_render = svga_render_16bpp_highres; + svga_hdisp <<= 1; + } + break; + case 24: + if (svga_lowres) + { + svga_render = svga_render_24bpp_lowres; + svga_hdisp = ((svga_hdisp<<3)/3); + } + else + { + svga_render = svga_render_24bpp_highres; + svga_hdisp = ((svga_hdisp<<3)/3); + } + break; + case 32: + if (svga_lowres) + svga_render = svga_render_32bpp_lowres; + else + { + svga_render = svga_render_32bpp_highres; + svga_hdisp <<= 1; + } + break; + } + break; + } + } + } + +// pclog("svga_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", svga_render, svga_render_text_40, svga_render_text_80, svga_render_8bpp_lowres, svga_render_8bpp_highres, svga_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + svga_linedbl = crtc[9] & 0x80; + svga_rowcount = crtc[9] & 31; if (svga_recalctimings_ex) svga_recalctimings_ex(); crtcconst=(seqregs[1]&1)?(svga_clock*8.0):(svga_clock*9.0); disptime =svga_htotal; - dispontime=svga_hdisp; - + _dispontime = svga_hdisp_time; + // printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8); - if (seqregs[1]&8) { disptime*=2; dispontime*=2; } - dispofftime=disptime-dispontime; - dispontime*=crtcconst; - dispofftime*=crtcconst; + if (seqregs[1]&8) { disptime*=2; _dispontime*=2; } + _dispofftime=disptime-_dispontime; + _dispontime*=crtcconst; + _dispofftime*=crtcconst; + dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); // printf("SVGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4)); // printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga_vtotal,svga_dispend,(crtc[9]&31)+1,svga_vsyncstart); // printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*svga_vtotal,(dispontime+dispofftime)*svga_vtotal*70,seqregs[1]); + +// pclog("svga_render %08X\n", svga_render); } +void (*svga_render)(); -static uint32_t ma,maback,ca; -static int vc,sc; -static int linepos, displine, vslines, linecountff, oddeven; +uint32_t ma, maback, ca; +static int vc; +int sc; +static int linepos, vslines, linecountff, oddeven; static int svga_dispon; -static int con, coff, cursoron, cgablink; -static int scrollcache; +int con, coff, cursoron, cgablink; +int scrollcache; int svga_hwcursor_on; @@ -237,17 +376,13 @@ SVGA_HWCURSOR svga_hwcursor, svga_hwcursor_latch; int svga_hdisp_on; -static int firstline_draw = 2000, lastline_draw = 0; +int firstline_draw = 2000, lastline_draw = 0; +int displine; void svga_poll() { - uint8_t chr,dat,attr; - uint32_t charaddr; - int x,xx; - uint32_t fg,bg; - int offset; - uint8_t edat[4]; - int drawcursor=0; + int x; + if (!linepos) { // if (!(vc & 15)) pclog("VC %i %i\n", vc, GetTickCount()); @@ -264,305 +399,17 @@ void svga_poll() ma&=vrammask; if (firstline==2000) firstline=displine; - if (scrblank) - { - if (firstline_draw == 2000) firstline_draw = displine; - lastline_draw = displine; - for (x=0;xline[displine])[(x*9)+xx+32]=0; - break; - case 1: - for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[(x*8)+xx+32]=0; - break; - case 8: - for (xx=0;xx<18;xx++) ((uint32_t *)buffer32->line[displine])[(x*18)+xx+32]=0; - break; - case 9: - for (xx=0;xx<16;xx++) ((uint32_t *)buffer32->line[displine])[(x*16)+xx+32]=0; - break; - } - } - } - else if (!(gdcreg[6]&1)) /*Text mode*/ - { - if (firstline_draw == 2000) firstline_draw = displine; - lastline_draw = displine; - if (fullchange) - { - for (x=0;x>4]]; } - else - { - fg=pallook[egapal[attr&15]]; - bg=pallook[egapal[attr>>4]]; - if (attr&0x80 && attrregs[0x10]&8) - { - bg=pallook[egapal[(attr>>4)&7]]; - if (cgablink&16) fg=bg; - } - } - - dat=vram[charaddr+(sc<<2)]; - if (seqregs[1]&8) /*40 column*/ - { - if (seqregs[1]&1) { for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x<<4)+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[((x<<4)+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg; } - else - { - for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x*18)+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg; - if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) ((uint32_t *)buffer32->line[displine])[((x*18)+32+16)&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+32+17)&2047]=bg; - else ((uint32_t *)buffer32->line[displine])[((x*18)+32+16)&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+32+17)&2047]=(dat&1)?fg:bg; - } - } - else /*80 column*/ - { - if (seqregs[1]&1) { for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x<<3)+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg; } - else - { - for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x*9)+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg; - if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) ((uint32_t *)buffer32->line[displine])[((x*9)+32+8)&2047]=bg; - else ((uint32_t *)buffer32->line[displine])[((x*9)+32+8)&2047]=(dat&1)?fg:bg; - } - } - ma+=4; ma&=vrammask; - } - } - } - else - { -// if (hwcursor_on) changedvram[ma>>10]=changedvram[(ma>>10)+1]=2; - switch (gdcreg[5]&0x60) - { - case 0x00: /*16 colours*/ - if (firstline_draw == 2000) firstline_draw = displine; - lastline_draw = displine; - if (seqregs[1]&8) /*Low res (320)*/ - { - offset=((8-scrollcache)<<1)+16; - for (x=0;x<=svga_hdisp;x++) - { - edat[0]=vram[ma]; - edat[1]=vram[ma|0x1]; - edat[2]=vram[ma|0x2]; - edat[3]=vram[ma|0x3]; - ma+=4; ma&=vrammask; - - dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<4)+14+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+15+offset]=pallook[egapal[dat&0xF]]; - ((uint32_t *)buffer32->line[displine])[(x<<4)+12+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+13+offset]=pallook[egapal[dat>>4]]; - dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<4)+10+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+11+offset]=pallook[egapal[dat&0xF]]; - ((uint32_t *)buffer32->line[displine])[(x<<4)+8+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+9+offset]=pallook[egapal[dat>>4]]; - dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<4)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+7+offset]=pallook[egapal[dat&0xF]]; - ((uint32_t *)buffer32->line[displine])[(x<<4)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+5+offset]=pallook[egapal[dat>>4]]; - dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<4)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+3+offset]=pallook[egapal[dat&0xF]]; - ((uint32_t *)buffer32->line[displine])[(x<<4)+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+1+offset]=pallook[egapal[dat>>4]]; - } - } - else /*High res (640)*/ - { - offset=(8-scrollcache)+24; - for (x=0;x<=svga_hdisp;x++) - { - edat[0]=vram[ma]; - edat[1]=vram[ma|0x1]; - edat[2]=vram[ma|0x2]; - edat[3]=vram[ma|0x3]; - ma+=4; ma&=vrammask; - - dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<3)+7+offset]=pallook[egapal[dat&0xF]]; - ((uint32_t *)buffer32->line[displine])[(x<<3)+6+offset]=pallook[egapal[dat>>4]]; - dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<3)+5+offset]=pallook[egapal[dat&0xF]]; - ((uint32_t *)buffer32->line[displine])[(x<<3)+4+offset]=pallook[egapal[dat>>4]]; - dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<3)+3+offset]=pallook[egapal[dat&0xF]]; - ((uint32_t *)buffer32->line[displine])[(x<<3)+2+offset]=pallook[egapal[dat>>4]]; - dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<3)+1+offset]=pallook[egapal[dat&0xF]]; - ((uint32_t *)buffer32->line[displine])[(x<<3)+offset]= pallook[egapal[dat>>4]]; - } - } - break; - case 0x20: /*4 colours*/ - if (firstline_draw == 2000) firstline_draw = displine; - lastline_draw = displine; - offset=((8-scrollcache)<<1)+16; - /*Low res (320) only, though high res (640) should be possible*/ - for (x=0;x<=svga_hdisp;x++) - { - if (sc&1 && !(crtc[0x17]&1)) - { - edat[0]=vram[(ma<<1)+0x8000]; - edat[1]=vram[(ma<<1)+0x8004]; - } - else - { - edat[0]=vram[(ma<<1)]; - edat[1]=vram[(ma<<1)+4]; - } - ma+=4; ma&=vrammask; - - ((uint32_t *)buffer32->line[displine])[(x<<4)+14+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+15+offset]=pallook[egapal[edat[1]&3]]; - ((uint32_t *)buffer32->line[displine])[(x<<4)+12+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+13+offset]=pallook[egapal[(edat[1]>>2)&3]]; - dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<4)+10+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+11+offset]=pallook[egapal[(edat[1]>>4)&3]]; - ((uint32_t *)buffer32->line[displine])[(x<<4)+8+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+9+offset]=pallook[egapal[(edat[1]>>6)&3]]; - dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<4)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+7+offset]=pallook[egapal[(edat[0]>>0)&3]]; - ((uint32_t *)buffer32->line[displine])[(x<<4)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+5+offset]=pallook[egapal[(edat[0]>>2)&3]]; - dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2); - ((uint32_t *)buffer32->line[displine])[(x<<4)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+3+offset]=pallook[egapal[(edat[0]>>4)&3]]; - ((uint32_t *)buffer32->line[displine])[(x<<4)+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+1+offset]=pallook[egapal[(edat[0]>>6)&3]]; - } - break; - case 0x40: case 0x60: /*256 colours (and more, with high/true colour RAMDAC)*/ - if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange) - { - if (firstline_draw == 2000) firstline_draw = displine; - lastline_draw = displine; - if (svga_lowres) /*Low res (320)*/ - { -// if (!displine) pclog("Lo res %i %i %i\n",bpp,svga_hdisp,(svga_hdisp<<3)/3); - offset=(8-(scrollcache&6))+24; - if (bpp==8) /*Regular 8 bpp palette mode*/ - { - for (x=0;x<=svga_hdisp;x++) - { - edat[0]=vram[ma]; - edat[1]=vram[ma|0x1]; - edat[2]=vram[ma|0x2]; - edat[3]=vram[ma|0x3]; - ma+=4; ma&=vrammask; - ((uint32_t *)buffer32->line[displine])[(x<<3)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+7+offset]=pallook[edat[3]]; - ((uint32_t *)buffer32->line[displine])[(x<<3)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+5+offset]=pallook[edat[2]]; - ((uint32_t *)buffer32->line[displine])[(x<<3)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+3+offset]=pallook[edat[1]]; - ((uint32_t *)buffer32->line[displine])[(x<<3)+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+1+offset]=pallook[edat[0]]; - } - } - else if (bpp==16) /*16 bpp 565 mode*/ - { - for (x=0;x<=svga_hdisp;x++) - { - fg=vram[ma]|(vram[ma|0x1]<<8); - bg=vram[ma|0x2]|(vram[ma|0x3]<<8); - ma+=4; ma&=vrammask; - ((uint32_t *)buffer32->line[displine])[(x<<2)+2+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=((bg&31)<<3)|(((bg>>5)&63)<<10)|(((bg>>11)&31)<<19); - ((uint32_t *)buffer32->line[displine])[(x<<2)+0+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=((fg&31)<<3)|(((fg>>5)&63)<<10)|(((fg>>11)&31)<<19); - } - } - else if (bpp==15) /*15 bpp 555 mode*/ - { - for (x=0;x<=svga_hdisp;x++) - { - fg=vram[ma]|(vram[ma|0x1]<<8); - bg=vram[ma|0x2]|(vram[ma|0x3]<<8); - ma+=4; ma&=vrammask; - ((uint32_t *)buffer32->line[displine])[(x<<1)+2+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19); - ((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19); - } - } - else if (bpp==24) /*24 bpp 888 mode*/ - { - for (x=0;x<=((svga_hdisp<<3)/3);x++) - { - fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16); - ma+=3; ma&=vrammask; - ((uint32_t *)buffer32->line[displine])[(x<<1)+offset]=((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=fg; - } - } - else if (bpp==32) /*32 bpp 8888 mode*/ - { - for (x = 0; x <= svga_hdisp; x++) - { - fg = vram[ma] | (vram[ma + 1] << 8) | (vram[ma + 2] << 16); - ma += 4; ma &= vrammask; - ((uint32_t *)buffer32->line[displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[displine])[(x << 1) + 1 + offset] = fg; - } - } - } - else /*High res (SVGA only)*/ - { -// if (!displine) pclog("Hi res %i %i %i\n",bpp,svga_hdisp,(svga_hdisp<<3)/3); - offset=(8-((scrollcache&6)>>1))+24; - if (bpp==8) - { - for (x=0;x<=(svga_hdisp<<1);x++) - { - edat[0]=vram[ma]; - edat[1]=vram[ma|0x1]; - edat[2]=vram[ma|0x2]; - edat[3]=vram[ma|0x3]; - ma+=4; ma&=vrammask; - ((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=pallook[edat[3]]; - ((uint32_t *)buffer32->line[displine])[(x<<2)+2+offset]=pallook[edat[2]]; - ((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=pallook[edat[1]]; - ((uint32_t *)buffer32->line[displine])[(x<<2)+offset]= pallook[edat[0]]; - } - } - else if (bpp==16) - { - for (x=0;x<=(svga_hdisp<<1);x++) - { - fg=vram[ma]|(vram[ma|0x1]<<8); - bg=vram[ma|0x2]|(vram[ma|0x3]<<8); - ma+=4; ma&=vrammask; - ((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=((bg&31)<<3)|(((bg>>5)&63)<<10)|(((bg>>11)&31)<<19); - ((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((fg&31)<<3)|(((fg>>5)&63)<<10)|(((fg>>11)&31)<<19); - } - } - else if (bpp==15) - { - for (x=0;x<=(svga_hdisp<<1);x++) - { - fg=vram[ma]|(vram[ma|0x1]<<8); - bg=vram[ma|0x2]|(vram[ma|0x3]<<8); - ma+=4; ma&=vrammask; - ((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19); - ((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19); - } - } - else if (bpp==24) - { - for (x=0;x<=((svga_hdisp<<3)/3);x++) - { - fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16); - ma+=3; ma&=vrammask; - ((uint32_t *)buffer32->line[displine])[x+offset]=fg; - } - } - else if (bpp==32) - { - for (x = 0; x <= (svga_hdisp<<2); x++) - { - fg = vram[ma] | (vram[ma + 1] << 8) | (vram[ma + 2] << 16); - ma += 4; ma &= vrammask; - ((uint32_t *)buffer32->line[displine])[x + offset] = fg; - } - } - } - } - break; - } + + if (svga_hwcursor_on) changedvram[ma >> 10] = changedvram[(ma >> 10) + 1] = 2; + + svga_render(); + if (svga_hwcursor_on) { svga_hwcursor_draw(displine); svga_hwcursor_on--; } - } + if (lastline=0xB0000) addr&=0x7FFF; else { @@ -783,8 +627,8 @@ void svga_write(uint32_t addr, uint8_t val) { addr<<=2; } -// pclog("%08X %02X %i %i %i\n", addr, val, writemask2, writemode, chain4); addr&=0x7FFFFF; + if (svga_output) pclog("%08X (%i, %i) %02X %i %i %i\n", addr, addr & 1023, addr >> 10, val, writemask2, writemode, chain4); changedvram[addr>>10]=changeframecount; switch (writemode) @@ -929,10 +773,9 @@ void svga_write(uint32_t addr, uint8_t val) } } -uint8_t svga_read(uint32_t addr) +uint8_t svga_read(uint32_t addr, void *priv) { uint8_t temp,temp2,temp3,temp4; - uint32_t addr2; cycles -= video_timing_b; cycles_lost += video_timing_b; @@ -985,20 +828,17 @@ uint8_t svga_read(uint32_t addr) return vram[addr|readplane]; } -void svga_write_linear(uint32_t addr, uint8_t val) +void svga_write_linear(uint32_t addr, uint8_t val, void *priv) { - int x,y; - char s[2]={0,0}; uint8_t vala,valb,valc,vald,wm=writemask; int writemask2 = writemask; - int bankaddr; cycles -= video_timing_b; cycles_lost += video_timing_b; egawrites++; -// pclog("Write LFB %08X %02X ", addr, val); + if (svga_output) pclog("Write LFB %08X %02X ", addr, val); if (!(gdcreg[6]&1)) fullchange=2; if (chain4) { @@ -1010,7 +850,7 @@ void svga_write_linear(uint32_t addr, uint8_t val) addr<<=2; } addr &= 0x7fffff; -// pclog("%08X\n", addr); + if (svga_output) pclog("%08X\n", addr); changedvram[addr>>10]=changeframecount; switch (writemode) @@ -1155,7 +995,7 @@ void svga_write_linear(uint32_t addr, uint8_t val) } } -uint8_t svga_read_linear(uint32_t addr) +uint8_t svga_read_linear(uint32_t addr, void *priv) { uint8_t temp,temp2,temp3,temp4; @@ -1220,8 +1060,16 @@ void svga_doblit(int y1, int y2) ysize=wy+1; if (xsize<64) xsize=656; if (ysize<32) ysize=200; - if (vres) updatewindowsize(xsize,ysize<<1); - else updatewindowsize(xsize,ysize); +/* if (bpp > 8) + { + if (vres) updatewindowsize(xsize<<1,ysize<<1); + else updatewindowsize(xsize<<1,ysize); + } + else + {*/ + if (vres) updatewindowsize(xsize,ysize<<1); + else updatewindowsize(xsize,ysize); +// } } if (vid_resize) { @@ -1234,12 +1082,12 @@ void svga_doblit(int y1, int y2) } -void svga_writew(uint32_t addr, uint16_t val) +void svga_writew(uint32_t addr, uint16_t val, void *priv) { if (!svga_fast) { - svga_write(addr, val); - svga_write(addr + 1, val >> 8); + svga_write(addr, val, priv); + svga_write(addr + 1, val >> 8, priv); return; } @@ -1248,22 +1096,22 @@ void svga_writew(uint32_t addr, uint16_t val) cycles -= video_timing_w; cycles_lost += video_timing_w; -// pclog("Writew %05X ", addr); + if (svga_output) pclog("Writew %05X ", addr); addr = (addr & 0xffff) + svgawbank; addr &= 0x7FFFFF; -// pclog("%08X %04X\n", addr, val); + if (svga_output) pclog("%08X (%i, %i) %04X\n", addr, addr & 1023, addr >> 10, val); changedvram[addr >> 10] = changeframecount; *(uint16_t *)&vram[addr] = val; } -void svga_writel(uint32_t addr, uint32_t val) +void svga_writel(uint32_t addr, uint32_t val, void *priv) { if (!svga_fast) { - svga_write(addr, val); - svga_write(addr + 1, val >> 8); - svga_write(addr + 2, val >> 16); - svga_write(addr + 3, val >> 24); + svga_write(addr, val, priv); + svga_write(addr + 1, val >> 8, priv); + svga_write(addr + 2, val >> 16, priv); + svga_write(addr + 3, val >> 24, priv); return; } @@ -1272,19 +1120,19 @@ void svga_writel(uint32_t addr, uint32_t val) cycles -= video_timing_l; cycles_lost += video_timing_l; -// pclog("Writel %05X ", addr); + if (svga_output) pclog("Writel %05X ", addr); addr = (addr & 0xffff) + svgawbank; addr &= 0x7FFFFF; -// pclog("%08X %08X\n", addr, val); + if (svga_output) pclog("%08X (%i, %i) %08X\n", addr, addr & 1023, addr >> 10, val); changedvram[addr >> 10] = changeframecount; *(uint32_t *)&vram[addr] = val; } -uint16_t svga_readw(uint32_t addr) +uint16_t svga_readw(uint32_t addr, void *priv) { if (!svga_fast) - return svga_read(addr) | (svga_read(addr + 1) << 8); + return svga_read(addr, priv) | (svga_read(addr + 1, priv) << 8); egareads += 2; @@ -1300,10 +1148,10 @@ uint16_t svga_readw(uint32_t addr) return *(uint16_t *)&vram[addr]; } -uint32_t svga_readl(uint32_t addr) +uint32_t svga_readl(uint32_t addr, void *priv) { if (!svga_fast) - return svga_read(addr) | (svga_read(addr + 1) << 8) | (svga_read(addr + 2) << 16) | (svga_read(addr + 3) << 24); + return svga_read(addr, priv) | (svga_read(addr + 1, priv) << 8) | (svga_read(addr + 2, priv) << 16) | (svga_read(addr + 3, priv) << 24); egareads += 4; @@ -1319,12 +1167,12 @@ uint32_t svga_readl(uint32_t addr) return *(uint32_t *)&vram[addr]; } -void svga_writew_linear(uint32_t addr, uint16_t val) +void svga_writew_linear(uint32_t addr, uint16_t val, void *priv) { if (!svga_fast) { - svga_write_linear(addr, val); - svga_write_linear(addr + 1, val >> 8); + svga_write_linear(addr, val, priv); + svga_write_linear(addr + 1, val >> 8, priv); return; } @@ -1333,19 +1181,20 @@ void svga_writew_linear(uint32_t addr, uint16_t val) cycles -= video_timing_w; cycles_lost += video_timing_w; + if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val); addr &= 0x7FFFFF; changedvram[addr >> 10] = changeframecount; *(uint16_t *)&vram[addr] = val; } -void svga_writel_linear(uint32_t addr, uint32_t val) +void svga_writel_linear(uint32_t addr, uint32_t val, void *priv) { if (!svga_fast) { - svga_write_linear(addr, val); - svga_write_linear(addr + 1, val >> 8); - svga_write_linear(addr + 2, val >> 16); - svga_write_linear(addr + 3, val >> 24); + svga_write_linear(addr, val, priv); + svga_write_linear(addr + 1, val >> 8, priv); + svga_write_linear(addr + 2, val >> 16, priv); + svga_write_linear(addr + 3, val >> 24, priv); return; } @@ -1354,15 +1203,16 @@ void svga_writel_linear(uint32_t addr, uint32_t val) cycles -= video_timing_l; cycles_lost += video_timing_l; + if (svga_output) pclog("Write LFBl %08X %08X\n", addr, val); addr &= 0x7fffff; changedvram[addr >> 10] = changeframecount; *(uint32_t *)&vram[addr] = val; } -uint16_t svga_readw_linear(uint32_t addr) +uint16_t svga_readw_linear(uint32_t addr, void *priv) { if (!svga_fast) - return svga_read_linear(addr) | (svga_read_linear(addr + 1) << 8); + return svga_read_linear(addr, priv) | (svga_read_linear(addr + 1, priv) << 8); egareads += 2; @@ -1375,10 +1225,10 @@ uint16_t svga_readw_linear(uint32_t addr) return *(uint16_t *)&vram[addr]; } -uint32_t svga_readl_linear(uint32_t addr) +uint32_t svga_readl_linear(uint32_t addr, void *priv) { if (!svga_fast) - return svga_read_linear(addr) | (svga_read_linear(addr + 1) << 8) | (svga_read_linear(addr + 2) << 16) | (svga_read_linear(addr + 3) << 24); + return svga_read_linear(addr, priv) | (svga_read_linear(addr + 1, priv) << 8) | (svga_read_linear(addr + 2, priv) << 16) | (svga_read_linear(addr + 3, priv) << 24); egareads += 4; diff --git a/src/vid_svga.h b/src/vid_svga.h index 6038409..f249295 100644 --- a/src/vid_svga.h +++ b/src/vid_svga.h @@ -1,10 +1,12 @@ /*Vertical timings*/ extern int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split; /*Horizontal timings*/ -extern int svga_hdisp, svga_htotal, svga_rowoffset; +extern int svga_hdisp, svga_htotal, svga_hdisp_time, svga_rowoffset; /*Flags - svga_lowres = 1/2 clock in 256+ colour modes, svga_interlace = interlace mode enabled*/ extern int svga_lowres, svga_interlace; +extern int svga_linedbl, svga_rowcount; + /*Status of display on*/ extern int svga_hdisp_on; @@ -35,19 +37,24 @@ extern SVGA_HWCURSOR svga_hwcursor, svga_hwcursor_latch; extern int svga_hwcursor_on; extern void (*svga_hwcursor_draw)(int displine); -uint8_t svga_read(uint32_t addr); -uint16_t svga_readw(uint32_t addr); -uint32_t svga_readl(uint32_t addr); -void svga_write(uint32_t addr, uint8_t val); -void svga_writew(uint32_t addr, uint16_t val); -void svga_writel(uint32_t addr, uint32_t val); -uint8_t svga_read_linear(uint32_t addr); -uint16_t svga_readw_linear(uint32_t addr); -uint32_t svga_readl_linear(uint32_t addr); -void svga_write_linear(uint32_t addr, uint8_t val); -void svga_writew_linear(uint32_t addr, uint16_t val); -void svga_writel_linear(uint32_t addr, uint32_t val); +uint8_t svga_read(uint32_t addr, void *priv); +uint16_t svga_readw(uint32_t addr, void *priv); +uint32_t svga_readl(uint32_t addr, void *priv); +void svga_write(uint32_t addr, uint8_t val, void *priv); +void svga_writew(uint32_t addr, uint16_t val, void *priv); +void svga_writel(uint32_t addr, uint32_t val, void *priv); +uint8_t svga_read_linear(uint32_t addr, void *priv); +uint16_t svga_readw_linear(uint32_t addr, void *priv); +uint32_t svga_readl_linear(uint32_t addr, void *priv); +void svga_write_linear(uint32_t addr, uint8_t val, void *priv); +void svga_writew_linear(uint32_t addr, uint16_t val, void *priv); +void svga_writel_linear(uint32_t addr, uint32_t val, void *priv); void svga_doblit(int y1, int y2); extern uint32_t svga_vram_limit; + +extern uint8_t svga_rotate[8][256]; + +void svga_out(uint16_t addr, uint8_t val, void *priv); +uint8_t svga_in(uint16_t addr, void *priv); diff --git a/src/vid_tandy.c b/src/vid_tandy.c index 4e53a71..0dc702d 100644 --- a/src/vid_tandy.c +++ b/src/vid_tandy.c @@ -2,6 +2,7 @@ #include "video.h" #include "io.h" #include "mem.h" +#include "timer.h" static int tandy_array_index; static uint8_t tandy_array[32]; @@ -14,7 +15,7 @@ static uint8_t *tandy_vram, *tandy_b8000; void tandy_recalcaddress(); void tandy_recalctimings(); -void tandy_out(uint16_t addr, uint8_t val) +void tandy_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; // pclog("Tandy OUT %04X %02X\n",addr,val); @@ -59,7 +60,7 @@ void tandy_out(uint16_t addr, uint8_t val) } } -uint8_t tandy_in(uint16_t addr) +uint8_t tandy_in(uint16_t addr, void *priv) { // if (addr!=0x3DA) pclog("Tandy IN %04X\n",addr); switch (addr) @@ -90,14 +91,14 @@ void tandy_recalcaddress() } } -void tandy_write(uint32_t addr, uint8_t val) +void tandy_write(uint32_t addr, uint8_t val, void *priv) { if (tandy_memctrl==-1) return; // pclog("Tandy VRAM write %05X %02X %04X:%04X %04X:%04X\n",addr,val,CS,pc,DS,SI); tandy_b8000[addr&0x7FFF]=val; } -uint8_t tandy_read(uint32_t addr) +uint8_t tandy_read(uint32_t addr, void *priv) { if (tandy_memctrl==-1) return 0xFF; // pclog("Tandy VRAM read %05X %02X %04X:%04X\n",addr,tandy_b8000[addr&0x7FFF],CS,pc); @@ -106,19 +107,22 @@ uint8_t tandy_read(uint32_t addr) void tandy_recalctimings() { + double _dispontime, _dispofftime; if (tandy_mode&1) { disptime=crtc[0]+1; - dispontime=crtc[1]; + _dispontime=crtc[1]; } else { disptime=(crtc[0]+1)<<1; - dispontime=crtc[1]<<1; + _dispontime=crtc[1]<<1; } - dispofftime=disptime-dispontime; - dispontime*=CGACONST; - dispofftime*=CGACONST; + _dispofftime=disptime-_dispontime; + _dispontime*=CGACONST; + _dispofftime*=CGACONST; + dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); } @@ -127,7 +131,7 @@ static int sc,vc; static int cgadispon; static int con,coff,cursoron,cgablink; static int vsynctime,vadj; -static uint16_t ma,maback,ca; +static uint16_t ma,maback; static int ntsc_col[8][8]= { @@ -157,7 +161,7 @@ void tandy_poll() int x,c; int oldvc; uint8_t chr,attr; - uint16_t dat,dat2,dat3,dat4; + uint16_t dat; int cols[4]; int col; int oldsc; @@ -582,8 +586,8 @@ void tandy_poll() int tandy_init() { - mem_sethandler(0xb8000, 0x8000, tandy_read, NULL, NULL, tandy_write, NULL, NULL); - io_sethandler(0x00a0, 0x0002, tandy_in, NULL, NULL, tandy_out, NULL, NULL); + mem_sethandler(0xb8000, 0x8000, tandy_read, NULL, NULL, tandy_write, NULL, NULL, NULL); + io_sethandler(0x00a0, 0x0002, tandy_in, NULL, NULL, tandy_out, NULL, NULL, NULL); tandy_memctrl = -1; return 0; } diff --git a/src/vid_tkd8001_ramdac.c b/src/vid_tkd8001_ramdac.c index 4c013ea..f15d0e5 100644 --- a/src/vid_tkd8001_ramdac.c +++ b/src/vid_tkd8001_ramdac.c @@ -7,7 +7,7 @@ static int tkd8001_state=0; static uint8_t tkd8001_ctrl; -void tkd8001_ramdac_out(uint16_t addr, uint8_t val) +void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv) { // pclog("OUT RAMDAC %04X %02X %04X:%04X\n",addr,val,CS,pc); switch (addr) @@ -40,10 +40,10 @@ void tkd8001_ramdac_out(uint16_t addr, uint8_t val) tkd8001_state = 0; break; } - svga_out(addr,val); + svga_out(addr, val, NULL); } -uint8_t tkd8001_ramdac_in(uint16_t addr) +uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv) { // pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc); switch (addr) @@ -60,5 +60,5 @@ uint8_t tkd8001_ramdac_in(uint16_t addr) tkd8001_state = 0; break; } - return svga_in(addr); + return svga_in(addr, NULL); } diff --git a/src/vid_tkd8001_ramdac.h b/src/vid_tkd8001_ramdac.h index 60a4626..1cf083e 100644 --- a/src/vid_tkd8001_ramdac.h +++ b/src/vid_tkd8001_ramdac.h @@ -1,2 +1,2 @@ -void tkd8001_ramdac_out(uint16_t addr, uint8_t val); -uint8_t tkd8001_ramdac_in(uint16_t addr); +void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv); +uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv); diff --git a/src/vid_tvga.c b/src/vid_tvga.c index eb43e1f..e07d010 100644 --- a/src/vid_tvga.c +++ b/src/vid_tvga.c @@ -1,18 +1,37 @@ /*Trident TVGA (8900D) emulation*/ #include "ibm.h" +#include "io.h" +#include "mem.h" #include "video.h" #include "vid_svga.h" +#include "vid_svga_render.h" #include "vid_tkd8001_ramdac.h" +void tvga_recalcmapping(); + uint8_t trident3d8,trident3d9; int tridentoldmode; uint8_t tridentoldctrl2,tridentnewctrl2; uint8_t tridentdac; -void tvga_out(uint16_t addr, uint8_t val) +uint32_t tvga_linear_base, tvga_linear_size; + +uint8_t tvga_accel_read(uint32_t addr, void *priv); +uint16_t tvga_accel_read_w(uint32_t addr, void *priv); +uint32_t tvga_accel_read_l(uint32_t addr, void *priv); + +void tvga_accel_write(uint32_t addr, uint8_t val, void *priv); +void tvga_accel_write_w(uint32_t addr, uint16_t val, void *priv); +void tvga_accel_write_l(uint32_t addr, uint32_t val, void *priv); + + +void tvga_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv); + +void tvga_out(uint16_t addr, uint8_t val, void *priv) { uint8_t old; +// pclog("tvga_out : %04X %02X %04X:%04X %i\n", addr, val, CS,pc, bpp); if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; switch (addr) @@ -32,12 +51,24 @@ void tvga_out(uint16_t addr, uint8_t val) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - tkd8001_ramdac_out(addr,val); - return; + if (gfxcard != GFX_TGUI9440) + { + tkd8001_ramdac_out(addr, val, NULL); + return; + } + break; case 0x3CF: switch (gdcaddr&15) { + case 0x6: + if (gdcreg[6] != val) + { + gdcreg[6] = val; + tvga_recalcmapping(); + } + return; + case 0xE: gdcreg[0xE]=val^2; if ((gdcreg[0xF]&1)==1) @@ -51,7 +82,8 @@ void tvga_out(uint16_t addr, uint8_t val) } break; case 0x3D4: - crtcreg=val&63; + if (gfxcard == GFX_TGUI9440) crtcreg = val & 0x7f; + else crtcreg = val & 0x3f; return; case 0x3D5: if (crtcreg <= 7 && crtc[0x11] & 0x80) return; @@ -66,6 +98,37 @@ void tvga_out(uint16_t addr, uint8_t val) svga_recalctimings(); } } + switch (crtcreg) + { + case 0x21: + if (old != val) + tvga_recalcmapping(); + break; + + + case 0x38: /*Pixel bus register*/ +// pclog("Pixel bus register %02X\n", val); + if (gfxcard != GFX_TGUI9440) + break; + + if ((val & 0xc) == 4) bpp = 16; + else if (!(val & 0xc)) bpp = 8; + else bpp = 24; + break; + + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + svga_hwcursor.x = (crtc[0x40] | (crtc[0x41] << 8)) & 0x7ff; + svga_hwcursor.y = (crtc[0x42] | (crtc[0x43] << 8)) & 0x7ff; + svga_hwcursor.xoff = crtc[0x46] & 0x3f; + svga_hwcursor.yoff = crtc[0x47] & 0x3f; + svga_hwcursor.addr = (crtc[0x44] << 10) | ((crtc[0x45] & 0x7) << 18) | (svga_hwcursor.yoff * 8); + break; + + case 0x50: + svga_hwcursor.ena = val & 0x80; + break; + } return; case 0x3D8: trident3d8=val; @@ -89,12 +152,12 @@ void tvga_out(uint16_t addr, uint8_t val) } return; } - svga_out(addr,val); + svga_out(addr, val, priv); } -uint8_t tvga_in(uint16_t addr) +uint8_t tvga_in(uint16_t addr, void *priv) { - uint8_t temp; +// if (addr != 0x3da) pclog("tvga_in : %04X %04X:%04X\n", addr, CS,pc); if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; @@ -105,7 +168,8 @@ uint8_t tvga_in(uint16_t addr) { // printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); tridentoldmode=0; - return 0x33; /*TVGA8900D*/ + if (gfxcard == GFX_TVGA) return 0x33; /*TVGA8900D*/ + else return 0xe3; /*TGUI9440AGi*/ } if ((seqaddr&0xF)==0xC) { @@ -119,15 +183,21 @@ uint8_t tvga_in(uint16_t addr) } break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return tkd8001_ramdac_in(addr); + if (gfxcard != GFX_TGUI9440) + return tkd8001_ramdac_in(addr, NULL); + break; case 0x3CD: /*Banking*/ return svgaseg; case 0x3D4: return crtcreg; case 0x3D5: return crtc[crtcreg]; + case 0x3d8: + return trident3d8; + case 0x3d9: + return trident3d9; } - return svga_in(addr); + return svga_in(addr, priv); } void tvga_recalctimings() @@ -147,7 +217,9 @@ void tvga_recalctimings() } if (tridentoldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/ svga_lowres=0; - + if (gfxcard == GFX_TGUI9440) + svga_lowres = !(crtc[0x2a] & 0x40); + if (gdcreg[0xF] & 8) { svga_htotal<<=1; @@ -166,16 +238,703 @@ void tvga_recalctimings() case 6: svga_clock = cpuclock/50350000.0; break; case 7: svga_clock = cpuclock/40000000.0; break; } + + if ((tridentoldctrl2 & 0x10) || (gfxcard == GFX_TGUI9440 && (crtc[0x2a] & 0x40))) + { + switch (bpp) + { + case 8: + svga_render = svga_render_8bpp_highres; + break; + case 15: + svga_render = svga_render_15bpp_highres; + break; + case 16: + svga_render = svga_render_16bpp_highres; + break; + case 24: + svga_render = svga_render_24bpp_highres; + break; + case 32: + svga_render = svga_render_32bpp_highres; + break; + } + } +} + +void tvga_recalcmapping() +{ + pclog("tvga_recalcmapping : %02X %02X\n", crtc[0x21], gdcreg[6]); + mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); + mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); + mem_removehandler(0xbc000, 0x4000, tvga_accel_read, NULL, NULL, tvga_accel_write, NULL, NULL, NULL); + + if (crtc[0x21] & 0x20) + { + tvga_linear_base = ((crtc[0x21] & 0xf) | ((crtc[0x21] >> 2) & 0x30)) << 20; + tvga_linear_size = (crtc[0x21] & 0x10) ? 0x200000 : 0x100000; + mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); + pclog("Trident linear framebuffer at %08X - size %06X\n", tvga_linear_base, tvga_linear_size); + mem_sethandler(0xbc000, 0x4000, tvga_accel_read, tvga_accel_read_w, tvga_accel_read_l, tvga_accel_write, tvga_accel_write_w, tvga_accel_write_l, NULL); + } + else + { +// pclog("Write mapping %02X\n", val); + switch (gdcreg[6] & 0xC) + { + case 0x0: /*128k at A0000*/ + mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); + break; + case 0x4: /*64k at A0000*/ + mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); + mem_sethandler(0xbc000, 0x4000, tvga_accel_read, NULL, NULL, tvga_accel_write, NULL, NULL, NULL); + break; + case 0x8: /*32k at B0000*/ + mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); + break; + case 0xC: /*32k at B8000*/ + mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL); + break; + } + } +} + +void tvga_hwcursor_draw(int displine) +{ +// int x; + uint32_t dat[2]; + int xx; + int offset = svga_hwcursor_latch.x - svga_hwcursor_latch.xoff; + +// pclog("HWcursor %i %i\n", svga_hwcursor_latch.x, svga_hwcursor_latch.y); +// for (x = 0; x < 32; x += 32) +// { + dat[0] = (vram[svga_hwcursor_latch.addr] << 24) | (vram[svga_hwcursor_latch.addr + 1] << 16) | (vram[svga_hwcursor_latch.addr + 2] << 8) | vram[svga_hwcursor_latch.addr + 3]; + dat[1] = (vram[svga_hwcursor_latch.addr + 4] << 24) | (vram[svga_hwcursor_latch.addr + 5] << 16) | (vram[svga_hwcursor_latch.addr + 6] << 8) | vram[svga_hwcursor_latch.addr + 7]; + for (xx = 0; xx < 32; xx++) + { + if (offset >= svga_hwcursor_latch.x) + { + if (!(dat[0] & 0x80000000)) + ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x80000000) ? 0xffffff : 0; + else if (dat[1] & 0x80000000) + ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff; +// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]); + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + svga_hwcursor_latch.addr += 8; +// } } int tvga_init() { svga_recalctimings_ex = tvga_recalctimings; - svga_vram_limit = 1 << 20; /*1mb - chip supports 2mb, but drivers are buggy*/ - vrammask = 0xfffff; + svga_hwcursor_draw = tvga_hwcursor_draw; + if (gfxcard == GFX_TVGA) + { + vrammask = 0xfffff; + svga_vram_limit = 1 << 20; /*1mb - chip supports 2mb, but drivers are buggy*/ + } + else + { + vrammask = 0x1fffff; + svga_vram_limit = 1 << 21; /*2mb*/ + } return svga_init(); } +struct tvga_accel +{ + uint16_t src_x, src_y; + uint16_t dst_x, dst_y; + uint16_t size_x, size_y; + uint16_t fg_col, bg_col; + uint8_t rop; + uint16_t flags; + uint8_t pattern[0x80]; + int command; + int offset; + uint8_t ger22; + + int x, y; + uint32_t src, dst, src_old, dst_old; + int pat_x, pat_y; + int use_src; + + int pitch, bpp; +} tvga_accel; + +enum +{ + TGUI_BITBLT = 1 +}; + +enum +{ + TGUI_SRCCPU = 0, + + TGUI_SRCDISP = 0x04, /*Source is from display*/ + TGUI_PATMONO = 0x20, /*Pattern is monochrome and needs expansion*/ + TGUI_SRCMONO = 0x40, /*Source is monochrome from CPU and needs expansion*/ + TGUI_TRANSENA = 0x1000, /*Transparent (no draw when source == bg col)*/ + TGUI_TRANSREV = 0x2000, /*Reverse fg/bg for transparent*/ + TGUI_SOLIDFILL = 0x4000 /*Pattern all zero?*/ +}; + +#define READ(addr, dat) if (tvga_accel.bpp == 0) dat = vram[addr & 0x1fffff]; \ + else dat = vram_w[addr & 0xfffff]; + +#define MIX() do \ + { \ + out = 0; \ + for (c=0;c<16;c++) \ + { \ + d=(dst_dat & (1<> 10] = changeframecount; \ + } \ + else \ + { \ + vram_w[addr & 0xfffff] = dat; \ + changedvram[((addr) & 0xfffff) >> 9] = changeframecount; \ + } + +static uint16_t tvga_pattern[8][8]; + +void tvga_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv); +void tvga_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv); + +void tvga_accel_command(int count, uint32_t cpu_dat) +{ + int x, y; + int c, d; + uint16_t src_dat, dst_dat, pat_dat; + uint16_t out; + int xdir = (tvga_accel.flags & 0x200) ? -1 : 1; + int ydir = (tvga_accel.flags & 0x100) ? -1 : 1; + uint16_t trans_col = (tvga_accel.flags & TGUI_TRANSREV) ? tvga_accel.fg_col : tvga_accel.bg_col; + uint16_t *vram_w = (uint16_t *)vram; + + if (tvga_accel.bpp == 0) + trans_col &= 0xff; + + if (count != -1 && !tvga_accel.x) + { + count -= tvga_accel.offset; + cpu_dat <<= tvga_accel.offset; + } + if (count == -1) + { + tvga_accel.x = tvga_accel.y = 0; + } + if (tvga_accel.flags & TGUI_SOLIDFILL) + { +// pclog("SOLIDFILL\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tvga_pattern[y][x] = tvga_accel.fg_col; + } + } + } + else if (tvga_accel.flags & TGUI_PATMONO) + { +// pclog("PATMONO\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tvga_pattern[y][x] = (tvga_accel.pattern[y] & (1 << x)) ? tvga_accel.fg_col : tvga_accel.bg_col; + } + } + } + else + { +// pclog("OTHER\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tvga_pattern[y][x] = tvga_accel.pattern[x + y*8]; + } + } + } + for (y = 0; y < 8; y++) + { + if (count == -1) pclog("Pattern %i : %02X %02X %02X %02X %02X %02X %02X %02X\n", y, tvga_pattern[y][0], tvga_pattern[y][1], tvga_pattern[y][2], tvga_pattern[y][3], tvga_pattern[y][4], tvga_pattern[y][5], tvga_pattern[y][6], tvga_pattern[y][7]); + } + if (count == -1) pclog("Command %i %i\n", tvga_accel.command, TGUI_BITBLT); + switch (tvga_accel.command) + { + case TGUI_BITBLT: + if (count == -1) pclog("BITBLT src %i,%i dst %i,%i size %i,%i flags %04X\n", tvga_accel.src_x, tvga_accel.src_y, tvga_accel.dst_x, tvga_accel.dst_y, tvga_accel.size_x, tvga_accel.size_y, tvga_accel.flags); + if (count == -1) + { + tvga_accel.src = tvga_accel.src_old = tvga_accel.src_x + (tvga_accel.src_y * tvga_accel.pitch); + tvga_accel.dst = tvga_accel.dst_old = tvga_accel.dst_x + (tvga_accel.dst_y * tvga_accel.pitch); + tvga_accel.pat_x = tvga_accel.dst_x; + tvga_accel.pat_y = tvga_accel.dst_y; + } + + switch (tvga_accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP)) + { + case TGUI_SRCCPU: + if (count == -1) + { +// pclog("Blit start\n"); + if (crtc[0x21] & 0x20) + { + mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); + mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l, NULL); + } + if (tvga_accel.use_src) + return; + } + else + count >>= 3; + while (count) + { + if (tvga_accel.bpp == 0) + { + src_dat = cpu_dat >> 24; + cpu_dat <<= 8; + } + else + { + src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00); + cpu_dat <<= 16; + count--; + } + READ(tvga_accel.dst, dst_dat); + pat_dat = tvga_pattern[tvga_accel.pat_y & 7][tvga_accel.pat_x & 7]; + + if (!(tvga_accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tvga_accel.dst, out); + } + +// pclog(" %i,%i %02X %02X %02X %02X\n", tvga_accel.x, tvga_accel.y, src_dat,dst_dat,pat_dat, out); + + tvga_accel.src += xdir; + tvga_accel.dst += xdir; + tvga_accel.pat_x += xdir; + + tvga_accel.x++; + if (tvga_accel.x > tvga_accel.size_x) + { + tvga_accel.x = 0; + tvga_accel.y++; + + tvga_accel.pat_x = tvga_accel.dst_x; + + tvga_accel.src = tvga_accel.src_old = tvga_accel.src_old + (ydir * tvga_accel.pitch); + tvga_accel.dst = tvga_accel.dst_old = tvga_accel.dst_old + (ydir * tvga_accel.pitch); + tvga_accel.pat_y += ydir; + + if (tvga_accel.y > tvga_accel.size_y) + { + if (crtc[0x21] & 0x20) + { +// pclog("Blit end\n"); + mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l, NULL); + mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); + } + return; + } + if (tvga_accel.use_src) + return; + } + count--; + } + break; + + case TGUI_SRCMONO | TGUI_SRCCPU: + if (count == -1) + { +// pclog("Blit start\n"); + if (crtc[0x21] & 0x20) + { + mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); + mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l, NULL); + } + if (tvga_accel.use_src) + return; + } +// pclog("TGUI_SRCMONO | TGUI_SRCCPU\n"); + while (count) + { + src_dat = ((cpu_dat >> 31) ? tvga_accel.fg_col : tvga_accel.bg_col); + if (tvga_accel.bpp == 0) + src_dat &= 0xff; + + READ(tvga_accel.dst, dst_dat); + pat_dat = tvga_pattern[tvga_accel.pat_y & 7][tvga_accel.pat_x & 7]; + + if (!(tvga_accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tvga_accel.dst, out); + } +// pclog(" %i,%i %02X %02X %02X %02X %i\n", tvga_accel.x, tvga_accel.y, src_dat,dst_dat,pat_dat, out, (!(tvga_accel.flags & TGUI_TRANSENA) || src_dat != trans_col)); + cpu_dat <<= 1; + tvga_accel.src += xdir; + tvga_accel.dst += xdir; + tvga_accel.pat_x += xdir; + + tvga_accel.x++; + if (tvga_accel.x > tvga_accel.size_x) + { + tvga_accel.x = 0; + tvga_accel.y++; + + tvga_accel.pat_x = tvga_accel.dst_x; + + tvga_accel.src = tvga_accel.src_old = tvga_accel.src_old + (ydir * tvga_accel.pitch); + tvga_accel.dst = tvga_accel.dst_old = tvga_accel.dst_old + (ydir * tvga_accel.pitch); + tvga_accel.pat_y += ydir; + + if (tvga_accel.y > tvga_accel.size_y) + { + if (crtc[0x21] & 0x20) + { +// pclog("Blit end\n"); + mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l, NULL); + mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL); + } + return; + } + if (tvga_accel.use_src) + return; + } + count--; + } + break; + + default: + while (count) + { + READ(tvga_accel.src, src_dat); + READ(tvga_accel.dst, dst_dat); + pat_dat = tvga_pattern[tvga_accel.pat_y & 7][tvga_accel.pat_x & 7]; + + if (!(tvga_accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tvga_accel.dst, out); + } +// pclog(" %i,%i %02X %02X %02X %02X\n", tvga_accel.x, tvga_accel.y, src_dat,dst_dat,pat_dat, out); + + tvga_accel.src += xdir; + tvga_accel.dst += xdir; + tvga_accel.pat_x += xdir; + + tvga_accel.x++; + if (tvga_accel.x > tvga_accel.size_x) + { + tvga_accel.x = 0; + tvga_accel.y++; + + tvga_accel.pat_x = tvga_accel.dst_x; + + tvga_accel.src = tvga_accel.src_old = tvga_accel.src_old + (ydir * tvga_accel.pitch); + tvga_accel.dst = tvga_accel.dst_old = tvga_accel.dst_old + (ydir * tvga_accel.pitch); + tvga_accel.pat_y += ydir; + + if (tvga_accel.y > tvga_accel.size_y) + return; + } + count--; + } + break; + } + break; + } +} + +void tvga_accel_write(uint32_t addr, uint8_t val, void *priv) +{ + pclog("tvga_accel_write : %08X %02X %04X(%08X):%08X %02X\n", addr, val, CS,cs,pc, opcode); + if ((addr & ~0xff) != 0xbff00) + return; + switch (addr & 0xff) + { + case 0x22: + tvga_accel.ger22 = val; + tvga_accel.pitch = 512 << ((val >> 2) & 3); + tvga_accel.bpp = (val & 3) ? 1 : 0; + tvga_accel.pitch >>= tvga_accel.bpp; + break; + + case 0x24: /*Command*/ + tvga_accel.command = val; + tvga_accel_command(-1, 0); + break; + + case 0x27: /*ROP*/ + tvga_accel.rop = val; + tvga_accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); + pclog("Write ROP %02X %i\n", val, tvga_accel.use_src); + break; + + case 0x28: /*Flags*/ + tvga_accel.flags = (tvga_accel.flags & 0xff00) | val; + break; + case 0x29: /*Flags*/ + tvga_accel.flags = (tvga_accel.flags & 0xff) | (val << 8); + break; + + case 0x2b: + tvga_accel.offset = val & 7; + break; + + case 0x2c: /*Foreground colour*/ + tvga_accel.fg_col = (tvga_accel.fg_col & 0xff00) | val; + break; + case 0x2d: /*Foreground colour*/ + tvga_accel.fg_col = (tvga_accel.fg_col & 0xff) | (val << 8); + break; + + case 0x30: /*Background colour*/ + tvga_accel.bg_col = (tvga_accel.bg_col & 0xff00) | val; + break; + case 0x31: /*Background colour*/ + tvga_accel.bg_col = (tvga_accel.bg_col & 0xff) | (val << 8); + break; + + case 0x38: /*Dest X*/ + tvga_accel.dst_x = (tvga_accel.dst_x & 0xff00) | val; + break; + case 0x39: /*Dest X*/ + tvga_accel.dst_x = (tvga_accel.dst_x & 0xff) | (val << 8); + break; + case 0x3a: /*Dest Y*/ + tvga_accel.dst_y = (tvga_accel.dst_y & 0xff00) | val; + break; + case 0x3b: /*Dest Y*/ + tvga_accel.dst_y = (tvga_accel.dst_y & 0xff) | (val << 8); + break; + + case 0x3c: /*Src X*/ + tvga_accel.src_x = (tvga_accel.src_x & 0xff00) | val; + break; + case 0x3d: /*Src X*/ + tvga_accel.src_x = (tvga_accel.src_x & 0xff) | (val << 8); + break; + case 0x3e: /*Src Y*/ + tvga_accel.src_y = (tvga_accel.src_y & 0xff00) | val; + break; + case 0x3f: /*Src Y*/ + tvga_accel.src_y = (tvga_accel.src_y & 0xff) | (val << 8); + break; + + case 0x40: /*Size X*/ + tvga_accel.size_x = (tvga_accel.size_x & 0xff00) | val; + break; + case 0x41: /*Size X*/ + tvga_accel.size_x = (tvga_accel.size_x & 0xff) | (val << 8); + break; + case 0x42: /*Size Y*/ + tvga_accel.size_y = (tvga_accel.size_y & 0xff00) | val; + break; + case 0x43: /*Size Y*/ + tvga_accel.size_y = (tvga_accel.size_y & 0xff) | (val << 8); + break; + + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + tvga_accel.pattern[addr & 0x7f] = val; + break; + } +} + +void tvga_accel_write_w(uint32_t addr, uint16_t val, void *priv) +{ + pclog("tvga_accel_write_w %08X %04X\n", addr, val); + tvga_accel_write(addr, val, NULL); + tvga_accel_write(addr + 1, val >> 8, NULL); +} + +void tvga_accel_write_l(uint32_t addr, uint32_t val, void *priv) +{ + pclog("tvga_accel_write_l %08X %08X\n", addr, val); + tvga_accel_write(addr, val, NULL); + tvga_accel_write(addr + 1, val >> 8, NULL); + tvga_accel_write(addr + 2, val >> 16, NULL); + tvga_accel_write(addr + 3, val >> 24, NULL); +} + +uint8_t tvga_accel_read(uint32_t addr, void *priv) +{ +// pclog("tvga_accel_read : %08X\n", addr); + if ((addr & ~0xff) != 0xbff00) + return 0xff; + switch (addr & 0xff) + { + case 0x20: /*Status*/ + return 0; + + case 0x27: /*ROP*/ + return tvga_accel.rop; + + case 0x28: /*Flags*/ + return tvga_accel.flags & 0xff; + case 0x29: /*Flags*/ + return tvga_accel.flags >> 8; + + case 0x2b: + return tvga_accel.offset; + + case 0x2c: /*Background colour*/ + return tvga_accel.bg_col & 0xff; + case 0x2d: /*Background colour*/ + return tvga_accel.bg_col >> 8; + + case 0x30: /*Foreground colour*/ + return tvga_accel.fg_col & 0xff; + case 0x31: /*Foreground colour*/ + return tvga_accel.fg_col >> 8; + + case 0x38: /*Dest X*/ + return tvga_accel.dst_x & 0xff; + case 0x39: /*Dest X*/ + return tvga_accel.dst_x >> 8; + case 0x3a: /*Dest Y*/ + return tvga_accel.dst_y & 0xff; + case 0x3b: /*Dest Y*/ + return tvga_accel.dst_y >> 8; + + case 0x3c: /*Src X*/ + return tvga_accel.src_x & 0xff; + case 0x3d: /*Src X*/ + return tvga_accel.src_x >> 8; + case 0x3e: /*Src Y*/ + return tvga_accel.src_y & 0xff; + case 0x3f: /*Src Y*/ + return tvga_accel.src_y >> 8; + + case 0x40: /*Size X*/ + return tvga_accel.size_x & 0xff; + case 0x41: /*Size X*/ + return tvga_accel.size_x >> 8; + case 0x42: /*Size Y*/ + return tvga_accel.size_y & 0xff; + case 0x43: /*Size Y*/ + return tvga_accel.size_y >> 8; + + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return tvga_accel.pattern[addr & 0x7f]; + } + return 0xff; +} + +uint16_t tvga_accel_read_w(uint32_t addr, void *priv) +{ + pclog("tvga_accel_read_w %08X\n", addr); + return tvga_accel_read(addr, NULL) | (tvga_accel_read(addr + 1, NULL) << 8); +} + +uint32_t tvga_accel_read_l(uint32_t addr, void *priv) +{ + pclog("tvga_accel_read_l %08X\n", addr); + return tvga_accel_read_w(addr, NULL) | (tvga_accel_read_w(addr + 2, NULL) << 16); +} + +void tvga_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv) +{ +// pclog("tvga_accel_write_fb_b %08X %02X\n", addr, val); + tvga_accel_command(8, val << 24); +} + +void tvga_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv) +{ +// pclog("tvga_accel_write_fb_w %08X %04X\n", addr, val); + tvga_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16); +} + +void tvga_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv) +{ +// pclog("tvga_accel_write_fb_l %08X %08X\n", addr, val); + tvga_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); +} + GFXCARD vid_tvga = { tvga_init, @@ -197,3 +956,27 @@ GFXCARD vid_tvga = video_read_null, video_read_null }; + +GFXCARD vid_tgui9440 = +{ + tvga_init, + /*IO at 3Cx/3Dx*/ + tvga_out, + tvga_in, + /*IO at 3Ax/3Bx*/ + video_out_null, + video_in_null, + + svga_poll, + svga_recalctimings, + + svga_write, + video_write_null, + video_write_null, + + svga_read, + video_read_null, + video_read_null +}; + + diff --git a/src/vid_unk_ramdac.c b/src/vid_unk_ramdac.c index d70d9aa..964826a 100644 --- a/src/vid_unk_ramdac.c +++ b/src/vid_unk_ramdac.c @@ -9,7 +9,7 @@ static int unk_state=0; static uint8_t unk_ctrl; -void unk_ramdac_out(uint16_t addr, uint8_t val) +void unk_ramdac_out(uint16_t addr, uint8_t val, void *priv) { //pclog("OUT RAMDAC %04X %02X\n",addr,val); switch (addr) @@ -42,10 +42,10 @@ void unk_ramdac_out(uint16_t addr, uint8_t val) unk_state = 0; break; } - svga_out(addr,val); + svga_out(addr, val, NULL); } -uint8_t unk_ramdac_in(uint16_t addr) +uint8_t unk_ramdac_in(uint16_t addr, void *priv) { //pclog("IN RAMDAC %04X\n",addr); switch (addr) @@ -62,5 +62,5 @@ uint8_t unk_ramdac_in(uint16_t addr) unk_state = 0; break; } - return svga_in(addr); + return svga_in(addr, NULL); } diff --git a/src/vid_unk_ramdac.h b/src/vid_unk_ramdac.h index 1f05aac..b4f1406 100644 --- a/src/vid_unk_ramdac.h +++ b/src/vid_unk_ramdac.h @@ -1,2 +1,2 @@ -void unk_ramdac_out(uint16_t addr, uint8_t val); -uint8_t unk_ramdac_in(uint16_t addr); +void unk_ramdac_out(uint16_t addr, uint8_t val, void *priv); +uint8_t unk_ramdac_in(uint16_t addr, void *priv); diff --git a/src/video.c b/src/video.c index f9ee7de..c87fb36 100644 --- a/src/video.c +++ b/src/video.c @@ -5,6 +5,9 @@ #include "vid_svga.h" #include "io.h" #include "cpu.h" +#include "timer.h" + +int video_timer; /*Video timing settings - @@ -81,46 +84,46 @@ int video_res_x, video_res_y, video_bpp; void (*video_blit_memtoscreen)(int x, int y, int y1, int y2, int w, int h); void (*video_blit_memtoscreen_8)(int x, int y, int w, int h); -void (*video_out) (uint16_t addr, uint8_t val); -void (*video_mono_out)(uint16_t addr, uint8_t val); -uint8_t (*video_in) (uint16_t addr); -uint8_t (*video_mono_in)(uint16_t addr); +void (*video_out) (uint16_t addr, uint8_t val, void *priv); +void (*video_mono_out)(uint16_t addr, uint8_t val, void *priv); +uint8_t (*video_in) (uint16_t addr, void *priv); +uint8_t (*video_mono_in)(uint16_t addr, void *priv); -void (*video_write_a000)(uint32_t addr, uint8_t val); -void (*video_write_b000)(uint32_t addr, uint8_t val); -void (*video_write_b800)(uint32_t addr, uint8_t val); +void (*video_write_a000)(uint32_t addr, uint8_t val, void *priv); +void (*video_write_b000)(uint32_t addr, uint8_t val, void *priv); +void (*video_write_b800)(uint32_t addr, uint8_t val, void *priv); -void (*video_write_a000_w)(uint32_t addr, uint16_t val); -void (*video_write_a000_l)(uint32_t addr, uint32_t val); +void (*video_write_a000_w)(uint32_t addr, uint16_t val, void *priv); +void (*video_write_a000_l)(uint32_t addr, uint32_t val, void *priv); -uint8_t (*video_read_a000)(uint32_t addr); -uint8_t (*video_read_b000)(uint32_t addr); -uint8_t (*video_read_b800)(uint32_t addr); +uint8_t (*video_read_a000)(uint32_t addr, void *priv); +uint8_t (*video_read_b000)(uint32_t addr, void *priv); +uint8_t (*video_read_b800)(uint32_t addr, void *priv); void (*video_recalctimings)(); -void video_out_null(uint16_t addr, uint8_t val) +void video_out_null(uint16_t addr, uint8_t val, void *priv) { } -uint8_t video_in_null(uint16_t addr) +uint8_t video_in_null(uint16_t addr, void *priv) { return 0xFF; } -void video_write_null(uint32_t addr, uint8_t val) +void video_write_null(uint32_t addr, uint8_t val, void *priv) { } -uint8_t video_read_null(uint32_t addr) +uint8_t video_read_null(uint32_t addr, void *priv) { return 0xff; } void video_load(GFXCARD g) { - io_sethandler(0x03a0, 0x0020, g.mono_in, NULL, NULL, g.mono_out, NULL, NULL); - io_sethandler(0x03c0, 0x0020, g.in, NULL, NULL, g.out, NULL, NULL); + io_sethandler(0x03a0, 0x0020, g.mono_in, NULL, NULL, g.mono_out, NULL, NULL, NULL); + io_sethandler(0x03c0, 0x0020, g.in, NULL, NULL, g.out, NULL, NULL, NULL); video_out = g.out; video_in = g.in; @@ -141,6 +144,8 @@ void video_load(GFXCARD g) video_write_a000_w = video_write_a000_l = NULL; g.init(); + + video_timer = timer_add(pollvideo, &vidtime, TIMER_ALWAYS_ENABLED, NULL); } void video_init() @@ -221,6 +226,38 @@ void video_init() video_load(vid_s3); break; + case GFX_VIRGE: + video_load(vid_s3_virge); + break; + + case GFX_TGUI9440: + video_load(vid_tgui9440); + break; + + case GFX_VGA: + video_load(vid_vga); + break; + + case GFX_VGAEDGE16: + video_load(vid_ati18800); + break; + + case GFX_VGACHARGER: + video_load(vid_ati28800); + break; + + case GFX_OTI067: + video_load(vid_oti067); + return; + + case GFX_MACH64GX: + video_load(vid_mach64); + return; + + case GFX_CL_GD5429: + video_load(vid_gd5429); + return; + default: fatal("Bad gfx card %i\n",gfxcard); } @@ -235,7 +272,8 @@ int speshul=0; uint8_t fontdat[256][8]; uint8_t fontdatm[256][16]; -float dispontime,dispofftime,disptime; +int dispontime,dispofftime; +double disptime; int svgaon; uint8_t cgamode=1,cgastat,cgacol=7,ocgamode; int linepos=0; @@ -404,7 +442,7 @@ PALETTE comppal= void initvideo() { - int c,d; + int c; // set_color_depth(desktop_color_depth()); // if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,2048,2048,0,0)) // set_gfx_mode(GFX_AUTODETECT_WINDOWED,1024,768,0,0); @@ -473,18 +511,6 @@ void resetvideo() mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; -/* switch (gfxcard) - { - case GFX_CGA: pollvideo=pollcga; break; - case GFX_MDA: - case GFX_HERCULES: pollvideo=pollmda; break; - } - if (TANDY) pollvideo=polltandy; - if (EGA) pollvideo=pollega; - if (romset==ROM_PC1512 || romset==ROM_PC200) pollvideo=pollcga;*/ -// tandyvram=&ram[0x9C000]; -// printf("Tandy VRAM %08X\n",tandyvram); -// tandyb8000=&ram[0x9C000]; } void closevideo() diff --git a/src/video.h b/src/video.h index 5f3d3a0..2909fad 100644 --- a/src/video.h +++ b/src/video.h @@ -10,7 +10,7 @@ extern uint8_t gdcreg[16]; extern int gdcaddr; extern uint8_t attrregs[32]; extern int attraddr,attrff; -extern uint8_t seqregs[32]; +extern uint8_t seqregs[64]; extern int seqaddr; extern int svgaon; @@ -34,31 +34,34 @@ extern int changeframecount; extern int firstline,lastline; extern int ega_hdisp,ega_rowoffset,ega_split,ega_dispend,ega_vsyncstart,ega_vtotal; -extern float dispontime,dispofftime,disptime; +extern int dispontime,dispofftime; +extern double disptime; -extern void (*video_out) (uint16_t addr, uint8_t val); -extern void (*video_mono_out)(uint16_t addr, uint8_t val); -extern uint8_t (*video_in) (uint16_t addr); -extern uint8_t (*video_mono_in)(uint16_t addr); +extern void (*video_out) (uint16_t addr, uint8_t val, void *priv); +extern void (*video_mono_out)(uint16_t addr, uint8_t val, void *priv); +extern uint8_t (*video_in) (uint16_t addr, void *priv); +extern uint8_t (*video_mono_in)(uint16_t addr, void *priv); -extern void (*video_write_a000)(uint32_t addr, uint8_t val); -extern void (*video_write_b000)(uint32_t addr, uint8_t val); -extern void (*video_write_b800)(uint32_t addr, uint8_t val); +extern void (*video_write_a000)(uint32_t addr, uint8_t val, void *priv); +extern void (*video_write_b000)(uint32_t addr, uint8_t val, void *priv); +extern void (*video_write_b800)(uint32_t addr, uint8_t val, void *priv); -extern uint8_t (*video_read_a000)(uint32_t addr); -extern uint8_t (*video_read_b000)(uint32_t addr); -extern uint8_t (*video_read_b800)(uint32_t addr); +extern uint8_t (*video_read_a000)(uint32_t addr, void *priv); +extern uint8_t (*video_read_b000)(uint32_t addr, void *priv); +extern uint8_t (*video_read_b800)(uint32_t addr, void *priv); -extern void (*video_write_a000_w)(uint32_t addr, uint16_t val); -extern void (*video_write_a000_l)(uint32_t addr, uint32_t val); +extern void (*video_write_a000_w)(uint32_t addr, uint16_t val, void *priv); +extern void (*video_write_a000_l)(uint32_t addr, uint32_t val, void *priv); -extern void video_out_null(uint16_t addr, uint8_t val); -extern uint8_t video_in_null(uint16_t addr); +extern void video_out_null(uint16_t addr, uint8_t val, void *priv); +extern uint8_t video_in_null(uint16_t addr, void *priv); -extern void video_write_null(uint32_t addr, uint8_t val); -extern uint8_t video_read_null (uint32_t addr); +extern void video_write_null(uint32_t addr, uint8_t val, void *priv); +extern uint8_t video_read_null (uint32_t addr, void *priv); +extern int video_timer; + extern uint8_t tridentoldctrl2,tridentnewctrl2; extern int rowdbl; @@ -73,6 +76,8 @@ extern BITMAP *buffer,*buffer32,*vbuf; extern BITMAP *screen; +BITMAP *create_bitmap(int w, int h); + extern int wx,wy; extern uint8_t fontdat[256][8]; @@ -98,18 +103,18 @@ extern uint32_t vrammask; typedef struct { int (*init)(); - void (*out)(uint16_t addr, uint8_t val); - uint8_t (*in)(uint16_t addr); - void (*mono_out)(uint16_t addr, uint8_t val); - uint8_t (*mono_in)(uint16_t addr); + void (*out)(uint16_t addr, uint8_t val, void *priv); + uint8_t (*in)(uint16_t addr, void *priv); + void (*mono_out)(uint16_t addr, uint8_t val, void *priv); + uint8_t (*mono_in)(uint16_t addr, void *priv); void (*poll)(); void (*recalctimings)(); - void (*write_a000)(uint32_t addr, uint8_t val); - void (*write_b000)(uint32_t addr, uint8_t val); - void (*write_b800)(uint32_t addr, uint8_t val); - uint8_t (*read_a000)(uint32_t addr); - uint8_t (*read_b000)(uint32_t addr); - uint8_t (*read_b800)(uint32_t addr); + void (*write_a000)(uint32_t addr, uint8_t val, void *priv); + void (*write_b000)(uint32_t addr, uint8_t val, void *priv); + void (*write_b800)(uint32_t addr, uint8_t val, void *priv); + uint8_t (*read_a000)(uint32_t addr, void *priv); + uint8_t (*read_b000)(uint32_t addr, void *priv); + uint8_t (*read_b800)(uint32_t addr, void *priv); } GFXCARD; extern GFXCARD vid_cga; @@ -127,7 +132,13 @@ extern GFXCARD vid_tvga; extern GFXCARD vid_et4000; extern GFXCARD vid_et4000w32p; extern GFXCARD vid_s3; - +extern GFXCARD vid_s3_virge; +extern GFXCARD vid_tgui9440; +extern GFXCARD vid_vga; +extern GFXCARD vid_ati18800; +extern GFXCARD vid_ati28800; +extern GFXCARD vid_mach64; +extern GFXCARD vid_gd5429; extern float cpuclock; diff --git a/src/wd76c10.c b/src/wd76c10.c index a5b96b0..75bd78f 100644 --- a/src/wd76c10.c +++ b/src/wd76c10.c @@ -10,7 +10,7 @@ static uint16_t wd76c10_2072; static uint16_t wd76c10_2872; static uint16_t wd76c10_5872; -uint16_t wd76c10_read(uint16_t port) +uint16_t wd76c10_read(uint16_t port, void *priv) { switch (port) { @@ -29,7 +29,7 @@ uint16_t wd76c10_read(uint16_t port) return 0; } -void wd76c10_write(uint16_t port, uint16_t val) +void wd76c10_write(uint16_t port, uint16_t val, void *priv) { pclog("WD76C10 write %04X %04X\n", port, val); switch (port) @@ -68,7 +68,7 @@ void wd76c10_write(uint16_t port, uint16_t val) fdc_remove(); if (!(val & 1)) - fdc_init(); + fdc_add(); break; case 0x5872: @@ -77,26 +77,26 @@ void wd76c10_write(uint16_t port, uint16_t val) } } -uint8_t wd76c10_readb(uint16_t port) +uint8_t wd76c10_readb(uint16_t port, void *priv) { if (port & 1) - return wd76c10_read(port & ~1) >> 8; - return wd76c10_read(port) & 0xff; + return wd76c10_read(port & ~1, priv) >> 8; + return wd76c10_read(port, priv) & 0xff; } -void wd76c10_writeb(uint16_t port, uint8_t val) +void wd76c10_writeb(uint16_t port, uint8_t val, void *priv) { - uint16_t temp = wd76c10_read(port); + uint16_t temp = wd76c10_read(port, priv); if (port & 1) - wd76c10_write(port & ~1, (temp & 0x00ff) | (val << 8)); + wd76c10_write(port & ~1, (temp & 0x00ff) | (val << 8), priv); else - wd76c10_write(port , (temp & 0xff00) | val); + wd76c10_write(port , (temp & 0xff00) | val, priv); } void wd76c10_init() { - io_sethandler(0x0092, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL); - io_sethandler(0x2072, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL); - io_sethandler(0x2872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL); - io_sethandler(0x5872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL); + io_sethandler(0x0092, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL, NULL); + io_sethandler(0x2072, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL, NULL); + io_sethandler(0x2872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL, NULL); + io_sethandler(0x5872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL, NULL); } diff --git a/src/win-video.c b/src/win-video.c index 1df1a89..ce763b2 100644 --- a/src/win-video.c +++ b/src/win-video.c @@ -1,4 +1,6 @@ #include +#include +#include #include "video.h" BITMAP *screen; diff --git a/src/win.c b/src/win.c index 898ddfd..52c5237 100644 --- a/src/win.c +++ b/src/win.c @@ -15,6 +15,8 @@ #include "video.h" #include "resources.h" #include "ide.h" +#include "nvr.h" +#include "sound.h" #include "plat-keyboard.h" @@ -25,7 +27,7 @@ #define TIMER_1SEC 1 int winsizex=640,winsizey=480; -int svgapresent, et4000w32_present, bahamas64_present, n9_9fx_present; +int gfx_present[18]; int wakeups,wokeups; #undef cs CRITICAL_SECTION cs; @@ -44,8 +46,6 @@ void endmainthread(); void endsoundthread(); void silencesound(); void restoresound(); -static HANDLE soundobject; - static HANDLE frameobject; int infocus=1; @@ -61,7 +61,7 @@ void vsyncint() // } } -int romspresent[25]; +int romspresent[26]; int quited=0; RECT oldclip,pcclip; @@ -99,11 +99,6 @@ void releasemouse() } } -static LARGE_INTEGER counter_base; -static LARGE_INTEGER counter_freq; -static LARGE_INTEGER counter_pos; -static LARGE_INTEGER counter_posold; - void setrefresh(int rate) { return; @@ -155,6 +150,7 @@ int pause=0; void mainthread(LPVOID param) { int t = 0; + int frames = 0; DWORD old_time, new_time; mainthreadon=1; // Sleep(500); @@ -190,12 +186,19 @@ void mainthread(LPVOID param) runpc(); // ddraw_draw(); endblit(); + frames++; + if (frames >= 200 && nvr_dosave) + { + frames = 0; + nvr_dosave = 0; + savenvr(); + } //#if 0 //#endif } else { -// Sleep(1); + Sleep(1); } // } } @@ -246,9 +249,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, HWND hwnd; /* This is the handle for our window */ MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ - int c,d; - FILE *f; - int oldinfocus=0; + int c, d; hinstance=hThisInstance; /* The Window structure */ @@ -317,19 +318,19 @@ int WINAPI WinMain (HINSTANCE hThisInstance, // set_display_switch_mode(SWITCH_BACKGROUND); d=romset; - for (c=0;c<25;c++) + for (c=0;c<26;c++) { romset=c; romspresent[c]=loadbios(); pclog("romset %i - %i\n", c, romspresent[c]); } - for (c = 0; c < 25; c++) + for (c = 0; c < 26; c++) { if (romspresent[c]) break; } - if (c == 25) + if (c == 26) { MessageBox(hwnd,"No ROMs present!\nYou must have at least one romset to use PCem.","PCem fatal error",MB_OK); return 0; @@ -340,8 +341,8 @@ int WINAPI WinMain (HINSTANCE hThisInstance, if (!c) { - if (romset!=-1) MessageBox(hwnd,"Configured romset not available.\nDefaulting to available romset.","PCemu error",MB_OK); - for (c=0;c<25;c++) + if (romset!=-1) MessageBox(hwnd,"Configured romset not available.\nDefaulting to available romset.","PCem error",MB_OK); + for (c=0;c<26;c++) { if (romspresent[c]) { @@ -352,60 +353,26 @@ int WINAPI WinMain (HINSTANCE hThisInstance, } } - f=romfopen("roms/trident.bin","rb"); - if (f) + d = gfxcard; + for (c = 0; c < 18; c++) { - fclose(f); - vgapresent=1; + gfxcard = c; + gfx_present[c] = mem_load_video_bios(); } - else + gfxcard = d; + c = mem_load_video_bios(); + if (!c) { - vgapresent=0; - if (gfxcard==GFX_TVGA) gfxcard=GFX_CGA; - } - f=romfopen("roms/et4000.bin","rb"); - if (f) - { - fclose(f); - svgapresent=1; - } - else - { - svgapresent=0; - if (gfxcard==GFX_ET4000) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA; - } - f=romfopen("roms/et4000w32.bin","rb"); - if (f) - { - fclose(f); - et4000w32_present=1; - } - else - { - et4000w32_present=0; - if (gfxcard==GFX_ET4000W32) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA; - } - f=romfopen("roms/bahamas64.bin","rb"); - if (f) - { - fclose(f); - bahamas64_present=1; - } - else - { - bahamas64_present=0; - if (gfxcard==GFX_BAHAMAS64) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA; - } - f=romfopen("roms/s3_764.bin","rb"); - if (f) - { - fclose(f); - n9_9fx_present=1; - } - else - { - n9_9fx_present=0; - if (gfxcard==GFX_N9_9FX) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA; + if (romset!=-1) MessageBox(hwnd,"Configured video BIOS not available.\nDefaulting to available romset.","PCem error",MB_OK); + for (c=0;c<18;c++) + { + if (gfx_present[c]) + { + gfxcard = c; + mem_load_video_bios(); + break; + } + } } timeBeginPeriod(1); // soundobject=CreateEvent(NULL, FALSE, FALSE, NULL); @@ -505,7 +472,6 @@ char openfilestring[260]; int getfile(HWND hwnd, char *f, char *fn) { OPENFILENAME ofn; // common dialog box structure - char szFile[260]; // buffer for file name BOOL r; DWORD err; @@ -546,7 +512,6 @@ int getfile(HWND hwnd, char *f, char *fn) int getsfile(HWND hwnd, char *f, char *fn) { OPENFILENAME ofn; // common dialog box structure - char szFile[260]; // buffer for file name BOOL r; DWORD err; @@ -585,12 +550,18 @@ int getsfile(HWND hwnd, char *f, char *fn) } extern int is486; -int romstolist[25], listtomodel[23], romstomodel[25], modeltolist[23]; -int vidtolist[10],listtovid[10]; +int romstolist[26], listtomodel[26], romstomodel[26], modeltolist[26]; +int vidtolist[20],listtovid[20]; -int mem_list_to_size[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,32,48,64}; +int mem_list_to_size[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,32,48,64,256}; int mem_size_to_list[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,18}; + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,18, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19}; #include "cpu.h" #include "model.h" @@ -601,13 +572,14 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara int c, d; int rom,gfx,mem,fpu; int temp_cpu, temp_cpu_m, temp_model; + int temp_GAMEBLASTER, temp_GUS, temp_sound_card_current; // pclog("Dialog msg %i %08X\n",message,message); switch (message) { case WM_INITDIALOG: pause=1; h=GetDlgItem(hdlg,IDC_COMBO1); - for (c=0;c<25;c++) romstolist[c]=0; + for (c=0;c<26;c++) romstolist[c]=0; c = d = 0; while (models[c].id != -1) { @@ -632,11 +604,19 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"MDA"); vidtolist[GFX_MDA]=1; listtovid[1]=1; SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Hercules"); vidtolist[GFX_HERCULES]=2; listtovid[2]=2; SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"EGA"); vidtolist[GFX_EGA]=3; listtovid[3]=3; - if (vgapresent) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Trident 8900D"); vidtolist[GFX_TVGA]=c; listtovid[c]=GFX_TVGA; c++; } - if (svgapresent) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Tseng ET4000AX"); vidtolist[GFX_ET4000]=c; listtovid[c]=GFX_ET4000; c++; } - if (et4000w32_present) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Diamond Stealth 32"); vidtolist[GFX_ET4000W32]=c; listtovid[c]=GFX_ET4000W32; c++; } - if (bahamas64_present) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Paradise Bahamas 64"); vidtolist[GFX_BAHAMAS64]=c; listtovid[c]=GFX_BAHAMAS64; c++; } - if (n9_9fx_present) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Number Nine 9FX"); vidtolist[GFX_N9_9FX]=c; listtovid[c]=GFX_N9_9FX; c++; } + if (gfx_present[GFX_TVGA]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Trident 8900D"); vidtolist[GFX_TVGA]=c; listtovid[c]=GFX_TVGA; c++; } + if (gfx_present[GFX_ET4000]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Tseng ET4000AX"); vidtolist[GFX_ET4000]=c; listtovid[c]=GFX_ET4000; c++; } + if (gfx_present[GFX_ET4000W32]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Diamond Stealth 32"); vidtolist[GFX_ET4000W32]=c; listtovid[c]=GFX_ET4000W32; c++; } + if (gfx_present[GFX_BAHAMAS64]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Paradise Bahamas 64"); vidtolist[GFX_BAHAMAS64]=c; listtovid[c]=GFX_BAHAMAS64; c++; } + if (gfx_present[GFX_N9_9FX]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Number Nine 9FX"); vidtolist[GFX_N9_9FX]=c; listtovid[c]=GFX_N9_9FX; c++; } + if (gfx_present[GFX_VIRGE]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"S3 VIRGE"); vidtolist[GFX_VIRGE]=c; listtovid[c]=GFX_VIRGE; c++; } + if (gfx_present[GFX_TGUI9440]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Trident TGUI9440"); vidtolist[GFX_TGUI9440]=c; listtovid[c]=GFX_TGUI9440; c++; } + if (gfx_present[GFX_VGA]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"VGA"); vidtolist[GFX_VGA]=c; listtovid[c]=GFX_VGA; c++; } + if (gfx_present[GFX_VGAEDGE16]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"ATI VGA Edge-16"); vidtolist[GFX_VGAEDGE16]=c; listtovid[c]=GFX_VGAEDGE16; c++; } + if (gfx_present[GFX_VGACHARGER]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"ATI VGA Charger"); vidtolist[GFX_VGACHARGER]=c; listtovid[c]=GFX_VGACHARGER; c++; } + if (gfx_present[GFX_OTI067]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Oak OTI-067"); vidtolist[GFX_OTI067]=c; listtovid[c]=GFX_OTI067; c++; } + if (gfx_present[GFX_MACH64GX]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"ATI Graphics Pro Turbo"); vidtolist[GFX_MACH64GX]=c; listtovid[c]=GFX_MACH64GX; c++; } + if (gfx_present[GFX_CL_GD5429]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Cirrus Logic CL-GD5429"); vidtolist[GFX_CL_GD5429]=c; listtovid[c]=GFX_CL_GD5429; c++; } SendMessage(h,CB_SETCURSEL,vidtolist[gfxcard],0); if (models[model].fixed_gfxcard) EnableWindow(h,FALSE); @@ -663,30 +643,30 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara SendMessage(h, CB_SETCURSEL, cpu, 0); h=GetDlgItem(hdlg,IDC_COMBOSND); - SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"None"); - SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"AdLib"); - SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v1.0"); - SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v1.5"); - SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v2.0"); - SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SB Pro v1"); - SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SB Pro v2"); - SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster 16"); - SendMessage(h,CB_SETCURSEL,sbtype,0); + c = 0; + while (1) + { + char *s = sound_card_getname(c); -// h=GetDlgItem(hdlg,IDC_CHECK2); -// SendMessage(h,BM_SETCHECK,ADLIB,0); + if (!s[0]) + break; + + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + c++; + } + SendMessage(h, CB_SETCURSEL, sound_card_current, 0); + + h=GetDlgItem(hdlg, IDC_CHECK3); + SendMessage(h, BM_SETCHECK, GAMEBLASTER, 0); + + h=GetDlgItem(hdlg, IDC_CHECKGUS); + SendMessage(h, BM_SETCHECK, GUS, 0); - h=GetDlgItem(hdlg,IDC_CHECK3); - SendMessage(h,BM_SETCHECK,GAMEBLASTER,0); - - h=GetDlgItem(hdlg,IDC_CHECK1); - SendMessage(h,BM_SETCHECK,FASTDISC,0); + h=GetDlgItem(hdlg, IDC_CHECK2); + SendMessage(h, BM_SETCHECK, slowega, 0); - h=GetDlgItem(hdlg,IDC_CHECK2); - SendMessage(h,BM_SETCHECK,slowega,0); - - h=GetDlgItem(hdlg,IDC_CHECK4); - SendMessage(h,BM_SETCHECK,cga_comp,0); + h=GetDlgItem(hdlg, IDC_CHECK4); + SendMessage(h, BM_SETCHECK, cga_comp, 0); h=GetDlgItem(hdlg,IDC_COMBOCHC); SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"A little"); @@ -725,6 +705,7 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"32 MB"); SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"48 MB"); SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"64 MB"); + SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"256 MB"); SendMessage(h,CB_SETCURSEL,mem_size_to_list[mem_size-1],0); pclog("Init cpuspeed %i\n",cpuspeed); @@ -750,7 +731,16 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara fpu = (models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type >= CPU_i486DX) ? 1 : 0; pclog("newcpu - %i %i %i %i\n",temp_cpu_m,temp_cpu,fpu,models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type); - if (temp_model != model || gfx!=gfxcard || mem!=mem_size || fpu!=hasfpu) + h = GetDlgItem(hdlg, IDC_CHECK3); + temp_GAMEBLASTER = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECKGUS); + temp_GUS = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_COMBOSND); + temp_sound_card_current = SendMessage(h, CB_GETCURSEL, 0, 0); + + if (temp_model != model || gfx != gfxcard || mem != mem_size || fpu != hasfpu || temp_GAMEBLASTER != GAMEBLASTER || temp_GUS != GUS || temp_sound_card_current != sound_card_current) { if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL)==IDOK) { @@ -760,9 +750,13 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara mem_size=mem; cpu_manufacturer = temp_cpu_m; cpu = temp_cpu; + GAMEBLASTER = temp_GAMEBLASTER; + GUS = temp_GUS; + sound_card_current = temp_sound_card_current; mem_resize(); loadbios(); + mem_load_video_bios(); resetpchard(); } else @@ -776,12 +770,6 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara h=GetDlgItem(hdlg,IDC_COMBOSPD); video_speed = SendMessage(h,CB_GETCURSEL,0,0); - h=GetDlgItem(hdlg,IDC_CHECK3); - GAMEBLASTER=SendMessage(h,BM_GETCHECK,0,0); - - h=GetDlgItem(hdlg,IDC_CHECK1); - FASTDISC=SendMessage(h,BM_GETCHECK,0,0); - h=GetDlgItem(hdlg,IDC_CHECK4); cga_comp=SendMessage(h,BM_GETCHECK,0,0); @@ -789,9 +777,6 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara cpu = temp_cpu; cpu_set(); - h=GetDlgItem(hdlg,IDC_COMBOSND); - sbtype=SendMessage(h,CB_GETCURSEL,0,0); - h=GetDlgItem(hdlg,IDC_COMBOCHC); cache=SendMessage(h,CB_GETCURSEL,0,0); mem_updatecache(); @@ -890,7 +875,6 @@ BOOL CALLBACK hdnewdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam HWND h; int c; PcemHDC hd[2]; - int changeddrv=0; FILE *f; uint8_t buf[512]; switch (message) @@ -1004,11 +988,7 @@ BOOL CALLBACK hdsizedlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara { char s[260]; HWND h; - int c; PcemHDC hd[2]; - int changeddrv=0; - FILE *f; - uint8_t buf[512]; switch (message) { case WM_INITDIALOG: @@ -1090,9 +1070,7 @@ BOOL CALLBACK hdconfdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara { char s[260]; HWND h; - int c; PcemHDC hd[2]; - int changeddrv=0; FILE *f; off64_t sz; switch (message) @@ -1344,8 +1322,6 @@ BOOL CALLBACK hdconfdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int c; int egasp; char s[256]; switch (message) @@ -1374,12 +1350,12 @@ BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara if (chain4) sprintf(s,"VGA chained (possibly mode 13h)"); else sprintf(s,"VGA unchained (possibly mode-X)"); SendDlgItemMessage(hdlg,IDC_STEXT9,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); - if (!video_bpp) sprintf(s,"VGA in text mode"); - else sprintf(s,"VGA colour depth : %i bpp", video_bpp); +/* if (!video_bpp) sprintf(s,"VGA in text mode"); + else */sprintf(s,"VGA colour depth : %i bpp", video_bpp); SendDlgItemMessage(hdlg,IDC_STEXT10,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); sprintf(s,"VGA resolution : %i x %i", video_res_x, video_res_y); SendDlgItemMessage(hdlg,IDC_STEXT11,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); - sprintf(s,"SB frequency : %i Hz",sb_freq); + sprintf(s,"SB frequency : %i Hz",0); SendDlgItemMessage(hdlg,IDC_STEXT12,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); sprintf(s,"Video refresh rate : %i Hz", emu_fps); SendDlgItemMessage(hdlg,IDC_STEXT13,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); @@ -1421,9 +1397,6 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM { HMENU hmenu; RECT rect; - int c; - int x, y; - POINT po; // pclog("Message %i %08X\n",message,message); switch (message) { diff --git a/src/x86.h b/src/x86.h index d0fe652..6c8cef9 100644 --- a/src/x86.h +++ b/src/x86.h @@ -1,4 +1,3 @@ -uint32_t old8,old82,old83; uint16_t oldcs; uint32_t oldpc; extern uint32_t rmdat32; @@ -16,11 +15,9 @@ int skipnextprint; int inhlt; uint8_t opcode; -int ins,noint,notpresent; -int inint; +int ins,noint; uint16_t lastcs,lastpc; -int lldt; int timetolive,keyboardtimer; #define setznp168 setznp16 @@ -96,3 +93,7 @@ extern uint8_t opcode2; extern uint16_t rds; extern uint32_t rmdat32; + +extern int inscounts[256]; + +void x86illegal(); diff --git a/src/x86_flags.h b/src/x86_flags.h index 9dc8eea..391c901 100644 --- a/src/x86_flags.h +++ b/src/x86_flags.h @@ -1,17 +1,387 @@ -static inline void setznp8(uint8_t val) +enum { - flags&=~0x8d5; - flags|=znptable8[val]; + FLAGS_UNKNOWN, + + FLAGS_ZN8, + FLAGS_ZN16, + FLAGS_ZN32, + + FLAGS_ADD8, + FLAGS_ADD16, + FLAGS_ADD32, + + FLAGS_SUB8, + FLAGS_SUB16, + FLAGS_SUB32 +}; + +static int flags_op; +static uint32_t flags_res; +static uint32_t flags_op1, flags_op2; + +static inline int ZF_SET() +{ + switch (flags_op) + { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + case FLAGS_ADD8: + case FLAGS_ADD16: + case FLAGS_ADD32: + case FLAGS_SUB8: + case FLAGS_SUB16: + case FLAGS_SUB32: + return !flags_res; + + case FLAGS_UNKNOWN: + return flags & Z_FLAG; + } } +static inline int NF_SET() +{ + switch (flags_op) + { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + return flags_res & 0x80; + + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + return flags_res & 0x8000; + + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + return flags_res & 0x80000000; + + case FLAGS_UNKNOWN: + return flags & N_FLAG; + } +} + +static inline int PF_SET() +{ + switch (flags_op) + { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + case FLAGS_ADD8: + case FLAGS_ADD16: + case FLAGS_ADD32: + case FLAGS_SUB8: + case FLAGS_SUB16: + case FLAGS_SUB32: + return znptable8[flags_res & 0xff] & P_FLAG; + + case FLAGS_UNKNOWN: + return flags & P_FLAG; + } +} + +static inline int VF_SET() +{ + switch (flags_op) + { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + return 0; + + case FLAGS_ADD8: + return !((flags_op1 ^ flags_op2) & 0x80) && ((flags_op1 ^ flags_res) & 0x80); + case FLAGS_ADD16: + return !((flags_op1 ^ flags_op2) & 0x8000) && ((flags_op1 ^ flags_res) & 0x8000); + case FLAGS_ADD32: + return !((flags_op1 ^ flags_op2) & 0x80000000) && ((flags_op1 ^ flags_res) & 0x80000000); + + case FLAGS_SUB8: + return ((flags_op1 ^ flags_op2) & (flags_op1 ^ flags_res) & 0x80); + case FLAGS_SUB16: + return ((flags_op1 ^ flags_op2) & (flags_op1 ^ flags_res) & 0x8000); + case FLAGS_SUB32: + return ((flags_op1 ^ flags_op2) & (flags_op1 ^ flags_res) & 0x80000000); + + case FLAGS_UNKNOWN: + return flags & V_FLAG; + } +} + +static inline int AF_SET() +{ + switch (flags_op) + { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + return 0; + + case FLAGS_ADD8: + case FLAGS_ADD16: + case FLAGS_ADD32: + return ((flags_op1 & 0xF) + (flags_op2 & 0xF)) & 0x10; + + case FLAGS_SUB8: + case FLAGS_SUB16: + case FLAGS_SUB32: + return ((flags_op1 & 0xF) - (flags_op2 & 0xF)) & 0x10; + + case FLAGS_UNKNOWN: + return flags & A_FLAG; + } +} + +#if 0 +static inline int CF_SET() +{ + switch (flags_op) + { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + return flags & C_FLAG; /*Temporary*/ + + case FLAGS_ADD8: + return (flags_op1 + flags_op2) & 0x100; + case FLAGS_ADD16: +// return (flags_op1 + flags_op2) & 0x10000; + + case FLAGS_UNKNOWN: + return flags & C_FLAG; + } +} +#endif + +//#define ZF_SET() (flags & Z_FLAG) +//#define NF_SET() (flags & N_FLAG) +//#define PF_SET() (flags & P_FLAG) +//#define VF_SET() (flags & V_FLAG) +#define CF_SET() (flags & C_FLAG) +//#define AF_SET() (flags & A_FLAG) + +static inline void flags_rebuild() +{ + if (flags_op != FLAGS_UNKNOWN) + { + uint16_t tempf = 0; + if (CF_SET()) tempf |= C_FLAG; + if (PF_SET()) tempf |= P_FLAG; + if (AF_SET()) tempf |= A_FLAG; + if (ZF_SET()) tempf |= Z_FLAG; + if (NF_SET()) tempf |= N_FLAG; + if (VF_SET()) tempf |= V_FLAG; + flags = (flags & ~0x8d5) | tempf; + flags_op = FLAGS_UNKNOWN; + } +} + +static inline void flags_extract() +{ + flags_op = FLAGS_UNKNOWN; +} + +static inline void flags_rebuild_c() +{ + if (flags_op != FLAGS_UNKNOWN) + { + if (CF_SET()) + flags |= C_FLAG; + else + flags &= ~C_FLAG; + } +} + +static inline void setznp8(uint8_t val) +{ + flags_op = FLAGS_ZN8; + flags_res = val; + flags &= ~C_FLAG; +} static inline void setznp16(uint16_t val) { - flags&=~0x8d5; - flags|=znptable16[val]; + flags_op = FLAGS_ZN16; + flags_res = val; + flags &= ~C_FLAG; } static inline void setznp32(uint32_t val) { - flags&=~0x8d5; - flags|=((val&0x80000000)?N_FLAG:((!val)?Z_FLAG:0)); - flags|=znptable8[val&0xFF]&P_FLAG; + flags_op = FLAGS_ZN32; + flags_res = val; + flags &= ~C_FLAG; } + +static inline void setadd8(uint8_t a, uint8_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = (a + b) & 0xff; + flags_op = FLAGS_ADD8; + + if ((a + b) & 0x100) flags |= C_FLAG; + else flags &= ~C_FLAG; +} +static inline void setadd16(uint16_t a, uint16_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = (a + b) & 0xffff; + flags_op = FLAGS_ADD16; + + if ((a + b) & 0x10000) flags |= C_FLAG; + else flags &= ~C_FLAG; +} +static inline void setadd32(uint32_t a, uint32_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = a + b; + flags_op = FLAGS_ADD32; + + if (flags_res < a) flags |= C_FLAG; + else flags &= ~C_FLAG; +} +static inline void setadd8nc(uint8_t a, uint8_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = (a + b) & 0xff; + flags_op = FLAGS_ADD8; +} +static inline void setadd16nc(uint16_t a, uint16_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = (a + b) & 0xffff; + flags_op = FLAGS_ADD16; +} +static inline void setadd32nc(uint32_t a, uint32_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = a + b; + flags_op = FLAGS_ADD32; +} + +static inline void setsub8(uint8_t a, uint8_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = (a - b) & 0xff; + flags_op = FLAGS_SUB8; + + if (a < b) flags |= C_FLAG; + else flags &= ~C_FLAG; +} +static inline void setsub16(uint16_t a, uint16_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = (a - b) & 0xffff; + flags_op = FLAGS_SUB16; + + if (a < b) flags |= C_FLAG; + else flags &= ~C_FLAG; +} +static inline void setsub32(uint32_t a, uint32_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = a - b; + flags_op = FLAGS_SUB32; + + if (a < b) flags |= C_FLAG; + else flags &= ~C_FLAG; +} + +static inline void setsub8nc(uint8_t a, uint8_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = (a - b) & 0xff; + flags_op = FLAGS_SUB8; +} +static inline void setsub16nc(uint16_t a, uint16_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = (a - b) & 0xffff; + flags_op = FLAGS_SUB16; +} +static inline void setsub32nc(uint32_t a, uint32_t b) +{ + flags_op1 = a; + flags_op2 = b; + flags_res = a - b; + flags_op = FLAGS_SUB32; +} + +static inline void setadc8(uint8_t a, uint8_t b) +{ + uint16_t c=(uint16_t)a+(uint16_t)b+tempc; + flags_op = FLAGS_UNKNOWN; + flags&=~0x8D5; + flags|=znptable8[c&0xFF]; + if (c&0x100) flags|=C_FLAG; + if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; + if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; +} +static inline void setadc16(uint16_t a, uint16_t b) +{ + uint32_t c=(uint32_t)a+(uint32_t)b+tempc; + flags_op = FLAGS_UNKNOWN; + flags&=~0x8D5; + flags|=znptable16[c&0xFFFF]; + if (c&0x10000) flags|=C_FLAG; + if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; + if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; +} + +static inline void setsbc8(uint8_t a, uint8_t b) +{ + uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc); + flags_op = FLAGS_UNKNOWN; + flags&=~0x8D5; + flags|=znptable8[c&0xFF]; + if (c&0x100) flags|=C_FLAG; + if ((a^b)&(a^c)&0x80) flags|=V_FLAG; + if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; +} +static inline void setsbc16(uint16_t a, uint16_t b) +{ + uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); + flags_op = FLAGS_UNKNOWN; + flags&=~0x8D5; + flags|=(znptable16[c&0xFFFF]&~4); + flags|=(znptable8[c&0xFF]&4); + if (c&0x10000) flags|=C_FLAG; + if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; + if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; +} + +static inline void setadc32(uint32_t a, uint32_t b) +{ + uint32_t c=(uint32_t)a+(uint32_t)b+tempc; + flags_op = FLAGS_UNKNOWN; + flags&=~0x8D5; + flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0)); + flags|=(znptable8[c&0xFF]&P_FLAG); + if ((ca) || (c==a && tempc)) flags|=C_FLAG; + if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG; + if (((a&0xF)-((b&0xF)+tempc))&0x10) flags|=A_FLAG; +} + diff --git a/src/x86seg.c b/src/x86seg.c index 5d6c1b4..f794187 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -1,8 +1,11 @@ //#if 0 #include #include +#include #include "ibm.h" +#include "mem.h" #include "x86.h" +#include "386.h" /*Controls whether the accessed bit in a descriptor is set when CS is loaded. The 386 PRM is ambiguous on this subject, but BOCHS doesn't set it and Windows 98 @@ -29,7 +32,6 @@ int intgatesize; void taskswitch286(uint16_t seg, uint16_t *segdat, int is32); void taskswitch386(uint16_t seg, uint16_t *segdat); -int notpresent=0; int output; void pmodeint(int num, int soft); /*NOT PRESENT is INT 0B @@ -125,8 +127,6 @@ void x86ts(char *s, uint16_t error) void x86np(char *s, uint16_t error) { // pclog("NP %04X : %s\n", error, s); -// dumpregs(); -// exit(-1); abrt = ABRT_NP; abrt_error = error; } @@ -325,8 +325,6 @@ void loadcs(uint16_t seg) { uint16_t segdat[4]; uint32_t addr; - int count; - uint16_t oldss,oldsp; if (output) pclog("Load CS %04X\n",seg); if (msw&1 && !(eflags&VM_FLAG)) { @@ -452,10 +450,9 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) uint16_t segdat[4]; uint32_t addr; int count; - uint16_t oldss,oldsp; uint16_t type,seg2; uint32_t newpc; - if (output) pclog("Load CS JMP %04X\n",seg); +// pclog("Load CS JMP %04X\n",seg); if (msw&1 && !(eflags&VM_FLAG)) { if (!(seg&~3)) @@ -495,6 +492,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) if (output) pclog("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]); if (segdat[2]&0x1000) /*Normal code segment*/ { +// pclog("Normal CS\n"); if (!(segdat[2]&0x400)) /*Not conforming*/ { if ((seg&3)>CPL) @@ -528,7 +526,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) #endif CS = (seg & ~3) | CPL; - segdat[2] = (segdat[2] & ~(3 << 5+8)) | (CPL << 5+8); + segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8)); _cs.limit=segdat[0]|((segdat[3]&0xF)<<16); if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF; @@ -541,6 +539,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) } else /*System segment*/ { +// pclog("System CS\n"); if (!(segdat[2]&0x8000)) { x86np("Load CS JMP system selector not present\n", seg & 0xfffc); @@ -553,6 +552,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) { case 0x400: /*Call gate*/ case 0xC00: +// pclog("Call gate\n"); cgate32=(type&0x800); cgate16=!cgate32; oldcs=CS; @@ -654,6 +654,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) case 0x900: /*386 Task gate*/ +// pclog("Task gate\n"); pc=oxpc; cpl_override=1; taskswitch286(seg,segdat,segdat[2]&0x800); @@ -853,7 +854,7 @@ void loadcscall(uint16_t seg) if (segdat[2]&0x400) { seg = (seg & ~3) | CPL; - segdat[2] = (segdat[2] & ~(3 << 5+8)) | (CPL << 5+8); + segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8)); } else /*On non-conforming segments, set RPL = CPL*/ seg = (seg & ~3) | CPL; @@ -1332,7 +1333,7 @@ void pmoderetf(int is32, uint16_t off) pc=newpc; if (segdat[2] & 0x400) - segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8); + segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8)); CS = seg; _cs.limit=segdat[0]|((segdat[3]&0xF)<<16); if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF; @@ -1493,7 +1494,7 @@ void pmoderetf(int is32, uint16_t off) #endif /*Conforming segments don't change CPL, so CPL = RPL*/ if (segdat[2]&0x400) - segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8); + segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8)); pc=newpc; CS=seg; @@ -1521,14 +1522,11 @@ void pmodeint(int num, int soft) { uint16_t segdat[4],segdat2[4],segdat3[4]; uint32_t addr, oaddr; - int dpl; - uint16_t oldcs=CPL,oldcs2,newss; + uint16_t newss; uint32_t oldss,oldsp; - uint8_t oldaccess; int type; uint32_t newsp; uint16_t seg; - int v86int=eflags&VM_FLAG; int stack_changed=0; // if (!num) pclog("Pmode int 0 at %04X(%06X):%08X\n",CS,cs,pc); // pclog("Pmode int %02X %i %04X:%08X %04X:%08X %i\n",num,soft,CS,pc, SS, ESP, abrt); @@ -1910,12 +1908,10 @@ void pmodeint(int num, int soft) } } -int inint; void pmodeiret(int is32) { uint32_t newsp; - uint16_t oldcs=CPL,newss; - uint16_t tempw,tempw2; + uint16_t newss; uint32_t tempflags,flagmask; uint32_t newpc; uint16_t segdat[4],segdat2[4]; @@ -1991,7 +1987,6 @@ void pmodeiret(int is32) cpl_override=0; return; } - inint=0; oxpc=pc; flagmask=0xFFFF; if (CPL) flagmask&=~0x3000; @@ -2254,7 +2249,7 @@ void pmodeiret(int is32) #endif /*Conforming segments don't change CPL, so CPL = RPL*/ if (segdat[2]&0x400) - segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8); + segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8)); CS=seg; _cs.limit=segdat[0]|((segdat[3]&0xF)<<16); @@ -2295,12 +2290,10 @@ void pmodeiret(int is32) void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) { - uint32_t base,obase=tr.base; + uint32_t base; uint32_t limit; - int x386; uint32_t templ; uint16_t tempw; - int c; uint32_t new_cr3=0; uint16_t new_es,new_cs,new_ss,new_ds,new_fs,new_gs; @@ -2310,8 +2303,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) uint32_t addr; - uint16_t oldflags; - uint16_t segdat2[4]; //output=3; @@ -2361,6 +2352,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) if (optype==IRET) flags&=~NT_FLAG; // if (output) pclog("Write PC %08X %08X\n",tr.base,pc); + cpu_386_flags_rebuild(); writememl(tr.base,0x1C,cr3); writememl(tr.base,0x20,pc); writememl(tr.base,0x24,flags|(eflags<<16)); @@ -2402,7 +2394,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) cr3=new_cr3; -// pclog("New CR3 %08X\n",cr3); + pclog("TS New CR3 %08X\n",cr3); flushmmucache(); @@ -2411,6 +2403,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) // if (output) pclog("New pc %08X\n",new_pc); flags=new_flags; eflags=new_flags>>16; + cpu_386_flags_extract(); // if (output) pclog("Load LDT %04X\n",new_ldt); ldt.seg=new_ldt; diff --git a/src/x87.c b/src/x87.c index 420c1ce..0e84c70 100644 --- a/src/x87.c +++ b/src/x87.c @@ -8,8 +8,11 @@ //SCR_CalcRefdef //Calls R_SetVrect and R_ViewChanged +#define fplog 0 + #include #include "ibm.h" +#include "pic.h" #include "x86.h" #include "x87.h" @@ -67,6 +70,30 @@ int TOP; #define C2 (1<<10) #define C3 (1<<14) +#define STATUS_ZERODIVIDE 4 + +#define x87_div(dst, src1, src2) do \ + { \ + if (((double)src2) == 0.0) \ + { \ + npxs |= STATUS_ZERODIVIDE; \ + if (npxc & STATUS_ZERODIVIDE) \ + dst = src1 / (double)src2; \ + else \ + { \ + pclog("FPU : divide by zero\n"); \ + picint(1 << 13); \ + } \ + return; \ + } \ + else \ + dst = src1 / (double)src2; \ + } while (0) + +void x87_checkexceptions() +{ +} + void x87_reset() { } @@ -80,8 +107,8 @@ void x87_dumpregs() void x87_print() { - pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",ST[TOP],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]); - pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7]); + pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",ST[TOP&7],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]); + pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t TOP=%i CR=%04X SR=%04X TAG=%04X\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7], TOP, npxc, npxs, tag); } void x87_push(double i) @@ -186,16 +213,19 @@ void x87_d8() { case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/ case 0xC4: case 0xC5: case 0xC6: case 0xC7: + if (fplog) pclog("FADD\n"); ST(0)=ST(0)+ST(rmdat32&7); cycles-=8; return; case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/ case 0xCC: case 0xCD: case 0xCE: case 0xCF: + if (fplog) pclog("FMUL\n"); ST(0)=ST(0)*ST(rmdat32&7); cycles-=16; return; case 0xD0: case 0xD1: case 0xD2: case 0xD3: /*FCOM*/ case 0xD4: case 0xD5: case 0xD6: case 0xD7: + if (fplog) pclog("FCOM\n"); npxs&=~(C0|C2|C3); if (ST(0)==ST(rmdat32&7)) npxs|=C3; else if (ST(0)>((TOP&1)<<1))&3); + if (fplog) pclog("FXAM %i %f\n", ((tag>>((TOP&7)<<1))&3), ST(0)); +// pclog("FXAM %f %i\n",ST(0),(tag>>((TOP&7)<<1))&3); npxs&=~(C0|C2|C3); - if (((tag>>((TOP&1)<<1))&3)==3) npxs|=(C0|C3); + if (((tag>>((TOP&7)<<1))&3)==3) npxs|=(C0|C3); else if (ST(0)==0.0) npxs|=C3; else npxs|=C2; if (ST(0)<0.0) npxs|=C1; cycles-=8; return; case 0xE8: /*FLD1*/ + if (fplog) pclog("FLD1\n"); x87_push(1.0); cycles-=4; return; case 0xE9: /*FLDL2T*/ + if (fplog) pclog("FLDL2T\n"); x87_push(3.3219280948873623); cycles-=8; return; case 0xEA: /*FLDL2E*/ + if (fplog) pclog("FLDL2E\n"); x87_push(1.4426950408889634); cycles-=8; return; case 0xEB: /*FLDPI*/ + if (fplog) pclog("FLDPI\n"); x87_push(3.141592653589793); cycles-=8; return; case 0xEC: /*FLDEG2*/ + if (fplog) pclog("FLDEG2\n"); x87_push(0.3010299956639812); cycles-=8; return; case 0xED: /*FLDLN2*/ + if (fplog) pclog("FLDLN2\n"); x87_push(0.693147180559945); cycles-=8; return; case 0xEE: /*FLDZ*/ + if (fplog) pclog("FLDZ\n"); // pclog("FLDZ %04X:%08X\n",CS,pc); x87_push(0.0); tag|=(1<<((TOP&7)<<1)); cycles-=4; return; case 0xF0: /*F2XM1*/ + if (fplog) pclog("F2XM1\n"); ST(0)=pow(2.0,ST(0))-1.0; cycles-=200; return; case 0xF1: /*FYL2X*/ + if (fplog) pclog("FYL2X\n"); ST(1)=ST(1)*(log(ST(0))/log(2.0)); x87_pop(); cycles-=250; return; case 0xF2: /*FPTAN*/ + if (fplog) pclog("FPTAN\n"); // pclog("Tan of %f = ",ST(0)); ST(0)=tan(ST(0)); // pclog("%f\n",ST(0)); @@ -379,20 +439,31 @@ void x87_d9() cycles-=235; return; case 0xF3: /*FPATAN*/ + if (fplog) pclog("FPATAN\n"); +/* times++; + if (times==50) + { + dumpregs(); + exit(-1); + }*/ // pclog("FPATAN %08X\n",pc); ST(1)=atan2(ST(1),ST(0)); x87_pop(); cycles-=250; return; case 0xF6: /*FDECSTP*/ + if (fplog) pclog("FDECSTP\n"); TOP=(TOP-1)&7; return; case 0xF7: /*FINCSTP*/ + if (fplog) pclog("FINCSTP\n"); TOP=(TOP+1)&7; return; case 0xF8: /*FPREM*/ + if (fplog) pclog("FPREM %f %f ", ST(0), ST(1)); temp64=(int64_t)(ST(0)/ST(1)); ST(0)=ST(0)-(ST(1)*(double)temp64); + if (fplog) pclog("%f\n", ST(0)); npxs&=~(C0|C1|C2|C3); if (temp64&4) npxs|=C0; if (temp64&2) npxs|=C3; @@ -400,10 +471,12 @@ void x87_d9() cycles-=100; return; case 0xFA: /*FSQRT*/ + if (fplog) pclog("FSQRT\n"); ST(0)=sqrt(ST(0)); cycles-=83; return; case 0xFB: /*FSINCOS*/ + if (fplog) pclog("FSINCOS\n"); td=ST(0); ST(0)=sin(td); x87_push(cos(td)); @@ -411,22 +484,26 @@ void x87_d9() cycles-=330; return; case 0xFC: /*FRNDINT*/ + if (fplog) pclog("FRNDINT\n"); // pclog("FRNDINT %f %i ",ST(0),(npxc>>10)&3); ST(0)=(double)x87_fround(ST(0)); // pclog("%f\n",ST(0)); cycles-=21; return; case 0xFD: /*FSCALE*/ + if (fplog) pclog("FSCALE\n"); temp64=(int64_t)ST(1); ST(0)=ST(0)*pow(2.0,(double)temp64); cycles-=30; return; case 0xFE: /*FSIN*/ + if (fplog) pclog("FSIN\n"); ST(0)=sin(ST(0)); npxs&=~C2; cycles-=300; return; case 0xFF: /*FCOS*/ + if (fplog) pclog("FCOS\n"); ST(0)=cos(ST(0)); npxs&=~C2; cycles-=300; @@ -438,24 +515,30 @@ void x87_d9() switch (reg) { case 0: /*FLD single-precision*/ + if (fplog) pclog("FLDs %08X:%08X\n", easeg, eaaddr); // if ((rmdat32&0xFFFF)==0xD445) { pclog("FLDS\n"); output=3; dumpregs(); exit(-1); } - ts.i=(float)geteal(); if (abrt) return; + ts.i=geteal(); if (abrt) { pclog("FLD sp abort\n"); return; } + if (fplog) pclog(" %f\n", ts.s); x87_push((double)ts.s); cycles-=3; return; case 2: /*FST single-precision*/ + if (fplog) pclog("FSTs %08X:%08X\n", easeg, eaaddr); ts.s=(float)ST(0); seteal(ts.i); + if (abrt) { pclog("FST sp abort\n"); return; } cycles-=7; return; case 3: /*FSTP single-precision*/ + if (fplog) pclog("FSTPs %08X:%08X\n", easeg, eaaddr); ts.s=(float)ST(0); - seteal(ts.i); if (abrt) return; + seteal(ts.i); if (abrt) { pclog("FSTP sp abort\n"); return; } // if (pc==0x3f50c) pclog("FSTP %f %f %08X\n",ST(0),ts.s,ts.i); x87_pop(); cycles-=7; return; case 4: /*FLDENV*/ + if (fplog) pclog("FLDENV %08X:%08X\n", easeg, eaaddr); switch ((cr0&1)|(op32&0x100)) { case 0x000: /*16-bit real mode*/ @@ -474,14 +557,17 @@ void x87_d9() break; } cycles-=(cr0&1)?34:44; + if (abrt) { pclog("FLDENV\n"); return; } return; case 5: /*FLDCW*/ + if (fplog) pclog("FLDCW %08X:%08X\n", easeg, eaaddr); tempw=geteaw(); - if (abrt) return; + if (abrt) if (abrt) { pclog("FLDCW abort\n"); return; } npxc=tempw; cycles-=4; return; case 6: /*FSTENV*/ + if (fplog) pclog("FSTENV %08X:%08X\n", easeg, eaaddr); switch ((cr0&1)|(op32&0x100)) { case 0x000: /*16-bit real mode*/ @@ -518,10 +604,13 @@ void x87_d9() writememl(easeg,eaaddr+24,x87_op_seg); break; } + if (abrt) { pclog("FSTENV\n"); return; } cycles-=(cr0&1)?56:67; return; case 7: /*FSTCW*/ + if (fplog) pclog("FSTCW %08X:%08X\n", easeg, eaaddr); seteaw(npxc); + if (abrt) { pclog("FSTCW\n"); return; } cycles-=3; return; } @@ -537,6 +626,7 @@ void x87_da() switch (rmdat32&0xFF) { case 0xE9: /*FUCOMPP*/ + if (fplog) pclog("FUCOMPP\n", easeg, eaaddr); npxs&=~(C0|C2|C3); if (ST(0)==ST(1)) npxs|=C3; else if (ST(0) 2147483647 || temp64 < -2147483647) + fatal("FISTl out of range! %i\n", temp64);*/ + seteal((int32_t)temp64); cycles-=28; return; case 3: /*FISTP short*/ - seteal((int32_t)x87_fround(ST(0))); if (abrt) return; + if (fplog) pclog("FISTPs %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 2147483647 || temp64 < -2147483647) + fatal("FISTPl out of range! %i\n", temp64);*/ + seteal((int32_t)temp64); if (abrt) return; x87_pop(); cycles-=28; return; case 5: /*FLD extended*/ + if (fplog) pclog("FLDe %08X:%08X\n", easeg, eaaddr); t=x87_ld80(); if (abrt) return; + if (fplog) pclog(" %f\n", t); x87_push(t); cycles-=6; return; case 7: /*FSTP extended*/ + if (fplog) pclog("FSTPe %08X:%08X\n", easeg, eaaddr); x87_st80(ST(0)); if (abrt) return; x87_pop(); cycles-=6; @@ -668,32 +782,38 @@ void x87_dc() { case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/ case 0xC4: case 0xC5: case 0xC6: case 0xC7: + if (fplog) pclog("FADD %f %f\n", ST(rmdat32 & 7), ST(0)); ST(rmdat32&7)=ST(rmdat32&7)+ST(0); cycles-=8; return; case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/ case 0xCC: case 0xCD: case 0xCE: case 0xCF: + if (fplog) pclog("FMUL %f %f\n", ST(rmdat32 & 7), ST(0)); ST(rmdat32&7)=ST(rmdat32&7)*ST(0); cycles-=16; return; case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBR*/ case 0xE4: case 0xE5: case 0xE6: case 0xE7: + if (fplog) pclog("FSUBR %f %f\n", ST(rmdat32 & 7), ST(0)); ST(rmdat32&7)=ST(0)-ST(rmdat32&7); cycles-=8; return; case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUB*/ case 0xEC: case 0xED: case 0xEE: case 0xEF: + if (fplog) pclog("FSUB %f %f\n", ST(rmdat32 & 7), ST(0)); ST(rmdat32&7)=ST(rmdat32&7)-ST(0); cycles-=8; return; case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVR*/ case 0xF4: case 0xF5: case 0xF6: case 0xF7: - ST(rmdat32&7)=ST(0)/ST(rmdat32&7); + if (fplog) pclog("FDIVR %f %f\n", ST(rmdat32 & 7), ST(0)); + x87_div(ST(rmdat32&7), ST(0), ST(rmdat32&7)); cycles-=73; return; case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIV*/ case 0xFC: case 0xFD: case 0xFE: case 0xFF: - ST(rmdat32&7)=ST(rmdat32&7)/ST(0); + if (fplog) pclog("FDIV %f %f\n", ST(rmdat32 & 7), ST(0)); + x87_div(ST(rmdat32&7), ST(rmdat32&7), ST(0)); cycles-=73; return; } @@ -706,20 +826,24 @@ void x87_dc() switch (reg) { case 0: /*FADD double*/ + if (fplog) pclog("FADDd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d); ST(0)+=t.d; cycles-=8; return; case 1: /*FMUL double*/ + if (fplog) pclog("FMULd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d); ST(0)*=t.d; cycles-=14; return; case 2: /*FCOM double*/ + if (fplog) pclog("FCOMd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d); npxs&=~(C0|C2|C3); if (ST(0)==t.d) npxs|=C3; else if (ST(0)>((TOP&7)<<1))&3; tag&=~(3<<((rmdat32&7)<<1)); @@ -771,6 +901,7 @@ void x87_dd() cycles-=3; return; case 3: /*FSTP*/ + if (fplog) pclog("FSTP\n"); ST(rmdat32&7)=ST(0); temp=(tag>>((TOP&7)<<1))&3; tag&=~(3<<((rmdat32&7)<<1)); @@ -779,12 +910,14 @@ void x87_dd() cycles-=3; return; case 4: /*FUCOM*/ + if (fplog) pclog("FUCOM\n"); npxs&=~(C0|C2|C3); if (ST(0)==ST(rmdat32&7)) npxs|=C3; else if (ST(0)>32)); cycles-=8; return; case 3: /*FSTP double-precision*/ + if (fplog) pclog("FSTPd %08X:%08X\n", easeg, eaaddr); t.d=ST(0); writememl(easeg,eaaddr,t.i); writememl(easeg,eaaddr+4,(t.i>>32)); if (abrt) return; @@ -817,6 +954,7 @@ void x87_dd() cycles-=8; return; case 4: /*FRSTOR*/ + if (fplog) pclog("FRSTOR %08X:%08X\n", easeg, eaaddr); switch ((cr0&1)|(op32&0x100)) { case 0x000: /*16-bit real mode*/ @@ -847,6 +985,7 @@ void x87_dd() cycles-=(cr0&1)?34:44; return; case 6: /*FSAVE*/ + if (fplog) pclog("FSAVE %08X:%08X\n", easeg, eaaddr); switch ((cr0&1)|(op32&0x100)) { case 0x000: /*16-bit real mode*/ @@ -922,6 +1061,7 @@ void x87_dd() cycles-=(cr0&1)?56:67; return; case 7: /*FSTSW*/ + if (fplog) pclog("FSTSW %08X:%08X\n", easeg, eaaddr); seteaw((npxs&0xC7FF)|(TOP<<11)); cycles-=3; return; @@ -932,7 +1072,6 @@ void x87_dd() } void x87_de() { - double t; int32_t templ; if (mod==3) { @@ -940,17 +1079,20 @@ void x87_de() { case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADDP*/ case 0xC4: case 0xC5: case 0xC6: case 0xC7: - ST(rmdat32&7)=ST(rmdat32&7)+ST[TOP]; + if (fplog) pclog("FADDP %f %f\n", ST(rmdat32 & 7), ST(0)); + ST(rmdat32&7)=ST(rmdat32&7)+ST(0); x87_pop(); cycles-=8; return; case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMULP*/ case 0xCC: case 0xCD: case 0xCE: case 0xCF: - ST(rmdat32&7)=ST(rmdat32&7)*ST[TOP]; + if (fplog) pclog("FMULP %f %f\n", ST(rmdat32 & 7), ST(0)); + ST(rmdat32&7)=ST(rmdat32&7)*ST(0); x87_pop(); cycles-=16; return; case 0xD9: /*FCOMPP*/ + if (fplog) pclog("FCOMPP %f %f\n", ST(0), ST(1)); npxs&=~(C0|C2|C3); if (ST(0)==ST(1)) npxs|=C3; else if (ST(0) 32767 || temp64 < -32768) + fatal("FISTw overflow %i\n", temp64);*/ + seteaw((int16_t)temp64); cycles-=29; return; case 3: /*FISTP word*/ - temp16=x87_fround(ST(0)); - seteaw(temp16); if (abrt) return; + if (fplog) pclog("FISTPw %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 32767 || temp64 < -32768) + fatal("FISTw overflow %i\n", temp64);*/ + seteaw((int16_t)temp64); if (abrt) return; x87_pop(); cycles-=29; return; case 5: /*FILD long*/ + if (fplog) pclog("FILDl %08X:%08X\n", easeg, eaaddr); temp64=geteal(); if (abrt) return; temp64|=(uint64_t)readmeml(easeg,eaaddr+4)<<32; + if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,eaaddr), readmeml(easeg,eaaddr+4)); x87_push((double)temp64); cycles-=10; return; case 6: /*FBSTP*/ + if (fplog) pclog("FBSTP %08X:%08X\n", easeg, eaaddr); tempd=ST(0); + if (tempd < 0.0) + tempd = -tempd; for (c=0;c<9;c++) { tempc=(uint8_t)floor(fmod(tempd,10.0)); tempd-=floor(fmod(tempd,10.0)); tempd/=10.0; @@ -1088,11 +1256,12 @@ void x87_df() writememb(easeg,eaaddr+c,tempc); } tempc=(uint8_t)floor(fmod(tempd,10.0)); - if (tempd<0.0) tempc|=0x80; + if (ST(0)<0.0) tempc|=0x80; writememb(easeg,eaaddr+9,tempc); if (abrt) return; x87_pop(); return; case 7: /*FISTP long*/ + if (fplog) pclog("FISTPl %08X:%08X\n", easeg, eaaddr); temp64=x87_fround(ST(0)); seteal(temp64); writememl(easeg,eaaddr+4,temp64>>32); if (abrt) return; diff --git a/src/xtide.c b/src/xtide.c index 0dbe2d9..9205040 100644 --- a/src/xtide.c +++ b/src/xtide.c @@ -1,10 +1,12 @@ #include "ibm.h" -#include "xtide.h" + +#include "io.h" #include "ide.h" +#include "xtide.h" uint8_t xtide_high; -void xtide_write(uint16_t port, uint8_t val) +void xtide_write(uint16_t port, uint8_t val, void *priv) { switch (port & 0xf) { @@ -27,7 +29,7 @@ void xtide_write(uint16_t port, uint8_t val) } } -uint8_t xtide_read(uint16_t port) +uint8_t xtide_read(uint16_t port, void *priv) { uint16_t tempw; switch (port & 0xf) @@ -51,5 +53,6 @@ uint8_t xtide_read(uint16_t port) void xtide_init() { - io_sethandler(0x0300, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL); + ide_init(); + io_sethandler(0x0300, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL, NULL); }