Merge branch 'master' of ssh://github.com/OBattler/PCem-Unofficial into port-forward-config

This commit is contained in:
RichardG867
2016-07-10 21:58:11 -03:00
34 changed files with 950 additions and 989 deletions

View File

@@ -1,2 +1,7 @@
# PCem-Experimental
Unofficial experimental branchof the PCem emulator.
# PCem Unofficial [![Build Status](http://polar.rol.im:8080/job/PCem-Unofficial/badge/icon)](http://polar.rol.im:8080/job/PCem-Unofficial)
PCem Unofficial is an unofficial branch of the PCem emulator, which aims to emulate IBM compatible machines from 1981-2000 period. This branch adds several emulated motherboards.
---
Keep in touch with the PCem Unoffical community:
[![Visit our IRC channel](https://kiwiirc.com/buttons/irc.rol.im/pcem-x.png)](https://kiwiirc.com/client/irc.rol.im/?nick=pcem|?#pcem-x)

View File

@@ -297,7 +297,10 @@ int rep386(int fv)
that high frequency timers still work okay. This amount is different
for interpreter and recompiler*/
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100);
if (trap)
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/
cpu_reps++;
flags_rebuild();

View File

@@ -2,36 +2,34 @@ VPATH = . dosbox resid-fp slirp
CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
KFLAGS = -O2 -flto -ffast-math -msse -msse2 -mfpmath=387 -mstackrealign
CFLAGS = -O3 -march=native -mtune=native -flto -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
BFLAGS = -DRELEASE_BUILD
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
scat.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \
sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \
soundopenal.o tandy_eeprom.o tandy_rom.o timer.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_cga_comp.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
vid_pcjr.o vid_ps1_svga.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_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
vid_vga.o vid_voodoo.o video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res
FMOBJ = dbopl.o
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
DBOBJ = dbopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
SLIRPOBJ = bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o ip_input.o queue.o tcp_input.o tftp.o debug.o ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
LIBS = -mwindows -lwinmm -lopenal.dll -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static
PCem.exe: $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem.exe" $(LIBS)
PCem.exe: $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem.exe" $(LIBS)
strip "PCem.exe"
all : PCem.exe

View File

@@ -8,28 +8,28 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
scat.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \
sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \
soundopenal.o tandy_eeprom.o tandy_rom.o timer.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_cga_comp.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
vid_pcjr.o vid_ps1_svga.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_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
vid_vga.o vid_voodoo.o video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res
FMOBJ = dbopl.o
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
DBOBJ = dbopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
SLIRPOBJ = bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o ip_input.o queue.o tcp_input.o tftp.o debug.o ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
LIBS = -mwindows -lwinmm -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static -lopenal.dll -flto -lgcov -lPacket -lwpcap
LIBS = -mwindows -lwinmm -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static -lopenal.dll -lgcov -lPacket -lwpcap
PCem64.exe: $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem64.exe" $(LIBS)
PCem64.exe: $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem64.exe" $(LIBS)
strip "PCem64.exe"
all : PCem64.exe

View File

@@ -2,35 +2,34 @@ VPATH = . dosbox resid-fp slirp
CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
CFLAGS = -O3 -march=amdfam10 -mtune=amdfam10 -flto -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mfpmath=sse -mstackrealign
BFLAGS = -DRELEASE_BUILD
CFLAGS = -O3 -march=amdfam10 -mtune=amdfam10 -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mfpmath=sse -mstackrealign
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
scat.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \
sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \
soundopenal.o tandy_eeprom.o tandy_rom.o timer.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_cga_comp.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
vid_pcjr.o vid_ps1_svga.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_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
vid_vga.o vid_voodoo.o video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res
FMOBJ = dbopl.o
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
DBOBJ = dbopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
SLIRPOBJ = bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o ip_input.o queue.o tcp_input.o tftp.o debug.o ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
LIBS = -mwindows -lwinmm -lopenal.dll -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static
PCem.exe: $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem.exe" $(LIBS)
PCem.exe: $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem.exe" $(LIBS)
strip "PCem.exe"
all : PCem.exe

View File

@@ -75,6 +75,7 @@ int cpu_use_dynarec;
uint64_t cpu_CR4_mask;
int is286, is386;
int israpidcad;
uint64_t tsc = 0;
@@ -228,9 +229,9 @@ CPU cpus_i386[] =
{"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0},
{"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0},
{"i386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0},
{"RapidCAD/25", CPU_i486DX, 2, 25000000, 1, 0, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC},
{"RapidCAD/33", CPU_i486DX, 3, 33333333, 1, 0, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC},
{"RapidCAD/40", CPU_i486DX, 4, 40000000, 1, 0, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC},
{"RapidCAD/25", CPU_RAPIDCAD, 2, 25000000, 1, 0, 0x404, 0, 0, 0},
{"RapidCAD/33", CPU_RAPIDCAD, 3, 33333333, 1, 0, 0x404, 0, 0, 0},
{"RapidCAD/40", CPU_RAPIDCAD, 4, 40000000, 1, 0, 0x404, 0, 0, 0},
{"", -1, 0, 0, 0}
};
@@ -292,7 +293,6 @@ CPU cpus_i486[] =
{"iDX4/100", CPU_i486DX,10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
{"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC},
{"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC},
{"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0},
{"", -1, 0, 0, 0}
};
@@ -582,7 +582,8 @@ void cpu_set()
is8086 = (cpu_s->cpu_type > CPU_8088);
is286 = (cpu_s->cpu_type >= CPU_286);
is386 = (cpu_s->cpu_type >= CPU_386SX);
is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC);
israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD);
is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD);
hasfpu = (cpu_s->cpu_type >= CPU_i486DX);
cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1);
cpu_16bitbus = (cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC);
@@ -800,6 +801,37 @@ void cpu_set()
timing_jmp_pm_gate = 45;
break;
case CPU_RAPIDCAD:
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*/
timing_int = 4;
timing_int_rm = 26;
timing_int_v86 = 82;
timing_int_pm = 44;
timing_int_pm_outer = 71;
timing_iret_rm = 15;
timing_iret_v86 = 36; /*unknown*/
timing_iret_pm = 20;
timing_iret_pm_outer = 36;
timing_call_rm = 18;
timing_call_pm = 20;
timing_call_pm_gate = 35;
timing_call_pm_gate_inner = 69;
timing_retf_rm = 13;
timing_retf_pm = 17;
timing_retf_pm_outer = 35;
timing_jmp_rm = 17;
timing_jmp_pm = 19;
timing_jmp_pm_gate = 32;
break;
case CPU_486SLC:
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
timing_rr = 1; /*register dest - register src*/

View File

@@ -13,34 +13,35 @@ extern int cpu, cpu_manufacturer;
/*386 class CPUs*/
#define CPU_386SX 3
#define CPU_386DX 4
#define CPU_486SLC 5
#define CPU_486DLC 6
#define CPU_RAPIDCAD 5
#define CPU_486SLC 6
#define CPU_486DLC 7
/*486 class CPUs*/
#define CPU_i486SX 7
#define CPU_Am486SX 8
#define CPU_Cx486S 9
#define CPU_i486DX 10
#define CPU_Am486DX 11
#define CPU_Cx486DX 12
#define CPU_Cx5x86 13
#define CPU_i486SX 8
#define CPU_Am486SX 9
#define CPU_Cx486S 10
#define CPU_i486DX 11
#define CPU_Am486DX 12
#define CPU_Cx486DX 13
#define CPU_Cx5x86 14
/*586 class CPUs*/
#define CPU_WINCHIP 14
#define CPU_PENTIUM 15
#define CPU_PENTIUMMMX 16
#define CPU_Cx6x86 17
#define CPU_Cx6x86MX 18
#define CPU_Cx6x86L 19
#define CPU_CxGX1 20
#define CPU_K5 21
#define CPU_5K86 22
#define CPU_K6 23
#define CPU_WINCHIP 15
#define CPU_PENTIUM 16
#define CPU_PENTIUMMMX 17
#define CPU_Cx6x86 18
#define CPU_Cx6x86MX 19
#define CPU_Cx6x86L 20
#define CPU_CxGX1 21
#define CPU_K5 22
#define CPU_5K86 23
#define CPU_K6 24
/*686 class CPUs*/
#define CPU_PENTIUMPRO 24
#define CPU_PENTIUM2 25
#define CPU_PENTIUM2D 26
#define CPU_PENTIUMPRO 25
#define CPU_PENTIUM2 26
#define CPU_PENTIUM2D 27
#define MANU_INTEL 0
#define MANU_AMD 1

View File

@@ -5,13 +5,10 @@
#include <stdint.h>
#include <math.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h"
#include "vid_cga.h"
#include "../ibm.h"
#include "../device.h"
#include "../mem.h"
#include "../vid_cga.h"
#include "vid_cga_comp.h"
int CGA_Composite_Table[1024];
@@ -145,24 +142,8 @@ void update_cga16_color(cga_t *cga) {
video_bi = (int) (bi*iq_adjust_i + bq*iq_adjust_q);
video_bq = (int) (-bi*iq_adjust_q + bq*iq_adjust_i);
video_sharpness = (int) (sharpness*256/100);
#if 0
df = fopen("CGA_Composite_Table.dmp", "wb");
fwrite(CGA_Composite_Table, 1024, sizeof(int), df);
fclose(df);
#endif
}
#if 0
void configure_comp(double h, uint8_t n, uint8_t bw, uint8_t b1)
{
hue_offset = h;
new_cga = n;
is_bw = bw;
is_bpp1 = b1;
}
#endif
static Bit8u byte_clamp(int v) {
v >>= 13;
return v < 0 ? 0 : (v > 255 ? 255 : v);
@@ -216,7 +197,7 @@ Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool double
for (x = 0; x < 5; ++x)
OUT(b[x&3]);
if ((cga->cgamode & 4) != 0 || !cga_color_burst) {
if ((cga->cgamode & 4) != 0) {
// Decode
int* i = temp + 5;
Bit32u* srgb = (Bit32u *)TempLine;
@@ -256,18 +237,6 @@ Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool double
#undef COMPOSITE_CONVERT
#undef OUT
#if 0
df = fopen("temp.dmp", "ab");
fwrite(temp, SCALER_MAXWIDTH + 10, sizeof(int), df);
fclose(df);
df = fopen("atemp.dmp", "ab");
fwrite(atemp, SCALER_MAXWIDTH + 2, sizeof(int), df);
fclose(df);
df = fopen("btemp.dmp", "ab");
fwrite(btemp, SCALER_MAXWIDTH + 2, sizeof(int), df);
fclose(df);
#endif
return TempLine;
}
@@ -343,7 +312,7 @@ void DecreaseSharpness(cga_t *cga)
void cga_comp_init(cga_t *cga)
{
new_cga = (gfxcard == GFX_NEW_CGA);
new_cga = cga->revision;
/* Making sure this gets reset after reset. */
brightness = 0;
@@ -353,4 +322,4 @@ void cga_comp_init(cga_t *cga)
hue_offset = 0;
update_cga16_color(cga);
}
}

View File

@@ -99,13 +99,11 @@ void fdc_reset()
fdc_set_skip_pulses(1, 0);
fdd_stepping_motor_on[0] = fdd_stepping_motor_on[1] = 0;
fdd_track_diff[0] = fdd_track_diff[1] = 0;
#if 0
if (!AT)
{
fdc.rate = 2;
// fdc_update_rate();
}
#endif
fdc_state = FDC_STATE_NORMAL;
// pclog("Reset FDC\n");
}

View File

@@ -194,6 +194,7 @@ uint32_t dr[8];
//#define IOPLV86 ((!(msw&1)) || (CPL<=IOPL))
extern int cycles;
extern int cycles_lost;
extern int israpidcad;
extern int is486;
extern uint8_t opcode;
extern int insc;
@@ -286,7 +287,7 @@ char discfns[2][256];
int driveempty[2];
#define MDA ((gfxcard==GFX_MDA || gfxcard==GFX_HERCULES || gfxcard==GFX_INCOLOR) && (romset<ROM_TANDY || romset>=ROM_IBMAT))
#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_NEW_CGA && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200)
#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200)
#define PCJR (romset == ROM_IBMPCJR)
#define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486)
@@ -385,7 +386,6 @@ enum
GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/
GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/
GFX_INCOLOR, /* Hercules InColor */
GFX_NEW_CGA,
GFX_ET4000W32C, /*Tseng ET4000/W32p (Cardex) */
GFX_COMPAQ_EGA, /*Compaq EGA*/
GFX_SUPER_EGA, /*Using Chips & Technologies SuperEGA BIOS*/
@@ -393,7 +393,7 @@ enum
GFX_MIRO_VISION964, /*S3 Vision964 (Miro Crystal)*/
GFX_CL_GD5446, /*Cirrus Logic CL-GD5446*/
GFX_VGAWONDERXL, /*Compaq ATI VGA Wonder XL (28800-5)*/
GFX_WD90C11, /*Paradise WD90C11*/
GFX_WD90C11, /*Paradise WD90C11 Standalone*/
GFX_OTI077, /*Oak OTI-077*/
GFX_MAX
};

View File

@@ -3,6 +3,14 @@
#include "device.h"
#include "mem.h"
#define FLASH_IS_BXB 2
#define FLASH_INVERT 1
#define BLOCK_MAIN 0
#define BLOCK_DMI 1
#define BLOCK_ESCD 2
#define BLOCK_BOOT 3
enum
{
CMD_READ_ARRAY = 0xff,
@@ -18,99 +26,86 @@ enum
typedef struct flash_t
{
uint32_t command, status;
uint32_t data_addr1, data_addr2, data_start, boot_start;
uint32_t main_start[2], main_end[2], main_len[2];
uint32_t flash_id, invert_high_pin;
mem_mapping_t read_mapping, write_mapping;
mem_mapping_t read_mapping_h, write_mapping_h;
uint32_t flash_id;
uint8_t type; /* 0 = BXT, 1 = BXB */
uint8_t invert_high_pin; /* 0 = no, 1 = yes */
mem_mapping_t mapping[8], mapping_h[8];
uint32_t block_start[4], block_end[4], block_len[4];
uint8_t array[131072];
} flash_t;
static flash_t flash;
char flash_path[1024];
#if 0
mem_mapping_t flash_null_mapping[4];
uint8_t flash_read_null(uint32_t addr, void *priv)
{
return 0xff;
}
uint16_t flash_read_nullw(uint32_t addr, void *priv)
{
return 0xffff;
}
uint32_t flash_read_nulll(uint32_t addr, void *priv)
{
// pclog("Read BIOS %08X %02X %04X:%04X\n", addr, *(uint32_t *)&rom[addr & biosmask], CS, pc);
return 0xffffffff;
}
void flash_null_mapping_disable()
{
mem_mapping_disable(&flash_null_mapping[0]);
mem_mapping_disable(&flash_null_mapping[1]);
mem_mapping_disable(&flash_null_mapping[2]);
mem_mapping_disable(&flash_null_mapping[3]);
}
void flash_null_mapping_enable()
{
mem_mapping_enable(&flash_null_mapping[0]);
mem_mapping_enable(&flash_null_mapping[1]);
mem_mapping_enable(&flash_null_mapping[2]);
mem_mapping_enable(&flash_null_mapping[3]);
}
void flash_add_null_mapping()
{
mem_mapping_add(&flash_null_mapping[0], 0xe0000, 0x04000, flash_read_null, flash_read_nullw, flash_read_nulll, mem_write_null, mem_write_nullw, mem_write_nulll, NULL, MEM_MAPPING_EXTERNAL, 0);
mem_mapping_add(&flash_null_mapping[1], 0xe4000, 0x04000, flash_read_null, flash_read_nullw, flash_read_nulll, mem_write_null, mem_write_nullw, mem_write_nulll, NULL, MEM_MAPPING_EXTERNAL, 0);
mem_mapping_add(&flash_null_mapping[2], 0xe8000, 0x04000, flash_read_null, flash_read_nullw, flash_read_nulll, mem_write_null, mem_write_nullw, mem_write_nulll, NULL, MEM_MAPPING_EXTERNAL, 0);
mem_mapping_add(&flash_null_mapping[3], 0xec000, 0x04000, flash_read_null, flash_read_nullw, flash_read_nulll, mem_write_null, mem_write_nullw, mem_write_nulll, NULL, MEM_MAPPING_EXTERNAL, 0);
flash_null_mapping_disable();
}
#endif
static uint8_t flash_read(uint32_t addr, void *p)
{
flash_t *flash = (flash_t *)p;
// pclog("flash_read : addr=%08x command=%02x %04x:%08x\n", addr, flash->command, CS, pc);
if (flash->invert_high_pin)
{
// pclog("flash_read : addr=%08x/%08x val=%02x command=%02x %04x:%08x\n", addr, addr ^ 0x10000, flash->array[(addr ^ 0x10000) & 0x1ffff], flash->command, CS, cpu_state.pc);
addr ^= 0x10000;
if (addr & 0xfff00000) return flash->array[addr & 0x1ffff];
}
// pclog("flash_read : addr=%08x command=%02x %04x:%08x\n", addr, flash->command, CS, cpu_state.pc);
addr &= 0x1ffff;
switch (flash->command)
{
case CMD_READ_ARRAY:
default:
return flash->array[addr];
case CMD_IID:
if (addr & 1)
return flash->flash_id;
return 0x89;
default:
return flash->status;
case CMD_READ_STATUS:
return flash->status;
}
}
static uint16_t flash_readw(uint32_t addr, void *p)
{
flash_t *flash = (flash_t *)p;
addr &= 0x1ffff;
if (flash->invert_high_pin) addr ^= 0x10000;
return *(uint16_t *)&(flash->array[addr]);
}
static uint32_t flash_readl(uint32_t addr, void *p)
{
flash_t *flash = (flash_t *)p;
addr &= 0x1ffff;
if (flash->invert_high_pin) addr ^= 0x10000;
return *(uint32_t *)&(flash->array[addr]);
}
static void flash_write(uint32_t addr, uint8_t val, void *p)
{
flash_t *flash = (flash_t *)p;
int i;
// pclog("flash_write : addr=%08x val=%02x command=%02x %04x:%08x\n", addr, val, flash->command, CS, pc);
// pclog("flash_write : addr=%08x val=%02x command=%02x %04x:%08x\n", addr, val, flash->command, CS, cpu_state.pc);
if (flash->invert_high_pin)
{
addr ^= 0x10000;
if (addr & 0xfff00000) return;
}
addr &= 0x1ffff;
switch (flash->command)
{
case CMD_ERASE_SETUP:
if (val == CMD_ERASE_CONFIRM)
{
// pclog("flash_write: erase %05x\n", addr & 0x1ffff);
pclog("flash_write: erase %05x\n", addr);
if ((addr & 0x1f000) == flash->data_addr1)
memset(&rom[flash->data_addr1], 0xff, 0x1000);
if ((addr & 0x1f000) == flash->data_addr2)
memset(&rom[flash->data_addr2], 0xff, 0x1000);
if (((addr & 0x1ffff) >= flash->main_start[0]) && ((addr & 0x1ffff) <= flash->main_end[0]) && flash->main_len[0])
memset(&rom[flash->main_start[0]], 0xff, flash->main_len[0]);
if (((addr & 0x1ffff) >= flash->main_start[1]) && ((addr & 0x1ffff) <= flash->main_end[1]) && flash->main_len[1])
memset(&rom[flash->main_start[1]], 0xff, flash->main_len[1]);
for (i = 0; i < 3; i++)
{
if ((addr >= flash->block_start[i]) && (addr <= flash->block_end[i]))
memset(&(flash->array[flash->block_start[i]]), 0xff, flash->block_len[i]);
}
flash->status = 0x80;
}
@@ -118,9 +113,9 @@ static void flash_write(uint32_t addr, uint8_t val, void *p)
break;
case CMD_PROGRAM_SETUP:
// pclog("flash_write: program %05x %02x\n", addr & 0x1ffff, val);
if ((addr & 0x1e000) != (flash->boot_start & 0x1e000))
rom[addr & 0x1ffff] = val;
pclog("flash_write: program %05x %02x\n", addr, val);
if ((addr & 0x1e000) != (flash->block_start[3] & 0x1e000))
flash->array[addr] = val;
flash->command = CMD_READ_STATUS;
flash->status = 0x80;
break;
@@ -131,46 +126,42 @@ static void flash_write(uint32_t addr, uint8_t val, void *p)
{
case CMD_CLEAR_STATUS:
flash->status = 0;
break;
case CMD_IID:
case CMD_READ_STATUS:
for (i = 0; i < 8; i++)
{
mem_mapping_disable((addr & 0x8000000) ? &bios_high_mapping[i] : &bios_mapping[i]);
}
mem_mapping_enable((addr & 0x8000000) ? &flash->read_mapping_h : &flash->read_mapping);
break;
case CMD_READ_ARRAY:
for (i = 0; i < 8; i++)
{
mem_mapping_enable((addr & 0x8000000) ? &bios_high_mapping[i] : &bios_mapping[i]);
}
mem_mapping_disable((addr & 0x8000000) ? &flash->read_mapping_h : &flash->read_mapping);
#if 0
if ((romset == ROM_MB500N) || (romset == ROM_430VX) || (romset == ROM_P55VA) || (romset == ROM_P55TVP4) || (romset == ROM_440FX))
{
for (i = 0; i < 4; i++)
{
mem_mapping_disable(&bios_mapping[i]);
}
flash_null_mapping_enable();
}
pclog("; This line needed\n");
#endif
break;
break;
}
}
}
void *intel_flash_init(int type)
void intel_flash_add_mappings(flash_t *flash)
{
int i = 0;
for (i = 0; i <= 7; i++)
{
mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash);
mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), 0, (void *)flash);
}
}
/* This is for boards which invert the high pin - the flash->array pointers need to pointer invertedly in order for INTERNAL writes to go to the right part of the array. */
void intel_flash_add_mappings_inverted(flash_t *flash)
{
int i = 0;
for (i = 0; i <= 7; i++)
{
mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash);
mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), 0, (void *)flash);
}
}
void *intel_flash_init(uint8_t type)
{
FILE *f;
flash_t *flash = malloc(sizeof(flash_t));
char fpath[1024];
memset(flash, 0, sizeof(flash_t));
int i;
/* IMPORTANT: Do NOT zero the pointers! */
memset(flash, 0, sizeof(flash_t) - (6 * sizeof(void *)));
// pclog("Initializing Flash (type = %i)\n", type);
@@ -223,132 +214,119 @@ void *intel_flash_init(int type)
}
// pclog("Flash init: Path is: %s\n", flash_path);
switch(type)
flash->type = (type & 2) ? 1 : 0;
flash->flash_id = (!flash->type) ? 0x94 : 0x95;
flash->invert_high_pin = (type & 1);
/* The block lengths are the same both flash types. */
flash->block_len[0] = 0x1c000;
flash->block_len[1] = 0x01000;
flash->block_len[2] = 0x01000;
flash->block_len[3] = 0x02000;
if(flash->type) /* 28F001BX-B */
{
case 0:
flash->data_addr1 = 0xc000;
flash->data_addr2 = 0xd000;
flash->data_start = 0xc000;
flash->boot_start = 0xe000;
flash->main_start[0] = 0x0000;
flash->main_end[0] = 0xbfff;
flash->main_len[0] = 0xc000;
flash->main_start[1] = 0x10000;
flash->main_end[1] = 0x1ffff;
flash->main_len[1] = 0x10000;
break;
case 1:
flash->data_addr1 = 0x1c000;
flash->data_addr2 = 0x1d000;
flash->data_start = 0x1c000;
flash->boot_start = 0x1e000;
flash->main_start[0] = 0x00000;
flash->main_end[0] = 0x1bfff;
flash->main_len[0] = 0x1c000;
flash->main_start[1] = flash->main_end[1] = flash->main_len[1] = 0;
break;
case 2:
flash->data_addr1 = 0x3000;
flash->data_addr2 = 0x2000;
flash->data_start = 0x2000;
flash->boot_start = 0x00000;
flash->main_start[0] = 0x04000;
flash->main_end[0] = 0x1ffff;
flash->main_len[0] = 0x1c000;
flash->main_start[1] = flash->main_end[1] = flash->main_len[1] = 0;
break;
flash->block_start[0] = 0x04000; /* MAIN BLOCK */
flash->block_end[0] = 0x1ffff;
flash->block_start[1] = 0x03000; /* DMI BLOCK */
flash->block_end[1] = 0x03fff;
flash->block_start[2] = 0x04000; /* ESCD BLOCK */
flash->block_end[2] = 0x04fff;
flash->block_start[3] = 0x00000; /* BOOT BLOCK */
flash->block_end[3] = 0x01fff;
}
else /* 28F001BX-T */
{
flash->block_start[0] = 0x00000; /* MAIN BLOCK */
flash->block_end[0] = 0x1bfff;
flash->block_start[1] = 0x1c000; /* DMI BLOCK */
flash->block_end[1] = 0x1cfff;
flash->block_start[2] = 0x1d000; /* ESCD BLOCK */
flash->block_end[2] = 0x1dfff;
flash->block_start[3] = 0x1e000; /* BOOT BLOCK */
flash->block_end[3] = 0x1ffff;
}
flash->flash_id = (type != 2) ? 0x94 : 0x95;
flash->invert_high_pin = (type == 0) ? 1 : 0;
mem_mapping_add(&flash->read_mapping,
0xe0000,
0x20000,
flash_read, NULL, NULL,
NULL, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, (void *)flash);
mem_mapping_add(&flash->write_mapping,
0xe0000,
0x20000,
NULL, NULL, NULL,
flash_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, (void *)flash);
mem_mapping_disable(&flash->read_mapping);
if (type > 0)
for (i = 0; i < 8; i++)
{
mem_mapping_add(&flash->read_mapping_h,
0xfffe0000,
0x20000,
flash_read, NULL, NULL,
NULL, NULL, NULL,
NULL, 0, (void *)flash);
mem_mapping_add(&flash->write_mapping_h,
0xfffe0000,
0x20000,
NULL, NULL, NULL,
flash_write, NULL, NULL,
NULL, 0, (void *)flash);
mem_mapping_disable(&flash->read_mapping_h);
/* if (romset != ROM_P55TVP4) */ mem_mapping_disable(&flash->write_mapping);
mem_mapping_disable(&bios_mapping[i]);
mem_mapping_disable(&bios_high_mapping[i]);
}
flash->command = CMD_READ_ARRAY;
flash->status = 0;
if ((romset == ROM_586MC1) || (romset == ROM_MB500N) || (type == 0))
if (flash->invert_high_pin)
{
memset(&rom[flash->data_addr2], 0xFF, 0x1000);
memcpy(flash->array, rom + 65536, 65536);
memcpy(flash->array + 65536, rom, 65536);
}
else
{
memset(&rom[flash->data_start], 0xFF, 0x2000);
memcpy(flash->array, rom, 131072);
}
if ((romset != ROM_586MC1) && (romset != ROM_MB500N) && (type > 0))
if (flash->invert_high_pin)
{
memset(fpath, 0, 1024);
strcpy(fpath, flash_path);
strcat(fpath, "dmi.bin");
f = romfopen(fpath, "rb");
if (f)
{
fread(&rom[flash->data_addr1], 0x1000, 1, f);
fclose(f);
}
intel_flash_add_mappings_inverted(flash);
}
else
{
intel_flash_add_mappings(flash);
}
flash->command = CMD_READ_ARRAY;
flash->status = 0;
/* Load the main block. */
memset(fpath, 0, 1024);
strcpy(fpath, flash_path);
strcat(fpath, "main.bin");
f = romfopen(fpath, "rb");
if (f)
{
fread(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f);
fclose(f);
}
/* Load the DMI block. */
memset(fpath, 0, 1024);
strcpy(fpath, flash_path);
strcat(fpath, "dmi.bin");
f = romfopen(fpath, "rb");
if (f)
{
fread(&(flash->array[flash->block_start[BLOCK_DMI]]), flash->block_len[BLOCK_DMI], 1, f);
fclose(f);
}
/* Load the ESCD block. */
memset(fpath, 0, 1024);
strcpy(fpath, flash_path);
strcat(fpath, "escd.bin");
f = romfopen(fpath, "rb");
if (f)
{
fread(&rom[flash->data_addr2], 0x1000, 1, f);
fread(&(flash->array[flash->block_start[BLOCK_ESCD]]), flash->block_len[BLOCK_ESCD], 1, f);
fclose(f);
}
#if 0
flash_add_null_mapping();
#endif
return flash;
}
/* For AMI BIOS'es - Intel 28F001BXT with high address pin inverted. */
void *intel_flash_bxt_ami_init()
{
return intel_flash_init(0);
return intel_flash_init(FLASH_INVERT);
}
/* For Award BIOS'es - Intel 28F001BXT with high address pin not inverted. */
void *intel_flash_bxt_init()
{
return intel_flash_init(1);
return intel_flash_init(0);
}
/* For Acerd BIOS'es - Intel 28F001BXB. */
/* For Acer BIOS'es - Intel 28F001BXB. */
void *intel_flash_bxb_init()
{
return intel_flash_init(2);
return intel_flash_init(FLASH_IS_BXB);
}
void intel_flash_close(void *p)
@@ -360,20 +338,28 @@ void intel_flash_close(void *p)
// pclog("Flash close: Path is: %s\n", flash_path);
if ((romset != ROM_586MC1) && (romset != ROM_MB500N))
{
memset(fpath, 0, 1024);
strcpy(fpath, flash_path);
strcat(fpath, "dmi.bin");
f = romfopen(fpath, "wb");
fwrite(&rom[flash->data_addr1], 0x1000, 1, f);
fclose(f);
}
/* Save the main block. */
memset(fpath, 0, 1024);
strcpy(fpath, flash_path);
strcat(fpath, "main.bin");
f = romfopen(fpath, "wb");
fwrite(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f);
fclose(f);
/* Save the DMI block. */
memset(fpath, 0, 1024);
strcpy(fpath, flash_path);
strcat(fpath, "dmi.bin");
f = romfopen(fpath, "wb");
fwrite(&(flash->array[flash->block_start[BLOCK_DMI]]), flash->block_len[BLOCK_DMI], 1, f);
fclose(f);
/* Save the ESCD block. */
memset(fpath, 0, 1024);
strcpy(fpath, flash_path);
strcat(fpath, "escd.bin");
f = romfopen(fpath, "wb");
fwrite(&rom[flash->data_addr2], 0x1000, 1, f);
fwrite(&(flash->array[flash->block_start[BLOCK_ESCD]]), flash->block_len[BLOCK_ESCD], 1, f);
fclose(f);
free(flash);

View File

@@ -1,48 +0,0 @@
#include <sys/time.h>
#include <time.h>
#include "ibm.h"
#include "nvr.h"
void time_get(char *nvrram)
{
int c,d;
uint8_t baknvr[10];
time_t cur_time;
struct tm cur_time_tm;
memcpy(baknvr,nvrram,10);
cur_time = time(NULL);
localtime_r(&cur_time, &cur_time_tm);
d = cur_time_tm.tm_sec % 10;
c = cur_time_tm.tm_sec / 10;
nvrram[0] = d | (c << 4);
d = cur_time_tm.tm_min % 10;
c = cur_time_tm.tm_min / 10;
nvrram[2] = d | (c << 4);
d = cur_time_tm.tm_hour % 10;
c = cur_time_tm.tm_hour / 10;
nvrram[4] = d | (c << 4);
d = cur_time_tm.tm_wday % 10;
c = cur_time_tm.tm_wday / 10;
nvrram[6] = d | (c << 4);
d = cur_time_tm.tm_mday % 10;
c = cur_time_tm.tm_mday / 10;
nvrram[7] = d | (c << 4);
d = cur_time_tm.tm_mon % 10;
c = cur_time_tm.tm_mon / 10;
nvrram[8] = d | (c << 4);
d = cur_time_tm.tm_year % 10;
c = (cur_time_tm.tm_year / 10) % 10;
nvrram[9] = d | (c << 4);
if (baknvr[0] != nvrram[0] ||
baknvr[2] != nvrram[2] ||
baknvr[4] != nvrram[4] ||
baknvr[6] != nvrram[6] ||
baknvr[7] != nvrram[7] ||
baknvr[8] != nvrram[8] ||
baknvr[9] != nvrram[9])
nvrram[0xA] |= 0x80;
}

View File

@@ -1647,7 +1647,7 @@ void mem_write_nulll(uint32_t addr, uint32_t val, void *p)
void mem_updatecache()
{
flushmmucache();
if (!is386)
if (!is386 || israpidcad)
{
cachesize=256;
memwaitstate=0;

View File

@@ -441,6 +441,7 @@ void at_batman_init()
sio_init(1);
fdc37c665_init();
intel_batman_init();
device_add(&intel_flash_bxt_ami_device);
if (cdrom_channel >= 4) ide_ter_init();
}
@@ -466,7 +467,7 @@ void at_plato_init()
fdc37c665_init();
/* It seems it uses the same interface as Batman. */
intel_batman_init();
// device_add(&intel_flash_bxt_ami_device);
device_add(&intel_flash_bxt_ami_device);
if (cdrom_channel >= 4) ide_ter_init();
}

390
src/nvr.c
View File

@@ -4,6 +4,7 @@
#include "nvr.h"
#include "pic.h"
#include "timer.h"
#include "rtc.h"
int oldromset;
int nvrmask=63;
@@ -14,230 +15,16 @@ int nvr_dosave = 0;
static int nvr_onesec_time = 0, nvr_onesec_cnt = 0;
int enable_sync = 0;
#define second internal_time[0]
#define minute internal_time[1]
#define hour internal_time[2]
#define day internal_time[3]
#define month internal_time[4]
#define year internal_time[5]
int internal_time[6];
int days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int is_leap(int org_year)
{
if (org_year % 400 == 0) return 1;
if (org_year % 100 == 0) return 0;
if (org_year % 4 == 0) return 1;
return 0;
}
static int get_days(int org_month, int org_year)
{
if (org_month != 2)
{
return days_in_month[org_month];
}
else
{
return is_leap(org_year) ? 29 : 28;
}
}
static int convert_to_bcd(int number)
{
int n1, n2;
n1 = number % 10;
n2 = number - n1;
n2 /= 10;
n2 <<= 4;
return (n2 | n1);
}
static int convert_from_bcd(int number)
{
int n1, n2;
n1 = number & 0xF;
n2 = number >> 4;
n2 *= 10;
return (n2 + n1);
}
static int final_form(int isbcd, int number)
{
return isbcd ? convert_to_bcd(number) : number;
}
static int original_form(int isbcd, int number)
{
return isbcd ? convert_from_bcd(number) : number;
}
static void nvr_recalc_clock()
{
if (second == 60)
{
second = 0;
minute++;
}
if (minute == 60)
{
minute = 0;
hour++;
}
if (hour == 24)
{
hour = 0;
day++;
}
if (day == (get_days(month, year) + 1))
{
day = 1;
month++;
}
if (month == 13)
{
month = 1;
year++;
}
nvr_dosave = 1;
}
static void nvr_update_internal_clock()
{
second++;
nvr_recalc_clock();
}
void nvr_add_10sec()
{
time_sleep(10000);
if (!enable_sync)
{
second+=10;
nvr_recalc_clock();
}
}
static int to_12_hour(int org_hour)
{
int hour2 = org_hour;
hour2 %= 12;
if (!hour2) hour2 = 12;
return hour2;
}
static int from_12_hour(int org_hour)
{
int hour2 = org_hour & 0x7F;
if (hour2 == 12) hour2 = 0;
if (hour & 0x80) hour2 += 12;
return hour2;
}
static int week_day()
{
int day_of_month = day;
int month2 = month;
int year2 = year % 100;
int century = ((year - year2) / 100) % 4;
int sum = day_of_month + month2 + year2 + century;
/* (sum mod 7) gives 0 for Saturday, we need it for Monday, so +5 */
int raw_wd = ((sum + 5) % 7);
/* +1 so 1 = Monday, 7 = Sunday */
return raw_wd + 1;
}
/* Called on every get time. */
static void set_registers()
{
int is24hour = (nvrram[0xB] & 2) ? 1 : 0;
int isbcd = (nvrram[0xB] & 4) ? 0 : 1;
uint8_t baknvr[10];
memcpy(baknvr,nvrram,10);
if (AMSTRAD)
{
is24hour = 1;
isbcd = 1;
}
nvrram[0] = final_form(isbcd, second);
nvrram[2] = final_form(isbcd, minute);
nvrram[4] = is24hour ? final_form(isbcd, hour) : final_form(isbcd, to_12_hour(hour));
nvrram[6] = week_day();
nvrram[7] = final_form(isbcd, day);
nvrram[8] = final_form(isbcd, month);
nvrram[9] = final_form(isbcd, (year % 100));
if (baknvr[0] != nvrram[0] ||
baknvr[2] != nvrram[2] ||
baknvr[4] != nvrram[4] ||
baknvr[6] != nvrram[6] ||
baknvr[7] != nvrram[7] ||
baknvr[8] != nvrram[8] ||
baknvr[9] != nvrram[9])
nvrram[0xA]|=0x80;
}
/* Called on NVR load and write. */
static void get_registers()
{
int is24hour = (nvrram[0xB] & 2) ? 1 : 0;
int isbcd = (nvrram[0xB] & 4) ? 0 : 1;
int temp_hour = 0;
if (AMSTRAD)
{
is24hour = 1;
isbcd = 1;
}
second = original_form(isbcd, nvrram[0]);
minute = original_form(isbcd, nvrram[2]);
hour = is24hour ? original_form(isbcd, nvrram[4]) : from_12_hour(original_form(isbcd, nvrram[4]));
day = original_form(isbcd, nvrram[7]);
month = original_form(isbcd, nvrram[8]);
year = original_form(isbcd, nvrram[9]) + 1900;
}
void getnvrtime()
{
if (enable_sync)
{
/* Get time from host. */
time_get(nvrram);
}
else
{
/* Get time from internal clock. */
set_registers();
}
}
void update_sync()
{
if (enable_sync)
{
/* Get time from host. */
time_get(nvrram);
}
else
{
/* Save time to registers but keep it as is. */
get_registers();
}
time_get(nvrram);
}
void nvr_recalc()
{
int c;
int newrtctime;
c=1<<((nvrram[0xA]&0xF)-1);
c=1<<((nvrram[RTCREGA]&(RTCRS0|RTCRS1|RTCRS2|RTCRS3))-1);
newrtctime=(int)(RTCCONST * c * (1 << TIMER_SHIFT));
if (rtctime>newrtctime) rtctime=newrtctime;
}
@@ -245,42 +32,80 @@ void nvr_recalc()
void nvr_rtc(void *p)
{
int c;
if (!(nvrram[0xA]&0xF))
if (!(nvrram[RTCREGA]&(RTCRS0|RTCRS1|RTCRS2|RTCRS3)))
{
rtctime=0x7fffffff;
return;
}
c=1<<((nvrram[0xA]&0xF)-1);
c=1<<((nvrram[RTCREGA]&(RTCRS0|RTCRS1|RTCRS2|RTCRS3))-1);
rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
// pclog("RTCtime now %f\n",rtctime);
nvrram[0xC] |= 0x40;
if (nvrram[0xB]&0x40)
nvrram[RTCREGC] |= RTCPF;
if (nvrram[RTCREGB]&RTCPIE)
{
nvrram[0xC]|=0x80;
nvrram[RTCREGC]|=RTCIRQF;
if (AMSTRAD) picint(2);
else picint(0x100);
// pclog("RTC int\n");
}
}
int nvr_update_status = 0;
#define ALARM_DONTCARE 0xc0
int nvr_check_alarm(int nvraddr)
{
return (nvrram[nvraddr + 1] == nvrram[nvraddr] || (nvrram[nvraddr + 1] & ALARM_DONTCARE) == ALARM_DONTCARE);
}
void nvr_onesec(void *p)
{
nvr_onesec_cnt++;
if (nvr_onesec_cnt >= 100)
if (nvr_onesec_cnt >= 32768)
{
nvr_onesec_cnt = 0;
/* If sync is disabled, move internal clock ahead by 1 second. */
if (!enable_sync) nvr_update_internal_clock();
nvrram[0xC] |= 0x10;
if (nvrram[0xB] & 0x10)
/* If sync is disabled, move internal clock ahead by 1 second. */
if (!(nvrram[RTCREGB] & RTCSET))
{
nvrram[0xC] |= 0x80;
if (AMSTRAD) picint(2);
else picint(0x100);
nvr_update_status = RTCUIP;
if (!enable_sync) rtc_tick();
nvr_dosave = 1;
}
// pclog("RTC onesec\n");
}
nvr_onesec_time += (int)(10000 * TIMER_USEC);
else if (nvr_onesec_cnt == 73) /* 73 of our cycles means 244+1984 us = update in progress time per the specification. */
{
if (!(nvrram[RTCREGB] & RTCSET))
{
getnvrtime();
/* Clear update status. */
nvr_update_status = 0;
if (nvr_check_alarm(RTCSECONDS) && nvr_check_alarm(RTCMINUTES) && nvr_check_alarm(RTCHOURS))
{
nvrram[RTCREGC] |= RTCAF;
if (nvrram[RTCREGB] & RTCAIE)
{
nvrram[RTCREGC] |= RTCIRQF;
if (AMSTRAD) picint(2);
else picint(0x100);
}
}
/* The flag and interrupt should be issued on update ended, not started. */
nvrram[RTCREGC] |= RTCUF;
if (nvrram[RTCREGB] & RTCUIE)
{
nvrram[RTCREGC] |= RTCIRQF;
if (AMSTRAD) picint(2);
else picint(0x100);
}
// pclog("RTC onesec\n");
}
}
/* This is correct! The real RTC's one second timer operates at 32768 Hz, not 100 Hz! */
nvr_onesec_time += (int)((1000000.0 / 32768.0) * TIMER_USEC);
}
void writenvr(uint16_t addr, uint8_t val, void *priv)
@@ -289,45 +114,48 @@ void writenvr(uint16_t addr, uint8_t val, void *priv)
// printf("Write NVR %03X %02X %02X %04X:%04X %i\n",addr,nvraddr,val,cs>>4,pc,ins);
if (addr&1)
{
if (nvraddr==RTCREGC || nvraddr==RTCREGD) return; /* Registers C and D are read-only. There's no reason to continue. */
// if (nvraddr == 0x33) pclog("NVRWRITE33 %02X %04X:%04X %i\n",val,CS,pc,ins);
old = nvrram[nvraddr];
if (nvraddr >= 0xe && nvrram[nvraddr] != val)
if (nvraddr > RTCREGD && nvrram[nvraddr] != val)
nvr_dosave = 1;
// if (nvraddr==0xB) update_reg_0B(val);
if (nvraddr!=0xC && nvraddr!=0xD) nvrram[nvraddr]=val;
old = nvrram[nvraddr];
nvrram[nvraddr]=val;
/* If not syncing the time with the host, we need to update our internal clock on write. */
if (!enable_sync)
{
switch(nvraddr)
{
case 0:
case 2:
case 4:
case 6:
case 7:
case 8:
case 9:
if (old != val)
{
get_registers();
nvr_dosave = 1;
}
return;
}
}
if (nvraddr==0xA)
if (nvraddr==RTCREGA)
{
// pclog("NVR rate %i\n",val&0xF);
if (val&0xF)
if (val&(RTCRS0|RTCRS1|RTCRS2|RTCRS3))
{
c=1<<((val&0xF)-1);
c=1<<((val&(RTCRS0|RTCRS1|RTCRS2|RTCRS3))-1);
rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
}
else
rtctime = 0x7fffffff;
}
else
{
if (nvraddr==RTCREGB)
{
if (((old ^ val) & RTCSET) && (val & RTCSET))
{
nvrram[RTCREGA] &= ~RTCUIP; /* This has to be done according to the datasheet. */
nvrram[RTCREGB] &= ~RTCUIE; /* This also has to happen per the specification. */
}
}
if ((nvraddr < RTCREGA) || (nvraddr == RTCCENTURY))
{
if ((nvraddr != 1) && (nvraddr != 3) && (nvraddr != 5))
{
if ((old != val) && !enable_sync)
{
time_update(nvrram, nvraddr);
nvr_dosave = 1;
}
}
}
}
}
else nvraddr=val&nvrmask;
}
@@ -338,20 +166,14 @@ uint8_t readnvr(uint16_t addr, void *priv)
// printf("Read NVR %03X %02X %02X %04X:%04X\n",addr,nvraddr,nvrram[nvraddr],cs>>4,pc);
if (addr&1)
{
if (nvraddr<=0xA) getnvrtime();
if (nvraddr==0xD) nvrram[0xD]|=0x80;
if (nvraddr==0xA)
{
temp=nvrram[0xA];
nvrram[0xA]&=~0x80;
return temp;
}
if (nvraddr==0xC)
if (nvraddr==RTCREGA) return ((nvrram[RTCREGA] & 0x7F) | nvr_update_status);
if (nvraddr==RTCREGD) nvrram[RTCREGD]|=RTCVRT;
if (nvraddr==RTCREGC)
{
if (AMSTRAD) picintc(2);
else picintc(0x100);
temp=nvrram[0xC];
nvrram[0xC]=0;
temp=nvrram[RTCREGC];
nvrram[RTCREGC]=0; /* All flags in register C are unused (always 0) or cleared on read */
return temp;
}
// if (AMIBIOS && nvraddr==0x36) return 0;
@@ -379,7 +201,7 @@ void loadnvr()
case ROM_IBMPS1_2121: f = romfopen("nvr/ibmps1_2121.nvr", "rb"); nvrmask = 127; break;
case ROM_CMDPC30: f = romfopen("nvr/cmdpc30.nvr", "rb"); nvrmask = 127; break;
case ROM_AMI286: f = romfopen("nvr/ami286.nvr", "rb"); nvrmask = 127; break;
case ROM_AWARD286: f = romfopen("nvr/award286.nvr", "rb"); nvrmask = 127; break;
case ROM_AWARD286: f = romfopen("nvr/award286.nvr", "rb"); nvrmask = 127; break;
case ROM_DELL200: f = romfopen("nvr/dell200.nvr", "rb"); nvrmask = 127; break;
case ROM_IBMAT386: f = romfopen("nvr/at386.nvr", "rb"); nvrmask = 127; break;
case ROM_DESKPRO_386: f = romfopen("nvr/deskpro386.nvr", "rb"); break;
@@ -413,19 +235,22 @@ void loadnvr()
if (!f)
{
memset(nvrram,0xFF,128);
if (!enable_sync)
{
nvrram[RTCSECONDS] = nvrram[RTCMINUTES] = nvrram[RTCHOURS] = 0;
nvrram[RTCDOM] = nvrram[RTCMONTH] = 1;
nvrram[RTCYEAR] = BCD(80);
nvrram[RTCCENTURY] = BCD(19);
nvrram[RTCREGB]=RTC2412;
}
return;
}
fread(nvrram,128,1,f);
if (!(feof(f)))
fread(internal_time,6,4,f);
else
{
if (!enable_sync) get_registers();
}
if (!enable_sync) time_update(nvrram, 0xFF); /* Update the internal clock state based on the NVR registers. */
fclose(f);
nvrram[0xA]=6;
nvrram[0xB]=0;
c=1<<((6&0xF)-1);
nvrram[RTCREGA]=(RTCRS1|RTCRS2);
nvrram[RTCREGB]=RTC2412;
c=1<<((nvrram[RTCREGA]&(RTCRS0|RTCRS1|RTCRS2|RTCRS3))-1);
rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
}
void savenvr()
@@ -443,7 +268,7 @@ void savenvr()
case ROM_IBMPS1_2121: f = romfopen("nvr/ibmps1_2121.nvr", "wb"); break;
case ROM_CMDPC30: f = romfopen("nvr/cmdpc30.nvr", "wb"); break;
case ROM_AMI286: f = romfopen("nvr/ami286.nvr", "wb"); break;
case ROM_AWARD286: f = romfopen("nvr/award286.nvr", "wb"); break;
case ROM_AWARD286: f = romfopen("nvr/award286.nvr", "wb"); break;
case ROM_DELL200: f = romfopen("nvr/dell200.nvr", "wb"); break;
case ROM_IBMAT386: f = romfopen("nvr/at386.nvr", "wb"); break;
case ROM_DESKPRO_386: f = romfopen("nvr/deskpro386.nvr", "wb"); break;
@@ -474,10 +299,7 @@ void savenvr()
case ROM_KN97: f = romfopen("nvr/kn97.nvr", "wb"); break;
default: return;
}
/* If sync is disabled, save internal clock to registers. */
if (!enable_sync) set_registers();
fwrite(nvrram,128,1,f);
fwrite(internal_time,6,4,f);
fclose(f);
}

View File

@@ -1,11 +1,8 @@
void nvr_init();
extern int nvr_dosave;
extern int enable_sync;
void time_sleep(int count);
extern int nvr_dosave;
void time_get(char *nvrram);
void nvr_add_10sec();
void update_sync();

View File

@@ -511,7 +511,7 @@ void runpc()
if (win_title_update)
{
win_title_update=0;
sprintf(s, "PCem v11 [Experimental] - %i%% - %s - %s - %s", fps, model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : "Press F12-F8 or middle button to release mouse");
sprintf(s, "PCem v11 [Unofficial] - %i%% - %s - %s - %s", fps, model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : "Press F12-F8 or middle button to release mouse");
set_window_title(s);
}
done++;
@@ -673,11 +673,9 @@ void loadconfig(char *fn)
force_43 = config_get_int(NULL, "force_43", 0);
enable_overscan = config_get_int(NULL, "enable_overscan", 0);
cga_color_burst = config_get_int(NULL, "cga_color_burst", 1);
cga_brown = config_get_int(NULL, "cga_brown", 1);
enable_flash = config_get_int(NULL, "enable_flash", 1);
enable_sync = config_get_int(NULL, "enable_sync", 0);
enable_sync = config_get_int(NULL, "enable_sync", 1);
mouse_always_serial = config_get_int(NULL, "mouse_always_serial", 0);
window_w = config_get_int(NULL, "window_w", 0);
@@ -768,8 +766,6 @@ void saveconfig()
config_set_int(NULL, "force_43", force_43);
config_set_int(NULL, "enable_overscan", enable_overscan);
config_set_int(NULL, "cga_color_burst", cga_color_burst);
config_set_int(NULL, "cga_brown", cga_brown);
config_set_int(NULL, "enable_flash", enable_flash);
config_set_int(NULL, "enable_sync", enable_sync);

View File

@@ -57,13 +57,13 @@ BEGIN
END
END
ConfigureDlg DIALOGEX 0, 0, 248+40, 248+76
ConfigureDlg DIALOGEX 0, 0, 248+40, 248+60
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Configure PCem"
FONT 9, "Segoe UI"
BEGIN
DEFPUSHBUTTON "OK",IDOK,64,300,50,14, WS_TABSTOP
PUSHBUTTON "Cancel",IDCANCEL,128,300,50,14, WS_TABSTOP
DEFPUSHBUTTON "OK",IDOK,64,284,50,14, WS_TABSTOP
PUSHBUTTON "Cancel",IDCANCEL,128,284,50,14, WS_TABSTOP
COMBOBOX IDC_COMBO1,62,16,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBOVID,62,36,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Configure", IDC_CONFIGUREVID, 224, 36, 40, 14, WS_TABSTOP
@@ -84,22 +84,19 @@ BEGIN
CONTROL "Enable time sync",IDC_CHECKSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,236,102,10
CONTROL "Force 4:3 display ratio",IDC_CHECKFORCE43,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,172,102,10
CONTROL "Composite CGA color burst",IDC_CHECKCBURST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,188,102,10
CONTROL "RGB CGA brown circuit",IDC_CHECKBROWN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,204,102,10
CONTROL "EGA/(S)VGA overscan",IDC_CHECKOVERSCAN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,220,102,10
CONTROL "Disk activity flash",IDC_CHECKFLASH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,236,102,10
CONTROL "EGA/(S)VGA overscan",IDC_CHECKOVERSCAN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,188,102,10
CONTROL "Disk activity flash",IDC_CHECKFLASH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,204,102,10
CONTROL "Ser.mouse inst.of PS/2",IDC_CHECKSERIAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,220,102,10
CONTROL "Ser. mouse instead of PS/2",IDC_CHECKSERIAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,252,102,10
CONTROL "Voodoo Graphics",IDC_CHECKVOODOO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,236,102,10
PUSHBUTTON "Configure", IDC_CONFIGUREVOODOO, 224, 236, 40, 14, WS_TABSTOP
CONTROL "Voodoo Graphics",IDC_CHECKVOODOO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,252,102,10
PUSHBUTTON "Configure", IDC_CONFIGUREVOODOO, 224, 252, 40, 14, WS_TABSTOP
LTEXT "Joystick :",IDC_STATIC,15,268,40,10
COMBOBOX IDC_COMBOJOY,62,268,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Joystick 1...",IDC_JOY1,16,284,50,14, WS_TABSTOP
PUSHBUTTON "Joystick 2...",IDC_JOY2,80,284,50,14, WS_TABSTOP
DEFPUSHBUTTON "Joystick 3...",IDC_JOY3,144,284,50,14, WS_TABSTOP
PUSHBUTTON "Joystick 4...",IDC_JOY4,208,284,50,14, WS_TABSTOP
LTEXT "Joystick :",IDC_STATIC,15,252,40,10
COMBOBOX IDC_COMBOJOY,62,252,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Joystick 1...",IDC_JOY1,16,268,50,14, WS_TABSTOP
PUSHBUTTON "Joystick 2...",IDC_JOY2,80,268,50,14, WS_TABSTOP
DEFPUSHBUTTON "Joystick 3...",IDC_JOY3,144,268,50,14, WS_TABSTOP
PUSHBUTTON "Joystick 4...",IDC_JOY4,208,268,50,14, WS_TABSTOP
LTEXT "Machine :",IDC_STATIC,15,16,40,10
LTEXT "Video :",IDC_STATIC,15,36,34,10

View File

@@ -51,11 +51,9 @@
#define IDC_STATIC 1020
#define IDC_CHECKFORCE43 1021
#define IDC_CHECKOVERSCAN 1022
#define IDC_CHECKCBURST 1023
#define IDC_CHECKBROWN 1024
#define IDC_CHECKFLASH 1025
#define IDC_CHECKSYNC 1026
#define IDC_CHECKSERIAL 1027
#define IDC_CHECKFLASH 1023
#define IDC_CHECKSYNC 1024
#define IDC_CHECKSERIAL 1025
#define IDC_EDIT1 1030
#define IDC_EDIT2 1031
#define IDC_EDIT3 1032

261
src/rtc.c Normal file
View File

@@ -0,0 +1,261 @@
/* Emulation of:
Dallas Semiconductor DS12C887 Real Time Clock
http://datasheets.maximintegrated.com/en/ds/DS12885-DS12C887A.pdf
http://dev-docs.atariforge.org/files/MC146818A_RTC_1984.pdf
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "nvr.h"
#include "rtc.h"
int enable_sync;
typedef struct
{
int sec;
int min;
int hour;
int mday;
int mon;
int year;
}
internal_clock_t;
internal_clock_t internal_clock;
/* When the RTC was last updated */
time_t rtc_set_time = 0;
/* Table for days in each month */
int rtc_days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/* Called to determine whether the year is leap or not */
static int rtc_is_leap(int org_year)
{
if (org_year % 400 == 0) return 1;
if (org_year % 100 == 0) return 0;
if (org_year % 4 == 0) return 1;
return 0;
}
/* Called to determine the days in the current month */
static int rtc_get_days(int org_month, int org_year)
{
if (org_month != 2)
{
return rtc_days_in_month[org_month];
}
else
{
return rtc_is_leap(org_year) ? 29 : 28;
}
}
/* Called when the internal clock gets updated */
static void rtc_recalc()
{
if (internal_clock.sec == 60)
{
internal_clock.sec = 0;
internal_clock.min++;
}
if (internal_clock.min == 60)
{
internal_clock.min = 0;
internal_clock.hour++;
}
if (internal_clock.hour == 24)
{
internal_clock.hour = 0;
internal_clock.mday++;
}
if (internal_clock.mday == (rtc_get_days(internal_clock.mon, internal_clock.year) + 1))
{
internal_clock.mday = 1;
internal_clock.mon++;
}
if (internal_clock.mon == 13)
{
internal_clock.mon = 1;
internal_clock.year++;
}
nvr_dosave = 1;
}
/* Called when ticking the second */
void rtc_tick()
{
internal_clock.sec++;
rtc_recalc();
}
/* Called when modifying the NVR registers */
void time_update(char *nvrram, int reg)
{
int temp;
switch(reg)
{
case RTCSECONDS:
internal_clock.sec = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCSECONDS] : DCB(nvrram[RTCSECONDS]);
break;
case RTCMINUTES:
internal_clock.min = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCMINUTES] : DCB(nvrram[RTCMINUTES]);
break;
case RTCHOURS:
temp = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCHOURS] : DCB(nvrram[RTCHOURS]);
if (nvrram[RTCREGB] & RTC2412)
{
internal_clock.hour = temp;
}
else
{
internal_clock.hour = ((temp & ~RTCAMPM) % 12) + ((temp & RTCAMPM) ? 12 : 0);
}
break;
case RTCDOM:
internal_clock.mday = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCDOM] : DCB(nvrram[RTCDOM]);
break;
case RTCMONTH:
internal_clock.mon = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCMONTH] : DCB(nvrram[RTCMONTH]);
break;
case RTCYEAR:
internal_clock.year = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCYEAR] : DCB(nvrram[RTCYEAR]);
internal_clock.year += (nvrram[RTCREGB] & RTCDM) ? 1900 : (DCB(nvrram[RTCCENTURY]) * 100);
break;
case RTCCENTURY:
if (nvrram[RTCREGB] & RTCDM) return;
internal_clock.year %= 100;
internal_clock.year += (DCB(nvrram[RTCCENTURY]) * 100);
break;
case 0xFF: /* Load the entire internal clock state from the NVR. */
internal_clock.sec = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCSECONDS] : DCB(nvrram[RTCSECONDS]);
internal_clock.min = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCMINUTES] : DCB(nvrram[RTCMINUTES]);
temp = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCHOURS] : DCB(nvrram[RTCHOURS]);
if (nvrram[RTCREGB] & RTC2412)
{
internal_clock.hour = temp;
}
else
{
internal_clock.hour = ((temp & ~RTCAMPM) % 12) + ((temp & RTCAMPM) ? 12 : 0);
}
internal_clock.mday = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCDOM] : DCB(nvrram[RTCDOM]);
internal_clock.mon = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCMONTH] : DCB(nvrram[RTCMONTH]);
internal_clock.year = (nvrram[RTCREGB] & RTCDM) ? nvrram[RTCYEAR] : DCB(nvrram[RTCYEAR]);
internal_clock.year += (nvrram[RTCREGB] & RTCDM) ? 1900 : (DCB(nvrram[RTCCENTURY]) * 100);
break;
}
}
/* Called to obtain the current day of the week based on the internal clock */
static int time_week_day()
{
int day_of_month = internal_clock.mday;
int month2 = internal_clock.mon;
int year2 = internal_clock.year % 100;
int century = ((internal_clock.year - year2) / 100) % 4;
int sum = day_of_month + month2 + year2 + century;
/* (Sum mod 7) gives 0 for Saturday, we need it for Sunday, so +6 for Saturday to get 6 and Sunday 0 */
int raw_wd = ((sum + 6) % 7);
return raw_wd;
}
/* Called to get time into the internal clock */
static void time_internal(struct tm **time_var)
{
if (*time_var == NULL) *time_var = (struct tm *) malloc(sizeof(struct tm));
(*time_var)->tm_sec = internal_clock.sec;
(*time_var)->tm_min = internal_clock.min;
(*time_var)->tm_hour = internal_clock.hour;
(*time_var)->tm_wday = time_week_day();
(*time_var)->tm_mday = internal_clock.mday;
(*time_var)->tm_mon = internal_clock.mon - 1;
(*time_var)->tm_year = internal_clock.year - 1900;
}
/* Periodic RTC update function
See also: nvr_onesec() in nvr.c
*/
void time_get(char *nvrram)
{
time_t cur_time;
struct tm* cur_time_tm;
int dow, mon, year;
if (enable_sync)
{
cur_time = time(NULL);
/* Mingw doesn't support localtime_r */
#if __MINGW32__
cur_time_tm = localtime(&cur_time);
#else
#if __MINGW64__
cur_time_tm = localtime(&cur_time);
#else
localtime_r(&cur_time, &cur_time_tm);
#endif
#endif
}
else
{
time_internal(&cur_time_tm);
}
if (nvrram[RTCREGB] & RTCDM)
{
nvrram[RTCSECONDS] = cur_time_tm->tm_sec;
nvrram[RTCMINUTES] = cur_time_tm->tm_min;
nvrram[RTCDOW] = cur_time_tm->tm_wday + 1;
nvrram[RTCDOM] = cur_time_tm->tm_mday;
nvrram[RTCMONTH] = cur_time_tm->tm_mon + 1;
nvrram[RTCYEAR] = cur_time_tm->tm_year % 100;
if (nvrram[RTCREGB] & RTC2412)
{
nvrram[RTCHOURS] = cur_time_tm->tm_hour;
}
else
{
nvrram[RTCHOURS] = (cur_time_tm->tm_hour % 12) ? (cur_time_tm->tm_hour % 12) : 12;
if (cur_time_tm->tm_hour > 11)
{
nvrram[RTCHOURS] |= RTCAMPM;
}
}
}
else
{
nvrram[RTCSECONDS] = BCD(cur_time_tm->tm_sec);
nvrram[RTCMINUTES] = BCD(cur_time_tm->tm_min);
nvrram[RTCDOW] = BCD(cur_time_tm->tm_wday + 1);
nvrram[RTCDOM] = BCD(cur_time_tm->tm_mday);
nvrram[RTCMONTH] = BCD(cur_time_tm->tm_mon + 1);
nvrram[RTCYEAR] = BCD(cur_time_tm->tm_year % 100);
if (nvrram[RTCREGB] & RTC2412)
{
nvrram[RTCHOURS] = BCD(cur_time_tm->tm_hour);
}
else
{
nvrram[RTCHOURS] = (cur_time_tm->tm_hour % 12) ? BCD(cur_time_tm->tm_hour % 12) : BCD(12);
if (cur_time_tm->tm_hour > 11)
{
nvrram[RTCHOURS] |= RTCAMPM;
}
}
}
}

186
src/rtc.h Normal file
View File

@@ -0,0 +1,186 @@
#define BCD(X) (((X) % 10) | (((X) / 10) << 4))
#define DCB(X) ((((X) & 0xF0) >> 4) * 10 + ((X) & 0x0F))
enum RTCADDR
{
RTCSECONDS,
RTCALARMSECONDS,
RTCMINUTES,
RTCALARMMINUTES,
RTCHOURS,
RTCALARMHOURS,
RTCDOW,
RTCDOM,
RTCMONTH,
RTCYEAR,
RTCREGA,
RTCREGB,
RTCREGC,
RTCREGD
};
/* The century register at location 32h is a BCD register designed to automatically load the BCD value 20 as the year register changes from 99 to 00.
The MSB of this register is not affected when the load of 20 occurs, and remains at the value written by the user. */
#define RTCCENTURY 0x32
/* When the 12-hour format is selected, the higher-order bit of the hours byte represents PM when it is logic 1. */
#define RTCAMPM 0b10000000
/* Register A bitflags */
enum RTCRABITS
{
/* Rate Selector (RS0)
These four rate-selection bits select one of the 13 taps on the 15-stage divider or disable the divider output.
The tap selected can be used to generate an output square wave (SQW pin) and/or a periodic interrupt.
The user can do one of the following:
- Enable the interrupt with the PIE bit;
- Enable the SQW output pin with the SQWE bit;
- Enable both at the same time and the same rate; or
- Enable neither.
Table 3 lists the periodic interrupt rates and the square wave frequencies that can be chosen with the RS bits.
These four read/write bits are not affected by !RESET. */
RTCRS0 = 0b1,
RTCRS1 = 0b10, /*!<RS1*/
RTCRS2 = 0b100, /*!<RS2*/
RTCRS3 = 0b1000, /*!<RS3*/
/* DV0
These three bits are used to turn the oscillator on or off and to reset the countdown chain.
A pattern of 010 is the only combination of bits that turn the oscillator on and allow the RTC to keep time.
A pattern of 11x enables the oscillator but holds the countdown chain in reset.
The next update occurs at 500ms after a pattern of 010 is written to DV0, DV1, and DV2. */
RTCDV0 = 0b10000,
RTCDV1 = 0b100000, /*!<DV1*/
RTCDV2 = 0b1000000, /*!<DV2*/
/* Update-In-Progress (UIP)
This bit is a status flag that can be monitored. When the UIP bit is a 1, the update transfer occurs soon.
When UIP is a 0, the update transfer does not occur for at least 244us.
The time, calendar, and alarm information in RAM is fully available for access when the UIP bit is 0.
The UIP bit is read-only and is not affected by !RESET.
Writing the SET bit in Register B to a 1 inhibits any update transfer and clears the UIP status bit. */
RTCUIP = 0b10000000
};
/* Register B bitflags */
enum RTCRBBITS
{
/* Daylight Saving Enable (DSE)
This bit is a read/write bit that enables two daylight saving adjustments when DSE is set to 1.
On the first Sunday in April (or the last Sunday in April in the MC146818A), the time increments from 1:59:59 AM to 3:00:00 AM.
On the last Sunday in October when the time first reaches 1:59:59 AM, it changes to 1:00:00 AM.
When DSE is enabled, the internal logic test for the first/last Sunday condition at midnight.
If the DSE bit is not set when the test occurs, the daylight saving function does not operate correctly.
These adjustments do not occur when the DSE bit is 0. This bit is not affected by internal functions or !RESET. */
RTCDSE = 0b1,
/* 24/12
The 24/12 control bit establishes the format of the hours byte. A 1 indicates the 24-hour mode and a 0 indicates the 12-hour mode.
This bit is read/write and is not affected by internal functions or !RESET. */
RTC2412 = 0b10,
/* Data Mode (DM)
This bit indicates whether time and calendar information is in binary or BCD format.
The DM bit is set by the program to the appropriate format and can be read as required.
This bit is not modified by internal functions or !RESET. A 1 in DM signifies binary data, while a 0 in DM specifies BCD data. */
RTCDM = 0b100,
/* Square-Wave Enable (SQWE)
When this bit is set to 1, a square-wave signal at the frequency set by the rate-selection bits RS3-RS0 is driven out on the SQW pin.
When the SQWE bit is set to 0, the SQW pin is held low. SQWE is a read/write bit and is cleared by !RESET.
SQWE is low if disabled, and is high impedance when VCC is below VPF. SQWE is cleared to 0 on !RESET. */
RTCSQWE = 0b1000,
/* Update-Ended Interrupt Enable (UIE)
This bit is a read/write bit that enables the update-end flag (UF) bit in Register C to assert !IRQ.
The !RESET pin going low or the SET bit going high clears the UIE bit.
The internal functions of the device do not affect the UIE bit, but is cleared to 0 on !RESET. */
RTCUIE = 0b10000,
/* Alarm Interrupt Enable (AIE)
This bit is a read/write bit that, when set to 1, permits the alarm flag (AF) bit in Register C to assert !IRQ.
An alarm interrupt occurs for each second that the three time bytes equal the three alarm bytes, including a don't-care alarm code of binary 11XXXXXX.
The AF bit does not initiate the !IRQ signal when the AIE bit is set to 0.
The internal functions of the device do not affect the AIE bit, but is cleared to 0 on !RESET. */
RTCAIE = 0b100000,
/* Periodic Interrupt Enable (PIE)
The PIE bit is a read/write bit that allows the periodic interrupt flag (PF) bit in Register C to drive the !IRQ pin low.
When the PIE bit is set to 1, periodic interrupts are generated by driving the !IRQ pin low at a rate specified by the RS3-RS0 bits of Register A.
A 0 in the PIE bit blocks the !IRQ output from being driven by a periodic interrupt, but the PF bit is still set at the periodic rate.
PIE is not modified by any internal device functions, but is cleared to 0 on !RESET. */
RTCPIE = 0b1000000,
/* SET
When the SET bit is 0, the update transfer functions normally by advancing the counts once per second.
When the SET bit is written to 1, any update transfer is inhibited, and the program can initialize the time and calendar bytes without an update
occurring in the midst of initializing. Read cycles can be executed in a similar manner. SET is a read/write bit and is not affected by !RESET or
internal functions of the device. */
RTCSET = 0b10000000
};
/* Register C bitflags */
enum RTCRCBITS
{
/* Unused
These bits are unused in Register C. These bits always read 0 and cannot be written. */
RTCRC0 = 0b1,
RTCRC1 = 0b10, /*!<Unused*/
RTCRC2 = 0b100, /*!<Unused*/
RTCRC3 = 0b1000, /*!<Unused*/
/* Update-Ended Interrupt Flag (UF)
This bit is set after each update cycle. When the UIE bit is set to 1, the 1 in UF causes the IRQF bit to be a 1, which asserts the !IRQ pin.
This bit can be cleared by reading Register C or with a !RESET. */
RTCUF = 0b10000,
/* Alarm Interrupt Flag (AF)
A 1 in the AF bit indicates that the current time has matched the alarm time.
If the AIE bit is also 1, the !IRQ pin goes low and a 1 appears in the IRQF bit. This bit can be cleared by reading Register C or with a !RESET. */
RTCAF = 0b100000,
/* Periodic Interrupt Flag (PF)
This bit is read-only and is set to 1 when an edge is detected on the selected tap of the divider chain.
The RS3 through RS0 bits establish the periodic rate. PF is set to 1 independent of the state of the PIE bit.
When both PF and PIE are 1s, the !IRQ signal is active and sets the IRQF bit. This bit can be cleared by reading Register C or with a !RESET. */
RTCPF = 0b1000000,
/* Interrupt Request Flag (IRQF)
The interrupt request flag (IRQF) is set to a 1 when one or more of the following are true:
- PF == PIE == 1
- AF == AIE == 1
- UF == UIE == 1
Any time the IRQF bit is a 1, the !IRQ pin is driven low.
All flag bits are cleared after Register C is read by the program or when the !RESET pin is low. */
RTCIRQF = 0b10000000
};
/* Register D bitflags */
enum RTCRDBITS
{
/* Unused
The remaining bits of Register D are not usable. They cannot be written and they always read 0. */
RTCRD0 = 0b1,
RTCRD1 = 0b10, /*!<Unused*/
RTCRD2 = 0b100, /*!<Unused*/
RTCRD3 = 0b1000, /*!<Unused*/
RTCRD4 = 0b10000, /*!<Unused*/
RTCRD5 = 0b100000, /*!<Unused*/
RTCRD6 = 0b1000000, /*!<Unused*/
/* Valid RAM and Time (VRT)
This bit indicates the condition of the battery connected to the VBAT pin. This bit is not writeable and should always be 1 when read.
If a 0 is ever present, an exhausted internal lithium energy source is indicated and both the contents of the RTC data and RAM data are questionable.
This bit is unaffected by !RESET. */
RTCVRT = 0b10000000
};
void rtc_tick();
void time_update(char *nvrram, int reg);
void time_get(char *nvrram);

View File

@@ -8,14 +8,13 @@
#include "timer.h"
#include "video.h"
#include "vid_cga.h"
#include "vid_cga_comp.h"
#include "dosbox/vid_cga_comp.h"
static int i_filt[8],q_filt[8];
#define CGA_RGB 0
#define CGA_COMPOSITE 1
static uint8_t tarray[65536];
int cga_brown;
int cga_color_burst;
#define COMPOSITE_OLD 0
#define COMPOSITE_NEW 1
static uint8_t crtcmask[32] =
{
@@ -48,7 +47,8 @@ void cga_out(uint16_t addr, uint8_t val, void *p)
}
return;
case 0x3D8:
if (((cga->cgamode ^ val) & 5) != 0) {
if (((cga->cgamode ^ val) & 5) != 0)
{
cga->cgamode = val;
update_cga16_color(cga);
}
@@ -80,9 +80,6 @@ void cga_write(uint32_t addr, uint8_t val, void *p)
{
cga_t *cga = (cga_t *)p;
// pclog("CGA_WRITE %04X %02X\n", addr, val);
/* Horrible hack, I know, but it's the only way to fix the 440FX BIOS filling the VRAM with garbage until Tom fixes the memory emulation. */
if ((cs == 0xE0000) && (cpu_state.pc == 0xBF2F) && (romset == ROM_440FX)) { egawrites++; return; }
if ((cs == 0xE0000) && (cpu_state.pc == 0xBF77) && (romset == ROM_440FX)) { egawrites++; return; }
cga->vram[addr & 0x3fff] = val;
cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val;
cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
@@ -125,18 +122,6 @@ void cga_recalctimings(cga_t *cga)
cga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
}
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*/
};
void cga_poll(void *p)
{
cga_t *cga = (cga_t *)p;
@@ -149,11 +134,7 @@ void cga_poll(void *p)
int cols[4];
int col;
int oldsc;
int y_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, y_val, y_tot;
int i_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, i_val, i_tot;
int q_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, q_val, q_tot;
int r, g, b;
uint8_t *tline;
if (!cga->linepos)
{
cga->vidtime += cga->dispofftime;
@@ -307,21 +288,12 @@ void cga_poll(void *p)
if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16;
else x = (cga->crtc[1] << 4) + 16;
if (cga_comp)
if (cga->composite)
{
tline = (uint8_t *) buffer32->line[cga->displine];
for (c = 0; c < x; c++)
buffer32->line[cga->displine][c] = buffer->line[cga->displine][c] & 0xf;
for (c = 0; c < x; c++)
{
tarray[c] = buffer->line[cga->displine][c] & 0xf;
}
Composite_Process(cga, 0, x >> 2, tarray);
for (c = 0; c < x; c++)
{
((uint32_t *) tline)[c] = ((uint32_t *) tarray)[c];
}
Composite_Process(cga, 0, x >> 2, buffer32->line[cga->displine]);
}
cga->sc = oldsc;
@@ -386,8 +358,7 @@ void cga_poll(void *p)
{
cga->cgadispon = 0;
cga->displine = 0;
// cga->vsynctime = (cga->crtc[3] >> 4) + 1;
cga->vsynctime = 16;
cga->vsynctime = 16;
if (cga->crtc[7])
{
if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16;
@@ -403,7 +374,7 @@ void cga_poll(void *p)
}
startblit();
if (cga_comp)
if (cga->composite)
video_blit_memtoscreen(0, cga->firstline - 4, 0, (cga->lastline - cga->firstline) + 8, xsize, (cga->lastline - cga->firstline) + 8);
else
video_blit_memtoscreen_8(0, cga->firstline - 4, xsize, (cga->lastline - cga->firstline) + 8);
@@ -445,7 +416,8 @@ endblit();
cga->sc &= 31;
cga->ma = cga->maback;
}
if (cga->cgadispon) cga->cgastat &= ~1;
if (cga->cgadispon)
cga->cgastat &= ~1;
if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))))
cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1))
@@ -458,28 +430,27 @@ endblit();
void cga_init(cga_t *cga)
{
cga->composite = 0;
}
void *cga_standalone_init()
{
int c;
int cga_tint = -2;
int display_type;
cga_t *cga = malloc(sizeof(cga_t));
memset(cga, 0, sizeof(cga_t));
display_type = device_get_config_int("display_type");
cga->composite = (display_type != CGA_RGB);
cga->revision = device_get_config_int("composite_type");
cga->vram = malloc(0x4000);
cga_comp_init(cga);
cga_comp_init(cga);
timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga);
mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga);
io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga);
for (c = 0; c < 8192; c++)
{
((uint64_t *) tarray)[c] = 0;
}
overscan_x = overscan_y = 16;
overscan_x = overscan_y = 16;
return cga;
}
@@ -499,26 +470,62 @@ void cga_speed_changed(void *p)
cga_recalctimings(cga);
}
device_t cga_device =
static device_config_t cga_config[] =
{
"CGA (Old)",
0,
cga_standalone_init,
cga_close,
NULL,
cga_speed_changed,
NULL,
NULL
{
.name = "display_type",
.description = "Display type",
.type = CONFIG_SELECTION,
.selection =
{
{
.description = "RGB",
.value = CGA_RGB
},
{
.description = "Composite",
.value = CGA_COMPOSITE
},
{
.description = ""
}
},
.default_int = CGA_RGB
},
{
.name = "composite_type",
.description = "Composite type",
.type = CONFIG_SELECTION,
.selection =
{
{
.description = "Old",
.value = COMPOSITE_OLD
},
{
.description = "New",
.value = COMPOSITE_NEW
},
{
.description = ""
}
},
.default_int = COMPOSITE_OLD
},
{
.type = -1
}
};
device_t cga_new_device =
device_t cga_device =
{
"CGA (New)",
"CGA",
0,
cga_standalone_init,
cga_close,
NULL,
cga_speed_changed,
NULL,
NULL
NULL,
cga_config
};

View File

@@ -27,6 +27,9 @@ typedef struct cga_t
uint8_t *vram;
uint8_t charbuffer[256];
int revision;
int composite;
} cga_t;
void cga_init(cga_t *cga);
@@ -37,5 +40,4 @@ uint8_t cga_read(uint32_t addr, void *p);
void cga_recalctimings(cga_t *cga);
void cga_poll(void *p);
extern device_t cga_new_device;
extern device_t cga_device;

View File

@@ -51,8 +51,7 @@ static VIDEO_CARD video_cards[] =
{"ATI VGA Charger (ATI-28800)", &ati28800_device, GFX_VGACHARGER},
{"ATI VGA Edge-16 (ATI-18800)", &ati18800_device, GFX_VGAEDGE16},
{"Cardex Tseng ET4000/w32p", &et4000w32pc_device, GFX_ET4000W32C},
{"CGA (New)", &cga_new_device, GFX_NEW_CGA},
{"CGA (Old)", &cga_device, GFX_CGA},
{"CGA", &cga_device, GFX_CGA},
{"Cirrus Logic CL-GD5429", &gd5429_device, GFX_CL_GD5429},
{"Diamond Stealth 32 (Tseng ET4000/w32p)", &et4000w32p_device, GFX_ET4000W32},
{"Diamond Stealth 3D 2000 (S3 ViRGE)", &s3_virge_device, GFX_VIRGE},

View File

@@ -75,10 +75,6 @@ extern int enable_overscan;
extern int overscan_x, overscan_y;
/* Forcibly stretch emulated video output to 4:3 or not. */
extern int force_43;
/* Enable CGA brown circuitry. */
extern int cga_brown;
/* Enable CGA color burst. */
extern int cga_color_burst;
/* Enable disk activity flash. */
extern int enable_flash;

View File

@@ -172,12 +172,6 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
h=GetDlgItem(hdlg, IDC_CHECK4);
SendMessage(h, BM_SETCHECK, cga_comp, 0);
h=GetDlgItem(hdlg, IDC_CHECKCBURST);
SendMessage(h, BM_SETCHECK, cga_color_burst, 0);
h=GetDlgItem(hdlg, IDC_CHECKBROWN);
SendMessage(h, BM_SETCHECK, cga_brown, 0);
h=GetDlgItem(hdlg, IDC_CHECKFORCE43);
SendMessage(h, BM_SETCHECK, force_43, 0);
@@ -340,18 +334,11 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
h = GetDlgItem(hdlg, IDC_CHECKOVERSCAN);
enable_overscan = SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CHECKCBURST);
cga_color_burst=SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CHECKBROWN);
cga_brown=SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CHECKFLASH);
enable_flash=SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CHECKSYNC);
enable_sync = SendMessage(h, BM_GETCHECK, 0, 0);
update_sync();
h = GetDlgItem(hdlg, IDC_CHECKSERIAL);
temp_always_serial = SendMessage(h, BM_GETCHECK, 0, 0);

View File

@@ -286,8 +286,6 @@ static void ddraw_fs_blit_memtoscreen_8(int x, int y, int w, int h)
for (xx = 0; xx < w; xx++)
{
p[xx] = pal_lookup[buffer->line[y + yy][x + xx]];
/* If brown circuity is disabled, double the green component. */
if ((buffer->line[y + yy][x + xx] == 0x16) && !cga_brown) p[xx] += (p[xx] & 0xff00);
}
}
}

View File

@@ -252,8 +252,6 @@ static void ddraw_blit_memtoscreen_8(int x, int y, int w, int h)
for (xx = 0; xx < w; xx++)
{
p[xx] = pal_lookup[buffer->line[y + yy][x + xx]];
/* If brown circuity is disabled, double the green component. */
if ((buffer->line[y + yy][x + xx] == 0x16) && !cga_brown) p[xx] += (p[xx] & 0xff00);
}
}
}

View File

@@ -1,48 +0,0 @@
#include <windows.h>
#include "ibm.h"
#include "nvr.h"
void time_sleep(int count)
{
Sleep(count);
}
void time_get(char *nvrram)
{
SYSTEMTIME systemtime;
int c, d;
uint8_t baknvr[10];
memcpy(baknvr,nvrram,10);
GetLocalTime(&systemtime);
d = systemtime.wSecond % 10;
c = systemtime.wSecond / 10;
nvrram[0] = d | (c << 4);
d = systemtime.wMinute % 10;
c = systemtime.wMinute / 10;
nvrram[2] = d | (c << 4);
d = systemtime.wHour % 10;
c = systemtime.wHour / 10;
nvrram[4] = d | (c << 4);
d = systemtime.wDayOfWeek % 10;
c = systemtime.wDayOfWeek / 10;
nvrram[6] = d | (c << 4);
d = systemtime.wDay % 10;
c = systemtime.wDay / 10;
nvrram[7] = d | (c << 4);
d = systemtime.wMonth % 10;
c = systemtime.wMonth / 10;
nvrram[8] = d | (c << 4);
d = systemtime.wYear % 10;
c = (systemtime.wYear / 10) % 10;
nvrram[9] = d | (c << 4);
if (baknvr[0] != nvrram[0] ||
baknvr[2] != nvrram[2] ||
baknvr[4] != nvrram[4] ||
baknvr[6] != nvrram[6] ||
baknvr[7] != nvrram[7] ||
baknvr[8] != nvrram[8] ||
baknvr[9] != nvrram[9])
nvrram[0xA]|=0x80;
}

View File

@@ -555,7 +555,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"PCem v11 [Experimental]", /* Title Text */
"PCem v11 [Unofficial]", /* Title Text */
WS_OVERLAPPEDWINDOW&~WS_SIZEBOX, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */

View File

@@ -1,77 +0,0 @@
static int opINT3(uint32_t fetchdat)
{
if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
{
x86gpf(NULL,0);
return 1;
}
x86_int_sw(3);
CLOCK_CYCLES((is486) ? 44 : 59);
return 1;
}
static int opINT(uint32_t fetchdat)
{
uint8_t temp;
/*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);
return 1;
}
temp = getbytef();
// /*if (temp == 0x10 && AH == 0xe) */pclog("INT %02X : %04X %04X %04X %04X %c %04X:%04X\n", temp, AX, BX, CX, DX, (AL < 32) ? ' ' : AL, CS, pc);
// if (CS == 0x0028 && pc == 0xC03813C0)
// output = 3;
/* if (pc == 0x8028009A)
output = 3;
if (pc == 0x80282B6F)
{
__times++;
if (__times == 2)
fatal("WRONG\n");
}
if (pc == 0x802809CE)
fatal("RIGHT\n");*/
// if (CS == 0x0028 && pc == 0x80037FE9)
// output = 3;
//if (CS == 0x9087 && pc == 0x3763)
// fatal("Here\n");
//if (CS==0x9087 && pc == 0x0850)
// output = 1;
/* if (output && pc == 0x80033008)
{
__times++;
if (__times == 2)
fatal("WRONG\n");
}*/
/* if (output && pc == 0x80D8)
{
__times++;
if (__times == 2)
fatal("RIGHT\n");
}*/
x86_int_sw(temp);
return 1;
}
static int opINTO(uint32_t fetchdat)
{
if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
{
x86gpf(NULL,0);
return 1;
}
if (VF_SET())
{
oldpc = pc;
x86_int_sw(4);
return 1;
}
CLOCK_CYCLES(3);
return 0;
}

View File

@@ -1,112 +0,0 @@
static int opIN_AL_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t)getbytef();
check_io_perm(port);
AL = inb(port);
CLOCK_CYCLES(12);
return 0;
}
static int opIN_AX_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t)getbytef();
check_io_perm(port);
check_io_perm(port + 1);
AX = inw(port);
CLOCK_CYCLES(12);
return 0;
}
static int opIN_EAX_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t)getbytef();
check_io_perm(port);
check_io_perm(port + 1);
check_io_perm(port + 2);
check_io_perm(port + 3);
EAX = inl(port);
CLOCK_CYCLES(12);
return 0;
}
static int opOUT_AL_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t)getbytef();
check_io_perm(port);
outb(port, AL);
CLOCK_CYCLES(10);
if (port == 0x64)
return x86_was_reset;
return 0;
}
static int opOUT_AX_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t)getbytef();
check_io_perm(port);
check_io_perm(port + 1);
outw(port, AX);
CLOCK_CYCLES(10);
return 0;
}
static int opOUT_EAX_imm(uint32_t fetchdat)
{
uint16_t port = (uint16_t)getbytef();
check_io_perm(port);
check_io_perm(port + 1);
check_io_perm(port + 2);
check_io_perm(port + 3);
outl(port, EAX);
CLOCK_CYCLES(10);
return 0;
}
static int opIN_AL_DX(uint32_t fetchdat)
{
check_io_perm(DX);
AL = inb(DX);
CLOCK_CYCLES(12);
return 0;
}
static int opIN_AX_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX + 1);
AX = inw(DX);
CLOCK_CYCLES(12);
return 0;
}
static int opIN_EAX_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
EAX = inl(DX);
CLOCK_CYCLES(12);
return 0;
}
static int opOUT_AL_DX(uint32_t fetchdat)
{
check_io_perm(DX);
outb(DX, AL);
CLOCK_CYCLES(11);
return x86_was_reset;
}
static int opOUT_AX_DX(uint32_t fetchdat)
{
//pclog("OUT_AX_DX %04X %04X\n", DX, AX);
check_io_perm(DX);
check_io_perm(DX + 1);
outw(DX, AX);
CLOCK_CYCLES(11);
return 0;
}
static int opOUT_EAX_DX(uint32_t fetchdat)
{
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
outl(DX, EAX);
CLOCK_CYCLES(11);
return 0;
}

View File

@@ -723,6 +723,16 @@ static int opLOADALL386(uint32_t fetchdat)
{
uint32_t la_addr = es + EDI;
if (is486 || israpidcad)
{
cpu_state.pc = oldpc;
// fatal("Illegal instruction %08X\n", fetchdat);
pclog("Illegal instruction %08X\n", fetchdat);
x86illegal();
return 0;
}
cr0 = readmeml(0, la_addr);
flags = readmemw(0, la_addr + 4);
eflags = readmemw(0, la_addr + 6);