Added emulation of Packard Bell PB410A, along with the built-in Headland HT216-32 video.

This commit is contained in:
SarahW 2019-04-03 21:32:48 +01:00
commit 35962551dd
18 changed files with 1178 additions and 13 deletions

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \

View file

@ -89,6 +89,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];
}

119
src/acc2168.c Normal file
View file

@ -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);
}

1
src/acc2168.h Normal file
View file

@ -0,0 +1 @@
void acc2168_init();

122
src/acc3221.c Normal file
View file

@ -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);
}

1
src/acc3221.h Normal file
View file

@ -0,0 +1 @@
void acc3221_init();

View file

@ -467,6 +467,7 @@ enum
ROM_IBMPS2_M70_TYPE4,
ROM_TULIP_TC7,
ROM_ZD_SUPERS, /* [8088] Zenith Data Systems SupersPort */
ROM_PB410A,
ROM_MAX
};

View file

@ -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);

View file

@ -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();

View file

@ -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;
}

873
src/vid_ht216.c Normal file
View file

@ -0,0 +1,873 @@
#include <stdlib.h>
#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
};

1
src/vid_ht216.h Normal file
View file

@ -0,0 +1 @@
extern device_t ht216_32_pb410a_device;

View file

@ -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)