Merge branch 'master' of ssh://github.com/OBattler/PCem-Unofficial into port-forward-config
This commit is contained in:
@@ -1,2 +1,7 @@
|
||||
# PCem-Experimental
|
||||
Unofficial experimental branchof the PCem emulator.
|
||||
# PCem Unofficial [](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:
|
||||
|
||||
[](https://kiwiirc.com/client/irc.rol.im/?nick=pcem|?#pcem-x)
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
42
src/cpu.c
42
src/cpu.c
@@ -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*/
|
||||
|
45
src/cpu.h
45
src/cpu.h
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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");
|
||||
}
|
||||
|
@@ -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
|
||||
};
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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
390
src/nvr.c
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
8
src/pc.c
8
src/pc.c
@@ -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);
|
||||
|
31
src/pc.rc
31
src/pc.rc
@@ -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
|
||||
|
@@ -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
261
src/rtc.c
Normal 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
186
src/rtc.h
Normal 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);
|
137
src/vid_cga.c
137
src/vid_cga.c
@@ -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
|
||||
};
|
||||
|
@@ -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;
|
||||
|
@@ -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},
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user