From 35962551dd46621920e8c88d7067086b2ec416fe Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 3 Apr 2019 21:32:48 +0100 Subject: [PATCH] Added emulation of Packard Bell PB410A, along with the built-in Headland HT216-32 video. --- src/Makefile.am | 4 +- src/Makefile.linux32-wx-sdl2 | 4 +- src/Makefile.linux64-wx-sdl2 | 4 +- src/Makefile.mingw-wx-sdl2 | 6 +- src/Makefile.mingw-wx-sdl2-network | 4 +- src/Makefile.osx64-wx-sdl2 | 4 +- src/acc2036.c | 3 + src/acc2168.c | 119 ++++ src/acc2168.h | 1 + src/acc3221.c | 122 ++++ src/acc3221.h | 1 + src/ibm.h | 1 + src/mem_bios.c | 8 + src/model.c | 12 + src/nvr.c | 2 + src/vid_ht216.c | 873 +++++++++++++++++++++++++++++ src/vid_ht216.h | 1 + src/video.c | 22 + 18 files changed, 1178 insertions(+), 13 deletions(-) create mode 100644 src/acc2168.c create mode 100644 src/acc2168.h create mode 100644 src/acc3221.c create mode 100644 src/acc3221.h create mode 100644 src/vid_ht216.c create mode 100644 src/vid_ht216.h diff --git a/src/Makefile.am b/src/Makefile.am index 0aa3d5f..fa29f7d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,7 +23,7 @@ wx-resources.cpp : pc.xrc -wxrc -c pc.xrc -o wx-resources.cpp # PCem -pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ +pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acc2036.c acc2168.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ cmd640.c codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430hx.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ @@ -36,7 +36,7 @@ sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_e t1000.c t3100e.c \ timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \ vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_genius.c vid_hercules.c \ -vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.c vid_oti037.c vid_oti067.c vid_paradise.c vid_pc200.c \ +vid_ht216.c vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.c vid_oti037.c vid_oti067.c vid_paradise.c vid_pc200.c \ vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c vid_sigma.c \ vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_t1000.c vid_t3100e.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \ vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c \ diff --git a/src/Makefile.linux32-wx-sdl2 b/src/Makefile.linux32-wx-sdl2 index 490e946..f7f89dd 100644 --- a/src/Makefile.linux32-wx-sdl2 +++ b/src/Makefile.linux32-wx-sdl2 @@ -4,7 +4,7 @@ CC = gcc WXRC = wxrc CFLAGS = -O3 -fomit-frame-pointer -msse2 -m32 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags) CXXFLAGS = $(CFLAGS) -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \ +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acc2036.o acc2168.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \ cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.c compaq.o config.o cpu.o \ dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ @@ -16,7 +16,7 @@ sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_sb. sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o \ timer.o um8669f.o um8881f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o \ vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_genius.o vid_hercules.o \ -vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \ +vid_ht216.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \ vid_pc1512.o vid_pc1640.o vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o \ vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_t1000.o vid_t3100e.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 vid_wy700.o video.o wd76c10.o \ diff --git a/src/Makefile.linux64-wx-sdl2 b/src/Makefile.linux64-wx-sdl2 index 4a330d6..a900867 100644 --- a/src/Makefile.linux64-wx-sdl2 +++ b/src/Makefile.linux64-wx-sdl2 @@ -4,7 +4,7 @@ CC = gcc WXRC = wxrc CFLAGS = -O3 -fomit-frame-pointer -msse2 -m64 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags) CXXFLAGS = $(CFLAGS) -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \ +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acc2036.o acc2168.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \ cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.c compaq.o config.o cpu.o \ dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ @@ -16,7 +16,7 @@ sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_sb. sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o \ timer.o um8669f.o um8881f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o \ vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_genius.o vid_hercules.o \ -vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \ +vid_ht216.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \ vid_pc1512.o vid_pc1640.o vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o \ vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_t1000.o vid_t3100e.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 vid_wy700.o video.o wd76c10.o \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index eb39856..a308211 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -3,10 +3,10 @@ CPP = g++ CC = gcc WINDRES = windres.exe WXVERSION = 31 -WXINCLUDE = C:/MinGW/include/wx/ +WXINCLUDE = e:/MinGWget/include/wx/ CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing CXXFLAGS = $(CFLAGS) -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl.o cdrom-image.o \ +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acc2168.o acc3221.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl.o cdrom-image.o \ cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o \ device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o \ i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ @@ -17,7 +17,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429 sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o \ - vid_et4000w32.o vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \ + vid_et4000w32.o vid_et4000w32i.o vid_genius.o vid_hercules.o vid_ht216.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \ vid_olivetti_m24.o vid_oti037.c 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_sigma.o vid_stg_ramdac.o vid_svga.o \ vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ diff --git a/src/Makefile.mingw-wx-sdl2-network b/src/Makefile.mingw-wx-sdl2-network index f811df3..b062cc9 100644 --- a/src/Makefile.mingw-wx-sdl2-network +++ b/src/Makefile.mingw-wx-sdl2-network @@ -6,7 +6,7 @@ WXVERSION = 31 WXINCLUDE = e:/mingwget/include/wx/ CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing -DUSE_NETWORKING CXXFLAGS = $(CFLAGS) -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl.o cdrom-image.o \ +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acc2036.o acc2168.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl.o cdrom-image.o \ cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o \ device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o \ i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ @@ -17,7 +17,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429 sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o \ - vid_et4000w32.o vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \ + vid_et4000w32.o vid_et4000w32i.o vid_genius.o vid_hercules.o vid_ht216.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \ vid_olivetti_m24.o vid_oti037.c 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_sigma.o vid_stg_ramdac.o vid_svga.o \ vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ diff --git a/src/Makefile.osx64-wx-sdl2 b/src/Makefile.osx64-wx-sdl2 index a2e0a8e..2a99c06 100644 --- a/src/Makefile.osx64-wx-sdl2 +++ b/src/Makefile.osx64-wx-sdl2 @@ -3,7 +3,7 @@ CPP = g++ CC = gcc WXRC = wxrc CFLAGS = -D__unix=1 -DPCEM_RENDER_WITH_TIMER -DPCEM_RENDER_TIMER_LOOP -Dfopen64=fopen -Dfseeko64=fseeko -Dftello64=ftello -Doff64_t=off_t -O3 -fomit-frame-pointer -msse2 -m64 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags) -I/usr/local/opt/openal-soft/include -I/usr/local/include -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-osx.o cdrom-image.o cdrom-null.o \ +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acc2036.o acc2168.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-osx.o cdrom-image.o cdrom-null.o \ cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.c compaq.o config.o cpu.o \ device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \ hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \ @@ -15,7 +15,7 @@ sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_sb. sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o \ timer.o um8669f.o um8881f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o \ vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_genius.o vid_hercules.o \ -vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \ +vid_ht216.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \ vid_pc1512.o vid_pc1640.o vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o \ vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_t1000.o vid_t3100e.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 vid_wy700.o video.o wd76c10.o \ diff --git a/src/acc2036.c b/src/acc2036.c index bf511fb..faacd9d 100644 --- a/src/acc2036.c +++ b/src/acc2036.c @@ -88,6 +88,9 @@ static uint8_t acc2036_read(uint16_t addr, void *p) { if (!(addr & 1)) return acc2036.reg_idx; + + if (acc2036.reg_idx >= 0xbc) + return 0xff; return acc2036.regs[acc2036.reg_idx]; } diff --git a/src/acc2168.c b/src/acc2168.c new file mode 100644 index 0000000..e6ab7dd --- /dev/null +++ b/src/acc2168.c @@ -0,0 +1,119 @@ +#include "ibm.h" +#include "acc2168.h" +#include "cpu.h" +#include "io.h" +#include "mem.h" +#include "x86.h" + +static struct +{ + int reg_idx; + uint8_t regs[256]; + uint8_t port_62; +} acc2168; + +static void acc2168_shadow_recalc() +{ + if (acc2168.regs[0x02] & 8) + { + switch (acc2168.regs[0x02] & 0x30) + { + case 0x00: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 0x10: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 0x20: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 0x30: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + } + } + else + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + if (acc2168.regs[0x02] & 4) + { + switch (acc2168.regs[0x02] & 0x30) + { + case 0x00: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 0x10: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 0x20: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 0x30: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + } + } + else + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); +} + +static void acc2168_write(uint16_t addr, uint8_t val, void *p) +{ +// pclog("acc2168_write: addr=%04x val=%02x\n", addr, val); + if (!(addr & 1)) + acc2168.reg_idx = val; + else + { + acc2168.regs[acc2168.reg_idx] = val; +// pclog("acc2168_write: idx=%02x val=%02x %04x:%04x\n", acc2168.reg_idx, val, CS,cpu_state.pc); + + switch (acc2168.reg_idx) + { + case 0x02: + acc2168_shadow_recalc(); + break; + } + } +} + +static uint8_t acc2168_read(uint16_t addr, void *p) +{ + if (!(addr & 1)) + return acc2168.reg_idx; + +// pclog("acc2168_read: idx=%02x val=%02x\n", acc2168.reg_idx, acc2168.regs[acc2168.reg_idx]); + return acc2168.regs[acc2168.reg_idx]; +} + +static uint8_t port78_read(uint16_t addr, void *p) +{ + return 0; +} + +static uint8_t port92_read(uint16_t addr, void *p) +{ + return acc2168.port_62 | 0xfc; +} + +static void port92_write(uint16_t addr, uint8_t val, void *p) +{ + if ((mem_a20_alt ^ val) & 2) + { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~acc2168.port_62 & val) & 1) + { + softresetx86(); + cpu_set_edx(); + } + acc2168.port_62 = val | 0xfC; +} + +void acc2168_init() +{ + memset(&acc2168, 0, sizeof(acc2168)); + io_sethandler(0x00f2, 0x0002, acc2168_read, NULL, NULL, acc2168_write, NULL, NULL, NULL); + io_sethandler(0x0078, 0x0001, port78_read, NULL, NULL, NULL, NULL, NULL, NULL); + io_sethandler(0x0092, 0x0001, port92_read, NULL, NULL, port92_write, NULL, NULL, NULL); +} diff --git a/src/acc2168.h b/src/acc2168.h new file mode 100644 index 0000000..93515ee --- /dev/null +++ b/src/acc2168.h @@ -0,0 +1 @@ +void acc2168_init(); diff --git a/src/acc3221.c b/src/acc3221.c new file mode 100644 index 0000000..38c6fa9 --- /dev/null +++ b/src/acc3221.c @@ -0,0 +1,122 @@ +#include "ibm.h" +#include "acc3221.h" +#include "fdc.h" +#include "ide.h" +#include "io.h" +#include "lpt.h" +#include "serial.h" + +static struct +{ + int reg_idx; + uint8_t regs[256]; +} acc3221; + +#define REG_BE_LPT1_DISABLE (1 << 4) + +#define REG_DB_SERIAL1_DISABLE (1 << 4) +#define REG_DB_SERIAL2_DISABLE (1 << 1) + +#define REG_DE_SIRQ3_SOURCE (3 << 6) +#define REG_DE_SIRQ3_SERIAL1 (1 << 6) +#define REG_DE_SIRQ3_SERIAL2 (3 << 6) + +#define REG_DE_SIRQ4_SOURCE (3 << 4) +#define REG_DE_SIRQ4_SERIAL1 (1 << 4) +#define REG_DE_SIRQ4_SERIAL2 (3 << 4) + +#define REG_FB_FDC_DISABLE (1 << 1) + +#define REG_FE_IDE_DISABLE (1 << 1) + +static void acc3221_write(uint16_t addr, uint8_t val, void *p) +{ + if (!(addr & 1)) + acc3221.reg_idx = val; + else + { + acc3221.regs[acc3221.reg_idx] = val; +// pclog("Write ACC2036 R%02x %02x %04x:%04x %i\n", acc2036.reg_idx, val, CS,cpu_state.pc, ins); + + if (acc3221.reg_idx >= 0xbc) + { +// pclog("Write ACC3221 R%02x %02x %04x:%04x %i\n", acc3221.reg_idx, val, CS,cpu_state.pc, ins); + fdc_remove(); + if (!(acc3221.regs[0xfb] & REG_FB_FDC_DISABLE)) + fdc_add(); + + serial1_remove(); + if (!(acc3221.regs[0xdb] & REG_DB_SERIAL1_DISABLE)) + { + uint16_t addr = (acc3221.regs[0xdc] & 0x7f) << 2; + + if ((acc3221.regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL1) + { +// pclog("COM1 addr %03x IRQ 3\n", addr); + serial1_set(addr, 3); + } + else if ((acc3221.regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ3_SERIAL1) + { +// pclog("COM1 addr %03x IRQ 4\n", addr); + serial1_set(addr, 4); + } +// else +// pclog("COM1 addr %03x no IRQ\n", addr); + } +// else +// pclog("COM1 disabled\n"); + + serial2_remove(); + if (!(acc3221.regs[0xdb] & REG_DB_SERIAL2_DISABLE)) + { + uint16_t addr = (acc3221.regs[0xdd] & 0x7f) << 2; + + if ((acc3221.regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL2) + { +// pclog("COM2 addr %03x IRQ 3\n", addr); + serial2_set(addr, 3); + } + else if ((acc3221.regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ3_SERIAL2) + { +// pclog("COM2 addr %03x IRQ 4\n", addr); + serial2_set(addr, 4); + } +// else +// pclog("COM2 addr %03x no IRQ\n", addr); + } +// else +// pclog("COM2 disabled\n"); + + lpt1_remove(); + lpt2_remove(); + if (!(acc3221.regs[0xbe] & REG_BE_LPT1_DISABLE)) + { +// pclog("LPT1 addr %03x\n", acc3221.regs[0xbf] << 2); + lpt1_init(acc3221.regs[0xbf] << 2); + } +// else +// pclog("LPT1 disabled\n"); + + ide_pri_disable(); + if (!(acc3221.regs[0xfe] & REG_FE_IDE_DISABLE)) + ide_pri_enable(); + } + } +} + +static uint8_t acc3221_read(uint16_t addr, void *p) +{ + if (!(addr & 1)) + return acc3221.reg_idx; + + if (acc3221.reg_idx < 0xbc) + return 0xff; + + return acc3221.regs[acc3221.reg_idx]; +} + +void acc3221_init() +{ + memset(&acc3221, 0, sizeof(acc3221)); + io_sethandler(0x00f2, 0x0002, acc3221_read, NULL, NULL, acc3221_write, NULL, NULL, NULL); +} diff --git a/src/acc3221.h b/src/acc3221.h new file mode 100644 index 0000000..95824ec --- /dev/null +++ b/src/acc3221.h @@ -0,0 +1 @@ +void acc3221_init(); diff --git a/src/ibm.h b/src/ibm.h index 702d93e..e7dca29 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -467,6 +467,7 @@ enum ROM_IBMPS2_M70_TYPE4, ROM_TULIP_TC7, ROM_ZD_SUPERS, /* [8088] Zenith Data Systems SupersPort */ + ROM_PB410A, ROM_MAX }; diff --git a/src/mem_bios.c b/src/mem_bios.c index 143490c..c49271e 100644 --- a/src/mem_bios.c +++ b/src/mem_bios.c @@ -965,6 +965,14 @@ int loadbios() fclose(f); biosmask = 0x7fff; return 1; + + case ROM_PB410A: + f = romfopen("pb410a/PB410A.080337.4ABF.U25.bin","rb"); + if (!f) break; + romfread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); diff --git a/src/model.c b/src/model.c index 2c898b4..fa7599c 100644 --- a/src/model.c +++ b/src/model.c @@ -5,6 +5,8 @@ #include "mouse.h" #include "acc2036.h" +#include "acc2168.h" +#include "acc3221.h" #include "acer386sx.h" #include "ali1429.h" #include "amstrad.h" @@ -107,6 +109,7 @@ void xt_t1000_init(); void xt_t1200_init(); void at_sl82c460_init(); void at_zappa_init(); +void at_pb410a_init(); void at_pb520r_init(); void at_pb570_init(); void compaq_pip_init(); @@ -189,6 +192,7 @@ MODEL models[] = {"[486] Award SiS 496/497", ROM_SIS496, "sis496", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_HAS_IDE, 1, 256, 1, at_sis496_init, NULL}, {"[486] Elonex PC-425X", ROM_ELX_PC425X, "elx_pc425x", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_sl82c460_init, NULL}, {"[486] IBM PS/2 Model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibmps2_m70_type4", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL}, + {"[486] Packard Bell PB410A", ROM_PB410A, "pb410a", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 64, 1, at_pb410a_init, NULL}, {"[Socket 4] Intel Premiere/PCI", ROM_REVENGE, "revenge", { {"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_batman_init, NULL}, {"[Socket 4] Packard Bell PB520R",ROM_PB520R, "pb520r", { {"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_pb520r_init, NULL}, @@ -591,6 +595,14 @@ void pb_l300sx_init() acc2036_init(); } +void at_pb410a_init() +{ + at_init(); + acc2168_init(); + acc3221_init(); +} + + void at_sis496_init() { at_init(); diff --git a/src/nvr.c b/src/nvr.c index 2585544..4857825 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -314,6 +314,7 @@ void loadnvr() case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","rb"); break; case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","rb"); break; case ROM_TULIP_TC7: f = nvrfopen("tulip_tc7.nvr", "rb"); break; + case ROM_PB410A: f = nvrfopen("pb410a.nvr", "rb"); nvrmask = 127; break; default: return; } @@ -410,6 +411,7 @@ void savenvr() case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","wb"); break; case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","wb"); break; case ROM_TULIP_TC7: f = nvrfopen("tulip_tc7.nvr", "wb"); break; + case ROM_PB410A: f = nvrfopen("pb410a.nvr", "wb"); break; default: return; } diff --git a/src/vid_ht216.c b/src/vid_ht216.c new file mode 100644 index 0000000..16db980 --- /dev/null +++ b/src/vid_ht216.c @@ -0,0 +1,873 @@ +#include +#include "ibm.h" +#include "device.h" +#include "io.h" +#include "mem.h" +#include "rom.h" +#include "video.h" +#include "vid_ht216.h" +#include "vid_svga.h" +#include "vid_svga_render.h" +#include "vid_unk_ramdac.h" + +typedef struct ht216_t +{ + svga_t svga; + + mem_mapping_t linear_mapping; + + rom_t bios_rom; + + uint32_t vram_mask; + + int ext_reg_enable; + int clk_sel; + + uint8_t read_bank_reg[2], write_bank_reg[2]; + uint32_t read_bank[2], write_bank[2]; + uint8_t misc; + + uint8_t bg_latch[8]; + + uint8_t ht_regs[256]; +} ht216_t; + +#define HT_MISC_PAGE_SEL (1 << 5) + +/*Shifts CPU VRAM read address by 3 bits, for use with fat pixel colour expansion*/ +#define HT_REG_C8_MOVSB (1 << 0) +#define HT_REG_C8_E256 (1 << 4) +#define HT_REG_C8_XLAM (1 << 6) + +#define HT_REG_CD_FP8PCEXP (1 << 1) +#define HT_REG_CD_BMSKSL (3 << 2) +#define HT_REG_CD_RMWMDE (1 << 5) +/*Use GDC data rotate as offset when reading VRAM data into latches*/ +#define HT_REG_CD_ASTODE (1 << 6) +#define HT_REG_CD_EXALU (1 << 7) + +#define HT_REG_E0_SBAE (1 << 7) + +#define HT_REG_F9_XPSEL (1 << 0) + +/*Enables A[14:15] of VRAM address in chain-4 modes*/ +#define HT_REG_FC_ECOLRE (1 << 2) + +#define HT_REG_FE_FBRC (1 << 1) +#define HT_REG_FE_FBMC (3 << 2) +#define HT_REG_FE_FBRSL (3 << 4) + +void ht216_remap(ht216_t *ht216); + +void ht216_out(uint16_t addr, uint8_t val, void *p); +uint8_t ht216_in(uint16_t addr, void *p); + +void ht216_out(uint16_t addr, uint8_t val, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + uint8_t old; + +// pclog("ht216 %i out %04X %02X %04X:%04X\n", svga->miscout & 1, addr, val, CS, cpu_state.pc); + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) + { + case 0x3c2: + ht216->clk_sel = (ht216->clk_sel & ~3) | ((val & 0x0c) >> 2); + ht216->misc = val; + ht216_remap(ht216); + svga_recalctimings(&ht216->svga); + break; + + case 0x3c5: + if (svga->seqaddr == 4) + { + svga->chain4 = val & 8; + ht216_remap(ht216); + } + else if (svga->seqaddr == 6) + { + if (val == 0xea) + ht216->ext_reg_enable = 1; + else if (val == 0xae) + ht216->ext_reg_enable = 0; + } + else if (svga->seqaddr >= 0x80 && ht216->ext_reg_enable) + { + ht216->ht_regs[svga->seqaddr & 0xff] = val; +// pclog("HT[%02x]=%02x %04x(%08x):%08x\n", svga->seqaddr, val, CS,cs,cpu_state.pc); + switch (svga->seqaddr & 0xff) + { + case 0x83: + svga->attraddr = val & 0x1f; + svga->attrff = (val & 0x80) ? 1 : 0; + break; + + case 0x94: + svga->hwcursor.addr = ((val << 6) | (3 << 14) | ((ht216->ht_regs[0xff] & 0x60) << 11)) << 2; + //pclog("cursor_addr = %05x\n", svga->hwcursor.addr); + break; + case 0x9c: case 0x9d: + svga->hwcursor.x = ht216->ht_regs[0x9d] | ((ht216->ht_regs[0x9c] & 7) << 8); + break; + case 0x9e: case 0x9f: + svga->hwcursor.y = ht216->ht_regs[0x9f] | ((ht216->ht_regs[0x9e] & 3) << 8); + break; + case 0xa0: + svga->la = val; + break; + case 0xa1: + svga->lb = val; + break; + case 0xa2: + svga->lc = val; + break; + case 0xa3: + svga->ld = val; + break; + case 0xa4: + ht216->clk_sel = (val >> 2) & 0xf; + svga->miscout = (svga->miscout & ~0xc) | ((ht216->clk_sel & 3) << 2); + break; + case 0xa5: + svga->hwcursor.ena = val & 0x80; + break; + case 0xe8: + ht216->read_bank_reg[0] = val; + ht216->write_bank_reg[0] = val; + break; + case 0xe9: + ht216->read_bank_reg[1] = val; + ht216->write_bank_reg[1] = val; + break; + case 0xf6: + svga->vram_display_mask = (val & 0x40) ? ht216->vram_mask : 0x3ffff; + break; + case 0xff: + svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | (3 << 14) | ((val & 0x60) << 11)) << 2; + //pclog("cursor_addr = %05x\n", svga->hwcursor.addr); + break; + } + switch (svga->seqaddr & 0xff) + { + case 0xa4: case 0xf6: case 0xfc: + svga->fullchange = changeframecount; + svga_recalctimings(&ht216->svga); + break; + } + switch (svga->seqaddr & 0xff) + { + case 0xc8: case 0xc9: case 0xcf: + case 0xe0: case 0xe8: case 0xe9: + case 0xf6: case 0xf9: + ht216_remap(ht216); + break; + } + return; + } + break; + + case 0x3cf: + if (svga->gdcaddr == 6) + { + if (val & 8) + svga->banked_mask = 0x7fff; + else + svga->banked_mask = 0xffff; + } + break; + + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + +// if (svga->crtcreg == 0xc) +// pclog("CRTC[C]=%02x %08x\n", val, svga->vram_display_mask); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + + if (old != val) + { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(&ht216->svga); + } + } + break; + + case 0x46e8: + io_removehandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); + mem_mapping_disable(&ht216->svga.mapping); + mem_mapping_disable(&ht216->linear_mapping); + if (val & 8) + { + io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); + mem_mapping_enable(&ht216->svga.mapping); + ht216_remap(ht216); + } + break; + } + svga_out(addr, val, svga); +} + +uint8_t ht216_in(uint16_t addr, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + +// if (addr != 0x3ba && addr != 0x3da) pclog("ht216 %i in %04X\n", svga->miscout & 1, addr); + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) + { + case 0x3c2: +// pclog("3C2 read\n"); + break; +// return 0x10; + + case 0x3c5: + if (svga->seqaddr == 6) + return ht216->ext_reg_enable; + if (svga->seqaddr >= 0x80) + { + if (ht216->ext_reg_enable) + { +// pclog("Read HT[%02x]=%02x\n", svga->seqaddr & 0xff, ht216->ht_regs[svga->seqaddr & 0xff]); + switch (svga->seqaddr & 0xff) + { + case 0x83: + if (svga->attrff) + return svga->attraddr | 0x80; + return svga->attraddr; + + case 0x8e: return 0x61; /*HT216-32*/ + case 0x8f: return 0x78; + + case 0xa0: + return svga->la; + case 0xa1: + return svga->lb; + case 0xa2: + return svga->lc; + case 0xa3: + return svga->ld; + } + return ht216->ht_regs[svga->seqaddr & 0xff]; + } + else + return 0xff; + } + break; + + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + if (svga->crtcreg == 0x1f) + return svga->crtc[0xc] ^ 0xea; + return svga->crtc[svga->crtcreg]; + } + return svga_in(addr, svga); +} + +void ht216_remap(ht216_t *ht216) +{ + svga_t *svga = &ht216->svga; + + mem_mapping_disable(&ht216->linear_mapping); + if (ht216->ht_regs[0xc8] & HT_REG_C8_XLAM) + { + uint32_t linear_base = ((ht216->ht_regs[0xc9] & 0xf) << 20) | (ht216->ht_regs[0xcf] << 24); + + pclog("Linear base %08x\n", linear_base); + mem_mapping_set_addr(&ht216->linear_mapping, linear_base, 0x100000); + + /*Linear mapping enabled*/ + } + else + { + uint32_t read_offset = (ht216->ht_regs[0xf6] & 0xc) << 16; + uint32_t write_offset = (ht216->ht_regs[0xf6] & 0x3) << 18; + + if (svga->chain4 && (ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) + { + if (ht216->misc & HT_MISC_PAGE_SEL) + { + read_offset |= (1 << 17); + write_offset |= (1 << 17); + } + if (ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL) + { + read_offset |= (1 << 16); + write_offset |= (1 << 16); + } + } + ht216->read_bank[0] = read_offset + (ht216->read_bank_reg[0] << 12); + ht216->write_bank[0] = write_offset + (ht216->write_bank_reg[0] << 12); + if (ht216->ht_regs[0xe0] & HT_REG_E0_SBAE) + { + /*Split bank*/ + ht216->read_bank[1] = read_offset + (ht216->read_bank_reg[1] << 12); + ht216->write_bank[1] = write_offset + (ht216->write_bank_reg[1] << 12); + } + else + { + ht216->read_bank[1] = ht216->read_bank[0] + (svga->chain4 ? 0x8000 : 0x20000); + ht216->write_bank[1] = ht216->write_bank[0] + (svga->chain4 ? 0x8000 : 0x20000); + } + + if (!svga->chain4) + { + ht216->read_bank[0] >>= 2; + ht216->read_bank[1] >>= 2; + ht216->write_bank[0] >>= 2; + ht216->write_bank[1] >>= 2; + } + } +// pclog("Remap - chain4=%i gdc[6]=%02x read[0]=%05X write[0]=%05X read[1]=%05X write[1]=%05X\n", svga->chain4, svga->gdcreg[6], ht216->read_bank[0], ht216->write_bank[0], ht216->read_bank[1], ht216->write_bank[1]); +} + +void ht216_recalctimings(svga_t *svga) +{ + ht216_t *ht216 = (ht216_t *)svga->p; + +// pclog("clk_sel = %i\n", ht216->clk_sel); + switch (ht216->clk_sel) + { + case 5: svga->clock = cpuclock / 65000000.0; break; + case 6: svga->clock = cpuclock / 40000000.0; break; + case 10: svga->clock = cpuclock / 80000000.0; break; + } + svga->lowres = !(ht216->ht_regs[0xc8] & HT_REG_C8_E256); + svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12); + svga->interlace = ht216->ht_regs[0xe0] & 1; + + if (svga->bpp == 8 && !svga->lowres) + svga->render = svga_render_8bpp_highres; +} + +static void ht216_hwcursor_draw(svga_t *svga, int displine) +{ +// ht216_t *ht216 = (ht216_t *)svga->p; + int x; + uint32_t dat[2]; + int offset = svga->hwcursor_latch.x + 32; + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 4; + + dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | + (svga->vram[svga->hwcursor_latch.addr+1] << 16) | + (svga->vram[svga->hwcursor_latch.addr+2] << 8) | + svga->vram[svga->hwcursor_latch.addr+3]; + dat[1] = (svga->vram[svga->hwcursor_latch.addr+128] << 24) | + (svga->vram[svga->hwcursor_latch.addr+128+1] << 16) | + (svga->vram[svga->hwcursor_latch.addr+128+2] << 8) | + svga->vram[svga->hwcursor_latch.addr+128+3]; + + for (x = 0; x < 32; x++) + { + if (!(dat[0] & 0x80000000)) + ((uint32_t *)buffer32->line[displine])[offset + x] = 0; + if (dat[1] & 0x80000000) + ((uint32_t *)buffer32->line[displine])[offset + x] ^= 0xffffff; + + dat[0] <<= 1; + dat[1] <<= 1; + } + + svga->hwcursor_latch.addr += 4; + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 4; +} + +static inline uint8_t extalu(int op, uint8_t input_a, uint8_t input_b) +{ + uint8_t val; + + switch (op) + { + case 0x0: val = 0; break; + case 0x1: val = ~(input_a | input_b); break; + case 0x2: val = input_a & ~input_b; break; + case 0x3: val = ~input_b; break; + case 0x4: val = ~input_a & input_b; break; + case 0x5: val = ~input_a; break; + case 0x6: val = input_a ^ input_b; break; + case 0x7: val = ~(input_a & input_b); break; + case 0x8: val = input_a & input_b; break; + case 0x9: val = ~(input_a ^ input_b); break; + case 0xa: val = input_a; break; + case 0xb: val = input_a | ~input_b; break; + case 0xc: val = input_b; break; + case 0xd: val = ~input_a | input_b; break; + case 0xe: val = input_a | input_b; break; + case 0xf: default: val = 0xff; break; + } + + return val; +} + +static void ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bit_mask, uint8_t cpu_dat_unexpanded, uint8_t rop_select) +{ + /*Input B = CD.5 + Input A = FE[3:2] + 00 = Set/Reset output mode + output = CPU-side ALU input + 01 = Solid fg/bg mode (3C4:FA/FB) + Bit mask = 3CF.F5 or CPU byte + 10 = Dithered fg (3CF:EC-EF) + 11 = RMW (dest data) (set if CD.5 = 1) + F/B ROP select = FE[5:4] + 00 = CPU byte + 01 = Bit mask (3CF:8) + 1x = (3C4:F5)*/ + svga_t *svga = &ht216->svga; + uint8_t input_a = 0, input_b = 0; + uint8_t fg, bg; + uint8_t output; + + if (ht216->ht_regs[0xcd] & HT_REG_CD_RMWMDE) /*RMW*/ + input_b = svga->vram[addr]; + else + input_b = ht216->bg_latch[addr & 7]; + + switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBMC) + { + case 0x00: + input_a = cpu_dat; + break; + case 0x04: + if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC) + input_a = (cpu_dat_unexpanded & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + else + input_a = (ht216->ht_regs[0xf5] & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + break; + case 0x08: + input_a = ht216->ht_regs[0xec + (addr & 3)]; + break; + case 0x0c: + input_a = ht216->bg_latch[addr & 7]; + break; + } + + fg = extalu(ht216->ht_regs[0xce] >> 4, input_a, input_b); + bg = extalu(ht216->ht_regs[0xce] & 0xf, input_a, input_b); +// svga->vram[addr] + output = (fg & rop_select) | (bg & ~rop_select); + svga->vram[addr] = (svga->vram[addr] & ~bit_mask) | (output & bit_mask); +// pclog(" A=%02x B=%02x R=%02x FG=%02x BG=%02x ops=%02x val=%02x addr=%05x\n", input_a, input_b, rop_select, fg, bg, ht216->ht_regs[0xce], svga->vram[addr], addr); + svga->changedvram[addr >> 12] = changeframecount; +} + +static void ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) +{ + /*Input B = CD.5 + Input A = FE[3:2] + 00 = Set/Reset output mode + output = CPU-side ALU input + 01 = Solid fg/bg mode (3C4:FA/FB) + Bit mask = 3CF.F5 or CPU byte + 10 = Dithered fg (3CF:EC-EF) + 11 = RMW (dest data) (set if CD.5 = 1) + F/B ROP select = FE[5:4] + 00 = CPU byte + 01 = Bit mask (3CF:8) + 1x = (3C4:F5) + */ + uint8_t bit_mask = 0, rop_select = 0; + svga_t *svga = &ht216->svga; + + addr &= 0xfffff; + +// pclog("%08X %02x %08x\n", addr, svga->gdcreg[6], svga->banked_mask); + + val = svga_rotate[svga->gdcreg[3] & 7][val]; + + switch (ht216->ht_regs[0xcd] & HT_REG_CD_BMSKSL) + { + case 0x00: + bit_mask = svga->gdcreg[8]; + break; + case 0x04: + bit_mask = val; + break; + case 0x08: case 0x0c: + bit_mask = ht216->ht_regs[0xf5]; + break; + } + switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBRSL) + { + case 0x00: + rop_select = val; + break; + case 0x10: + rop_select = svga->gdcreg[8]; + break; + case 0x20: case 0x30: + rop_select = ht216->ht_regs[0xf5]; + break; + } + + if (ht216->ht_regs[0xcd] & HT_REG_CD_EXALU) /*Extended ALU*/ + { + if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) /*1->8 bit expansion*/ + { + addr = (addr << 3) & 0xfffff; + ht216_dm_extalu_write(ht216, addr, (val & 0x80) ? 0xff : 0, (bit_mask & 0x80) ? 0xff : 0, val, (rop_select & 0x80) ? 0xff : 0); + ht216_dm_extalu_write(ht216, addr + 1, (val & 0x40) ? 0xff : 0, (bit_mask & 0x40) ? 0xff : 0, val, (rop_select & 0x40) ? 0xff : 0); + ht216_dm_extalu_write(ht216, addr + 2, (val & 0x20) ? 0xff : 0, (bit_mask & 0x20) ? 0xff : 0, val, (rop_select & 0x20) ? 0xff : 0); + ht216_dm_extalu_write(ht216, addr + 3, (val & 0x10) ? 0xff : 0, (bit_mask & 0x10) ? 0xff : 0, val, (rop_select & 0x10) ? 0xff : 0); + ht216_dm_extalu_write(ht216, addr + 4, (val & 0x08) ? 0xff : 0, (bit_mask & 0x08) ? 0xff : 0, val, (rop_select & 0x08) ? 0xff : 0); + ht216_dm_extalu_write(ht216, addr + 5, (val & 0x04) ? 0xff : 0, (bit_mask & 0x04) ? 0xff : 0, val, (rop_select & 0x04) ? 0xff : 0); + ht216_dm_extalu_write(ht216, addr + 6, (val & 0x02) ? 0xff : 0, (bit_mask & 0x02) ? 0xff : 0, val, (rop_select & 0x02) ? 0xff : 0); + ht216_dm_extalu_write(ht216, addr + 7, (val & 0x01) ? 0xff : 0, (bit_mask & 0x01) ? 0xff : 0, val, (rop_select & 0x01) ? 0xff : 0); + } + else + ht216_dm_extalu_write(ht216, addr, val, bit_mask, val, rop_select); + } +} + +static void ht216_write(uint32_t addr, uint8_t val, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + +/* if (ht216->ht_regs[0xcd]) + pclog("ht216_write: [CD]=%02x [FE]=%02x %08x %02x ", ht216->ht_regs[0xcd], ht216->ht_regs[0xfe], addr, val); + pclog("ht216_write : %05X %02X ", addr, val);*/ + addr &= svga->banked_mask; + addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; +// pclog("phys_addr=%05x\n", addr); + if (!ht216->ht_regs[0xcd]) + svga_write_linear(addr, val, &ht216->svga); + else + ht216_write_common(ht216, addr, val); +} +static void ht216_writew(uint32_t addr, uint16_t val, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + + addr &= svga->banked_mask; + addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; + if (!ht216->ht_regs[0xcd]) + svga_writew_linear(addr, val, &ht216->svga); + else + { + ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr+1, val >> 8); + } +} +static void ht216_writel(uint32_t addr, uint32_t val, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + + addr &= svga->banked_mask; + addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; + if (!ht216->ht_regs[0xcd]) + svga_writel_linear(addr, val, &ht216->svga); + else + { + ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr+1, val >> 8); + ht216_write_common(ht216, addr+2, val >> 16); + ht216_write_common(ht216, addr+3, val >> 24); + } +} + +static void ht216_write_linear(uint32_t addr, uint8_t val, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + + if (!svga->chain4) /*Bits 16 and 17 of linear address seem to be unused in planar modes*/ + addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); + + if (!ht216->ht_regs[0xcd]) + svga_write_linear(addr, val, &ht216->svga); + else + ht216_write_common(ht216, addr, val); +} +static void ht216_writew_linear(uint32_t addr, uint16_t val, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + + if (!svga->chain4) + addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); + + if (!ht216->ht_regs[0xcd]) + svga_writew_linear(addr, val, &ht216->svga); + else + { + ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr+1, val >> 8); + } +} +static void ht216_writel_linear(uint32_t addr, uint32_t val, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + + if (!svga->chain4) + addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); + + if (!ht216->ht_regs[0xcd]) + svga_writel_linear(addr, val, &ht216->svga); + else + { + ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr+1, val >> 8); + ht216_write_common(ht216, addr+2, val >> 16); + ht216_write_common(ht216, addr+3, val >> 24); + } +} + +static uint8_t ht216_read_common(ht216_t *ht216, uint32_t addr) +{ + svga_t *svga = &ht216->svga; + uint8_t temp, temp2, temp3, temp4; + int readplane = svga->readplane; + uint32_t latch_addr; + + if (ht216->ht_regs[0xc8] & HT_REG_C8_MOVSB) + addr <<= 3; +// pclog("%08X\n", addr); + + addr &= 0xfffff; + + cycles -= video_timing_read_b; + cycles_lost += video_timing_read_b; + + egareads++; + + if (svga->chain4 || svga->fb_only) + { +// if (ht216->ht_regs[0xcd]) +// pclog(" addr=%08x decode_mask=%08x vram_max=%08x\n", addr, svga->decode_mask, svga->vram_max); + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + + latch_addr = (addr & svga->vram_mask) & ~7; + if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) + latch_addr += (svga->gdcreg[3] & 7); + ht216->bg_latch[0] = svga->vram[latch_addr]; + ht216->bg_latch[1] = svga->vram[latch_addr + 1]; + ht216->bg_latch[2] = svga->vram[latch_addr + 2]; + ht216->bg_latch[3] = svga->vram[latch_addr + 3]; + ht216->bg_latch[4] = svga->vram[latch_addr + 4]; + ht216->bg_latch[5] = svga->vram[latch_addr + 5]; + ht216->bg_latch[6] = svga->vram[latch_addr + 6]; + ht216->bg_latch[7] = svga->vram[latch_addr + 7]; + +/*pclog(" Read %08x %02x %02x %02x %02x %02x %02x %02x %02x\n", addr, + ht216->bg_latch[0],ht216->bg_latch[1],ht216->bg_latch[2],ht216->bg_latch[3], + ht216->bg_latch[4],ht216->bg_latch[5],ht216->bg_latch[6],ht216->bg_latch[7]);*/ + + return svga->vram[addr & svga->vram_mask]; + } + else if (svga->chain2_read) + { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + addr <<= 2; + } + else + addr<<=2; + + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) + return 0xff; + + addr &= svga->vram_mask; + + latch_addr = addr & ~7; + if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) + { + int offset = addr & 7; + + ht216->bg_latch[0] = svga->vram[latch_addr | offset]; + ht216->bg_latch[1] = svga->vram[latch_addr | ((offset + 1) & 7)]; + ht216->bg_latch[2] = svga->vram[latch_addr | ((offset + 2) & 7)]; + ht216->bg_latch[3] = svga->vram[latch_addr | ((offset + 3) & 7)]; + ht216->bg_latch[4] = svga->vram[latch_addr | ((offset + 4) & 7)]; + ht216->bg_latch[5] = svga->vram[latch_addr | ((offset + 5) & 7)]; + ht216->bg_latch[6] = svga->vram[latch_addr | ((offset + 6) & 7)]; + ht216->bg_latch[7] = svga->vram[latch_addr | ((offset + 7) & 7)]; + } + else + { + ht216->bg_latch[0] = svga->vram[latch_addr]; + ht216->bg_latch[1] = svga->vram[latch_addr | 1]; + ht216->bg_latch[2] = svga->vram[latch_addr | 2]; + ht216->bg_latch[3] = svga->vram[latch_addr | 3]; + ht216->bg_latch[4] = svga->vram[latch_addr | 4]; + ht216->bg_latch[5] = svga->vram[latch_addr | 5]; + ht216->bg_latch[6] = svga->vram[latch_addr | 6]; + ht216->bg_latch[7] = svga->vram[latch_addr | 7]; + } +/*pclog(" Read %02x %02x %02x %02x %02x %02x %02x %02x\n", + ht216->bg_latch[0],ht216->bg_latch[1],ht216->bg_latch[2],ht216->bg_latch[3], + ht216->bg_latch[4],ht216->bg_latch[5],ht216->bg_latch[6],ht216->bg_latch[7]);*/ + if (addr & 4) + { + svga->la = ht216->bg_latch[4]; + svga->lb = ht216->bg_latch[5]; + svga->lc = ht216->bg_latch[6]; + svga->ld = ht216->bg_latch[7]; + } + else + { + svga->la = ht216->bg_latch[0]; + svga->lb = ht216->bg_latch[1]; + svga->lc = ht216->bg_latch[2]; + svga->ld = ht216->bg_latch[3]; + } + if (svga->readmode) + { + temp = svga->la; + temp ^= (svga->colourcompare & 1) ? 0xff : 0; + temp &= (svga->colournocare & 1) ? 0xff : 0; + temp2 = svga->lb; + temp2 ^= (svga->colourcompare & 2) ? 0xff : 0; + temp2 &= (svga->colournocare & 2) ? 0xff : 0; + temp3 = svga->lc; + temp3 ^= (svga->colourcompare & 4) ? 0xff : 0; + temp3 &= (svga->colournocare & 4) ? 0xff : 0; + temp4 = svga->ld; + temp4 ^= (svga->colourcompare & 8) ? 0xff : 0; + temp4 &= (svga->colournocare & 8) ? 0xff : 0; + return ~(temp | temp2 | temp3 | temp4); + } +//printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane); + return svga->vram[addr | readplane]; + +// return svga_read_linear(addr, &ht216->svga); +} +static uint8_t ht216_read(uint32_t addr, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + +// if (ht216->ht_regs[0xcd]) +// pclog("ht216_read: [CD]=%02x [FC]=%02x %08x\n", ht216->ht_regs[0xcd], ht216->ht_regs[0xfc], addr); +// pclog("ht216_read : %05X ", addr); + addr &= svga->banked_mask; + addr = (addr & 0x7fff) + ht216->read_bank[(addr >> 15) & 1]; + + return ht216_read_common(ht216, addr); +} + +/*static uint16_t ht216_readw(uint32_t addr, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + + addr &= svga->banked_mask; + addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; + return svga_readw_linear(addr, &ht216->svga); +}*/ + +static uint8_t ht216_read_linear(uint32_t addr, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + svga_t *svga = &ht216->svga; + + if (svga->chain4) + return ht216_read_common(ht216, addr); + else + return ht216_read_common(ht216, (addr & 0xffff) | ((addr & 0xc0000) >> 2)); +} + +void *ht216_init() +{ + ht216_t *ht216 = malloc(sizeof(ht216_t)); + svga_t *svga = &ht216->svga; + memset(ht216, 0, sizeof(ht216_t)); + + io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); + io_sethandler(0x46e8, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); + + svga_init(&ht216->svga, ht216, 1 << 20, /*1MB*/ + ht216_recalctimings, + ht216_in, ht216_out, + ht216_hwcursor_draw, + NULL); + svga->hwcursor.ysize = 32; + ht216->vram_mask = 0xfffff; + svga->decode_mask = 0xfffff; + + mem_mapping_set_handler(&ht216->svga.mapping, ht216_read, NULL/*ht216_readw*/, NULL, ht216_write, ht216_writew, ht216_writel); + mem_mapping_set_p(&ht216->svga.mapping, ht216); + mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, 0, &ht216->svga); + + svga->bpp = 8; + svga->miscout = 1; + + ht216->ht_regs[0xb4] = 0x08; /*32-bit DRAM bus*/ + + return ht216; +} + +static void *ht216_pb410a_init() +{ + ht216_t *ht216 = ht216_init(); + + return ht216; +} + +void ht216_close(void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + + svga_close(&ht216->svga); + + free(ht216); +} + +void ht216_speed_changed(void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + + svga_recalctimings(&ht216->svga); +} + +void ht216_force_redraw(void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + + ht216->svga.fullchange = changeframecount; +} + +void ht216_add_status_info(char *s, int max_len, void *p) +{ + ht216_t *ht216 = (ht216_t *)p; + + svga_add_status_info(s, max_len, &ht216->svga); +} + +device_t ht216_32_pb410a_device = +{ + "Headland HT216-32 (Packard Bell PB410A)", + 0, + ht216_pb410a_init, + ht216_close, + NULL, + ht216_speed_changed, + ht216_force_redraw, + ht216_add_status_info +}; diff --git a/src/vid_ht216.h b/src/vid_ht216.h new file mode 100644 index 0000000..c5e7b3a --- /dev/null +++ b/src/vid_ht216.h @@ -0,0 +1 @@ +extern device_t ht216_32_pb410a_device; diff --git a/src/video.c b/src/video.c index dfe8e68..b0c8039 100644 --- a/src/video.c +++ b/src/video.c @@ -23,6 +23,7 @@ #include "vid_et4000w32.h" #include "vid_genius.h" #include "vid_hercules.h" +#include "vid_ht216.h" #include "vid_incolor.h" #include "vid_colorplus.h" #include "vid_mda.h" @@ -128,6 +129,7 @@ static video_timings_t timing_ps1_svga = {VIDEO_ISA, 6, 8,16, 6, 8,16}; static video_timings_t timing_t3100e = {VIDEO_ISA, 8,16,32, 8,16,32}; static video_timings_t timing_t1000 = {VIDEO_ISA, 8,16,32, 8,16,32}; static video_timings_t timing_pc425x = {VIDEO_BUS, 5, 5, 9, 20,20,30}; +static video_timings_t timing_pb410a = {VIDEO_BUS, 5, 5, 9, 20,20,30}; static video_timings_t timing_pb570 = {VIDEO_BUS, 4, 4, 8, 10,10,20}; static video_timings_t timing_pb520r = {VIDEO_BUS, 4, 4, 8, 10,10,20}; @@ -220,6 +222,9 @@ device_t *video_card_getdevice(int card) case ROM_ELX_PC425X: return &tgui9400cxi_elx_device; + case ROM_PB410A: + return &ht216_32_pb410a_device; + case ROM_PB570: return &gd5430_pb570_device; @@ -332,6 +337,7 @@ int video_is_mda() case ROM_T3100E: case ROM_T1000: case ROM_ELX_PC425X: + case ROM_PB410A: case ROM_PB570: case ROM_PB520R: return 0; @@ -371,6 +377,7 @@ int video_is_cga() case ROM_IBMPS2_M80: case ROM_IBMPS1_2121: case ROM_ELX_PC425X: + case ROM_PB410A: case ROM_PB570: case ROM_PB520R: return 0; @@ -407,6 +414,7 @@ int video_is_ega_vga() case ROM_IBMPS2_M80: case ROM_IBMPS1_2121: case ROM_ELX_PC425X: + case ROM_PB410A: case ROM_PB570: case ROM_PB520R: return 1; @@ -561,6 +569,11 @@ void video_updatetiming() timing = &timing_pc425x; break; + case ROM_PB410A: + if (gfxcard == GFX_BUILTIN) + timing = &timing_pb410a; + break; + case ROM_PB570: timing = &timing_pb570; break; @@ -733,6 +746,15 @@ void video_init() device_add(&tgui9400cxi_elx_device); return; + case ROM_PB410A: + device_add(&ht216_32_pb410a_device); + if (gfxcard != GFX_BUILTIN) + { + svga_set_override(svga_get_pri(), 1); + break; + } + return; + case ROM_PB570: device_add(&gd5430_pb570_device); if (gfxcard != GFX_BUILTIN)