diff --git a/src/86box.h b/src/86box.h index 516356138..42b516047 100644 --- a/src/86box.h +++ b/src/86box.h @@ -8,13 +8,16 @@ * * Main emulator include file. * - * Version: @(#)86box.h 1.0.2 2017/06/04 + * Version: @(#)86box.h 1.0.3 2017/10/09 + * + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Author: Miran Grca, * Copyright 2016-2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. */ -#ifndef BOX_H -# define BOX_H +#ifndef EMU_86BOX_H +# define EMU_86BOX_H #if defined(ENABLE_BUSLOGIC_LOG) || \ @@ -38,5 +41,8 @@ #define CONFIG_FILE_W L"86box.cfg" +#define NVR_PATH L"nvr" +#define SCREENSHOT_PATH L"screenshots" -#endif /*BOX_H*/ + +#endif /*EMU_86BOX_H*/ diff --git a/src/Makefile.local b/src/Makefile.local index 9b9988201..6f0df2aa8 100644 --- a/src/Makefile.local +++ b/src/Makefile.local @@ -10,7 +10,7 @@ # settings, so we can avoid changing the main one for all of # our local setups. # -# Version: @(#)Makefile.local 1.0.2 2017/05/23 +# Version: @(#)Makefile.local 1.0.4 2017/10/14 # # Author: Fred N. van Kempen, # @@ -20,23 +20,23 @@ ######################################################################### -DEBUG = y -OPTIM = n -COPTIM = -O1 +DEBUG := y +OPTIM := n +COPTIM := -O1 # Name of the executable. -PROG = yourexe +PROG := yourexe # Various compile-time options. -STUFF = #-DROM_TRACE=0xC800 -DIO_TRACE=0x70 -EXTRAS = #-DYOURNAME +STUFF := #-DROM_TRACE=0xC800 -DIO_TRACE=0x70 +EXTRAS := #-DYOURNAME ######################################################################### # Include the master Makefile.MinGW for the rest. # ######################################################################### -include Makefile.mingw +include win/Makefile.mingw # End of Makefile.local. diff --git a/src/Makefile.mingw b/src/Makefile.mingw deleted file mode 100644 index 33fb3644d..000000000 --- a/src/Makefile.mingw +++ /dev/null @@ -1,987 +0,0 @@ -# -# 86Box A hypervisor and IBM PC system emulator that specializes in -# running old operating systems and software designed for IBM -# PC systems and compatibles from 1981 through fairly recent -# system designs based on the PCI bus. -# -# This file is part of the 86Box distribution. -# -# Modified Makefile for Win32 (MinGW32) environment. -# -# Version: @(#)Makefile.mingw 1.0.45 2017/09/12 -# -# Authors: Miran Grca, -# Fred N. van Kempen, -# - -# Name of the executable. -ifndef PROG -PROG = 86Box -endif - -# Various compile-time options. -# -DROM_TRACE=0xc800 traces ROM access from segment C800 -# -DIO_TRACE=0x66 traces I/O on port 0x66 -STUFF = - -# Add feature selections here. -# -DANSI_CFG forces the config file to ANSI encoding. -# -DENABLE_VRAM_DUMP enables Video Ram dumping. -# -DENABLE_LOG_BREAKPOINT enables extra logging. -# -DENABLE_SCSI_BIOS_COMMAND_LOG=n enables extra logging. -# -DENABLE_AHA154X_LOG=n enables extra logging. -# -DENABLE_BUSLOGIC_LOG=n enables extra logging. -# -DENABLE_CDROM_LOG enables extra logging. -# -DENABLE_D86F_LOG enables extra logging. -# -DENABLE_FDC_LOG enables extra logging. -# -DENABLE_IDE_LOG enables extra logging. -# -DENABLE_SERIAL_LOG enables extra logging. -# -DENABLE_NIC_LOG enables extra logging. -ifndef EXTRAS -EXTRAS = -endif - -# Defaults for several build options (possibly defined in a chained file.) -ifndef DEBUG -DEBUG = n -endif -ifndef OPTIM -OPTIM = n -endif -ifndef RELEASE -RELEASE = n -endif -ifndef USB -USB = n -endif -ifndef DEV_BRANCH -DEV_BRANCH = n -endif -ifndef CIRRUS -CIRRUS = n -endif -ifndef NV_RIVA -NV_RIVA = n -endif -ifndef FLUIDSYNTH -FLUIDSYNTH = y -endif -ifndef MUNT -MUNT = y -endif -ifndef PAS16 -PAS16 = n -endif -ifndef NETWORK -NETWORK = y -endif -ifndef X64 -X64 = n -endif - - -######################################################################### -# Nothing should need changing from here on.. # -######################################################################### -VPATH = $(EXPATH) . cpu \ - cdrom floppy hdd machine \ - sound \ - sound/munt sound/munt/c_interface sound/munt/sha1 \ - sound/munt/srchelper \ - sound/resid-fp \ - scsi video lzf network network/slirp win -PLAT = win/ -ifeq ($(X64), y) -CPP = g++.exe -m64 -CC = gcc.exe -m64 -else -CPP = g++.exe -m32 -CC = gcc.exe -m32 -endif -WINDRES = windres.exe - -OPTS = -DWIN32 -I$(PLAT) $(EXTRAS) $(STUFF) -ifdef EXFLAGS -OPTS += $(EXFLAGS) -endif -ifdef EXINC -OPTS += -I$(EXINC) -endif - -ifeq ($(X64), y) - ifeq ($(OPTIM), y) - DFLAGS = -march=native - else - DFLAGS = - endif -else - ifeq ($(OPTIM), y) - DFLAGS = -march=native - else - DFLAGS = -march=i686 - endif -endif -ifeq ($(DEBUG), y) - DFLAGS += -ggdb -DDEBUG - AOPTIM = - ifndef COPTIM - COPTIM = -Og - endif -else - ifeq ($(OPTIM), y) - AOPTIM = -mtune=native - ifndef COPTIM - COPTIM = -O6 - endif - else - ifndef COPTIM - COPTIM = -O3 - endif - endif -endif -AFLAGS = -msse -msse2 -mfpmath=sse -CFLAGS = $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) $(AFLAGS) \ - -fomit-frame-pointer -mstackrealign -Wall -RFLAGS = --input-format=rc -O coff -ifeq ($(RELEASE), y) -CFLAGS += -DRELEASE_BUILD -RFLAGS += -DRELEASE_BUILD -endif -ifeq ($(VRAMDUMP), y) -CFLAGS += -DENABLE_VRAM_DUMP -RFLAGS += -DENABLE_VRAM_DUMP -endif -ifeq ($(FLUIDSYNTH), y) -CFLAGS += -DUSE_FLUIDSYNTH -FSYNTHOBJ = midi_fluidsynth.o -endif -ifeq ($(MUNT), y) -CFLAGS += -DUSE_MUNT -endif -ifeq ($(NETWORK), y) -CFLAGS += -DUSE_NETWORK -RFLAGS += -DUSE_NETWORK -endif -ifeq ($(X64), y) -PLATCG = codegen_x86-64.o -CGOPS = codegen_ops_x86-64.h -VCG = vid_voodoo_codegen_x86-64.h -else -PLATCG = codegen_x86.o -CGOPS = codegen_ops_x86.h -VCG = vid_voodoo_codegen_x86.h -endif - - -# Options for the DEV branch. -ifeq ($(DEV_BRANCH), y) -CFLAGS += -DDEV_BRANCH -ifeq ($(CIRRUS), y) -CFLAGS += -DUSE_CIRRUS -endif -ifeq ($(NV_RIVA), y) -CFLAGS += -DUSE_RIVA -endif -ifeq ($(PAS16), y) -CFLAGS += -DUSE_PAS16 -endif -endif - -# Options for works-in-progress. -ifndef SERIAL -SERIAL = serial.o -endif -ifndef EUROPC -EUROPC = machine_europc.o -endif - - -MAINOBJ = pc.o config.o random.o timer.o io.o dma.o nmi.o pic.o pit.o \ - ppi.o pci.o mca.o mcr.o mem.o memregs.o rom.o \ - device.o rtc.o nvr.o nvr_ps2.o \ - intel.o intel_flash.o intel_sio.o - -CPUOBJ = cpu.o 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o \ - codegen.o \ - codegen_ops.o \ - codegen_timing_common.o codegen_timing_486.o \ - codegen_timing_686.o codegen_timing_pentium.o \ - codegen_timing_winchip.o $(PLATCG) \ - x86seg.o x87.o - -MACHINEOBJ = machine.o \ - machine_common.o \ - machine_amstrad.o $(EUROPC) \ - machine_olivetti_m24.o \ - machine_pcjr.o \ - machine_tandy.o \ - machine_xt.o machine_xt_laserxt.o \ - machine_at.o \ - machine_at_ali1429.o machine_at_commodore.o \ - machine_at_neat.o machine_at_headland.o \ - machine_at_opti495.o machine_at_scat.o \ - machine_at_wd76c10.o \ - machine_at_sis_85c471.o machine_at_sis_85c496.o \ - machine_at_430lx_nx.o machine_at_430fx.o \ - machine_at_430hx.o machine_at_430vx.o \ - machine_at_440fx.o \ - machine_ps1.o \ - machine_ps2_isa.o machine_ps2_mca.o - -DEVOBJ = bugger.o lpt.o $(SERIAL) \ - tandy_eeprom.o tandy_rom.o \ - sio_detect.o \ - sio_fdc37c665.o sio_fdc37c669.o sio_fdc37c932fr.o \ - sio_pc87306.o sio_w83877f.o sio_um8669f.o \ - keyboard.o \ - keyboard_xt.o keyboard_at.o keyboard_pcjr.o \ - keyboard_amstrad.o keyboard_olim24.o \ - gameport.o \ - joystick_standard.o joystick_ch_flightstick_pro.o \ - joystick_sw_pad.o joystick_tm_fcs.o \ - mouse.o mouse_serial.o mouse_ps2.o mouse_bus.o - -FDDOBJ = fdd.o fdc.o fdi2raw.o \ - floppy.o floppy_common.o floppy_86f.o \ - floppy_fdi.o floppy_imd.o floppy_img.o floppy_json.o floppy_td0.o - -CDROMOBJ= cdrom.o \ - cdrom_dosbox.o cdrom_image.o cdrom_ioctl.o cdrom_null.o - -HDDOBJ = hdd.o hdd_image.o \ - hdd_mfm_at.o hdd_mfm_xebec.o hdd_esdi_at.o hdd_esdi_mca.o \ - hdd_ide_at.o hdd_ide_xt.o piix.o -ifeq ($(USB), y) -USBOBJ = usb.o -endif -ifeq ($(MUNT), y) -MUNTOBJ = midi_mt32.o \ - Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \ - LA32FloatWaveGenerator.o LA32WaveGenerator.o \ - MidiStreamParser.o Part.o Partial.o PartialManager.o \ - Poly.o ROMInfo.o SampleRateConverter_dummy.o Synth.o \ - Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o -endif -ifeq ($(NETWORK), y) -NETOBJ = network.o \ - net_pcap.o \ - net_slirp.o \ - bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o \ - ip_input.o queue.o tcp_input.o debug.o ip_output.o \ - sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o \ - net_ne2000.o -endif -SCSIOBJ = scsi.o scsi_bios_command.o scsi_device.o scsi_disk.o \ - scsi_buslogic.o scsi_aha154x.o -ifeq ($(DEV_BRANCH), y) -ifeq ($(PAS16), y) -PAS16OBJ = snd_pas16.o -endif -endif -SNDOBJ = sound.o \ - openal.o \ - dbopl.o nukedopl.o \ - convolve.o convolve-sse.o envelope.o extfilt.o \ - filter.o pot.o sid.o voice.o wave6581__ST.o \ - wave6581_P_T.o wave6581_PS_.o wave6581_PST.o \ - wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ - wave8580_PST.o wave.o \ - midi.o $(FSYNTHOBJ) $(MUNTOBJ) \ - midi_system.o \ - snd_speaker.o \ - snd_ps1.o snd_pssj.o \ - snd_lpt_dac.o snd_lpt_dss.o \ - snd_adlib.o snd_adlibgold.o snd_ad1848.o \ - snd_sb.o snd_sb_dsp.o snd_cms.o snd_dbopl.o \ - snd_emu8k.o snd_gus.o snd_opl.o \ - snd_mpu401.o $(PAS16OBJ) snd_resid.o \ - snd_sn76489.o snd_ssi2001.o snd_wss.o \ - snd_ym7128.o -VIDOBJ = video.o \ - vid_cga.o vid_cga_comp.o vid_mda.o \ - vid_ega.o vid_ega_render.o \ - vid_vga.o vid_svga.o vid_svga_render.o \ - vid_hercules.o vid_herculesplus.o vid_incolor.o \ - vid_colorplus.o \ - vid_genius.o \ - vid_s3.o vid_s3_virge.o \ - vid_et4000.o vid_et4000w32.o vid_icd2061.o \ - vid_oti067.o \ - vid_paradise.o \ - vid_tvga.o vid_tgui9440.o vid_tkd8001_ramdac.o \ - vid_ati_eeprom.o vid_ati18800.o vid_ati28800.o \ - vid_ati68860_ramdac.o vid_ati_mach64.o \ - vid_ics2595.o \ - vid_sc1502x_ramdac.o \ - vid_sdac_ramdac.o \ - vid_stg_ramdac.o \ - vid_wy700.o \ - vid_voodoo.o \ - vid_pcjr.o vid_ps1_svga.o \ - vid_olivetti_m24.o \ - vid_pc1512.o vid_pc1640.o vid_pc200.o \ - vid_tandy.o vid_tandysl.o -WINOBJ = win.o \ - win_ddraw.o win_ddraw_fs.o win_ddraw_screenshot.o \ - win_d3d.o win_d3d_fs.o \ - win_language.o win_status.o $(OPENDIR) win_dynld.o \ - win_video.o $(WSERIAL) win_keyboard.o win_mouse.o \ - win_iodev.o win_joystick.o win_midi.o \ - win_settings.o win_deviceconfig.o win_joystickconfig.o \ - 86Box.res -ifeq ($(DEV_BRANCH), y) -ifeq ($(CIRRUS), y) -CIRRUSOBJ = vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o -endif -ifeq ($(NV_RIVA), y) -RIVAOBJ = vid_nv_riva128.o -endif -DEVBRANCHOBJ = $(CIRRUSOBJ) $(RIVAOBJ) -endif -OBJ = $(MAINOBJ) $(CPUOBJ) $(MACHINEOBJ) $(DEVOBJ) \ - $(FDDOBJ) $(CDROMOBJ) $(HDDOBJ) \ - $(USBOBJ) $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \ - $(WINOBJ) $(DEVBRANCHOBJ) -ifdef EXOBJ -OBJ += $(EXOBJ) -endif - -LZFOBJ = lzf_c.o lzf_d.o - -LIBS = -mwindows \ - -lopenal.dll \ - -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ - -lcomctl32 -lwinmm -ifeq ($(NETWORK), y) -LIBS += -lkernel32 -lwsock32 -liphlpapi -lpsapi -endif -LIBS += -static -lstdc++ -lgcc -LIBS += -Wl,--large-address-aware - - -# Build rules. -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) $(WFLAGS) -c $< - -%.o: %.cc - @echo $< - @$(CPP) $(CFLAGS) $(WFLAGS) -c $< - -%.o: %.cpp - @echo $< - @$(CPP) $(CFLAGS) $(WFLAGS) -c $< - -all: $(PROG).exe pcap_if.exe - - -$(PROG).exe: $(OBJ) $(LZFOBJ) - @echo Linking $(PROG).exe .. - @$(CC) -o $(PROG).exe $(OBJ) $(LZFOBJ) $(LIBS) -ifneq ($(DEBUG), y) - @strip $(PROG).exe -endif - -pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res - @echo Linking pcap_if.exe .. - @$(CC) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res -ifneq ($(DEBUG), y) - @strip pcap_if.exe -endif - - - -clean: - -rm *.o - -rm *.exe - -rm *.res - -86Box.res: 86Box.rc - @echo Processing $< - @$(WINDRES) $(RFLAGS) $(EXTRAS) -i win/86Box.rc -o 86Box.res - -pcap_if.res: pcap_if.rc - @echo Processing $< - @$(WINDRES) $(RFLAGS) -i win/pcap_if.rc -o pcap_if.res - - -# Module dependencies. -386.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87.h mem.h floppy.h fdc.h pic.h timer.h cpu/386_common.h - -386_dynarec.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_ops.h cpu/x87.h mem.h cpu/codegen.h floppy.h fdc.h pic.h timer.h cpu/386_common.h \ - cpu/x86_ops.h cpu/x86seg.h cpu/x86_ops_arith.h cpu/x86_ops_atomic.h cpu/x86_ops_bcd.h cpu/x86_ops_bit.h \ - cpu/x86_ops_bitscan.h cpu/x86_ops_call.h cpu/x86_ops_flag.h cpu/x86_ops_fpu.h cpu/x86_ops_inc_dec.h cpu/x86_ops_int.h \ - cpu/x86_ops_io.h cpu/x86_ops_jump.h cpu/x86_ops_misc.h \ - cpu/x87_ops_arith.h cpu/x87_ops_misc.h cpu/x87_ops_loadstore.h \ - cpu/x87_ops.h cpu/x86_ops_i686.h cpu/x86_ops_mmx.h \ - cpu/x86_ops_mmx_arith.h cpu/x86_ops_mmx_cmp.h cpu/x86_ops_mmx_logic.h cpu/x86_ops_mmx_pack.h cpu/x86_ops_mmx_shift.h \ - cpu/x86_ops_mov.h cpu/x86_ops_mov_ctrl.h cpu/x86_ops_mov_seg.h cpu/x86_ops_movx.h cpu/x86_ops_msr.h cpu/x86_ops_mul.h \ - cpu/x86_ops_pmode.h cpu/x86_ops_prefix.h cpu/x86_ops_rep.h cpu/x86_ops_ret.h cpu/x86_ops_set.h cpu/x86_ops_shift.h \ - cpu/x86_ops_stack.h cpu/x86_ops_string.h cpu/x86_ops_xchg.h \ - cpu/386_ops.h - -386_dynarec_ops.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_ops.h cpu/x87.h cpu/x86_flags.h mem.h cpu/codegen.h pic.h cpu/386_common.h \ - cpu/x86_ops.h cpu/x86seg.h cpu/x86_ops_arith.h cpu/x86_ops_atomic.h cpu/x86_ops_bcd.h cpu/x86_ops_bit.h \ - cpu/x86_ops_bitscan.h cpu/x86_ops_call.h cpu/x86_ops_flag.h cpu/x86_ops_fpu.h cpu/x86_ops_inc_dec.h cpu/x86_ops_int.h \ - cpu/x86_ops_io.h cpu/x86_ops_jump.h cpu/x86_ops_misc.h \ - cpu/x87_ops_arith.h cpu/x87_ops_misc.h cpu/x87_ops_loadstore.h \ - cpu/x87_ops.h cpu/x86_ops_i686.h cpu/x86_ops_mmx.h \ - cpu/x86_ops_mmx_arith.h cpu/x86_ops_mmx_cmp.h cpu/x86_ops_mmx_logic.h cpu/x86_ops_mmx_pack.h cpu/x86_ops_mmx_shift.h \ - cpu/x86_ops_mov.h cpu/x86_ops_mov_ctrl.h cpu/x86_ops_mov_seg.h cpu/x86_ops_movx.h cpu/x86_ops_msr.h cpu/x86_ops_mul.h \ - cpu/x86_ops_pmode.h cpu/x86_ops_prefix.h cpu/x86_ops_rep.h cpu/x86_ops_ret.h cpu/x86_ops_set.h cpu/x86_ops_shift.h \ - cpu/x86_ops_stack.h cpu/x86_ops_string.h cpu/x86_ops_xchg.h \ - cpu/386_ops.h - -808x.o: ibm.h cpu/cpu.h cpu/x86.h keyboard.h mem.h nmi.h pic.h scsi/scsi.h timer.h - -codegen.o: ibm.h cpu/x86_ops.h mem.h cpu/codegen.h - -codegen_ops.o: ibm.h mem.h cpu/x86.h cpu/x86_ops.h cpu/x86_flags.h cpu/x87.h cpu/386_common.h cpu/cpu.h cpu/codegen.h cpu/codegen_ops.h \ - cpu/$(CGOPS) cpu/codegen_ops_arith.h cpu/codegen_ops_fpu.h cpu/codegen_ops_jump.h cpu/codegen_ops_logic.h cpu/codegen_ops_misc.h \ - cpu/codegen_ops_mmx.h cpu/codegen_ops_mov.h cpu/codegen_ops_shift.h cpu/codegen_ops_stack.h cpu/codegen_ops_xchg.h - -codegen_timing_486.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h - -codegen_timing_686.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_timing_common.h - -codegen_timing_common.o: ibm.h cpu/codegen_timing_common.h - -codegen_timing_pentium.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h - -codegen_timing_winchip.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x87_ops.h cpu/x87.h mem.h cpu/codegen.h cpu/codegen_ops.h cpu/codegen_timing_common.h - -codegen_x86.o: ibm.h cpu/cpu.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h mem.h cpu/386_common.h cpu/codegen.h cpu/codegen_ops.h \ - cpu/codegen_ops_x86.h - -codegen_x86-64.o: ibm.h mem.h cpu/cpu.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h cpu/386_common.h cpu/codegen.h cpu/codegen_ops.h \ - cpu/codegen_ops_x86-64.h - -cpu.o: ibm.h cpu/cpu.h device.h machine/machine.h io.h cpu/x86_ops.h mem.h pci.h cpu/codegen.h - -x86seg.o: ibm.h mem.h nvr.h cpu/x86.h cpu/386.h cpu/386_common.h cpu/cpu.h - -x87.o: ibm.h pic.h cpu/x86.h cpu/x86_flags.h cpu/x86_ops.h cpu/x87.h cpu/386_common.h - -bugger.o: ibm.h io.h bugger.h - -cdrom.o: 86box.h cdrom.h ibm.h hdd/hdd_ide_at.h piix.h scsi/scsi.h timer.h \ - win/plat_iodev.h - -cdrom_dosbox.o: cdrom_dosbox.h - -cdrom_image.o: config.h cdrom_dosbox.h cdrom.h cdrom_image.h cdrom_null.h - -cdrom_ioctl.o: ibm.h cdrom.h cdrom_ioctl.h scsi/scsi.h - -cdrom_null.o: ibm.h cdrom.h cdrom_ioctl.h - -config.o: cdrom.h config.h device.h floppy/floppy.h floppy/fdc.h floppy/fdd.h ibm.h \ - cpu/cpu.h gameport.h hdd/hdd_ide_at.h hdd/hdd.h machine/machine.h \ - mouse.h network/network.h nvr.h scsi/scsi.h win/plat_joystick.h \ - win/plat_midi.h sound/snd_dbopl.h sound/snd_mpu401.h \ - sound/snd_opl.h sound/sound.h video/video.h win/win.h \ - win/resource.h win/win_language.h - -device.o: ibm.h cpu/cpu.h config.h device.h machine/machine.h sound/sound.h - -dma.o: ibm.h cpu/x86.h mem.h io.h dma.h - -floppy.o: ibm.h config.h floppy.h floppy_fdi.h fdc.h fdd.h timer.h \ - floppy_img.h floppy_86f.h floppy_td0.h floppy_imd.h - -floppy_common.o: ibm.h floppy.h floppy_common.h fdc.h fdd.h - -floppy_86f.o: lzf/lzf.h config.h dma.h random.h floppy.h floppy_86f.h \ - fdc.h fdd.h ibm.h - -floppy_fdi.o: ibm.h floppy.h floppy_img.h floppy_fdi.h fdc.h fdd.h fdi2raw.h \ - floppy.h floppy_imd.h fdc.h fdd.h config.h floppy_img.h - -floppy_td0.o: ibm.h floppy.h floppy_td0.h fdc.h fdd.h - -floppy_json.o: ibm.h floppy.h floppy_common.h floppy_json.h fdc.h fdd.h - -fdc.o: ibm.h io.h dma.h pic.h timer.h floppy.h fdc.h fdd.h - -fdd.o: ibm.h floppy.h fdc.h fdd.h - -fdi2raw.o: fdi2raw.h ibm.h - -gameport.o: ibm.h cpu/cpu.h device.h io.h timer.h gameport.h \ - joystick_ch_flightstick_pro.h joystick_standard.h \ - joystick_sw_pad.h joystick_tm_fcs.h plat_joystick.h - -hdd.o: ibm.h cpu/cpu.h device.h hdd/hdd.h machine/machine.h \ - hdd/hdd_esdi_at.h hdd/hdd_esdi_mca.h hdd/hdd_mfm_at.h \ - hdd/hdd_mfm_xebec.h hdd/hdd_ide_xt.h - -hdd_image.o: ibm.h hdd/hdd_ide_at.h hdd/hdd_image.h - -hdd_esdi_at.o: ibm.h device.h hdd_image.h io.h mem.h pic.h rom.h timer.h \ - hdd/hdd_esdi_at.h - -hdd_esdi_mca.o: ibm.h device.h dma.h hdd/hdd_image.h io.h mca.h mem.h \ - pic.h rom.h timer.h hdd/hdd_esdi_mca.h - -hdd_ide_at.o: 86box.h cdrom.h hdd/hdd_image.h ibm.h io.h pic.h timer.h \ - cdrom.h scsi/scsi.h hdd/hdd_ide_at.h - -hdd_ide_xt.o: ibm.h io.h mem.h rom.h device.h hdd/hdd_ide_at.h hdd/hdd_ide_xt.h - -hdd_mfm_at.o: ibm.h device.h hdd/hdd_image.h io.h pic.h timer.h hdd/hdd_mfm_at.h - -hdd_mfm_xebec.o: ibm.h device.h dma.h hdd/hdd_image.h io.h mem.h pic.h rom.h \ - timer.h hdd/hdd_mfm_xebec.h - -intel.o: ibm.h cpu/cpu.h io.h mem.h pit.h timer.h intel.h - -intel_flash.o: ibm.h cpu/cpu.h device.h mem.h machine/machine.h rom.h - -intel_sio.o: ibm.h dma.h mem.h pci.h intel_sio.h - -io.o: ibm.h io.h - -joystick_ch_flightstick_pro.o: ibm.h device.h timer.h gameport.h \ - joystick_standard.h plat_joystick.h - -joystick_standard.o: ibm.h device.h timer.h gameport.h \ - joystick_standard.h plat_joystick.h - -joystick_sw_pad.o: ibm.h device.h timer.h gameport.h \ - joystick_sw_pad.h plat_joystick.h - -joystick_tm_fcs.o: ibm.h device.h timer.h gameport.h \ - joystick_standard.h plat_joystick.h - -keyboard.o: ibm.h plat_keyboard.h keyboard.h - -keyboard_amstrad.o: ibm.h io.h mem.h pic.h pit.h timer.h sound/sound.h \ - sound/snd_speaker.h keyboard.h keyboard_amstrad.h - -keyboard_at.o: ibm.h io.h mem.h pic.h pit.h timer.h floppy.h fdc.h \ - sound/sound.h sound/snd_speaker.h keyboard.h keyboard_at.h - -keyboard_olim24.o: ibm.h io.h mem.h pic.h pit.h timer.h mouse.h \ - sound/sound.h sound/snd_speaker.h keyboard.h keyboard_olim24.h - -keyboard_pcjr.o: ibm.h io.h mem.h nmi.h pic.h pit.h timer.h \ - device.h sound/sound.h sound/snd_speaker.h \ - sound/snd_sn76489.h keyboard.h keyboard_pcjr.h - -keyboard_xt.o: ibm.h io.h mem.h pic.h pit.h timer.h device.h tandy_eeprom.h \ - sound/sound.h sound/snd_speaker.h keyboard.h keyboard_xt.h - -lpt.o: ibm.h io.h lpt.h sound/snd_lpt_dac.h sound/snd_lpt_dss.h - -machine.o: ibm.h cpu/cpu.h device.h floppy.h fdc.h fdd.h io.h \ - machine/machine.h machine/machine_common.h machine/machine_amstrad.h \ - machine/machine_europc.h machine/machine_olivetti_m24.h machine/machine_pcjr.h machine/machine_tandy.h \ - machine/machine_xt.h machine/machine_xt_laserxt.h machine/machine_at.h machine/machine_at_ali1429.h \ - machine/machine_at_commodore.h machine/machine_at_headland.h machine/machine_at_neat.h machine/machine_at_opti495.h \ - machine/machine_at_scat.h machine/machine_at_wd76c10.h machine/machine_ps1.h machine/machine_ps2_isa.h \ - machine/machine_ps2_mca.h machine/machine_at_sis_85c471.h machine/machine_at_sis_85c496.h \ - machine/machine_at_430lx_nx.h machine/machine_at_430fx.h machine/machine_at_430hx.h machine/machine_at_430vx.h \ - machine/machine_at_440fx.h video/vid_pcjr.h video/vid_tandy.h video/vid_tandysl.h - -machine_amstrad.o: ibm.h cpu/cpu.h device.h floppy.h fdd.h fdc.h gameport.h io.h keyboard.h keyboard_amstrad.h lpt.h mem.h mouse.h \ - nmi.h nvr.h machine/machine_common.h - -machine_at.o: ibm.h bugger.h device.h dma.h gameport.h hdd/hdd_ide_at.h keyboard_at.h lpt.h mem.h nvr.h pic.h pit.h \ - machine/machine_common.h machine/machine_at.h - -machine_at_430fx.o: ibm.h cpu/cpu.h device.h sio.h intel_flash.h mem.h memregs.h pci.h piix.h \ - machine/machine_at.h machine/machine_at_430fx.h - -machine_at_430hx.o: ibm.h cpu/cpu.h device.h sio.h io.h intel_flash.h mem.h memregs.h pci.h \ - piix.h sio.h machine/machine_at.h machine/machine_at_430hx.h - -machine_at_430lx_nx.o: ibm.h cpu/cpu.h device.h sio.h intel.h intel_flash.h mem.h memregs.h pci.h intel_sio.h machine/machine_at.h \ - machine/machine_at_430lx_nx.h - -machine_at_430vx.o: ibm.h cpu/cpu.h device.h sio.h io.h mem.h memregs.h intel_flash.h pci.h piix.h \ - machine/machine_at.h machine/machine_at_430vx.h - -machine_at_440fx.o: ibm.h cpu/cpu.h device.h sio.h intel_flash.h io.h mem.h memregs.h pci.h piix.h machine/machine_at.h \ - machine/machine_at_440fx.h - -machine_at_ali1429.o: ibm.h cpu/cpu.h hdd/hdd_ide_at.h io.h mem.h machine/machine_at.h machine/machine_at_ali1429.h - -machine_at_commodore.o: ibm.h io.h lpt.h serial.h machine/machine_at.h machine/machine_at_commodore.h - -machine_at_compaq.o: ibm.h cpu/cpu.h mem.h machine/machine_at.h machine/machine_at_compaq.h - -machine_at_headland.o: ibm.h cpu/cpu.h io.h mem.h machine/machine_at.h machine/machine_at_headland.h - -machine_at_neat.o: ibm.h cpu/cpu.h io.h machine/machine_at.h machine/machine_at_neat.h - -machine_at_opti495.o: ibm.h cpu/cpu.h io.h mem.h machine/machine_at.h machine/machine_at_opti495.h - -machine_at_scat.o: ibm.h cpu/cpu.h io.h mem.h cpu/x86.h machine/machine_at.h machine/machine_at_scat.h - -machine_at_sis_85c50x.o: ibm.h io.h mem.h pci.h machine/machine_at.h machine/machine_at_sis_5c50x.h - -machine_at_sis_85c471.o: ibm.h floppy.h fdc.h fdd.h hdd/hdd_ide_at.h io.h lpt.h memregs.h serial.h machine/machine_at.h \ - machine/machine_at_sis_85c471.h - -machine_at_sis_85c496.o: ibm.h cpu/cpu.h sio.h io.h mem.h memregs.h pci.h machine/machine_at.h machine/machine_at_sis_85c496.h - -machine_at_wd76c10.o: ibm.h floppy.h fdc.h io.h mem.h serial.h machine/machine_at.h machine/machine_at_wd76c10.h - -machine_common.o: ibm.h dma.h floppy.h fdd.h fdc.h lpt.h pic.h pit.h serial.h machine/machine_common.h - -machine_europc.o: ibm.h cpu/cpu.h io.h device.h gameport.h keyboard_xt.h lpt.h mem.h nmi.h rom.h machine/machine_common.h \ - machine/machine_europc.h -europc_hdd.o: ibm.h io.h dma.h pic.h device.h timer.h hdd/hdd_image.h europc.h - -machine_olivetti_m24.o: ibm.h cpu/cpu.h device.h gameport.h keyboard_olim24.h mem.h nmi.h nvr.h io.h machine/machine_common.h \ - machine/machine_olivetti_m24.h - -machine_pcjr.o: ibm.h device.h floppy.h fdc.h fdd.h keyboard_pcjr.h mem.h nmi.h pic.h pit.h serial.h sound/snd_sn76489.h \ - machine/machine_pcjr.h - -machine_ps1.o: ibm.h cpu/cpu.h device.h floppy.h dma.h gameport.h hdd/hdd_ide_at.h fdd.h fdc.h io.h keyboard_at.h lpt.h \ - mem.h nvr.h pic.h pit.h rom.h serial.h sound/snd_ps1.h machine/machine_common.h machine/machine_ps1.h - -machine_ps2_isa.o: ibm.h cpu/cpu.h device.h floppy.h dma.h fdd.h fdc.h io.h keyboard.h keyboard_at.h lpt.h mem.h nvr.h pic.h \ - pit.h rom.h serial.h machine/machine_common.h machine/machine_ps2_isa.h - -machine_ps2_mca.o: ibm.h cpu/cpu.h cpu/x86.h device.h dma.h io.h keyboard_at.h lpt.h mca.h mem.h mouse.h nvr.h pic.h \ - pit.h rom.h nvr_ps2.h serial.h machine/machine_common.h machine/machine_ps2_mca.h - -machine_tandy.o: ibm.h device.h gameport.h keyboard_xt.h mem.h nmi.h tandy_eeprom.h tandy_rom.h sound/snd_pssj.h \ - sound/snd_sn76489.h - -machine_xt.o: ibm.h bugger.h device.h gameport.h keyboard_xt.h mem.h nmi.h pit.h machine/machine_common.h \ - machine/machine_xt.h - -machine_xt_laserxt.o: ibm.h cpu/cpu.h io.h mem.h machine/machine_xt.h machine/machine_xt_laserxt.h - -mca.o: ibm.h io.h mem.h mca.h - -mcr.o: ibm.h - -mem.o: ibm.h cpu/cpu.h cpu/x86_ops.h cpu/x86.h config.h \ - io.h mem.h rom.h cpu/codegen.h video/video.h - -memregs.o: ibm.h io.h memregs.h - -mouse.o: ibm.h cpu/cpu.h device.h machine/machine.h mouse.h \ - keyboard_olim24.h - -mouse_bus.o: ibm.h io.h pic.h timer.h mouse.h - -mouse_ps2.o: ibm.h keyboard_at.h mouse.h plat_mouse.h - -mouse_serial.o: ibm.h timer.h serial.h mouse.h - -nmi.o: ibm.h io.h nmi.h - -network.o: ibm.h device.h network/network.h network/net_ne2000.h win/plat_ui.h - -net_pcap.o: ibm.h config.h device.h network/network.h win/plat_dynld.h win/plat_thread.h - -net_slirp.o: network/slirp/slirp.h network/slirp/queue.h ibm.h config.h device.h network/network.h win/plat_thread.h - -net_ne2000.o: ibm.h io.h mem.h rom.h pci.h pic.h device.h config.h random.h network/network.h network/net_ne2000.h network/bswap.h - -nvr.o: ibm.h cpu/cpu.h device.h io.h mem.h machine/machine.h \ - machine/machine_europc.h nvr.h pic.h rom.h timer.h rtc.h - -nvr_ps2.o: ibm.h device.h io.h mem.h rom.h nvr_ps2.h - -pc.o: 86box.h config.h random.h ibm.h mem.h \ - cpu/cpu.h cpu/x86_ops.h cpu/codegen.h \ - dma.h nvr.h pic.h pit.h timer.h device.h machine/machine.h \ - floppy.h floppy_86f.h floppy_fdi.h floppy_imd.h floppy_img.h floppy_td0.h \ - random.h config.h fdc.h fdd.h gameport.h plat_joystick.h \ - plat_midi.h hdd/hdd.h hdd/hdd_ide_at.h cdrom.h cdrom_ioctl.h \ - cdrom_image.h cdrom_null.h scsi/scsi.h keyboard.h plat_keyboard.h \ - keyboard_at.h mouse.h plat_mouse.h network/network.h serial.h \ - sound/sound.h sound/snd_cms.h sound/snd_dbopl.h \ - sound/snd_mpu401.h sound/snd_opl.h sound/snd_gus.h \ - sound/snd_sb.h sound/snd_speaker.h sound/snd_ssi2001.h \ - video/video.h video/vid_voodoo.h win/plat_ui.h - -pci.o: ibm.h cdrom.h floppy.h fdc.h hdd/hdd_ide_at.h io.h keyboard_at.h mem.h pic.h pci.h - -pic.o: ibm.h io.h pic.h pit.h - -piix.o: ibm.h dma.h hdd/hdd_ide_at.h io.h mem.h pci.h piix.h - -pit.o: ibm.h cpu/cpu.h dma.h io.h pic.h pit.h device.h timer.h \ - machine/machine.h sound/snd_speaker.h video/video.h - -ppi.o: ibm.h pit.h plat_keyboard.h plat_mouse.h - -random.o: random.h - -rom.o: config.h ibm.h mem.h rom.h - -rtc.o: nvr.h rtc.h - -scsi.o: 86box.h ibm.h timer.h device.h cdrom.h scsi/scsi.h \ - scsi/scsi_aha154x.h scsi/scsi_buslogic.h - -scsi_bios_command.o: ibm.h dma.h scsi/scsi.h scsi/scsi_bios_command.h scsi/scsi_device.h - -scsi_device.o: ibm.h scsi/scsi.h scsi/scsi_disk.h cdrom.h - -scsi_aha154x.o: ibm.h io.h mca.h mem.h mca.h rom.h dma.h pic.h timer.h \ - device.h scsi/scsi.h scsi/scsi_bios_command.h scsi/scsi_aha154x.h \ - -scsi_buslogic.o: ibm.h io.h mem.h rom.h dma.h pic.h pci.h timer.h \ - device.h scsi/scsi.h scsi/scsi_bios_command.h scsi/scsi_device.h \ - scsi/scsi_buslogic.h - -scsi_disk.o: 86box.h cdrom.h hdd/hdd_image.h ibm.h hdd/hdd_ide_at.h piix.h scsi/scsi.h \ - scsi/scsi_disk.h timer.h win/plat_iodev.h - -serial.o: ibm.h io.h pic.h timer.h serial.h plat_serial.h - -sio_detect.o: ibm.h io.h floppy.h fdd.h fdc.h sio.h - -sio_fdc37c665.o: ibm.h floppy.h fdc.h fdd.h hdd/hdd_ide_at.h io.h lpt.h serial.h \ - sio.h floppy.h fdc.h fdd.h io.h hdd/hdd_ide_at.h lpt.h serial.h - -sio_fdc37c932fr.o: ibm.h floppy.h fdc.h fdd.h hdd/hdd_ide_at.h io.h lpt.h \ - serial.h sio.h - -sio_pc87306.o: ibm.h floppy.h fdc.h fdd.h hdd/hdd_ide_at.h io.h lpt.h serial.h \ - sio.h - -sio_w83877f.o: ibm.h floppy.h fdc.h fdd.h io.h lpt.h serial.h sio.h - -dbopl.o: sound/dbopl.h - -midi.o: device.h sound/midi.h ibm.h win/plat_midi.h win/plat_ticks.h sound/midi_fluidsynth.h sound/midi_mt32.h sound/midi_system.h - -midi_fluidsynth.o: config.h win/plat_dynld.h win/plat_thread.h win/plat_ui.h device.h sound/midi_fluidsynth.h sound/midi.h sound/sound.h - -midi_mt32.o: sound/munt/c_interface/c_interface.h win/plat_thread.h ibm.h device.h mem.h rom.h sound/midi_mt32.h sound/midi.h \ - sound/sound.h - -midi_system.o: device.h win/plat_midi.h sound/midi_system.h sound/midi.h - -nukedopl.o: sound/nukedopl.h - -openal.o: ibm.h sound/sound.h - -snd_ad1848.o: ibm.h dma.h pic.h timer.h sound/sound.h sound/snd_ad1848.h - -snd_adlib.o: ibm.h io.h mca.h device.h sound/sound.h sound/snd_adlib.h sound/snd_opl.h - -snd_adlibgold.o: ibm.h io.h dma.h pic.h pit.h mem.h rom.h timer.h device.h sound/sound.h sound/filters.h sound/snd_opl.h sound/snd_ym7128.h - -snd_cms.o: ibm.h io.h device.h sound/sound.h sound/snd_cms.h - -snd_dbopl.o: sound/dbopl.h sound/nukedopl.h sound/snd_dbopl.h - -snd_emu8k.o: ibm.h io.h mem.h rom.h timer.h device.h sound/sound.h sound/snd_emu8k.h - -snd_gus.o: ibm.h io.h pic.h dma.h timer.h device.h sound/sound.h sound/snd_gus.h - -snd_lpt_dac.o: ibm.h cpu/cpu.h sound/filters.h lpt.h sound/snd_lpt_dac.h sound/sound.h timer.h - -snd_lpt_dss.o: ibm.h cpu/cpu.h sound/filters.h lpt.h sound/snd_lpt_dss.h sound/sound.h timer.h - -snd_mpu401.o: ibm.h device.h io.h pic.h timer.h sound/midi.h sound/sound.h sound/snd_mpu401.h - -snd_opl.o: ibm.h io.h timer.h sound/sound.h sound/snd_opl.h sound/snd_dbopl.h - -snd_pas16.o: ibm.h io.h pic.h pit.h dma.h timer.h device.h sound/sound.h sound/snd_opl.h sound/snd_pas16.h sound/snd_sb_dsp.h \ - SOUND\filters.h - -snd_ps1.o: ibm.h io.h pic.h timer.h device.h sound/sound.h sound/snd_ps1.h sound/snd_sn76489.h - -snd_pssj.o: ibm.h io.h dma.h pic.h timer.h device.h sound/sound.h sound/snd_pssj.h sound/snd_sn76489.h - -snd_resid.o: sound/resid-fp/sid.h sound/snd_resid.h - -snd_sb.o: ibm.h io.h mca.h mem.h rom.h device.h sound/sound.h sound/snd_dbopl.h sound/snd_emu8k.h sound/snd_mpu401.h \ - sound/snd_opl.h sound/snd_sb.h sound/snd_sb_dsp.h sound/filters.h - -snd_sb_dsp.o: ibm.h io.h pic.h dma.h timer.h device.h sound/midi.h sound/sound.h sound/snd_mpu401.h sound/snd_sb_dsp.h - -snd_sn76489.o: ibm.h io.h device.h sound/sound.h sound/snd_sn76489.h - -snd_speaker.o: ibm.h sound/sound.h sound/snd_speaker.h - -snd_ssi2001.o: ibm.h io.h device.h sound/sound.h sound/snd_resid.h sound/snd_ssi2001.h - -snd_wss.o: ibm.h io.h pic.h dma.h device.h sound/sound.h sound/snd_ad1848.h sound/snd_opl.h sound/snd_wss.h - -snd_ym7128.o: ibm.h sound/snd_ym7128.h - -sound.o: ibm.h device.h timer.h cdrom.h win/plat_thread.h sound/midi.h sound/sound.h sound/snd_opl.h sound/snd_adlib.h \ - sound/snd_pas16.h sound/snd_sb.h sound/snd_sb_dsp.h sound/snd_wss.h sound/filters.h - -tandy_eeprom.o: ibm.h device.h mem.h io.h rom.h tandy_eeprom.h - -tandy_rom.o: ibm.h device.h io.h mem.h rom.h tandy_rom.h - -timer.o: ibm.h timer.h - -usb.o: ibm.h io.h mem.h usb.h - -vid_ati_eeprom.o: ibm.h mem.h rom.h video/vid_ati_eeprom.h - -vid_ati_mach64.o: ibm.h device.h io.h mem.h pci.h rom.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_svga_render.h \ - video/vid_ati68860_ramdac.h video/vid_ati_eeprom.h video/vid_ics2595.h - -vid_ati18800.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_ati18800.h video/vid_ati_eeprom.h video/vid_svga.h - -vid_ati28800.o: ibm.h io.h mem.h rom.h device.h timer.h video/video.h video/vid_ati28800.h video/vid_ati_eeprom.h video/vid_svga.h \ - video/vid_svga_render.h - -vid_ati68860_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_ati68860_ramdac.h video/vid_svga_render.h - -vid_cga.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_cga_comp.h win/win_cgapal.h - -vid_cga_comp.o: ibm.h device.h mem.h video/vid_cga.h video/vid_cga_comp.h - -vid_cl_gd.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_cl_ramdac.h \ - video/vid_cl_gd.h video/vid_cl_gd_blit.h - -vid_cl_gd_blit.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_cl_ramdac.h \ - video/vid_cl_gd.h video/vid_cl_gd_blit.h video/vid_cl_gd_vga_rop.h - -vid_cl_gd_ramdac.o: ibm.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_cl_ramdac.h video/vid_cl_gd.h \ - video/vid_cl_gd_blit.h - -vid_colorplus.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_colorplus.h video/vid_cga_comp.h - -vid_ega.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_ega.h video/vid_ega_render.h - -vid_ega_render.o: ibm.h device.h mem.h rom.h video/video.h video/vid_ega.h video/vid_ega_render.h - -vid_et4000.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_sc1502x_ramdac.h video/vid_et4000.h - -vid_et4000w32.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_icd2061.h \ - video/vid_stg_ramdac.h - -vid_genius.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_genius.h - -vid_hercules.o: ibm.h mem.h io.h timer.h device.h video/video.h video/vid_hercules.h win/win_cgapal.h - -vid_herculesplus.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_herculesplus.h - -vid_icd2061.o: ibm.h video/vid_icd2061.h - -vid_ics2595.o: ibm.h video/vid_ics2595.h - -vid_incolor.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_incolor.h - -vid_mda.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_mda.h win/win_cgapal.h - -vid_nv_riva128.o: ibm.h io.h mem.h pci.h pic.h rom.h timer.h device.h win/plat_thread.h video/video.h video/vid_svga.h \ - video/vid_svga_render.h - -vid_olivetti_m24.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_olivetti_m24.h - -vid_oti067.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_oti067.h video/vid_svga.h - -vid_paradise.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_paradise.h video/vid_svga.h video/vid_svga_render.h - -vid_pc200.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_cga.h video/vid_pc200.h - -vid_pc1512.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_pc1512.h - -vid_pc1640.o: ibm.h io.h mem.h rom.h timer.h device.h video/video.h video/vid_cga.h video/vid_ega.h video/vid_pc1640.h - -vid_pcjr.o: ibm.h io.h mem.h pic.h timer.h device.h video/video.h video/vid_cga_comp.h video/vid_pcjr.h - -vid_ps1_svga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_vga.h - -vid_s3.o: ibm.h device.h io.h mem.h pci.h rom.h win/plat_thread.h video/video.h video/vid_s3.h video/vid_svga.h \ - video/vid_svga_render.h video/vid_sdac_ramdac.h - -vid_s3_virge.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_s3_virge.h video/vid_svga.h \ - video/vid_svga_render.h - -vid_sc1502x_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_sc1502x_ramdac.h - -vid_sdac_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_sdac_ramdac.h - -vid_stg_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_stg_ramdac.h - -vid_svga.o: ibm.h io.h mem.h rom.h timer.h video/video.h video/vid_svga.h video/vid_svga_render.h - -vid_svga_render.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_svga_render.h - -vid_tandy.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_tandy.h video/vid_cga_comp.h - -vid_tandysl.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_tandysl.h - -vid_tgui9440.o: ibm.h io.h mem.h pci.h rom.h device.h win/plat_thread.h video/video.h video/vid_svga.h video/vid_svga_render.h \ - video/vid_tkd8001_ramdac.h video/vid_tgui9440.h - -vid_tkd8001_ramdac.o: ibm.h mem.h video/video.h video/vid_svga.h video/vid_tkd8001_ramdac.h - -vid_tvga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_svga_render.h video/vid_tkd8001_ramdac.h \ - video/vid_tvga.h - -vid_vga.o: ibm.h io.h mem.h rom.h device.h video/video.h video/vid_svga.h video/vid_vga.h - -vid_voodoo.o: ibm.h cpu/cpu.h mem.h rom.h pci.h timer.h device.h win/plat_thread.h video/video.h video/vid_svga.h \ - video/vid_voodoo.h video/vid_voodoo_dither.h video/$(VCG) - -vid_wy700.o: ibm.h io.h mem.h timer.h device.h video/video.h video/vid_wy700.h - -video.o: ibm.h cpu/cpu.h io.h mem.h rom.h config.h device.h timer.h win/plat_thread.h video/video.h video/vid_svga.h \ - win/resource.h win/win.h win/win_cgapal.h \ - video/vid_ati18800.h video/vid_ati28800.h video/vid_ati_mach64.h video/vid_cga.h \ - video/vid_cl_ramdac.h video/vid_cl_gd.h \ - video/vid_ega.h video/vid_et4000.h video/vid_et4000w32.h video/vid_genius.h video/vid_hercules.h \ - video/vid_herculesplus.h video/vid_incolor.h video/vid_colorplus.h video/vid_mda.h \ - video/vid_nv_riva128.h \ - video/vid_olivetti_m24.h video/vid_oti067.h video/vid_paradise.h video/vid_pc1512.h video/vid_pc1640.h \ - video/vid_pc200.h video/vid_pcjr.h video/vid_ps1_svga.h video/vid_s3.h video/vid_s3_virge.h video/vid_tandy.h \ - video/vid_tandysl.h video/vid_tgui9440.h video/vid_tvga.h video/vid_vga.h video/vid_wy700.h - -win.o: 86box.h device.h floppy.h fdd.h hdd.h ibm.h cpu/cpu.h mem.h rom.h nvr.h config.h machine/machine.h hdd/hdd_ide_at.h cdrom.h cdrom_null.h \ - cdrom_ioctl.h cdrom_image.h scsi/scsi.h scsi_disk.h video/video.h video/vid_ega.h mouse.h sound/sound.h sound/snd_dbopl.h \ - win/plat_keyboard.h win/plat_iodev.h win/plat_mouse.h win/plat_midi.h win/plat_thread.h win/plat_ticks.h win/plat_ui.h \ - win/resource.h win/win.h win/win_cgapal.h win/win_ddraw.h win/win_d3d.h win/win_language.h - -win_d3d.o: video/video.h win/win.h win/resource.h win/win_d3d.h win/win_cgapal.h - -win_d3d_fs.o: 86box.h video/video.h win/win.h win/resource.h win/win_d3d.h win/win_cgapal.h - -win_ddraw.o: video/video.h win/resource.h win/win_ddraw.h win/win_cgapal.h - -win_ddraw_fs.o: video/video.h win/resource.h win/win_ddraw.h win/win_cgapal.h - -win_ddraw_screenshot.o: video/video.h win/resource.h win/win.h win/win_ddraw.h win/win_language.h - -win_deviceconfig.o: win/plat_midi.h win/resource.h win/win.h win/win_language.h - -win_dynld.o: win/plat_dynld.h win/resource.h ibm.h - -win_iodev.o: ibm.h device.h cdrom.h cdrom_image.h cdrom_ioctl.h cdrom_null.h scsi/scsi_disk.h win/plat_iodev.h win/resource.h win/win.h - -win_joystick.o: device.h gameport.h win/plat_joystick.h win/resource.h win/win.h - -win_joystickconfig.o: ibm.h config.h device.h gameport.h win/plat_joystick.h win/resource.h win/win.h - -win_keyboard.o: device.h win/plat_keyboard.h win/resource.h win/win.h - -win_language.o: ibm.h device.h win/plat_ui.h win/resource.h win/win.h win/win_language.h - -win_midi.o: ibm.h config.h sound/midi.h win/plat_midi.h win/resource.h - -win_mouse.o: win/plat_mouse.h win/resource.h win/win.h - -win_opendir.o: ibm.h win/plat_dir.h win/resource.h - -win_serial.o: win/plat_thread.h win/plat_serial.h win/resource.h - -win_settings.o: ibm.h mem.h cpu/cpu.h nvr.h device.h machine/machine.h cdrom.h floppy.h fdd.h hdd/hdd.h hdd/hdd_ide_at.h scsi/scsi.h network/network.h sound/midi.h \ - sound/sound.h sound/snd_dbopl.h sound/snd_mpu401.h video/video.h video/vid_voodoo.h gameport.h mouse.h win/plat_midi.h \ - win/resource.h win/win.h win/win_language.h - -win_status.o: ibm.h mem.h cpu/x86_ops.h cpu/codegen.h device.h win/resource.h win/win.h - -win_video.o: video/video.h win/resource.h win/win_cgapal.h - - -# End of Makefile.mingw. diff --git a/src/bugger.c b/src/bugger.c index ce5ed03a9..75d5c983c 100644 --- a/src/bugger.c +++ b/src/bugger.c @@ -44,13 +44,18 @@ * configuration register (CTRL_SPCFG bit set) but have to * remember that stuff first... * - * Version: @(#)bugger.c 1.0.4 2017/05/09 + * Version: @(#)bugger.c 1.0.7 2017/10/09 * * Author: Fred N. van Kempen, * Copyright 1989-2017 Fred N. van Kempen. */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" +#include "ui.h" #include "bugger.h" @@ -99,7 +104,7 @@ bug_setui(void) (bug_ledr&0x02)?'R':'r', (bug_ledr&0x01)?'R':'r'); /* Send formatted string to the UI. */ - status_settext(bug_str); + ui_sb_set_text(bug_str); } diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 3986b1591..91bb614c6 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -9,24 +9,33 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.c 1.0.4 2017/09/03 + * Version: @(#)cdrom.c 1.0.17 2017/10/14 * * Author: Miran Grca, + * * Copyright 2016,2017 Miran Grca. */ -#include #include -#include #include #include +#include +#include +#include #include "../86box.h" +#include "../config.h" #include "../ibm.h" +#include "../timer.h" +#include "../device.h" #include "../piix.h" #include "../scsi/scsi.h" -#include "../timer.h" -#include "../hdd/hdd_ide_at.h" -#include "../win/plat_iodev.h" +#include "../nvr.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" +#include "../plat.h" +#include "../ui.h" #include "cdrom.h" +#include "cdrom_image.h" +#include "cdrom_null.h" /* Bits of 'status' */ @@ -41,12 +50,6 @@ #define ABRT_ERR 0x04 /* Command aborted */ #define MCR_ERR 0x08 /* Media change request */ -#define MODE_SELECT_PHASE_IDLE 0 -#define MODE_SELECT_PHASE_HEADER 1 -#define MODE_SELECT_PHASE_BLOCK_DESC 2 -#define MODE_SELECT_PHASE_PAGE_HEADER 3 -#define MODE_SELECT_PHASE_PAGE 4 - cdrom_t cdrom[CDROM_NUM]; cdrom_drive_t cdrom_drives[CDROM_NUM]; uint8_t atapi_cdrom_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; @@ -67,12 +70,9 @@ uint8_t scsi_cdrom_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; -#ifdef __MSC__ -# pragma pack(push,1) + +#pragma pack(push,1) static struct -#else -static struct __attribute__((__packed__)) -#endif { uint8_t opcode; uint8_t polled; @@ -82,24 +82,17 @@ static struct __attribute__((__packed__)) uint16_t len; uint8_t control; } *gesn_cdb; -#ifdef __MSC__ -# pragma pack(pop) -#endif +#pragma pack(pop) -#ifdef __MSC__ -# pragma pack(push,1) +#pragma pack(push,1) static struct -#else -static struct __attribute__((__packed__)) -#endif { uint16_t len; uint8_t notification_class; uint8_t supported_events; } *gesn_event_header; -#ifdef __MSC__ -# pragma pack(pop) -#endif +#pragma pack(pop) + /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ uint8_t cdrom_command_flags[0x100] = @@ -986,16 +979,16 @@ void cdrom_mode_sense_load(uint8_t id) switch(id) { case 0: - f = _wfopen(nvr_concat(L"cdrom_1_mode_sense.bin"), L"rb"); + f = plat_fopen(nvr_path(L"cdrom_1_mode_sense.bin"), L"rb"); break; case 1: - f = _wfopen(nvr_concat(L"cdrom_2_mode_sense.bin"), L"rb"); + f = plat_fopen(nvr_path(L"cdrom_2_mode_sense.bin"), L"rb"); break; case 2: - f = _wfopen(nvr_concat(L"cdrom_3_mode_sense.bin"), L"rb"); + f = plat_fopen(nvr_path(L"cdrom_3_mode_sense.bin"), L"rb"); break; case 3: - f = _wfopen(nvr_concat(L"cdrom_4_mode_sense.bin"), L"rb"); + f = plat_fopen(nvr_path(L"cdrom_4_mode_sense.bin"), L"rb"); break; default: return; @@ -1014,16 +1007,16 @@ void cdrom_mode_sense_save(uint8_t id) switch(id) { case 0: - f = _wfopen(nvr_concat(L"cdrom_1_mode_sense.bin"), L"wb"); + f = plat_fopen(nvr_path(L"cdrom_1_mode_sense.bin"), L"wb"); break; case 1: - f = _wfopen(nvr_concat(L"cdrom_2_mode_sense.bin"), L"wb"); + f = plat_fopen(nvr_path(L"cdrom_2_mode_sense.bin"), L"wb"); break; case 2: - f = _wfopen(nvr_concat(L"cdrom_3_mode_sense.bin"), L"wb"); + f = plat_fopen(nvr_path(L"cdrom_3_mode_sense.bin"), L"wb"); break; case 3: - f = _wfopen(nvr_concat(L"cdrom_4_mode_sense.bin"), L"wb"); + f = plat_fopen(nvr_path(L"cdrom_4_mode_sense.bin"), L"wb"); break; default: return; @@ -1431,23 +1424,23 @@ static void cdrom_command_common(uint8_t id) cdrom[id].pos = 0; if (cdrom[id].packet_status == CDROM_PHASE_COMPLETE) { - cdrom[id].callback = 20 * CDROM_TIME; + cdrom[id].callback = 20LL * CDROM_TIME; } else if (cdrom[id].packet_status == CDROM_PHASE_DATA_IN) { if (cdrom[id].current_cdb[0] == 0x42) { cdrom_log("CD-ROM %i: READ SUBCHANNEL\n"); - cdrom[id].callback = 1000 * CDROM_TIME; + cdrom[id].callback = 1000LL * CDROM_TIME; } else { - cdrom[id].callback = 60 * CDROM_TIME; + cdrom[id].callback = 60LL * CDROM_TIME; } } else { - cdrom[id].callback = 60 * CDROM_TIME; + cdrom[id].callback = 60LL * CDROM_TIME; } } @@ -1505,11 +1498,7 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al } if (cdrom_request_length_is_zero(id) || (len == 0) || (cdrom_current_mode(id) == 0)) { - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - { - SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = 0; - } - else + if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) { cdrom[id].init_length = 0; } @@ -1521,11 +1510,7 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al { if (direction == 0) { - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - { - SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = alloc_len; - } - else + if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) { cdrom[id].init_length = alloc_len; } @@ -1561,6 +1546,7 @@ static void cdrom_sense_clear(int id, int command) static void cdrom_cmd_error(uint8_t id) { + SCSIPhase = SCSI_PHASE_STATUS; cdrom[id].error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR; if (cdrom[id].unit_attention) { @@ -1569,12 +1555,13 @@ static void cdrom_cmd_error(uint8_t id) cdrom[id].status = READY_STAT | ERR_STAT; cdrom[id].phase = 3; cdrom[id].packet_status = 0x80; - cdrom[id].callback = 50 * CDROM_TIME; + cdrom[id].callback = 50LL * CDROM_TIME; cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", id, cdrom_sense_key, cdrom_asc, cdrom_ascq); } static void cdrom_unit_attention(uint8_t id) { + SCSIPhase = SCSI_PHASE_STATUS; cdrom[id].error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; if (cdrom[id].unit_attention) { @@ -1583,7 +1570,7 @@ static void cdrom_unit_attention(uint8_t id) cdrom[id].status = READY_STAT | ERR_STAT; cdrom[id].phase = 3; cdrom[id].packet_status = 0x80; - cdrom[id].callback = 50 * CDROM_TIME; + cdrom[id].callback = 50LL * CDROM_TIME; cdrom_log("CD-ROM %i: UNIT ATTENTION\n", id); } @@ -1920,7 +1907,7 @@ static int cdrom_read_dvd_structure(uint8_t id, int format, const uint8_t *packe case 0x00: /* Physical format information */ total_sectors = (uint64_t) cdrom_drives[id].handler->size(id); - if (layer != 0) + if (layer != 0) { cdrom_invalid_field(id); return 0; @@ -2020,47 +2007,6 @@ static int cdrom_read_dvd_structure(uint8_t id, int format, const uint8_t *packe } } -/*SCSI Get Event Status Notification*/ -static uint32_t cdrom_get_event_status(uint8_t id, uint8_t *buffer) -{ - uint8_t event_code, media_status = 0; - - if (buffer[5]) - { - media_status = MS_TRAY_OPEN; - if (cdrom_drives[id].handler->stop) - { - cdrom_drives[id].handler->stop(id); - } - } - else - { - media_status = MS_MEDIA_PRESENT; - } - - event_code = MEC_NO_CHANGE; - if (media_status != MS_TRAY_OPEN) - { - if (!buffer[4]) - { - event_code = MEC_NEW_MEDIA; - cdrom_drives[id].handler->load(id); - } - else if (buffer[4]==2) - { - event_code = MEC_EJECT_REQUESTED; - cdrom_drives[id].handler->eject(id); - } - } - - buffer[4] = event_code; - buffer[5] = media_status; - buffer[6] = 0; - buffer[7] = 0; - - return 8; -} - void cdrom_insert(uint8_t id) { cdrom[id].unit_attention = 1; @@ -2164,6 +2110,15 @@ skip_ready_check: } /* Next it's time for NOT READY. */ + if (!ready) + { + cdrom[id].media_status = MEC_MEDIA_REMOVAL; + } + else + { + cdrom[id].media_status = (cdrom[id].unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + } + if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { cdrom_log("CD-ROM %i: Not ready (%02X)\n", id, cdb[0]); @@ -2182,7 +2137,7 @@ void cdrom_clear_callback(uint8_t channel) if (id <= CDROM_NUM) { - cdrom[id].callback = 0; + cdrom[id].callback = 0LL; } } @@ -2210,7 +2165,7 @@ void cdrom_reset(uint8_t id) { cdrom_rezero(id); cdrom[id].status = 0; - cdrom[id].callback = 0; + cdrom[id].callback = 0LL; cdrom[id].packet_status = 0xff; cdrom[id].unit_attention = 0; } @@ -2262,7 +2217,7 @@ void cdrom_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length) } } - /* cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", id, cdbufferb[2], cdbufferb[12], cdbufferb[13]); */ + cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); if (buffer[2] == SENSE_UNIT_ATTENTION) { @@ -2321,16 +2276,20 @@ void cdrom_command(uint8_t id, uint8_t *cdb) int track = 0; char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + int32_t blen = 0; + int32_t *BufLen; -#if 0 +#if 1 int CdbLength; #endif if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { + BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength; cdrom[id].status &= ~ERR_STAT; } else { + BufLen = &blen; cdrom[id].error = 0; } @@ -2355,10 +2314,10 @@ void cdrom_command(uint8_t id, uint8_t *cdb) cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, ins, cdrom[id].unit_attention); cdrom_log("CD-ROM %i: Request length: %04X\n", id, cdrom[id].request_length); -#if 0 +#if 1 for (CdbLength = 1; CdbLength < cdrom[id].cdb_len; CdbLength++) { - cdrom_log("CD-ROM %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]); + cdrom_log("CD-ROM %i: CDB[%d] = %d\n", id, CdbLength, cdb[CdbLength]); } #endif } @@ -2366,6 +2325,8 @@ void cdrom_command(uint8_t id, uint8_t *cdb) msf = cdb[1] & 2; cdrom[id].sector_len = 0; + SCSIPhase = SCSI_PHASE_STATUS; + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ if (cdrom_pre_execution_check(id, cdb) == 0) { @@ -2375,6 +2336,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) switch (cdb[0]) { case GPCMD_TEST_UNIT_READY: + SCSIPhase = SCSI_PHASE_STATUS; cdrom_command_complete(id); break; @@ -2385,16 +2347,22 @@ void cdrom_command(uint8_t id, uint8_t *cdb) } cdrom[id].sector_pos = cdrom[id].sector_len = 0; cdrom_seek(id, 0); + SCSIPhase = SCSI_PHASE_STATUS; break; case GPCMD_REQUEST_SENSE: /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE should forget about the not ready, and report unit attention straight away. */ + SCSIPhase = SCSI_PHASE_DATA_IN; if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength < cdb[4]) + if ((*BufLen == -1) || (cdb[4] < *BufLen)) { - cdb[4] = SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength; + *BufLen = cdb[4]; + } + if (*BufLen < cdb[4]) + { + cdb[4] = *BufLen; } } cdrom_request_sense(id, cdbufferb, cdb[4]); @@ -2403,12 +2371,20 @@ void cdrom_command(uint8_t id, uint8_t *cdb) case GPCMD_SET_SPEED: case GPCMD_SET_SPEED_ALT: + SCSIPhase = SCSI_PHASE_STATUS; cdrom_command_complete(id); break; case GPCMD_MECHANISM_STATUS: + SCSIPhase = SCSI_PHASE_DATA_IN; + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + memset(cdbufferb, 0, 8); cdbufferb[5] = 1; @@ -2418,6 +2394,8 @@ void cdrom_command(uint8_t id, uint8_t *cdb) case GPCMD_READ_TOC_PMA_ATIP: cdrom[id].toctimes++; + SCSIPhase = SCSI_PHASE_DATA_IN; + max_len = cdb[7]; max_len <<= 8; max_len |= cdb[8]; @@ -2431,6 +2409,13 @@ void cdrom_command(uint8_t id, uint8_t *cdb) cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; goto cdrom_readtoc_fallback; } + else + { + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + } alloc_length = cdbufferb[0]; alloc_length <<= 8; alloc_length |= cdbufferb[1]; @@ -2476,6 +2461,11 @@ cdrom_readtoc_fallback: cdbufferb[1] = (len - 2) & 0xff; } + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + cdrom_data_command_finish(id, len, len, len, 0); /* cdrom_log("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", id, toc_format, ide->cylinder, cdbufferb[1]); */ return; @@ -2487,6 +2477,8 @@ cdrom_readtoc_fallback: case GPCMD_READ_12: case GPCMD_READ_CD: case GPCMD_READ_CD_MSF: + SCSIPhase = SCSI_PHASE_DATA_IN; + switch(cdb[0]) { case GPCMD_READ_6: @@ -2526,9 +2518,10 @@ cdrom_readtoc_fallback: if (!cdrom[id].sector_len) { + SCSIPhase = SCSI_PHASE_STATUS; /* cdrom_log("CD-ROM %i: All done - callback set\n", id); */ cdrom[id].packet_status = CDROM_PHASE_COMPLETE; - cdrom[id].callback = 20 * CDROM_TIME; + cdrom[id].callback = 20LL * CDROM_TIME; break; } @@ -2550,6 +2543,12 @@ cdrom_readtoc_fallback: } cdrom[id].packet_len = max_len * alloc_length; + + if ((*BufLen == -1) || (cdrom[id].packet_len < *BufLen)) + { + *BufLen = cdrom[id].packet_len; + } + if (cdrom[id].requested_blocks > 1) { cdrom_data_command_finish(id, alloc_length, alloc_length / cdrom[id].requested_blocks, alloc_length, 0); @@ -2561,15 +2560,17 @@ cdrom_readtoc_fallback: cdrom[id].all_blocks_total = cdrom[id].block_total; if (cdrom[id].packet_status != CDROM_PHASE_COMPLETE) { - update_status_bar_icon(SB_CDROM | id, 1); + ui_sb_update_icon(SB_CDROM | id, 1); } else { - update_status_bar_icon(SB_CDROM | id, 0); + ui_sb_update_icon(SB_CDROM | id, 0); } return; case GPCMD_READ_HEADER: + SCSIPhase = SCSI_PHASE_DATA_IN; + if (cdrom_drives[id].handler->pass_through) { ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); @@ -2577,6 +2578,13 @@ cdrom_readtoc_fallback: { return; } + else + { + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + } } else { @@ -2600,11 +2608,18 @@ cdrom_readtoc_fallback: len = 8; } + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + cdrom_data_command_finish(id, len, len, len, 0); return; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: + SCSIPhase = SCSI_PHASE_DATA_IN; + if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; @@ -2674,6 +2689,11 @@ cdrom_readtoc_fallback: alloc_length = len; } + if ((*BufLen == -1) || (alloc_length < *BufLen)) + { + *BufLen = alloc_length; + } + cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", id, cdb[2]); cdrom_data_command_finish(id, len, len, alloc_length, 0); @@ -2681,6 +2701,8 @@ cdrom_readtoc_fallback: case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: + SCSIPhase = SCSI_PHASE_DATA_OUT; + if (cdb[0] == GPCMD_MODE_SELECT_6) { len = cdb[4]; @@ -2690,12 +2712,19 @@ cdrom_readtoc_fallback: len = (cdb[7] << 8) | cdb[8]; } + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + ret = cdrom_mode_select_init(id, cdb[0], len, cdb[1] & 1); cdrom_data_command_finish(id, len, len, len, 1); return; case GPCMD_GET_CONFIGURATION: + SCSIPhase = SCSI_PHASE_DATA_IN; + /* XXX: could result in alignment problems in some architectures */ len = (cdb[7] << 8) | cdb[8]; alloc_length = len; @@ -2745,10 +2774,17 @@ cdrom_readtoc_fallback: cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff; cdbufferb[3] = (alloc_length - 4) & 0xff; + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + cdrom_data_command_finish(id, len, len, alloc_length, 0); break; case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + SCSIPhase = SCSI_PHASE_DATA_IN; + gesn_cdb = (void *) cdb; gesn_event_header = (void *) cdbufferb; @@ -2788,7 +2824,12 @@ cdrom_readtoc_fallback: if (gesn_cdb->class & (1 << GESN_MEDIA)) { gesn_event_header->notification_class |= GESN_MEDIA; - used_len = cdrom_get_event_status(id, cdbufferb); + + cdbufferb[4] = cdrom[id].media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ + cdbufferb[5] = 1; /* Power Status (1 = Active) */ + cdbufferb[6] = 0; + cdbufferb[7] = 0; + used_len = 8; } else { @@ -2797,10 +2838,19 @@ cdrom_readtoc_fallback: } gesn_event_header->len = used_len - sizeof(*gesn_event_header); + memcpy(cdbufferb, gesn_event_header, 4); + + if ((*BufLen == -1) || (used_len < *BufLen)) + { + *BufLen = used_len; + } + cdrom_data_command_finish(id, used_len, used_len, used_len, 0); break; case GPCMD_READ_DISC_INFORMATION: + SCSIPhase = SCSI_PHASE_DATA_IN; + max_len = cdb[7]; max_len <<= 8; max_len |= cdb[8]; @@ -2834,10 +2884,18 @@ cdrom_readtoc_fallback: len=34; } + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + cdrom_data_command_finish(id, len, len, max_len, 0); + SCSIPhase = BUS_IO; break; case GPCMD_READ_TRACK_INFORMATION: + SCSIPhase = SCSI_PHASE_DATA_IN; + max_len = cdb[7]; max_len <<= 8; max_len |= cdb[8]; @@ -2894,13 +2952,21 @@ cdrom_readtoc_fallback: } } + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + cdrom_data_command_finish(id, len, len, max_len, 0); + SCSIPhase = BUS_IO; break; case GPCMD_PLAY_AUDIO_10: case GPCMD_PLAY_AUDIO_12: case GPCMD_PLAY_AUDIO_MSF: case GPCMD_PLAY_AUDIO_TRACK_INDEX: + SCSIPhase = SCSI_PHASE_STATUS; + switch(cdb[0]) { case GPCMD_PLAY_AUDIO_10: @@ -2947,6 +3013,8 @@ cdrom_readtoc_fallback: break; case GPCMD_READ_SUBCHANNEL: + SCSIPhase = SCSI_PHASE_DATA_IN; + max_len = cdb[7]; max_len <<= 8; max_len |= cdb[8]; @@ -3053,10 +3121,17 @@ cdrom_readtoc_fallback: } } + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + cdrom_data_command_finish(id, len, len, max_len, 0); break; case GPCMD_READ_DVD_STRUCTURE: + SCSIPhase = SCSI_PHASE_DATA_IN; + if (cdrom_drives[id].handler->pass_through) { ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); @@ -3064,6 +3139,13 @@ cdrom_readtoc_fallback: { return; } + else + { + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + } } else { @@ -3109,6 +3191,11 @@ cdrom_readtoc_fallback: { ret = cdrom_read_dvd_structure(id, format, cdb, cdbufferb); + if ((*BufLen == -1) || (alloc_length < *BufLen)) + { + *BufLen = alloc_length; + } + if (ret) { cdrom_data_command_finish(id, len, len, alloc_length, 0); @@ -3132,6 +3219,8 @@ cdrom_readtoc_fallback: break; case GPCMD_START_STOP_UNIT: + SCSIPhase = SCSI_PHASE_STATUS; + switch(cdb[4] & 3) { case 0: /* Stop the disc. */ @@ -3159,6 +3248,8 @@ cdrom_readtoc_fallback: break; case GPCMD_INQUIRY: + SCSIPhase = SCSI_PHASE_DATA_IN; + max_len = cdb[3]; max_len <<= 8; max_len |= cdb[4]; @@ -3237,15 +3328,23 @@ atapi_out: cdbufferb[size_idx] = idx - preamble_len; len=idx; + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + cdrom_data_command_finish(id, len, len, max_len, 0); break; case GPCMD_PREVENT_REMOVAL: + SCSIPhase = SCSI_PHASE_STATUS; cdrom_command_complete(id); break; case GPCMD_PAUSE_RESUME_ALT: case GPCMD_PAUSE_RESUME: + SCSIPhase = SCSI_PHASE_STATUS; + if (cdb[8] & 1) { if (cdrom_drives[id].handler->resume) @@ -3275,6 +3374,8 @@ atapi_out: case GPCMD_SEEK_6: case GPCMD_SEEK_10: + SCSIPhase = SCSI_PHASE_STATUS; + switch(cdb[0]) { case GPCMD_SEEK_6: @@ -3289,15 +3390,24 @@ atapi_out: break; case GPCMD_READ_CDROM_CAPACITY: + SCSIPhase = SCSI_PHASE_DATA_IN; + if (cdrom_read_capacity(id, cdrom[id].current_cdb, cdbufferb, &len) == 0) { return; } + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + cdrom_data_command_finish(id, len, len, len, 0); break; case GPCMD_STOP_PLAY_SCAN: + SCSIPhase = SCSI_PHASE_STATUS; + if (cdrom_drives[id].handler->stop) { cdrom_drives[id].handler->stop(id); @@ -3482,6 +3592,7 @@ int cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) uint8_t *cdbufferb; uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; + int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; cdbufferb = (uint8_t *) cdrom[id].buffer; @@ -3490,14 +3601,15 @@ int cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) return 0; } - cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id][scsi_lun].InitLength); - memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, SCSIDevices[scsi_id][scsi_lun].InitLength); + cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); return 1; } int cdrom_read_from_dma(uint8_t id) { uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer; + int32_t *BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength; int i = 0; int ret = 0; @@ -3520,7 +3632,7 @@ int cdrom_read_from_dma(uint8_t id) if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - in_data_length = SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength; + in_data_length = *BufLen; cdrom_log("CD-ROM %i: SCSI Input data length: %i\n", id, in_data_length); } else @@ -3605,6 +3717,7 @@ int cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) uint8_t *cdbufferb; uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; + int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; if (id > CDROM_NUM) { @@ -3613,8 +3726,8 @@ int cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) cdbufferb = (uint8_t *) cdrom[id].buffer; - cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id][scsi_lun].InitLength); - memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, SCSIDevices[scsi_id][scsi_lun].InitLength); + cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, *BufLen); cdrom_log("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); cdrom_log("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); return 1; @@ -3626,6 +3739,7 @@ int cdrom_write_to_dma(uint8_t id) if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { + cdrom_log("Write to SCSI DMA: (%02X:%02X)\n", cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); ret = cdrom_write_to_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); } else @@ -3671,7 +3785,7 @@ void cdrom_phase_callback(uint8_t id) cdrom[id].status = READY_STAT; cdrom[id].phase = 3; cdrom[id].packet_status = 0xFF; - update_status_bar_icon(SB_CDROM | id, 0); + ui_sb_update_icon(SB_CDROM | id, 0); cdrom_irq_raise(id); return; case CDROM_PHASE_DATA_OUT: @@ -3686,7 +3800,7 @@ void cdrom_phase_callback(uint8_t id) cdrom[id].packet_status = CDROM_PHASE_COMPLETE; cdrom[id].status = READY_STAT; cdrom[id].phase = 3; - update_status_bar_icon(SB_CDROM | id, 0); + ui_sb_update_icon(SB_CDROM | id, 0); cdrom_irq_raise(id); return; case CDROM_PHASE_DATA_IN: @@ -3701,7 +3815,7 @@ void cdrom_phase_callback(uint8_t id) cdrom[id].packet_status = CDROM_PHASE_COMPLETE; cdrom[id].status = READY_STAT; cdrom[id].phase = 3; - update_status_bar_icon(SB_CDROM | id, 0); + ui_sb_update_icon(SB_CDROM | id, 0); cdrom_irq_raise(id); return; case CDROM_PHASE_ERROR: @@ -3854,3 +3968,79 @@ void cdrom_write(uint8_t channel, uint32_t val, int length) return; } } + +void cdrom_hard_reset(void) +{ + int i = 0; + + for (i=0; i= 'A') && (cdrom_drives[i].host_drive <= 'Z')) + { + ioctl_reset(i); + } + } +} + + +/* Peform a master init on the entire module. */ +void +cdrom_global_init(void) +{ + int c; + + /* Clear the global data. */ + memset(cdrom, 0x00, sizeof(cdrom)); + memset(cdrom_drives, 0x00, sizeof(cdrom_drives)); + + /* Initialize the host devices, if any. */ + cdrom_init_host_drives(); + + /* Set all drives to NULL mode. */ + for (c=0; c='A') && (cdrom_drives[c].host_drive <= 'Z')) { + ioctl_open(c, cdrom_drives[c].host_drive); + } else { + cdrom_null_open(c, cdrom_drives[c].host_drive); + } + } +} + + +void +cdrom_close(uint8_t id) +{ + switch (cdrom_drives[id].host_drive) { + case 0: + null_close(id); + break; + + case 200: + image_close(id); + break; + + default: + ioctl_close(id); + break; + } +} diff --git a/src/cdrom/cdrom.h b/src/cdrom/cdrom.h index bd1d99783..dfdd70977 100644 --- a/src/cdrom/cdrom.h +++ b/src/cdrom/cdrom.h @@ -9,10 +9,11 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.h 1.0.1 2017/06/03 + * Version: @(#)cdrom.h 1.0.2 2017/10/12 * * Author: Miran Grca, - * Copyright 2016-2017 Miran Grca. + * + * Copyright 2016,2017 Miran Grca. */ #ifndef EMU_CDROM_H #define EMU_CDROM_H @@ -33,14 +34,15 @@ #define CDROM_IMAGE 200 -#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) -#define CDROM_TIME (5 * 100 * (1 << TIMER_SHIFT)) +#define IDE_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) +#define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) typedef struct { int (*ready)(uint8_t id); int (*medium_changed)(uint8_t id); int (*media_type_id)(uint8_t id); + void (*audio_callback)(uint8_t id, int16_t *output, int len); void (*audio_stop)(uint8_t id); int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); @@ -61,10 +63,11 @@ typedef struct { void (*exit)(uint8_t id); } CDROM; -#pragma pack(push,1) typedef struct { uint8_t previous_command; + int toctimes; + int media_status; int is_dma; @@ -130,9 +133,7 @@ typedef struct { int init_length; } cdrom_t; -#pragma pack(pop) -#pragma pack(push,1) typedef struct { int max_blocks_at_once; @@ -153,7 +154,6 @@ typedef struct { unsigned int sound_on; unsigned int atapi_dma; } cdrom_drive_t; -#pragma pack(pop) typedef struct { int image_is_iso; @@ -227,14 +227,15 @@ int cdrom_lba_to_msf_accurate(int lba); } #endif -void cdrom_reset(uint8_t id); -void cdrom_set_signature(int id); -void cdrom_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); -void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); -void cdrom_insert(uint8_t id); +extern void cdrom_close(uint8_t id); +extern void cdrom_reset(uint8_t id); +extern void cdrom_set_signature(int id); +extern void cdrom_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); +extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); +extern void cdrom_insert(uint8_t id); -int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); +extern int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); +extern int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); #define cdrom_sense_error cdrom[id].sense[0] #define cdrom_sense_key cdrom[id].sense[2] @@ -242,5 +243,9 @@ int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len #define cdrom_ascq cdrom[id].sense[13] #define cdrom_drive cdrom_drives[id].host_drive +extern void cdrom_global_init(void); +extern void cdrom_global_reset(void); +extern void cdrom_hard_reset(void); + #endif /*EMU_CDROM_H*/ diff --git a/src/cdrom/cdrom_dosbox.cpp b/src/cdrom/cdrom_dosbox.cpp index 0b2ea24c6..a8b1ef389 100644 --- a/src/cdrom/cdrom_dosbox.cpp +++ b/src/cdrom/cdrom_dosbox.cpp @@ -20,7 +20,10 @@ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE -#define _GNU_SOURCE +#ifdef WIN32 +//FIXME: should not be needed. */ +# define _GNU_SOURCE +#endif #include #include diff --git a/src/cdrom/cdrom_image.cc b/src/cdrom/cdrom_image.cc index bee50d072..a2da43dee 100644 --- a/src/cdrom/cdrom_image.cc +++ b/src/cdrom/cdrom_image.cc @@ -6,9 +6,13 @@ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE +#include +#include +#include +#include #include -#include #include "../config.h" +#include "../plat.h" #include "cdrom_dosbox.h" #include "cdrom.h" #include "cdrom_image.h" @@ -987,10 +991,10 @@ int image_open(uint8_t id, wchar_t *fn) if (!cdrom_image[id].image_inited || cdrom_image[id].image_changed) { - _swprintf(cdrom_image[id].image_path, L"%ws", fn); + swprintf(cdrom_image[id].image_path, sizeof(cdrom_image[id].image_path)/sizeof(wchar_t), L"%ls", fn); } - if (!wcsicmp(get_extension_w(fn), L"ISO")) + if (! wcscasecmp(get_extension_w(fn), L"ISO")) { cdrom_image[id].image_is_iso = 1; } diff --git a/src/cdrom/cdrom_ioctl.h b/src/cdrom/cdrom_ioctl.h deleted file mode 100644 index a81d773b8..000000000 --- a/src/cdrom/cdrom_ioctl.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Implementation of the CD-ROM host drive IOCTL interface for - * Windows using SCSI Passthrough Direct. - * - * This file lists the functions provided by various platform- - * specific cdrom-ioctl files. - * - * Version: @(#)cdrom_ioctl.h 1.0.3 2017/09/03 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2016 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#ifndef EMU_CDROM_IOCTL_H -#define EMU_CDROM_IOCTL_H - - -extern uint32_t cdrom_capacity; - - -extern int ioctl_open(uint8_t id, char d); -extern void ioctl_reset(uint8_t id); - -extern void ioctl_close(uint8_t id); - - -#endif /*EMU_CDROM_IOCTL_H */ diff --git a/src/cdrom/cdrom_null.c b/src/cdrom/cdrom_null.c index f0bc68f0c..28d383100 100644 --- a/src/cdrom/cdrom_null.c +++ b/src/cdrom/cdrom_null.c @@ -9,139 +9,181 @@ * Implementation of the CD-ROM null interface for unmounted * guest CD-ROM drives. * - * Version: @(#)cdrom_null.c 1.0.2 2017/09/03 + * Version: @(#)cdrom_null.c 1.0.4 2017/10/09 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2016 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "../ibm.h" #include "cdrom.h" -#include "cdrom_ioctl.h" static CDROM null_cdrom; -static int null_ready(uint8_t id) +static int +null_ready(uint8_t id) { - return 0; + return(0); } + /* Always return 0, the contents of a null CD-ROM drive never change. */ -static int null_medium_changed(uint8_t id) +static int +null_medium_changed(uint8_t id) { - return 0; + return(0); } -static uint8_t null_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) + +static uint8_t +null_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) { - return 0x13; + return(0x13); } -static void null_eject(uint8_t id) + +static void +null_eject(uint8_t id) { } -static void null_load(uint8_t id) + +static void +null_load(uint8_t id) { } -static int null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) +static int +null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) { - *len = 0; - return 0; + *len = 0; + + return(0); } -static int null_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) + +static int +null_readtoc(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single) { - return 0; + return(0); } -static int null_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) + +static int +null_readtoc_session(uint8_t id, uint8_t *b, int msf, int maxlen) { - return 0; + return(0); } -static int null_readtoc_raw(uint8_t id, unsigned char *b, int maxlen) + +static int +null_readtoc_raw(uint8_t id, uint8_t *b, int maxlen) { - return 0; + return(0); } -static uint32_t null_size(uint8_t id) + +static uint32_t +null_size(uint8_t id) { - return 0; + return(0); } -static int null_status(uint8_t id) + +static int +null_status(uint8_t id) { - return CD_STATUS_EMPTY; + return(CD_STATUS_EMPTY); } -void cdrom_null_reset(uint8_t id) + +void +cdrom_null_reset(uint8_t id) { } + void cdrom_set_null_handler(uint8_t id); -int cdrom_null_open(uint8_t id, char d) +int +cdrom_null_open(uint8_t id, char d) { - cdrom_set_null_handler(id); - return 0; + cdrom_set_null_handler(id); + + return(0); } -void null_close(uint8_t id) + +void +null_close(uint8_t id) { } -static void null_exit(uint8_t id) + +static +void null_exit(uint8_t id) { } -static int null_is_track_audio(uint8_t id, uint32_t pos, int ismsf) + +static int +null_is_track_audio(uint8_t id, uint32_t pos, int ismsf) { - return 0; + return(0); } -static int null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) + +static int +null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) { - return 0; + return(0); } -static int null_media_type_id(uint8_t id) + +static int +null_media_type_id(uint8_t id) { - return 0x70; + return(0x70); } -void cdrom_set_null_handler(uint8_t id) + +void +cdrom_set_null_handler(uint8_t id) { - cdrom_drives[id].handler = &null_cdrom; - cdrom_drives[id].host_drive = 0; - memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); + cdrom_drives[id].handler = &null_cdrom; + cdrom_drives[id].host_drive = 0; + memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); } -static CDROM null_cdrom = -{ - null_ready, - null_medium_changed, - null_media_type_id, - NULL, - NULL, - null_readtoc, - null_readtoc_session, - null_readtoc_raw, - null_getcurrentsubchannel, - null_pass_through, - null_readsector_raw, - NULL, - null_load, - null_eject, - NULL, - NULL, - null_size, - null_status, - null_is_track_audio, - NULL, - null_exit + +static CDROM null_cdrom = { + null_ready, + null_medium_changed, + null_media_type_id, + NULL, + NULL, + null_readtoc, + null_readtoc_session, + null_readtoc_raw, + null_getcurrentsubchannel, + null_pass_through, + null_readsector_raw, + NULL, + null_load, + null_eject, + NULL, + NULL, + null_size, + null_status, + null_is_track_audio, + NULL, + null_exit }; diff --git a/src/config.c b/src/config.c index 89b84d199..3ba7b842e 100644 --- a/src/config.c +++ b/src/config.c @@ -8,2620 +8,2038 @@ * * Configuration file handler. * - * Version: @(#)config.c 1.0.4 2017/09/03 + * Version: @(#)config.c 1.0.21 2017/10/13 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * Overdoze, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. * Copyright 2017 Fred N. van Kempen. * - * NOTE: Forcing config files to be in Unicode encoding breaks it on - * Windows XP, and possibly also Vista. Use -DANSI_CFG for use - * on these systems. + * NOTE: Forcing config files to be in Unicode encoding breaks + * it on Windows XP, and possibly also Vista. Use the + * -DANSI_CFG for use on these systems. */ -#include #include #include #include #include +#include +#include #include "ibm.h" #include "cpu/cpu.h" +#include "nvr.h" #include "config.h" #include "device.h" -#include "gameport.h" #include "lpt.h" -#include "nvr.h" #include "cdrom/cdrom.h" +#include "disk/hdd.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" #include "floppy/floppy.h" #include "floppy/fdc.h" #include "floppy/fdd.h" -#include "hdd/hdd.h" -#include "hdd/hdd_ide_at.h" +#include "game/gameport.h" #include "machine/machine.h" #include "mouse.h" -#ifdef USE_NETWORK #include "network/network.h" -#endif #include "scsi/scsi.h" -#include "win/plat_joystick.h" -#include "win/plat_midi.h" #include "sound/midi.h" #include "sound/snd_dbopl.h" #include "sound/snd_mpu401.h" #include "sound/snd_opl.h" #include "sound/sound.h" #include "video/video.h" -#include "win/win.h" -#include "win/win_language.h" +#include "plat.h" +#include "plat_joystick.h" +#include "plat_midi.h" +#include "ui.h" + + +typedef struct _list_ { + struct _list_ *next; +} list_t; + +typedef struct { + list_t list; + + char name[128]; + + list_t entry_head; +} section_t; + +typedef struct { + list_t list; + + char name[128]; + char data[256]; + wchar_t wdata[512]; +} entry_t; + +#define list_add(new, head) { \ + list_t *next = head; \ + \ + while (next->next != NULL) \ + next = next->next; \ + \ + (next)->next = new; \ + (new)->next = NULL; \ +} + +#define list_delete(old, head) { \ + list_t *next = head; \ + \ + while ((next)->next != old) { \ + next = (next)->next; \ + } \ + \ + (next)->next = (old)->next; \ +} wchar_t config_file_default[256]; -static wchar_t config_file[256]; +static list_t config_head; -typedef struct list_t +static section_t * +find_section(char *name) { - struct list_t *next; -} list_t; + section_t *sec; + char blank[] = ""; -static list_t config_head; + sec = (section_t *)config_head.next; + if (name == NULL) + name = blank; -typedef struct section_t + while (sec != NULL) { + if (! strncmp(sec->name, name, sizeof(sec->name))) + return(sec); + + sec = (section_t *)sec->list.next; + } + + return(NULL); +} + + +static entry_t * +find_entry(section_t *section, char *name) { - struct list_t list; - - char name[256]; - - struct list_t entry_head; -} section_t; + entry_t *ent; -typedef struct entry_t + ent = (entry_t *)section->entry_head.next; + + while (ent != NULL) { + if (! strncmp(ent->name, name, sizeof(ent->name))) + return(ent); + + ent = (entry_t *)ent->list.next; + } + + return(NULL); +} + + +static int +entries_num(section_t *section) { - struct list_t list; - - char name[256]; - char data[256]; - wchar_t wdata[256]; -} entry_t; + entry_t *ent; + int i = 0; -#define list_add(new, head) \ - { \ - struct list_t *next = head; \ - \ - while (next->next) \ - next = next->next; \ - \ - (next)->next = new; \ - (new)->next = NULL; \ - } + ent = (entry_t *)section->entry_head.next; -#define list_delete(old, head) \ - { \ - struct list_t *next = head; \ - \ - while ((next)->next != old) \ - { \ - next = (next)->next; \ - } \ - \ - (next)->next = (old)->next; \ - } + while (ent != NULL) { + if (strlen(ent->name) > 0) i++; + + ent = (entry_t *)ent->list.next; + } + + return(i); +} -void config_dump(void) +static void +delete_section_if_empty(char *head) { - section_t *current_section; - - pclog("Config data :\n"); - - current_section = (section_t *)config_head.next; - - while (current_section) - { - entry_t *current_entry; - - pclog("[%s]\n", current_section->name); - - current_entry = (entry_t *)current_section->entry_head.next; - - while (current_entry) - { - pclog("%s = %s\n", current_entry->name, current_entry->data); + section_t *section; - current_entry = (entry_t *)current_entry->list.next; - } + section = find_section(head); + if (section == NULL) return; - current_section = (section_t *)current_section->list.next; - } + if (entries_num(section) == 0) { + list_delete(§ion->list, &config_head); + free(section); + } +} + + +static section_t * +create_section(char *name) +{ + section_t *ns = malloc(sizeof(section_t)); + + memset(ns, 0x00, sizeof(section_t)); + strncpy(ns->name, name, sizeof(ns->name)); + list_add(&ns->list, &config_head); + + return(ns); +} + + +static entry_t * +create_entry(section_t *section, char *name) +{ + entry_t *ne = malloc(sizeof(entry_t)); + + memset(ne, 0x00, sizeof(entry_t)); + strncpy(ne->name, name, sizeof(ne->name)); + list_add(&ne->list, §ion->entry_head); + + return(ne); } #if 0 -static void config_free(void) +static void +config_free(void) { - section_t *current_section; - current_section = (section_t *)config_head.next; - - while (current_section) - { - section_t *next_section = (section_t *)current_section->list.next; - entry_t *current_entry; - - current_entry = (entry_t *)current_section->entry_head.next; - - while (current_entry) - { - entry_t *next_entry = (entry_t *)current_entry->list.next; - - free(current_entry); - current_entry = next_entry; - } + section_t *sec, *ns; + entry_t *ent; - free(current_section); - current_section = next_section; - } -} -#endif + sec = (section_t *)config_head.next; + while (sec != NULL) { + ns = (section_t *)sec->list.next; + ent = (entry_t *)sec->entry_head.next; + while (ent != NULL) { + entry_t *nent = (entry_t *)ent->list.next; -static wchar_t cfgbuffer[1024]; -static char sname[256]; -static char ename[256]; - -int config_load(wchar_t *fn) -{ - section_t *current_section; - section_t *new_section; - entry_t *new_entry; - FILE *f; - int c; - int sd = 0, ed = 0, data_pos; - -#ifdef ANSI_CFG - f = _wfopen(fn, L"rt"); -#else - f = _wfopen(fn, L"rt, ccs=UNICODE"); -#endif - if (!f) - return 0; - - current_section = malloc(sizeof(section_t)); - memset(current_section, 0x00, sizeof(section_t)); - memset(&config_head, 0x00, sizeof(list_t)); - list_add(¤t_section->list, &config_head); - - while (1) - { - memset(cfgbuffer, 0, 2048); - fgetws(cfgbuffer, 255, f); - if (feof(f)) break; - - c = 0; - - while (cfgbuffer[c] == L' ') - c++; - - if (cfgbuffer[c] == L'\0') continue; - - if (cfgbuffer[c] == L'#') /*Comment*/ - continue; - - if (cfgbuffer[c] == L'[') /*Section*/ - { - sd = 0; - c++; - while (cfgbuffer[c] != L']' && cfgbuffer[c]) - wctomb(&(sname[sd++]), cfgbuffer[c++]); - - if (cfgbuffer[c] != L']') - continue; - sname[sd] = 0; - - new_section = malloc(sizeof(section_t)); - memset(new_section, 0, sizeof(section_t)); - strncpy(new_section->name, sname, 256); - list_add(&new_section->list, &config_head); - - current_section = new_section; - } - else - { - ed = 0; - while (cfgbuffer[c] != L'=' && cfgbuffer[c] != L' ' && cfgbuffer[c]) - wctomb(&(ename[ed++]), cfgbuffer[c++]); - - if (cfgbuffer[c] == L'\0') continue; - ename[ed] = 0; - - while ((cfgbuffer[c] == L'=' || cfgbuffer[c] == L' ') && cfgbuffer[c]) - c++; - - if (!cfgbuffer[c]) continue; - - data_pos = c; - while (cfgbuffer[c]) - { - if (cfgbuffer[c] == L'\n') - cfgbuffer[c] = L'\0'; - c++; - } - - new_entry = malloc(sizeof(entry_t)); - memset(new_entry, 0, sizeof(entry_t)); - strncpy(new_entry->name, ename, 256); - memcpy(new_entry->wdata, &cfgbuffer[data_pos], 512); - new_entry->wdata[255] = L'\0'; - wcstombs(new_entry->data, new_entry->wdata, sizeof(new_entry->data)); - new_entry->data[255] = '\0'; - list_add(&new_entry->list, ¤t_section->entry_head); - } - } - - fclose(f); - - config_dump(); - - return 1; -} - - -void config_new(void) -{ -#ifdef ANSI_CFG - FILE *f = _wfopen(config_file, L"wt"); -#else - FILE *f = _wfopen(config_file, L"wt, ccs=UNICODE"); -#endif - fclose(f); -} - - -static section_t *find_section(char *name) -{ - section_t *current_section; - char blank[] = ""; - - current_section = (section_t *)config_head.next; - if (!name) - name = blank; - - while (current_section) - { - if (!strncmp(current_section->name, name, 256)) - return current_section; - - current_section = (section_t *)current_section->list.next; - } - return NULL; -} - - -static entry_t *find_entry(section_t *section, char *name) -{ - entry_t *current_entry; - - current_entry = (entry_t *)section->entry_head.next; - - while (current_entry) - { - if (!strncmp(current_entry->name, name, 256)) - return current_entry; - - current_entry = (entry_t *)current_entry->list.next; - } - return NULL; -} - - -static int entries_num(section_t *section) -{ - entry_t *current_entry; - int i = 0; - - current_entry = (entry_t *)section->entry_head.next; - - while (current_entry) - { - if (strlen(current_entry->name) > 0) - { - i++; - } - - current_entry = (entry_t *)current_entry->list.next; - } - return i; -} - - -static section_t *create_section(char *name) -{ - section_t *new_section = malloc(sizeof(section_t)); - - memset(new_section, 0, sizeof(section_t)); - strncpy(new_section->name, name, 256); - list_add(&new_section->list, &config_head); - - return new_section; -} - - -static entry_t *create_entry(section_t *section, char *name) -{ - entry_t *new_entry = malloc(sizeof(entry_t)); - memset(new_entry, 0, sizeof(entry_t)); - strncpy(new_entry->name, name, 256); - list_add(&new_entry->list, §ion->entry_head); - - return new_entry; -} - - -int config_get_int(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - int value; - - section = find_section(head); - - if (!section) - return def; - - entry = find_entry(section, name); - - if (!entry) - return def; - - sscanf(entry->data, "%i", &value); - - return value; -} - - -int config_get_hex16(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - int value; - - section = find_section(head); - - if (!section) - return def; - - entry = find_entry(section, name); - - if (!entry) - return def; - - sscanf(entry->data, "%04X", &value); - - return value; -} - - -int config_get_hex20(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - int value; - - section = find_section(head); - - if (!section) - return def; - - entry = find_entry(section, name); - - if (!entry) - return def; - - sscanf(entry->data, "%05X", &value); - - return value; -} - - -int config_get_mac(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - int val0 = 0, val1 = 0, val2 = 0; - - section = find_section(head); - - if (!section) - return def; - - entry = find_entry(section, name); - - if (!entry) - return def; - - sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2); - - return (val0 << 16) + (val1 << 8) + val2; -} - - -char *config_get_string(char *head, char *name, char *def) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - return def; - - entry = find_entry(section, name); - - if (!entry) - return def; - - return entry->data; -} - - -wchar_t *config_get_wstring(char *head, char *name, wchar_t *def) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - return def; - - entry = find_entry(section, name); - - if (!entry) - return def; - - return entry->wdata; -} - - -void config_delete_var(char *head, char *name) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - return; - - entry = find_entry(section, name); - - if (!entry) - return; - - list_delete(&entry->list, §ion->entry_head); - free(entry); - - return; -} - - -void config_delete_section_if_empty(char *head) -{ - section_t *section; - - section = find_section(head); - - if (!section) - return; - - if (entries_num(section) == 0) - { - list_delete(§ion->list, &config_head); - free(section); + free(ent); + ent = nent; } - - return; + + free(sec); + sec = ns; + } } - - -void config_set_int(char *head, char *name, int val) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - section = create_section(head); - - entry = find_entry(section, name); - - if (!entry) - entry = create_entry(section, name); - - sprintf(entry->data, "%i", val); - mbstowcs(entry->wdata, entry->data, 512); -} - - -void config_set_hex16(char *head, char *name, int val) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - section = create_section(head); - - entry = find_entry(section, name); - - if (!entry) - entry = create_entry(section, name); - - sprintf(entry->data, "%04X", val); - mbstowcs(entry->wdata, entry->data, 512); -} - - -void config_set_hex20(char *head, char *name, int val) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - section = create_section(head); - - entry = find_entry(section, name); - - if (!entry) - entry = create_entry(section, name); - - sprintf(entry->data, "%05X", val); - mbstowcs(entry->wdata, entry->data, 512); -} - - -void config_set_mac(char *head, char *name, int val) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - section = create_section(head); - - entry = find_entry(section, name); - - if (!entry) - entry = create_entry(section, name); - - sprintf(entry->data, "%02x:%02x:%02x", (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); - mbstowcs(entry->wdata, entry->data, 512); -} - - -void config_set_string(char *head, char *name, char *val) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - section = create_section(head); - - entry = find_entry(section, name); - - if (!entry) - entry = create_entry(section, name); - - strncpy(entry->data, val, 256); - mbstowcs(entry->wdata, entry->data, 256); -} - - -void config_set_wstring(char *head, char *name, wchar_t *val) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - - if (!section) - section = create_section(head); - - entry = find_entry(section, name); - - if (!entry) - entry = create_entry(section, name); - - memcpy(entry->wdata, val, 512); -} - - -char *get_filename(char *s) -{ - int c = strlen(s) - 1; - while (c > 0) - { - if (s[c] == '/' || s[c] == '\\') - return &s[c+1]; - c--; - } - return s; -} - - -wchar_t *get_filename_w(wchar_t *s) -{ - int c = wcslen(s) - 1; - while (c > 0) - { - if (s[c] == L'/' || s[c] == L'\\') - return &s[c+1]; - c--; - } - return s; -} - - -void append_filename(char *dest, char *s1, char *s2, int size) -{ - sprintf(dest, "%s%s", s1, s2); -} - - -void append_filename_w(wchar_t *dest, wchar_t *s1, wchar_t *s2, int size) -{ - _swprintf(dest, L"%s%s", s1, s2); -} - - -void put_backslash(char *s) -{ - int c = strlen(s) - 1; - if (s[c] != '/' && s[c] != '\\') - s[c] = '/'; -} - - -void put_backslash_w(wchar_t *s) -{ - int c = wcslen(s) - 1; - if (s[c] != L'/' && s[c] != L'\\') - s[c] = L'/'; -} - - -char *get_extension(char *s) -{ - int c = strlen(s) - 1; - - if (c <= 0) - return s; - - while (c && s[c] != '.') - c--; - - if (!c) - return &s[strlen(s)]; - - return &s[c+1]; -} - - -wchar_t *get_extension_w(wchar_t *s) -{ - int c = wcslen(s) - 1; - - if (c <= 0) - return s; - - while (c && s[c] != L'.') - c--; - - if (!c) - return &s[wcslen(s)]; - - return &s[c+1]; -} - - -static wchar_t wname[512]; - - -void config_save(wchar_t *fn) -{ - section_t *current_section; - FILE *f; - int fl = 0; - -#ifdef ANSI_CFG - f = _wfopen(fn, L"wt"); -#else - f = _wfopen(fn, L"wt, ccs=UNICODE"); #endif - if (f == NULL) - return; - current_section = (section_t *)config_head.next; - while (current_section) - { - entry_t *current_entry; - - if (current_section->name[0]) - { - mbstowcs(wname, current_section->name, strlen(current_section->name) + 1); - if (fl) - { - fwprintf(f, L"\n[%ws]\n", wname); - } - else - { - fwprintf(f, L"[%ws]\n", wname); - } + +/* Read and parse the configuration file into memory. */ +static int +config_read(wchar_t *fn) +{ + char sname[128], ename[128]; + wchar_t buff[1024]; + section_t *sec, *ns; + entry_t *ne; + int c, d; + FILE *f; + +#if defined(ANSI_CFG) || !defined(WIN32) + f = plat_fopen(fn, L"rt"); +#else + f = plat_fopen(fn, L"rt, ccs=UNICODE"); +#endif + if (f == NULL) return(0); + + sec = malloc(sizeof(section_t)); + memset(sec, 0x00, sizeof(section_t)); + memset(&config_head, 0x00, sizeof(list_t)); + list_add(&sec->list, &config_head); + + while (1) { + memset(buff, 0x00, sizeof(buff)); + fgetws(buff, sizeof_w(buff), f); + if (feof(f)) break; + + /* Make sure there are no stray newlines or hard-returns in there. */ + if (buff[wcslen(buff)-1] == L'\n') buff[wcslen(buff)-1] = L'\0'; + if (buff[wcslen(buff)-1] == L'\r') buff[wcslen(buff)-1] = L'\0'; + + /* Skip any leading whitespace. */ + c = 0; + while ((buff[c] == L' ') || (buff[c] == L'\t')) + c++; + + /* Skip empty lines. */ + if (buff[c] == L'\0') continue; + + /* Skip lines that (only) have a comment. */ + if ((buff[c] == L'#') || (buff[c] == L';')) continue; + + if (buff[c] == L'[') { /*Section*/ + c++; + d = 0; + while (buff[c] != L']' && buff[c]) + wctomb(&(sname[d++]), buff[c++]); + sname[d] = L'\0'; + + /* Is the section name properly terminated? */ + if (buff[c] != L']') continue; + + /* Create a new section and insert it. */ + ns = malloc(sizeof(section_t)); + memset(ns, 0x00, sizeof(section_t)); + strncpy(ns->name, sname, sizeof(ns->name)); + list_add(&ns->list, &config_head); + + /* New section is now the current one. */ + sec = ns; + continue; + } + + /* Get the variable name. */ + d = 0; + while ((buff[c] != L'=') && (buff[c] != L' ') && buff[c]) + wctomb(&(ename[d++]), buff[c++]); + ename[d] = L'\0'; + + /* Skip incomplete lines. */ + if (buff[c] == L'\0') continue; + + /* Look for =, skip whitespace. */ + while ((buff[c] == L'=' || buff[c] == L' ') && buff[c]) + c++; + + /* Skip incomplete lines. */ + if (buff[c] == L'\0') continue; + + /* This is where the value part starts. */ + d = c; + + /* Allocate a new variable entry.. */ + ne = malloc(sizeof(entry_t)); + memset(ne, 0x00, sizeof(entry_t)); + strncpy(ne->name, ename, sizeof(ne->name)); + wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata)-1); + ne->wdata[sizeof_w(ne->wdata)-1] = L'\0'; + wcstombs(ne->data, ne->wdata, sizeof(ne->data)); + ne->data[sizeof(ne->data)-1] = '\0'; + + /* .. and insert it. */ + list_add(&ne->list, &sec->entry_head); + } + + (void)fclose(f); + + config_dump(); + + return(1); +} + + +/* + * Write the in-memory configuration to disk. + * This is a public function, because the Settings UI + * want to directly write the configuration after it + * has changed it. + */ +void +config_write(wchar_t *fn) +{ + wchar_t wtemp[512]; + section_t *sec; + FILE *f; + int fl = 0; + +#if defined(ANSI_CFG) || !defined(WIN32) + f = plat_fopen(fn, L"wt"); +#else + f = plat_fopen(fn, L"wt, ccs=UNICODE"); +#endif + if (f == NULL) return; + + sec = (section_t *)config_head.next; + while (sec != NULL) { + entry_t *ent; + + if (sec->name[0]) { + mbstowcs(wtemp, sec->name, strlen(sec->name)+1); + if (fl) + fwprintf(f, L"\n[%ls]\n", wtemp); + else + fwprintf(f, L"[%ls]\n", wtemp); + fl++; + } + + ent = (entry_t *)sec->entry_head.next; + while (ent != NULL) { + if (ent->name[0] != '\0') { + mbstowcs(wtemp, ent->name, sizeof_w(wtemp)); + if (ent->wdata[0] == L'\0') + fwprintf(f, L"%ls = \n", wtemp); + else + fwprintf(f, L"%ls = %ls\n", wtemp, ent->wdata); fl++; } - - current_entry = (entry_t *)current_section->entry_head.next; - - while (current_entry) - { - if(current_entry->name[0]) - { - mbstowcs(wname, current_entry->name, strlen(current_entry->name) + 1); - if (current_entry->wdata[0] == L'\0') - { - fwprintf(f, L"%ws = \n", wname); - } - else - { - fwprintf(f, L"%ws = %ws\n", wname, current_entry->wdata); - } - fl++; - } + ent = (entry_t *)ent->list.next; + } - current_entry = (entry_t *)current_entry->list.next; - } - - current_section = (section_t *)current_section->list.next; - } - - fclose(f); + sec = (section_t *)sec->list.next; + } + + (void)fclose(f); } -/* General */ -static void loadconfig_general(void) +#if NOT_USED +static void +config_new(void) { - char *cat = "General"; - char temps[512]; - char *p; +#if defined(ANSI_CFG) || !defined(WIN32) + FILE *f = _wfopen(config_file, L"wt"); +#else + FILE *f = _wfopen(config_file, L"wt, ccs=UNICODE"); +#endif - vid_resize = !!config_get_int(cat, "vid_resize", 0); + if (file != NULL) + (void)fclose(f); +} +#endif - memset(temps, '\0', sizeof(temps)); - p = config_get_string(cat, "vid_renderer", "d3d9"); - if (p != NULL) - { - strcpy(temps, p); - } - if (!strcmp(temps, "ddraw")) - { - vid_api = 0; - } - else - { - vid_api = 1; - } - config_delete_var(cat, "vid_api"); +/* Load "General" section. */ +static void +load_general(void) +{ + char *cat = "General"; + char temp[512]; + char *p; - video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0); - video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 0); + vid_resize = !!config_get_int(cat, "vid_resize", 0); - force_43 = !!config_get_int(cat, "force_43", 0); - scale = config_get_int(cat, "scale", 1); - if (scale > 3) - { - scale = 3; - } - enable_overscan = !!config_get_int(cat, "enable_overscan", 0); - vid_cga_contrast = !!config_get_int(cat, "vid_cga_contrast", 0); - video_grayscale = config_get_int(cat, "video_grayscale", 0); - video_graytype = config_get_int(cat, "video_graytype", 0); + memset(temp, '\0', sizeof(temp)); + p = config_get_string(cat, "vid_renderer", "d3d9"); + if (p != NULL) + strcpy(temp, p); + if (! strcmp(temp, "ddraw")) + vid_api = 0; + else if (! strcmp(temp, "d3d9")) + vid_api = 1; +#ifdef USE_VNC + else if (! strcmp(temp, "vnc")) + vid_api = 2; +#endif +#ifdef USE_RDP + else if (! strcmp(temp, "rdp")) + vid_api = 3; +#endif + else + vid_api = 1; /* default to d3d9 on invalid values */ + config_delete_var(cat, "vid_api"); - window_remember = config_get_int(cat, "window_remember", 0); + video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0); - if (window_remember) - { - p = config_get_string(cat, "window_coordinates", NULL); - if (p == NULL) - p = "0, 0, 0, 0"; - sscanf(p, "%i, %i, %i, %i", &window_w, &window_h, &window_x, &window_y); - } - else - { - config_delete_var(cat, "window_remember"); - config_delete_var(cat, "window_coordinates"); - window_w = window_h = window_x = window_y = 0; - } + video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 0); -#ifndef __unix - /* Currently, 86Box is English (US) only, but in the future (version 1.30 at the earliest) other languages will be added, - therefore it is better to future-proof the code. */ - dwLanguage = config_get_hex16(cat, "language", 0x0409); + force_43 = !!config_get_int(cat, "force_43", 0); + scale = config_get_int(cat, "scale", 1); + if (scale > 3) + scale = 3; + + enable_overscan = !!config_get_int(cat, "enable_overscan", 0); + vid_cga_contrast = !!config_get_int(cat, "vid_cga_contrast", 0); + video_grayscale = config_get_int(cat, "video_grayscale", 0); + video_graytype = config_get_int(cat, "video_graytype", 0); + + window_remember = config_get_int(cat, "window_remember", 0); + if (window_remember) { + p = config_get_string(cat, "window_coordinates", NULL); + if (p == NULL) + p = "0, 0, 0, 0"; + sscanf(p, "%i, %i, %i, %i", &window_w, &window_h, &window_x, &window_y); + } else { + config_delete_var(cat, "window_remember"); + config_delete_var(cat, "window_coordinates"); + + window_w = window_h = window_x = window_y = 0; + } + +#ifdef USE_LANGUAGE + /* + * Currently, 86Box is English (US) only, but in the future + * (version 1.30 at the earliest) other languages will be + * added, therefore it is better to future-proof the code. + */ + plat_langid = config_get_hex16(cat, "language", 0x0409); #endif } -/* Machine */ -static void loadconfig_machine(void) +/* Load "Machine" section. */ +static void +load_machine(void) { - char *cat = "Machine"; - wchar_t *wp; - wchar_t last; - char *p; + char *cat = "Machine"; + char *p; - p = config_get_string(cat, "machine", NULL); - if (p != NULL) - { + p = config_get_string(cat, "machine", NULL); + if (p != NULL) + machine = machine_get_machine_from_internal_name(p); + else + machine = 0; + if (machine >= machine_count()) + machine = machine_count() - 1; + + /* This is for backwards compatibility. */ + p = config_get_string(cat, "model", NULL); + if (p != NULL) { + /* Detect the old model typos and fix them. */ + if (! strcmp(p, "p55r2p4")) { + machine = machine_get_machine_from_internal_name("p55t2p4"); + } else { machine = machine_get_machine_from_internal_name(p); } - else - machine = 0; - if (machine >= machine_count()) - machine = machine_count() - 1; + config_delete_var(cat, "model"); + } + if (machine >= machine_count()) + machine = machine_count() - 1; - /* This is for backwards compatibility. */ - p = config_get_string(cat, "model", NULL); - if (p != NULL) - { - /* Detect the old model typo and fix it, so that old configurations don't braek. */ - if (strcmp(p, "p55r2p4") == 0) - { - machine = machine_get_machine_from_internal_name("p55t2p4"); - } - else - { - machine = machine_get_machine_from_internal_name(p); - } - config_delete_var(cat, "model"); - } - if (machine >= machine_count()) - machine = machine_count() - 1; + romset = machine_getromset(); + cpu_manufacturer = config_get_int(cat, "cpu_manufacturer", 0); + cpu = config_get_int(cat, "cpu", 0); + cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0); - romset = machine_getromset(); - cpu_manufacturer = config_get_int(cat, "cpu_manufacturer", 0); - cpu = config_get_int(cat, "cpu", 0); - cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0); + mem_size = config_get_int(cat, "mem_size", 4096); + if (mem_size < (((machines[machine].flags & MACHINE_AT) && + (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram)) + mem_size = (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram); + if (mem_size > 1048576) + mem_size = 1048576; - mem_size = config_get_int(cat, "mem_size", 4096); - if (mem_size < (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram)) - mem_size = (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram); - if (mem_size > 1048576) - { - mem_size = 1048576; - } + cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0); - memset(nvr_path, 0x00, sizeof(nvr_path)); - wp = config_get_wstring(cat, "nvr_path", L""); - if (wp != NULL) { - if (wcslen(wp) && (wcslen(wp) <= 992)) - { - wcscpy(nvr_path, wp); - } - else - { - append_filename_w(nvr_path, pcempath, L"nvr\\", 511); - } - } - else append_filename_w(nvr_path, pcempath, L"nvr\\", 511); + enable_external_fpu = !!config_get_int(cat, "cpu_enable_fpu", 0); - if (nvr_path[wcslen(nvr_path) - 1] != L'/') - { - if (nvr_path[wcslen(nvr_path) - 1] != L'\\') - { - nvr_path[wcslen(nvr_path)] = L'\\'; - nvr_path[wcslen(nvr_path) + 1] = L'\0'; - } - } + enable_sync = !!config_get_int(cat, "enable_sync", 1); - path_len = wcslen(nvr_path); - -#ifndef __unix - last = nvr_path[wcslen(nvr_path) - 1]; - nvr_path[wcslen(nvr_path) - 1] = 0; - if (!DirectoryExists(nvr_path)) - { - CreateDirectory(nvr_path, NULL); - } - nvr_path[wcslen(nvr_path)] = last; -#endif - - cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0); - - enable_external_fpu = !!config_get_int(cat, "cpu_enable_fpu", 0); - - enable_sync = !!config_get_int(cat, "enable_sync", 1); + /* Remove this after a while.. */ + config_delete_var(cat, "nvr_path"); } -/* Video */ -static void loadconfig_video(void) +/* Load "Video" section. */ +static void +load_video(void) { - char *cat = "Video"; - char *p; + char *cat = "Video"; + char *p; - p = config_get_string(cat, "gfxcard", NULL); - if (p != NULL) - gfxcard = video_get_video_from_internal_name(p); - else - gfxcard = 0; + p = config_get_string(cat, "gfxcard", NULL); + if (p != NULL) + gfxcard = video_get_video_from_internal_name(p); + else + gfxcard = 0; - video_speed = config_get_int(cat, "video_speed", 3); + video_speed = config_get_int(cat, "video_speed", 3); - voodoo_enabled = !!config_get_int(cat, "voodoo", 0); + voodoo_enabled = !!config_get_int(cat, "voodoo", 0); } -/* Input devices */ -static void loadconfig_input_devices(void) +/* Load "Input Devices" section. */ +static void +load_input_devices(void) { - char *cat = "Input devices"; - char temps[512]; - int c, d; - char *p; + char *cat = "Input devices"; + char temp[512]; + int c, d; + char *p; - p = config_get_string(cat, "mouse_type", NULL); - if (p != NULL) - mouse_type = mouse_get_from_internal_name(p); - else - mouse_type = 0; + p = config_get_string(cat, "mouse_type", NULL); + if (p != NULL) + mouse_type = mouse_get_from_internal_name(p); + else + mouse_type = 0; - joystick_type = config_get_int(cat, "joystick_type", 7); + joystick_type = config_get_int(cat, "joystick_type", 7); - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) - { - sprintf(temps, "joystick_%i_nr", c); - joystick_state[c].plat_joystick_nr = config_get_int(cat, temps, 0); + for (c=0; c max_spt) - { - hdc[c].spt = max_spt; - } - if (hdc[c].hpc > max_hpc) - { - hdc[c].hpc = max_hpc; - } - if (hdc[c].tracks > max_tracks) - { - hdc[c].tracks = max_tracks; - } - - /* MFM */ - sprintf(temps, "hdd_%02i_mfm_channel", c + 1); - if (hdc[c].bus == HDD_BUS_MFM) - { - hdc[c].mfm_channel = !!config_get_int(cat, temps, c & 1); - } - else - { - config_delete_var(cat, temps); - } - - /* XT IDE */ - sprintf(temps, "hdd_%02i_xtide_channel", c + 1); - if (hdc[c].bus == HDD_BUS_XTIDE) - { - hdc[c].xtide_channel = !!config_get_int(cat, temps, c & 1); - } - else - { - config_delete_var(cat, temps); - } - - /* ESDI */ - sprintf(temps, "hdd_%02i_esdi_channel", c + 1); - if (hdc[c].bus == HDD_BUS_ESDI) - { - hdc[c].esdi_channel = !!config_get_int(cat, temps, c & 1); - } - else - { - config_delete_var(cat, temps); - } - - /* IDE */ - sprintf(temps, "hdd_%02i_ide_channel", c + 1); - if ((hdc[c].bus == HDD_BUS_IDE_PIO_ONLY) || (hdc[c].bus == HDD_BUS_IDE_PIO_AND_DMA)) - { - sprintf(temps2, "%01u:%01u", c >> 1, c & 1); - p = config_get_string(cat, temps, temps2); - - if (strstr(p, ":") == NULL) - { - sscanf(p, "%i", &hdc[c].ide_channel); - hdc[c].ide_channel &= 7; - } - else - { - sscanf(p, "%01u:%01u", &board, &dev); - - board &= 3; - dev &= 1; - hdc[c].ide_channel = (board << 1) + dev; - } - - if (hdc[c].ide_channel > 7) - { - hdc[c].ide_channel = 7; - } - } - else - { - config_delete_var(cat, temps); - } - - /* SCSI */ - sprintf(temps, "hdd_%02i_scsi_location", c + 1); - if ((hdc[c].bus == HDD_BUS_SCSI) || (hdc[c].bus == HDD_BUS_SCSI_REMOVABLE)) - { - sprintf(temps2, "%02u:%02u", c, 0); - p = config_get_string(cat, temps, temps2); - - sscanf(p, "%02u:%02u", &hdc[c].scsi_id, &hdc[c].scsi_lun); - - if (hdc[c].scsi_id > 15) - { - hdc[c].scsi_id = 15; - } - if (hdc[c].scsi_lun > 7) - { - hdc[c].scsi_lun = 7; - } - } - else - { - config_delete_var(cat, temps); - } - - memset(hdc[c].fn, 0, sizeof(hdc[c].fn)); - memset(hdc[c].prev_fn, 0, sizeof(hdc[c].prev_fn)); - sprintf(temps, "hdd_%02i_fn", c + 1); - wp = config_get_wstring(cat, temps, L""); - memcpy(hdc[c].fn, wp, (wcslen(wp) << 1) + 2); - - /* If the hard disk is in any way empty or invalid, mark the relevant variables for deletion. */ - if (!hard_disk_is_valid(c)) - { - sprintf(temps, "hdd_%02i_parameters", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "hdd_%02i_preide_channels", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "hdd_%02i_ide_channels", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "hdd_%02i_scsi_location", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "hdd_%02i_fn", c + 1); - config_delete_var(cat, temps); - } - - sprintf(temps, "hdd_%02i_mfm_channel", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "hdd_%02i_ide_channel", c + 1); - config_delete_var(cat, temps); - } -} - - -/* Removable devices */ -static void loadconfig_removable_devices(void) -{ - char *cat = "Removable devices"; - char temps[512]; - char temps2[512]; - char s[512]; - int c; - char *p; - wchar_t *wp; - unsigned int board = 0, dev = 0; - - for (c = 0; c < FDD_NUM; c++) - { - sprintf(temps, "fdd_%02i_type", c + 1); - p = config_get_string(cat, temps, (c < 2) ? "525_2dd" : "none"); - fdd_set_type(c, fdd_get_from_internal_name(p)); - if (fdd_get_type(c) > 13) - { - fdd_set_type(c, 13); - } - - sprintf(temps, "fdd_%02i_fn", c + 1); - wp = config_get_wstring(cat, temps, L""); - memcpy(floppyfns[c], wp, (wcslen(wp) << 1) + 2); - printf("Floppy: %ws\n", floppyfns[c]); - sprintf(temps, "fdd_%02i_writeprot", c + 1); - ui_writeprot[c] = !!config_get_int(cat, temps, 0); - sprintf(temps, "fdd_%02i_turbo", c + 1); - fdd_set_turbo(c, !!config_get_int(cat, temps, 0)); - sprintf(temps, "fdd_%02i_check_bpb", c + 1); - fdd_set_check_bpb(c, !!config_get_int(cat, temps, 1)); - - /* Check, whether each value is default, if yes, delete it so that only non-default values will later be saved. */ - if (fdd_get_type(c) == ((c < 2) ? 2 : 0)) - { - sprintf(temps, "fdd_%02i_type", c + 1); - config_delete_var(cat, temps); - } - - if (wcslen(floppyfns[c]) == 0) - { - sprintf(temps, "fdd_%02i_fn", c + 1); - config_delete_var(cat, temps); - } - - if (ui_writeprot[c] == 0) - { - sprintf(temps, "fdd_%02i_writeprot", c + 1); - config_delete_var(cat, temps); - } - - if (fdd_get_turbo(c) == 0) - { - sprintf(temps, "fdd_%02i_turbo", c + 1); - config_delete_var(cat, temps); - } - - if (fdd_get_check_bpb(c) == 1) - { - sprintf(temps, "fdd_%02i_check_bpb", c + 1); - config_delete_var(cat, temps); - } - } - - memset(temps, 0, 512); - for (c = 0; c < CDROM_NUM; c++) - { - sprintf(temps, "cdrom_%02i_host_drive", c + 1); - cdrom_drives[c].host_drive = config_get_int(cat, temps, 0); - cdrom_drives[c].prev_host_drive = cdrom_drives[c].host_drive; - - sprintf(temps, "cdrom_%02i_parameters", c + 1); - p = config_get_string(cat, temps, NULL); - if (p != NULL) - { - sscanf(p, "%u, %s", &cdrom_drives[c].sound_on, s); - } - else - { - sscanf("0, none", "%u, %s", &cdrom_drives[c].sound_on, s); - } - - cdrom_drives[c].bus_type = config_string_to_bus(s, 1); - - sprintf(temps, "cdrom_%02i_ide_channel", c + 1); - if ((cdrom_drives[c].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[c].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - { - sprintf(temps2, "%01u:%01u", (c + 2) >> 1, (c + 2) & 1); - p = config_get_string(cat, temps, temps2); - - if (strstr(p, ":") == NULL) - { - sscanf(p, "%i", &hdc[c].ide_channel); - cdrom_drives[c].ide_channel &= 7; - } - else - { - sscanf(p, "%02u:%02u", &board, &dev); - - board &= 3; - dev &= 1; - cdrom_drives[c].ide_channel = (board << 1) + dev; - } - - if (cdrom_drives[c].ide_channel > 7) - { - cdrom_drives[c].ide_channel = 7; - } - } - else - { - config_delete_var(cat, temps); - } - - sprintf(temps, "cdrom_%02i_scsi_location", c + 1); - if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) - { - sprintf(temps2, "%02u:%02u", c + 2, 0); - p = config_get_string(cat, temps, temps2); - sscanf(p, "%02u:%02u", &cdrom_drives[c].scsi_device_id, &cdrom_drives[c].scsi_device_lun); - - if (cdrom_drives[c].scsi_device_id > 15) - { - cdrom_drives[c].scsi_device_id = 15; - } - if (cdrom_drives[c].scsi_device_lun > 7) - { - cdrom_drives[c].scsi_device_lun = 7; - } - } - else - { - config_delete_var(cat, temps); - } - - sprintf(temps, "cdrom_%02i_image_path", c + 1); - wp = config_get_wstring(cat, temps, L""); - memcpy(cdrom_image[c].image_path, wp, (wcslen(wp) << 1) + 2); - wcscpy(cdrom_image[c].prev_image_path, cdrom_image[c].image_path); - - if (cdrom_drives[c].host_drive < 'A') - { - cdrom_drives[c].host_drive = 0; - } - - if ((cdrom_drives[c].host_drive == 0x200) && (wcslen(cdrom_image[c].image_path) == 0)) - { - cdrom_drives[c].host_drive = 0; - } - - /* If the CD-ROM is disabled, delete all its variables. */ - if (cdrom_drives[c].bus_type == CDROM_BUS_DISABLED) - { - sprintf(temps, "cdrom_%02i_host_drive", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "cdrom_%02i_parameters", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "cdrom_%02i_ide_channel", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "cdrom_%02i_scsi_location", c + 1); - config_delete_var(cat, temps); - - sprintf(temps, "cdrom_%02i_image_path", c + 1); - config_delete_var(cat, temps); - } - - sprintf(temps, "cdrom_%02i_iso_path", c + 1); - config_delete_var(cat, temps); - } -} - - -void loadconfig(wchar_t *fn) -{ - int i = 0; - - if (fn == NULL) - fn = config_file_default; - i = config_load(fn); - - if (i == 0) - { - cpu = 0; -#ifndef __unix - dwLanguage = 0x0409; -#endif - scale = 1; - vid_api = 1; - enable_sync = 1; - joystick_type = 7; - strcpy(hdd_controller_name, "none"); - serial_enabled[0] = 1; - serial_enabled[1] = 1; - lpt_enabled = 1; - fdd_set_type(0, 2); - fdd_set_type(1, 2); - mem_size = 640; - - return; - } - - /* General */ - loadconfig_general(); - - /* Machine */ - loadconfig_machine(); - - /* Video */ - loadconfig_video(); - - /* Input devices */ - loadconfig_input_devices(); - - /* Sound */ - loadconfig_sound(); - -#ifdef USE_NETWORK - /* Network */ - loadconfig_network(); -#endif - - /* Ports (COM & LPT) */ - loadconfig_ports(); - - /* Other peripherals */ - loadconfig_other_peripherals(); - - /* Hard disks */ - loadconfig_hard_disks(); - - /* Removable devices */ - loadconfig_removable_devices(); - -} - - -wchar_t *nvr_concat(wchar_t *to_concat) -{ - static wchar_t temp_nvr_path[1024]; - char *p; - wchar_t *wp; - - memset(temp_nvr_path, 0, 2048); - wcscpy(temp_nvr_path, nvr_path); - - p = (char *) temp_nvr_path; - p += (path_len * 2); - wp = (wchar_t *) p; - - wcscpy(wp, to_concat); - return temp_nvr_path; -} - - -static void saveconfig_general(void) -{ - char *cat = "General"; - char temps[512]; - - config_set_int(cat, "vid_resize", vid_resize); - if (vid_resize == 0) - { - config_delete_var(cat, "vid_resize"); - } - - if (vid_api == 1) - { - config_delete_var(cat, "vid_renderer"); - } - else - { - switch(vid_api) - { - case 0: - config_set_string(cat, "vid_renderer", "ddraw"); - break; - case 1: - default: - config_set_string(cat, "vid_renderer", "d3d9"); - break; - } - } - - if (video_fullscreen_scale == 0) - { - config_delete_var(cat, "video_fullscreen_scale"); - } - else - { - config_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale); - } - - if (video_fullscreen_first == 0) - { - config_delete_var(cat, "video_fullscreen_first"); - } - else - { - config_set_int(cat, "video_fullscreen_first", video_fullscreen_first); - } - - if (force_43 == 0) - { - config_delete_var(cat, "force_43"); - } - else - { - config_set_int(cat, "force_43", force_43); - } - - if (scale == 1) - { - config_delete_var(cat, "scale"); - } - else - { - config_set_int(cat, "scale", scale); - } - - if (enable_overscan == 0) - { - config_delete_var(cat, "enable_overscan"); - } - else - { - config_set_int(cat, "enable_overscan", enable_overscan); - } - - if (vid_cga_contrast == 0) - { - config_delete_var(cat, "vid_cga_contrast"); - } - else - { - config_set_int(cat, "vid_cga_contrast", vid_cga_contrast); - } - - if (video_grayscale == 0) - { - config_delete_var(cat, "video_grayscale"); - } - else - { - config_set_int(cat, "video_grayscale", video_grayscale); - } - - if (video_graytype == 0) - { - config_delete_var(cat, "video_graytype"); - } - else - { - config_set_int(cat, "video_graytype", video_graytype); - } - - if (window_remember) - { - config_set_int(cat, "window_remember", window_remember); - - sprintf(temps, "%i, %i, %i, %i", window_w, window_h, window_x, window_y); - config_set_string(cat, "window_coordinates", temps); - } - else - { - config_delete_var(cat, "window_remember"); - config_delete_var(cat, "window_coordinates"); - } - -#ifndef __unix - if (dwLanguage == 0x0409) - { - config_delete_var(cat, "language"); - } - else - { - config_set_hex16(cat, "language", dwLanguage); - } -#endif - - config_delete_section_if_empty(cat); -} - - -/* Machine */ -static void saveconfig_machine(void) -{ - char *cat = "Machine"; - - config_set_string(cat, "machine", machine_get_internal_name()); - - if (cpu_manufacturer == 0) - { - config_delete_var(cat, "cpu_manufacturer"); - } - else - { - config_set_int(cat, "cpu_manufacturer", cpu_manufacturer); - } - - if (cpu == 0) - { - config_delete_var(cat, "cpu"); - } - else - { - config_set_int(cat, "cpu", cpu); - } - - if (cpu_waitstates == 0) - { - config_delete_var(cat, "cpu_waitstates"); - } - else - { - config_set_int(cat, "cpu_waitstates", cpu_waitstates); - } - - if (mem_size == 4096) - { - config_delete_var(cat, "mem_size"); - } - else - { - config_set_int(cat, "mem_size", mem_size); - } - - config_set_wstring(cat, "nvr_path", nvr_path); - - config_set_int(cat, "cpu_use_dynarec", cpu_use_dynarec); - - if (enable_external_fpu == 0) - { - config_delete_var(cat, "cpu_enable_fpu"); - } - else - { - config_set_int(cat, "cpu_enable_fpu", enable_external_fpu); - } - - if (enable_sync == 1) - { - config_delete_var(cat, "enable_sync"); - } - else - { - config_set_int(cat, "enable_sync", enable_sync); - } - - config_delete_section_if_empty(cat); -} - - -/* Video */ -static void saveconfig_video(void) -{ - char *cat = "Video"; - - config_set_string(cat, "gfxcard", video_get_internal_name(video_old_to_new(gfxcard))); - - if (video_speed == 3) - { - config_delete_var(cat, "video_speed"); - } - else - { - config_set_int(cat, "video_speed", video_speed); - } - - if (voodoo_enabled == 0) - { - config_delete_var(cat, "voodoo"); - } - else - { - config_set_int(cat, "voodoo", voodoo_enabled); - } - - config_delete_section_if_empty(cat); -} - - -/* Input devices */ -static void saveconfig_input_devices(void) -{ - char *cat = "Input devices"; - char temps[512]; - char s[512]; - int c, d; - - config_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type)); - - if ((joystick_type == 0) || (joystick_type == 7)) - { - if (joystick_type == 7) - { - config_delete_var(cat, "joystick_type"); - } - else - { - config_set_int(cat, "joystick_type", joystick_type); - } - - for (c = 0; c < 16; c++) - { - sprintf(s, "joystick_%i_nr", c); - config_delete_var(cat, s); - - for (d = 0; d < 16; d++) - { - sprintf(s, "joystick_%i_axis_%i", c, d); - config_delete_var(cat, s); - } - for (d = 0; d < 16; d++) - { - sprintf(s, "joystick_%i_button_%i", c, d); - config_delete_var(cat, s); - } - for (d = 0; d < 16; d++) - { - sprintf(s, "joystick_%i_pov_%i", c, d); - config_delete_var(cat, s); - } - } - } - else - { - config_set_int(cat, "joystick_type", joystick_type); - - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) - { - sprintf(s, "joystick_%i_nr", c); - config_set_int(cat, s, joystick_state[c].plat_joystick_nr); - - if (joystick_state[c].plat_joystick_nr) - { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - { - sprintf(s, "joystick_%i_axis_%i", c, d); - config_set_int(cat, s, joystick_state[c].axis_mapping[d]); - } - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - { - sprintf(s, "joystick_%i_button_%i", c, d); - config_set_int(cat, s, joystick_state[c].button_mapping[d]); - } - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - { - sprintf(s, "joystick_%i_pov_%i", c, d); - sprintf(temps, "%i, %i", joystick_state[c].pov_mapping[d][0], joystick_state[c].pov_mapping[d][1]); - config_set_string(cat, s, temps); - } - } - } - } - - config_delete_section_if_empty(cat); -} - - -/* Sound */ -static void saveconfig_sound(void) -{ - char *cat = "Sound"; - - if (sound_card_current == 0) - { - config_delete_var(cat, "sndcard"); - } - else - { - config_set_string(cat, "sndcard", sound_card_get_internal_name(sound_card_current)); - } - - - if (!strcmp(midi_device_get_internal_name(midi_device_current), "none")) - { - config_delete_var(cat, "midi_device"); - } - else - { - config_set_string(cat, "midi_device", midi_device_get_internal_name(midi_device_current)); - } - - if (mpu401_standalone_enable == 0) - { - config_delete_var(cat, "mpu401_standalone"); - } - else - { - config_set_int(cat, "mpu401_standalone", mpu401_standalone_enable); - } - - if (SSI2001 == 0) - { - config_delete_var(cat, "ssi2001"); - } - else - { - config_set_int(cat, "ssi2001", SSI2001); - } - - if (GAMEBLASTER == 0) - { - config_delete_var(cat, "gameblaster"); - } - else - { - config_set_int(cat, "gameblaster", GAMEBLASTER); - } - - if (GUS == 0) - { - config_delete_var(cat, "gus"); - } - else - { - config_set_int(cat, "gus", GUS); - } - - if (opl3_type == 0) - { - config_delete_var(cat, "opl3_type"); - } - else - { - config_set_string(cat, "opl3_type", (opl3_type == 1) ? "nukedopl" : "dbopl"); - } - - if (sound_is_float == 1) - { - config_delete_var(cat, "sound_type"); - } - else - { - config_set_string(cat, "sound_type", (sound_is_float == 1) ? "float" : "int16"); - } - - config_delete_section_if_empty(cat); -} - - -#ifdef USE_NETWORK -/* Network */ -static void saveconfig_network(void) -{ - char *cat = "Network"; - - if (network_type == NET_TYPE_NONE) - { - config_delete_var(cat, "net_type"); - } - else - { - config_set_string(cat, "net_type", (network_type == NET_TYPE_SLIRP) ? "slirp" : "pcap"); - } - - if (network_pcap[0] != '\0') - { - if (!strcmp(network_pcap, "none")) - { - config_delete_var(cat, "net_pcap_device"); - } - else - { - config_set_string(cat, "net_pcap_device", network_pcap); - } - } - else - { - /* config_set_string(cat, "net_pcap_device", "none"); */ - config_delete_var(cat, "net_pcap_device"); - } - - if (network_card == 0) - { - config_delete_var(cat, "net_card"); - } - else - { - config_set_string(cat, "net_card", network_card_get_internal_name(network_card)); - } - - config_delete_section_if_empty(cat); -} -#endif - - -/* Ports (COM & LPT) */ -static void saveconfig_ports(void) -{ - char *cat = "Ports (COM & LPT)"; - - if (serial_enabled[0]) - { - config_delete_var(cat, "serial1_enabled"); - } - else - { - config_set_int(cat, "serial1_enabled", serial_enabled[0]); - } - - if (serial_enabled[1]) - { - config_delete_var(cat, "serial2_enabled"); - } - else - { - config_set_int(cat, "serial2_enabled", serial_enabled[1]); - } - - if (lpt_enabled) - { - config_delete_var(cat, "lpt_enabled"); - } - else - { - config_set_int(cat, "lpt_enabled", lpt_enabled); - } - - if (!strcmp(lpt1_device_name, "none")) - { - config_delete_var(cat, "lpt1_device"); - } - else - { - config_set_string(cat, "lpt1_device", lpt1_device_name); - } - - config_delete_section_if_empty(cat); -} - - -/* Other peripherals */ -static void saveconfig_other_peripherals(void) -{ - char *cat = "Other peripherals"; - char temps[512]; - char temps2[512]; - int c; - - if (scsi_card_current == 0) - { - config_delete_var(cat, "scsicard"); - } - else - { - config_set_string(cat, "scsicard", scsi_card_get_internal_name(scsi_card_current)); - } - - if (!strcmp(hdd_controller_name, "none")) - { config_delete_var(cat, "hdd_controller"); - } - else - { - config_set_string(cat, "hdd_controller", hdd_controller_name); - } + } + if (p == NULL) { + if (machines[machine].flags & MACHINE_HAS_HDC) + strcpy(hdc_name, "internal"); + else + strcpy(hdc_name, "none"); + } else + strcpy(hdc_name, p); + config_set_string(cat, "hdc", hdc_name); - memset(temps, '\0', sizeof(temps)); - for (c = 2; c < 4; c++) - { - sprintf(temps, "ide_%02i", c + 1); - sprintf(temps2, "%i, %02i", !!ide_enable[c], ide_irq[c]); + memset(temp, '\0', sizeof(temp)); + for (c=2; c<4; c++) { + sprintf(temp, "ide_%02i", c + 1); + p = config_get_string(cat, temp, NULL); + if (p == NULL) + p = "0, 00"; + sscanf(p, "%i, %02i", &ide_enable[c], &ide_irq[c]); + } - if (ide_enable[c] == 0) - { - config_delete_var(cat, temps); - } - else - { - config_set_string(cat, temps, temps2); - } - } + bugger_enabled = !!config_get_int(cat, "bugger_enabled", 0); - if (bugger_enabled == 0) - { - config_delete_var(cat, "bugger_enabled"); - } - else - { - config_set_int(cat, "bugger_enabled", bugger_enabled); - } - - config_delete_section_if_empty(cat); + /* Remove these after a while. */ + serial_enabled[0] = !!config_get_int(cat, "serial1_enabled", 1); + config_delete_var(cat, "serial1_enabled"); + serial_enabled[1] = !!config_get_int(cat, "serial2_enabled", 1); + config_delete_var(cat, "serial2_enabled"); + lpt_enabled = !!config_get_int(cat, "lpt_enabled", 1); + config_delete_var(cat, "lpt_enabled"); } -static char *config_bus_to_string(int bus, int cdrom) +static int +tally_char(char *str, char c) { - switch (bus) - { + int tally; + + tally = 0; + if (str != NULL) { + while (*str) + if (*str++ == c) tally++; + } + + return(tally); +} + + +/* Load "Hard Disks" section. */ +static void +load_hard_disks(void) +{ + char *cat = "Hard disks"; + char temp[512], tmp2[512]; + char s[512]; + int c; + char *p; + wchar_t *wp; + int max_spt, max_hpc, max_tracks; + int board = 0, dev = 0; + + memset(temp, '\0', sizeof(temp)); + for (c=0; c max_spt) + hdd[c].spt = max_spt; + if (hdd[c].hpc > max_hpc) + hdd[c].hpc = max_hpc; + if (hdd[c].tracks > max_tracks) + hdd[c].tracks = max_tracks; + + /* MFM/RLL */ + sprintf(temp, "hdd_%02i_mfm_channel", c+1); + if (hdd[c].bus == HDD_BUS_MFM) + hdd[c].mfm_channel = !!config_get_int(cat, temp, c & 1); + else + config_delete_var(cat, temp); + + /* XT IDE */ + sprintf(temp, "hdd_%02i_xtide_channel", c+1); + if (hdd[c].bus == HDD_BUS_XTIDE) + hdd[c].xtide_channel = !!config_get_int(cat, temp, c & 1); + else + config_delete_var(cat, temp); + + /* ESDI */ + sprintf(temp, "hdd_%02i_esdi_channel", c+1); + if (hdd[c].bus == HDD_BUS_ESDI) + hdd[c].esdi_channel = !!config_get_int(cat, temp, c & 1); + else + config_delete_var(cat, temp); + + /* IDE */ + sprintf(temp, "hdd_%02i_ide_channel", c+1); + if ((hdd[c].bus == HDD_BUS_IDE_PIO_ONLY) || + (hdd[c].bus == HDD_BUS_IDE_PIO_AND_DMA)) { + sprintf(tmp2, "%01u:%01u", c>>1, c&1); + p = config_get_string(cat, temp, tmp2); + if (! strstr(p, ":")) { + sscanf(p, "%i", (int *)&hdd[c].ide_channel); + hdd[c].ide_channel &= 7; + } else { + sscanf(p, "%01u:%01u", &board, &dev); + + board &= 3; + dev &= 1; + hdd[c].ide_channel = (board<<1) + dev; + } + + if (hdd[c].ide_channel > 7) + hdd[c].ide_channel = 7; + } else { + config_delete_var(cat, temp); + } + + /* SCSI */ + sprintf(temp, "hdd_%02i_scsi_location", c+1); + if ((hdd[c].bus == HDD_BUS_SCSI) || + (hdd[c].bus == HDD_BUS_SCSI_REMOVABLE)) { + sprintf(tmp2, "%02u:%02u", c, 0); + p = config_get_string(cat, temp, tmp2); + + sscanf(p, "%02u:%02u", + (int *)&hdd[c].scsi_id, (int *)&hdd[c].scsi_lun); + + if (hdd[c].scsi_id > 15) + hdd[c].scsi_id = 15; + if (hdd[c].scsi_lun > 7) + hdd[c].scsi_lun = 7; + } else { + config_delete_var(cat, temp); + } + + memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn)); + memset(hdd[c].prev_fn, 0x00, sizeof(hdd[c].prev_fn)); + sprintf(temp, "hdd_%02i_fn", c+1); + wp = config_get_wstring(cat, temp, L""); + +#if 0 + /* + * NOTE: + * Temporary hack to remove the absolute + * path currently saved in most config + * files. We should remove this before + * finalizing this release! --FvK + */ + if (! wcsnicmp(wp, cfg_path, wcslen(cfg_path))) { + /* + * Yep, its absolute and prefixed + * with the CFG path. Just strip + * that off for now... + */ + wcsncpy(hdd[c].fn, &wp[wcslen(cfg_path)], sizeof_w(hdd[c].fn)); + } else +#endif + wcsncpy(hdd[c].fn, wp, sizeof_w(hdd[c].fn)); + + /* If disk is empty or invalid, mark it for deletion. */ + if (! hdd_is_valid(c)) { + sprintf(temp, "hdd_%02i_parameters", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_preide_channels", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_ide_channels", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_scsi_location", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_fn", c+1); + config_delete_var(cat, temp); + } + + sprintf(temp, "hdd_%02i_mfm_channel", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_ide_channel", c+1); + config_delete_var(cat, temp); + } } -/* Hard disks */ -static void saveconfig_hard_disks(void) +/* Load "Removable Devices" section. */ +static void +load_removable_devices(void) { - char *cat = "Hard disks"; - char temps[24]; - char temps2[64]; - char s[512]; - int c; - char *p; + char *cat = "Removable devices"; + char temp[512], tmp2[512], *p; + char s[512]; + unsigned int board = 0, dev = 0; + wchar_t *wp; + int c; - memset(temps, 0, sizeof(temps)); - for (c = 0; c < HDC_NUM; c++) - { - sprintf(temps, "hdd_%02i_parameters", c + 1); - memset(s, 0, sizeof(s)); - if (!hard_disk_is_valid(c)) - { - config_delete_var(cat, temps); - } - else - { - p = config_bus_to_string(hdc[c].bus, 0); - sprintf(temps2, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %i, %s", hdc[c].spt, hdc[c].hpc, hdc[c].tracks, hdc[c].wp, p); - config_set_string(cat, temps, temps2); + for (c=0; c 13) + fdd_set_type(c, 13); + + sprintf(temp, "fdd_%02i_fn", c + 1); + wp = config_get_wstring(cat, temp, L""); + +#if 0 + /* + * NOTE: + * Temporary hack to remove the absolute + * path currently saved in most config + * files. We should remove this before + * finalizing this release! --FvK + */ + if (! wcsnicmp(wp, cfg_path, wcslen(cfg_path))) { + /* + * Yep, its absolute and prefixed + * with the EXE path. Just strip + * that off for now... + */ + wcsncpy(floppyfns[c], &wp[wcslen(cfg_path)], sizeof_w(floppyfns[c])); + } else +#endif + wcsncpy(floppyfns[c], wp, sizeof_w(floppyfns[c])); + + if (*wp != L'\0') + printf("Floppy%d: %ls\n", c, floppyfns[c]); + sprintf(temp, "fdd_%02i_writeprot", c+1); + ui_writeprot[c] = !!config_get_int(cat, temp, 0); + sprintf(temp, "fdd_%02i_turbo", c + 1); + fdd_set_turbo(c, !!config_get_int(cat, temp, 0)); + sprintf(temp, "fdd_%02i_check_bpb", c+1); + fdd_set_check_bpb(c, !!config_get_int(cat, temp, 1)); + + /* Check whether each value is default, if yes, delete it so that only non-default values will later be saved. */ + if (fdd_get_type(c) == ((c < 2) ? 2 : 0)) { + sprintf(temp, "fdd_%02i_type", c+1); + config_delete_var(cat, temp); + } + if (wcslen(floppyfns[c]) == 0) { + sprintf(temp, "fdd_%02i_fn", c+1); + config_delete_var(cat, temp); + } + if (ui_writeprot[c] == 0) { + sprintf(temp, "fdd_%02i_writeprot", c+1); + config_delete_var(cat, temp); + } + if (fdd_get_turbo(c) == 0) { + sprintf(temp, "fdd_%02i_turbo", c+1); + config_delete_var(cat, temp); + } + if (fdd_get_check_bpb(c) == 1) { + sprintf(temp, "fdd_%02i_check_bpb", c+1); + config_delete_var(cat, temp); + } + } + + memset(temp, 0x00, sizeof(temp)); + for (c=0; c>1, (c+2)&1); + p = config_get_string(cat, temp, tmp2); + if (! strstr(p, ":")) { + sscanf(p, "%i", (int *)&hdd[c].ide_channel); + cdrom_drives[c].ide_channel &= 7; + } else { + sscanf(p, "%02u:%02u", &board, &dev); + + board &= 3; + dev &= 1; + cdrom_drives[c].ide_channel = (board<<1)+dev; } - sprintf(temps, "hdd_%02i_mfm_channel", c + 1); - if (!hard_disk_is_valid(c) || (hdc[c].bus != HDD_BUS_MFM)) - { - config_delete_var(cat, temps); - } - else - { - config_set_int(cat, temps, hdc[c].mfm_channel); - } - - sprintf(temps, "hdd_%02i_xtide_channel", c + 1); - if (!hard_disk_is_valid(c) || (hdc[c].bus != HDD_BUS_XTIDE)) - { - config_delete_var(cat, temps); - } - else - { - config_set_int(cat, temps, hdc[c].xtide_channel); - } - - sprintf(temps, "hdd_%02i_esdi_channel", c + 1); - if (!hard_disk_is_valid(c) || (hdc[c].bus != HDD_BUS_ESDI)) - { - config_delete_var(cat, temps); - } - else - { - config_set_int(cat, temps, hdc[c].esdi_channel); - } - - sprintf(temps, "hdd_%02i_ide_channel", c + 1); - if (!hard_disk_is_valid(c) || ((hdc[c].bus != HDD_BUS_IDE_PIO_ONLY) && (hdc[c].bus != HDD_BUS_IDE_PIO_AND_DMA))) - { - config_delete_var(cat, temps); - } - else - { - sprintf(temps2, "%01u:%01u", hdc[c].ide_channel >> 1, hdc[c].ide_channel & 1); - config_set_string(cat, temps, temps2); - } - - sprintf(temps, "hdd_%02i_scsi_location", c + 1); - if (!hard_disk_is_valid(c) || ((hdc[c].bus != HDD_BUS_SCSI) && (hdc[c].bus != HDD_BUS_SCSI_REMOVABLE))) - { - config_delete_var(cat, temps); - } - else - { - sprintf(temps2, "%02u:%02u", hdc[c].scsi_id, hdc[c].scsi_lun); - config_set_string(cat, temps, temps2); - } - - sprintf(temps, "hdd_%02i_fn", c + 1); - if (!hard_disk_is_valid(c) || (wcslen(hdc[c].fn) == 0)) - { - config_delete_var(cat, temps); - } - else - { - config_set_wstring(cat, temps, hdc[c].fn); + if (cdrom_drives[c].ide_channel > 7) + cdrom_drives[c].ide_channel = 7; + else + config_delete_var(cat, temp); + } else { + sprintf(temp, "cdrom_%02i_scsi_location", c+1); + if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { + sprintf(tmp2, "%02u:%02u", c+2, 0); + p = config_get_string(cat, temp, tmp2); + sscanf(p, "%02u:%02u", + &cdrom_drives[c].scsi_device_id, + &cdrom_drives[c].scsi_device_lun); + + if (cdrom_drives[c].scsi_device_id > 15) + cdrom_drives[c].scsi_device_id = 15; + if (cdrom_drives[c].scsi_device_lun > 7) + cdrom_drives[c].scsi_device_lun = 7; + } else { + config_delete_var(cat, temp); } } - config_delete_section_if_empty(cat); + sprintf(temp, "cdrom_%02i_image_path", c+1); + wp = config_get_wstring(cat, temp, L""); + +#if 0 + /* + * NOTE: + * Temporary hack to remove the absolute + * path currently saved in most config + * files. We should remove this before + * finalizing this release! --FvK + */ + if (! wcsnicmp(wp, cfg_path, wcslen(cfg_path))) { + /* + * Yep, its absolute and prefixed + * with the EXE path. Just strip + * that off for now... + */ + wcsncpy(cdrom_image[c].image_path, &wp[wcslen(cfg_path)], sizeof_w(cdrom_image[c].image_path)); + } else +#endif + wcsncpy(cdrom_image[c].image_path, wp, sizeof_w(cdrom_image[c].image_path)); + wcscpy(cdrom_image[c].prev_image_path, cdrom_image[c].image_path); + + if (cdrom_drives[c].host_drive < 'A') + cdrom_drives[c].host_drive = 0; + + if ((cdrom_drives[c].host_drive == 0x200) && + (wcslen(cdrom_image[c].image_path) == 0)) + cdrom_drives[c].host_drive = 0; + + /* If the CD-ROM is disabled, delete all its variables. */ + if (cdrom_drives[c].bus_type == CDROM_BUS_DISABLED) { + sprintf(temp, "cdrom_%02i_host_drive", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_parameters", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_ide_channel", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_scsi_location", c+1); + config_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_image_path", c+1); + config_delete_var(cat, temp); + } + + sprintf(temp, "cdrom_%02i_iso_path", c+1); + config_delete_var(cat, temp); + } } -/* Removable devices */ -static void saveconfig_removable_devices(void) +/* Load the specified or a default configuration file. */ +void +config_load(wchar_t *fn) { - char *cat = "Removable devices"; - char temps[512]; - char temps2[512]; - int c; + if (fn == NULL) + fn = config_file_default; + pclog("Loading config file '%ls'..\n", fn); - memset(temps, '\0', sizeof(temps)); - for (c = 0; c < FDD_NUM; c++) - { - sprintf(temps, "fdd_%02i_type", c + 1); - if (fdd_get_type(c) == ((c < 2) ? 2 : 0)) - { - config_delete_var(cat, temps); - } - else - { - config_set_string(cat, temps, fdd_get_internal_name(fdd_get_type(c))); - } + if (! config_read(fn)) { + cpu = 0; +#ifdef USE_LANGUAGE + plat_langid = 0x0409; +#endif + scale = 1; + vid_api = 1; + enable_sync = 1; + joystick_type = 7; + strcpy(hdc_name, "none"); + serial_enabled[0] = 0; + serial_enabled[1] = 0; + lpt_enabled = 0; + fdd_set_type(0, 2); + fdd_set_type(1, 2); + mem_size = 640; - sprintf(temps, "fdd_%02i_fn", c + 1); - if (wcslen(floppyfns[c]) == 0) - { - config_delete_var(cat, temps); + pclog("Config file not present or invalid!\n"); + return; + } - ui_writeprot[c] = 0; + load_general(); /* General */ + load_machine(); /* Machine */ + load_video(); /* Video */ + load_input_devices(); /* Input devices */ + load_sound(); /* Sound */ + load_network(); /* Network */ + load_ports(); /* Ports (COM & LPT) */ + load_other_peripherals(); /* Other peripherals */ + load_hard_disks(); /* Hard disks */ + load_removable_devices(); /* Removable devices */ - sprintf(temps, "fdd_%02i_writeprot", c + 1); - config_delete_var(cat, temps); - } - else - { - config_set_wstring(cat, temps, floppyfns[c]); - } - - sprintf(temps, "fdd_%02i_writeprot", c + 1); - if (ui_writeprot[c] == 0) - { - config_delete_var(cat, temps); - } - else - { - config_set_int(cat, temps, ui_writeprot[c]); - } - - sprintf(temps, "fdd_%02i_turbo", c + 1); - if (fdd_get_turbo(c) == 0) - { - config_delete_var(cat, temps); - } - else - { - config_set_int(cat, temps, fdd_get_turbo(c)); - } - - sprintf(temps, "fdd_%02i_check_bpb", c + 1); - if (fdd_get_check_bpb(c) == 1) - { - config_delete_var(cat, temps); - } - else - { - config_set_int(cat, temps, fdd_get_check_bpb(c)); - } - } - - memset(temps, '\0', sizeof(temps)); - for (c = 0; c < CDROM_NUM; c++) - { - sprintf(temps, "cdrom_%02i_host_drive", c + 1); - if ((cdrom_drives[c].bus_type == 0) || (cdrom_drives[c].host_drive < 'A') || ((cdrom_drives[c].host_drive > 'Z') && (cdrom_drives[c].host_drive != 200))) - { - config_delete_var(cat, temps); - } - else - { - config_set_int(cat, temps, cdrom_drives[c].host_drive); - } - - sprintf(temps, "cdrom_%02i_parameters", c + 1); - if (cdrom_drives[c].bus_type == 0) - { - config_delete_var(cat, temps); - } - else - { - sprintf(temps2, "%u, %s", cdrom_drives[c].sound_on, config_bus_to_string(cdrom_drives[c].bus_type, 1)); - config_set_string(cat, temps, temps2); - } - - sprintf(temps, "cdrom_%02i_ide_channel", c + 1); - if ((cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_ONLY) && (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_AND_DMA)) - { - config_delete_var(cat, temps); - } - else - { - sprintf(temps2, "%01u:%01u", cdrom_drives[c].ide_channel >> 1, cdrom_drives[c].ide_channel & 1); - config_set_string(cat, temps, temps2); - } - - sprintf(temps, "cdrom_%02i_scsi_location", c + 1); - if (cdrom_drives[c].bus_type != CDROM_BUS_SCSI) - { - config_delete_var(cat, temps); - } - else - { - sprintf(temps2, "%02u:%02u", cdrom_drives[c].scsi_device_id, cdrom_drives[c].scsi_device_lun); - config_set_string(cat, temps, temps2); - } - - sprintf(temps, "cdrom_%02i_image_path", c + 1); - if ((cdrom_drives[c].bus_type == 0) || (wcslen(cdrom_image[c].image_path) == 0)) - { - config_delete_var(cat, temps); - } - else - { - config_set_wstring(cat, temps, cdrom_image[c].image_path); - } - } - - config_delete_section_if_empty(cat); + pclog("Config loaded.\n\n"); } -void saveconfig(void) +/* Save "General" section. */ +static void +save_general(void) { - /* General */ - saveconfig_general(); + char *cat = "General"; + char temp[512]; - /* Machine */ - saveconfig_machine(); + config_set_int(cat, "vid_resize", vid_resize); + if (vid_resize == 0) + config_delete_var(cat, "vid_resize"); - /* Video */ - saveconfig_video(); + if (vid_api == 1) { + config_delete_var(cat, "vid_renderer"); + } else switch(vid_api) { + case 0: + config_set_string(cat, "vid_renderer", "ddraw"); + break; - /* Input devices */ - saveconfig_input_devices(); + case 1: + default: + config_set_string(cat, "vid_renderer", "d3d9"); + break; - /* Sound */ - saveconfig_sound(); - -#ifdef USE_NETWORK - /* Network */ - saveconfig_network(); +#ifdef USE_VNC + case 2: + config_set_string(cat, "vid_renderer", "vnc"); + break; #endif - /* Ports (COM & LPT) */ - saveconfig_ports(); +#ifdef USE_RDP + case 3: + config_set_string(cat, "vid_renderer", "rdp"); + break; +#endif + } - /* Other peripherals */ - saveconfig_other_peripherals(); + if (video_fullscreen_scale == 0) + config_delete_var(cat, "video_fullscreen_scale"); + else + config_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale); - /* Hard disks */ - saveconfig_hard_disks(); + if (video_fullscreen_first == 0) + config_delete_var(cat, "video_fullscreen_first"); + else + config_set_int(cat, "video_fullscreen_first", video_fullscreen_first); - /* Removable devices */ - saveconfig_removable_devices(); + if (force_43 == 0) + config_delete_var(cat, "force_43"); + else + config_set_int(cat, "force_43", force_43); - config_save(config_file_default); + if (scale == 1) + config_delete_var(cat, "scale"); + else + config_set_int(cat, "scale", scale); + + if (enable_overscan == 0) + config_delete_var(cat, "enable_overscan"); + else + config_set_int(cat, "enable_overscan", enable_overscan); + + if (vid_cga_contrast == 0) + config_delete_var(cat, "vid_cga_contrast"); + else + config_set_int(cat, "vid_cga_contrast", vid_cga_contrast); + + if (video_grayscale == 0) + config_delete_var(cat, "video_grayscale"); + else + config_set_int(cat, "video_grayscale", video_grayscale); + + if (video_graytype == 0) + config_delete_var(cat, "video_graytype"); + else + config_set_int(cat, "video_graytype", video_graytype); + + if (window_remember) { + config_set_int(cat, "window_remember", window_remember); + + sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y); + config_set_string(cat, "window_coordinates", temp); + } else { + config_delete_var(cat, "window_remember"); + config_delete_var(cat, "window_coordinates"); + } + +#ifdef USE_LANGUAGE + if (plat_langid == 0x0409) + config_delete_var(cat, "language"); + else + config_set_hex16(cat, "language", plat_langid); +#endif + + delete_section_if_empty(cat); +} + + +/* Save "Machine" section. */ +static void +save_machine(void) +{ + char *cat = "Machine"; + + config_set_string(cat, "machine", machine_get_internal_name()); + + if (cpu_manufacturer == 0) + config_delete_var(cat, "cpu_manufacturer"); + else + config_set_int(cat, "cpu_manufacturer", cpu_manufacturer); + + if (cpu == 0) + config_delete_var(cat, "cpu"); + else + config_set_int(cat, "cpu", cpu); + + if (cpu_waitstates == 0) + config_delete_var(cat, "cpu_waitstates"); + else + config_set_int(cat, "cpu_waitstates", cpu_waitstates); + + if (mem_size == 4096) + config_delete_var(cat, "mem_size"); + else + config_set_int(cat, "mem_size", mem_size); + + config_set_int(cat, "cpu_use_dynarec", cpu_use_dynarec); + + if (enable_external_fpu == 0) + config_delete_var(cat, "cpu_enable_fpu"); + else + config_set_int(cat, "cpu_enable_fpu", enable_external_fpu); + + if (enable_sync == 1) + config_delete_var(cat, "enable_sync"); + else + config_set_int(cat, "enable_sync", enable_sync); + + delete_section_if_empty(cat); +} + + +/* Save "Video" section. */ +static void +save_video(void) +{ + char *cat = "Video"; + + config_set_string(cat, "gfxcard", + video_get_internal_name(video_old_to_new(gfxcard))); + + if (video_speed == 3) + config_delete_var(cat, "video_speed"); + else + config_set_int(cat, "video_speed", video_speed); + + if (voodoo_enabled == 0) + config_delete_var(cat, "voodoo"); + else + config_set_int(cat, "voodoo", voodoo_enabled); + + delete_section_if_empty(cat); +} + + +/* Save "Input Devices" section. */ +static void +save_input_devices(void) +{ + char *cat = "Input devices"; + char temp[512], tmp2[512]; + int c, d; + + config_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type)); + + if ((joystick_type == 0) || (joystick_type == 7)) { + if (joystick_type == 7) + config_delete_var(cat, "joystick_type"); + else + config_set_int(cat, "joystick_type", joystick_type); + + for (c=0; c<16; c++) { + sprintf(tmp2, "joystick_%i_nr", c); + config_delete_var(cat, tmp2); + + for (d=0; d<16; d++) { + sprintf(tmp2, "joystick_%i_axis_%i", c, d); + config_delete_var(cat, tmp2); + } + for (d=0; d<16; d++) { + sprintf(tmp2, "joystick_%i_button_%i", c, d); + config_delete_var(cat, tmp2); + } + for (d=0; d<16; d++) { + sprintf(tmp2, "joystick_%i_pov_%i", c, d); + config_delete_var(cat, tmp2); + } + } + } else { + config_set_int(cat, "joystick_type", joystick_type); + + for (c=0; c> 1, hdd[c].ide_channel & 1); + config_set_string(cat, temp, tmp2); + } + + sprintf(temp, "hdd_%02i_scsi_location", c+1); + if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_SCSI) && (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE))) { + config_delete_var(cat, temp); + } else { + sprintf(tmp2, "%02u:%02u", hdd[c].scsi_id, hdd[c].scsi_lun); + config_set_string(cat, temp, tmp2); + } + + sprintf(temp, "hdd_%02i_fn", c+1); + if (hdd_is_valid(c) && (wcslen(hdd[c].fn) != 0)) + config_set_wstring(cat, temp, hdd[c].fn); + else + config_delete_var(cat, temp); + } + + delete_section_if_empty(cat); +} + + +/* Save "Removable Devices" section. */ +static void +save_removable_devices(void) +{ + char *cat = "Removable devices"; + char temp[512], tmp2[512]; + int c; + + for (c=0; c 'Z') && (cdrom_drives[c].host_drive != 200))) { + config_delete_var(cat, temp); + } else { + config_set_int(cat, temp, cdrom_drives[c].host_drive); + } + + sprintf(temp, "cdrom_%02i_parameters", c+1); + if (cdrom_drives[c].bus_type == 0) { + config_delete_var(cat, temp); + } else { + sprintf(tmp2, "%u, %s", cdrom_drives[c].sound_on, + hdd_bus_to_string(cdrom_drives[c].bus_type, 1)); + config_set_string(cat, temp, tmp2); + } + + sprintf(temp, "cdrom_%02i_ide_channel", c+1); + if ((cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_ONLY) && + (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_AND_DMA)) { + config_delete_var(cat, temp); + } else { + sprintf(tmp2, "%01u:%01u", cdrom_drives[c].ide_channel>>1, + cdrom_drives[c].ide_channel & 1); + config_set_string(cat, temp, tmp2); + } + + sprintf(temp, "cdrom_%02i_scsi_location", c + 1); + if (cdrom_drives[c].bus_type != CDROM_BUS_SCSI) { + config_delete_var(cat, temp); + } else { + sprintf(tmp2, "%02u:%02u", cdrom_drives[c].scsi_device_id, + cdrom_drives[c].scsi_device_lun); + config_set_string(cat, temp, tmp2); + } + + sprintf(temp, "cdrom_%02i_image_path", c + 1); + if ((cdrom_drives[c].bus_type == 0) || + (wcslen(cdrom_image[c].image_path) == 0)) { + config_delete_var(cat, temp); + } else { + config_set_wstring(cat, temp, cdrom_image[c].image_path); + } + } + + delete_section_if_empty(cat); +} + + +void +config_save(void) +{ + save_general(); /* General */ + save_machine(); /* Machine */ + save_video(); /* Video */ + save_input_devices(); /* Input devices */ + save_sound(); /* Sound */ + save_network(); /* Network */ + save_ports(); /* Ports (COM & LPT) */ + save_other_peripherals(); /* Other peripherals */ + save_hard_disks(); /* Hard disks */ + save_removable_devices(); /* Removable devices */ + + config_write(config_file_default); +} + + +void +config_dump(void) +{ + section_t *sec; + + sec = (section_t *)config_head.next; + while (sec != NULL) { + entry_t *ent; + + if (sec->name && sec->name[0]) + pclog("[%s]\n", sec->name); + + ent = (entry_t *)sec->entry_head.next; + while (ent != NULL) { + pclog("%s = %ls\n", ent->name, ent->wdata); + + ent = (entry_t *)ent->list.next; + } + + sec = (section_t *)sec->list.next; + } +} + + +void +config_delete_var(char *head, char *name) +{ + section_t *section; + entry_t *entry; + + section = find_section(head); + if (section == NULL) return; + + entry = find_entry(section, name); + if (entry != NULL) { + list_delete(&entry->list, §ion->entry_head); + free(entry); + } +} + + +int +config_get_int(char *head, char *name, int def) +{ + section_t *section; + entry_t *entry; + int value; + + section = find_section(head); + if (section == NULL) + return(def); + + entry = find_entry(section, name); + if (entry == NULL) + return(def); + + sscanf(entry->data, "%i", &value); + + return(value); +} + + +int +config_get_hex16(char *head, char *name, int def) +{ + section_t *section; + entry_t *entry; + int value; + + section = find_section(head); + if (section == NULL) + return(def); + + entry = find_entry(section, name); + if (entry == NULL) + return(def); + + sscanf(entry->data, "%04X", &value); + + return(value); +} + + +int +config_get_hex20(char *head, char *name, int def) +{ + section_t *section; + entry_t *entry; + int value; + + section = find_section(head); + if (section == NULL) + return(def); + + entry = find_entry(section, name); + if (entry == NULL) + return(def); + + sscanf(entry->data, "%05X", &value); + + return(value); +} + + +int +config_get_mac(char *head, char *name, int def) +{ + section_t *section; + entry_t *entry; + int val0 = 0, val1 = 0, val2 = 0; + + section = find_section(head); + if (section == NULL) + return(def); + + entry = find_entry(section, name); + if (entry == NULL) + return(def); + + sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2); + + return((val0 << 16) + (val1 << 8) + val2); +} + + +char * +config_get_string(char *head, char *name, char *def) +{ + section_t *section; + entry_t *entry; + + section = find_section(head); + if (section == NULL) + return(def); + + entry = find_entry(section, name); + if (entry == NULL) + return(def); + + return(entry->data); +} + + +wchar_t * +config_get_wstring(char *head, char *name, wchar_t *def) +{ + section_t *section; + entry_t *entry; + + section = find_section(head); + if (section == NULL) + return(def); + + entry = find_entry(section, name); + if (entry == NULL) + return(def); + + return(entry->wdata); +} + + +void +config_set_int(char *head, char *name, int val) +{ + section_t *section; + entry_t *ent; + + section = find_section(head); + if (section == NULL) + section = create_section(head); + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%i", val); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); +} + + +void +config_set_hex16(char *head, char *name, int val) +{ + section_t *section; + entry_t *ent; + + section = find_section(head); + if (section == NULL) + section = create_section(head); + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%04X", val); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); +} + + +void +config_set_hex20(char *head, char *name, int val) +{ + section_t *section; + entry_t *ent; + + section = find_section(head); + if (section == NULL) + section = create_section(head); + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%05X", val); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); +} + + +void +config_set_mac(char *head, char *name, int val) +{ + section_t *section; + entry_t *ent; + + section = find_section(head); + if (section == NULL) + section = create_section(head); + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%02x:%02x:%02x", + (val>>16)&0xff, (val>>8)&0xff, val&0xff); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); +} + + +void +config_set_string(char *head, char *name, char *val) +{ + section_t *section; + entry_t *ent; + + section = find_section(head); + if (section == NULL) + section = create_section(head); + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + strncpy(ent->data, val, sizeof(ent->data)); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); +} + + +void +config_set_wstring(char *head, char *name, wchar_t *val) +{ + section_t *section; + entry_t *ent; + + section = find_section(head); + if (section == NULL) + section = create_section(head); + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + memcpy(ent->wdata, val, sizeof_w(ent->wdata)); + wcstombs(ent->data, ent->wdata, sizeof(ent->data)); +} + + +/* FIXME: should be moved elsewhere. --FvK */ +wchar_t * +get_filename_w(wchar_t *s) +{ + int c = wcslen(s) - 1; + + while (c > 0) { + if (s[c] == L'/' || s[c] == L'\\') + return(&s[c+1]); + c--; + } + + return(s); +} + + +/* FIXME: should be moved elsewhere. --FvK */ +void +append_filename_w(wchar_t *dest, wchar_t *s1, wchar_t *s2, int size) +{ + wcscat(dest, s1); + wcscat(dest, s2); +} + + +/* FIXME: should be moved elsewhere. --FvK */ +void +put_backslash_w(wchar_t *s) +{ + int c = wcslen(s) - 1; + + if (s[c] != L'/' && s[c] != L'\\') + s[c] = L'/'; +} + + +/* FIXME: should be moved elsewhere. --FvK */ +wchar_t +*get_extension_w(wchar_t *s) +{ + int c = wcslen(s) - 1; + + if (c <= 0) + return(s); + + while (c && s[c] != L'.') + c--; + + if (!c) + return(&s[wcslen(s)]); + + return(&s[c+1]); } diff --git a/src/config.h b/src/config.h index 352d19faa..bca7591d2 100644 --- a/src/config.h +++ b/src/config.h @@ -8,12 +8,13 @@ * * Configuration file handler header. * - * Version: @(#)config.h 1.0.1 2017/08/23 + * Version: @(#)config.h 1.0.3 2017/10/13 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * Overdoze, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. * Copyright 2017 Fred N. van Kempen. @@ -29,13 +30,18 @@ extern wchar_t config_file_default[256]; extern "C" { #endif +extern void config_load(wchar_t *fn); +extern void config_save(void); +extern void config_write(wchar_t *fn); +extern void config_dump(void); + +extern void config_delete_var(char *head, char *name); extern int config_get_int(char *head, char *name, int def); extern int config_get_hex16(char *head, char *name, int def); extern int config_get_hex20(char *head, char *name, int def); extern int config_get_mac(char *head, char *name, int def); extern char *config_get_string(char *head, char *name, char *def); extern wchar_t *config_get_wstring(char *head, char *name, wchar_t *def); -extern void config_delete_var(char *head, char *name); extern void config_set_int(char *head, char *name, int val); extern void config_set_hex16(char *head, char *name, int val); extern void config_set_hex20(char *head, char *name, int val); @@ -43,22 +49,11 @@ extern void config_set_mac(char *head, char *name, int val); extern void config_set_string(char *head, char *name, char *val); extern void config_set_wstring(char *head, char *name, wchar_t *val); -extern char *get_filename(char *s); extern wchar_t *get_filename_w(wchar_t *s); -extern void append_filename(char *dest, char *s1, char *s2, int size); extern void append_filename_w(wchar_t *dest, wchar_t *s1, wchar_t *s2, int size); -extern void put_backslash(char *s); extern void put_backslash_w(wchar_t *s); -extern char *get_extension(char *s); - extern wchar_t *get_extension_w(wchar_t *s); -extern int config_load(wchar_t *fn); -extern void config_save(wchar_t *fn); -extern void config_dump(void); - -extern void loadconfig(wchar_t *fn); -extern void saveconfig(void); #ifdef __cplusplus } diff --git a/src/cpu/386.c b/src/cpu/386.c index 08bd8bf41..4bbb87976 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -1,10 +1,12 @@ +#include +#include +#include +#include +#include #include #ifndef INFINITY # define INFINITY (__builtin_inff()) #endif -#include -#include -#include #include "../ibm.h" #include "cpu.h" #include "x86.h" @@ -39,21 +41,15 @@ x86seg _oldds; extern int cpl_override; -int has_fpu; extern int fpucount; uint16_t rds; uint16_t ea_rseg; -int is486; int cgate32; uint32_t cr2, cr3, cr4; uint32_t dr[8]; - -uint8_t romext[32768]; -uint8_t *ram,*rom; - uint32_t rmdat32; #define rmdat rmdat32 #define fetchdat rmdat32 diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 8ff50b946..1c4200b1a 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -1,21 +1,26 @@ +#include +#include +#include +#include +#include #include #ifndef INFINITY # define INFINITY (__builtin_inff()) #endif -#include -#include -#include #include "../ibm.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" #include "../mem.h" +#include "../nmi.h" #include "../pic.h" #include "../timer.h" #include "../floppy/floppy.h" #include "../floppy/fdc.h" +#ifdef USE_DYNAREC #include "codegen.h" +#endif #include "386_common.h" @@ -43,18 +48,12 @@ int trap; int cpl_override=0; -int has_fpu; int fpucount=0; uint16_t rds; uint16_t ea_rseg; -int is486; int cgate32; - -uint8_t romext[32768]; -uint8_t *ram,*rom; - uint32_t rmdat32; uint32_t backupregs[16]; int oddeven=0; @@ -503,6 +502,7 @@ static int cpu_cycle_period(void) } } +#ifdef USE_DYNAREC static int cycles_main = 0; void exec386_dynarec(int cycs) { @@ -606,6 +606,9 @@ void exec386_dynarec(int cycs) if (trap) CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + ins++; insc++; @@ -754,6 +757,9 @@ inrecomp=0; if (trap) CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + if (cpu_state.abrt) { @@ -822,6 +828,9 @@ inrecomp=0; if (trap) CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + if (cpu_state.abrt) { @@ -888,6 +897,19 @@ inrecomp=0; loadcs(readmemw(0,addr+2)); } } + else if (nmi && nmi_enable && nmi_mask) + { + cpu_state.oldpc = cpu_state.pc; + oldcs = CS; + pclog("NMI\n"); + x86_int(2); + nmi_enable = 0; + if (nmi_auto_clear) + { + nmi_auto_clear = 0; + nmi = 0; + } + } else if ((flags&I_FLAG) && pic_intpending) { temp=picinterrupt(); @@ -931,3 +953,4 @@ inrecomp=0; cycles_main -= (cycles_start - cycles); } } +#endif diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c index e0e018872..5e7a6692c 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu/386_dynarec_ops.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include #ifndef INFINITY # define INFINITY (__builtin_inff()) @@ -9,6 +13,7 @@ #include "x87.h" #include "x86_flags.h" #include "../mem.h" +#include "../nmi.h" #include "codegen.h" #include "../pic.h" diff --git a/src/cpu/808x.c b/src/cpu/808x.c index d948031ba..3d77f2018 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1,4 +1,4 @@ -/* +/* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM * PC systems and compatibles from 1981 through fairly recent @@ -8,34 +8,41 @@ * * 808x CPU emulation. * - * Version: @(#)808x.c 1.0.0 2017/05/30 + * SHR AX,1 * - * Author: Sarah Walker, + * 4 clocks - fetch opcode + * 4 clocks - fetch mod/rm + * 2 clocks - execute 2 clocks - fetch opcode 1 + * 2 clocks - fetch opcode 2 + * 4 clocks - fetch mod/rm + * 2 clocks - fetch opcode 1 2 clocks - execute + * 2 clocks - fetch opcode 2 etc + * + * Version: @(#)808x.c 1.0.4 2017/10/12 + * + * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - -/*SHR AX,1 - - 4 clocks - fetch opcode - 4 clocks - fetch mod/rm - 2 clocks - execute 2 clocks - fetch opcode 1 - 2 clocks - fetch opcode 2 - 4 clocks - fetch mod/rm - 2 clocks - fetch opcode 1 2 clocks - execute - 2 clocks - fetch opcode 2 etc*/ #include -#include +#include +#include +#include #include "../ibm.h" #include "cpu.h" #include "x86.h" -#include "../keyboard.h" #include "../mem.h" +#include "../rom.h" #include "../nmi.h" #include "../pic.h" #include "../timer.h" -#include "../scsi/scsi.h" +#include "../device.h" /* for scsi.h */ +#include "../keyboard.h" /* its WRONG to have this in here!! --FvK */ +#include "../scsi/scsi.h" /* its WRONG to have this in here!! --FvK */ +#include "../plat.h" + int xt_cpu_multi; int nmi = 0; @@ -127,7 +134,10 @@ int noint=0; int output=0; +#if 0 +/* Also in mem.c */ int shadowbios=0; +#endif int ins=0; @@ -483,7 +493,10 @@ void makeznptable() if (c&0x8000) znptable16[c]|=N_FLAG; } } +#if 1 +/* Also in mem.c */ int timetolive=0; +#endif extern uint32_t oldcs2; extern uint32_t oldpc2; @@ -503,7 +516,7 @@ void dumpregs(int force) #ifndef RELEASE_BUILD indump = 1; output=0; - _wchdir(pcempath); + (void)plat_chdir(cfg_path); nopageerrors=1; f=fopen("ram.dmp","wb"); fwrite(ram,mem_size*1024,1,f); @@ -600,7 +613,9 @@ void resetx86() mmu_perm=4; memset(inscounts, 0, sizeof(inscounts)); x86seg_reset(); +#ifdef USE_DYNAREC codegen_reset(); +#endif x86_was_reset = 1; port_92_clear_reset(); scsi_card_reset(); diff --git a/src/cpu/codegen.c b/src/cpu/codegen.c index afe795601..e3773089b 100644 --- a/src/cpu/codegen.c +++ b/src/cpu/codegen.c @@ -1,6 +1,10 @@ +#include +#include +#include +#include #include "../ibm.h" -#include "x86_ops.h" #include "../mem.h" +#include "x86_ops.h" #include "codegen.h" void (*codegen_timing_start)(); diff --git a/src/cpu/codegen_ops.c b/src/cpu/codegen_ops.c index c91a0d9db..309241c0e 100644 --- a/src/cpu/codegen_ops.c +++ b/src/cpu/codegen_ops.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "x86.h" diff --git a/src/cpu/codegen_ops_x86-64.h b/src/cpu/codegen_ops_x86-64.h index f6ec2f055..773829b1d 100644 --- a/src/cpu/codegen_ops_x86-64.h +++ b/src/cpu/codegen_ops_x86-64.h @@ -543,7 +543,7 @@ static x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, u } else { - int base_reg, index_reg; + int base_reg = 0, index_reg = 0; switch (rm) { diff --git a/src/cpu/codegen_timing_486.c b/src/cpu/codegen_timing_486.c index 8317e2c49..56f654313 100644 --- a/src/cpu/codegen_timing_486.c +++ b/src/cpu/codegen_timing_486.c @@ -1,9 +1,13 @@ +#include +#include +#include +#include #include "../ibm.h" +#include "../mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" -#include "../mem.h" #include "codegen.h" #include "codegen_ops.h" #include "codegen_timing_common.h" diff --git a/src/cpu/codegen_timing_686.c b/src/cpu/codegen_timing_686.c index f62e63429..17ec4ab43 100644 --- a/src/cpu/codegen_timing_686.c +++ b/src/cpu/codegen_timing_686.c @@ -8,13 +8,16 @@ - FPU queue - Out of order execution (beyond most simplistic approximation) */ - +#include +#include +#include +#include #include "../ibm.h" +#include "../mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" -#include "../mem.h" #include "codegen.h" #include "codegen_timing_common.h" diff --git a/src/cpu/codegen_timing_common.c b/src/cpu/codegen_timing_common.c index d32247f35..d02ff2a42 100644 --- a/src/cpu/codegen_timing_common.c +++ b/src/cpu/codegen_timing_common.c @@ -1,6 +1,11 @@ +#include +#include +#include +#include #include "../ibm.h" #include "codegen_timing_common.h" + uint64_t opcode_deps[256] = { /* ADD ADD ADD ADD*/ diff --git a/src/cpu/codegen_timing_pentium.c b/src/cpu/codegen_timing_pentium.c index 74f4a0f3d..95edbe1d6 100644 --- a/src/cpu/codegen_timing_pentium.c +++ b/src/cpu/codegen_timing_pentium.c @@ -9,19 +9,21 @@ - PMMX decode queue - MMX latencies */ - +#include +#include +#include +#include #include "../ibm.h" +#include "../mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" -#include "../mem.h" #include "codegen.h" #include "codegen_ops.h" #include "codegen_timing_common.h" - /*Instruction has different execution time for 16 and 32 bit data. Does not pair */ #define CYCLES_HAS_MULTI (1 << 28) diff --git a/src/cpu/codegen_timing_winchip.c b/src/cpu/codegen_timing_winchip.c index 2726bbcc9..06644e90f 100644 --- a/src/cpu/codegen_timing_winchip.c +++ b/src/cpu/codegen_timing_winchip.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "cpu.h" #include "x86.h" diff --git a/src/cpu/codegen_x86-64.c b/src/cpu/codegen_x86-64.c index 6a3e714f1..671630021 100644 --- a/src/cpu/codegen_x86-64.c +++ b/src/cpu/codegen_x86-64.c @@ -1,6 +1,10 @@ #ifdef __amd64__ +#include +#include +#include #include +#include #include "../ibm.h" #include "../mem.h" #include "cpu.h" @@ -60,7 +64,9 @@ static int last_ssegs; void codegen_init() { +#if UNUSED int c; +#endif #ifdef __linux__ void *start; size_t len; @@ -234,7 +240,9 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) void codegen_block_init(uint32_t phys_addr) { codeblock_t *block; +#if UNUSED int has_evicted = 0; +#endif page_t *page = &pages[phys_addr >> 12]; if (!page->block[(phys_addr >> 10) & 3]) @@ -274,7 +282,9 @@ void codegen_block_init(uint32_t phys_addr) void codegen_block_start_recompile(codeblock_t *block) { +#if UNUSED int has_evicted = 0; +#endif page_t *page = &pages[block->phys >> 12]; if (!page->block[(block->phys >> 10) & 3]) @@ -590,7 +600,7 @@ static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, } else { - int base_reg, index_reg; + int base_reg = 0, index_reg = 0; switch (cpu_rm) { @@ -1074,11 +1084,11 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t generate_call: codegen_timing_opcode(opcode, fetchdat, op_32); - if ((op_table == x86_dynarec_opcodes && - ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || - (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || - (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30))) || - (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80)))) + if (((op_table == x86_dynarec_opcodes) && + (((opcode & 0xf0) == 0x70) || ((opcode & 0xfc) == 0xe0) || (opcode == 0xc2) || + ((opcode & 0xfe) == 0xca) || ((opcode & 0xfc) == 0xcc) || ((opcode & 0xfc) == 0xe8) || + ((opcode == 0xff) && (((fetchdat & 0x38) >= 0x10) && ((fetchdat & 0x38) < 0x30)))) || + ((op_table == x86_dynarec_opcodes_0f) && ((opcode & 0xf0) == 0x80)))) { /*Opcode is likely to cause block to exit, update cycle count*/ if (codegen_block_cycles) diff --git a/src/cpu/codegen_x86.c b/src/cpu/codegen_x86.c index b8f4be818..1b03efdfd 100644 --- a/src/cpu/codegen_x86.c +++ b/src/cpu/codegen_x86.c @@ -1,13 +1,17 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#include +#include #include +#include #include "../ibm.h" +#include "../mem.h" #include "cpu.h" #include "x86.h" #include "x86_flags.h" #include "x86_ops.h" #include "x87.h" -#include "../mem.h" #include "386_common.h" diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 843d5204d..a0d474b65 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -8,15 +8,20 @@ * * CPU type handler. * - * Version: @(#)cpu.c 1.0.1 2017/06/03 + * Version: @(#)cpu.c 1.0.4 2017/10/14 * * Authors: Sarah Walker, * leilei, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016-2017 leilei. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "../ibm.h" #include "cpu.h" #include "../device.h" @@ -25,11 +30,14 @@ #include "x86_ops.h" #include "../mem.h" #include "../pci.h" +#ifdef USE_DYNAREC #include "codegen.h" +#endif int isa_cycles; static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6; +#ifdef USE_DYNAREC OpFn *x86_dynarec_opcodes; OpFn *x86_dynarec_opcodes_0f; OpFn *x86_dynarec_opcodes_d8_a16; @@ -50,6 +58,7 @@ OpFn *x86_dynarec_opcodes_df_a16; OpFn *x86_dynarec_opcodes_df_a32; OpFn *x86_dynarec_opcodes_REPE; OpFn *x86_dynarec_opcodes_REPNE; +#endif OpFn *x86_opcodes; OpFn *x86_opcodes_0f; @@ -110,7 +119,7 @@ int cpu_waitstates; int cpu_cache_int_enabled, cpu_cache_ext_enabled; int cpu_pci_speed; -int is286, is386; +int is286, is386, is486; int israpidcad, is_pentium; uint64_t tsc = 0; @@ -255,6 +264,13 @@ CPU cpus_ibmat[] = {"", -1, 0, 0, 0, 0} }; +CPU cpus_ibmxt286[] = +{ + /*286*/ + {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2}, + {"", -1, 0, 0, 0, 0} +}; + CPU cpus_ps1_m2011[] = { /*286*/ @@ -676,12 +692,19 @@ void cpu_set() pclog("hasfpu - %i\n",hasfpu); pclog("is486 - %i %i\n",is486,cpu_s->cpu_type); +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f); +#else + x86_setopcodes(ops_386, ops_386_0f); +#endif x86_opcodes_REPE = ops_REPE; x86_opcodes_REPNE = ops_REPNE; +#ifdef USE_DYNAREC x86_dynarec_opcodes_REPE = dynarec_ops_REPE; x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE; +#endif +#ifdef USE_DYNAREC if (hasfpu) { x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16; @@ -721,6 +744,7 @@ void cpu_set() x86_dynarec_opcodes_df_a32 = dynarec_ops_nofpu_a32; } codegen_timing_set(&codegen_timing_486); +#endif if (hasfpu) { @@ -773,9 +797,14 @@ void cpu_set() break; case CPU_286: +#ifdef USE_DYNAREC x86_setopcodes(ops_286, ops_286_0f, dynarec_ops_286, dynarec_ops_286_0f); +#else + x86_setopcodes(ops_286, ops_286_0f); +#endif if (enable_external_fpu) { +#ifdef USE_DYNAREC x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; @@ -790,6 +819,7 @@ void cpu_set() x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; +#endif x86_opcodes_d9_a16 = ops_fpu_287_d9_a16; x86_opcodes_d9_a32 = ops_fpu_287_d9_a32; x86_opcodes_da_a16 = ops_fpu_287_da_a16; @@ -929,7 +959,11 @@ void cpu_set() break; case CPU_486SLC: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 3; /*register dest - memory src*/ timing_mr = 5; /*memory dest - register src*/ @@ -963,7 +997,11 @@ void cpu_set() break; case CPU_486DLC: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 3; /*register dest - memory src*/ timing_mr = 3; /*memory dest - register src*/ @@ -1002,7 +1040,11 @@ void cpu_set() cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME; case CPU_i486SX: case CPU_i486DX: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ timing_mr = 3; /*memory dest - register src*/ @@ -1037,7 +1079,11 @@ void cpu_set() case CPU_Am486SX: case CPU_Am486DX: /*AMD timing identical to Intel*/ +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ timing_mr = 3; /*memory dest - register src*/ @@ -1071,7 +1117,11 @@ void cpu_set() case CPU_Cx486S: case CPU_Cx486DX: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 3; /*register dest - memory src*/ timing_mr = 3; /*memory dest - register src*/ @@ -1104,7 +1154,11 @@ void cpu_set() break; case CPU_Cx5x86: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 1; /*register dest - memory src*/ timing_mr = 2; /*memory dest - register src*/ @@ -1138,7 +1192,11 @@ void cpu_set() break; case CPU_WINCHIP: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_winchip_0f, dynarec_ops_386, dynarec_ops_winchip_0f); +#else + x86_setopcodes(ops_386, ops_winchip_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ timing_mr = 2; /*memory dest - register src*/ @@ -1172,13 +1230,19 @@ void cpu_set() timing_jmp_rm = 5; timing_jmp_pm = 7; timing_jmp_pm_gate = 17; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_winchip); +#endif timing_misaligned = 2; cpu_cyrix_alignment = 1; break; case CPU_PENTIUM: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); +#else + x86_setopcodes(ops_386, ops_pentium_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ timing_mr = 3; /*memory dest - register src*/ @@ -1215,11 +1279,17 @@ void cpu_set() cpu_hasCR4 = 1; cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_pentium); +#endif break; case CPU_PENTIUMMMX: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); +#else + x86_setopcodes(ops_386, ops_pentiummmx_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ timing_mr = 3; /*memory dest - register src*/ @@ -1256,11 +1326,17 @@ void cpu_set() cpu_hasCR4 = 1; cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_pentium); +#endif break; case CPU_Cx6x86: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); +#else + x86_setopcodes(ops_386, ops_pentium_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 1; /*register dest - memory src*/ timing_mr = 2; /*memory dest - register src*/ @@ -1295,12 +1371,18 @@ void cpu_set() cpu_hasMMX = 0; cpu_hasMSR = 0; cpu_hasCR4 = 0; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); +#endif CPUID = 0; /*Disabled on powerup by default*/ break; case CPU_Cx6x86L: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); +#else + x86_setopcodes(ops_386, ops_pentium_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 1; /*register dest - memory src*/ timing_mr = 2; /*memory dest - register src*/ @@ -1335,13 +1417,19 @@ void cpu_set() cpu_hasMMX = 0; cpu_hasMSR = 0; cpu_hasCR4 = 0; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); +#endif ccr4 = 0x80; break; case CPU_CxGX1: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); +#else + x86_setopcodes(ops_386, ops_pentium_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 1; /*register dest - memory src*/ timing_mr = 2; /*memory dest - register src*/ @@ -1359,11 +1447,14 @@ void cpu_set() cpu_hasMSR = 1; cpu_hasCR4 = 1; cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); +#endif break; case CPU_Cx6x86MX: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; @@ -1371,6 +1462,9 @@ void cpu_set() x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; +#else + x86_setopcodes(ops_386, ops_c6x86mx_0f); +#endif x86_opcodes_da_a16 = ops_fpu_686_da_a16; x86_opcodes_da_a32 = ops_fpu_686_da_a32; x86_opcodes_db_a16 = ops_fpu_686_db_a16; @@ -1412,13 +1506,19 @@ void cpu_set() cpu_hasMSR = 1; cpu_hasCR4 = 1; cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); +#endif ccr4 = 0x80; break; case CPU_K5: case CPU_5K86: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); +#else + x86_setopcodes(ops_386, ops_k6_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ timing_mr = 3; /*memory dest - register src*/ @@ -1438,7 +1538,11 @@ void cpu_set() break; case CPU_K6: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); +#else + x86_setopcodes(ops_386, ops_k6_0f); +#endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ timing_mr = 3; /*memory dest - register src*/ @@ -1456,10 +1560,13 @@ void cpu_set() cpu_hasCR4 = 1; cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_pentium); +#endif break; case CPU_PENTIUMPRO: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f); x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; @@ -1467,6 +1574,9 @@ void cpu_set() x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; +#else + x86_setopcodes(ops_386, ops_pentiumpro_0f); +#endif x86_opcodes_da_a16 = ops_fpu_686_da_a16; x86_opcodes_da_a32 = ops_fpu_686_da_a32; x86_opcodes_db_a16 = ops_fpu_686_db_a16; @@ -1490,11 +1600,14 @@ void cpu_set() cpu_hasCR4 = 1; cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); +#endif break; #if 0 case CPU_PENTIUM2: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f); x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; @@ -1502,6 +1615,9 @@ void cpu_set() x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; +#else + x86_setopcodes(ops_386, ops_pentium2_0f); +#endif x86_opcodes_da_a16 = ops_fpu_686_da_a16; x86_opcodes_da_a32 = ops_fpu_686_da_a32; x86_opcodes_db_a16 = ops_fpu_686_db_a16; @@ -1525,11 +1641,14 @@ void cpu_set() cpu_hasCR4 = 1; cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); +#endif break; #endif case CPU_PENTIUM2D: +#ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium2d_0f, dynarec_ops_386, dynarec_ops_pentium2d_0f); x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; @@ -1537,6 +1656,9 @@ void cpu_set() x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; +#else + x86_setopcodes(ops_386, ops_pentium2d_0f); +#endif x86_opcodes_da_a16 = ops_fpu_686_da_a16; x86_opcodes_da_a32 = ops_fpu_686_da_a32; x86_opcodes_db_a16 = ops_fpu_686_db_a16; @@ -1560,7 +1682,9 @@ void cpu_set() cpu_hasCR4 = 1; cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE | CR4_OSFXSR; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); +#endif break; default: @@ -2452,6 +2576,7 @@ uint8_t cyrix_read(uint16_t addr, void *priv) return 0xff; } +#ifdef USE_DYNAREC void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn *dynarec_opcodes_0f) { x86_opcodes = opcodes; @@ -2459,6 +2584,13 @@ void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn x86_dynarec_opcodes = dynarec_opcodes; x86_dynarec_opcodes_0f = dynarec_opcodes_0f; } +#else +void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f) +{ + x86_opcodes = opcodes; + x86_opcodes_0f = opcodes_0f; +} +#endif void cpu_update_waitstates() { diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 0cdc29513..793c141f4 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -8,18 +8,18 @@ * * CPU type handler. * - * Version: @(#)cpu.h 1.0.0 2017/05/30 + * Version: @(#)cpu.h 1.0.2 2017/10/14 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * leilei, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016-2017 leilei. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - -#ifndef _CPU_H_ -#define _CPU_H_ +#ifndef EMU_CPU_H +# define EMU_CPU_H extern int cpu, cpu_manufacturer; @@ -130,6 +130,7 @@ extern CPU cpus_pcjr[]; extern CPU cpus_europc[]; extern CPU cpus_pc1512[]; extern CPU cpus_ibmat[]; +extern CPU cpus_ibmxt286[]; extern CPU cpus_ps1_m2011[]; extern CPU cpus_ps2_m30_286[]; extern CPU cpus_acer[]; @@ -197,4 +198,5 @@ typedef struct extern msr_t msr; -#endif + +#endif /*EMU_CPU_H*/ diff --git a/src/cpu/x86.h b/src/cpu/x86.h index deb210cb6..a49ea9769 100644 --- a/src/cpu/x86.h +++ b/src/cpu/x86.h @@ -17,7 +17,7 @@ uint8_t opcode; int noint; uint16_t lastcs,lastpc; -int timetolive,keyboardtimer; +extern int timetolive,keyboardtimer; #define setznp168 setznp16 diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 7cce21c61..e0b981807 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -4,8 +4,13 @@ #ifndef _X86_OPS_H #define _X86_OPS_H + +#define UNUSED(x) (void)(x) + + typedef int (*OpFn)(uint32_t fetchdat); +#ifdef USE_DYNAREC void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn *dynarec_opcodes_0f); extern OpFn *x86_dynarec_opcodes; @@ -91,6 +96,9 @@ extern OpFn dynarec_ops_fpu_686_df_a32[256]; extern OpFn dynarec_ops_REPE[1024]; extern OpFn dynarec_ops_REPNE[1024]; +#else +void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f); +#endif extern OpFn *x86_opcodes; extern OpFn *x86_opcodes_0f; diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index 7205af152..59c692c65 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -99,7 +99,9 @@ static int opSAHF(uint32_t fetchdat) CLOCK_CYCLES(3); PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); +#if 0 codegen_flags_changed = 0; +#endif return 0; } @@ -180,7 +182,9 @@ static int opPOPF_286(uint32_t fetchdat) CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); +#if 0 codegen_flags_changed = 0; +#endif return 0; } @@ -238,7 +242,9 @@ static int opPOPF(uint32_t fetchdat) CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); +#if 0 codegen_flags_changed = 0; +#endif return 0; } @@ -270,7 +276,9 @@ static int opPOPFD(uint32_t fetchdat) CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0); +#if 0 codegen_flags_changed = 0; +#endif return 0; } diff --git a/src/cpu/x86_ops_io.h b/src/cpu/x86_ops_io.h index 7d42299cc..9fa91a215 100644 --- a/src/cpu/x86_ops_io.h +++ b/src/cpu/x86_ops_io.h @@ -5,6 +5,8 @@ static int opIN_AL_imm(uint32_t fetchdat) AL = inb(port); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } static int opIN_AX_imm(uint32_t fetchdat) @@ -15,6 +17,8 @@ static int opIN_AX_imm(uint32_t fetchdat) AX = inw(port); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } static int opIN_EAX_imm(uint32_t fetchdat) @@ -27,6 +31,8 @@ static int opIN_EAX_imm(uint32_t fetchdat) EAX = inl(port); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, -1, 0,1,0,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } @@ -39,6 +45,8 @@ static int opOUT_AL_imm(uint32_t fetchdat) PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); if (port == 0x64) return x86_was_reset; + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } static int opOUT_AX_imm(uint32_t fetchdat) @@ -49,6 +57,8 @@ static int opOUT_AX_imm(uint32_t fetchdat) outw(port, AX); CLOCK_CYCLES(10); PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } static int opOUT_EAX_imm(uint32_t fetchdat) @@ -61,6 +71,8 @@ static int opOUT_EAX_imm(uint32_t fetchdat) outl(port, EAX); CLOCK_CYCLES(10); PREFETCH_RUN(10, 2, -1, 0,0,0,1, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } @@ -70,6 +82,8 @@ static int opIN_AL_DX(uint32_t fetchdat) AL = inb(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } static int opIN_AX_DX(uint32_t fetchdat) @@ -79,6 +93,8 @@ static int opIN_AX_DX(uint32_t fetchdat) AX = inw(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } static int opIN_EAX_DX(uint32_t fetchdat) @@ -90,6 +106,8 @@ static int opIN_EAX_DX(uint32_t fetchdat) EAX = inl(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 0,1,0,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } @@ -99,6 +117,8 @@ static int opOUT_AL_DX(uint32_t fetchdat) outb(DX, AL); CLOCK_CYCLES(11); PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return x86_was_reset; } static int opOUT_AX_DX(uint32_t fetchdat) @@ -108,6 +128,8 @@ static int opOUT_AX_DX(uint32_t fetchdat) outw(DX, AX); CLOCK_CYCLES(11); PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } static int opOUT_EAX_DX(uint32_t fetchdat) @@ -118,5 +140,7 @@ static int opOUT_EAX_DX(uint32_t fetchdat) check_io_perm(DX + 3); outl(DX, EAX); PREFETCH_RUN(11, 1, -1, 0,0,0,1, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; return 0; } diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 177a555ca..e365488bc 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -8,17 +8,20 @@ * * x86 CPU segment emulation. * - * Version: @(#)x86seg.c 1.0.0 2017/05/30 + * Version: @(#)x86seg.c 1.0.3 2017/10/12 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - #include -#include +#include +#include #include +#include +#include #include "../ibm.h" #include "../mem.h" #include "../nvr.h" @@ -27,6 +30,7 @@ #include "386_common.h" #include "cpu.h" + /*Controls whether the accessed bit in a descriptor is set when CS is loaded.*/ #define CS_ACCESSED @@ -36,7 +40,6 @@ int stimes = 0; int dtimes = 0; int btimes = 0; -int is486=1; uint32_t abrt_error; int cgate16,cgate32; @@ -61,7 +64,7 @@ void x86abort(const char *format, ...) vprintf(format, ap); va_end(ap); fflush(stdout); - savenvr(); + nvr_save(); dumpregs(1); fflush(stdout); exit(-1); @@ -402,10 +405,12 @@ void loadseg(uint16_t seg, x86seg *s) } #endif s->checked = 0; +#ifdef USE_DYNAREC if (s == &_ds) codegen_flat_ds = 0; if (s == &_ss) codegen_flat_ss = 0; +#endif } else { @@ -415,10 +420,12 @@ void loadseg(uint16_t seg, x86seg *s) if (s == &_ss) stack32 = 0; s->checked = 1; +#ifdef USE_DYNAREC if (s == &_ds) codegen_flat_ds = 0; if (s == &_ss) codegen_flat_ss = 0; +#endif } if (s == &_ds) diff --git a/src/cpu/x86seg.h b/src/cpu/x86seg.h index f4badadf4..4f12a8d65 100644 --- a/src/cpu/x86seg.h +++ b/src/cpu/x86seg.h @@ -8,10 +8,11 @@ * * x86 CPU segment emulation. * - * Version: @(#)x86seg.h 1.0.0 2017/05/30 + * Version: @(#)x86seg.h 1.0.1 2017/10/12 * * Author: Miran Grca, + * * Copyright 2016-2017 Miran Grca. */ -void do_seg_load(x86seg *s, uint16_t *segdat); +extern void do_seg_load(x86seg *s, uint16_t *segdat); diff --git a/src/cpu/x87.c b/src/cpu/x87.c index a241130fb..362e288d7 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #define fplog 0 #include #include "../ibm.h" diff --git a/src/device.c b/src/device.c index 647c25850..ef2904f1a 100644 --- a/src/device.c +++ b/src/device.c @@ -9,13 +9,17 @@ * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.c 1.0.3 2017/09/02 + * Version: @(#)device.c 1.0.4 2017/10/04 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2016 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "ibm.h" #include "cpu/cpu.h" #include "config.h" @@ -27,336 +31,387 @@ #define DEVICE_MAX 256 /* max # of devices */ -static void *device_priv[DEVICE_MAX]; -static device_t *devices[DEVICE_MAX]; -static device_t *current_device; +static device_t *devices[DEVICE_MAX]; +static void *device_priv[DEVICE_MAX]; +static device_t *device_current; -void device_init(void) +void +device_init(void) { - memset(devices, 0x00, sizeof(devices)); + memset(devices, 0x00, sizeof(devices)); } -void device_add(device_t *d) +void +device_add(device_t *d) { - int c = 0; - void *priv = NULL; - - while (devices[c] != NULL && c < 256) + void *priv = NULL; + int c = 0; + + while (devices[c] != NULL && c < 256) c++; + if (c >= DEVICE_MAX) + fatal("device_add: too many devices\n"); - if (c >= DEVICE_MAX) - fatal("device_add : too many devices\n"); - - current_device = d; - - if (d->init != NULL) - { - priv = d->init(); - if (priv == NULL) - fatal("device_add : device init failed\n"); - } - - devices[c] = d; - device_priv[c] = priv; + device_current = d; + + if (d->init != NULL) { + priv = d->init(d); + if (priv == NULL) + fatal("device_add: device init failed\n"); + } + + devices[c] = d; + device_priv[c] = priv; } -void device_close_all(void) +void +device_close_all(void) { - int c; + int c; - for (c=0; cclose != NULL) - devices[c]->close(device_priv[c]); - devices[c] = device_priv[c] = NULL; - } - } + for (c=0; cclose != NULL) + devices[c]->close(device_priv[c]); + devices[c] = device_priv[c] = NULL; + } + } } -void *device_get_priv(device_t *d) +void +device_reset_all(void) { - int c; + int c; - for (c=0; creset != NULL) + devices[c]->reset(device_priv[c]); + } + } } -int device_available(device_t *d) +void * +device_get_priv(device_t *d) +{ + int c; + + for (c=0; cflags & DEVICE_NOT_WORKING) - return 0; + if (d->flags & DEVICE_NOT_WORKING) return(0); #endif - if (d->available) - return d->available(); - - return 1; + if (d->available != NULL) + return(d->available()); + + return(1); } -void device_speed_changed(void) +void +device_speed_changed(void) { - int c; - - for (c=0; cspeed_changed != NULL) - { - devices[c]->speed_changed(device_priv[c]); - } - } - } - - sound_speed_changed(); + int c; + + for (c=0; cspeed_changed != NULL) + devices[c]->speed_changed(device_priv[c]); + } + } + + sound_speed_changed(); } -void device_force_redraw(void) +void +device_force_redraw(void) { - int c; - - for (c=0; cforce_redraw != NULL) - { + int c; + + for (c=0; cforce_redraw != NULL) devices[c]->force_redraw(device_priv[c]); - } - } - } + } + } } -char *device_add_status_info(char *s, int max_len) +void +device_add_status_info(char *s, int max_len) { - int c; - - for (c=0; cadd_status_info != NULL) - devices[c]->add_status_info(s, max_len, device_priv[c]); - } - } + int c; - return NULL; + for (c=0; cadd_status_info != NULL) + devices[c]->add_status_info(s, max_len, device_priv[c]); + } + } } -int device_get_config_int(char *s) +char * +device_get_config_string(char *s) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - return config_get_int(current_device->name, s, config->default_int); + device_config_t *c = device_current->config; - config++; - } - return 0; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_string(device_current->name, s, c->default_string)); + + c++; + } + + return(NULL); } -int device_get_config_int_ex(char *s, int default_int) +int +device_get_config_int(char *s) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - return config_get_int(current_device->name, s, default_int); + device_config_t *c = device_current->config; - config++; - } - return default_int; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_int(device_current->name, s, c->default_int)); + + c++; + } + + return(0); } -int device_get_config_hex16(char *s) +int +device_get_config_int_ex(char *s, int default_int) { - device_config_t *config = current_device->config; + device_config_t *c = device_current->config; - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - return config_get_hex16(current_device->name, s, config->default_int); + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_int(device_current->name, s, default_int)); - config++; - } - return 0; + c++; + } + + return(default_int); } -int device_get_config_hex20(char *s) +int +device_get_config_hex16(char *s) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - return config_get_hex20(current_device->name, s, config->default_int); + device_config_t *c = device_current->config; - config++; - } - return 0; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_hex16(device_current->name, s, c->default_int)); + + c++; + } + + return(0); } -int device_get_config_mac(char *s, int default_int) +int +device_get_config_hex20(char *s) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - return config_get_mac(current_device->name, s, default_int); + device_config_t *c = device_current->config; - config++; - } - return default_int; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_hex20(device_current->name, s, c->default_int)); + + c++; + } + + return(0); } -void device_set_config_int(char *s, int val) +int +device_get_config_mac(char *s, int default_int) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - { - config_set_int(current_device->name, s, val); - return; - } + device_config_t *c = device_current->config; - config++; - } + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_mac(device_current->name, s, default_int)); + + c++; + } + + return(default_int); } -void device_set_config_hex16(char *s, int val) +void +device_set_config_int(char *s, int val) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - { - config_set_hex16(current_device->name, s, val); - return; - } + device_config_t *c = device_current->config; - config++; - } + while (c && c->type != -1) { + if (! strcmp(s, c->name)) { + config_set_int(device_current->name, s, val); + break; + } + + c++; + } } -void device_set_config_hex20(char *s, int val) +void +device_set_config_hex16(char *s, int val) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - { - config_set_hex20(current_device->name, s, val); - return; - } + device_config_t *c = device_current->config; - config++; - } + while (c && c->type != -1) { + if (! strcmp(s, c->name)) { + config_set_hex16(device_current->name, s, val); + break; + } + + c++; + } } -void device_set_config_mac(char *s, int val) +void +device_set_config_hex20(char *s, int val) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - { - config_set_mac(current_device->name, s, val); - return; - } + device_config_t *c = device_current->config; - config++; - } + while (c && c->type != -1) { + if (! strcmp(s, c->name)) { + config_set_hex20(device_current->name, s, val); + break; + } + + c++; + } } -char *device_get_config_string(char *s) +void +device_set_config_mac(char *s, int val) { - device_config_t *config = current_device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - return config_get_string(current_device->name, s, config->default_string); + device_config_t *c = device_current->config; - config++; - } - return NULL; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) { + config_set_mac(device_current->name, s, val); + break; + } + + c++; + } } -int machine_get_config_int(char *s) +int +device_is_valid(device_t *device, int machine_flags) { - device_t *device = machine_getdevice(machine); - device_config_t *config; + if (!device) + { + return 1; + } - if (!device) - return 0; + if ((device->flags & DEVICE_AT) && !(machine_flags & MACHINE_AT)) { + return 0; + } - config = device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - return config_get_int(device->name, s, config->default_int); + if ((device->flags & DEVICE_CBUS) && !(machine_flags & MACHINE_CBUS)) { + return 0; + } - config++; - } - return 0; + if ((device->flags & DEVICE_ISA) && !(machine_flags & MACHINE_ISA)) { + return 0; + } + + if ((device->flags & DEVICE_MCA) && !(machine_flags & MACHINE_MCA)) { + return 0; + } + + if ((device->flags & DEVICE_EISA) && !(machine_flags & MACHINE_EISA)) { + return 0; + } + + if ((device->flags & DEVICE_VLB) && !(machine_flags & MACHINE_VLB)) { + return 0; + } + + if ((device->flags & DEVICE_PCI) && !(machine_flags & MACHINE_PCI)) { + return 0; + } + + if ((device->flags & DEVICE_PS2) && !(machine_flags & MACHINE_PS2_HDD)) { + return 0; + } + + if ((device->flags & DEVICE_AGP) && !(machine_flags & MACHINE_AGP)) { + return 0; + } + + return 1; } -char *machine_get_config_string(char *s) +int +machine_get_config_int(char *s) { - device_t *device = machine_getdevice(machine); - device_config_t *config; - - if (!device) - return 0; + device_t *d = machine_getdevice(machine); + device_config_t *c; - config = device->config; - - while (config && config->type != -1) - { - if (!strcmp(s, config->name)) - return config_get_string(device->name, s, config->default_string); + if (d == NULL) return(0); - config++; - } - return NULL; + c = d->config; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_int(d->name, s, c->default_int)); + + c++; + } + + return(0); +} + + +char * +machine_get_config_string(char *s) +{ + device_t *d = machine_getdevice(machine); + device_config_t *c; + + if (d == NULL) return(0); + + c = d->config; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_string(d->name, s, c->default_string)); + + c++; + } + + return(NULL); } diff --git a/src/device.h b/src/device.h index 168e11508..d3460555a 100644 --- a/src/device.h +++ b/src/device.h @@ -9,12 +9,14 @@ * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.h 1.0.2 2017/08/23 + * Version: @(#)device.h 1.0.3 2017/10/04 * * Authors: Sarah Walker, * Miran Grca, + * Fred N. van Kempen, * Copyright 2008-2016 Sarah Walker. * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. */ #ifndef EMU_DEVICE_H # define EMU_DEVICE_H @@ -32,69 +34,73 @@ #define CONFIG_MAC 9 -enum -{ - DEVICE_NOT_WORKING = 1, /*Device does not currently work correctly and will be disabled in a release build*/ - DEVICE_AT = 2, /*Device requires an AT-compatible system*/ - DEVICE_PS2 = 4, /*Device requires a PS/1 or PS/2 system*/ - DEVICE_MCA = 0x20, /*Device requires the MCA bus*/ - DEVICE_PCI = 0x40 /*Device requires the PCI bus*/ +enum { + DEVICE_NOT_WORKING = 1, /* does not currently work correctly and will be disabled in a release build*/ + DEVICE_AT = 2, /* requires an AT-compatible system */ + DEVICE_PS2 = 4, /* requires a PS/1 or PS/2 system */ + DEVICE_ISA = 8, /* requires the ISA bus */ + DEVICE_CBUS = 0x10, /* requires the C-BUS bus */ + DEVICE_MCA = 0x20, /* requires the MCA bus */ + DEVICE_EISA = 0x40, /* requires the EISA bus */ + DEVICE_VLB = 0x80, /* requires the PCI bus */ + DEVICE_PCI = 0x100, /* requires the VLB bus */ + DEVICE_AGP = 0x200 /* requires the AGP bus */ }; -typedef struct device_config_selection_t -{ - char description[256]; - int value; +typedef struct { + char description[256]; + int value; } device_config_selection_t; -typedef struct device_config_file_filter_t -{ - char description[256]; - char extensions[25][25]; +typedef struct { + char description[256]; + char extensions[25][25]; } device_config_file_filter_t; -typedef struct device_config_spinner_t -{ - int min; - int max; - int step; +typedef struct { + int min; + int max; + int step; } device_config_spinner_t; -typedef struct device_config_t -{ - char name[256]; - char description[256]; - int type; - char default_string[256]; - int default_int; - device_config_selection_t selection[16]; - device_config_file_filter_t file_filter[16]; - device_config_spinner_t spinner; +typedef struct { + char name[256]; + char description[256]; + int type; + char default_string[256]; + int default_int; + device_config_selection_t selection[16]; + device_config_file_filter_t file_filter[16]; + device_config_spinner_t spinner; } device_config_t; -typedef struct device_t -{ - char name[50]; - uint32_t flags; - void *(*init)(); - void (*close)(void *p); - int (*available)(); - void (*speed_changed)(void *p); - void (*force_redraw)(void *p); - void (*add_status_info)(char *s, int max_len, void *p); - device_config_t *config; +typedef struct _device_ { + char name[50]; + uint32_t flags; /* system flags */ + uint32_t local; /* flags local to device */ + + void *(*init)(struct _device_ *); + void (*close)(void *p); + void (*reset)(void *p); + int (*available)(void); + void (*speed_changed)(void *p); + void (*force_redraw)(void *p); + void (*add_status_info)(char *s, int max_len, void *p); + + device_config_t *config; } device_t; extern void device_init(void); extern void device_add(device_t *d); extern void device_close_all(void); +extern void device_reset_all(void); extern void *device_get_priv(device_t *d); extern int device_available(device_t *d); extern void device_speed_changed(void); extern void device_force_redraw(void); -extern char *device_add_status_info(char *s, int max_len); +extern void device_add_status_info(char *s, int max_len); extern int device_get_config_int(char *name); extern int device_get_config_int_ex(char *s, int default_int); @@ -106,6 +112,7 @@ extern void device_set_config_hex16(char *s, int val); extern void device_set_config_hex20(char *s, int val); extern void device_set_config_mac(char *s, int val); extern char *device_get_config_string(char *name); +extern int device_is_valid(device_t *device, int machine_flags); extern int machine_get_config_int(char *s); extern char *machine_get_config_string(char *s); diff --git a/src/disk/hdc.c b/src/disk/hdc.c new file mode 100644 index 000000000..39b180599 --- /dev/null +++ b/src/disk/hdc.c @@ -0,0 +1,193 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Common code to handle all sorts of disk controllers. + * + * Version: @(#)hdc.c 1.0.3 2017/10/04 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include "../ibm.h" +#include "../cpu/cpu.h" +#include "../device.h" +#include "../machine/machine.h" +#include "hdc.h" + + +char hdc_name[16]; /* configured HDC name */ +int hdc_current; + + +static void * +null_init(device_t *info) +{ + return(NULL); +} + + +static void +null_close(void *priv) +{ +} + + +static device_t null_device = { + "Null HDC", 0, 0, + null_init, null_close, NULL, + NULL, NULL, NULL, NULL, NULL +}; + + +static void * +inthdc_init(device_t *info) +{ + return(NULL); +} + + +static void +inthdc_close(void *priv) +{ +} + + +static device_t inthdc_device = { + "Internal Controller", 0, 0, + inthdc_init, inthdc_close, NULL, + NULL, NULL, NULL, NULL, NULL +}; + + +static struct { + char name[50]; + char internal_name[16]; + device_t *device; + int is_mfm; +} controllers[] = { + { "None", "none", + &null_device, 0 }, + + { "Internal Controller", "internal", + &inthdc_device, 0 }, + + { "[ISA] [MFM] IBM PC Fixed Disk Adapter", "mfm_xebec", + &mfm_xt_xebec_device, 1 }, + + { "[ISA] [MFM] DTC-5150X Fixed Disk Adapter", "mfm_dtc5150x", + &mfm_xt_dtc5150x_device, 1 }, + + { "[ISA] [MFM] IBM PC/AT Fixed Disk Adapter", "mfm_at", + &mfm_at_wd1003_device, 1 }, + + { "[ISA] [ESDI] PC/AT ESDI Fixed Disk Adapter", "esdi_wd1007vse1", + &esdi_at_wd1007vse1_device, 0 }, + +#if 0 + { "[ISA] [IDE] PC/AT IDE Adapter", "ide_isa", + &ide_isa_device, 0 }, + + { "[PCI] [IDE] PCI IDE Adapter", "ide_pci", + &ide_pci_device, 0 }, +#endif + + { "[ISA] [IDE] PC/XT XTIDE", "xtide", + &xtide_device , 0 }, + + { "[ISA] [IDE] PC/AT XTIDE", "xtide_at", + &xtide_at_device, 0 }, + + { "[ISA] [IDE] PS/2 XTIDE (Acculogic)", "xtide_ps2", + &xtide_ps2_device, 0 }, + + { "[ISA] [IDE] PS/2 AT XTIDE (1.1.5)", "xtide_at_ps2", + &xtide_at_ps2_device, 0 }, + + { "[MCA] [ESDI] IBM PS/2 ESDI Fixed Disk Adapter","esdi_mca", + &esdi_ps2_device, 1 }, + + { "", "", NULL, 0 } +}; + + +/* Initialize the 'hdc_current' value based on configured HDC name. */ +void +hdc_init(char *name) +{ + int c; + + pclog("HDC: initializing..\n"); + + for (c=0; controllers[c].device; c++) { + if (! strcmp(name, controllers[c].internal_name)) { + hdc_current = c; + break; + } + } +} + + +/* Reset the HDC, whichever one that is. */ +void +hdc_reset(void) +{ + pclog("HDC: reset(current=%d, internal=%d)\n", + hdc_current, (machines[machine].flags & MACHINE_HAS_HDC)?1:0); + + /* If we have a valid controller, add its device. */ + if (hdc_current > 1) + device_add(controllers[hdc_current].device); +} + + +char * +hdc_get_name(int hdc) +{ + return(controllers[hdc].name); +} + + +char * +hdc_get_internal_name(int hdc) +{ + return(controllers[hdc].internal_name); +} + + +device_t * +hdc_get_device(int hdc) +{ + return(controllers[hdc].device); +} + + +int +hdc_get_flags(int hdc) +{ + return(controllers[hdc].device->flags); +} + + +int +hdc_available(int hdc) +{ + return(device_available(controllers[hdc].device)); +} + + +int +hdc_current_is_mfm(void) +{ + return(controllers[hdc_current].is_mfm); +} diff --git a/src/disk/hdc.h b/src/disk/hdc.h new file mode 100644 index 000000000..5d0e93657 --- /dev/null +++ b/src/disk/hdc.h @@ -0,0 +1,58 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for the common disk controller handler. + * + * Version: @(#)hdc.h 1.0.3 2017/10/01 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#ifndef EMU_HDC_H +# define EMU_HDC_H + + +#define MFM_NUM 2 /* 2 drives per controller supported */ +#define ESDI_NUM 2 /* 2 drives per controller supported */ +#define XTIDE_NUM 2 /* 2 drives per controller supported */ +#define IDE_NUM 8 +#define SCSI_NUM 16 /* theoretically the controller can have at + * least 7 devices, with each device being + * able to support 8 units, but hey... */ + +extern char hdc_name[16]; +extern int hdc_current; + + +extern device_t mfm_xt_xebec_device; /* mfm_xt_xebec */ +extern device_t mfm_xt_dtc5150x_device; /* mfm_xt_dtc */ +extern device_t mfm_at_wd1003_device; /* mfm_at_wd1003 */ + +extern device_t esdi_at_wd1007vse1_device; /* esdi_at */ +extern device_t esdi_ps2_device; /* esdi_mca */ + +extern device_t xtide_device; /* xtide_xt */ +extern device_t xtide_at_device; /* xtide_at */ +extern device_t xtide_ps2_device; /* xtide_ps2 */ +extern device_t xtide_at_ps2_device; /* xtide_at_ps2 */ + + +extern void hdc_init(char *name); +extern void hdc_reset(void); + +extern char *hdc_get_name(int hdc); +extern char *hdc_get_internal_name(int hdc); +extern device_t *hdc_get_device(int hdc); +extern int hdc_get_flags(int hdc); +extern int hdc_available(int hdc); +extern int hdc_current_is_mfm(void); + + +#endif /*EMU_HDC_H*/ diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c new file mode 100644 index 000000000..91d847c5a --- /dev/null +++ b/src/disk/hdc_esdi_at.c @@ -0,0 +1,853 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Driver for the ESDI controller (WD1007-vse1) for PC/AT. + * + * Version: @(#)hdc_esdi_at.c 1.0.4 2017/10/09 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../device.h" +#include "../io.h" +#include "../mem.h" +#include "../pic.h" +#include "../rom.h" +#include "../timer.h" +#include "../ui.h" +#include "hdc.h" +#include "hdd.h" + + +#define HDC_TIME (TIMER_USEC*10LL) +#define BIOS_FILE L"roms/hdd/esdi_at/62-000279-061.bin" + +#define STAT_ERR 0x01 +#define STAT_INDEX 0x02 +#define STAT_CORRECTED_DATA 0x04 +#define STAT_DRQ 0x08 /* Data request */ +#define STAT_DSC 0x10 +#define STAT_SEEK_COMPLETE 0x20 +#define STAT_READY 0x40 +#define STAT_BUSY 0x80 + +#define ERR_DAM_NOT_FOUND 0x01 /*Data Address Mark not found*/ +#define ERR_TR000 0x02 /*Track 0 not found*/ +#define ERR_ABRT 0x04 /*Command aborted*/ +#define ERR_ID_NOT_FOUND 0x10 /*ID not found*/ +#define ERR_DATA_CRC 0x40 /*Data CRC error*/ +#define ERR_BAD_BLOCK 0x80 /*Bad Block detected*/ + +#define CMD_NOP 0x00 +#define CMD_RESTORE 0x10 +#define CMD_READ 0x20 +#define CMD_WRITE 0x30 +#define CMD_VERIFY 0x40 +#define CMD_FORMAT 0x50 +#define CMD_SEEK 0x70 +#define CMD_DIAGNOSE 0x90 +#define CMD_SET_PARAMETERS 0x91 +#define CMD_READ_PARAMETERS 0xec + + +extern char ide_fn[4][512]; + + +typedef struct { + int cfg_spt; + int cfg_hpc; + int current_cylinder; + int real_spt; + int real_hpc; + int real_tracks; + int present; + int hdd_num; +} drive_t; + +typedef struct { + uint8_t status; + uint8_t error; + int secount,sector,cylinder,head,cylprecomp; + uint8_t command; + uint8_t fdisk; + int pos; + + int drive_sel; + int reset; + uint16_t buffer[256]; + int irqstat; + + int64_t callback; + + drive_t drives[2]; + + rom_t bios_rom; +} esdi_t; + + +static inline void +irq_raise(esdi_t *esdi) +{ + if (! (esdi->fdisk&2)) + picint(1<<14); + + esdi->irqstat=1; +} + + +static inline void +irq_lower(esdi_t *esdi) +{ + picintc(1<<14); +} + + +static void +irq_update(esdi_t *esdi) +{ + if (esdi->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(esdi->fdisk & 2)) + picint(1<<14); +} + + +/* Return the sector offset for the current register values. */ +static int +get_sector(esdi_t *esdi, off64_t *addr) +{ + drive_t *drive = &esdi->drives[esdi->drive_sel]; + int heads = drive->cfg_hpc; + int sectors = drive->cfg_spt; + + if (esdi->head > heads) { + pclog("esdi_get_sector: past end of configured heads\n"); + return 1; + } + + if (esdi->sector >= sectors+1) { + pclog("esdi_get_sector: past end of configured sectors\n"); + return 1; + } + + if (drive->cfg_spt==drive->real_spt && drive->cfg_hpc==drive->real_hpc) { + *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * + sectors) + (esdi->sector - 1); + } else { + /* + * When performing translation, the firmware seems to leave 1 + * sector per track inaccessible (spare sector) + */ + int c, h, s; + + *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * + sectors) + (esdi->sector - 1); + + s = *addr % (drive->real_spt - 1); + h = (*addr / (drive->real_spt - 1)) % drive->real_hpc; + c = (*addr / (drive->real_spt - 1)) / drive->real_hpc; + + *addr = ((((off64_t)c * drive->real_hpc) + h) * drive->real_spt) + s; + } + + return(0); +} + + +/* Move to the next sector using CHS addressing. */ +static void +next_sector(esdi_t *esdi) +{ + drive_t *drive = &esdi->drives[esdi->drive_sel]; + + esdi->sector++; + if (esdi->sector == (drive->cfg_spt + 1)) { + esdi->sector = 1; + if (++esdi->head == drive->cfg_hpc) { + esdi->head = 0; + esdi->cylinder++; + if (drive->current_cylinder < drive->real_tracks) + drive->current_cylinder++; + } + } +} + + +static void +esdi_writew(uint16_t port, uint16_t val, void *priv) +{ + esdi_t *esdi = (esdi_t *)priv; + + esdi->buffer[esdi->pos >> 1] = val; + esdi->pos += 2; + + if (esdi->pos >= 512) { + esdi->pos = 0; + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 6LL*HDC_TIME; + timer_update_outstanding(); + } +} + + +static void +esdi_write(uint16_t port, uint8_t val, void *priv) +{ + esdi_t *esdi = (esdi_t *)priv; + + switch (port) { + case 0x1F0: /* Data */ + esdi_writew(port, val | (val << 8), priv); + return; + + case 0x1F1: /* Write precompenstation */ + esdi->cylprecomp = val; + return; + + case 0x1F2: /* Sector count */ + esdi->secount = val; + return; + + case 0x1F3: /* Sector */ + esdi->sector = val; + return; + + case 0x1F4: /* Cylinder low */ + esdi->cylinder = (esdi->cylinder & 0xFF00) | val; + return; + + case 0x1F5: /* Cylinder high */ + esdi->cylinder = (esdi->cylinder & 0xFF) | (val << 8); + return; + + case 0x1F6: /* Drive/Head */ + esdi->head = val & 0xF; + esdi->drive_sel = (val & 0x10) ? 1 : 0; + if (esdi->drives[esdi->drive_sel].present) + esdi->status = 0; + else + esdi->status = STAT_READY | STAT_DSC; + return; + + case 0x1F7: /* Command register */ + irq_lower(esdi); + esdi->command = val; + esdi->error = 0; + + switch (val & 0xf0) { + case CMD_RESTORE: + esdi->command &= ~0x0f; /*Mask off step rate*/ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200LL*HDC_TIME; + timer_update_outstanding(); + break; + + case CMD_SEEK: + esdi->command &= ~0x0f; /*Mask off step rate*/ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200LL*HDC_TIME; + timer_update_outstanding(); + break; + + default: + switch (val) { + case CMD_NOP: + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200LL*HDC_TIME; + timer_update_outstanding(); + break; + + case CMD_READ: + case CMD_READ+1: + case CMD_READ+2: + case CMD_READ+3: + esdi->command &= ~3; + if (val & 2) + fatal("Read with ECC\n"); + + case 0xa0: + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200LL*HDC_TIME; + timer_update_outstanding(); + break; + + case CMD_WRITE: + case CMD_WRITE+1: + case CMD_WRITE+2: + case CMD_WRITE+3: + esdi->command &= ~3; + if (val & 2) + fatal("Write with ECC\n"); + esdi->status = STAT_DRQ | STAT_DSC; + esdi->pos=0; + break; + + case CMD_VERIFY: + case CMD_VERIFY+1: + esdi->command &= ~1; + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200LL*HDC_TIME; + timer_update_outstanding(); + break; + + case CMD_FORMAT: + esdi->status = STAT_DRQ; + esdi->pos=0; + break; + + case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 30LL*HDC_TIME; + timer_update_outstanding(); + break; + + case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200LL*HDC_TIME; + timer_update_outstanding(); + break; + + case 0xe0: /*???*/ + case CMD_READ_PARAMETERS: + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200LL*HDC_TIME; + timer_update_outstanding(); + break; + + default: + pclog("Bad esdi command %02X\n", val); + case 0xe8: /*???*/ + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 200LL*HDC_TIME; + timer_update_outstanding(); + break; + } + } + break; + + case 0x3F6: /* Device control */ + if ((esdi->fdisk & 4) && !(val & 4)) { + timer_process(); + esdi->callback = 500LL*HDC_TIME; + timer_update_outstanding(); + esdi->reset = 1; + esdi->status = STAT_BUSY; + } + + if (val & 4) { + /*Drive held in reset*/ + timer_process(); + esdi->callback = 0LL; + timer_update_outstanding(); + esdi->status = STAT_BUSY; + } + esdi->fdisk = val; + irq_update(esdi); + } +} + + +static uint16_t +esdi_readw(uint16_t port, void *priv) +{ + esdi_t *esdi = (esdi_t *)priv; + uint16_t temp; + + temp = esdi->buffer[esdi->pos >> 1]; + esdi->pos += 2; + + if (esdi->pos >= 512) { + esdi->pos=0; + esdi->status = STAT_READY | STAT_DSC; + if (esdi->command == CMD_READ || esdi->command == 0xa0) { + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) { + next_sector(esdi); + esdi->status = STAT_BUSY; + timer_process(); + esdi->callback = 6LL*HDC_TIME; + timer_update_outstanding(); + } + } + } + + return(temp); +} + + +static uint8_t +esdi_read(uint16_t port, void *priv) +{ + esdi_t *esdi = (esdi_t *)priv; + uint8_t temp = 0xff; + + switch (port) { + case 0x1F0: /* Data */ + temp = esdi_readw(port, esdi) & 0xff; + break; + + case 0x1F1: /* Error */ + temp = esdi->error; + break; + + case 0x1F2: /* Sector count */ + temp = (uint8_t)esdi->secount; + break; + + case 0x1F3: /* Sector */ + temp = (uint8_t)esdi->sector; + break; + + case 0x1F4: /* Cylinder low */ + temp = (uint8_t)(esdi->cylinder&0xFF); + break; + + case 0x1F5: /* Cylinder high */ + temp = (uint8_t)(esdi->cylinder>>8); + break; + + case 0x1F6: /* Drive/Head */ + temp = (uint8_t)(esdi->head | (esdi->drive_sel?0x10:0) | 0xa0); + break; + + case 0x1F7: /* Status */ + irq_lower(esdi); + temp = esdi->status; + break; + } + + return(temp); +} + + +static void +esdi_callback(void *priv) +{ + esdi_t *esdi = (esdi_t *)priv; + drive_t *drive = &esdi->drives[esdi->drive_sel]; + off64_t addr; + + esdi->callback = 0; + if (esdi->reset) { + esdi->status = STAT_READY | STAT_DSC; + esdi->error = 1; + esdi->secount = 1; + esdi->sector = 1; + esdi->head = 0; + esdi->cylinder = 0; + esdi->reset = 0; + + return; + } + + switch (esdi->command) { + case CMD_RESTORE: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + } else { + drive->current_cylinder = 0; + esdi->status = STAT_READY | STAT_DSC; + } + irq_raise(esdi); + break; + + case CMD_SEEK: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + } else { + esdi->status = STAT_READY | STAT_DSC; + } + irq_raise(esdi); + break; + + case CMD_READ: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } + + if (get_sector(esdi, &addr)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } + + if (hdd_image_read_ex(drive->hdd_num, addr, 1, + (uint8_t *)esdi->buffer)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } + + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; + + case CMD_WRITE: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } + + if (get_sector(esdi, &addr)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } + + if (hdd_image_write_ex(drive->hdd_num, addr, 1, + (uint8_t *)esdi->buffer)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } + + irq_raise(esdi); + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) { + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + esdi->pos = 0; + next_sector(esdi); + } else { + esdi->status = STAT_READY | STAT_DSC; + } + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; + + case CMD_VERIFY: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } + + if (get_sector(esdi, &addr)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } + + if (hdd_image_read_ex(drive->hdd_num, addr, 1, + (uint8_t *)esdi->buffer)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } + + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + next_sector(esdi); + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) + esdi->callback = 6LL*HDC_TIME; + else { + esdi->pos = 0; + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + } + break; + + case CMD_FORMAT: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } + + if (get_sector(esdi, &addr)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } + if (hdd_image_zero_ex(drive->hdd_num, addr, esdi->secount)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; + + case CMD_DIAGNOSE: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + } else { + esdi->error = 1; /*No error detected*/ + esdi->status = STAT_READY | STAT_DSC; + } + irq_raise(esdi); + break; + + case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } + + drive->cfg_spt = esdi->secount; + drive->cfg_hpc = esdi->head+1; + pclog("Parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); + if (! esdi->secount) + fatal("secount=0\n"); + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + break; + + case CMD_NOP: + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + + case 0xe0: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } + + switch (esdi->cylinder >> 8) { + case 0x31: + esdi->cylinder = drive->real_tracks; + break; + + case 0x33: + esdi->cylinder = drive->real_hpc; + break; + + case 0x35: + esdi->cylinder = 0x200; + break; + + case 0x36: + esdi->cylinder = drive->real_spt; + break; + + default: + pclog("EDSI Bad read config %02x\n", + esdi->cylinder >> 8); + } + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + break; + + case 0xa0: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + } else { + memset(esdi->buffer, 0, 512); + memset(&esdi->buffer[3], 0xff, 512-6); + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + } + irq_raise(esdi); + break; + + case CMD_READ_PARAMETERS: + if (! drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } + + memset(esdi->buffer, 0, 512); + esdi->buffer[0] = 0x44; /* general configuration */ + esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */ + esdi->buffer[2] = 0; /* number of removable cylinders */ + esdi->buffer[3] = drive->real_hpc; /* number of heads */ + esdi->buffer[4] = 600; /* number of unformatted bytes/track */ + esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/sector */ + esdi->buffer[6] = drive->real_spt; /* number of sectors */ + esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/ + esdi->buffer[8] = 0; /* minimum bytes in postamble */ + esdi->buffer[9] = 0; /* number of words of vendor status */ + /* controller info */ + esdi->buffer[20] = 2; /* controller type */ + esdi->buffer[21] = 1; /* sector buffer size, in sectors */ + esdi->buffer[22] = 0; /* ecc bytes appended */ + esdi->buffer[27] = 'W' | ('D' << 8); + esdi->buffer[28] = '1' | ('0' << 8); + esdi->buffer[29] = '0' | ('7' << 8); + esdi->buffer[30] = 'V' | ('-' << 8); + esdi->buffer[31] = 'S' | ('E' << 8); + esdi->buffer[32] = '1'; + esdi->buffer[47] = 0; /* sectors per interrupt */ + esdi->buffer[48] = 0;/* can use double word read/write? */ + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + irq_raise(esdi); + break; + + default: + pclog("ESDI Callback on unknown command %02x\n", esdi->command); + case 0xe8: + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } + + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); +} + + +static void +esdi_rom_write(uint32_t addr, uint8_t val, void *priv) +{ + rom_t *rom = (rom_t *)priv; + + addr &= rom->mask; + if (addr >= 0x1f00 && addr < 0x2000) + rom->rom[addr] = val; +} + + +static void +loadhd(esdi_t *esdi, int hdd_num, int d, const wchar_t *fn) +{ + drive_t *drive = &esdi->drives[d]; + + if (! hdd_image_load(hdd_num)) { + drive->present = 0; + return; + } + + drive->cfg_spt = drive->real_spt = hdd[hdd_num].spt; + drive->cfg_hpc = drive->real_hpc = hdd[hdd_num].hpc; + drive->real_tracks = hdd[hdd_num].tracks; + drive->hdd_num = hdd_num; + drive->present = 1; +} + + +static void * +wd1007vse1_init(device_t *info) +{ + int i, c = 0; + + esdi_t *esdi = malloc(sizeof(esdi_t)); + memset(esdi, 0x00, sizeof(esdi_t)); + + esdi->drives[0].present = esdi->drives[1].present = 0; + + for (i=0; i= ESDI_NUM) break; + } + } + + esdi->status = STAT_READY | STAT_DSC; + esdi->error = 1; + + rom_init(&esdi->bios_rom, + BIOS_FILE, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_set_handler( + &esdi->bios_rom.mapping, + rom_read, rom_readw, rom_readl, + esdi_rom_write, NULL, NULL); + + io_sethandler(0x01f0, 1, + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, esdi); + io_sethandler(0x01f1, 7, + esdi_read, NULL, NULL, + esdi_write, NULL, NULL, esdi); + io_sethandler(0x03f6, 1, NULL, NULL, NULL, + esdi_write, NULL, NULL, esdi); + + timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi); + + return(esdi); +} + + +static void +wd1007vse1_close(void *priv) +{ + esdi_t *esdi = (esdi_t *)priv; + drive_t *drive; + int d; + + esdi->drives[0].present = esdi->drives[1].present = 0; + + for (d=0; d<2; d++) { + drive = &esdi->drives[d]; + + hdd_image_close(drive->hdd_num); + } + + free(esdi); +} + + +static int +wd1007vse1_available(void) +{ + return(rom_present(BIOS_FILE)); +} + + +device_t esdi_at_wd1007vse1_device = { + "Western Digital WD1007V-SE1 (ESDI)", + DEVICE_ISA | DEVICE_AT, + 0, + wd1007vse1_init, + wd1007vse1_close, + NULL, + wd1007vse1_available, + NULL, NULL, NULL, NULL +}; diff --git a/src/hdd/hdd_esdi_mca.c b/src/disk/hdc_esdi_mca.c similarity index 95% rename from src/hdd/hdd_esdi_mca.c rename to src/disk/hdc_esdi_mca.c index 8e1895d33..19868e488 100644 --- a/src/hdd/hdd_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -52,25 +52,31 @@ * however, are auto-configured by the system software as * shown above. * - * Version: @(#)hdd_esdi_mca.c 1.0.2 2017/08/27 + * Version: @(#)hdc_esdi_mca.c 1.0.6 2017/10/09 * * Authors: Sarah Walker, - * Miran Grca, + * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2017 Fred N. van Kempen. */ -#include +#include +#include +#include +#include +#include #include "../ibm.h" #include "../device.h" #include "../dma.h" -#include "hdd_image.h" #include "../io.h" #include "../mca.h" #include "../mem.h" #include "../pic.h" #include "../rom.h" #include "../timer.h" -#include "hdd_esdi_mca.h" +#include "../ui.h" +#include "hdc.h" +#include "hdd.h" /* These are hardwired. */ @@ -78,8 +84,11 @@ #define ESDI_IOADDR_SEC 0x3518 #define ESDI_IRQCHAN 14 +#define BIOS_FILE_L L"roms/hdd/esdi/90x8969.bin" +#define BIOS_FILE_H L"roms/hdd/esdi/90x8970.bin" -#define ESDI_TIME (2000 * TIMER_USEC) + +#define ESDI_TIME (200LL*TIMER_USEC) #define CMD_ADAPTER 0 @@ -88,8 +97,8 @@ typedef struct esdi_drive { int tracks; int sectors; int present; - int hdc_num; -} esdi_drive_t; + int hdd_num; +} drive_t; typedef struct esdi { uint16_t base; @@ -125,7 +134,7 @@ typedef struct esdi { int cmd_state; int in_reset; - int callback; + int64_t callback; uint32_t rba; @@ -133,7 +142,7 @@ typedef struct esdi { int req_in_progress; } cmds[3]; - esdi_drive_t drives[2]; + drive_t drives[2]; uint8_t pos_regs[8]; } esdi_t; @@ -267,10 +276,10 @@ static void esdi_callback(void *priv) { esdi_t *dev = (esdi_t *)priv; - esdi_drive_t *drive; + drive_t *drive; int val; - dev->callback = 0; + dev->callback = 0LL; /* If we are returning from a RESET, handle this first. */ if (dev->in_reset) { @@ -317,8 +326,8 @@ esdi_callback(void *priv) if (! dev->data_pos) { if (dev->rba >= drive->sectors) fatal("Read past end of drive\n"); - hdd_image_read(drive->hdc_num, dev->rba, 1, (uint8_t *)dev->data); - update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1); + hdd_image_read(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); } while (dev->data_pos < 256) { @@ -396,14 +405,14 @@ esdi_callback(void *priv) if (dev->rba >= drive->sectors) fatal("Write past end of drive\n"); - hdd_image_write(drive->hdc_num, dev->rba, 1, (uint8_t *)dev->data); + hdd_image_write(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data); dev->rba++; dev->sector_pos++; - update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); dev->data_pos = 0; } - update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); dev->status = STATUS_CMD_IN_PROGRESS; dev->cmd_state = 2; @@ -671,7 +680,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case 2: /*Basic control register*/ if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { dev->in_reset = 1; - dev->callback = ESDI_TIME * 50; + dev->callback = ESDI_TIME * 50LL; dev->status = STATUS_BUSY; } dev->basic_ctrl = val; @@ -701,7 +710,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case ATTN_RESET: dev->in_reset = 1; - dev->callback = ESDI_TIME * 50; + dev->callback = ESDI_TIME * 50LL; dev->status = STATUS_BUSY; break; @@ -963,9 +972,9 @@ esdi_mca_write(int port, uint8_t val, void *priv) static void * -esdi_init(void) +esdi_init(device_t *info) { - esdi_drive_t *drive; + drive_t *drive; esdi_t *dev; int c, i; @@ -980,17 +989,16 @@ esdi_init(void) dev->irq = ESDI_IRQCHAN; rom_init_interleaved(&dev->bios_rom, - L"roms/hdd/esdi/90x8970.bin", - L"roms/hdd/esdi/90x8969.bin", - 0x00000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + BIOS_FILE_L, BIOS_FILE_H, + 0x00000, 16384, 0x3fff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_disable(&dev->bios_rom.mapping); dev->drives[0].present = dev->drives[1].present = 0; - for (c=0,i=0; idrives[hdc[i].esdi_channel]; + drive = &dev->drives[hdd[i].esdi_channel]; /* Try to load an image for the drive. */ if (! hdd_image_load(i)) { @@ -1000,11 +1008,11 @@ esdi_init(void) } /* OK, so fill in geometry info. */ - drive->spt = hdc[i].spt; - drive->hpc = hdc[i].hpc; - drive->tracks = hdc[i].tracks; - drive->sectors = hdc[i].spt*hdc[i].hpc*hdc[i].tracks; - drive->hdc_num = i; + drive->spt = hdd[i].spt; + drive->hpc = hdd[i].hpc; + drive->tracks = hdd[i].tracks; + drive->sectors = hdd[i].spt*hdd[i].hpc*hdd[i].tracks; + drive->hdd_num = i; /* Mark drive as present. */ drive->present = 1; @@ -1022,7 +1030,7 @@ esdi_init(void) /* Mark for a reset. */ dev->in_reset = 1; - dev->callback = ESDI_TIME * 50; + dev->callback = ESDI_TIME * 50LL; dev->status = STATUS_BUSY; /* Set the reply timer. */ @@ -1036,7 +1044,7 @@ static void esdi_close(void *priv) { esdi_t *dev = (esdi_t *)priv; - esdi_drive_t *drive; + drive_t *drive; int d; dev->drives[0].present = dev->drives[1].present = 0; @@ -1044,7 +1052,7 @@ esdi_close(void *priv) for (d=0; d<2; d++) { drive = &dev->drives[d]; - hdd_image_close(drive->hdc_num); + hdd_image_close(drive->hdd_num); } free(dev); @@ -1054,20 +1062,13 @@ esdi_close(void *priv) static int esdi_available(void) { - return(rom_present(L"roms/hdd/esdi/90x8969.bin") && - rom_present(L"roms/hdd/esdi/90x8970.bin")); + return(rom_present(BIOS_FILE_L) && rom_present(BIOS_FILE_H)); } -device_t hdd_esdi_device = -{ +device_t esdi_ps2_device = { "IBM ESDI Fixed Disk Adapter (MCA)", - DEVICE_MCA, - esdi_init, - esdi_close, - esdi_available, - NULL, - NULL, - NULL, - NULL + DEVICE_MCA, 0, + esdi_init, esdi_close, NULL, + esdi_available, NULL, NULL, NULL, NULL }; diff --git a/src/hdd/hdd_ide_at.c b/src/disk/hdc_ide.c similarity index 84% rename from src/hdd/hdd_ide_at.c rename to src/disk/hdc_ide.c index b9c92ba99..69e83229f 100644 --- a/src/hdd/hdd_ide_at.c +++ b/src/disk/hdc_ide.c @@ -9,16 +9,20 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdd_ide_at.c 1.0.6 2017/09/03 + * Version: @(#)hdc_ide.c 1.0.12 2017/10/11 * * Authors: Sarah Walker, * Miran Grca, - * TheCollector1995, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ +#define __USE_LARGEFILE64 +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#include #include -#include +#include #include #include #include "../86box.h" @@ -27,10 +31,13 @@ #include "../pic.h" #include "../pci.h" #include "../timer.h" +#include "../device.h" #include "../cdrom/cdrom.h" #include "../scsi/scsi.h" -#include "hdd_image.h" -#include "hdd_ide_at.h" +#include "../ui.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "hdd.h" /* Bits of 'atastat' */ @@ -83,38 +90,19 @@ enum IDE_CDROM }; -uint64_t hdt[128][3] = { { 306, 4, 17 }, { 615, 2, 17 }, { 306, 4, 26 }, { 1024, 2, 17 }, { 697, 3, 17 }, { 306, 8, 17 }, { 614, 4, 17 }, { 615, 4, 17 }, /* 000-007 */ - { 670, 4, 17 }, { 697, 4, 17 }, { 987, 3, 17 }, { 820, 4, 17 }, { 670, 5, 17 }, { 697, 5, 17 }, { 733, 5, 17 }, { 615, 6, 17 }, /* 008-015 */ - { 462, 8, 17 }, { 306, 8, 26 }, { 615, 4, 26 }, { 1024, 4, 17 }, { 855, 5, 17 }, { 925, 5, 17 }, { 932, 5, 17 }, { 1024, 2, 40 }, /* 016-023 */ - { 809, 6, 17 }, { 976, 5, 17 }, { 977, 5, 17 }, { 698, 7, 17 }, { 699, 7, 17 }, { 981, 5, 17 }, { 615, 8, 17 }, { 989, 5, 17 }, /* 024-031 */ - { 820, 4, 26 }, { 1024, 5, 17 }, { 733, 7, 17 }, { 754, 7, 17 }, { 733, 5, 26 }, { 940, 6, 17 }, { 615, 6, 26 }, { 462, 8, 26 }, /* 032-039 */ - { 830, 7, 17 }, { 855, 7, 17 }, { 751, 8, 17 }, { 1024, 4, 26 }, { 918, 7, 17 }, { 925, 7, 17 }, { 855, 5, 26 }, { 977, 7, 17 }, /* 040-047 */ - { 987, 7, 17 }, { 1024, 7, 17 }, { 823, 4, 38 }, { 925, 8, 17 }, { 809, 6, 26 }, { 976, 5, 26 }, { 977, 5, 26 }, { 698, 7, 26 }, /* 048-055 */ - { 699, 7, 26 }, { 940, 8, 17 }, { 615, 8, 26 }, { 1024, 5, 26 }, { 733, 7, 26 }, { 1024, 8, 17 }, { 823, 10, 17 }, { 754, 11, 17 }, /* 056-063 */ - { 830, 10, 17 }, { 925, 9, 17 }, { 1224, 7, 17 }, { 940, 6, 26 }, { 855, 7, 26 }, { 751, 8, 26 }, { 1024, 9, 17 }, { 965, 10, 17 }, /* 064-071 */ - { 969, 5, 34 }, { 980, 10, 17 }, { 960, 5, 35 }, { 918, 11, 17 }, { 1024, 10, 17 }, { 977, 7, 26 }, { 1024, 7, 26 }, { 1024, 11, 17 }, /* 072-079 */ - { 940, 8, 26 }, { 776, 8, 33 }, { 755, 16, 17 }, { 1024, 12, 17 }, { 1024, 8, 26 }, { 823, 10, 26 }, { 830, 10, 26 }, { 925, 9, 26 }, /* 080-087 */ - { 960, 9, 26 }, { 1024, 13, 17 }, { 1224, 11, 17 }, { 900, 15, 17 }, { 969, 7, 34 }, { 917, 15, 17 }, { 918, 15, 17 }, { 1524, 4, 39 }, /* 088-095 */ - { 1024, 9, 26 }, { 1024, 14, 17 }, { 965, 10, 26 }, { 980, 10, 26 }, { 1020, 15, 17 }, { 1023, 15, 17 }, { 1024, 15, 17 }, { 1024, 16, 17 }, /* 096-103 */ - { 1224, 15, 17 }, { 755, 16, 26 }, { 903, 8, 46 }, { 984, 10, 34 }, { 900, 15, 26 }, { 917, 15, 26 }, { 1023, 15, 26 }, { 684, 16, 38 }, /* 104-111 */ - { 1930, 4, 62 }, { 967, 16, 31 }, { 1013, 10, 63 }, { 1218, 15, 36 }, { 654, 16, 63 }, { 659, 16, 63 }, { 702, 16, 63 }, { 1002, 13, 63 }, /* 112-119 */ - { 854, 16, 63 }, { 987, 16, 63 }, { 995, 16, 63 }, { 1024, 16, 63 }, { 1036, 16, 63 }, { 1120, 16, 59 }, { 1054, 16, 63 }, { 0, 0, 0 } }; /* 119-127 */ - + IDE ide_drives[IDE_NUM + XTIDE_NUM]; - IDE *ext_ide; - int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); void (*ide_bus_master_set_irq)(int channel); - -int idecallback[5] = {0, 0, 0, 0, 0}; - +int64_t idecallback[5] = {0LL, 0LL, 0LL, 0LL, 0LL}; int cur_ide[5]; + int ide_do_log = 0; -void ide_log(const char *format, ...) +static void ide_log(const char *format, ...) { #ifdef ENABLE_IDE_LOG if (ide_do_log) @@ -343,29 +331,29 @@ static void ide_identify(IDE *ide) uint32_t c, h, s; char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; #if 0 - uint64_t full_size = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt); + uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); #endif - device_identify[6] = (ide->hdc_num / 10) + 0x30; - device_identify[7] = (ide->hdc_num % 10) + 0x30; + device_identify[6] = (ide->hdd_num / 10) + 0x30; + device_identify[7] = (ide->hdd_num % 10) + 0x30; ide_log("IDE Identify: %s\n", device_identify); memset(ide->buffer, 0, 512); - c = hdc[ide->hdc_num].tracks; /* Cylinders */ - h = hdc[ide->hdc_num].hpc; /* Heads */ - s = hdc[ide->hdc_num].spt; /* Sectors */ + c = hdd[ide->hdd_num].tracks; /* Cylinders */ + h = hdd[ide->hdd_num].hpc; /* Heads */ + s = hdd[ide->hdd_num].spt; /* Sectors */ - if (hdc[ide->hdc_num].tracks <= 16383) + if (hdd[ide->hdd_num].tracks <= 16383) { - ide->buffer[1] = hdc[ide->hdc_num].tracks; /* Cylinders */ + ide->buffer[1] = hdd[ide->hdd_num].tracks; /* Cylinders */ } else { ide->buffer[1] = 16383; /* Cylinders */ } - ide->buffer[3] = hdc[ide->hdc_num].hpc; /* Heads */ - ide->buffer[6] = hdc[ide->hdc_num].spt; /* Sectors */ + ide->buffer[3] = hdd[ide->hdd_num].hpc; /* Heads */ + ide->buffer[6] = hdd[ide->hdd_num].spt; /* Sectors */ ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ @@ -373,7 +361,7 @@ static void ide_identify(IDE *ide) ide->buffer[21] = 512; /*Buffer size*/ ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/ ide->buffer[48] = 1; /*Dword transfers supported*/ - if (PCI && (ide->board < 2) && (hdc[ide->hdc_num].bus == HDD_BUS_IDE_PIO_AND_DMA)) + if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA)) { ide->buffer[49] = (1 << 8); /* LBA and DMA supported */ } @@ -406,10 +394,10 @@ static void ide_identify(IDE *ide) ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; if (ide->buffer[49] & (1 << 9)) { - ide->buffer[60] = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt) & 0xFFFF; /* Total addressable sectors (LBA) */ - ide->buffer[61] = ((hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt) >> 16) & 0x0FFF; + ide->buffer[60] = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt) & 0xFFFF; /* Total addressable sectors (LBA) */ + ide->buffer[61] = ((hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt) >> 16) & 0x0FFF; } - if (PCI && (ide->board < 2) && (hdc[ide->hdc_num].bus == HDD_BUS_IDE_PIO_AND_DMA)) + if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA)) { ide->buffer[52] = 2 << 8; /*DMA timing mode*/ @@ -499,21 +487,16 @@ static void ide_next_sector(IDE *ide) static void loadhd(IDE *ide, int d, const wchar_t *fn) { - int ret = 0; - - ret = hdd_image_load(d); - - if (!ret) - { + if (! hdd_image_load(d)) { ide->type = IDE_NONE; return; } - ide->spt = hdc[d].spt; - ide->hpc = hdc[d].hpc; - ide->tracks = hdc[d].tracks; + ide->spt = hdd[d].spt; + ide->hpc = hdd[d].hpc; + ide->tracks = hdd[d].tracks; ide->type = IDE_HDD; - ide->hdc_num = d; + ide->hdd_num = d; ide->hdi = hdd_image_get_type(d); } @@ -590,7 +573,7 @@ static int ide_set_features(IDE *ide) break; case 0x04: /* Multiword DMA mode */ - if (!PCI || (hdc[ide->hdc_num].bus != HDD_BUS_IDE_PIO_AND_DMA) || (ide->board >= 2) || (submode > 2)) + if (!PCI || (hdd[ide->hdd_num].bus != HDD_BUS_IDE_PIO_AND_DMA) || (ide->board >= 2) || (submode > 2)) { return 0; } @@ -619,30 +602,32 @@ void ide_set_sector(IDE *ide, int64_t sector_num) } else { - cyl = sector_num / (hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt); - r = sector_num % (hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt); + cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); ide->cylinder = cyl; - ide->head = ((r / hdc[ide->hdc_num].spt) & 0x0f); - ide->sector = (r % hdc[ide->hdc_num].spt) + 1; + ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f); + ide->sector = (r % hdd[ide->hdd_num].spt) + 1; } } void ide_ter_disable_cond(); void ide_qua_disable_cond(); -void resetide(void) + +void ide_reset(void) { int c, d; - + build_atapi_cdrom_map(); /* Close hard disk image files (if previously open) */ - for (d = 0; d < (IDE_NUM + XTIDE_NUM); d++) + for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++) { ide_drives[d].channel = d; ide_drives[d].type = IDE_NONE; - hdd_image_close(ide_drives[d].hdc_num); - if (ide_drive_is_cdrom(&ide_drives[d])) + if (ide_drives[d].hdd_num != -1) + hdd_image_close(ide_drives[d].hdd_num); + if ((d < 8) && ide_drive_is_cdrom(&ide_drives[d])) { cdrom[atapi_cdrom_drives[d]].status = READY_STAT | DSC_STAT; } @@ -651,28 +636,28 @@ void resetide(void) ide_drives[d].board = d >> 1; } - idecallback[0]=idecallback[1]=0; - idecallback[2]=idecallback[3]=0; - idecallback[4]=0; + idecallback[0]=idecallback[1]=0LL; + idecallback[2]=idecallback[3]=0LL; + idecallback[4]=0LL; + pclog("IDE: loading disks...\n"); c = 0; - for (d = 0; d < HDC_NUM; d++) + for (d = 0; d < HDD_NUM; d++) { - if (((hdc[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdc[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdc[d].ide_channel < IDE_NUM)) + if (((hdd[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdd[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdd[d].ide_channel < IDE_NUM)) { - ide_log("Found IDE hard disk on channel %i\n", hdc[d].ide_channel); - loadhd(&ide_drives[hdc[d].ide_channel], d, hdc[d].fn); - c++; - if (c >= (IDE_NUM + XTIDE_NUM)) break; + ide_log("Found IDE hard disk on channel %i\n", hdd[d].ide_channel); + loadhd(&ide_drives[hdd[d].ide_channel], d, hdd[d].fn); + if (++c >= (IDE_NUM+XTIDE_NUM)) break; } - if ((hdc[d].bus == HDD_BUS_XTIDE) && (hdc[d].xtide_channel < XTIDE_NUM)) + if ((hdd[d].bus==HDD_BUS_XTIDE) && (hdd[d].xtide_channel < XTIDE_NUM)) { - ide_log("Found XT IDE hard disk on channel %i\n", hdc[d].xtide_channel); - loadhd(&ide_drives[hdc[d].xtide_channel | 8], d, hdc[d].fn); - c++; - if (c >= (IDE_NUM + XTIDE_NUM)) break; + ide_log("Found XT IDE hard disk on channel %i\n", hdd[d].xtide_channel); + loadhd(&ide_drives[hdd[d].xtide_channel | 8], d, hdd[d].fn); + if (++c >= (IDE_NUM+XTIDE_NUM)) break; } } + pclog("IDE: done, loaded %d disks.\n", c); for (d = 0; d < IDE_NUM; d++) { @@ -770,7 +755,7 @@ void ide_write_data(int ide_board, uint32_t val, int length) } else { - idecallback[ide_board]=6*IDE_TIME; + idecallback[ide_board]=6LL*IDE_TIME; } timer_update_outstanding(); } @@ -900,7 +885,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) cdrom[atapi_cdrom_drives[ide->channel]].error = 1; cdrom[atapi_cdrom_drives[ide->channel]].phase = 1; cdrom[atapi_cdrom_drives[ide->channel]].request_length = 0xEB14; - cdrom[atapi_cdrom_drives[ide->channel]].callback = 0; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 0LL; ide->cylinder = 0xEB14; } if (ide_drive_is_cdrom(ide_other)) @@ -909,11 +894,11 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) cdrom[atapi_cdrom_drives[ide_other->channel]].error = 1; cdrom[atapi_cdrom_drives[ide_other->channel]].phase = 1; cdrom[atapi_cdrom_drives[ide_other->channel]].request_length = 0xEB14; - cdrom[atapi_cdrom_drives[ide_other->channel]].callback = 0; + cdrom[atapi_cdrom_drives[ide_other->channel]].callback = 0LL; ide->cylinder = 0xEB14; } - idecallback[ide_board] = 0; + idecallback[ide_board] = 0LL; timer_update_outstanding(); return; } @@ -959,9 +944,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 100*IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 100LL*IDE_TIME; } - idecallback[ide_board]=100*IDE_TIME; + idecallback[ide_board]=100LL*IDE_TIME; timer_update_outstanding(); return; @@ -978,9 +963,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 100*IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 100LL*IDE_TIME; } - idecallback[ide_board]=100*IDE_TIME; + idecallback[ide_board]=100LL*IDE_TIME; timer_update_outstanding(); return; @@ -1006,9 +991,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME; } - idecallback[ide_board]=200*IDE_TIME; + idecallback[ide_board]=200LL*IDE_TIME; timer_update_outstanding(); ide->do_initial_read = 1; return; @@ -1046,9 +1031,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME; } - idecallback[ide_board]=200*IDE_TIME; + idecallback[ide_board]=200LL*IDE_TIME; timer_update_outstanding(); return; @@ -1065,9 +1050,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME; } - idecallback[ide_board]=200*IDE_TIME; + idecallback[ide_board]=200LL*IDE_TIME; timer_update_outstanding(); return; @@ -1095,9 +1080,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 30*IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 30LL*IDE_TIME; } - idecallback[ide_board]=30*IDE_TIME; + idecallback[ide_board]=30LL*IDE_TIME; timer_update_outstanding(); return; @@ -1126,9 +1111,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) /* callbackide(ide_board); */ if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 200 * IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL * IDE_TIME; } - idecallback[ide_board] = 200 * IDE_TIME; + idecallback[ide_board] = 200LL * IDE_TIME; timer_update_outstanding(); } else @@ -1144,9 +1129,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 30 * IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 30LL * IDE_TIME; } - idecallback[ide_board] = 30 * IDE_TIME; + idecallback[ide_board] = 30LL * IDE_TIME; timer_update_outstanding(); } return; @@ -1164,9 +1149,9 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME; } - idecallback[ide_board]=200*IDE_TIME; + idecallback[ide_board]=200LL*IDE_TIME; timer_update_outstanding(); return; @@ -1183,7 +1168,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) { ide->atastat = BUSY_STAT; timer_process(); - idecallback[ide_board]=1; + idecallback[ide_board]=1LL; timer_update_outstanding(); ide->pos=0; } @@ -1213,9 +1198,9 @@ ide_bad_command: timer_process(); if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]].callback = 0; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 0LL; } - idecallback[ide_board]=500*IDE_TIME; + idecallback[ide_board]=500LL*IDE_TIME; timer_update_outstanding(); if (ide->type != IDE_NONE) @@ -1236,7 +1221,7 @@ ide_bad_command: { /*Drive held in reset*/ timer_process(); - idecallback[ide_board] = 0; + idecallback[ide_board] = 0LL; timer_update_outstanding(); ide->atastat = ide_other->atastat = BUSY_STAT; ide_irq_lower(ide); @@ -1313,13 +1298,13 @@ uint32_t ide_read_data(int ide_board, int length) } else { - idecallback[ide_board]=6*IDE_TIME; + idecallback[ide_board]=6LL*IDE_TIME; } timer_update_outstanding(); } else { - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } } } @@ -1513,13 +1498,13 @@ void callbackide(int ide_board) ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; if (ide->type == IDE_HDD) { - full_size = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt); + full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); } ext_ide = ide; if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback = 0; + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback = 0LL; } if (ide->command==0x30) times30++; @@ -1650,11 +1635,11 @@ void callbackide(int ide_board) ide->sector_pos = 0; if (ide->secount) { - hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); } else { - hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer); + hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); } } @@ -1667,7 +1652,7 @@ void callbackide(int ide_board) ide_irq_raise(ide); - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); return; case WIN_READ_DMA: @@ -1686,11 +1671,11 @@ void callbackide(int ide_board) ide->sector_pos = 0; if (ide->secount) { - hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); } else { - hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer); + hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); } } @@ -1700,7 +1685,7 @@ void callbackide(int ide_board) { if (ide_bus_master_read(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512)) { - idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + idecallback[ide_board]=6LL*IDE_TIME; /*DMA not performed, try again later*/ } else { @@ -1713,13 +1698,13 @@ void callbackide(int ide_board) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); + idecallback[ide_board]=6LL*IDE_TIME; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); } else { ide_irq_raise(ide); - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } } } @@ -1748,11 +1733,11 @@ void callbackide(int ide_board) ide->sector_pos = 0; if (ide->secount) { - hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); } else { - hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer); + hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); } } @@ -1772,7 +1757,7 @@ void callbackide(int ide_board) ide->blockcount = 0; } - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); return; case WIN_WRITE: @@ -1785,7 +1770,7 @@ void callbackide(int ide_board) { goto id_not_found; } - hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); ide_irq_raise(ide); ide->secount = (ide->secount - 1) & 0xff; if (ide->secount) @@ -1793,12 +1778,12 @@ void callbackide(int ide_board) ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; ide->pos=0; ide_next_sector(ide); - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); } else { ide->atastat = READY_STAT | DSC_STAT; - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } return; @@ -1817,12 +1802,12 @@ void callbackide(int ide_board) { if (ide_bus_master_write(ide_board, (uint8_t *)ide->buffer, 512)) { - idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + idecallback[ide_board]=6LL*IDE_TIME; /*DMA not performed, try again later*/ } else { /*DMA successful*/ - hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; @@ -1831,13 +1816,13 @@ void callbackide(int ide_board) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); + idecallback[ide_board]=6LL*IDE_TIME; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); } else { ide_irq_raise(ide); - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } } } @@ -1853,7 +1838,7 @@ void callbackide(int ide_board) { goto id_not_found; } - hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); ide->blockcount++; if (ide->blockcount >= ide->blocksize || ide->secount == 1) { @@ -1866,12 +1851,12 @@ void callbackide(int ide_board) ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; ide->pos=0; ide_next_sector(ide); - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); } else { ide->atastat = READY_STAT | DSC_STAT; - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } return; @@ -1888,7 +1873,7 @@ void callbackide(int ide_board) ide->pos=0; ide->atastat = READY_STAT | DSC_STAT; ide_irq_raise(ide); - update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); return; case WIN_FORMAT: @@ -1900,12 +1885,12 @@ void callbackide(int ide_board) { goto id_not_found; } - hdd_image_zero(ide->hdc_num, ide_get_sector(ide), ide->secount); + hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount); ide->atastat = READY_STAT | DSC_STAT; ide_irq_raise(ide); - /* update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); */ + /* ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); */ return; case WIN_DRIVE_DIAGNOSTICS: @@ -1952,7 +1937,7 @@ void callbackide(int ide_board) full_size /= (ide->head+1); full_size /= ide->secount; ide->specify_success = 1; - hdd_image_specify(ide->hdc_num, ide->head + 1, ide->secount); + hdd_image_specify(ide->hdd_num, ide->head + 1, ide->secount); ide->spt=ide->secount; ide->hpc=ide->head+1; ide->atastat = READY_STAT | DSC_STAT; @@ -2004,9 +1989,9 @@ void callbackide(int ide_board) { goto abort_cmd; } - snum = hdc[ide->hdc_num].spt; - snum *= hdc[ide->hdc_num].hpc; - snum *= hdc[ide->hdc_num].tracks; + snum = hdd[ide->hdd_num].spt; + snum *= hdd[ide->hdd_num].hpc; + snum *= hdd[ide->hdd_num].tracks; ide_set_sector(ide, snum - 1); ide->atastat = READY_STAT | DSC_STAT; ide_irq_raise(ide); @@ -2075,31 +2060,31 @@ id_not_found: void ide_callback_pri() { - idecallback[0] = 0; + idecallback[0] = 0LL; callbackide(0); } void ide_callback_sec() { - idecallback[1] = 0; + idecallback[1] = 0LL; callbackide(1); } void ide_callback_ter() { - idecallback[2] = 0; + idecallback[2] = 0LL; callbackide(2); } void ide_callback_qua() { - idecallback[3] = 0; + idecallback[3] = 0LL; callbackide(3); } void ide_callback_xtide() { - idecallback[4] = 0; + idecallback[4] = 0LL; callbackide(4); } @@ -2206,7 +2191,8 @@ uint32_t ide_read_qua_l(uint16_t addr, void *priv) static uint16_t ide_base_main[2] = { 0x1f0, 0x170 }; static uint16_t ide_side_main[2] = { 0x3f6, 0x376 }; -void ide_pri_enable() + +void ide_pri_enable(void) { io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); @@ -2214,7 +2200,7 @@ void ide_pri_enable() ide_side_main[0] = 0x3f6; } -void ide_pri_enable_ex() +void ide_pri_enable_ex(void) { if (ide_base_main[0] & 0x300) { @@ -2228,13 +2214,13 @@ void ide_pri_enable_ex() } } -void ide_pri_disable() +void ide_pri_disable(void) { io_removehandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); io_removehandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); } -void ide_sec_enable() +void ide_sec_enable(void) { io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); @@ -2242,7 +2228,7 @@ void ide_sec_enable() ide_side_main[1] = 0x376; } -void ide_sec_enable_ex() +void ide_sec_enable_ex(void) { if (ide_base_main[1] & 0x300) { @@ -2254,12 +2240,13 @@ void ide_sec_enable_ex() } } -void ide_sec_disable() +void ide_sec_disable(void) { io_removehandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); io_removehandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); } + void ide_set_base(int controller, uint16_t port) { ide_base_main[controller] = port; @@ -2270,19 +2257,19 @@ void ide_set_side(int controller, uint16_t port) ide_side_main[controller] = port; } -void ide_ter_enable() +void ide_ter_enable(void) { io_sethandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL); io_sethandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL); } -void ide_ter_disable() +void ide_ter_disable(void) { io_removehandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL); io_removehandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL); } -void ide_ter_disable_cond() +void ide_ter_disable_cond(void) { if ((ide_drives[4].type == IDE_NONE) && (ide_drives[5].type == IDE_NONE)) { @@ -2290,20 +2277,20 @@ void ide_ter_disable_cond() } } -void ide_ter_init() +void ide_ter_init(void) { ide_ter_enable(); timer_add(ide_callback_ter, &idecallback[2], &idecallback[2], NULL); } -void ide_qua_enable() +void ide_qua_enable(void) { io_sethandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL); io_sethandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL); } -void ide_qua_disable_cond() +void ide_qua_disable_cond(void) { if ((ide_drives[6].type == IDE_NONE) && (ide_drives[7].type == IDE_NONE)) { @@ -2311,20 +2298,39 @@ void ide_qua_disable_cond() } } -void ide_qua_disable() +void ide_qua_disable(void) { io_removehandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL); io_removehandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL); } -void ide_qua_init() +void ide_qua_init(void) { ide_qua_enable(); timer_add(ide_callback_qua, &idecallback[3], &idecallback[3], NULL); } -void ide_init() + +/*FIXME: this will go away after Kotori's rewrite. --FvK */ +void ide_init_first(void) +{ + int d; + + memset(ide_drives, 0x00, sizeof(ide_drives)); + for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++) + { + ide_drives[d].channel = d; + ide_drives[d].type = IDE_NONE; + ide_drives[d].hdd_num = -1; + ide_drives[d].atastat = READY_STAT | DSC_STAT; + ide_drives[d].service = 0; + ide_drives[d].board = d >> 1; + } +} + + +void ide_init(void) { ide_pri_enable(); ide_sec_enable(); @@ -2334,7 +2340,8 @@ void ide_init() timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL); } -void ide_xtide_init() + +void ide_xtide_init(void) { ide_bus_master_read = ide_bus_master_write = NULL; diff --git a/src/hdd/hdd_ide_at.h b/src/disk/hdc_ide.h similarity index 91% rename from src/hdd/hdd_ide_at.h rename to src/disk/hdc_ide.h index 8aa64b944..2ee0b0f50 100644 --- a/src/hdd/hdd_ide_at.h +++ b/src/disk/hdc_ide.h @@ -9,11 +9,10 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdd_ide_at.h 1.0.2 2017/08/24 + * Version: @(#)hdd_ide.h 1.0.4 2017/09/30 * * Authors: Sarah Walker, * Miran Grca, - * TheCollector1995, * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ @@ -21,7 +20,6 @@ # define EMU_IDE_H -#pragma pack(push,1) typedef struct { int type; int board; @@ -47,14 +45,13 @@ typedef struct { int blocksize, blockcount; uint16_t dma_identify_data[3]; int hdi,base; - int hdc_num; + int hdd_num; uint8_t specify_success; int mdma_mode; uint8_t sector_buffer[256*512]; int do_initial_read; int sector_pos; } IDE; -#pragma pack(pop) extern int ideboard; @@ -63,43 +60,47 @@ extern int ide_enable[5]; extern int ide_irq[5]; extern IDE ide_drives[IDE_NUM + XTIDE_NUM]; -extern int idecallback[5]; +extern int64_t idecallback[5]; +extern void ide_irq_raise(IDE *ide); +extern void ide_irq_lower(IDE *ide); + extern void writeide(int ide_board, uint16_t addr, uint8_t val); extern void writeidew(int ide_board, uint16_t val); extern uint8_t readide(int ide_board, uint16_t addr); extern uint16_t readidew(int ide_board); extern void callbackide(int ide_board); -extern void resetide(void); -extern void ide_init(void); -extern void ide_xtide_init(void); -extern void ide_ter_init(void); -extern void ide_qua_init(void); -extern void ide_pri_enable(void); -extern void ide_sec_enable(void); -extern void ide_ter_enable(void); -extern void ide_qua_enable(void); -extern void ide_pri_disable(void); -extern void ide_sec_disable(void); -extern void ide_ter_disable(void); -extern void ide_qua_disable(void); + extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel)); -extern void ide_irq_raise(IDE *ide); -extern void ide_irq_lower(IDE *ide); - -extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); - extern void win_cdrom_eject(uint8_t id); extern void win_cdrom_reload(uint8_t id); -extern void ide_pri_disable(void); -extern void ide_pri_enable_ex(void); extern void ide_set_base(int controller, uint16_t port); extern void ide_set_side(int controller, uint16_t port); +extern void ide_init_first(void); +extern void ide_init(void); +extern void ide_reset(void); + +extern void ide_xtide_init(void); + +extern void ide_pri_enable(void); +extern void ide_pri_enable_ex(void); +extern void ide_pri_disable(void); +extern void ide_sec_enable(void); +extern void ide_sec_disable(void); +extern void ide_ter_enable(void); +extern void ide_ter_disable(void); +extern void ide_ter_init(void); +extern void ide_qua_enable(void); +extern void ide_qua_disable(void); +extern void ide_qua_init(void); + extern void secondary_ide_check(void); +extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); + #endif /*EMU_IDE_H*/ diff --git a/src/disk/hdc_mfm_at.c b/src/disk/hdc_mfm_at.c new file mode 100644 index 000000000..11d77373e --- /dev/null +++ b/src/disk/hdc_mfm_at.c @@ -0,0 +1,771 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Driver for the IBM PC-AT MFM/RLL Fixed Disk controller. + * + * This controller was a 16bit ISA card, and it used a WD1003 + * based design. Most cards were WD1003-WA2 or -WAH, where the + * -WA2 cards had a floppy controller as well (to save space.) + * + * Version: @(#)hdd_mfm_at.c 1.0.8 2017/10/14 + * + * Authors: Sarah Walker, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2017 Fred N. van Kempen. + */ +#define __USE_LARGEFILE64 +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../device.h" +#include "../io.h" +#include "../pic.h" +#include "../timer.h" +#include "../ui.h" +#include "hdc.h" +#include "hdd.h" + + +#define MFM_TIME (TIMER_USEC*10LL) +#define MFM_DEBUG 0 + +#define STAT_ERR 0x01 +#define STAT_INDEX 0x02 +#define STAT_ECC 0x04 +#define STAT_DRQ 0x08 /* data request */ +#define STAT_DSC 0x10 +#define STAT_WRFLT 0x20 +#define STAT_READY 0x40 +#define STAT_BUSY 0x80 + +#define ERR_DAM_NOT_FOUND 0x01 /* Data Address Mark not found */ +#define ERR_TR000 0x02 /* track 0 not found */ +#define ERR_ABRT 0x04 /* command aborted */ +#define ERR_ID_NOT_FOUND 0x10 /* ID not found */ +#define ERR_DATA_CRC 0x40 /* data CRC error */ +#define ERR_BAD_BLOCK 0x80 /* bad block detected */ + +#define CMD_RESTORE 0x10 +#define CMD_READ 0x20 +#define CMD_WRITE 0x30 +#define CMD_VERIFY 0x40 +#define CMD_FORMAT 0x50 +#define CMD_SEEK 0x70 +#define CMD_DIAGNOSE 0x90 +#define CMD_SET_PARAMETERS 0x91 + + +typedef struct { + int8_t present, /* drive is present */ + hdd_num, /* drive number in system */ + steprate, /* current servo step rate */ + spt, /* physical #sectors per track */ + hpc, /* physical #heads per cylinder */ + pad; + int16_t tracks; /* physical #tracks per cylinder */ + + int8_t cfg_spt, /* configured #sectors per track */ + cfg_hpc; /* configured #heads per track */ + + int16_t curcyl; /* current track number */ +} drive_t; + + +typedef struct { + uint8_t precomp, /* 1: precomp/error register */ + error, + secount, /* 2: sector count register */ + sector, /* 3: sector number */ + head, /* 6: head number + drive select */ + command, /* 7: command/status */ + status, + fdisk; /* 8: control register */ + uint16_t cylinder; /* 4/5: cylinder LOW and HIGH */ + + int8_t reset, /* controller in reset */ + irqstat, /* current IRQ status */ + drvsel, /* current selected drive */ + pad; + + int pos; /* offset within data buffer */ + int64_t callback; /* callback delay timer */ + + uint16_t buffer[256]; /* data buffer (16b wide) */ + + drive_t drives[MFM_NUM]; /* attached drives */ +} mfm_t; + + +static __inline void irq_raise(mfm_t *mfm) +{ + /* If not already pending.. */ + if (! mfm->irqstat) { + /* If enabled in the control register.. */ + if (! (mfm->fdisk&0x02)) { + /* .. raise IRQ14. */ + picint(1<<14); + } + + /* Remember this. */ + mfm->irqstat = 1; + } +} + + +static __inline void irq_lower(mfm_t *mfm) +{ + /* If raised.. */ + if (mfm->irqstat) { + /* If enabled in the control register.. */ + if (! (mfm->fdisk&0x02)) { + /* .. drop IRQ14. */ + picintc(1<<14); + } + + /* Remember this. */ + mfm->irqstat = 0; + } +} + + +/* + * Return the sector offset for the current register values. + * + * According to the WD1002/WD1003 technical reference manual, + * this is not done entirely correct. It specifies that the + * parameters set with the SET_DRIVE_PARAMETERS command are + * to be used only for multi-sector operations, and that any + * such operation can only be executed AFTER these parameters + * have been set. This would imply that for regular single + * transfers, the controller uses (or, can use) the actual + * geometry information... + */ +static int +get_sector(mfm_t *mfm, off64_t *addr) +{ + drive_t *drive = &mfm->drives[mfm->drvsel]; + + if (drive->curcyl != mfm->cylinder) { + pclog("WD1003(%d) sector: wrong cylinder\n"); + return(1); + } + + if (mfm->head > drive->cfg_hpc) { + pclog("WD1003(%d) get_sector: past end of configured heads\n", + mfm->drvsel); + return(1); + } + + if (mfm->sector >= drive->cfg_spt+1) { + pclog("WD1003(%d) get_sector: past end of configured sectors\n", + mfm->drvsel); + return(1); + } + +#if 1 + /* We should check this in the SET_DRIVE_PARAMETERS command! --FvK */ + if (mfm->head > drive->hpc) { + pclog("WD1003(%d) get_sector: past end of heads\n", mfm->drvsel); + return(1); + } + + if (mfm->sector >= drive->spt+1) { + pclog("WD1003(%d) get_sector: past end of sectors\n", mfm->drvsel); + return(1); + } +#endif + + *addr = ((((off64_t) mfm->cylinder * drive->cfg_hpc) + mfm->head) * + drive->cfg_spt) + (mfm->sector - 1); + + return(0); +} + + +/* Move to the next sector using CHS addressing. */ +static void +next_sector(mfm_t *mfm) +{ + drive_t *drive = &mfm->drives[mfm->drvsel]; + + if (++mfm->sector == (drive->cfg_spt+1)) { + mfm->sector = 1; + if (++mfm->head == drive->cfg_hpc) { + mfm->head = 0; + mfm->cylinder++; + if (drive->curcyl < drive->tracks) + drive->curcyl++; + } + } +} + + +static void +mfm_cmd(mfm_t *mfm, uint8_t val) +{ + drive_t *drive = &mfm->drives[mfm->drvsel]; + + if (! drive->present) { + /* This happens if sofware polls all drives. */ + pclog("WD1003(%d) command %02x on non-present drive\n", + mfm->drvsel, val); + mfm->command = 0xff; + mfm->status = STAT_BUSY; + timer_process(); + mfm->callback = 200LL*MFM_TIME; + timer_update_outstanding(); + + return; + } + + irq_lower(mfm); + mfm->error = 0; + + switch (val & 0xf0) { + case CMD_RESTORE: + drive->steprate = (val & 0x0f); +#if MFM_DEBUG + pclog("WD1003(%d) restore, step=%d\n", + mfm->drvsel, drive->steprate); +#endif + drive->curcyl = 0; + mfm->status = STAT_READY|STAT_DSC; + mfm->command = 0x00; + irq_raise(mfm); + break; + + case CMD_SEEK: + drive->steprate = (val & 0x0f); + mfm->command = (val & 0xf0); + mfm->status = STAT_BUSY; + timer_process(); + mfm->callback = 200LL*MFM_TIME; + timer_update_outstanding(); + break; + + default: + switch (val) { + case CMD_READ: + case CMD_READ+1: + case CMD_READ+2: + case CMD_READ+3: +#if MFM_DEBUG + pclog("WD1003(%d) read, opt=%d\n", + mfm->drvsel, val&0x03); +#endif + mfm->command = (val & 0xf0); + if (val & 2) + fatal("WD1003: READ with ECC\n"); + mfm->status = STAT_BUSY; + timer_process(); + mfm->callback = 200LL*MFM_TIME; + timer_update_outstanding(); + break; + + case CMD_WRITE: + case CMD_WRITE+1: + case CMD_WRITE+2: + case CMD_WRITE+3: +#if MFM_DEBUG + pclog("WD1003(%d) write, opt=%d\n", + mfm->drvsel, val & 0x03); +#endif + mfm->command = (val & 0xf0); + if (val & 2) + fatal("WD1003: WRITE with ECC\n"); + mfm->status = STAT_DRQ|STAT_DSC; + mfm->pos = 0; + break; + + case CMD_VERIFY: + case CMD_VERIFY+1: + mfm->command = (val & 0xfe); + mfm->status = STAT_BUSY; + timer_process(); + mfm->callback = 200LL*MFM_TIME; + timer_update_outstanding(); + break; + + case CMD_FORMAT: + mfm->command = val; + mfm->status = STAT_DRQ|STAT_BUSY; + mfm->pos = 0; + break; + + case CMD_DIAGNOSE: + mfm->command = val; + mfm->status = STAT_BUSY; + timer_process(); + mfm->callback = 200LL*MFM_TIME; + timer_update_outstanding(); + break; + + case CMD_SET_PARAMETERS: + /* + * NOTE: + * + * We currently just set these parameters, and + * never bother to check if they "fit within" + * the actual parameters, as determined by the + * image loader. + * + * The difference in parameters is OK, and + * occurs when the BIOS or operating system + * decides to use a different translation + * scheme, but either way, it SHOULD always + * fit within the actual parameters! + * + * We SHOULD check that here!! --FvK + */ + if (drive->cfg_spt == 0) { + /* Only accept after RESET or DIAG. */ + drive->cfg_spt = mfm->secount; + drive->cfg_hpc = mfm->head+1; + pclog("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n", + mfm->drvsel, drive->tracks, + drive->cfg_spt, drive->cfg_hpc); + } else { + pclog("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n", + mfm->drvsel, drive->tracks, + drive->cfg_spt, drive->cfg_hpc); + } + mfm->command = 0x00; + mfm->status = STAT_READY|STAT_DSC; + mfm->error = 1; + irq_raise(mfm); + break; + + default: + pclog("WD1003: bad command %02X\n", val); + mfm->status = STAT_BUSY; + timer_process(); + mfm->callback = 200LL*MFM_TIME; + timer_update_outstanding(); + break; + } + } +} + + +static void +mfm_writew(uint16_t port, uint16_t val, void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + + mfm->buffer[mfm->pos >> 1] = val; + mfm->pos += 2; + + if (mfm->pos >= 512) { + mfm->pos = 0; + mfm->status = STAT_BUSY; + timer_process(); + mfm->callback = 6LL*MFM_TIME; + timer_update_outstanding(); + } +} + + +static void +mfm_write(uint16_t port, uint8_t val, void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + +#if MFM_DEBUG > 1 + pclog("WD1003 write(%04x, %02x)\n", port, val); +#endif + switch (port) { + case 0x01f0: /* data */ + mfm_writew(port, val | (val << 8), priv); + return; + + case 0x01f1: /* write precompenstation */ + mfm->precomp = val; + return; + + case 0x01f2: /* sector count */ + mfm->secount = val; + return; + + case 0x01f3: /* sector */ + mfm->sector = val; + return; + + case 0x01f4: /* cylinder low */ + mfm->cylinder = (mfm->cylinder & 0xff00) | val; + return; + + case 0x01f5: /* cylinder high */ + mfm->cylinder = (mfm->cylinder & 0xff) | (val << 8); + return; + + case 0x01f6: /* drive/head */ + mfm->head = val & 0xF; + mfm->drvsel = (val & 0x10) ? 1 : 0; + if (mfm->drives[mfm->drvsel].present) + mfm->status = STAT_READY|STAT_DSC; + else + mfm->status = 0; + return; + + case 0x01f7: /* command register */ + mfm_cmd(mfm, val); + break; + + case 0x03f6: /* device control */ + val &= 0x0f; + if ((mfm->fdisk & 0x04) && !(val & 0x04)) { + mfm->status = STAT_BUSY; + mfm->reset = 1; + timer_process(); + mfm->callback = 500LL*MFM_TIME; + timer_update_outstanding(); + } + + if (val & 0x04) { + /* Drive held in reset. */ + mfm->status = STAT_BUSY; + mfm->callback = 0LL; + timer_process(); + timer_update_outstanding(); + } + mfm->fdisk = val; + break; + } +} + + +static uint16_t +mfm_readw(uint16_t port, void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + uint16_t ret; + + ret = mfm->buffer[mfm->pos >> 1]; + mfm->pos += 2; + if (mfm->pos >= 512) { + mfm->pos = 0; + mfm->status = STAT_READY|STAT_DSC; + if (mfm->command == CMD_READ) { + mfm->secount = (mfm->secount - 1) & 0xff; + if (mfm->secount) { + next_sector(mfm); + mfm->status = STAT_BUSY; + timer_process(); + mfm->callback = 6LL*MFM_TIME; + timer_update_outstanding(); + } else { + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); + } + } + } + + return(ret); +} + + +static uint8_t +mfm_read(uint16_t port, void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x01f0: /* data */ + ret = mfm_readw(port, mfm) & 0xff; + break; + + case 0x01f1: /* error */ + ret = mfm->error; + break; + + case 0x01f2: /* sector count */ + ret = mfm->secount; + break; + + case 0x01f3: /* sector */ + ret = mfm->sector; + break; + + case 0x01f4: /* CYlinder low */ + ret = (uint8_t)(mfm->cylinder&0xff); + break; + + case 0x01f5: /* Cylinder high */ + ret = (uint8_t)(mfm->cylinder>>8); + break; + + case 0x01f6: /* drive/head */ + ret = (uint8_t)(0xa0 | mfm->head | (mfm->drvsel?0x10:0)); + break; + + case 0x01f7: /* Status */ + irq_lower(mfm); + ret = mfm->status; + break; + + default: + break; + } +#if MFM_DEBUG > 1 + pclog("WD1003 read(%04x) = %02x\n", port, ret); +#endif + + return(ret); +} + + +static void +do_seek(mfm_t *mfm) +{ + drive_t *drive = &mfm->drives[mfm->drvsel]; + +#if MFM_DEBUG + pclog("WD1003(%d) seek(%d) max=%d\n", + mfm->drvsel,mfm->cylinder,drive->tracks); +#endif + if (mfm->cylinder < drive->tracks) + drive->curcyl = mfm->cylinder; + else + drive->curcyl = drive->tracks-1; +} + + +static void +do_callback(void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + drive_t *drive = &mfm->drives[mfm->drvsel]; + off64_t addr; + + mfm->callback = 0LL; + if (mfm->reset) { +#if MFM_DEBUG + pclog("WD1003(%d) reset\n", mfm->drvsel); +#endif + mfm->status = STAT_READY|STAT_DSC; + mfm->error = 1; + mfm->secount = 1; + mfm->sector = 1; + mfm->head = 0; + mfm->cylinder = 0; + + drive->steprate = 0x0f; /* default steprate */ + drive->cfg_spt = 0; /* need new parameters */ + + mfm->reset = 0; + + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); + + return; + } + + switch (mfm->command) { + case CMD_SEEK: +#if MFM_DEBUG + pclog("WD1003(%d) seek, step=%d\n", + mfm->drvsel, drive->steprate); +#endif + do_seek(mfm); + mfm->status = STAT_READY|STAT_DSC; + irq_raise(mfm); + break; + + case CMD_READ: +#if MFM_DEBUG + pclog("WD1003(%d) read(%d,%d,%d)\n", + mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); +#endif + do_seek(mfm); + if (get_sector(mfm, &addr)) { + mfm->error = ERR_ID_NOT_FOUND; + mfm->status = STAT_READY|STAT_DSC|STAT_ERR; + irq_raise(mfm); + break; + } + + hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *)mfm->buffer); + + mfm->pos = 0; + mfm->status = STAT_DRQ|STAT_READY|STAT_DSC; + irq_raise(mfm); + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); + break; + + case CMD_WRITE: +#if MFM_DEBUG + pclog("WD1003(%d) write(%d,%d,%d)\n", + mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); +#endif + do_seek(mfm); + if (get_sector(mfm, &addr)) { + mfm->error = ERR_ID_NOT_FOUND; + mfm->status = STAT_READY|STAT_DSC|STAT_ERR; + irq_raise(mfm); + break; + } + + hdd_image_write(drive->hdd_num, addr, 1,(uint8_t *)mfm->buffer); + + mfm->status = STAT_READY|STAT_DSC; + mfm->secount = (mfm->secount - 1) & 0xff; + if (mfm->secount) { + /* More sectors to do.. */ + mfm->status |= STAT_DRQ; + mfm->pos = 0; + next_sector(mfm); + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); + } else { + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); + } + irq_raise(mfm); + break; + + case CMD_VERIFY: +#if MFM_DEBUG + pclog("WD1003(%d) verify(%d,%d,%d)\n", + mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); +#endif + do_seek(mfm); + mfm->pos = 0; + mfm->status = STAT_READY|STAT_DSC; + irq_raise(mfm); + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); + break; + + case CMD_FORMAT: +#if MFM_DEBUG + pclog("WD1003(%d) format(%d,%d)\n", + mfm->drvsel, mfm->cylinder, mfm->head); +#endif + do_seek(mfm); + if (get_sector(mfm, &addr)) { + mfm->error = ERR_ID_NOT_FOUND; + mfm->status = STAT_READY|STAT_DSC|STAT_ERR; + irq_raise(mfm); + break; + } + + hdd_image_zero(drive->hdd_num, addr, mfm->secount); + + mfm->status = STAT_READY|STAT_DSC; + irq_raise(mfm); + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); + break; + + case CMD_DIAGNOSE: +#if MFM_DEBUG + pclog("WD1003(%d) diag\n", mfm->drvsel); +#endif + drive->steprate = 0x0f; + mfm->error = 1; + mfm->status = STAT_READY|STAT_DSC; + irq_raise(mfm); + break; + + default: + pclog("WD1003(%d) callback on unknown command %02x\n", + mfm->drvsel, mfm->command); + mfm->status = STAT_READY|STAT_ERR|STAT_DSC; + mfm->error = ERR_ABRT; + irq_raise(mfm); + break; + } +} + + +static void +loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn) +{ + drive_t *drive = &mfm->drives[c]; + + if (! hdd_image_load(d)) { + drive->present = 0; + + return; + } + + drive->spt = hdd[d].spt; + drive->hpc = hdd[d].hpc; + drive->tracks = hdd[d].tracks; + drive->hdd_num = d; + drive->present = 1; +} + + +static void * +mfm_init(device_t *info) +{ + mfm_t *mfm; + int c, d; + + pclog("WD1003: ISA MFM/RLL Fixed Disk Adapter initializing ...\n"); + mfm = malloc(sizeof(mfm_t)); + memset(mfm, 0x00, sizeof(mfm_t)); + + c = 0; + for (d=0; d= MFM_NUM) break; + } + } + + mfm->status = STAT_READY|STAT_DSC; /* drive is ready */ + mfm->error = 1; /* no errors */ + + io_sethandler(0x01f0, 1, + mfm_read, mfm_readw, NULL, mfm_write, mfm_writew, NULL, mfm); + io_sethandler(0x01f1, 7, + mfm_read, NULL, NULL, mfm_write, NULL, NULL, mfm); + io_sethandler(0x03f6, 1, + NULL, NULL, NULL, mfm_write, NULL, NULL, mfm); + + timer_add(do_callback, &mfm->callback, &mfm->callback, mfm); + + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); + + return(mfm); +} + + +static void +mfm_close(void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + int d; + + for (d=0; d<2; d++) { + drive_t *drive = &mfm->drives[d]; + + hdd_image_close(drive->hdd_num); + } + + free(mfm); + + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); +} + + +device_t mfm_at_wd1003_device = { + "WD1003 AT MFM/RLL Controller", + DEVICE_ISA | DEVICE_AT, + 0, + mfm_init, mfm_close, NULL, + NULL, NULL, NULL, NULL, NULL +}; diff --git a/src/disk/hdc_mfm_xt.c b/src/disk/hdc_mfm_xt.c new file mode 100644 index 000000000..0ff2c652a --- /dev/null +++ b/src/disk/hdc_mfm_xt.c @@ -0,0 +1,921 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Driver for the IBM PC-XT Fixed Disk controller. + * + * The original controller shipped by IBM was made by Xebec, and + * several variations had been made: + * + * #1 Original, single drive (ST412), 10MB, 2 heads. + * #2 Update, single drive (ST412) but with option for a + * switch block that can be used to 'set' the actual + * drive type. Four switches are define, where switches + * 1 and 2 define drive0, and switches 3 and 4 drive1. + * + * 0 ON ON 306 2 0 + * 1 ON OFF 375 8 0 + * 2 OFF ON 306 6 256 + * 3 OFF OFF 306 4 0 + * + * The latter option is the default, in use on boards + * without the switch block option. + * + * #3 Another updated board, mostly to accomodate the new + * 20MB disk now being shipped. The controller can have + * up to 2 drives, the type of which is set using the + * switch block: + * + * SW1 SW2 CYLS HD SPT WPC + * 0 ON ON 306 4 17 0 + * 1 ON OFF 612 4 17 0 (type 16) + * 2 OFF ON 615 4 17 300 (Seagate ST-225, 2) + * 3 OFF OFF 306 8 17 128 (IBM WD25, 13) + * + * Examples of #3 are IBM/Xebec, WD10004A-WX1 and ST11R. + * + * Since all controllers (including the ones made by DTC) use + * (mostly) the same API, we keep them all in this module. + * + * Version: @(#)hdd_mfm_xt.c 1.0.9 2017/10/11 + * + * Authors: Sarah Walker, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2017 Fred N. van Kempen. + */ +#define __USE_LARGEFILE64 +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../device.h" +#include "../dma.h" +#include "../io.h" +#include "../mem.h" +#include "../pic.h" +#include "../rom.h" +#include "../timer.h" +#include "../ui.h" +#include "hdc.h" +#include "hdd.h" + + +#define MFM_TIME (2000LL*TIMER_USEC) +#define XEBEC_BIOS_FILE L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin" +#define DTC_BIOS_FILE L"roms/hdd/mfm_xebec/dtc_cxd21a.bin" + + +enum { + STATE_IDLE, + STATE_RECEIVE_COMMAND, + STATE_START_COMMAND, + STATE_RECEIVE_DATA, + STATE_RECEIVED_DATA, + STATE_SEND_DATA, + STATE_SENT_DATA, + STATE_COMPLETION_BYTE, + STATE_DUNNO +}; + + +typedef struct { + int spt, hpc; + int tracks; + int cfg_spt; + int cfg_hpc; + int cfg_cyl; + int current_cylinder; + int present; + int hdd_num; +} drive_t; + +typedef struct { + rom_t bios_rom; + int64_t callback; + int state; + uint8_t status; + uint8_t command[6]; + int command_pos; + uint8_t data[512]; + int data_pos, data_len; + uint8_t sector_buf[512]; + uint8_t irq_dma_mask; + uint8_t completion_byte; + uint8_t error; + int drive_sel; + drive_t drives[2]; + int sector, head, cylinder; + int sector_count; + uint8_t switches; +} mfm_t; + +#define STAT_IRQ 0x20 +#define STAT_DRQ 0x10 +#define STAT_BSY 0x08 +#define STAT_CD 0x04 +#define STAT_IO 0x02 +#define STAT_REQ 0x01 + +#define IRQ_ENA 0x02 +#define DMA_ENA 0x01 + +#define CMD_TEST_DRIVE_READY 0x00 +#define CMD_RECALIBRATE 0x01 +#define CMD_READ_STATUS 0x03 +#define CMD_VERIFY_SECTORS 0x05 +#define CMD_FORMAT_TRACK 0x06 +#define CMD_READ_SECTORS 0x08 +#define CMD_WRITE_SECTORS 0x0a +#define CMD_SEEK 0x0b +#define CMD_INIT_DRIVE_PARAMS 0x0c +#define CMD_WRITE_SECTOR_BUFFER 0x0f +#define CMD_BUFFER_DIAGNOSTIC 0xe0 +#define CMD_CONTROLLER_DIAGNOSTIC 0xe4 +#define CMD_DTC_GET_DRIVE_PARAMS 0xfb +#define CMD_DTC_SET_STEP_RATE 0xfc +#define CMD_DTC_SET_GEOMETRY 0xfe +#define CMD_DTC_GET_GEOMETRY 0xff + +#define ERR_NOT_READY 0x04 +#define ERR_SEEK_ERROR 0x15 +#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21 + + +static uint8_t +mfm_read(uint16_t port, void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + uint8_t temp = 0xff; + + switch (port) { + case 0x320: /*Read data*/ + mfm->status &= ~STAT_IRQ; + switch (mfm->state) { + case STATE_COMPLETION_BYTE: + if ((mfm->status & 0xf) != (STAT_CD | STAT_IO | STAT_REQ | STAT_BSY)) + fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", mfm->status); + + temp = mfm->completion_byte; + mfm->status = 0; + mfm->state = STATE_IDLE; + break; + + case STATE_SEND_DATA: + if ((mfm->status & 0xf) != (STAT_IO | STAT_REQ | STAT_BSY)) + fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", mfm->status); + if (mfm->data_pos >= mfm->data_len) + fatal("Data write with full data!\n"); + temp = mfm->data[mfm->data_pos++]; + if (mfm->data_pos == mfm->data_len) { + mfm->status = STAT_BSY; + mfm->state = STATE_SENT_DATA; + mfm->callback = MFM_TIME; + } + break; + + default: + fatal("Read data register - %i, %02x\n", mfm->state, mfm->status); + } + break; + + case 0x321: /*Read status*/ + temp = mfm->status; + break; + + case 0x322: /*Read option jumpers*/ + temp = mfm->switches; + break; + } + + return(temp); +} + + +static void +mfm_write(uint16_t port, uint8_t val, void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + + switch (port) { + case 0x320: /*Write data*/ + switch (mfm->state) { + case STATE_RECEIVE_COMMAND: + if ((mfm->status & 0xf) != (STAT_BSY | STAT_CD | STAT_REQ)) + fatal("Bad write data state - STATE_START_COMMAND, status=%02x\n", mfm->status); + if (mfm->command_pos >= 6) + fatal("Command write with full command!\n"); + /*Command data*/ + mfm->command[mfm->command_pos++] = val; + if (mfm->command_pos == 6) { + mfm->status = STAT_BSY; + mfm->state = STATE_START_COMMAND; + mfm->callback = MFM_TIME; + } + break; + + case STATE_RECEIVE_DATA: + if ((mfm->status & 0xf) != (STAT_BSY | STAT_REQ)) + fatal("Bad write data state - STATE_RECEIVE_DATA, status=%02x\n", mfm->status); + if (mfm->data_pos >= mfm->data_len) + fatal("Data write with full data!\n"); + /*Command data*/ + mfm->data[mfm->data_pos++] = val; + if (mfm->data_pos == mfm->data_len) { + mfm->status = STAT_BSY; + mfm->state = STATE_RECEIVED_DATA; + mfm->callback = MFM_TIME; + } + break; + + default: + fatal("Write data unknown state - %i %02x\n", mfm->state, mfm->status); + } + break; + + case 0x321: /*Controller reset*/ + mfm->status = 0; + break; + + case 0x322: /*Generate controller-select-pulse*/ + mfm->status = STAT_BSY | STAT_CD | STAT_REQ; + mfm->command_pos = 0; + mfm->state = STATE_RECEIVE_COMMAND; + break; + + case 0x323: /*DMA/IRQ mask register*/ + mfm->irq_dma_mask = val; + break; + } +} + + +static void mfm_complete(mfm_t *mfm) +{ + mfm->status = STAT_REQ | STAT_CD | STAT_IO | STAT_BSY; + mfm->state = STATE_COMPLETION_BYTE; + + if (mfm->irq_dma_mask & IRQ_ENA) { + mfm->status |= STAT_IRQ; + picint(1 << 5); + } +} + + +static void +mfm_error(mfm_t *mfm, uint8_t error) +{ + mfm->completion_byte |= 0x02; + mfm->error = error; + + pclog("mfm_error - %02x\n", mfm->error); +} + + +static int +get_sector(mfm_t *mfm, off64_t *addr) +{ + drive_t *drive = &mfm->drives[mfm->drive_sel]; + int heads = drive->cfg_hpc; + + if (drive->current_cylinder != mfm->cylinder) { + pclog("mfm_get_sector: wrong cylinder\n"); + mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS; + return(1); + } + if (mfm->head > heads) { + pclog("mfm_get_sector: past end of configured heads\n"); + mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS; + return(1); + } + if (mfm->head > drive->hpc) { + pclog("mfm_get_sector: past end of heads\n"); + mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS; + return(1); + } + if (mfm->sector >= 17) { + pclog("mfm_get_sector: past end of sectors\n"); + mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS; + return(1); + } + + *addr = ((((off64_t) mfm->cylinder * heads) + mfm->head) * + 17) + mfm->sector; + + return(0); +} + + +static void +next_sector(mfm_t *mfm) +{ + drive_t *drive = &mfm->drives[mfm->drive_sel]; + + mfm->sector++; + if (mfm->sector >= 17) { + mfm->sector = 0; + mfm->head++; + if (mfm->head >= drive->cfg_hpc) { + mfm->head = 0; + mfm->cylinder++; + drive->current_cylinder++; + if (drive->current_cylinder >= drive->cfg_cyl) + drive->current_cylinder = drive->cfg_cyl-1; + } + } +} + + +static void +mfm_callback(void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + drive_t *drive; + off64_t addr; + + mfm->callback = 0LL; + + mfm->drive_sel = (mfm->command[1] & 0x20) ? 1 : 0; + mfm->completion_byte = mfm->drive_sel & 0x20; + drive = &mfm->drives[mfm->drive_sel]; + + switch (mfm->command[0]) { + case CMD_TEST_DRIVE_READY: + if (!drive->present) + mfm_error(mfm, ERR_NOT_READY); + mfm_complete(mfm); + break; + + case CMD_RECALIBRATE: + if (!drive->present) + mfm_error(mfm, ERR_NOT_READY); + else { + mfm->cylinder = 0; + drive->current_cylinder = 0; + } + mfm_complete(mfm); + break; + + case CMD_READ_STATUS: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->state = STATE_SEND_DATA; + mfm->data_pos = 0; + mfm->data_len = 4; + mfm->status = STAT_BSY | STAT_IO | STAT_REQ; + mfm->data[0] = mfm->error; + mfm->data[1] = mfm->drive_sel ? 0x20 : 0; + mfm->data[2] = mfm->data[3] = 0; + mfm->error = 0; + break; + + case STATE_SENT_DATA: + mfm_complete(mfm); + break; + } + break; + + case CMD_VERIFY_SECTORS: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2); + drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder; + mfm->head = mfm->command[1] & 0x1f; + mfm->sector = mfm->command[2] & 0x1f; + mfm->sector_count = mfm->command[4]; + do { + if (get_sector(mfm, &addr)) { + pclog("get_sector failed\n"); + mfm_error(mfm, mfm->error); + mfm_complete(mfm); + return; + } + + next_sector(mfm); + + mfm->sector_count = (mfm->sector_count-1) & 0xff; + } while (mfm->sector_count); + + mfm_complete(mfm); + + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + break; + + default: + fatal("CMD_VERIFY_SECTORS: bad state %i\n", mfm->state); + } + break; + + case CMD_FORMAT_TRACK: + mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2); + drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder; + mfm->head = mfm->command[1] & 0x1f; + + if (get_sector(mfm, &addr)) { + pclog("get_sector failed\n"); + mfm_error(mfm, mfm->error); + mfm_complete(mfm); + return; + } + + hdd_image_zero(drive->hdd_num, addr, 17); + + mfm_complete(mfm); + break; + + case CMD_READ_SECTORS: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2); + drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder; + mfm->head = mfm->command[1] & 0x1f; + mfm->sector = mfm->command[2] & 0x1f; + mfm->sector_count = mfm->command[4]; + mfm->state = STATE_SEND_DATA; + mfm->data_pos = 0; + mfm->data_len = 512; + + if (get_sector(mfm, &addr)) { + mfm_error(mfm, mfm->error); + mfm_complete(mfm); + return; + } + + hdd_image_read(drive->hdd_num, addr, 1, + (uint8_t *) mfm->sector_buf); + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); + + if (mfm->irq_dma_mask & DMA_ENA) + mfm->callback = MFM_TIME; + else { + mfm->status = STAT_BSY | STAT_IO | STAT_REQ; + memcpy(mfm->data, mfm->sector_buf, 512); + } + break; + + case STATE_SEND_DATA: + mfm->status = STAT_BSY; + if (mfm->irq_dma_mask & DMA_ENA) { + for (; mfm->data_pos < 512; mfm->data_pos++) { + int val = dma_channel_write(3, mfm->sector_buf[mfm->data_pos]); + + if (val == DMA_NODATA) { + pclog("CMD_READ_SECTORS out of data!\n"); + mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; + mfm->callback = MFM_TIME; + return; + } + } + mfm->state = STATE_SENT_DATA; + mfm->callback = MFM_TIME; + } else + fatal("Read sectors no DMA! - shouldn't get here\n"); + break; + + case STATE_SENT_DATA: + next_sector(mfm); + + mfm->data_pos = 0; + + mfm->sector_count = (mfm->sector_count-1) & 0xff; + + if (mfm->sector_count) { + if (get_sector(mfm, &addr)) { + mfm_error(mfm, mfm->error); + mfm_complete(mfm); + return; + } + + hdd_image_read(drive->hdd_num, addr, 1, + (uint8_t *) mfm->sector_buf); + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); + + mfm->state = STATE_SEND_DATA; + + if (mfm->irq_dma_mask & DMA_ENA) + mfm->callback = MFM_TIME; + else { + mfm->status = STAT_BSY | STAT_IO | STAT_REQ; + memcpy(mfm->data, mfm->sector_buf, 512); + } + } else { + mfm_complete(mfm); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + } + break; + + default: + fatal("CMD_READ_SECTORS: bad state %i\n", mfm->state); + } + break; + + case CMD_WRITE_SECTORS: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2); + drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder; + mfm->head = mfm->command[1] & 0x1f; + mfm->sector = mfm->command[2] & 0x1f; + mfm->sector_count = mfm->command[4]; + mfm->state = STATE_RECEIVE_DATA; + mfm->data_pos = 0; + mfm->data_len = 512; + if (mfm->irq_dma_mask & DMA_ENA) + mfm->callback = MFM_TIME; + else + mfm->status = STAT_BSY | STAT_REQ; + break; + + case STATE_RECEIVE_DATA: + mfm->status = STAT_BSY; + if (mfm->irq_dma_mask & DMA_ENA) { + for (; mfm->data_pos < 512; mfm->data_pos++) { + int val = dma_channel_read(3); + + if (val == DMA_NODATA) { + pclog("CMD_WRITE_SECTORS out of data!\n"); + mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; + mfm->callback = MFM_TIME; + return; + } + + mfm->sector_buf[mfm->data_pos] = val & 0xff; + } + + mfm->state = STATE_RECEIVED_DATA; + mfm->callback = MFM_TIME; + } else + fatal("Write sectors no DMA! - should never get here\n"); + break; + + case STATE_RECEIVED_DATA: + if (! (mfm->irq_dma_mask & DMA_ENA)) + memcpy(mfm->sector_buf, mfm->data, 512); + + if (get_sector(mfm, &addr)) + { + mfm_error(mfm, mfm->error); + mfm_complete(mfm); + return; + } + + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *) mfm->sector_buf); + ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); + + next_sector(mfm); + mfm->data_pos = 0; + mfm->sector_count = (mfm->sector_count-1) & 0xff; + + if (mfm->sector_count) { + mfm->state = STATE_RECEIVE_DATA; + if (mfm->irq_dma_mask & DMA_ENA) + mfm->callback = MFM_TIME; + else + mfm->status = STAT_BSY | STAT_REQ; + } else + mfm_complete(mfm); + break; + + default: + fatal("CMD_WRITE_SECTORS: bad state %i\n", mfm->state); + } + break; + + case CMD_SEEK: + if (! drive->present) + mfm_error(mfm, ERR_NOT_READY); + else { + int cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2); + + drive->current_cylinder = (cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : cylinder; + + if (cylinder != drive->current_cylinder) + mfm_error(mfm, ERR_SEEK_ERROR); + } + mfm_complete(mfm); + break; + + case CMD_INIT_DRIVE_PARAMS: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->state = STATE_RECEIVE_DATA; + mfm->data_pos = 0; + mfm->data_len = 8; + mfm->status = STAT_BSY | STAT_REQ; + break; + + case STATE_RECEIVED_DATA: + drive->cfg_cyl = mfm->data[1] | (mfm->data[0] << 8); + drive->cfg_hpc = mfm->data[2]; + pclog("Drive %i: cylinders=%i, heads=%i\n", mfm->drive_sel, drive->cfg_cyl, drive->cfg_hpc); + mfm_complete(mfm); + break; + + default: + fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", mfm->state); + } + break; + + case CMD_WRITE_SECTOR_BUFFER: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->state = STATE_RECEIVE_DATA; + mfm->data_pos = 0; + mfm->data_len = 512; + if (mfm->irq_dma_mask & DMA_ENA) + mfm->callback = MFM_TIME; + else + mfm->status = STAT_BSY | STAT_REQ; + break; + + case STATE_RECEIVE_DATA: + if (mfm->irq_dma_mask & DMA_ENA) { + mfm->status = STAT_BSY; + + for (; mfm->data_pos < 512; mfm->data_pos++) { + int val = dma_channel_read(3); + + if (val == DMA_NODATA) { + pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n"); + mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; + mfm->callback = MFM_TIME; + return; + } + + mfm->data[mfm->data_pos] = val & 0xff; + } + + mfm->state = STATE_RECEIVED_DATA; + mfm->callback = MFM_TIME; + } else + fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n"); + break; + + case STATE_RECEIVED_DATA: + memcpy(mfm->sector_buf, mfm->data, 512); + mfm_complete(mfm); + break; + + default: + fatal("CMD_WRITE_SECTOR_BUFFER bad state %i\n", mfm->state); + } + break; + + case CMD_BUFFER_DIAGNOSTIC: + case CMD_CONTROLLER_DIAGNOSTIC: + mfm_complete(mfm); + break; + + case 0xfa: + mfm_complete(mfm); + break; + + case CMD_DTC_SET_STEP_RATE: + mfm_complete(mfm); + break; + + case CMD_DTC_GET_DRIVE_PARAMS: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->state = STATE_SEND_DATA; + mfm->data_pos = 0; + mfm->data_len = 4; + mfm->status = STAT_BSY | STAT_IO | STAT_REQ; + memset(mfm->data, 0, 4); + mfm->data[0] = drive->tracks & 0xff; + mfm->data[1] = 17 | ((drive->tracks >> 2) & 0xc0); + mfm->data[2] = drive->hpc-1; + pclog("Get drive params %02x %02x %02x %i\n", mfm->data[0], mfm->data[1], mfm->data[2], drive->tracks); + break; + + case STATE_SENT_DATA: + mfm_complete(mfm); + break; + + default: + fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", mfm->state); + } + break; + + case CMD_DTC_GET_GEOMETRY: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->state = STATE_SEND_DATA; + mfm->data_pos = 0; + mfm->data_len = 16; + mfm->status = STAT_BSY | STAT_IO | STAT_REQ; + memset(mfm->data, 0, 16); + mfm->data[0x4] = drive->tracks & 0xff; + mfm->data[0x5] = (drive->tracks >> 8) & 0xff; + mfm->data[0xa] = drive->hpc; + break; + + case STATE_SENT_DATA: + mfm_complete(mfm); + break; + } + break; + + case CMD_DTC_SET_GEOMETRY: + switch (mfm->state) { + case STATE_START_COMMAND: + mfm->state = STATE_RECEIVE_DATA; + mfm->data_pos = 0; + mfm->data_len = 16; + mfm->status = STAT_BSY | STAT_REQ; + break; + + case STATE_RECEIVED_DATA: + /*Bit of a cheat here - we always report the actual geometry of the drive in use*/ + mfm_complete(mfm); + break; + } + break; + + default: + fatal("Unknown Xebec command - %02x %02x %02x %02x %02x %02x\n", + mfm->command[0], mfm->command[1], + mfm->command[2], mfm->command[3], + mfm->command[4], mfm->command[5]); + } +} + + +static void +loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn) +{ + drive_t *drive = &mfm->drives[d]; + + if (! hdd_image_load(d)) { + drive->present = 0; + return; + } + + drive->spt = hdd[c].spt; + drive->hpc = hdd[c].hpc; + drive->tracks = hdd[c].tracks; + drive->hdd_num = c; + drive->present = 1; +} + + +static struct { + int tracks, hpc; +} hd_types[4] = { + { 306, 4 }, /* Type 0 */ + { 612, 4 }, /* Type 16 */ + { 615, 4 }, /* Type 2 */ + { 306, 8 } /* Type 13 */ +}; + + +static void +mfm_set_switches(mfm_t *mfm) +{ + int c, d; + + mfm->switches = 0; + + for (d=0; d<2; d++) { + drive_t *drive = &mfm->drives[d]; + + if (! drive->present) continue; + + for (c=0; c<4; c++) { + if (drive->spt == 17 && + drive->hpc == hd_types[c].hpc && + drive->tracks == hd_types[c].tracks) { + mfm->switches |= (c << (d ? 0 : 2)); + break; + } + } + + if (c == 4) + pclog("WARNING: Drive %c: has format not supported by Fixed Disk Adapter", d ? 'D' : 'C'); + } +} + + +static void * +xebec_init(device_t *info) +{ + int i, c = 0; + + mfm_t *xebec = malloc(sizeof(mfm_t)); + memset(xebec, 0x00, sizeof(mfm_t)); + + for (i=0; i MFM_NUM) break; + } + } + + mfm_set_switches(xebec); + + rom_init(&xebec->bios_rom, XEBEC_BIOS_FILE, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + io_sethandler(0x0320, 4, + mfm_read, NULL, NULL, mfm_write, NULL, NULL, xebec); + + timer_add(mfm_callback, &xebec->callback, &xebec->callback, xebec); + + return(xebec); +} + + +static void +mfm_close(void *priv) +{ + mfm_t *mfm = (mfm_t *)priv; + int d; + + for (d=0; d<2; d++) { + drive_t *drive = &mfm->drives[d]; + + hdd_image_close(drive->hdd_num); + } + + free(mfm); +} + + +static int +xebec_available(void) +{ + return(rom_present(XEBEC_BIOS_FILE)); +} + + +device_t mfm_xt_xebec_device = { + "IBM PC Fixed Disk Adapter", + DEVICE_ISA, + 0, + xebec_init, mfm_close, NULL, + xebec_available, NULL, NULL, NULL, + NULL +}; + + +static void * +dtc5150x_init(device_t *info) +{ + int i, c = 0; + + mfm_t *dtc = malloc(sizeof(mfm_t)); + memset(dtc, 0x00, sizeof(mfm_t)); + + for (i=0; i MFM_NUM) break; + } + } + + dtc->switches = 0xff; + + dtc->drives[0].cfg_cyl = dtc->drives[0].tracks; + dtc->drives[0].cfg_hpc = dtc->drives[0].hpc; + dtc->drives[1].cfg_cyl = dtc->drives[1].tracks; + dtc->drives[1].cfg_hpc = dtc->drives[1].hpc; + + rom_init(&dtc->bios_rom, DTC_BIOS_FILE, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + io_sethandler(0x0320, 4, + mfm_read, NULL, NULL, mfm_write, NULL, NULL, dtc); + + timer_add(mfm_callback, &dtc->callback, &dtc->callback, dtc); + + return(dtc); +} + + +static int +dtc5150x_available(void) +{ + return(rom_present(DTC_BIOS_FILE)); +} + + +device_t mfm_xt_dtc5150x_device = { + "DTC 5150X", + DEVICE_ISA, + 0, + dtc5150x_init, mfm_close, NULL, + dtc5150x_available, NULL, NULL, NULL, + NULL +}; diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c new file mode 100644 index 000000000..d3e5789e1 --- /dev/null +++ b/src/disk/hdc_xtide.c @@ -0,0 +1,272 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * XT-IDE controller emulation. + * + * The XT-IDE project is intended to allow 8-bit ("XT") systems + * to use regular IDE drives. IDE is a standard based on the + * 16b PC/AT design, and so a special board (with its own BIOS) + * had to be created for this. + * + * XT-IDE is *NOT* the same as XTA, or X-IDE, which is an older + * standard where the actual MFM/RLL controller for the PC/XT + * was placed on the hard drive (hard drives where its drive + * type would end in "X" or "XT", such as the 8425XT.) This was + * more or less the original IDE, but since those systems were + * already on their way out, the newer IDE standard based on the + * PC/AT controller and 16b design became the IDE we now know. + * + * Version: @(#)hdc_xtide.c 1.0.8 2017/10/09 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "hdc.h" +#include "hdc_ide.h" + + +#define ROM_PATH_XT L"roms/hdd/xtide/ide_xt.bin" +#define ROM_PATH_AT L"roms/hdd/xtide/ide_at.bin" +#define ROM_PATH_PS2 L"roms/hdd/xtide/SIDE1V12.BIN" +#define ROM_PATH_PS2AT L"roms/hdd/xtide/ide_at_1_1_5.bin" + + +typedef struct { + uint8_t data_high; + rom_t bios_rom; +} xtide_t; + + +static void +xtide_write(uint16_t port, uint8_t val, void *priv) +{ + xtide_t *xtide = (xtide_t *)priv; + + switch (port & 0xf) { + case 0x0: + writeidew(4, val | (xtide->data_high << 8)); + return; + + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + writeide(4, (port & 0xf) | 0x1f0, val); + return; + + case 0x8: + xtide->data_high = val; + return; + + case 0xe: + writeide(4, 0x3f6, val); + return; + } +} + + +static uint8_t +xtide_read(uint16_t port, void *priv) +{ + xtide_t *xtide = (xtide_t *)priv; + uint16_t tempw = 0xffff; + + switch (port & 0xf) { + case 0x0: + tempw = readidew(4); + xtide->data_high = tempw >> 8; + break; + + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + tempw = readide(4, (port & 0xf) | 0x1f0); + break; + + case 0x8: + tempw = xtide->data_high; + break; + + case 0xe: + tempw = readide(4, 0x3f6); + break; + + default: + break; + } + + return(tempw & 0xff); +} + + +static void * +xtide_init(device_t *info) +{ + xtide_t *xtide = malloc(sizeof(xtide_t)); + + memset(xtide, 0x00, sizeof(xtide_t)); + + rom_init(&xtide->bios_rom, ROM_PATH_XT, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + ide_xtide_init(); + + io_sethandler(0x0300, 16, + xtide_read, NULL, NULL, + xtide_write, NULL, NULL, xtide); + + return(xtide); +} + + +static int +xtide_available(void) +{ + return(rom_present(ROM_PATH_XT)); +} + + +static void * +xtide_at_init(device_t *info) +{ + xtide_t *xtide = malloc(sizeof(xtide_t)); + + memset(xtide, 0x00, sizeof(xtide_t)); + + rom_init(&xtide->bios_rom, ROM_PATH_AT, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + ide_init(); + + return(xtide); +} + + +static int +xtide_at_available(void) +{ + return(rom_present(ROM_PATH_AT)); +} + + +static void * +xtide_ps2_init(device_t *info) +{ + xtide_t *xtide = malloc(sizeof(xtide_t)); + + memset(xtide, 0x00, sizeof(xtide_t)); + + rom_init(&xtide->bios_rom, ROM_PATH_PS2, + 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + ide_xtide_init(); + + io_sethandler(0x0360, 16, + xtide_read, NULL, NULL, + xtide_write, NULL, NULL, xtide); + + return(xtide); +} + + +static int +xtide_ps2_available(void) +{ + return(rom_present(ROM_PATH_PS2)); +} + + +static void * +xtide_at_ps2_init(device_t *info) +{ + xtide_t *xtide = malloc(sizeof(xtide_t)); + + memset(xtide, 0x00, sizeof(xtide_t)); + + rom_init(&xtide->bios_rom, ROM_PATH_PS2AT, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + ide_init(); + + return(xtide); +} + + +static int +xtide_at_ps2_available(void) +{ + return(rom_present(ROM_PATH_PS2AT)); +} + + +static void +xtide_close(void *priv) +{ + xtide_t *xtide = (xtide_t *)priv; + + free(xtide); +} + + +device_t xtide_device = { + "XTIDE", + DEVICE_ISA, + 0, + xtide_init, xtide_close, NULL, + xtide_available, NULL, NULL, NULL, + NULL +}; + +device_t xtide_at_device = { + "XTIDE (AT)", + DEVICE_ISA | DEVICE_AT, + 0, + xtide_at_init, xtide_close, NULL, + xtide_at_available, NULL, NULL, NULL, + NULL +}; + +device_t xtide_ps2_device = { + "XTIDE (Acculogic)", + DEVICE_ISA, + 0, + xtide_ps2_init, xtide_close, NULL, + xtide_ps2_available, NULL, NULL, NULL, + NULL +}; + +device_t xtide_at_ps2_device = { + "XTIDE (AT) (1.1.5)", + DEVICE_ISA | DEVICE_PS2, + 0, + xtide_at_ps2_init, xtide_close, NULL, + xtide_at_ps2_available, NULL, NULL, NULL, + NULL +}; diff --git a/src/disk/hdd.c b/src/disk/hdd.c new file mode 100644 index 000000000..90cb7a140 --- /dev/null +++ b/src/disk/hdd.c @@ -0,0 +1,173 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Common code to handle all sorts of hard disk images. + * + * Version: @(#)hdd.c 1.0.4 2017/10/09 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include "../ibm.h" +#include "../ui.h" +#include "hdd.h" + + +hard_disk_t hdd[HDD_NUM]; + + +int +hdd_init(void) +{ + /* Clear all global data. */ + memset(hdd, 0x00, sizeof(hdd)); + + return(0); +} + + +int +hdd_string_to_bus(char *str, int cdrom) +{ + if (! strcmp(str, "none")) + return(HDD_BUS_DISABLED); + + if (! strcmp(str, "mfm")) { + if (cdrom) { +no_cdrom: + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4114); + return(0); + } + + return(HDD_BUS_MFM); + } + + /* FIXME: delete 'rll' in a year or so.. --FvK */ + if (!strcmp(str, "esdi") || !strcmp(str, "rll")) { + if (cdrom) goto no_cdrom; + + return(HDD_BUS_ESDI); + } + + if (! strcmp(str, "ide_pio_only")) + return(HDD_BUS_IDE_PIO_ONLY); + + if (! strcmp(str, "ide")) + return(HDD_BUS_IDE_PIO_ONLY); + + if (! strcmp(str, "atapi_pio_only")) + return(HDD_BUS_IDE_PIO_ONLY); + + if (! strcmp(str, "atapi")) + return(HDD_BUS_IDE_PIO_ONLY); + + if (! strcmp(str, "eide")) + return(HDD_BUS_IDE_PIO_ONLY); + + if (! strcmp(str, "xtide")) + return(HDD_BUS_XTIDE); + + if (! strcmp(str, "atide")) + return(HDD_BUS_IDE_PIO_ONLY); + + if (! strcmp(str, "ide_pio_and_dma")) + return(HDD_BUS_IDE_PIO_AND_DMA); + + if (! strcmp(str, "atapi_pio_and_dma")) + return(HDD_BUS_IDE_PIO_AND_DMA); + + if (! strcmp(str, "scsi")) + return(HDD_BUS_SCSI); + + if (! strcmp(str, "removable")) { + if (cdrom) goto no_cdrom; + + return(HDD_BUS_SCSI_REMOVABLE); + } + + if (! strcmp(str, "scsi_removable")) { + if (cdrom) goto no_cdrom; + + return(HDD_BUS_SCSI_REMOVABLE); + } + + if (! strcmp(str, "removable_scsi")) { + if (cdrom) goto no_cdrom; + + return(HDD_BUS_SCSI_REMOVABLE); + } + + if (! strcmp(str, "usb")) + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4110); + + return(0); +} + + +char * +hdd_bus_to_string(int bus, int cdrom) +{ + char *s = "none"; + + switch (bus) { + case HDD_BUS_DISABLED: + default: + break; + + case HDD_BUS_MFM: + s = "mfm"; + break; + + case HDD_BUS_XTIDE: + s = "xtide"; + break; + + case HDD_BUS_ESDI: + s = "esdi"; + break; + + case HDD_BUS_IDE_PIO_ONLY: + s = cdrom ? "atapi_pio_only" : "ide_pio_only"; + break; + + case HDD_BUS_IDE_PIO_AND_DMA: + s = cdrom ? "atapi_pio_and_dma" : "ide_pio_and_dma"; + break; + + case HDD_BUS_SCSI: + s = "scsi"; + break; + + case HDD_BUS_SCSI_REMOVABLE: + s = "scsi_removable"; + break; + } + + return(s); +} + + +int +hdd_is_valid(int c) +{ + if (hdd[c].bus == HDD_BUS_DISABLED) return(0); + + if ((wcslen(hdd[c].fn) == 0) && + (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE)) return(0); + + if ((hdd[c].tracks==0) || (hdd[c].hpc==0) || (hdd[c].spt==0)) return(0); + + return(1); +} diff --git a/src/disk/hdd.h b/src/disk/hdd.h new file mode 100644 index 000000000..dbb951bac --- /dev/null +++ b/src/disk/hdd.h @@ -0,0 +1,96 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for the hard disk image handler. + * + * Version: @(#)hdd.h 1.0.3 2017/10/05 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#ifndef EMU_HDD_H +# define EMU_HDD_H + + +#define HDD_NUM 30 /* total of 30 images supported */ + + +/* Hard Disk bus types. */ +enum { + HDD_BUS_DISABLED = 0, + HDD_BUS_MFM, + HDD_BUS_XTIDE, + HDD_BUS_ESDI, + HDD_BUS_IDE_PIO_ONLY, + HDD_BUS_IDE_PIO_AND_DMA, + HDD_BUS_SCSI, + HDD_BUS_SCSI_REMOVABLE, + HDD_BUS_USB +}; + + +/* Define the virtual Hard Disk. */ +typedef struct { + int8_t is_hdi; /* image type (should rename) */ + int8_t wp; /* disk has been mounted READ-ONLY */ + + uint8_t bus; + + uint8_t mfm_channel; /* should rename and/or unionize */ + uint8_t esdi_channel; + uint8_t xtide_channel; + uint8_t ide_channel; + uint8_t scsi_id; + uint8_t scsi_lun; + + uint32_t base; + + uint64_t spt, + hpc, /* physical geometry parameters */ + tracks; + + uint64_t at_spt, /* [Translation] parameters */ + at_hpc; + + FILE *f; /* current file handle to image */ + + wchar_t fn[260]; /* name of current image file */ + wchar_t prev_fn[260]; /* name of previous image file */ +} hard_disk_t; + + +extern hard_disk_t hdd[HDD_NUM]; +extern uint64_t hdd_table[128][3]; + + +extern int hdd_init(void); +extern int hdd_string_to_bus(char *str, int cdrom); +extern char *hdd_bus_to_string(int bus, int cdrom); +extern int hdd_is_valid(int c); + +extern int hdd_image_load(int id); +extern void hdd_image_seek(uint8_t id, uint32_t sector); +extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); +extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); +extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); +extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); +extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count); +extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count); +extern uint32_t hdd_image_get_last_sector(uint8_t id); +extern uint8_t hdd_image_get_type(uint8_t id); +extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt); +extern void hdd_image_unload(uint8_t id, int fn_preserve); +extern void hdd_image_close(uint8_t id); + +extern int image_is_hdi(const wchar_t *s); +extern int image_is_hdx(const wchar_t *s, int check_signature); + + +#endif /*EMU_HDD_H*/ diff --git a/src/hdd/hdd_image.c b/src/disk/hdd_image.c similarity index 74% rename from src/hdd/hdd_image.c rename to src/disk/hdd_image.c index cbd8b11ac..956a6732a 100644 --- a/src/hdd/hdd_image.c +++ b/src/disk/hdd_image.c @@ -1,15 +1,37 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Handling of hard disk image files. + * + * Version: @(#)hdd_image.c 1.0.5 2017/11/13 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016-2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE #define _GNU_SOURCE -#include -#include #include -#include #include - +#include +#include +#include +#include +#include #include "../ibm.h" -#include "hdd_ide_at.h" -#include "hdd_image.h" +#include "../plat.h" +#include "hdd.h" + typedef struct { @@ -20,11 +42,13 @@ typedef struct uint8_t loaded; } hdd_image_t; -hdd_image_t hdd_images[HDC_NUM]; + +hdd_image_t hdd_images[HDD_NUM]; static char empty_sector[512]; static char *empty_sector_1mb; + int hdd_image_do_log = 0; void hdd_image_log(const char *format, ...) @@ -41,6 +65,7 @@ void hdd_image_log(const char *format, ...) #endif } + int image_is_hdi(const wchar_t *s) { int len; @@ -52,7 +77,7 @@ int image_is_hdi(const wchar_t *s) return 0; } memcpy(ext, ws + ((len - 4) << 1), 8); - if (wcsicmp(ext, L".HDI") == 0) + if (! wcscasecmp(ext, L".HDI")) { return 1; } @@ -62,7 +87,9 @@ int image_is_hdi(const wchar_t *s) } } -int image_is_hdx(const wchar_t *s, int check_signature) + +int +image_is_hdx(const wchar_t *s, int check_signature) { int len; FILE *f; @@ -76,11 +103,11 @@ int image_is_hdx(const wchar_t *s, int check_signature) return 0; } memcpy(ext, ws + ((len - 4) << 1), 8); - if (wcsicmp(ext, L".HDX") == 0) + if (wcscasecmp(ext, L".HDX") == 0) { if (check_signature) { - f = _wfopen(s, L"rb"); + f = plat_fopen((wchar_t *)s, L"rb"); if (!f) { return 0; @@ -114,6 +141,7 @@ int image_is_hdx(const wchar_t *s, int check_signature) } } + int hdd_image_load(int id) { uint32_t sector_size = 512; @@ -123,7 +151,7 @@ int hdd_image_load(int id) uint64_t spt = 0, hpc = 0, tracks = 0; int c; uint64_t i = 0, s = 0, t = 0; - wchar_t *fn = hdc[id].fn; + wchar_t *fn = hdd[id].fn; int is_hdx[2] = { 0, 0 }; memset(empty_sector, 0, sizeof(empty_sector)); @@ -132,8 +160,11 @@ int hdd_image_load(int id) if (hdd_images[id].loaded) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; + if (hdd_images[id].file) + { + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + } hdd_images[id].loaded = 0; } @@ -144,10 +175,10 @@ int hdd_image_load(int id) if (fn[0] == '.') { hdd_image_log("File name starts with .\n"); - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - hdd_images[id].file = _wfopen(fn, L"rb+"); + hdd_images[id].file = plat_fopen(fn, L"rb+"); if (hdd_images[id].file == NULL) { /* Failed to open existing hard disk image */ @@ -155,34 +186,34 @@ int hdd_image_load(int id) { /* Failed because it does not exist, so try to create new file */ - if (hdc[id].wp) + if (hdd[id].wp) { hdd_image_log("A write-protected image must exist\n"); - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - hdd_images[id].file = _wfopen(fn, L"wb+"); + hdd_images[id].file = plat_fopen(fn, L"wb+"); if (hdd_images[id].file == NULL) { hdd_image_log("Unable to open image\n"); - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } else { if (image_is_hdi(fn)) { - full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512; + full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; hdd_images[id].base = 0x1000; fwrite(&zero, 1, 4, hdd_images[id].file); fwrite(&zero, 1, 4, hdd_images[id].file); fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file); fwrite(&full_size, 1, 4, hdd_images[id].file); fwrite(§or_size, 1, 4, hdd_images[id].file); - fwrite(&(hdc[id].spt), 1, 4, hdd_images[id].file); - fwrite(&(hdc[id].hpc), 1, 4, hdd_images[id].file); - fwrite(&(hdc[id].tracks), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); for (c = 0; c < 0x3f8; c++) { fwrite(&zero, 1, 4, hdd_images[id].file); @@ -191,14 +222,14 @@ int hdd_image_load(int id) } else if (is_hdx[0]) { - full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512; + full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; hdd_images[id].base = 0x28; fwrite(&signature, 1, 8, hdd_images[id].file); fwrite(&full_size, 1, 8, hdd_images[id].file); fwrite(§or_size, 1, 4, hdd_images[id].file); - fwrite(&(hdc[id].spt), 1, 4, hdd_images[id].file); - fwrite(&(hdc[id].hpc), 1, 4, hdd_images[id].file); - fwrite(&(hdc[id].tracks), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); fwrite(&zero, 1, 4, hdd_images[id].file); fwrite(&zero, 1, 4, hdd_images[id].file); hdd_images[id].type = 2; @@ -210,7 +241,7 @@ int hdd_image_load(int id) hdd_images[id].last_sector = 0; } - s = full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512; + s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; goto prepare_new_hard_disk; } @@ -218,7 +249,7 @@ int hdd_image_load(int id) { /* Failed for another reason */ hdd_image_log("Failed for another reason\n"); - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } } @@ -239,26 +270,26 @@ int hdd_image_load(int id) hdd_image_log("HDI: Sector size is not 512\n"); fclose(hdd_images[id].file); hdd_images[id].file = NULL; - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } fread(&spt, 1, 4, hdd_images[id].file); fread(&hpc, 1, 4, hdd_images[id].file); fread(&tracks, 1, 4, hdd_images[id].file); - if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) + if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks)) + if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) { hdd_image_log("HDI: Geometry mismatch\n"); fclose(hdd_images[id].file); hdd_images[id].file = NULL; - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } } - hdc[id].spt = spt; - hdc[id].hpc = hpc; - hdc[id].tracks = tracks; + hdd[id].spt = spt; + hdd[id].hpc = hpc; + hdd[id].tracks = tracks; hdd_images[id].type = 1; } else if (is_hdx[1]) @@ -274,33 +305,33 @@ int hdd_image_load(int id) hdd_image_log("HDX: Sector size is not 512\n"); fclose(hdd_images[id].file); hdd_images[id].file = NULL; - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } fread(&spt, 1, 4, hdd_images[id].file); fread(&hpc, 1, 4, hdd_images[id].file); fread(&tracks, 1, 4, hdd_images[id].file); - if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) + if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks)) + if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) { hdd_image_log("HDX: Geometry mismatch\n"); fclose(hdd_images[id].file); hdd_images[id].file = NULL; - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } } - hdc[id].spt = spt; - hdc[id].hpc = hpc; - hdc[id].tracks = tracks; - fread(&(hdc[id].at_spt), 1, 4, hdd_images[id].file); - fread(&(hdc[id].at_hpc), 1, 4, hdd_images[id].file); + hdd[id].spt = spt; + hdd[id].hpc = hpc; + hdd[id].tracks = tracks; + fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); + fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); hdd_images[id].type = 2; } else { - full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512; + full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; hdd_images[id].type = 0; } } @@ -339,8 +370,9 @@ prepare_new_hard_disk: hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - return 1; hdd_images[id].loaded = 1; + + return 1; } void hdd_image_seek(uint8_t id, uint32_t sector) @@ -477,17 +509,17 @@ void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt) { if (hdd_images[id].type == 2) { - hdc[id].at_hpc = hpc; - hdc[id].at_spt = spt; + hdd[id].at_hpc = hpc; + hdd[id].at_spt = spt; fseeko64(hdd_images[id].file, 0x20, SEEK_SET); - fwrite(&(hdc[id].at_spt), 1, 4, hdd_images[id].file); - fwrite(&(hdc[id].at_hpc), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); } } void hdd_image_unload(uint8_t id, int fn_preserve) { - if (wcslen(hdc[id].fn) == 0) + if (wcslen(hdd[id].fn) == 0) { return; } @@ -499,17 +531,15 @@ void hdd_image_unload(uint8_t id, int fn_preserve) fclose(hdd_images[id].file); hdd_images[id].file = NULL; } + hdd_images[id].loaded = 0; } hdd_images[id].last_sector = -1; - memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn)); + memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn)); if (fn_preserve) - { - wcscpy(hdc[id].prev_fn, hdc[id].fn); - } - - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); + wcscpy(hdd[id].prev_fn, hdd[id].fn); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); } void hdd_image_close(uint8_t id) @@ -519,4 +549,5 @@ void hdd_image_close(uint8_t id) fclose(hdd_images[id].file); hdd_images[id].file = NULL; } + hdd_images[id].loaded = 0; } diff --git a/src/disk/hdd_table.c b/src/disk/hdd_table.c new file mode 100644 index 000000000..bf61beef9 --- /dev/null +++ b/src/disk/hdd_table.c @@ -0,0 +1,177 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the IDE emulation for hard disks and ATAPI + * CD-ROM devices. + * + * Version: @(#)hdd_table.c 1.0.3 2017/09/30 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include +#include "../86box.h" +#include "../ibm.h" +#include "../io.h" +#include "../pic.h" +#include "../pci.h" +#include "../timer.h" +#include "hdd.h" + + +uint64_t hdd_table[128][3] = { + { 306, 4, 17 }, /* 0 - 7 */ + { 615, 2, 17 }, + { 306, 4, 26 }, + { 1024, 2, 17 }, + { 697, 3, 17 }, + { 306, 8, 17 }, + { 614, 4, 17 }, + { 615, 4, 17 }, + + { 670, 4, 17 }, /* 8 - 15 */ + { 697, 4, 17 }, + { 987, 3, 17 }, + { 820, 4, 17 }, + { 670, 5, 17 }, + { 697, 5, 17 }, + { 733, 5, 17 }, + { 615, 6, 17 }, + + { 462, 8, 17 }, /* 016-023 */ + { 306, 8, 26 }, + { 615, 4, 26 }, + { 1024, 4, 17 }, + { 855, 5, 17 }, + { 925, 5, 17 }, + { 932, 5, 17 }, + { 1024, 2, 40 }, + + { 809, 6, 17 }, /* 024-031 */ + { 976, 5, 17 }, + { 977, 5, 17 }, + { 698, 7, 17 }, + { 699, 7, 17 }, + { 981, 5, 17 }, + { 615, 8, 17 }, + { 989, 5, 17 }, + + { 820, 4, 26 }, /* 032-039 */ + { 1024, 5, 17 }, + { 733, 7, 17 }, + { 754, 7, 17 }, + { 733, 5, 26 }, + { 940, 6, 17 }, + { 615, 6, 26 }, + { 462, 8, 26 }, + + { 830, 7, 17 }, /* 040-047 */ + { 855, 7, 17 }, + { 751, 8, 17 }, + { 1024, 4, 26 }, + { 918, 7, 17 }, + { 925, 7, 17 }, + { 855, 5, 26 }, + { 977, 7, 17 }, + + { 987, 7, 17 }, /* 048-055 */ + { 1024, 7, 17 }, + { 823, 4, 38 }, + { 925, 8, 17 }, + { 809, 6, 26 }, + { 976, 5, 26 }, + { 977, 5, 26 }, + { 698, 7, 26 }, + + { 699, 7, 26 }, /* 056-063 */ + { 940, 8, 17 }, + { 615, 8, 26 }, + { 1024, 5, 26 }, + { 733, 7, 26 }, + { 1024, 8, 17 }, + { 823, 10, 17 }, + { 754, 11, 17 }, + + { 830, 10, 17 }, /* 064-071 */ + { 925, 9, 17 }, + { 1224, 7, 17 }, + { 940, 6, 26 }, + { 855, 7, 26 }, + { 751, 8, 26 }, + { 1024, 9, 17 }, + { 965, 10, 17 }, + + { 969, 5, 34 }, /* 072-079 */ + { 980, 10, 17 }, + { 960, 5, 35 }, + { 918, 11, 17 }, + { 1024, 10, 17 }, + { 977, 7, 26 }, + { 1024, 7, 26 }, + { 1024, 11, 17 }, + + { 940, 8, 26 }, /* 080-087 */ + { 776, 8, 33 }, + { 755, 16, 17 }, + { 1024, 12, 17 }, + { 1024, 8, 26 }, + { 823, 10, 26 }, + { 830, 10, 26 }, + { 925, 9, 26 }, + + { 960, 9, 26 }, /* 088-095 */ + { 1024, 13, 17 }, + { 1224, 11, 17 }, + { 900, 15, 17 }, + { 969, 7, 34 }, + { 917, 15, 17 }, + { 918, 15, 17 }, + { 1524, 4, 39 }, + + { 1024, 9, 26 }, /* 096-103 */ + { 1024, 14, 17 }, + { 965, 10, 26 }, + { 980, 10, 26 }, + { 1020, 15, 17 }, + { 1023, 15, 17 }, + { 1024, 15, 17 }, + { 1024, 16, 17 }, + + { 1224, 15, 17 }, /* 104-111 */ + { 755, 16, 26 }, + { 903, 8, 46 }, + { 984, 10, 34 }, + { 900, 15, 26 }, + { 917, 15, 26 }, + { 1023, 15, 26 }, + { 684, 16, 38 }, + + { 1930, 4, 62 }, /* 112-119 */ + { 967, 16, 31 }, + { 1013, 10, 63 }, + { 1218, 15, 36 }, + { 654, 16, 63 }, + { 659, 16, 63 }, + { 702, 16, 63 }, + { 1002, 13, 63 }, + + { 854, 16, 63 }, /* 119-127 */ + { 987, 16, 63 }, + { 995, 16, 63 }, + { 1024, 16, 63 }, + { 1036, 16, 63 }, + { 1120, 16, 59 }, + { 1054, 16, 63 }, + { 0, 0, 0 } +}; diff --git a/src/dma.c b/src/dma.c index ec2530ba0..f31bfe475 100644 --- a/src/dma.c +++ b/src/dma.c @@ -8,13 +8,17 @@ * * Implementation of the Intel DMA controllers. * - * Version: @(#)dma.c 1.0.2 2017/08/23 + * Version: @(#)dma.c 1.0.3 2017/09/24 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "ibm.h" #include "cpu/x86.h" #include "mem.h" diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 5a694baf7..e08d440db 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -9,27 +9,32 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.c 1.0.2 2017/09/03 + * Version: @(#)fdc.c 1.0.5 2017/10/09 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ -#include #include +#include #include +#include +#include #include "../ibm.h" #include "../io.h" +#include "../mem.h" +#include "../rom.h" #include "../dma.h" #include "../pic.h" #include "../timer.h" +#include "../ui.h" #include "floppy.h" #include "fdc.h" #include "fdd.h" -extern int motoron[FDD_NUM]; +extern int64_t motoron[FDD_NUM]; int ui_writeprot[FDD_NUM] = {0, 0, 0, 0}; @@ -101,8 +106,8 @@ typedef struct FDC int pcjr, ps1; - int watchdog_timer; - int watchdog_count; + int64_t watchdog_timer; + int64_t watchdog_count; int data_ready; int inread; @@ -147,7 +152,7 @@ typedef struct FDC uint16_t base_address; } FDC; -int floppytime; +int64_t floppytime; static FDC fdc; @@ -388,10 +393,10 @@ static void fdc_watchdog_poll(void *p) fdc->watchdog_count--; if (fdc->watchdog_count) - fdc->watchdog_timer += 1000 * TIMER_USEC; + fdc->watchdog_timer += 1000LL * TIMER_USEC; else { - fdc->watchdog_timer = 0; + fdc->watchdog_timer = 0LL; if (fdc->dor & 0x20) picint(1 << 6); } @@ -663,17 +668,17 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) { if ((fdc.dor & 0x40) && !(val & 0x40)) { - fdc.watchdog_timer = 1000 * TIMER_USEC; - fdc.watchdog_count = 1000; + fdc.watchdog_timer = 1000LL * TIMER_USEC; + fdc.watchdog_count = 1000LL; picintc(1 << 6); } if ((val & 0x80) && !(fdc.dor & 0x80)) { timer_process(); - floppytime = 128 * (1 << TIMER_SHIFT); + floppytime = 128LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); floppyint=-1; - update_status_bar_icon(SB_FLOPPY | 0, 0); + ui_sb_update_icon(SB_FLOPPY | 0, 0); fdc_reset(); } if (!fdd_get_flags(0)) @@ -703,14 +708,14 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) if ((val&4) && !(fdc.dor&4)) { timer_process(); - floppytime = 128 * (1 << TIMER_SHIFT); + floppytime = 128LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); floppyint=-1; fdc.perp &= 0xfc; for (i = 0; i < FDD_NUM; i++) { - update_status_bar_icon(SB_FLOPPY | i, 0); + ui_sb_update_icon(SB_FLOPPY | i, 0); } fdc_reset(); @@ -746,7 +751,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) if (val & 0x80) { timer_process(); - floppytime = 128 * (1 << TIMER_SHIFT); + floppytime = 128LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); floppyint=-1; fdc.perp &= 0xfc; @@ -927,7 +932,7 @@ bad_command: fdc.stat |= 0x10; floppyint=0xfc; timer_process(); - floppytime = 200 * (1 << TIMER_SHIFT); + floppytime = 200LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); break; } @@ -953,7 +958,7 @@ bad_command: fdc_log("Got all params %02X\n", fdc.command); floppyint=fdc.command&0x1F; timer_process(); - floppytime = 1024 * (1 << TIMER_SHIFT); + floppytime = 1024LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); fdc_reset_stat = 0; switch (floppyint & 0x1F) @@ -982,8 +987,8 @@ bad_command: { fdc.stat = 0x50; } - floppytime = 0; - update_status_bar_icon(SB_FLOPPY | fdc.drive, 1); + floppytime = 0LL; + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); fdc.inread = 1; break; @@ -992,7 +997,7 @@ bad_command: fdc.specify[0] = fdc.params[0]; fdc.specify[1] = fdc.params[1]; fdc.dma = (fdc.specify[1] & 1) ^ 1; - floppytime = 0; + floppytime = 0LL; break; case 0x12: @@ -1006,7 +1011,7 @@ bad_command: fdc.perp &= 0xfc; fdc.perp |= (fdc.params[0] & 0x03); } - floppytime = 0; + floppytime = 0LL; return; case 4: @@ -1026,9 +1031,9 @@ bad_command: fdc_implied_seek(); fdc.rw_track = fdc.params[1]; floppy_writesector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); - floppytime = 0; + floppytime = 0LL; fdc.written = 0; - update_status_bar_icon(SB_FLOPPY | fdc.drive, 1); + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); fdc.pos = 0; if (fdc.pcjr) fdc.stat = 0xb0; @@ -1059,9 +1064,9 @@ bad_command: fdc_implied_seek(); fdc.rw_track = fdc.params[1]; floppy_comparesector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); - floppytime = 0; + floppytime = 0LL; fdc.written = 0; - update_status_bar_icon(SB_FLOPPY | fdc.drive, 1); + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); fdc.pos = 0; if (fdc.pcjr || !fdc.dma) { @@ -1104,15 +1109,15 @@ bad_command: { fdc.stat = 0x50; } - floppytime = 0; - update_status_bar_icon(SB_FLOPPY | fdc.drive, 1); + floppytime = 0LL; + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); fdc.inread = 1; break; case 7: /*Recalibrate*/ seek_time_base = fdd_doublestep_40(real_drive(fdc.drive)) ? 10 : 5; fdc.stat = (1 << real_drive(fdc.drive)) | 0x80; - floppytime = 0; + floppytime = 0LL; drive_num = real_drive(fdc.drive); @@ -1128,10 +1133,10 @@ bad_command: fdc.st0 = 0x20 | (fdc.params[0] & 3); } fdc.pcn[fdc.params[0] & 3] = 0; - floppytime = 0; + floppytime = 0LL; floppyint=-3; timer_process(); - floppytime = 2048 * (1 << TIMER_SHIFT); + floppytime = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); break; } @@ -1140,7 +1145,7 @@ bad_command: { fdc_seek(fdc.drive, -fdc.max_track); } - floppytime = fdc.max_track * seek_time_base * TIMER_USEC; + floppytime = ((int64_t) fdc.max_track) * ((int64_t) seek_time_base) * TIMER_USEC; break; case 0x0d: /*Format*/ @@ -1160,7 +1165,7 @@ bad_command: fdc.stat = (1 << fdc.drive) | 0x80; fdc.head = (fdc.params[0] & 4) ? 1 : 0; fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); - floppytime = 0; + floppytime = 0LL; drive_num = real_drive(fdc.drive); seek_time_base = fdd_doublestep_40(drive_num) ? 10 : 5; @@ -1185,10 +1190,10 @@ bad_command: { fdc.pcn[fdc.params[0] & 3] = fdc.params[1]; } - floppytime = 0; + floppytime = 0LL; floppyint=-3; timer_process(); - floppytime = 2048 * (1 << TIMER_SHIFT); + floppytime = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); break; } @@ -1209,17 +1214,17 @@ bad_command: fdc_seek(fdc.drive, -fdc.params[1]); fdc.pcn[fdc.params[0] & 3] -= fdc.params[1]; } - floppytime = ((int) fdc.params[1]) * seek_time_base * TIMER_USEC; + floppytime = ((int64_t) fdc.params[1]) * ((int64_t) seek_time_base) * TIMER_USEC; } else { - floppytime = seek_time_base * TIMER_USEC; + floppytime = ((int64_t) seek_time_base) * TIMER_USEC; fdc.st0 = 0x20 | (fdc.params[0] & 7); - floppytime = 0; + floppytime = 0LL; floppyint=-3; timer_process(); - floppytime = 2048 * (1 << TIMER_SHIFT); + floppytime = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); break; } @@ -1232,10 +1237,10 @@ bad_command: if ((fdc.params[1] - fdc.pcn[fdc.params[0] & 3]) == 0) { fdc.st0 = 0x20 | (fdc.params[0] & 7); - floppytime = 0; + floppytime = 0LL; floppyint=-3; timer_process(); - floppytime = 2048 * (1 << TIMER_SHIFT); + floppytime = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); break; } @@ -1243,13 +1248,13 @@ bad_command: fdc_seek(fdc.drive, fdc.params[1] - fdc.pcn[fdc.params[0] & 3]); fdc.pcn[fdc.params[0] & 3] = fdc.params[1]; if (seek_time < 0) seek_time = -seek_time; - floppytime = seek_time; + floppytime = ((int64_t) seek_time); } break; case 10: /*Read sector ID*/ fdc_rate(fdc.drive); - floppytime = 0; + floppytime = 0LL; fdc.head = (fdc.params[0] & 4) ? 1 : 0; fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); if ((real_drive(fdc.drive) != 1) || fdc.drv2en) @@ -1385,7 +1390,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) /* if (floppyint==0xA) { timer_process(); - floppytime = 1024 * (1 << TIMER_SHIFT); + floppytime = 1024LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); } */ fdc.stat &= 0xf0; @@ -1462,7 +1467,7 @@ void fdc_poll_common_finish(int compare, int st5) fdc.res[9]=fdc.sector; fdc.res[10]=fdc.params[4]; fdc_log("Read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n" , fdc.res[4], fdc.res[5], fdc.res[6], fdc.res[7], fdc.res[8], fdc.res[9], fdc.res[10]); - update_status_bar_icon(SB_FLOPPY | fdc.drive, 0); + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0); paramstogo=7; } @@ -1476,7 +1481,7 @@ void fdc_poll_readwrite_finish(int compare) void fdc_no_dma_end(int compare) { - floppytime = 0; + floppytime = 0LL; fdc_poll_common_finish(compare, 0x80); } @@ -1486,7 +1491,7 @@ void fdc_callback(void *priv) int compare = 0; int drive_num = 0; int old_sector = 0; - floppytime = 0; + floppytime = 0LL; switch (floppyint) { case -3: /*End of command with interrupt*/ @@ -1508,7 +1513,7 @@ void fdc_callback(void *priv) return; case 2: /*Read track*/ - update_status_bar_icon(SB_FLOPPY | fdc.drive, 1); + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); fdc.eot[fdc.drive]--; fdc.read_track_sector.id.r++; if (!fdc.eot[fdc.drive] || fdc.tc) @@ -1544,7 +1549,7 @@ void fdc_callback(void *priv) fdc.stat = (fdc.stat & 0xf) | 0xd0; paramstogo = 1; floppyint = 0; - floppytime = 0; + floppytime = 0LL; return; case 5: /*Write data*/ case 9: /*Write deleted data*/ @@ -1668,7 +1673,7 @@ void fdc_callback(void *priv) { fdc.sector++; } - update_status_bar_icon(SB_FLOPPY | fdc.drive, 1); + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); switch (floppyint) { case 5: @@ -1723,7 +1728,7 @@ void fdc_callback(void *priv) } floppyint=-3; timer_process(); - floppytime = 2048 * (1 << TIMER_SHIFT); + floppytime = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); fdc.stat = 0x80 | (1 << fdc.drive); return; @@ -1761,7 +1766,7 @@ void fdc_callback(void *priv) paramstogo = 2; floppyint = 0; - floppytime = 0; + floppytime = 0LL; return; case 0x0d: /*Format track*/ @@ -1769,7 +1774,7 @@ void fdc_callback(void *priv) { fdc.format_state = 2; timer_process(); - floppytime = 128 * (1 << TIMER_SHIFT); + floppytime = 128LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); } else if (fdc.format_state == 2) @@ -1800,7 +1805,7 @@ void fdc_callback(void *priv) fdc.st0 = 0x20 | (fdc.params[0] & 7); floppyint=-3; timer_process(); - floppytime = 2048 * (1 << TIMER_SHIFT); + floppytime = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); fdc.stat = 0x80 | (1 << fdc.drive); return; @@ -1818,7 +1823,7 @@ void fdc_callback(void *priv) fdc.res[10] = fdc.pretrk; paramstogo = 10; floppyint=0; - floppytime = 0; + floppytime = 0LL; return; case 0x10: /*Version*/ @@ -1826,7 +1831,7 @@ void fdc_callback(void *priv) fdc.res[10] = 0x90; paramstogo=1; floppyint=0; - floppytime = 0; + floppytime = 0LL; return; case 0x13: /*Configure*/ @@ -1835,7 +1840,7 @@ void fdc_callback(void *priv) fdc.fifo = (fdc.params[1] & 0x20) ? 0 : 1; fdc.tfifo = (fdc.params[1] & 0xF); fdc.stat = 0x80; - floppytime = 0; + floppytime = 0LL; return; case 0x14: /*Unlock*/ fdc.lock = 0; @@ -1843,7 +1848,7 @@ void fdc_callback(void *priv) fdc.res[10] = 0; paramstogo=1; floppyint=0; - floppytime = 0; + floppytime = 0LL; return; case 0x94: /*Lock*/ fdc.lock = 1; @@ -1851,7 +1856,7 @@ void fdc_callback(void *priv) fdc.res[10] = 0x10; paramstogo=1; floppyint=0; - floppytime = 0; + floppytime = 0LL; return; case 0x18: /*NSC*/ @@ -1859,7 +1864,7 @@ void fdc_callback(void *priv) fdc.res[10] = 0x73; paramstogo=1; floppyint=0; - floppytime = 0; + floppytime = 0LL; return; case 0xfc: /*Invalid*/ @@ -1868,14 +1873,14 @@ void fdc_callback(void *priv) fdc.res[10] = fdc.st0; paramstogo=1; floppyint=0; - floppytime = 0; + floppytime = 0LL; return; } } void fdc_error(int st5, int st6) { - floppytime = 0; + floppytime = 0LL; fdc_int(); fdc.fintr = 0; @@ -1907,7 +1912,7 @@ void fdc_error(int st5, int st6) fdc.res[10]=0; break; } - update_status_bar_icon(SB_FLOPPY | fdc.drive, 0); + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0); paramstogo=7; } @@ -2138,7 +2143,7 @@ void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uin fdc.res[8]=side; fdc.res[9]=sector; fdc.res[10]=size; - update_status_bar_icon(SB_FLOPPY | fdc.drive, 0); + ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0); paramstogo=7; } @@ -2194,7 +2199,7 @@ void fdc_hard_reset() for (i = 0; i < FDD_NUM; i++) { - update_status_bar_icon(SB_FLOPPY | i, 0); + ui_sb_update_icon(SB_FLOPPY | i, 0); } } diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index b0cfdd2d0..10a755dc8 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -8,13 +8,17 @@ * * Implementation of the floppy drive emulation. * - * Version: @(#)fdd.c 1.0.2 2017/09/03 + * Version: @(#)fdd.c 1.0.3 2017/09/24 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "../ibm.h" #include "floppy.h" #include "fdc.h" diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index c8dd9820c..84e2c7388 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -19,9 +19,10 @@ #define STATIC_INLINE #include -#include -#include #include +#include +#include +#include /* IF UAE */ /*#include "sysconfig.h" @@ -37,7 +38,6 @@ #define VERBOSE #undef VERBOSE -#include #ifdef DEBUG static char *datalog(uae_u8 *src, int len) @@ -1608,7 +1608,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi randval = rand(); if (randval < (RAND_MAX / 2)) { if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) + if (randval <= (((3LL*RAND_MAX) / 8))) randval = (2 * randval) - (RAND_MAX /4); else randval = (4 * randval) - RAND_MAX; @@ -1617,7 +1617,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi } else { randval -= RAND_MAX / 2; if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) + if (randval <= (((3LL*RAND_MAX) / 8))) randval = (2 * randval) - (RAND_MAX /4); else randval = (4 * randval) - RAND_MAX; @@ -1643,7 +1643,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi randval = rand(); if (randval < (RAND_MAX / 2)) { if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) + if (randval <= (((3LL*RAND_MAX) / 8))) randval = (2 * randval) - (RAND_MAX /4); else randval = (4 * randval) - RAND_MAX; @@ -1652,7 +1652,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi } else { randval -= RAND_MAX / 2; if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) + if (randval <= (((3LL*RAND_MAX) / 8))) randval = (2 * randval) - (RAND_MAX /4); else randval = (4 * randval) - RAND_MAX; diff --git a/src/floppy/floppy.c b/src/floppy/floppy.c index da40cf9fb..809de0a88 100644 --- a/src/floppy/floppy.c +++ b/src/floppy/floppy.c @@ -9,18 +9,25 @@ * Generic floppy disk interface that communicates with the * other handlers. * - * Version: @(#)floppy.c 1.0.3 2017/09/12 + * Version: @(#)floppy.c 1.0.8 2017/10/12 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ -#define UNICODE -#include +#include +#include +#include +#include #include "../ibm.h" +#include "../mem.h" +#include "../rom.h" #include "../config.h" #include "../timer.h" +#include "../plat.h" +#include "../ui.h" #include "floppy.h" #include "floppy_86f.h" #include "floppy_fdi.h" @@ -36,7 +43,7 @@ extern int driveempty[4]; wchar_t floppyfns[4][512]; -int floppy_poll_time[FDD_NUM] = { 16, 16, 16, 16 }; +int64_t floppy_poll_time[FDD_NUM] = { 16LL, 16LL, 16LL, 16LL }; int floppy_track[FDD_NUM]; int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; @@ -60,7 +67,7 @@ int drive_empty[FDD_NUM] = {1, 1, 1, 1}; int floppy_changed[FDD_NUM]; int motorspin; -int motoron[FDD_NUM]; +int64_t motoron[FDD_NUM]; int fdc_indexcount = 52; @@ -130,14 +137,14 @@ void floppy_load(int drive, wchar_t *fn) if (!fn) return; p = get_extension_w(fn); if (!p) return; - f = _wfopen(fn, L"rb"); + f = plat_fopen(fn, L"rb"); if (!f) return; fseek(f, -1, SEEK_END); size = ftell(f) + 1; fclose(f); while (loaders[c].ext) { - if (!_wcsicmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) + if (!wcscasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) { driveloaders[drive] = c; memcpy(floppyfns[drive], fn, (wcslen(fn) << 1) + 2); @@ -149,11 +156,11 @@ void floppy_load(int drive, wchar_t *fn) } c++; } - pclog_w(L"Couldn't load %s %s\n",fn,p); + pclog("Couldn't load %ls %s\n",fn,p); drive_empty[drive] = 1; fdd_set_head(real_drive(drive), 0); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - update_status_bar_icon_state(drive, 1); + ui_sb_update_icon_state(drive, 1); } void floppy_close(int drive) @@ -172,7 +179,7 @@ void floppy_close(int drive) drives[drive].format = NULL; drives[drive].byteperiod = NULL; drives[drive].stop = NULL; - update_status_bar_icon_state(drive, 1); + ui_sb_update_icon_state(drive, 1); } int floppy_notfound=0; @@ -238,7 +245,7 @@ void floppy_poll(int drive) fatal("Attempting to poll floppy drive %i that is not supposed to be there\n", drive); } - floppy_poll_time[drive] += (int) floppy_real_period(drive); + floppy_poll_time[drive] += (int64_t) floppy_real_period(drive); if (drives[drive].poll) drives[drive].poll(drive); @@ -404,3 +411,18 @@ void floppy_stop(int drive) if (drives[drive].stop) drives[drive].stop(drive); } + +void floppy_general_init(void) +{ + floppy_init(); + fdi_init(); + img_init(); + d86f_init(); + td0_init(); + imd_init(); + + floppy_load(0, floppyfns[0]); + floppy_load(1, floppyfns[1]); + floppy_load(2, floppyfns[2]); + floppy_load(3, floppyfns[3]); +} diff --git a/src/floppy/floppy.h b/src/floppy/floppy.h index 0e1d93c88..28d9a47aa 100644 --- a/src/floppy/floppy.h +++ b/src/floppy/floppy.h @@ -42,13 +42,14 @@ extern DRIVE drives[FDD_NUM]; extern int curdrive; extern int floppy_time; -extern int floppy_poll_time[FDD_NUM]; +extern int64_t floppy_poll_time[FDD_NUM]; extern void floppy_load(int drive, wchar_t *fn); extern void floppy_new(int drive, char *fn); extern void floppy_close(int drive); extern void floppy_init(void); +extern void floppy_general_init(void); extern void floppy_reset(void); extern void floppy_poll(int drive); extern void floppy_poll_0(void* priv); @@ -87,7 +88,7 @@ extern int fdc_ready; extern int fdc_indexcount;*/ extern int motorspin; -extern int motoron[FDD_NUM]; +extern int64_t motoron[FDD_NUM]; extern int swwp; extern int disable_write; diff --git a/src/floppy/floppy_86f.c b/src/floppy/floppy_86f.c index 842945435..9328d7d3d 100644 --- a/src/floppy/floppy_86f.c +++ b/src/floppy/floppy_86f.c @@ -10,23 +10,26 @@ * data in the form of FM/MFM-encoded transitions) which also * forms the core of the emulator's floppy disk emulation. * - * Version: @(#)floppy_86f.c 1.0.2 2017/09/03 + * Version: @(#)floppy_86f.c 1.0.7 2017/10/12 * * Author: Miran Grca, * Copyright 2016,2017 Miran Grca. */ -#include #include #include -#include #include +#include +#include #include #include #include "../lzf/lzf.h" #include "../ibm.h" #include "../config.h" #include "../dma.h" +#include "../nvr.h" #include "../random.h" +#include "../plat.h" +#include "../ui.h" #include "floppy.h" #include "fdc.h" #include "fdd.h" @@ -3070,7 +3073,7 @@ void d86f_writeback(int drive) /* The image is compressed. */ /* Open the original, compressed file. */ - cf = _wfopen(d86f[drive].original_file_name, L"wb"); + cf = plat_fopen(d86f[drive].original_file_name, L"wb"); /* Write the header to the original file. */ fwrite(header, 1, header_size, cf); @@ -3362,10 +3365,10 @@ void d86f_load(int drive, wchar_t *fn) d86f_unregister(drive); writeprot[drive] = 0; - d86f[drive].f = _wfopen(fn, L"rb+"); + d86f[drive].f = plat_fopen(fn, L"rb+"); if (!d86f[drive].f) { - d86f[drive].f = _wfopen(fn, L"rb"); + d86f[drive].f = plat_fopen(fn, L"rb"); if (!d86f[drive].f) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -3423,7 +3426,7 @@ void d86f_load(int drive, wchar_t *fn) } fclose(d86f[drive].f); d86f[drive].f = NULL; - update_status_bar_icon_state(drive, 1); + ui_sb_update_icon_state(drive, 1); return; } else @@ -3470,13 +3473,13 @@ void d86f_load(int drive, wchar_t *fn) if (d86f[drive].is_compressed) { - memcpy(temp_file_name, drive ? nvr_concat(L"TEMP$$$1.$$$") : nvr_concat(L"TEMP$$$0.$$$"), 256); + memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 256); memcpy(d86f[drive].original_file_name, fn, (wcslen(fn) << 1) + 2); fclose(d86f[drive].f); d86f[drive].f = NULL; - d86f[drive].f = _wfopen(temp_file_name, L"wb"); + d86f[drive].f = plat_fopen(temp_file_name, L"wb"); if (!d86f[drive].f) { d86f_log("86F: Unable to create temporary decompressed file\n"); @@ -3484,7 +3487,7 @@ void d86f_load(int drive, wchar_t *fn) return; } - tf = _wfopen(fn, L"rb"); + tf = plat_fopen(fn, L"rb"); for (i = 0; i < 8; i++) { @@ -3510,12 +3513,12 @@ void d86f_load(int drive, wchar_t *fn) if (!temp) { d86f_log("86F: Error decompressing file\n"); - _wremove(temp_file_name); + plat_remove(temp_file_name); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } - d86f[drive].f = _wfopen(temp_file_name, L"rb+"); + d86f[drive].f = plat_fopen(temp_file_name, L"rb+"); } if (d86f[drive].disk_flags & 0x100) @@ -3526,7 +3529,7 @@ void d86f_load(int drive, wchar_t *fn) d86f[drive].f = NULL; if (d86f[drive].is_compressed) { - _wremove(temp_file_name); + plat_remove(temp_file_name); } memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; @@ -3540,7 +3543,7 @@ void d86f_load(int drive, wchar_t *fn) d86f[drive].f = NULL; if (d86f[drive].is_compressed) { - _wremove(temp_file_name); + plat_remove(temp_file_name); } memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; @@ -3559,11 +3562,11 @@ void d86f_load(int drive, wchar_t *fn) if (d86f[drive].is_compressed) { - d86f[drive].f = _wfopen(temp_file_name, L"rb"); + d86f[drive].f = plat_fopen(temp_file_name, L"rb"); } else { - d86f[drive].f = _wfopen(fn, L"rb"); + d86f[drive].f = plat_fopen(fn, L"rb"); } } @@ -3665,7 +3668,7 @@ void d86f_close(int drive) { wchar_t temp_file_name[2048]; - memcpy(temp_file_name, drive ? nvr_concat(L"TEMP$$$1.$$$") : nvr_concat(L"TEMP$$$0.$$$"), 26); + memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 26); if (d86f[drive].f) { @@ -3673,5 +3676,5 @@ void d86f_close(int drive) d86f[drive].f = NULL; } if (d86f[drive].is_compressed) - _wremove(temp_file_name); + plat_remove(temp_file_name); } diff --git a/src/floppy/floppy_common.c b/src/floppy/floppy_common.c index b5f181bf5..167dc6efb 100644 --- a/src/floppy/floppy_common.c +++ b/src/floppy/floppy_common.c @@ -8,12 +8,16 @@ * * Shared code for all the floppy modules. * - * Version: @(#)floppy_common.c 1.0.1 2017/09/10 + * Version: @(#)floppy_common.c 1.0.2 2017/09/24 * * Author: Fred N. van Kempen, * Copyright 2017 Fred N. van Kempen. */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../floppy/floppy.h" #include "floppy_common.h" diff --git a/src/floppy/floppy_fdi.c b/src/floppy/floppy_fdi.c index ff33b4a2a..1f65696b5 100644 --- a/src/floppy/floppy_fdi.c +++ b/src/floppy/floppy_fdi.c @@ -9,17 +9,20 @@ * Implementation of the FDI floppy stream image format * interface to the FDI2RAW module. * - * Version: @(#)floppy_fdi.c 1.0.1 2017/09/03 + * Version: @(#)floppy_fdi.c 1.0.3 2017/10/12 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ #include #include +#include #include #include "../ibm.h" +#include "../plat.h" #include "floppy.h" #include "floppy_86f.h" #include "floppy_img.h" @@ -263,7 +266,7 @@ void fdi_load(int drive, wchar_t *fn) char header[26]; writeprot[drive] = fwriteprot[drive] = 1; - fdi[drive].f = _wfopen(fn, L"rb"); + fdi[drive].f = plat_fopen(fn, L"rb"); if (!fdi[drive].f) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); diff --git a/src/floppy/floppy_imd.c b/src/floppy/floppy_imd.c index b9058e0ff..f5de9700d 100644 --- a/src/floppy/floppy_imd.c +++ b/src/floppy/floppy_imd.c @@ -8,14 +8,18 @@ * * Implementation of the IMD floppy image format. * - * Version: @(#)floppy_imd.c 1.0.1 2017/09/03 + * Version: @(#)floppy_imd.c 1.0.3 2017/10/12 * * Author: Miran Grca, - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ -#include +#include +#include +#include +#include #include #include "../ibm.h" +#include "../plat.h" #include "floppy.h" #include "floppy_imd.h" #include "fdc.h" @@ -86,10 +90,10 @@ void imd_load(int drive, wchar_t *fn) d86f_unregister(drive); writeprot[drive] = 0; - imd[drive].f = _wfopen(fn, L"rb+"); + imd[drive].f = plat_fopen(fn, L"rb+"); if (!imd[drive].f) { - imd[drive].f = _wfopen(fn, L"rb"); + imd[drive].f = plat_fopen(fn, L"rb"); if (!imd[drive].f) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); diff --git a/src/floppy/floppy_img.c b/src/floppy/floppy_img.c index 2fb9e60e8..20f712981 100644 --- a/src/floppy/floppy_img.c +++ b/src/floppy/floppy_img.c @@ -9,17 +9,22 @@ * Implementation of the raw sector-based floppy image format, * as well as the Japanese FDI, CopyQM, and FDF formats. * - * Version: @(#)floppy_img.c 1.0.1 2017/09/03 + * Version: @(#)floppy_img.c 1.0.3 2017/10/12 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include #include #include #include "../ibm.h" #include "../config.h" +#include "../plat.h" #include "floppy.h" #include "floppy_img.h" #include "fdc.h" @@ -346,10 +351,10 @@ void img_load(int drive, wchar_t *fn) d86f_unregister(drive); writeprot[drive] = 0; - img[drive].f = _wfopen(fn, L"rb+"); + img[drive].f = plat_fopen(fn, L"rb+"); if (!img[drive].f) { - img[drive].f = _wfopen(fn, L"rb"); + img[drive].f = plat_fopen(fn, L"rb"); if (!img[drive].f) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -367,7 +372,7 @@ void img_load(int drive, wchar_t *fn) img[drive].interleave = img[drive].skew = 0; - if (_wcsicmp(ext, L"FDI") == 0) + if (! wcscasecmp(ext, L"FDI")) { /* This is a Japanese FDI image, so let's read the header */ pclog("img_load(): File is a Japanese FDI image...\n"); @@ -412,7 +417,7 @@ void img_load(int drive, wchar_t *fn) pclog("img_load(): File is a FDF image...\n"); fwriteprot[drive] = writeprot[drive] = 1; fclose(img[drive].f); - img[drive].f = _wfopen(fn, L"rb"); + img[drive].f = plat_fopen(fn, L"rb"); fdf = 1; @@ -597,7 +602,7 @@ void img_load(int drive, wchar_t *fn) pclog("img_load(): File is a CopyQM image...\n"); fwriteprot[drive] = writeprot[drive] = 1; fclose(img[drive].f); - img[drive].f = _wfopen(fn, L"rb"); + img[drive].f = plat_fopen(fn, L"rb"); fseek(img[drive].f, 0x03, SEEK_SET); fread(&bpb_bps, 1, 2, img[drive].f); diff --git a/src/floppy/floppy_json.c b/src/floppy/floppy_json.c index c36c9810b..495269799 100644 --- a/src/floppy/floppy_json.c +++ b/src/floppy/floppy_json.c @@ -8,14 +8,19 @@ * * Implementation of the PCjs JSON floppy image format. * - * Version: @(#)floppy_json.c 1.0.1 2017/09/12 + * Version: @(#)floppy_json.c 1.0.7 2017/10/14 * * Author: Fred N. van Kempen, + * * Copyright 2017 Fred N. van Kempen. */ -#include +#include +#include +#include #include +#include #include "../ibm.h" +#include "../plat.h" #include "floppy.h" #include "fdc.h" #include "fdd.h" @@ -25,7 +30,7 @@ #define NTRACKS 256 #define NSIDES 2 -#define NSECTORS 128 +#define NSECTORS 256 typedef struct { @@ -122,10 +127,6 @@ handle(json_t *img, char *name, char *str) l >>= 8; *p++ = (l & 0x000000ff); } -#if 1 - pclog("JSON: added sector (%d,%d,%d/%d) size=%d pat=%08lx\n", - sec->track,sec->side,sec->sector,img->dmf,sec->size,pat); -#endif } else if (! strcmp(name, "data")) { if (sec->data == NULL) sec->data = (uint8_t *)malloc(sec->size); @@ -135,11 +136,6 @@ handle(json_t *img, char *name, char *str) if (sp != NULL) *sp++ = '\0'; l = atol(str); -#if 1 - if (p==sec->data) - pclog("JSON: added sector (%d,%d,%d/%d) size=%d data=%08lx\n", - sec->track,sec->side,sec->sector,img->dmf,sec->size,l); -#endif *p++ = (l & 0x000000ff); l >>= 8; *p++ = (l & 0x000000ff); @@ -482,7 +478,7 @@ json_load(int drive, wchar_t *fn) memset(img, 0x00, sizeof(json_t)); /* Open the image file. */ - img->f = _wfopen(fn, L"rb"); + img->f = plat_fopen(fn, L"rb"); if (img->f == NULL) { memset(fn, 0x00, sizeof(wchar_t)); return; @@ -500,7 +496,7 @@ json_load(int drive, wchar_t *fn) return; } - pclog("JSON(%d): %S (%i tracks, %i sides, %i sectors)\n", + pclog("JSON(%d): %ls (%i tracks, %i sides, %i sectors)\n", drive, fn, img->tracks, img->sides, img->spt[0][0]); /* diff --git a/src/floppy/floppy_td0.c b/src/floppy/floppy_td0.c index c2d695ccc..0d16e3250 100644 --- a/src/floppy/floppy_td0.c +++ b/src/floppy/floppy_td0.c @@ -8,7 +8,7 @@ * * Implementation of the Teledisk floppy image format. * - * Version: @(#)floppy_td0.c 1.0.2 2017/09/-3 + * Version: @(#)floppy_td0.c 1.0.4 2017/10/12 * * Authors: Milodrag Milanovic, * Haruhiko OKUMURA, @@ -37,9 +37,13 @@ * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI * Edited and translated to English by Kenji RIKITAKE */ -#include +#include +#include +#include #include +#include #include "../ibm.h" +#include "../plat.h" #include "floppy.h" #include "floppy_td0.h" #include "fdc.h" @@ -530,7 +534,7 @@ void td0_load(int drive, wchar_t *fn) d86f_unregister(drive); writeprot[drive] = 1; - td0[drive].f = _wfopen(fn, L"rb"); + td0[drive].f = plat_fopen(fn, L"rb"); if (!td0[drive].f) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); diff --git a/src/gameport.c b/src/game/gameport.c similarity index 85% rename from src/gameport.c rename to src/game/gameport.c index 7cb0e0142..7410abdd9 100644 --- a/src/gameport.c +++ b/src/game/gameport.c @@ -1,19 +1,22 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include #include +#include #include -#include "ibm.h" -#include "cpu/cpu.h" -#include "device.h" -#include "io.h" -#include "timer.h" +#include +#include "../ibm.h" +#include "../cpu/cpu.h" +#include "../device.h" +#include "../io.h" +#include "../timer.h" #include "gameport.h" #include "joystick_ch_flightstick_pro.h" #include "joystick_standard.h" #include "joystick_sw_pad.h" #include "joystick_tm_fcs.h" -#include "plat_joystick.h" +#include "../plat_joystick.h" int joystick_type; @@ -46,52 +49,52 @@ static joystick_if_t *joystick_list[] = NULL }; -char *joystick_get_name(int joystick) +char *joystick_get_name(int64_t joystick) { if (!joystick_list[joystick]) return NULL; return joystick_list[joystick]->name; } -int joystick_get_max_joysticks(int joystick) +int64_t joystick_get_max_joysticks(int64_t joystick) { return joystick_list[joystick]->max_joysticks; } -int joystick_get_axis_count(int joystick) +int64_t joystick_get_axis_count(int64_t joystick) { return joystick_list[joystick]->axis_count; } -int joystick_get_button_count(int joystick) +int64_t joystick_get_button_count(int64_t joystick) { return joystick_list[joystick]->button_count; } -int joystick_get_pov_count(int joystick) +int64_t joystick_get_pov_count(int64_t joystick) { return joystick_list[joystick]->pov_count; } - char *joystick_get_axis_name(int joystick, int id) + char *joystick_get_axis_name(int64_t joystick, int64_t id) { return joystick_list[joystick]->axis_names[id]; } -char *joystick_get_button_name(int joystick, int id) +char *joystick_get_button_name(int64_t joystick, int64_t id) { return joystick_list[joystick]->button_names[id]; } -char *joystick_get_pov_name(int joystick, int id) +char *joystick_get_pov_name(int64_t joystick, int64_t id) { return joystick_list[joystick]->pov_names[id]; } typedef struct gameport_axis_t { - int count; - int axis_nr; + int64_t count; + int64_t axis_nr; struct gameport_t *gameport; } gameport_axis_t; @@ -107,7 +110,7 @@ typedef struct gameport_t static gameport_t *gameport_global = NULL; -static int gameport_time(int axis) +static int64_t gameport_time(int64_t axis) { if (axis == AXIS_NOT_PRESENT) return 0; @@ -161,7 +164,7 @@ void gameport_timer_over(void *p) gameport->joystick->a0_over(gameport->joystick_dat); } -void *gameport_init_common() +void *gameport_init_common(void) { gameport_t *gameport = malloc(sizeof(gameport_t)); @@ -190,7 +193,7 @@ void *gameport_init_common() return gameport; } -void gameport_update_joystick_type() +void gameport_update_joystick_type(void) { gameport_t *gameport = gameport_global; @@ -202,7 +205,7 @@ void gameport_update_joystick_type() } } -void *gameport_init() +void *gameport_init(device_t *info) { gameport_t *gameport = NULL; @@ -219,7 +222,7 @@ void *gameport_init() return gameport; } -void *gameport_201_init() +void *gameport_201_init(device_t *info) { gameport_t *gameport; @@ -255,23 +258,19 @@ void gameport_close(void *p) device_t gameport_device = { "Game port", - 0, + 0, 0, gameport_init, gameport_close, - NULL, - NULL, - NULL, + NULL, NULL, NULL, NULL, NULL }; device_t gameport_201_device = { "Game port (port 201h only)", - 0, + 0, 0, gameport_201_init, gameport_close, - NULL, - NULL, - NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/gameport.h b/src/game/gameport.h similarity index 61% rename from src/gameport.h rename to src/game/gameport.h index f81762ce1..af663b78b 100644 --- a/src/gameport.h +++ b/src/game/gameport.h @@ -30,14 +30,14 @@ extern device_t gameport_201_device; extern int joystick_type; -extern char *joystick_get_name(int joystick); -extern int joystick_get_max_joysticks(int joystick); -extern int joystick_get_axis_count(int joystick); -extern int joystick_get_button_count(int joystick); -extern int joystick_get_pov_count(int joystick); -extern char *joystick_get_axis_name(int joystick, int id); -extern char *joystick_get_button_name(int joystick, int id); -extern char *joystick_get_pov_name(int joystick, int id); +extern char *joystick_get_name(int64_t joystick); +extern int64_t joystick_get_max_joysticks(int64_t joystick); +extern int64_t joystick_get_axis_count(int64_t joystick); +extern int64_t joystick_get_button_count(int64_t joystick); +extern int64_t joystick_get_pov_count(int64_t joystick); +extern char *joystick_get_axis_name(int64_t joystick, int64_t id); +extern char *joystick_get_button_name(int64_t joystick, int64_t id); +extern char *joystick_get_pov_name(int64_t joystick, int64_t id); extern void gameport_update_joystick_type(void); diff --git a/src/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c similarity index 93% rename from src/joystick_ch_flightstick_pro.c rename to src/game/joystick_ch_flightstick_pro.c index 9697c1c6a..ffec5e7bf 100644 --- a/src/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -1,10 +1,14 @@ +#include +#include +#include #include -#include "ibm.h" -#include "device.h" -#include "timer.h" +#include +#include "../ibm.h" +#include "../device.h" +#include "../timer.h" +#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" -#include "plat_joystick.h" static void *ch_flightstick_pro_init() diff --git a/src/joystick_ch_flightstick_pro.h b/src/game/joystick_ch_flightstick_pro.h similarity index 100% rename from src/joystick_ch_flightstick_pro.h rename to src/game/joystick_ch_flightstick_pro.h diff --git a/src/joystick_standard.c b/src/game/joystick_standard.c similarity index 97% rename from src/joystick_standard.c rename to src/game/joystick_standard.c index c73260cac..329355d0e 100644 --- a/src/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -1,10 +1,14 @@ +#include +#include +#include #include -#include "ibm.h" -#include "device.h" -#include "timer.h" +#include +#include "../ibm.h" +#include "../device.h" +#include "../timer.h" +#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" -#include "plat_joystick.h" static void *joystick_standard_init() diff --git a/src/joystick_standard.h b/src/game/joystick_standard.h similarity index 100% rename from src/joystick_standard.h rename to src/game/joystick_standard.h diff --git a/src/joystick_sw_pad.c b/src/game/joystick_sw_pad.c similarity index 93% rename from src/joystick_sw_pad.c rename to src/game/joystick_sw_pad.c index d256c290f..f127d2f49 100644 --- a/src/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -19,26 +19,29 @@ - Some DOS stuff will write to 0x201 while a packet is being transferred. This seems to be ignored. */ - +#include +#include +#include #include -#include "ibm.h" -#include "device.h" -#include "timer.h" +#include +#include "../ibm.h" +#include "../device.h" +#include "../timer.h" +#include "../plat_joystick.h" #include "gameport.h" #include "joystick_sw_pad.h" -#include "plat_joystick.h" typedef struct { - int poll_time; - int poll_left; - int poll_clock; + int64_t poll_time; + int64_t poll_left; + int64_t poll_clock; uint64_t poll_data; - int poll_mode; + int64_t poll_mode; - int trigger_time; - int data_mode; + int64_t trigger_time; + int64_t data_mode; } sw_data; static void sw_timer_over(void *p) @@ -56,7 +59,7 @@ static void sw_timer_over(void *p) } if (sw->poll_left == 1 && !sw->poll_clock) - sw->poll_time += TIMER_USEC * 160; + sw->poll_time += TIMER_USEC * 160LL; else if (sw->poll_left) sw->poll_time += TIMER_USEC * 5; else @@ -222,7 +225,7 @@ static int sw_read_axis(void *p, int axis) if (!JOYSTICK_PRESENT(0)) return AXIS_NOT_PRESENT; - return 0; /*No analogue support on Sidewinder game pad*/ + return 0LL; /*No analogue support on Sidewinder game pad*/ } static void sw_a0_over(void *p) diff --git a/src/joystick_sw_pad.h b/src/game/joystick_sw_pad.h similarity index 100% rename from src/joystick_sw_pad.h rename to src/game/joystick_sw_pad.h diff --git a/src/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c similarity index 92% rename from src/joystick_tm_fcs.c rename to src/game/joystick_tm_fcs.c index 93babc162..2fcbe4920 100644 --- a/src/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -1,10 +1,14 @@ +#include +#include +#include #include -#include "ibm.h" -#include "device.h" -#include "timer.h" +#include +#include "../ibm.h" +#include "../device.h" +#include "../timer.h" +#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" -#include "plat_joystick.h" static void *tm_fcs_init(void) diff --git a/src/joystick_tm_fcs.h b/src/game/joystick_tm_fcs.h similarity index 100% rename from src/joystick_tm_fcs.h rename to src/game/joystick_tm_fcs.h diff --git a/src/hdd/hdd.c b/src/hdd/hdd.c deleted file mode 100644 index 723539dab..000000000 --- a/src/hdd/hdd.c +++ /dev/null @@ -1,111 +0,0 @@ -#include "../ibm.h" -#include "../cpu/cpu.h" -#include "../device.h" -#include "../machine/machine.h" - -#include "hdd.h" - -#include "hdd_esdi_at.h" -#include "hdd_esdi_mca.h" -#include "hdd_mfm_at.h" -#include "hdd_mfm_xebec.h" -#include "hdd_ide_xt.h" - - -char hdd_controller_name[16]; -hard_disk_t hdc[HDC_NUM]; - -static device_t null_hdd_device; -static int hdd_controller_current; - - -static struct -{ - char name[50]; - char internal_name[16]; - device_t *device; - int is_mfm; -} hdd_controllers[] = -{ - {"None", "none", &null_hdd_device, 0}, - {"[MFM] AT Fixed Disk Adapter", "mfm_at", &mfm_at_device, 1}, - {"[MFM] DTC 5150X", "dtc5150x", &dtc_5150x_device, 1}, - {"[MFM] Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1}, - {"[ESDI] IBM ESDI Fixed Disk Adapter", "esdi_mca", &hdd_esdi_device, 1}, - {"[ESDI] Western Digital WD1007V-SE1", "wd1007vse1", &wd1007vse1_device, 0}, - {"[IDE] XTIDE", "xtide", &xtide_device, 0}, - {"[IDE] XTIDE (Acculogic)", "xtide_ps2", &xtide_ps2_device, 0}, - {"[IDE] XTIDE (AT)", "xtide_at", &xtide_at_device, 0}, - {"[IDE] XTIDE (AT) (1.1.5)", "xtide_at_ps2", &xtide_at_ps2_device, 0}, - {"", "", NULL, 0} -}; - -char *hdd_controller_get_name(int hdd) -{ - return hdd_controllers[hdd].name; -} - -char *hdd_controller_get_internal_name(int hdd) -{ - return hdd_controllers[hdd].internal_name; -} - -int hdd_controller_get_flags(int hdd) -{ - return hdd_controllers[hdd].device->flags; -} - -int hdd_controller_available(int hdd) -{ - return device_available(hdd_controllers[hdd].device); -} - -int hdd_controller_current_is_mfm() -{ - return hdd_controllers[hdd_controller_current].is_mfm; -} - -void hdd_controller_init(char *internal_name) -{ - int c = 0; - - if (machines[machine].flags & MACHINE_HAS_IDE) - { - return; - } - - while (hdd_controllers[c].device) - { - if (!strcmp(internal_name, hdd_controllers[c].internal_name)) - { - hdd_controller_current = c; - if (strcmp(internal_name, "none")) - device_add(hdd_controllers[c].device); - return; - } - c++; - } -} - - -static void *null_hdd_init() -{ - return NULL; -} - -static void null_hdd_close(void *p) -{ -} - -static device_t null_hdd_device = -{ - "Null HDD controller", - 0, - null_hdd_init, - null_hdd_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; diff --git a/src/hdd/hdd.h b/src/hdd/hdd.h deleted file mode 100644 index ff42de816..000000000 --- a/src/hdd/hdd.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef EMU_HDD_H -# define EMU_HDD_H - - -extern char hdd_controller_name[16]; - - -extern char *hdd_controller_get_name(int hdd); -extern char *hdd_controller_get_internal_name(int hdd); -extern int hdd_controller_get_flags(int hdd); -extern int hdd_controller_available(int hdd); -extern int hdd_controller_current_is_mfm(void); -extern void hdd_controller_init(char *internal_name); - - -#endif /*EMU_HDD_H*/ diff --git a/src/hdd/hdd_esdi_at.c b/src/hdd/hdd_esdi_at.c deleted file mode 100644 index f637c3ae9..000000000 --- a/src/hdd/hdd_esdi_at.c +++ /dev/null @@ -1,853 +0,0 @@ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#define _GNU_SOURCE - -#include -#include -#include -#include - -#include - -#include "../ibm.h" -#include "../device.h" -#include "hdd_image.h" -#include "../io.h" -#include "../mem.h" -#include "../pic.h" -#include "../rom.h" -#include "../timer.h" - -#include "hdd_esdi_at.h" - - -#define IDE_TIME (TIMER_USEC*10) - -#define STAT_ERR 0x01 -#define STAT_INDEX 0x02 -#define STAT_CORRECTED_DATA 0x04 -#define STAT_DRQ 0x08 /* Data request */ -#define STAT_DSC 0x10 -#define STAT_SEEK_COMPLETE 0x20 -#define STAT_READY 0x40 -#define STAT_BUSY 0x80 - -#define ERR_DAM_NOT_FOUND 0x01 /*Data Address Mark not found*/ -#define ERR_TR000 0x02 /*Track 0 not found*/ -#define ERR_ABRT 0x04 /*Command aborted*/ -#define ERR_ID_NOT_FOUND 0x10 /*ID not found*/ -#define ERR_DATA_CRC 0x40 /*Data CRC error*/ -#define ERR_BAD_BLOCK 0x80 /*Bad Block detected*/ - -#define CMD_NOP 0x00 -#define CMD_RESTORE 0x10 -#define CMD_READ 0x20 -#define CMD_WRITE 0x30 -#define CMD_VERIFY 0x40 -#define CMD_FORMAT 0x50 -#define CMD_SEEK 0x70 -#define CMD_DIAGNOSE 0x90 -#define CMD_SET_PARAMETERS 0x91 -#define CMD_READ_PARAMETERS 0xec - -extern char ide_fn[4][512]; - -typedef struct esdi_drive_t -{ - int cfg_spt; - int cfg_hpc; - int current_cylinder; - int real_spt; - int real_hpc; - int real_tracks; - int present; - int hdc_num; -} esdi_drive_t; - -typedef struct esdi_t -{ - uint8_t status; - uint8_t error; - int secount,sector,cylinder,head,cylprecomp; - uint8_t command; - uint8_t fdisk; - int pos; - - int drive_sel; - int reset; - uint16_t buffer[256]; - int irqstat; - - int callback; - - esdi_drive_t drives[2]; - - rom_t bios_rom; -} esdi_t; - -uint16_t esdi_readw(uint16_t port, void *p); -void esdi_writew(uint16_t port, uint16_t val, void *p); - -static inline void esdi_irq_raise(esdi_t *esdi) -{ - if (!(esdi->fdisk&2)) - picint(1 << 14); - - esdi->irqstat=1; -} - -static inline void esdi_irq_lower(esdi_t *esdi) -{ - picintc(1 << 14); -} - -void esdi_irq_update(esdi_t *esdi) -{ - if (esdi->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(esdi->fdisk & 2)) - picint(1 << 14); -} - -/* - * Return the sector offset for the current register values - */ -int esdi_get_sector(esdi_t *esdi, off64_t *addr) -{ - esdi_drive_t *drive = &esdi->drives[esdi->drive_sel]; - int heads = drive->cfg_hpc; - int sectors = drive->cfg_spt; - - if (esdi->head > heads) - { - pclog("esdi_get_sector: past end of configured heads\n"); - return 1; - } - if (esdi->sector >= sectors+1) - { - pclog("esdi_get_sector: past end of configured sectors\n"); - return 1; - } - - if (drive->cfg_spt == drive->real_spt && drive->cfg_hpc == drive->real_hpc) - { - *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * - sectors) + (esdi->sector - 1); - } - else - { - /*When performing translation, the firmware seems to leave 1 - sector per track inaccessible (spare sector)*/ - int c, h, s; - *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * - sectors) + (esdi->sector - 1); - - s = *addr % (drive->real_spt - 1); - h = (*addr / (drive->real_spt - 1)) % drive->real_hpc; - c = (*addr / (drive->real_spt - 1)) / drive->real_hpc; - - *addr = ((((off64_t) c * drive->real_hpc) + h) * - drive->real_spt) + s; - } - - return 0; -} - -/** - * Move to the next sector using CHS addressing - */ -void esdi_next_sector(esdi_t *esdi) -{ - esdi_drive_t *drive = &esdi->drives[esdi->drive_sel]; - - esdi->sector++; - if (esdi->sector == (drive->cfg_spt + 1)) - { - esdi->sector = 1; - esdi->head++; - if (esdi->head == drive->cfg_hpc) - { - esdi->head = 0; - esdi->cylinder++; - if (drive->current_cylinder < drive->real_tracks) - drive->current_cylinder++; - } - } -} - -void esdi_write(uint16_t port, uint8_t val, void *p) -{ - esdi_t *esdi = (esdi_t *)p; - - switch (port) - { - case 0x1F0: /* Data */ - esdi_writew(port, val | (val << 8), p); - return; - - case 0x1F1: /* Write precompenstation */ - esdi->cylprecomp = val; - return; - - case 0x1F2: /* Sector count */ - esdi->secount = val; - return; - - case 0x1F3: /* Sector */ - esdi->sector = val; - return; - - case 0x1F4: /* Cylinder low */ - esdi->cylinder = (esdi->cylinder & 0xFF00) | val; - return; - - case 0x1F5: /* Cylinder high */ - esdi->cylinder = (esdi->cylinder & 0xFF) | (val << 8); - return; - - case 0x1F6: /* Drive/Head */ - esdi->head = val & 0xF; - esdi->drive_sel = (val & 0x10) ? 1 : 0; - if (esdi->drives[esdi->drive_sel].present) - esdi->status = 0; - else - esdi->status = STAT_READY | STAT_DSC; - return; - - case 0x1F7: /* Command register */ - esdi_irq_lower(esdi); - esdi->command = val; - esdi->error = 0; - - switch (val & 0xf0) - { - case CMD_RESTORE: - esdi->command &= ~0x0f; /*Mask off step rate*/ - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_SEEK: - esdi->command &= ~0x0f; /*Mask off step rate*/ - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - default: - switch (val) - { - case CMD_NOP: - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_READ: case CMD_READ+1: - case CMD_READ+2: case CMD_READ+3: - esdi->command &= ~3; - if (val & 2) - fatal("Read with ECC\n"); - case 0xa0: - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_WRITE: case CMD_WRITE+1: - case CMD_WRITE+2: case CMD_WRITE+3: - esdi->command &= ~3; - if (val & 2) - fatal("Write with ECC\n"); - esdi->status = STAT_DRQ | STAT_DSC; - esdi->pos=0; - break; - - case CMD_VERIFY: case CMD_VERIFY+1: - esdi->command &= ~1; - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 200 * IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_FORMAT: - esdi->status = STAT_DRQ; - esdi->pos=0; - break; - - case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 30*IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - case 0xe0: /*???*/ - case CMD_READ_PARAMETERS: - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - default: - pclog("Bad esdi command %02X\n", val); - case 0xe8: /*???*/ - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - } - } - break; - - case 0x3F6: /* Device control */ - if ((esdi->fdisk & 4) && !(val & 4)) - { - timer_process(); - esdi->callback = 500*IDE_TIME; - timer_update_outstanding(); - esdi->reset = 1; - esdi->status = STAT_BUSY; - } - if (val & 4) - { - /*Drive held in reset*/ - timer_process(); - esdi->callback = 0; - timer_update_outstanding(); - esdi->status = STAT_BUSY; - } - esdi->fdisk = val; - esdi_irq_update(esdi); - return; - } -} - -void esdi_writew(uint16_t port, uint16_t val, void *p) -{ - esdi_t *esdi = (esdi_t *)p; - - esdi->buffer[esdi->pos >> 1] = val; - esdi->pos += 2; - - if (esdi->pos >= 512) - { - esdi->pos = 0; - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 6*IDE_TIME; - timer_update_outstanding(); - } -} - -uint8_t esdi_read(uint16_t port, void *p) -{ - esdi_t *esdi = (esdi_t *)p; - uint8_t temp = 0xff; - - switch (port) - { - case 0x1F0: /* Data */ - temp = esdi_readw(port, esdi) & 0xff; - break; - - case 0x1F1: /* Error */ - temp = esdi->error; - break; - - case 0x1F2: /* Sector count */ - temp = (uint8_t)esdi->secount; - break; - - case 0x1F3: /* Sector */ - temp = (uint8_t)esdi->sector; - break; - - case 0x1F4: /* Cylinder low */ - temp = (uint8_t)(esdi->cylinder&0xFF); - break; - - case 0x1F5: /* Cylinder high */ - temp = (uint8_t)(esdi->cylinder>>8); - break; - - case 0x1F6: /* Drive/Head */ - temp = (uint8_t)(esdi->head | (esdi->drive_sel ? 0x10 : 0) | 0xa0); - break; - - case 0x1F7: /* Status */ - esdi_irq_lower(esdi); - temp = esdi->status; - break; - } - - return temp; -} - -uint16_t esdi_readw(uint16_t port, void *p) -{ - esdi_t *esdi = (esdi_t *)p; - uint16_t temp; - - temp = esdi->buffer[esdi->pos >> 1]; - esdi->pos += 2; - - if (esdi->pos >= 512) - { - esdi->pos=0; - esdi->status = STAT_READY | STAT_DSC; - if (esdi->command == CMD_READ || esdi->command == 0xa0) - { - esdi->secount = (esdi->secount - 1) & 0xff; - if (esdi->secount) - { - esdi_next_sector(esdi); - esdi->status = STAT_BUSY; - timer_process(); - esdi->callback = 6*IDE_TIME; - timer_update_outstanding(); - } - } - } - - return temp; -} - -void esdi_callback(void *p) -{ - esdi_t *esdi = (esdi_t *)p; - esdi_drive_t *drive = &esdi->drives[esdi->drive_sel]; - off64_t addr; - - esdi->callback = 0; - if (esdi->reset) - { - esdi->status = STAT_READY | STAT_DSC; - esdi->error = 1; - esdi->secount = 1; - esdi->sector = 1; - esdi->head = 0; - esdi->cylinder = 0; - esdi->reset = 0; - return; - } - switch (esdi->command) - { - case CMD_RESTORE: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - drive->current_cylinder = 0; - esdi->status = STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - } - break; - - case CMD_SEEK: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - esdi->status = STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - } - break; - - case CMD_READ: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - if (esdi_get_sector(esdi, &addr)) - { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY | STAT_DSC | STAT_ERR; - esdi_irq_raise(esdi); - break; - } - if (hdd_image_read_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer)) - { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY | STAT_DSC | STAT_ERR; - esdi_irq_raise(esdi); - break; - } - esdi->pos = 0; - esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1); - } - break; - - case CMD_WRITE: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - if (esdi_get_sector(esdi, &addr)) - { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY | STAT_DSC | STAT_ERR; - esdi_irq_raise(esdi); - break; - } - if (hdd_image_write_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer)) - { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY | STAT_DSC | STAT_ERR; - esdi_irq_raise(esdi); - break; - } - esdi_irq_raise(esdi); - esdi->secount = (esdi->secount - 1) & 0xff; - if (esdi->secount) - { - esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; - esdi->pos = 0; - esdi_next_sector(esdi); - } - else - esdi->status = STAT_READY | STAT_DSC; - update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1); - } - break; - - case CMD_VERIFY: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - if (esdi_get_sector(esdi, &addr)) - { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY | STAT_DSC | STAT_ERR; - esdi_irq_raise(esdi); - break; - } - if (hdd_image_read_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer)) - { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY | STAT_DSC | STAT_ERR; - esdi_irq_raise(esdi); - break; - } - update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1); - esdi_next_sector(esdi); - esdi->secount = (esdi->secount - 1) & 0xff; - if (esdi->secount) - esdi->callback = 6*IDE_TIME; - else - { - esdi->pos = 0; - esdi->status = STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - } - } - break; - - case CMD_FORMAT: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - if (esdi_get_sector(esdi, &addr)) - { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY | STAT_DSC | STAT_ERR; - esdi_irq_raise(esdi); - break; - } - if (hdd_image_zero_ex(drive->hdc_num, addr, esdi->secount)) - { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY | STAT_DSC | STAT_ERR; - esdi_irq_raise(esdi); - break; - } - esdi->status = STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1); - } - break; - - case CMD_DIAGNOSE: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - esdi->error = 1; /*No error detected*/ - esdi->status = STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - } - break; - - case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - drive->cfg_spt = esdi->secount; - drive->cfg_hpc = esdi->head+1; - pclog("Parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); - if (!esdi->secount) - fatal("secount=0\n"); - esdi->status = STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - } - break; - - case CMD_NOP: - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - break; - - case 0xe0: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - switch (esdi->cylinder >> 8) - { - case 0x31: - esdi->cylinder = drive->real_tracks; - break; - case 0x33: - esdi->cylinder = drive->real_hpc; - break; - case 0x35: - esdi->cylinder = 0x200; - break; - case 0x36: - esdi->cylinder = drive->real_spt; - break; - default: - pclog("EDSI Bad read config %02x\n", esdi->cylinder >> 8); - } - esdi->status = STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - } - break; - - case 0xa0: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - memset(esdi->buffer, 0, 512); - memset(&esdi->buffer[3], 0xff, 512-6); - esdi->pos = 0; - esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - } - break; - - case CMD_READ_PARAMETERS: - if (!drive->present) - { - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - } - else - { - memset(esdi->buffer, 0, 512); - - esdi->buffer[0] = 0x44; /* general configuration */ - esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */ - esdi->buffer[2] = 0; /* number of removable cylinders */ - esdi->buffer[3] = drive->real_hpc; /* number of heads */ - esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/sector */ - esdi->buffer[4] = 600; /* number of unformatted bytes/track */ - esdi->buffer[6] = drive->real_spt; /* number of sectors */ - esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/ - esdi->buffer[8] = 0; /* minimum bytes in postamble */ - esdi->buffer[9] = 0; /* number of words of vendor status */ - /* controller info */ - esdi->buffer[20] = 2; /* controller type */ - esdi->buffer[21] = 1; /* sector buffer size, in sectors */ - esdi->buffer[22] = 0; /* ecc bytes appended */ - esdi->buffer[27] = 'W' | ('D' << 8); - esdi->buffer[28] = '1' | ('0' << 8); - esdi->buffer[29] = '0' | ('7' << 8); - esdi->buffer[30] = 'V' | ('-' << 8); - esdi->buffer[31] = 'S' | ('E' << 8); - esdi->buffer[32] = '1'; - esdi->buffer[47] = 0; /* sectors per interrupt */ - esdi->buffer[48] = 0;/* can use double word read/write? */ - esdi->pos = 0; - esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; - esdi_irq_raise(esdi); - } - break; - - default: - pclog("ESDI Callback on unknown command %02x\n", esdi->command); - case 0xe8: - esdi->status = STAT_READY | STAT_ERR | STAT_DSC; - esdi->error = ERR_ABRT; - esdi_irq_raise(esdi); - break; - } - - update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 0); -} - -static void esdi_rom_write(uint32_t addr, uint8_t val, void *p) -{ - rom_t *rom = (rom_t *)p; - - addr &= rom->mask; - - if (addr >= 0x1f00 && addr < 0x2000) - rom->rom[addr] = val; -} - -static void loadhd(esdi_t *esdi, int hdc_num, int d, const wchar_t *fn) -{ - esdi_drive_t *drive = &esdi->drives[d]; - int ret = 0; - - ret = hdd_image_load(hdc_num); - - if (!ret) - { - drive->present = 0; - return; - } - - drive->cfg_spt = drive->real_spt = hdc[hdc_num].spt; - drive->cfg_hpc = drive->real_hpc = hdc[hdc_num].hpc; - drive->real_tracks = hdc[hdc_num].tracks; - drive->hdc_num = hdc_num; - drive->present = 1; -} - -void *wd1007vse1_init() -{ - int i = 0; - int c = 0; - - esdi_t *esdi = malloc(sizeof(esdi_t)); - memset(esdi, 0, sizeof(esdi_t)); - - esdi->drives[0].present = esdi->drives[1].present = 0; - - for (i = 0; i < HDC_NUM; i++) - { - if ((hdc[i].bus == HDD_BUS_ESDI) && (hdc[i].esdi_channel < ESDI_NUM)) - { - loadhd(esdi, i, hdc[i].esdi_channel, hdc[i].fn); - c++; - if (c >= ESDI_NUM) break; - } - } - - esdi->status = STAT_READY | STAT_DSC; - esdi->error = 1; /*No errors*/ - - rom_init(&esdi->bios_rom, L"roms/hdd/esdi_at/62-000279-061.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - mem_mapping_set_handler(&esdi->bios_rom.mapping, - rom_read, rom_readw, rom_readl, - esdi_rom_write, NULL, NULL); - - io_sethandler(0x01f0, 0x0001, esdi_read, esdi_readw, NULL, esdi_write, esdi_writew, NULL, esdi); - io_sethandler(0x01f1, 0x0007, esdi_read, NULL, NULL, esdi_write, NULL, NULL, esdi); - io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, esdi_write, NULL, NULL, esdi); - - timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi); - - return esdi; -} - -void wd1007vse1_close(void *p) -{ - esdi_t *esdi = (esdi_t *)p; - esdi_drive_t *drive; - - int d; - - esdi->drives[0].present = esdi->drives[1].present = 0; - - for (d = 0; d < 2; d++) - { - drive = &esdi->drives[d]; - - hdd_image_close(drive->hdc_num); - } - - free(esdi); -} - -static int wd1007vse1_available() -{ - return rom_present(L"roms/hdd/esdi_at/62-000279-061.bin"); -} - -device_t wd1007vse1_device = -{ - "Western Digital WD1007V-SE1 (ESDI)", - DEVICE_AT, - wd1007vse1_init, - wd1007vse1_close, - wd1007vse1_available, - NULL, - NULL, - NULL, - NULL -}; diff --git a/src/hdd/hdd_esdi_at.h b/src/hdd/hdd_esdi_at.h deleted file mode 100644 index fa66ace21..000000000 --- a/src/hdd/hdd_esdi_at.h +++ /dev/null @@ -1 +0,0 @@ -extern device_t wd1007vse1_device; diff --git a/src/hdd/hdd_esdi_mca.h b/src/hdd/hdd_esdi_mca.h deleted file mode 100644 index 4fea361bd..000000000 --- a/src/hdd/hdd_esdi_mca.h +++ /dev/null @@ -1 +0,0 @@ -extern device_t hdd_esdi_device; diff --git a/src/hdd/hdd_ide_xt.c b/src/hdd/hdd_ide_xt.c deleted file mode 100644 index 1608cff11..000000000 --- a/src/hdd/hdd_ide_xt.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * XT IDE controller emulation. - * - * Version: @(#)xtide.c 1.0.3 2017/08/24 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#include -#include "../ibm.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "hdd_ide_at.h" -#include "hdd_ide_xt.h" - - -#define XTIDE_ROM_PATH L"roms/hdd/xtide/ide_xt.bin" -#define ATIDE_ROM_PATH L"roms/hdd/xtide/ide_at.bin" - - -typedef struct xtide_t -{ - uint8_t data_high; - rom_t bios_rom; -} xtide_t; - - -static void xtide_write(uint16_t port, uint8_t val, void *p) -{ - xtide_t *xtide = (xtide_t *)p; - - switch (port & 0xf) - { - case 0x0: - writeidew(4, val | (xtide->data_high << 8)); - return; - - case 0x1: case 0x2: case 0x3: - case 0x4: case 0x5: case 0x6: case 0x7: - writeide(4, (port & 0xf) | 0x1f0, val); - return; - - case 0x8: - xtide->data_high = val; - return; - - case 0xe: - writeide(4, 0x3f6, val); - return; - } -} - - -static uint8_t xtide_read(uint16_t port, void *p) -{ - xtide_t *xtide = (xtide_t *)p; - uint16_t tempw; - - switch (port & 0xf) - { - case 0x0: - tempw = readidew(4); - xtide->data_high = tempw >> 8; - return tempw & 0xff; - - case 0x1: case 0x2: case 0x3: - case 0x4: case 0x5: case 0x6: case 0x7: - return readide(4, (port & 0xf) | 0x1f0); - - case 0x8: - return xtide->data_high; - - case 0xe: - return readide(4, 0x3f6); - - default: - return 0xff; - } -} - - -static void *xtide_init(void) -{ - xtide_t *xtide = malloc(sizeof(xtide_t)); - memset(xtide, 0, sizeof(xtide_t)); - - rom_init(&xtide->bios_rom, XTIDE_ROM_PATH, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - ide_xtide_init(); - io_sethandler(0x0300, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL, xtide); - - return xtide; -} - - -static void *xtide_at_init(void) -{ - xtide_t *xtide = malloc(sizeof(xtide_t)); - memset(xtide, 0, sizeof(xtide_t)); - - rom_init(&xtide->bios_rom, ATIDE_ROM_PATH, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - ide_init(); - - return xtide; -} - - -static void *xtide_ps2_init(void) -{ - xtide_t *xtide = malloc(sizeof(xtide_t)); - memset(xtide, 0, sizeof(xtide_t)); - - rom_init(&xtide->bios_rom, L"roms/hdd/xtide/SIDE1V12.BIN", 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - ide_xtide_init(); - io_sethandler(0x0360, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL, xtide); - - return xtide; -} - - -static void *xtide_at_ps2_init(void) -{ - xtide_t *xtide = malloc(sizeof(xtide_t)); - memset(xtide, 0, sizeof(xtide_t)); - - rom_init(&xtide->bios_rom, L"roms/hdd/xtide/ide_at_1_1_5.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - ide_init(); - - return xtide; -} - - -static void xtide_close(void *p) -{ - xtide_t *xtide = (xtide_t *)p; - - free(xtide); -} - - -static int xtide_available(void) -{ - return rom_present(L"roms/hdd/xtide/ide_xt.bin"); -} - - -static int xtide_at_available(void) -{ - return rom_present(L"roms/hdd/xtide/ide_at.bin"); -} - - -static int xtide_ps2_available(void) -{ - return rom_present(L"roms/hdd/xtide/SIDE1V12.BIN"); -} - - -static int xtide_at_ps2_available(void) -{ - return rom_present(L"roms/hdd/xtide/ide_at_1_1_5.bin"); -} - - -device_t xtide_device = -{ - "XTIDE", - 0, - xtide_init, - xtide_close, - xtide_available, - NULL, - NULL, - NULL, - NULL -}; -device_t xtide_at_device = -{ - "XTIDE (AT)", - DEVICE_AT, - xtide_at_init, - xtide_close, - xtide_at_available, - NULL, - NULL, - NULL, - NULL -}; - -device_t xtide_ps2_device = -{ - "XTIDE (Acculogic)", - 0, - xtide_ps2_init, - xtide_close, - xtide_ps2_available, - NULL, - NULL, - NULL, - NULL -}; - -device_t xtide_at_ps2_device = -{ - "XTIDE (AT) (1.1.5)", - DEVICE_PS2, - xtide_at_ps2_init, - xtide_close, - xtide_at_ps2_available, - NULL, - NULL, - NULL, - NULL -}; diff --git a/src/hdd/hdd_ide_xt.h b/src/hdd/hdd_ide_xt.h deleted file mode 100644 index 8137cbbb0..000000000 --- a/src/hdd/hdd_ide_xt.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * XT IDE controller emulation. - * - * Version: @(#)xtide.h 1.0.2 2017/08/23 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#ifndef EMU_XTIDE_H -# define EMU_XTIDE_H - - -extern device_t xtide_device; -extern device_t xtide_at_device; -extern device_t xtide_ps2_device; -extern device_t xtide_at_ps2_device; - - -#endif /*EMU_XTIDE_H*/ diff --git a/src/hdd/hdd_image.h b/src/hdd/hdd_image.h deleted file mode 100644 index d04710999..000000000 --- a/src/hdd/hdd_image.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef EMU_HDD_IMAGE_H -# define EMU_HDD_IMAGE_H - - -extern int hdd_image_load(int id); -extern void hdd_image_seek(uint8_t id, uint32_t sector); -extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); -extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); -extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); -extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); -extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count); -extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count); -extern uint32_t hdd_image_get_last_sector(uint8_t id); -extern uint8_t hdd_image_get_type(uint8_t id); -extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt); -extern void hdd_image_unload(uint8_t id, int fn_preserve); -extern void hdd_image_close(uint8_t id); - - -#endif /*EMU_HDD_IMAGE_H*/ diff --git a/src/hdd/hdd_mfm_at.c b/src/hdd/hdd_mfm_at.c deleted file mode 100644 index 90928270e..000000000 --- a/src/hdd/hdd_mfm_at.c +++ /dev/null @@ -1,610 +0,0 @@ -#include - -#include "../ibm.h" -#include "hdd_image.h" -#include "../device.h" -#include "../io.h" -#include "../pic.h" -#include "../timer.h" -#include "hdd_mfm_at.h" - - -#define IDE_TIME (TIMER_USEC*10) - -#define STAT_ERR 0x01 -#define STAT_INDEX 0x02 -#define STAT_CORRECTED_DATA 0x04 -#define STAT_DRQ 0x08 /* Data request */ -#define STAT_DSC 0x10 -#define STAT_SEEK_COMPLETE 0x20 -#define STAT_READY 0x40 -#define STAT_BUSY 0x80 - -#define ERR_DAM_NOT_FOUND 0x01 /*Data Address Mark not found*/ -#define ERR_TR000 0x02 /*Track 0 not found*/ -#define ERR_ABRT 0x04 /*Command aborted*/ -#define ERR_ID_NOT_FOUND 0x10 /*ID not found*/ -#define ERR_DATA_CRC 0x40 /*Data CRC error*/ -#define ERR_BAD_BLOCK 0x80 /*Bad Block detected*/ - -#define CMD_RESTORE 0x10 -#define CMD_READ 0x20 -#define CMD_WRITE 0x30 -#define CMD_VERIFY 0x40 -#define CMD_FORMAT 0x50 -#define CMD_SEEK 0x70 -#define CMD_DIAGNOSE 0x90 -#define CMD_SET_PARAMETERS 0x91 - -typedef struct mfm_drive_t -{ - int spt, hpc; - int tracks; - int cfg_spt; - int cfg_hpc; - int current_cylinder; - int present; - int hdc_num; -} mfm_drive_t; - -typedef struct mfm_t -{ - uint8_t status; - uint8_t error; - int secount,sector,cylinder,head,cylprecomp; - uint8_t command; - uint8_t fdisk; - int pos; - - int drive_sel; - int reset; - uint16_t buffer[256]; - int irqstat; - - int callback; - - mfm_drive_t drives[2]; -} mfm_t; - -uint16_t mfm_readw(uint16_t port, void *p); -void mfm_writew(uint16_t port, uint16_t val, void *p); - -static __inline void mfm_irq_raise(mfm_t *mfm) -{ - if (!(mfm->fdisk&2)) - picint(1 << 14); - - mfm->irqstat=1; -} - -static __inline void mfm_irq_lower(mfm_t *mfm) -{ - picintc(1 << 14); -} - -void mfm_irq_update(mfm_t *mfm) -{ - if (mfm->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(mfm->fdisk & 2)) - picint(1 << 14); -} - -/* - * Return the sector offset for the current register values - */ -static int mfm_get_sector(mfm_t *mfm, off64_t *addr) -{ - mfm_drive_t *drive = &mfm->drives[mfm->drive_sel]; - int heads = drive->cfg_hpc; - int sectors = drive->cfg_spt; - - if (drive->current_cylinder != mfm->cylinder) - { - pclog("mfm_get_sector: wrong cylinder\n"); - return 1; - } - if (mfm->head > heads) - { - pclog("mfm_get_sector: past end of configured heads\n"); - return 1; - } - if (mfm->sector >= sectors+1) - { - pclog("mfm_get_sector: past end of configured sectors\n"); - return 1; - } - if (mfm->head > drive->hpc) - { - pclog("mfm_get_sector: past end of heads\n"); - return 1; - } - if (mfm->sector >= drive->spt+1) - { - pclog("mfm_get_sector: past end of sectors\n"); - return 1; - } - - *addr = ((((off64_t) mfm->cylinder * heads) + mfm->head) * - sectors) + (mfm->sector - 1); - - return 0; -} - -/** - * Move to the next sector using CHS addressing - */ -static void mfm_next_sector(mfm_t *mfm) -{ - mfm_drive_t *drive = &mfm->drives[mfm->drive_sel]; - - mfm->sector++; - if (mfm->sector == (drive->cfg_spt + 1)) - { - mfm->sector = 1; - mfm->head++; - if (mfm->head == drive->cfg_hpc) - { - mfm->head = 0; - mfm->cylinder++; - if (drive->current_cylinder < drive->tracks) - drive->current_cylinder++; - } - } -} - -static void loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn) -{ - mfm_drive_t *drive = &mfm->drives[c]; - int ret = 0; - - ret = hdd_image_load(d); - - if (!ret) - { - drive->present = 0; - return; - } - - drive->spt = hdc[d].spt; - drive->hpc = hdc[d].hpc; - drive->tracks = hdc[d].tracks; - drive->hdc_num = d; - drive->present = 1; -} - - - -void mfm_write(uint16_t port, uint8_t val, void *p) -{ - mfm_t *mfm = (mfm_t *)p; - - switch (port) - { - case 0x1F0: /* Data */ - mfm_writew(port, val | (val << 8), p); - return; - - case 0x1F1: /* Write precompenstation */ - mfm->cylprecomp = val; - return; - - case 0x1F2: /* Sector count */ - mfm->secount = val; - return; - - case 0x1F3: /* Sector */ - mfm->sector = val; - return; - - case 0x1F4: /* Cylinder low */ - mfm->cylinder = (mfm->cylinder & 0xFF00) | val; - return; - - case 0x1F5: /* Cylinder high */ - mfm->cylinder = (mfm->cylinder & 0xFF) | (val << 8); - return; - - case 0x1F6: /* Drive/Head */ - mfm->head = val & 0xF; - mfm->drive_sel = (val & 0x10) ? 1 : 0; - if (mfm->drives[mfm->drive_sel].present) - mfm->status = STAT_READY | STAT_DSC; - else - mfm->status = 0; - return; - - case 0x1F7: /* Command register */ - if (!mfm->drives[mfm->drive_sel].present) - fatal("Command on non-present drive\n"); - - mfm_irq_lower(mfm); - mfm->command = val; - mfm->error = 0; - - switch (val & 0xf0) - { - case CMD_RESTORE: - mfm->command &= ~0x0f; /*Mask off step rate*/ - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_SEEK: - mfm->command &= ~0x0f; /*Mask off step rate*/ - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - default: - switch (val) - { - case CMD_READ: case CMD_READ+1: - case CMD_READ+2: case CMD_READ+3: - mfm->command &= ~3; - if (val & 2) - fatal("Read with ECC\n"); - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_WRITE: case CMD_WRITE+1: - case CMD_WRITE+2: case CMD_WRITE+3: - mfm->command &= ~3; - if (val & 2) - fatal("Write with ECC\n"); - mfm->status = STAT_DRQ | STAT_DSC; - mfm->pos=0; - break; - - case CMD_VERIFY: case CMD_VERIFY+1: - mfm->command &= ~1; - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 200 * IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_FORMAT: - mfm->status = STAT_DRQ | STAT_BUSY; - mfm->pos=0; - break; - - case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 30*IDE_TIME; - timer_update_outstanding(); - break; - - case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - - default: - pclog("Bad MFM command %02X\n", val); - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); - break; - } - } - break; - - case 0x3F6: /* Device control */ - if ((mfm->fdisk & 4) && !(val & 4)) - { - timer_process(); - mfm->callback = 500*IDE_TIME; - timer_update_outstanding(); - mfm->reset = 1; - mfm->status = STAT_BUSY; - } - if (val & 4) - { - /*Drive held in reset*/ - timer_process(); - mfm->callback = 0; - timer_update_outstanding(); - mfm->status = STAT_BUSY; - } - mfm->fdisk = val; - mfm_irq_update(mfm); - return; - } -} - -void mfm_writew(uint16_t port, uint16_t val, void *p) -{ - mfm_t *mfm = (mfm_t *)p; - - mfm->buffer[mfm->pos >> 1] = val; - mfm->pos += 2; - - if (mfm->pos >= 512) - { - mfm->pos = 0; - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 6*IDE_TIME; - timer_update_outstanding(); - } -} - -uint8_t mfm_read(uint16_t port, void *p) -{ - mfm_t *mfm = (mfm_t *)p; - uint8_t temp; - - switch (port) - { - case 0x1F0: /* Data */ - temp = mfm_readw(port, mfm) & 0xff; - break; - - case 0x1F1: /* Error */ - temp = mfm->error; - break; - - case 0x1F2: /* Sector count */ - temp = (uint8_t)mfm->secount; - break; - - case 0x1F3: /* Sector */ - temp = (uint8_t)mfm->sector; - break; - - case 0x1F4: /* Cylinder low */ - temp = (uint8_t)(mfm->cylinder&0xFF); - break; - - case 0x1F5: /* Cylinder high */ - temp = (uint8_t)(mfm->cylinder>>8); - break; - - case 0x1F6: /* Drive/Head */ - temp = (uint8_t)(mfm->head | (mfm->drive_sel ? 0x10 : 0) | 0xa0); - break; - - case 0x1F7: /* Status */ - mfm_irq_lower(mfm); - temp = mfm->status; - break; - - default: - temp = 0xff; - break; - } - - return temp; -} - -uint16_t mfm_readw(uint16_t port, void *p) -{ - mfm_t *mfm = (mfm_t *)p; - uint16_t temp; - - temp = mfm->buffer[mfm->pos >> 1]; - mfm->pos += 2; - - if (mfm->pos >= 512) - { - mfm->pos=0; - mfm->status = STAT_READY | STAT_DSC; - if (mfm->command == CMD_READ) - { - mfm->secount = (mfm->secount - 1) & 0xff; - if (mfm->secount) - { - mfm_next_sector(mfm); - mfm->status = STAT_BUSY; - timer_process(); - mfm->callback = 6*IDE_TIME; - timer_update_outstanding(); - } - else - { - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0); - } - } - } - - return temp; -} - -static void do_seek(mfm_t *mfm) -{ - mfm_drive_t *drive = &mfm->drives[mfm->drive_sel]; - - if (mfm->cylinder < drive->tracks) - drive->current_cylinder = mfm->cylinder; - else - drive->current_cylinder = drive->tracks-1; -} - -void mfm_callback(void *p) -{ - mfm_t *mfm = (mfm_t *)p; - mfm_drive_t *drive = &mfm->drives[mfm->drive_sel]; - off64_t addr; - - mfm->callback = 0; - if (mfm->reset) - { - mfm->status = STAT_READY | STAT_DSC; - mfm->error = 1; - mfm->secount = 1; - mfm->sector = 1; - mfm->head = 0; - mfm->cylinder = 0; - mfm->reset = 0; - return; - } - switch (mfm->command) - { - case CMD_RESTORE: - drive->current_cylinder = 0; - mfm->status = STAT_READY | STAT_DSC; - mfm_irq_raise(mfm); - break; - - case CMD_SEEK: - do_seek(mfm); - mfm->status = STAT_READY | STAT_DSC; - mfm_irq_raise(mfm); - break; - - case CMD_READ: - do_seek(mfm); - if (mfm_get_sector(mfm, &addr)) - { - mfm->error = ERR_ID_NOT_FOUND; - mfm->status = STAT_READY | STAT_DSC | STAT_ERR; - mfm_irq_raise(mfm); - break; - } - - hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) mfm->buffer); - mfm->pos = 0; - mfm->status = STAT_DRQ | STAT_READY | STAT_DSC; - mfm_irq_raise(mfm); - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); - break; - - case CMD_WRITE: - do_seek(mfm); - if (mfm_get_sector(mfm, &addr)) - { - mfm->error = ERR_ID_NOT_FOUND; - mfm->status = STAT_READY | STAT_DSC | STAT_ERR; - mfm_irq_raise(mfm); - break; - } - hdd_image_write(drive->hdc_num, addr, 1, (uint8_t *) mfm->buffer); - mfm_irq_raise(mfm); - mfm->secount = (mfm->secount - 1) & 0xff; - if (mfm->secount) - { - mfm->status = STAT_DRQ | STAT_READY | STAT_DSC; - mfm->pos = 0; - mfm_next_sector(mfm); - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); - } - else - { - mfm->status = STAT_READY | STAT_DSC; - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0); - } - break; - - case CMD_VERIFY: - do_seek(mfm); - mfm->pos = 0; - mfm->status = STAT_READY | STAT_DSC; - mfm_irq_raise(mfm); - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); - break; - - case CMD_FORMAT: - do_seek(mfm); - if (mfm_get_sector(mfm, &addr)) - { - mfm->error = ERR_ID_NOT_FOUND; - mfm->status = STAT_READY | STAT_DSC | STAT_ERR; - mfm_irq_raise(mfm); - break; - } - hdd_image_zero(drive->hdc_num, addr, mfm->secount); - mfm->status = STAT_READY | STAT_DSC; - mfm_irq_raise(mfm); - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); - break; - - case CMD_DIAGNOSE: - mfm->error = 1; /*No error detected*/ - mfm->status = STAT_READY | STAT_DSC; - mfm_irq_raise(mfm); - break; - - case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ - drive->cfg_spt = mfm->secount; - drive->cfg_hpc = mfm->head+1; - pclog("Parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); - mfm->status = STAT_READY | STAT_DSC; - mfm_irq_raise(mfm); - break; - - default: - pclog("Callback on unknown command %02x\n", mfm->command); - mfm->status = STAT_READY | STAT_ERR | STAT_DSC; - mfm->error = ERR_ABRT; - mfm_irq_raise(mfm); - break; - } -} - -void *mfm_init() -{ - int c, d; - - mfm_t *mfm = malloc(sizeof(mfm_t)); - memset(mfm, 0, sizeof(mfm_t)); - - c = 0; - for (d = 0; d < HDC_NUM; d++) - { - if ((hdc[d].bus == HDD_BUS_MFM) && (hdc[d].mfm_channel < MFM_NUM)) - { - loadhd(mfm, hdc[d].mfm_channel, d, hdc[d].fn); - c++; - if (c >= MFM_NUM) break; - } - } - - mfm->status = STAT_READY | STAT_DSC; - mfm->error = 1; /*No errors*/ - - io_sethandler(0x01f0, 0x0001, mfm_read, mfm_readw, NULL, mfm_write, mfm_writew, NULL, mfm); - io_sethandler(0x01f1, 0x0007, mfm_read, NULL, NULL, mfm_write, NULL, NULL, mfm); - io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, mfm_write, NULL, NULL, mfm); - - timer_add(mfm_callback, &mfm->callback, &mfm->callback, mfm); - - return mfm; -} - -void mfm_close(void *p) -{ - mfm_t *mfm = (mfm_t *)p; - int d; - - for (d = 0; d < 2; d++) - { - mfm_drive_t *drive = &mfm->drives[d]; - - hdd_image_close(drive->hdc_num); - } - - free(mfm); -} - -device_t mfm_at_device = -{ - "IBM PC AT Fixed Disk Adapter", - DEVICE_AT, - mfm_init, - mfm_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; diff --git a/src/hdd/hdd_mfm_at.h b/src/hdd/hdd_mfm_at.h deleted file mode 100644 index 67907af23..000000000 --- a/src/hdd/hdd_mfm_at.h +++ /dev/null @@ -1 +0,0 @@ -extern device_t mfm_at_device; diff --git a/src/hdd/hdd_mfm_xebec.c b/src/hdd/hdd_mfm_xebec.c deleted file mode 100644 index d4647ac31..000000000 --- a/src/hdd/hdd_mfm_xebec.c +++ /dev/null @@ -1,918 +0,0 @@ -#include -#include - -#include "../ibm.h" - -#include "../device.h" -#include "../dma.h" -#include "hdd_image.h" -#include "../io.h" -#include "../mem.h" -#include "../pic.h" -#include "../rom.h" -#include "../timer.h" -#include "hdd_mfm_xebec.h" - - -#define XEBEC_TIME (2000 * TIMER_USEC) - -enum -{ - STATE_IDLE, - STATE_RECEIVE_COMMAND, - STATE_START_COMMAND, - STATE_RECEIVE_DATA, - STATE_RECEIVED_DATA, - STATE_SEND_DATA, - STATE_SENT_DATA, - STATE_COMPLETION_BYTE, - STATE_DUNNO -}; - -typedef struct mfm_drive_t -{ - int spt, hpc; - int tracks; - int cfg_spt; - int cfg_hpc; - int cfg_cyl; - int current_cylinder; - int present; - int hdc_num; -} mfm_drive_t; - -typedef struct xebec_t -{ - rom_t bios_rom; - - int callback; - - int state; - - uint8_t status; - - uint8_t command[6]; - int command_pos; - - uint8_t data[512]; - int data_pos, data_len; - - uint8_t sector_buf[512]; - - uint8_t irq_dma_mask; - - uint8_t completion_byte; - uint8_t error; - - int drive_sel; - - mfm_drive_t drives[2]; - - int sector, head, cylinder; - int sector_count; - - uint8_t switches; -} xebec_t; - -#define STAT_IRQ 0x20 -#define STAT_DRQ 0x10 -#define STAT_BSY 0x08 -#define STAT_CD 0x04 -#define STAT_IO 0x02 -#define STAT_REQ 0x01 - -#define IRQ_ENA 0x02 -#define DMA_ENA 0x01 - -#define CMD_TEST_DRIVE_READY 0x00 -#define CMD_RECALIBRATE 0x01 -#define CMD_READ_STATUS 0x03 -#define CMD_VERIFY_SECTORS 0x05 -#define CMD_FORMAT_TRACK 0x06 -#define CMD_READ_SECTORS 0x08 -#define CMD_WRITE_SECTORS 0x0a -#define CMD_SEEK 0x0b -#define CMD_INIT_DRIVE_PARAMS 0x0c -#define CMD_WRITE_SECTOR_BUFFER 0x0f -#define CMD_BUFFER_DIAGNOSTIC 0xe0 -#define CMD_CONTROLLER_DIAGNOSTIC 0xe4 -#define CMD_DTC_GET_DRIVE_PARAMS 0xfb -#define CMD_DTC_SET_STEP_RATE 0xfc -#define CMD_DTC_SET_GEOMETRY 0xfe -#define CMD_DTC_GET_GEOMETRY 0xff - -#define ERR_NOT_READY 0x04 -#define ERR_SEEK_ERROR 0x15 -#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21 - -static uint8_t xebec_read(uint16_t port, void *p) -{ - xebec_t *xebec = (xebec_t *)p; - uint8_t temp = 0xff; - - switch (port) - { - case 0x320: /*Read data*/ - xebec->status &= ~STAT_IRQ; - switch (xebec->state) - { - case STATE_COMPLETION_BYTE: - if ((xebec->status & 0xf) != (STAT_CD | STAT_IO | STAT_REQ | STAT_BSY)) - fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", xebec->status); - - temp = xebec->completion_byte; - xebec->status = 0; - xebec->state = STATE_IDLE; - break; - - case STATE_SEND_DATA: - if ((xebec->status & 0xf) != (STAT_IO | STAT_REQ | STAT_BSY)) - fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", xebec->status); - if (xebec->data_pos >= xebec->data_len) - fatal("Data write with full data!\n"); - temp = xebec->data[xebec->data_pos++]; - if (xebec->data_pos == xebec->data_len) - { - xebec->status = STAT_BSY; - xebec->state = STATE_SENT_DATA; - xebec->callback = XEBEC_TIME; - } - break; - - default: - fatal("Read data register - %i, %02x\n", xebec->state, xebec->status); - } - break; - - case 0x321: /*Read status*/ - temp = xebec->status; - break; - - case 0x322: /*Read option jumpers*/ - temp = xebec->switches; - break; - } - - return temp; -} - -static void xebec_write(uint16_t port, uint8_t val, void *p) -{ - xebec_t *xebec = (xebec_t *)p; - - switch (port) - { - case 0x320: /*Write data*/ - switch (xebec->state) - { - case STATE_RECEIVE_COMMAND: - if ((xebec->status & 0xf) != (STAT_BSY | STAT_CD | STAT_REQ)) - fatal("Bad write data state - STATE_START_COMMAND, status=%02x\n", xebec->status); - if (xebec->command_pos >= 6) - fatal("Command write with full command!\n"); - /*Command data*/ - xebec->command[xebec->command_pos++] = val; - if (xebec->command_pos == 6) - { - xebec->status = STAT_BSY; - xebec->state = STATE_START_COMMAND; - xebec->callback = XEBEC_TIME; - } - break; - - case STATE_RECEIVE_DATA: - if ((xebec->status & 0xf) != (STAT_BSY | STAT_REQ)) - fatal("Bad write data state - STATE_RECEIVE_DATA, status=%02x\n", xebec->status); - if (xebec->data_pos >= xebec->data_len) - fatal("Data write with full data!\n"); - /*Command data*/ - xebec->data[xebec->data_pos++] = val; - if (xebec->data_pos == xebec->data_len) - { - xebec->status = STAT_BSY; - xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; - } - break; - - default: - fatal("Write data unknown state - %i %02x\n", xebec->state, xebec->status); - } - break; - - case 0x321: /*Controller reset*/ - xebec->status = 0; - break; - - case 0x322: /*Generate controller-select-pulse*/ - xebec->status = STAT_BSY | STAT_CD | STAT_REQ; - xebec->command_pos = 0; - xebec->state = STATE_RECEIVE_COMMAND; - break; - - case 0x323: /*DMA/IRQ mask register*/ - xebec->irq_dma_mask = val; - break; - } -} - -static void xebec_complete(xebec_t *xebec) -{ - xebec->status = STAT_REQ | STAT_CD | STAT_IO | STAT_BSY; - xebec->state = STATE_COMPLETION_BYTE; - if (xebec->irq_dma_mask & IRQ_ENA) - { - xebec->status |= STAT_IRQ; - picint(1 << 5); - } -} - -static void xebec_error(xebec_t *xebec, uint8_t error) -{ - xebec->completion_byte |= 0x02; - xebec->error = error; - pclog("xebec_error - %02x\n", xebec->error); -} - -static int xebec_get_sector(xebec_t *xebec, off64_t *addr) -{ - mfm_drive_t *drive = &xebec->drives[xebec->drive_sel]; - int heads = drive->cfg_hpc; - - if (drive->current_cylinder != xebec->cylinder) - { - pclog("mfm_get_sector: wrong cylinder\n"); - xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS; - return 1; - } - if (xebec->head > heads) - { - pclog("mfm_get_sector: past end of configured heads\n"); - xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS; - return 1; - } - if (xebec->head > drive->hpc) - { - pclog("mfm_get_sector: past end of heads\n"); - xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS; - return 1; - } - if (xebec->sector >= 17) - { - pclog("mfm_get_sector: past end of sectors\n"); - xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS; - return 1; - } - - *addr = ((((off64_t) xebec->cylinder * heads) + xebec->head) * - 17) + xebec->sector; - - return 0; -} - -static void xebec_next_sector(xebec_t *xebec) -{ - mfm_drive_t *drive = &xebec->drives[xebec->drive_sel]; - - xebec->sector++; - if (xebec->sector >= 17) - { - xebec->sector = 0; - xebec->head++; - if (xebec->head >= drive->cfg_hpc) - { - xebec->head = 0; - xebec->cylinder++; - drive->current_cylinder++; - if (drive->current_cylinder >= drive->cfg_cyl) - drive->current_cylinder = drive->cfg_cyl-1; - } - } -} - -static void xebec_callback(void *p) -{ - off64_t addr; - - xebec_t *xebec = (xebec_t *)p; - mfm_drive_t *drive; - - xebec->callback = 0; - - xebec->drive_sel = (xebec->command[1] & 0x20) ? 1 : 0; - xebec->completion_byte = xebec->drive_sel & 0x20; - - drive = &xebec->drives[xebec->drive_sel]; - - switch (xebec->command[0]) - { - case CMD_TEST_DRIVE_READY: - if (!drive->present) - xebec_error(xebec, ERR_NOT_READY); - xebec_complete(xebec); - break; - - case CMD_RECALIBRATE: - if (!drive->present) - xebec_error(xebec, ERR_NOT_READY); - else - { - xebec->cylinder = 0; - drive->current_cylinder = 0; - } - xebec_complete(xebec); - break; - - case CMD_READ_STATUS: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->state = STATE_SEND_DATA; - xebec->data_pos = 0; - xebec->data_len = 4; - xebec->status = STAT_BSY | STAT_IO | STAT_REQ; - xebec->data[0] = xebec->error; - xebec->data[1] = xebec->drive_sel ? 0x20 : 0; - xebec->data[2] = xebec->data[3] = 0; - xebec->error = 0; - break; - - case STATE_SENT_DATA: - xebec_complete(xebec); - break; - } - break; - - case CMD_VERIFY_SECTORS: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2); - drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder; - xebec->head = xebec->command[1] & 0x1f; - xebec->sector = xebec->command[2] & 0x1f; - xebec->sector_count = xebec->command[4]; - do - { - if (xebec_get_sector(xebec, &addr)) - { - pclog("xebec_get_sector failed\n"); - xebec_error(xebec, xebec->error); - xebec_complete(xebec); - return; - } - - xebec_next_sector(xebec); - - xebec->sector_count = (xebec->sector_count-1) & 0xff; - } while (xebec->sector_count); - - xebec_complete(xebec); - - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); - break; - - default: - fatal("CMD_VERIFY_SECTORS: bad state %i\n", xebec->state); - } - break; - - case CMD_FORMAT_TRACK: - { - xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2); - drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder; - xebec->head = xebec->command[1] & 0x1f; - - if (xebec_get_sector(xebec, &addr)) - { - pclog("xebec_get_sector failed\n"); - xebec_error(xebec, xebec->error); - xebec_complete(xebec); - return; - } - - hdd_image_zero(drive->hdc_num, addr, 17); - - xebec_complete(xebec); - } - break; - - case CMD_READ_SECTORS: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2); - drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder; - xebec->head = xebec->command[1] & 0x1f; - xebec->sector = xebec->command[2] & 0x1f; - xebec->sector_count = xebec->command[4]; - xebec->state = STATE_SEND_DATA; - xebec->data_pos = 0; - xebec->data_len = 512; - { - if (xebec_get_sector(xebec, &addr)) - { - xebec_error(xebec, xebec->error); - xebec_complete(xebec); - return; - } - - hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf); - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); - } - if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; - else - { - xebec->status = STAT_BSY | STAT_IO | STAT_REQ; - memcpy(xebec->data, xebec->sector_buf, 512); - } - break; - - case STATE_SEND_DATA: - xebec->status = STAT_BSY; - if (xebec->irq_dma_mask & DMA_ENA) - { - for (; xebec->data_pos < 512; xebec->data_pos++) - { - int val = dma_channel_write(3, xebec->sector_buf[xebec->data_pos]); - - if (val == DMA_NODATA) - { - pclog("CMD_READ_SECTORS out of data!\n"); - xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; - return; - } - } - xebec->state = STATE_SENT_DATA; - xebec->callback = XEBEC_TIME; - } - else - fatal("Read sectors no DMA! - shouldn't get here\n"); - break; - - case STATE_SENT_DATA: - xebec_next_sector(xebec); - - xebec->data_pos = 0; - - xebec->sector_count = (xebec->sector_count-1) & 0xff; - - if (xebec->sector_count) - { - if (xebec_get_sector(xebec, &addr)) - { - xebec_error(xebec, xebec->error); - xebec_complete(xebec); - return; - } - - hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf); - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); - - xebec->state = STATE_SEND_DATA; - - if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; - else - { - xebec->status = STAT_BSY | STAT_IO | STAT_REQ; - memcpy(xebec->data, xebec->sector_buf, 512); - } - } - else - { - xebec_complete(xebec); - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0); - } - break; - - - default: - fatal("CMD_READ_SECTORS: bad state %i\n", xebec->state); - } - break; - - case CMD_WRITE_SECTORS: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2); - drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder; - xebec->head = xebec->command[1] & 0x1f; - xebec->sector = xebec->command[2] & 0x1f; - xebec->sector_count = xebec->command[4]; - xebec->state = STATE_RECEIVE_DATA; - xebec->data_pos = 0; - xebec->data_len = 512; - if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; - else - xebec->status = STAT_BSY | STAT_REQ; - break; - - case STATE_RECEIVE_DATA: - xebec->status = STAT_BSY; - if (xebec->irq_dma_mask & DMA_ENA) - { - for (; xebec->data_pos < 512; xebec->data_pos++) - { - int val = dma_channel_read(3); - - if (val == DMA_NODATA) - { - pclog("CMD_WRITE_SECTORS out of data!\n"); - xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; - return; - } - - xebec->sector_buf[xebec->data_pos] = val & 0xff; - } - - xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; - } - else - fatal("Write sectors no DMA! - should never get here\n"); - break; - - case STATE_RECEIVED_DATA: - if (!(xebec->irq_dma_mask & DMA_ENA)) - memcpy(xebec->sector_buf, xebec->data, 512); - - { - if (xebec_get_sector(xebec, &addr)) - { - xebec_error(xebec, xebec->error); - xebec_complete(xebec); - return; - } - - hdd_image_write(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf); - } - - update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); - - xebec_next_sector(xebec); - xebec->data_pos = 0; - xebec->sector_count = (xebec->sector_count-1) & 0xff; - - if (xebec->sector_count) - { - xebec->state = STATE_RECEIVE_DATA; - if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; - else - xebec->status = STAT_BSY | STAT_REQ; - } - else - xebec_complete(xebec); - break; - - default: - fatal("CMD_WRITE_SECTORS: bad state %i\n", xebec->state); - } - break; - - case CMD_SEEK: - if (!drive->present) - xebec_error(xebec, ERR_NOT_READY); - else - { - int cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2); - - drive->current_cylinder = (cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : cylinder; - - if (cylinder != drive->current_cylinder) - xebec_error(xebec, ERR_SEEK_ERROR); - } - xebec_complete(xebec); - break; - - case CMD_INIT_DRIVE_PARAMS: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->state = STATE_RECEIVE_DATA; - xebec->data_pos = 0; - xebec->data_len = 8; - xebec->status = STAT_BSY | STAT_REQ; - break; - - case STATE_RECEIVED_DATA: - drive->cfg_cyl = xebec->data[1] | (xebec->data[0] << 8); - drive->cfg_hpc = xebec->data[2]; - pclog("Drive %i: cylinders=%i, heads=%i\n", xebec->drive_sel, drive->cfg_cyl, drive->cfg_hpc); - xebec_complete(xebec); - break; - - default: - fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", xebec->state); - } - break; - - case CMD_WRITE_SECTOR_BUFFER: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->state = STATE_RECEIVE_DATA; - xebec->data_pos = 0; - xebec->data_len = 512; - if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; - else - xebec->status = STAT_BSY | STAT_REQ; - break; - - case STATE_RECEIVE_DATA: - if (xebec->irq_dma_mask & DMA_ENA) - { - xebec->status = STAT_BSY; - - for (; xebec->data_pos < 512; xebec->data_pos++) - { - int val = dma_channel_read(3); - - if (val == DMA_NODATA) - { - pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n"); - xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; - return; - } - - xebec->data[xebec->data_pos] = val & 0xff; - } - - xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; - } - else - fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n"); - break; - case STATE_RECEIVED_DATA: - memcpy(xebec->sector_buf, xebec->data, 512); - xebec_complete(xebec); - break; - - default: - fatal("CMD_WRITE_SECTOR_BUFFER bad state %i\n", xebec->state); - } - break; - - case CMD_BUFFER_DIAGNOSTIC: - case CMD_CONTROLLER_DIAGNOSTIC: - xebec_complete(xebec); - break; - - case 0xfa: - xebec_complete(xebec); - break; - - case CMD_DTC_SET_STEP_RATE: - xebec_complete(xebec); - break; - - case CMD_DTC_GET_DRIVE_PARAMS: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->state = STATE_SEND_DATA; - xebec->data_pos = 0; - xebec->data_len = 4; - xebec->status = STAT_BSY | STAT_IO | STAT_REQ; - memset(xebec->data, 0, 4); - xebec->data[0] = drive->tracks & 0xff; - xebec->data[1] = 17 | ((drive->tracks >> 2) & 0xc0); - xebec->data[2] = drive->hpc-1; - pclog("Get drive params %02x %02x %02x %i\n", xebec->data[0], xebec->data[1], xebec->data[2], drive->tracks); - break; - - case STATE_SENT_DATA: - xebec_complete(xebec); - break; - - default: - fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", xebec->state); - } - break; - - case CMD_DTC_GET_GEOMETRY: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->state = STATE_SEND_DATA; - xebec->data_pos = 0; - xebec->data_len = 16; - xebec->status = STAT_BSY | STAT_IO | STAT_REQ; - memset(xebec->data, 0, 16); - xebec->data[0x4] = drive->tracks & 0xff; - xebec->data[0x5] = (drive->tracks >> 8) & 0xff; - xebec->data[0xa] = drive->hpc; - break; - - case STATE_SENT_DATA: - xebec_complete(xebec); - break; - } - break; - - case CMD_DTC_SET_GEOMETRY: - switch (xebec->state) - { - case STATE_START_COMMAND: - xebec->state = STATE_RECEIVE_DATA; - xebec->data_pos = 0; - xebec->data_len = 16; - xebec->status = STAT_BSY | STAT_REQ; - break; - - case STATE_RECEIVED_DATA: - /*Bit of a cheat here - we always report the actual geometry of the drive in use*/ - xebec_complete(xebec); - break; - } - break; - - default: - fatal("Unknown Xebec command - %02x %02x %02x %02x %02x %02x\n", - xebec->command[0], xebec->command[1], - xebec->command[2], xebec->command[3], - xebec->command[4], xebec->command[5]); - } -} - -static void loadhd(xebec_t *xebec, int c, int d, const wchar_t *fn) -{ - mfm_drive_t *drive = &xebec->drives[d]; - int ret = 0; - - ret = hdd_image_load(d); - - if (!ret) - { - drive->present = 0; - return; - } - - drive->spt = hdc[c].spt; - drive->hpc = hdc[c].hpc; - drive->tracks = hdc[c].tracks; - drive->hdc_num = c; - drive->present = 1; -} - -static struct -{ - int tracks, hpc; -} xebec_hd_types[4] = -{ - {306, 4}, /*Type 0*/ - {612, 4}, /*Type 16*/ - {615, 4}, /*Type 2*/ - {306, 8} /*Type 13*/ -}; - -static void xebec_set_switches(xebec_t *xebec) -{ - int c, d; - - xebec->switches = 0; - - for (d = 0; d < 2; d++) - { - mfm_drive_t *drive = &xebec->drives[d]; - - if (!drive->present) - continue; - - for (c = 0; c < 4; c++) - { - if (drive->spt == 17 && - drive->hpc == xebec_hd_types[c].hpc && - drive->tracks == xebec_hd_types[c].tracks) - { - xebec->switches |= (c << (d ? 0 : 2)); - break; - } - } - - if (c == 4) - pclog("WARNING: Drive %c: has format not supported by Fixed Disk Adapter", d ? 'D' : 'C'); - } -} - -static void *xebec_init() -{ - int i = 0; - int c = 0; - - xebec_t *xebec = malloc(sizeof(xebec_t)); - memset(xebec, 0, sizeof(xebec_t)); - - for (i = 0; i < HDC_NUM; i++) - { - if ((hdc[i].bus == HDD_BUS_MFM) && (hdc[i].mfm_channel < MFM_NUM)) - { - loadhd(xebec, i, hdc[i].mfm_channel, hdc[i].fn); - c++; - if (c > MFM_NUM) break; - } - } - - xebec_set_switches(xebec); - - rom_init(&xebec->bios_rom, L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec); - - timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec); - - return xebec; -} - -static void xebec_close(void *p) -{ - xebec_t *xebec = (xebec_t *)p; - int d; - - for (d = 0; d < 2; d++) - { - mfm_drive_t *drive = &xebec->drives[d]; - - hdd_image_close(drive->hdc_num); - } - - free(xebec); -} - -static int xebec_available() -{ - return rom_present(L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin"); -} - -device_t mfm_xebec_device = -{ - "IBM PC Fixed Disk Adapter", - 0, - xebec_init, - xebec_close, - xebec_available, - NULL, - NULL, - NULL, - NULL -}; - -static void *dtc_5150x_init() -{ - int i = 0; - int c = 0; - - xebec_t *xebec = malloc(sizeof(xebec_t)); - memset(xebec, 0, sizeof(xebec_t)); - - for (i = 0; i < HDC_NUM; i++) - { - if ((hdc[i].bus == HDD_BUS_MFM) && (hdc[i].mfm_channel < MFM_NUM)) - { - loadhd(xebec, i, hdc[i].mfm_channel, hdc[i].fn); - c++; - if (c > MFM_NUM) break; - } - } - - xebec->switches = 0xff; - - xebec->drives[0].cfg_cyl = xebec->drives[0].tracks; - xebec->drives[0].cfg_hpc = xebec->drives[0].hpc; - xebec->drives[1].cfg_cyl = xebec->drives[1].tracks; - xebec->drives[1].cfg_hpc = xebec->drives[1].hpc; - - rom_init(&xebec->bios_rom, L"roms/hdd/mfm_xebec/dtc_cxd21a.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec); - - timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec); - - return xebec; -} -static int dtc_5150x_available() -{ - return rom_present(L"roms/hdd/mfm_xebec/dtc_cxd21a.bin"); -} - -device_t dtc_5150x_device = -{ - "DTC 5150X", - 0, - dtc_5150x_init, - xebec_close, - dtc_5150x_available, - NULL, - NULL, - NULL, - NULL -}; diff --git a/src/hdd/hdd_mfm_xebec.h b/src/hdd/hdd_mfm_xebec.h deleted file mode 100644 index e6bafff17..000000000 --- a/src/hdd/hdd_mfm_xebec.h +++ /dev/null @@ -1,2 +0,0 @@ -extern device_t mfm_xebec_device; -extern device_t dtc_5150x_device; diff --git a/src/i82335.c b/src/i82335.c index 981ea8f55..a29303b2b 100644 --- a/src/i82335.c +++ b/src/i82335.c @@ -1,6 +1,9 @@ /* Intel 82335 SX emulation, used by the Phoenix 386 clone. */ +#include #include +#include +#include #include "ibm.h" #include "io.h" #include "mem.h" diff --git a/src/ibm.h b/src/ibm.h index b6f9b54d5..d671fff9b 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -8,18 +8,20 @@ * * General include file. * - * Version: @(#)ibm.h 1.0.3 2017/09/03 + * !!!NOTE!!! The goal is to GET RID of this file. Do NOT add stuff !! + * + * Version: @(#)ibm.h 1.0.8 2017/10/04 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ -#include -#include -#include -#include -#define printf pclog +#ifndef EMU_IBM_H +# define EMU_IBM_H + + +#define printf pclog /*Memory*/ @@ -286,38 +288,38 @@ extern int cpl_override; /*Timer*/ typedef struct PIT_nr { - int nr; + int64_t nr; struct PIT *pit; } PIT_nr; typedef struct PIT { uint32_t l[3]; - int c[3]; + int64_t c[3]; uint8_t m[3]; uint8_t ctrl,ctrls[3]; - int wp,rm[3],wm[3]; + int64_t wp,rm[3],wm[3]; uint16_t rl[3]; - int thit[3]; - int delay[3]; - int rereadlatch[3]; - int gate[3]; - int out[3]; - int running[3]; - int enabled[3]; - int newcount[3]; - int count[3]; - int using_timer[3]; - int initial[3]; - int latched[3]; - int disabled[3]; + int64_t thit[3]; + int64_t delay[3]; + int64_t rereadlatch[3]; + int64_t gate[3]; + int64_t out[3]; + int64_t running[3]; + int64_t enabled[3]; + int64_t newcount[3]; + int64_t count[3]; + int64_t using_timer[3]; + int64_t initial[3]; + int64_t latched[3]; + int64_t disabled[3]; uint8_t read_status[3]; - int do_read_status[3]; + int64_t do_read_status[3]; PIT_nr pit_nr[3]; - void (*set_out_funcs[3])(int new_out, int old_out); + void (*set_out_funcs[3])(int64_t new_out, int64_t old_out); } PIT; PIT pit, pit2; @@ -373,176 +375,80 @@ extern PIC pic, pic2; extern int pic_intpending; -extern int floppytime; +extern int64_t floppytime; extern wchar_t floppyfns[4][512]; extern int driveempty[4]; #define MDA ((gfxcard==GFX_MDA || gfxcard==GFX_HERCULES || gfxcard==GFX_HERCULESPLUS || gfxcard==GFX_INCOLOR || gfxcard==GFX_GENIUS) && (romset=ROM_IBMAT)) -#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_COLORPLUS && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_WY700 && gfxcard!=GFX_GENIUS && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && gfxcard!=GFX_HERCULESPLUS && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200) -#define PCJR (romset == ROM_IBMPCJR) -#define AMIBIOS (romset==ROM_AMI386SX || romset==ROM_AMI486 || romset == ROM_WIN486) +#define VGA ((gfxcard>=GFX_TVGA) && gfxcard!=GFX_COLORPLUS && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_WY700 && gfxcard!=GFX_GENIUS && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && gfxcard!=GFX_HERCULESPLUS && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200) int GAMEBLASTER, GUS, SSI2001, voodoo_enabled, buslogic_enabled; extern int AMSTRAD, AT, is286, is386, PCI, TANDY; -enum -{ - ROM_IBMPC = 0, /*301 keyboard error, 131 cassette (!!!) error*/ - ROM_IBMXT, /*301 keyboard error*/ - ROM_IBMPCJR, - ROM_GENXT, /*'Generic XT BIOS'*/ - ROM_DTKXT, - ROM_EUROPC, - ROM_OLIM24, - ROM_TANDY, - ROM_PC1512, - ROM_PC200, - ROM_PC1640, - ROM_PC2086, - ROM_PC3086, - ROM_AMIXT, /*XT Clone with AMI BIOS*/ - ROM_LTXT, - ROM_LXT3, - ROM_PX386, - ROM_DTK386, - ROM_PXXT, - ROM_JUKOPC, - ROM_TANDY1000HX, - ROM_TANDY1000SL2, - ROM_IBMAT, - ROM_CMDPC30, - ROM_AMI286, - ROM_AWARD286, - ROM_DELL200, - ROM_MISC286, - ROM_IBMAT386, - ROM_ACER386, - ROM_MEGAPC, - ROM_AMI386SX, - ROM_AMI486, - ROM_WIN486, - ROM_PCI486, - ROM_SIS496, - ROM_430VX, - ROM_ENDEAVOR, - ROM_REVENGE, - ROM_IBMPS1_2011, - ROM_DESKPRO_386, - ROM_PORTABLE, -#if 0 - ROM_PORTABLEII, - ROM_PORTABLEIII, - ROM_PORTABLEIII386, /* The original Compaq Portable III shipped with an Intel 80286 CPU, but later switched to a 386DX. */ -#endif - ROM_IBMPS1_2121, - - ROM_AMI386DX_OPTI495, - ROM_MR386DX_OPTI495, - - ROM_IBMPS2_M30_286, - ROM_IBMPS2_M50, - ROM_IBMPS2_M55SX, - ROM_IBMPS2_M80, - - ROM_DTK486, /*DTK PKM-0038S E-2 / SiS 471 / Award BIOS / SiS 85C471*/ - ROM_VLI486SV2G, /*ASUS VL/I-486SV2G / SiS 471 / Award BIOS / SiS 85C471*/ - ROM_R418, /*Rise Computer R418 / SiS 496/497 / Award BIOS / SMC FDC37C665*/ - ROM_586MC1, /*Micro Star 586MC1 MS-5103 / 430LX / Award BIOS*/ - ROM_PLATO, /*Intel Premiere/PCI II / 430NX / AMI BIOS / SMC FDC37C665*/ - ROM_MB500N, /*PC Partner MB500N / 430FX / Award BIOS / SMC FDC37C665*/ - ROM_P54TP4XE, /*ASUS P/I-P55TP4XE / 430FX / Award BIOS / SMC FDC37C665*/ - ROM_AP53, /*AOpen AP53 / 430HX / AMI BIOS / SMC FDC37C665/669*/ - ROM_P55T2S, /*ASUS P/I-P55T2S / 430HX / AMI BIOS / National Semiconductors PC87306*/ - ROM_ACERM3A, /*Acer M3A / 430HX / Acer BIOS / SMC FDC37C932FR*/ - ROM_ACERV35N, /*Acer V35N / 430HX / Acer BIOS / SMC FDC37C932FR*/ - ROM_P55T2P4, /*ASUS P/I-P55T2P4 / 430HX / Award BIOS / Winbond W8387F*/ - ROM_P55TVP4, /*ASUS P/I-P55TVP4 / 430HX / Award BIOS / Winbond W8387F*/ - ROM_P55VA, /*Epox P55-VA / 430VX / Award BIOS / SMC FDC37C932FR*/ - - ROM_440FX, /*Tyan Titan-Pro AT / 440FX / Award BIOS / SMC FDC37C665*/ - - ROM_MARL, /*Intel Advanced/ML / 430HX / AMI BIOS / National Semiconductors PC87306*/ - ROM_THOR, /*Intel Advanced/ATX / 430FX / AMI BIOS / National Semiconductors PC87306*/ - ROM_MRTHOR, /*Intel Advanced/ATX / 430FX / MR.BIOS / National Semiconductors PC87306*/ - ROM_POWERMATE_V,/*NEC PowerMate V / 430FX / Phoenix BIOS / SMC FDC37C665*/ - - ROM_IBMPS1_2121_ISA,/*IBM PS/1 Model 2121 with ISA expansion bus*/ - - ROM_SPC4200P, /*Samsung SPC-4200P / SCAT / Phoenix BIOS*/ - ROM_SUPER286TR, /*Hyundai Super-286TR / SCAT / Award BIOS*/ - - ROM_AWARD386SX_OPTI495, - ROM_AWARD386DX_OPTI495, - ROM_AWARD486_OPTI495, - - ROM_MEGAPCDX, /*386DX mdoel of the Mega PC - Note by Tohka: The documentation (that I have in German) clearly says such a model exists.*/ - ROM_ZAPPA, /*Intel Advanced/ZP / 430FX / AMI BIOS / National Semiconductors PC87306*/ - - ROM_CMDPC60, - - ROM_S1668, /*Tyan Titan-Pro ATX / 440FX / AMI BIOS / SMC FDC37C669*/ - ROM_IBMPS1_2133, - - ROM_PRESIDENT, /*President Award 430FX PCI / 430FX / Award BIOS / Unknown Super I/O chip*/ - ROM_IBMPS2_M80_486, - - ROM_MAX -}; - -extern int romspresent[ROM_MAX]; - extern int hasfpu; -extern int romset; enum { GFX_CGA = 0, GFX_MDA, GFX_HERCULES, - GFX_EGA, /*Using IBM EGA BIOS*/ - GFX_TVGA, /*Using Trident TVGA8900D BIOS*/ - GFX_ET4000, /*Tseng ET4000*/ - GFX_ET4000W32, /*Tseng ET4000/W32p (Diamond Stealth 32)*/ - GFX_BAHAMAS64, /*S3 Vision864 (Paradise Bahamas 64)*/ - GFX_N9_9FX, /*S3 764/Trio64 (Number Nine 9FX)*/ - GFX_VIRGE, /*S3 Virge*/ - GFX_TGUI9440, /*Trident TGUI9440*/ - GFX_VGA, /*IBM VGA*/ - GFX_VGAEDGE16, /*ATI VGA Edge-16 (18800-1)*/ - GFX_VGACHARGER, /*ATI VGA Charger (28800-5)*/ - GFX_OTI067, /*Oak OTI-067*/ - GFX_MACH64GX, /*ATI Graphics Pro Turbo (Mach64)*/ - GFX_CL_GD5429, /*Cirrus Logic CL-GD5429*/ - GFX_VIRGEDX, /*S3 Virge/DX*/ - GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/ - GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/ - GFX_INCOLOR, /* Hercules InColor */ - GFX_COLORPLUS, /* Plantronics ColorPlus */ - GFX_WY700, /* Wyse 700 */ - GFX_GENIUS, /* MDSI Genius */ - GFX_MACH64VT2, /*ATI Mach64 VT2*/ + GFX_EGA, /*Using IBM EGA BIOS*/ + GFX_TVGA, /*Using Trident TVGA8900D BIOS*/ + GFX_ET4000, /*Tseng ET4000*/ + GFX_ET4000W32_VLB, /*Tseng ET4000/W32p (Diamond Stealth 32) VLB*/ + GFX_ET4000W32_PCI, /*Tseng ET4000/W32p (Diamond Stealth 32) PCI*/ + GFX_BAHAMAS64_VLB, /*S3 Vision864 (Paradise Bahamas 64) VLB*/ + GFX_BAHAMAS64_PCI, /*S3 Vision864 (Paradise Bahamas 64) PCI*/ + GFX_N9_9FX_VLB, /*S3 764/Trio64 (Number Nine 9FX) VLB*/ + GFX_N9_9FX_PCI, /*S3 764/Trio64 (Number Nine 9FX) PCI*/ + GFX_VIRGE_VLB, /*S3 Virge VLB*/ + GFX_VIRGE_PCI, /*S3 Virge PCI*/ + GFX_TGUI9440_VLB, /*Trident TGUI9440 VLB*/ + GFX_TGUI9440_PCI, /*Trident TGUI9440 PCI*/ + GFX_VGA, /*IBM VGA*/ + GFX_VGAEDGE16, /*ATI VGA Edge-16 (18800-1)*/ + GFX_VGACHARGER, /*ATI VGA Charger (28800-5)*/ + GFX_OTI067, /*Oak OTI-067*/ + GFX_MACH64GX_VLB, /*ATI Graphics Pro Turbo (Mach64) VLB*/ + GFX_MACH64GX_PCI, /*ATI Graphics Pro Turbo (Mach64) PCI*/ + GFX_CL_GD5429, /*Cirrus Logic CL-GD5429*/ + GFX_VIRGEDX_VLB, /*S3 Virge/DX VLB*/ + GFX_VIRGEDX_PCI, /*S3 Virge/DX PCI*/ + GFX_PHOENIX_TRIO32_VLB, /*S3 732/Trio32 (Phoenix) VLB*/ + GFX_PHOENIX_TRIO32_PCI, /*S3 732/Trio32 (Phoenix) PCI*/ + GFX_PHOENIX_TRIO64_VLB, /*S3 764/Trio64 (Phoenix) VLB*/ + GFX_PHOENIX_TRIO64_PCI, /*S3 764/Trio64 (Phoenix) PCI*/ + GFX_INCOLOR, /*Hercules InColor*/ + GFX_COLORPLUS, /*Plantronics ColorPlus*/ + GFX_WY700, /*Wyse 700*/ + GFX_GENIUS, /*MDSI Genius*/ + GFX_MACH64VT2, /*ATI Mach64 VT2*/ - GFX_COMPAQ_EGA, /*Compaq EGA*/ - GFX_SUPER_EGA, /*Using Chips & Technologies SuperEGA BIOS*/ - GFX_COMPAQ_VGA, /*Compaq/Paradise VGA*/ - GFX_MIRO_VISION964, /*S3 Vision964 (Miro Crystal)*/ - GFX_CL_GD5446, /*Cirrus Logic CL-GD5446*/ - GFX_VGAWONDERXL, /*Compaq ATI VGA Wonder XL (28800-5)*/ - GFX_WD90C11, /*Paradise WD90C11 Standalone*/ - GFX_OTI077, /*Oak OTI-077*/ - GFX_VGAWONDERXL24, /*Compaq ATI VGA Wonder XL24 (28800-6)*/ - GFX_STEALTH64, /*S3 Vision864 (Diamond Stealth 64)*/ - GFX_PHOENIX_VISION864, /*S3 Vision864 (Phoenix)*/ - GFX_RIVATNT, - GFX_RIVA128, + GFX_COMPAQ_EGA, /*Compaq EGA*/ + GFX_SUPER_EGA, /*Using Chips & Technologies SuperEGA BIOS*/ + GFX_COMPAQ_VGA, /*Compaq/Paradise VGA*/ + GFX_CL_GD5446, /*Cirrus Logic CL-GD5446*/ + GFX_VGAWONDERXL, /*Compaq ATI VGA Wonder XL (28800-5)*/ + GFX_WD90C11, /*Paradise WD90C11 Standalone*/ + GFX_OTI077, /*Oak OTI-077*/ + GFX_VGAWONDERXL24, /*Compaq ATI VGA Wonder XL24 (28800-6)*/ + GFX_STEALTH64_VLB, /*S3 Vision864 (Diamond Stealth 64) VLB*/ + GFX_STEALTH64_PCI, /*S3 Vision864 (Diamond Stealth 64) PCI*/ + GFX_PHOENIX_VISION864_VLB, /*S3 Vision864 (Phoenix) VLB*/ + GFX_PHOENIX_VISION864_PCI, /*S3 Vision864 (Phoenix) PCI*/ + GFX_RIVATNT, /*nVidia Riva TNT*/ + GFX_RIVATNT2, /*nVidia Riva TNT2*/ + GFX_RIVA128, /*nVidia Riva 128*/ GFX_HERCULESPLUS, - GFX_RIVATNT2, + GFX_VIRGEVX_VLB, /*S3 Virge/VX VLB*/ + GFX_VIRGEVX_PCI, /*S3 Virge/VX PCI*/ + GFX_VIRGEDX4_VLB, /*S3 Virge/DX (VBE 2.0) VLB*/ + GFX_VIRGEDX4_PCI, /*S3 Virge/DX (VBE 2.0) PCI*/ - GFX_TRIGEM_UNK, - GFX_OTI037, /*Oak OTI-037*/ + GFX_OTI037, /*Oak OTI-037*/ - GFX_VIRGEVX, /*S3 Virge/VX*/ - GFX_VIRGEDX4, /*S3 Virge/DX (VBE 2.0)*/ + GFX_TRIGEM_UNK, /*Unknown TriGem graphics card with Hangeul ROM*/ + GFX_MIRO_VISION964, /*S3 Vision964 (Miro Crystal)*/ GFX_MAX }; @@ -585,62 +491,12 @@ extern int gated,speakval,speakon; #define SND_WSS 9 /*Windows Sound System*/ #define SND_PAS16 10 /*Pro Audio Spectrum 16*/ -extern wchar_t pcempath[512]; +extern wchar_t exe_path[1024]; +extern wchar_t cfg_path[1024]; -/*Hard disk*/ -enum -{ - HDD_BUS_DISABLED = 0, - HDD_BUS_MFM, - HDD_BUS_XTIDE, - HDD_BUS_ESDI, - HDD_BUS_IDE_PIO_ONLY, - HDD_BUS_IDE_PIO_AND_DMA, - HDD_BUS_SCSI, - HDD_BUS_SCSI_REMOVABLE, - HDD_BUS_USB -}; - -#define HDC_NUM 30 -#define MFM_NUM 2 -#define ESDI_NUM 2 -#define XTIDE_NUM 2 -#define IDE_NUM 8 -#define SCSI_NUM 16 /* Theoretically the controller can have at least 64 devices, or even 128 in case of a wide bus, but - let's not exaggerate with them - 16 ought to be enough for everyone. */ - -#pragma pack(push,1) -typedef struct { - FILE *f; - uint64_t spt,hpc; /*Sectors per track, heads per cylinder*/ - uint64_t tracks; - int is_hdi; - int wp; - uint32_t base; - uint64_t at_spt,at_hpc; /*[Translation] Sectors per track, heads per cylinder*/ - unsigned int bus; - unsigned int mfm_channel; - unsigned int esdi_channel; - unsigned int xtide_channel; - unsigned int ide_channel; - unsigned int scsi_id; - unsigned int scsi_lun; - wchar_t fn[260]; - wchar_t prev_fn[260]; -} hard_disk_t; -#pragma pack(pop) - -extern hard_disk_t hdc[HDC_NUM]; - -uint64_t hdt[128][3]; -uint64_t hdt_mfm[128][3]; - -int image_is_hdi(const wchar_t *s); -int image_is_hdx(const wchar_t *s, int check_signature); - /*Keyboard*/ -extern int keybsenddelay; +extern int64_t keybsenddelay; /*CD-ROM*/ @@ -653,7 +509,7 @@ enum CDROM_BUS_USB = 8 }; -extern int idecallback[5]; +extern int64_t idecallback[5]; #define CD_STATUS_EMPTY 0 #define CD_STATUS_DATA_ONLY 1 @@ -682,10 +538,6 @@ extern uint64_t timer_freq; extern int infocus; -extern void onesec(void); - -extern void resetpc_cad(void); -extern void ctrl_alt_esc(void); extern int dump_on_exit; extern int start_in_fullscreen; @@ -704,10 +556,6 @@ extern uint64_t star; #define FPU_CW_Reserved_Bits (0xe0c0) -extern wchar_t nvr_path[1024]; -extern int path_len; - -wchar_t *nvr_concat(wchar_t *to_concat); extern int mem_a20_state; @@ -735,11 +583,11 @@ extern PCI_RESET pci_reset_handler; extern void trc_init(void); -extern int enable_xtide; extern int enable_external_fpu; extern int serial_enabled[2]; extern int lpt_enabled, bugger_enabled; +extern int romset; extern int invert_display; @@ -749,8 +597,24 @@ extern int scale; /* Function prototypes. */ +extern void pclog(const char *format, ...); +extern void fatal(const char *format, ...); +extern wchar_t *pc_concat(wchar_t *str); +extern int pc_init_modules(void); +extern int pc_init(int argc, wchar_t *argv[]); +extern void pc_close(void); +extern void pc_reset_hard_close(void); +extern void pc_reset_hard_init(void); +extern void pc_reset_hard(void); +extern void pc_full_speed(void); +extern void pc_speed_changed(void); +extern void pc_send_cad(void); +extern void pc_send_cae(void); +extern void pc_run(void); +extern void onesec(void); + + extern int checkio(int port); -extern void closepc(void); extern void codegen_block_end(void); extern void codegen_reset(void); extern void cpu_set_edx(void); @@ -762,12 +626,9 @@ extern void execx86(int cycs); extern void flushmmucache(void); extern void flushmmucache_cr3(void); extern int idivl(int32_t val); -extern void initmodules(void); -extern void initpc(int argc, wchar_t *argv[]); extern void loadcscall(uint16_t seg); extern void loadcsjmp(uint16_t seg, uint32_t oxpc); extern void mmu_invalidate(uint32_t addr); -extern void pclog(const char *format, ...); extern void pmodeint(int num, int soft); extern void pmoderetf(int is32, uint16_t off); extern void pmodeiret(int is32); @@ -775,15 +636,9 @@ extern void port_92_clear_reset(void); extern uint8_t readdacfifo(void); extern void refreshread(void); extern void resetmcr(void); -extern void resetpchard_close(void); -extern void resetpchard_init(void); -extern void resetpchard(void); extern void resetreadlookup(void); extern void resetx86(void); -extern void runpc(void); -extern void saveconfig(void); extern void softresetx86(void); -extern void speedchanged(void); extern void x86_int_sw(int num); extern int x86_int_sw_rm(int num); extern void x86gpf(char *s, uint16_t error); @@ -793,25 +648,10 @@ extern void x86ts(char *s, uint16_t error); extern void x87_dumpregs(void); extern void x87_reset(void); -/* Platform functions. */ -extern void pclog(const char *format, ...); -extern void pclog_w(const wchar_t *format, ...); -extern void fatal(const char *format, ...); - -extern void update_status_bar_icon(int tag, int active); -extern void update_status_bar_icon_state(int tag, int state); -extern void status_settextw(wchar_t *wstr); -extern void status_settext(char *str); - -#define SB_FLOPPY 0x00 -#define SB_CDROM 0x10 -#define SB_RDISK 0x20 -#define SB_HDD 0x40 -#define SB_NETWORK 0x50 -#define SB_TEXT 0x60 - -#define UNUSED(x) (void)x /* Configuration values. */ #define SERIAL_MAX 2 #define PARALLEL_MAX 1 + + +#endif /*EMU_IBM_H*/ diff --git a/src/intel.c b/src/intel.c index 01560852f..10442aff1 100644 --- a/src/intel.c +++ b/src/intel.c @@ -1,6 +1,10 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "ibm.h" #include "cpu/cpu.h" #include "io.h" @@ -23,7 +27,7 @@ uint8_t batman_brdconfig(uint16_t port, void *p) } static uint16_t batman_timer_latch; -static int batman_timer = 0; +static int64_t batman_timer = 0; static void batman_timer_over(void *p) { batman_timer = 0; diff --git a/src/intel_flash.c b/src/intel_flash.c index 990c603ee..7da82f2ac 100644 --- a/src/intel_flash.c +++ b/src/intel_flash.c @@ -8,21 +8,27 @@ * * Implementation of the Intel 2 Mbit 8-bit flash devices. * - * Version: @(#)intel_flash.c 1.0.1 2017/08/23 + * Version: @(#)intel_flash.c 1.0.8 2017/10/14 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - +#include +#include +#include #include +#include #include "ibm.h" #include "cpu/cpu.h" #include "device.h" #include "mem.h" #include "machine/machine.h" -#include "rom.h" +#include "nvr.h" +#include "plat.h" + #define FLASH_IS_BXB 2 #define FLASH_INVERT 1 @@ -175,7 +181,7 @@ static void intel_flash_add_mappings_inverted(flash_t *flash) void *intel_flash_init(uint8_t type) { FILE *f; - int i; + int i, l; flash_t *flash; wchar_t *machine_name; wchar_t *flash_name; @@ -183,14 +189,16 @@ void *intel_flash_init(uint8_t type) flash = malloc(sizeof(flash_t)); memset(flash, 0, sizeof(flash_t)); - machine_name = (wchar_t *) malloc((strlen(machine_get_internal_name_ex(machine)) << 1) + 2); - mbstowcs(machine_name, machine_get_internal_name_ex(machine), strlen(machine_get_internal_name_ex(machine)) + 1); - flash_name = (wchar_t *) malloc((wcslen(machine_name) << 1) + 2 + 8); - _swprintf(flash_name, L"%s.bin", machine_name); + l = strlen(machine_get_internal_name_ex(machine)) + 1; + machine_name = (wchar_t *) malloc(l << 1); + mbstowcs(machine_name, machine_get_internal_name_ex(machine), l); + l = wcslen(machine_name) + 5; + flash_name = (wchar_t *) malloc(l << 1); + swprintf(flash_name, l, L"%s.bin", machine_name); wcscpy(flash_path, flash_name); - pclog_w(L"Flash path: %s\n", flash_name); + pclog("Flash path: %ls\n", flash_name); flash->flash_id = (type & FLASH_IS_BXB) ? 0x95 : 0x94; flash->invert_high_pin = (type & FLASH_INVERT); @@ -252,7 +260,7 @@ void *intel_flash_init(uint8_t type) flash->command = CMD_READ_ARRAY; flash->status = 0; - f = nvrfopen(flash_path, L"rb"); + f = nvr_fopen(flash_path, L"rb"); if (f) { fread(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f); @@ -295,7 +303,7 @@ void intel_flash_close(void *p) FILE *f; flash_t *flash = (flash_t *)p; - f = nvrfopen(flash_path, L"wb"); + f = nvr_fopen(flash_path, L"wb"); fwrite(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f); fwrite(&(flash->array[flash->block_start[BLOCK_DATA1]]), flash->block_len[BLOCK_DATA1], 1, f); fwrite(&(flash->array[flash->block_start[BLOCK_DATA2]]), flash->block_len[BLOCK_DATA2], 1, f); @@ -304,54 +312,43 @@ void intel_flash_close(void *p) free(flash); } + device_t intel_flash_bxt_ami_device = { "Intel 28F001BXT Flash BIOS", - 0, + 0, 0, intel_flash_bxt_ami_init, intel_flash_close, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, + NULL, NULL, NULL, NULL, NULL }; device_t intel_flash_bxb_ami_device = { "Intel 28F001BXB Flash BIOS", - 0, + 0, 0, intel_flash_bxb_ami_init, intel_flash_close, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, + NULL, NULL, NULL, NULL, NULL }; device_t intel_flash_bxt_device = { "Intel 28F001BXT Flash BIOS", - 0, + 0, 0, intel_flash_bxt_init, intel_flash_close, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, + NULL, NULL, NULL, NULL, NULL }; device_t intel_flash_bxb_device = { "Intel 28F001BXB Flash BIOS", - 0, + 0, 0, intel_flash_bxb_init, intel_flash_close, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/intel_sio.c b/src/intel_sio.c index 7210b1a2d..9dfe965ba 100644 --- a/src/intel_sio.c +++ b/src/intel_sio.c @@ -6,14 +6,17 @@ * * Emulation of Intel System I/O PCI chip. * - * Version: @(#)intel_sio.c 1.0.5 2017/09/03 + * Version: @(#)intel_sio.c 1.0.6 2017/09/24 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ +#include +#include #include +#include #include "ibm.h" #include "io.h" #include "dma.h" diff --git a/src/io.c b/src/io.c index dd10e42c9..6983b47ad 100644 --- a/src/io.c +++ b/src/io.c @@ -1,6 +1,10 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" @@ -69,6 +73,44 @@ void io_sethandler(uint16_t base, int size, } } +void io_sethandler_interleaved(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) +{ + int c; + size <<= 2; + for (c = 0; c < size; c += 2) + { + if (!port_inb[ base + c][0] && !port_inw[ base + c][0] && !port_inl[ base + c][0] && + !port_outb[base + c][0] && !port_outw[base + c][0] && !port_outl[base + c][0]) + { + port_inb[ base + c][0] = inb; + port_inw[ base + c][0] = inw; + port_inl[ base + c][0] = inl; + port_outb[base + c][0] = outb; + port_outw[base + c][0] = outw; + port_outl[base + c][0] = outl; + port_priv[base + c][0] = priv; + } + else if (!port_inb[ base + c][1] && !port_inw[ base + c][1] && !port_inl[ base + c][1] && + !port_outb[base + c][1] && !port_outw[base + c][1] && !port_outl[base + c][1]) + { + port_inb[ base + c][1] = inb; + port_inw[ base + c][1] = inw; + port_inl[ base + c][1] = inl; + port_outb[base + c][1] = outb; + port_outw[base + c][1] = outw; + port_outl[base + c][1] = outl; + port_priv[base + c][1] = priv; + } + } +} + void io_removehandler(uint16_t base, int size, uint8_t (*inb)(uint16_t addr, void *priv), uint16_t (*inw)(uint16_t addr, void *priv), @@ -116,11 +158,61 @@ void io_removehandler(uint16_t base, int size, } } +void io_removehandler_interleaved(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) +{ + int c; + size <<= 2; + for (c = 0; c < size; c += 2) + { + if (port_priv[base + c][0] == priv) + { + if (port_inb[ base + c][0] == inb) + port_inb[ base + c][0] = NULL; + if (port_inw[ base + c][0] == inw) + port_inw[ base + c][0] = NULL; + if (port_inl[ base + c][0] == inl) + port_inl[ base + c][0] = NULL; + if (port_outb[ base + c][0] == outb) + port_outb[ base + c][0] = NULL; + if (port_outw[ base + c][0] == outw) + port_outw[ base + c][0] = NULL; + if (port_outl[ base + c][0] == outl) + port_outl[ base + c][0] = NULL; + port_priv[base + c][0] = NULL; + } + if (port_priv[base + c][1] == priv) + { + if (port_inb[ base + c][1] == inb) + port_inb[ base + c][1] = NULL; + if (port_inw[ base + c][1] == inw) + port_inw[ base + c][1] = NULL; + if (port_inl[ base + c][1] == inl) + port_inl[ base + c][1] = NULL; + if (port_outb[ base + c][1] == outb) + port_outb[ base + c][1] = NULL; + if (port_outw[ base + c][1] == outw) + port_outw[ base + c][1] = NULL; + if (port_outl[ base + c][1] == outl) + port_outl[ base + c][1] = NULL; + port_priv[base + c][1] = NULL; + } + } +} + +#if 0 uint8_t cgamode,cgastat=0,cgacol; int hsync; uint8_t lpt2dat; int sw9; int t237=0; +#endif uint8_t inb(uint16_t port) { uint8_t temp = 0xff; diff --git a/src/io.h b/src/io.h index 384ca4662..1ff610788 100644 --- a/src/io.h +++ b/src/io.h @@ -11,7 +11,16 @@ extern void io_sethandler(uint16_t base, int size, void (*outw)(uint16_t addr, uint16_t val, void *priv), void (*outl)(uint16_t addr, uint32_t val, void *priv), void *priv); - + +extern void io_sethandler_interleaved(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); + extern void io_removehandler(uint16_t base, int size, uint8_t (*inb)(uint16_t addr, void *priv), uint16_t (*inw)(uint16_t addr, void *priv), @@ -20,3 +29,12 @@ extern void io_removehandler(uint16_t base, int size, void (*outw)(uint16_t addr, uint16_t val, void *priv), void (*outl)(uint16_t addr, uint32_t val, void *priv), void *priv); + +extern void io_removehandler_interleaved(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); diff --git a/src/keyboard.c b/src/keyboard.c index cf9729715..8a4bbdf5b 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -8,20 +8,26 @@ * * Host to guest keyboard interface and keyboard scan code sets. * - * Version: @(#)keyboard.c 1.0.1 2017/08/23 + * Version: @(#)keyboard.c 1.0.4 2017/10/10 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - +#include +#include +#include +#include #include "ibm.h" #include "plat_keyboard.h" #include "keyboard.h" + int keybsendcallback = 0; -int keybsenddelay; +int64_t keybsenddelay; + typedef struct { diff --git a/src/keyboard_amstrad.c b/src/keyboard_amstrad.c index 96273fa20..6ebbaa0f3 100644 --- a/src/keyboard_amstrad.c +++ b/src/keyboard_amstrad.c @@ -1,7 +1,10 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include #include +#include +#include #include "ibm.h" #include "io.h" #include "mem.h" @@ -45,12 +48,16 @@ void keyboard_amstrad_poll(void) keyboard_amstrad.wantirq = 0; keyboard_amstrad.pa = keyboard_amstrad.key_waiting; picint(2); +#if ENABLE_KEYBOARD_LOG pclog("keyboard_amstrad : take IRQ\n"); +#endif } if (key_queue_start != key_queue_end && !keyboard_amstrad.pa) { keyboard_amstrad.key_waiting = key_queue[key_queue_start]; +#if ENABLE_KEYBOARD_LOG pclog("Reading %02X from the key queue at %i\n", keyboard_amstrad.key_waiting, key_queue_start); +#endif key_queue_start = (key_queue_start + 1) & 0xf; keyboard_amstrad.wantirq = 1; } @@ -59,22 +66,30 @@ void keyboard_amstrad_poll(void) void keyboard_amstrad_adddata(uint8_t val) { key_queue[key_queue_end] = val; +#if ENABLE_KEYBOARD_LOG pclog("keyboard_amstrad : %02X added to key queue at %i\n", val, key_queue_end); +#endif key_queue_end = (key_queue_end + 1) & 0xf; return; } void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv) { +#if ENABLE_KEYBOARD_LOG pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, keyboard_amstrad.pb); +#endif switch (port) { case 0x61: +#if ENABLE_KEYBOARD_LOG pclog("keyboard_amstrad : pb write %02X %02X %i %02X %i\n", val, keyboard_amstrad.pb, !(keyboard_amstrad.pb & 0x40), keyboard_amstrad.pb & 0x40, (val & 0x40)); +#endif if (!(keyboard_amstrad.pb & 0x40) && (val & 0x40)) /*Reset keyboard*/ { +#if ENABLE_KEYBOARD_LOG pclog("keyboard_amstrad : reset keyboard\n"); +#endif keyboard_amstrad_adddata(0xaa); } keyboard_amstrad.pb = val; @@ -165,7 +180,9 @@ void keyboard_amstrad_reset(void) void keyboard_amstrad_init(void) { +#if ENABLE_KEYBOARD_LOG pclog("keyboard_amstrad_init\n"); +#endif io_sethandler(0x0060, 0x0006, keyboard_amstrad_read, NULL, NULL, keyboard_amstrad_write, NULL, NULL, NULL); keyboard_amstrad_reset(); keyboard_send = keyboard_amstrad_adddata; diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 7230189a9..2b98f21f6 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -8,19 +8,23 @@ * * Intel 8042 (AT keyboard controller) emulation. * - * Version: @(#)keyboard_at.c 1.0.2 2017/09/03 + * Version: @(#)keyboard_at.c 1.0.3 2017/09/24 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ +#include #include +#include +#include #include "ibm.h" #include "io.h" #include "pic.h" #include "pit.h" #include "mem.h" +#include "rom.h" #include "timer.h" #include "floppy/floppy.h" #include "floppy/fdc.h" @@ -43,7 +47,7 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -#define PS2_REFRESH_TIME (16 * TIMER_USEC) +#define PS2_REFRESH_TIME (16LL * TIMER_USEC) #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 @@ -84,7 +88,7 @@ struct void (*mouse_write)(uint8_t val, void *p); void *mouse_p; - int refresh_time; + int64_t refresh_time; int refresh; int is_ps2; @@ -141,7 +145,7 @@ void keyboard_at_log(const char *format, ...) static void keyboard_at_poll(void) { - keybsenddelay += (1000 * TIMER_USEC); + keybsenddelay += (1000LL * TIMER_USEC); if ((keyboard_at.out_new != -1) && !keyboard_at.last_irq) { diff --git a/src/keyboard_olim24.c b/src/keyboard_olim24.c index 3923483bf..371a104c3 100644 --- a/src/keyboard_olim24.c +++ b/src/keyboard_olim24.c @@ -1,4 +1,8 @@ +#include +#include +#include #include +#include #include "ibm.h" #include "io.h" #include "mem.h" @@ -45,16 +49,20 @@ static uint8_t mouse_scancodes[7]; static void keyboard_olim24_poll(void) { - keybsenddelay += (1000 * TIMER_USEC); + keybsenddelay += (1000LL * TIMER_USEC); if (keyboard_olim24.wantirq) { keyboard_olim24.wantirq = 0; picint(2); +#if ENABLE_KEYBOARD_LOG pclog("keyboard_olim24 : take IRQ\n"); +#endif } if (!(keyboard_olim24.status & STAT_OFULL) && key_queue_start != key_queue_end) { +#if ENABLE_KEYBOARD_LOG pclog("Reading %02X from the key queue at %i\n", keyboard_olim24.out, key_queue_start); +#endif keyboard_olim24.out = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; keyboard_olim24.status |= STAT_OFULL; @@ -68,14 +76,18 @@ void keyboard_olim24_adddata(uint8_t val) { key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; +#if ENABLE_KEYBOARD_LOG pclog("keyboard_olim24 : %02X added to key queue %02X\n", val, keyboard_olim24.status); +#endif return; } static void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv) { +#if ENABLE_KEYBOARD_LOG pclog("keyboard_olim24 : write %04X %02X\n", port, val); +#endif /* if (ram[8] == 0xc3) { output = 3; diff --git a/src/keyboard_pcjr.c b/src/keyboard_pcjr.c index 682c84ce7..ccd9986f2 100644 --- a/src/keyboard_pcjr.c +++ b/src/keyboard_pcjr.c @@ -1,7 +1,10 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include #include +#include +#include #include "ibm.h" #include "io.h" #include "mem.h" @@ -43,7 +46,7 @@ static int key_queue_start = 0, key_queue_end = 0; void keyboard_pcjr_poll() { - keybsenddelay += (220 * TIMER_USEC); + keybsenddelay += (220LL * TIMER_USEC); if (key_queue_start != key_queue_end && !keyboard_pcjr.serial_pos && !keyboard_pcjr.latched) diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index e0784e1c4..3e93125c9 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -1,10 +1,14 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include #include +#include +#include #include "ibm.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "pic.h" #include "pit.h" #include "timer.h" @@ -42,12 +46,14 @@ static int key_queue_start = 0, key_queue_end = 0; static void keyboard_xt_poll(void) { - keybsenddelay += (1000 * TIMER_USEC); + keybsenddelay += (1000LL * TIMER_USEC); if (key_queue_start != key_queue_end && !keyboard_xt.blocked) { keyboard_xt.pa = key_queue[key_queue_start]; picint(2); +#if ENABLE_KEYBOARD_LOG pclog("Reading %02X from the key queue at %i\n", keyboard_xt.pa, key_queue_start); +#endif key_queue_start = (key_queue_start + 1) & 0xf; keyboard_xt.blocked = 1; } @@ -56,7 +62,9 @@ static void keyboard_xt_poll(void) void keyboard_xt_adddata(uint8_t val) { key_queue[key_queue_end] = val; +#if ENABLE_KEYBOARD_LOG pclog("keyboard_xt : %02X added to key queue at %i\n", val, key_queue_end); +#endif key_queue_end = (key_queue_end + 1) & 0xf; return; } @@ -68,7 +76,9 @@ static void keyboard_xt_write(uint16_t port, uint8_t val, void *priv) case 0x61: if (!(keyboard_xt.pb & 0x40) && (val & 0x40)) /*Reset keyboard*/ { +#if ENABLE_KEYBOARD_LOG pclog("keyboard_xt : reset keyboard\n"); +#endif key_queue_end = key_queue_start; keyboard_xt_adddata(0xaa); } diff --git a/src/lnx/cdrom_ioctl_linux.c b/src/lnx/cdrom_ioctl_linux.c deleted file mode 100644 index bf1f73994..000000000 --- a/src/lnx/cdrom_ioctl_linux.c +++ /dev/null @@ -1,725 +0,0 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -/*Linux CD-ROM support via IOCTL*/ - -#include -#include -#include -#include -#include "ibm.h" -#include "ide.h" -#include "cdrom_ioctl.h" - -static ATAPI ioctl_atapi; - -static uint32_t last_block = 0; -static uint32_t cdrom_capacity = 0; -static int ioctl_inited = 0; -static char ioctl_path[8]; -static int tocvalid = 0; -static struct cdrom_tocentry toc[100]; -static int first_track, last_track; - -int old_cdrom_drive; - -#define MSFtoLBA(m,s,f) (((((m*60)+s)*75)+f)-150) - -enum -{ - CD_STOPPED = 0, - CD_PLAYING, - CD_PAUSED -}; - -static int ioctl_cd_state = CD_STOPPED; -static uint32_t ioctl_cd_pos = 0, ioctl_cd_end = 0; -#define BUF_SIZE 32768 -static int16_t cd_buffer[BUF_SIZE]; -static int cd_buflen = 0; -void ioctl_audio_callback(int16_t *output, int len) -{ - int fd; - struct cdrom_read_audio read_audio; - -// pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount()); - if (ioctl_cd_state != CD_PLAYING) - { - memset(output, 0, len * 2); - return; - } - fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (fd <= 0) - { - memset(output, 0, len * 2); - return; - } - - while (cd_buflen < len) - { - if (ioctl_cd_pos < ioctl_cd_end) - { - read_audio.addr.lba = ioctl_cd_pos - 150; - read_audio.addr_format = CDROM_LBA; - read_audio.nframes = 1; - read_audio.buf = (__u8 *)&cd_buffer[cd_buflen]; - - if (ioctl(fd, CDROMREADAUDIO, &read_audio) < 0) - { -// pclog("DeviceIoControl returned false\n"); - memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2); - ioctl_cd_state = CD_STOPPED; - cd_buflen = len; - } - else - { -// pclog("DeviceIoControl returned true\n"); - ioctl_cd_pos++; - cd_buflen += (2352 / 2); - } - } - else - { - memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2); - ioctl_cd_state = CD_STOPPED; - cd_buflen = len; - } - } - close(fd); - memcpy(output, cd_buffer, len * 2); -// for (c = 0; c < BUF_SIZE - len; c++) -// cd_buffer[c] = cd_buffer[c + cd_buflen]; - memcpy(&cd_buffer[0], &cd_buffer[len], (BUF_SIZE - len) * 2); - cd_buflen -= len; -// pclog("Done %i\n", GetTickCount()); -} - -void ioctl_audio_stop() -{ - ioctl_cd_state = CD_STOPPED; -} - -static int get_track_nr(uint32_t pos) -{ - int c; - int track = 0; - - if (!tocvalid) - return 0; - - for (c = first_track; c < last_track; c++) - { - uint32_t track_address = toc[c].cdte_addr.msf.frame + - (toc[c].cdte_addr.msf.second * 75) + - (toc[c].cdte_addr.msf.minute * 75 * 60); -//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address); - if (track_address <= pos) - track = c; - } - return track; -} - -static int is_track_audio(uint32_t pos) -{ - int c; - int control = 0; - - if (!tocvalid) - return 0; - - for (c = first_track; c < last_track; c++) - { - uint32_t track_address = toc[c].cdte_addr.msf.frame + - (toc[c].cdte_addr.msf.second * 75) + - (toc[c].cdte_addr.msf.minute * 75 * 60); -//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address); - if (track_address <= pos) - control = toc[c].cdte_ctrl; - } - return (control & 4) ? 0 : 1; -} - -static int ioctl_is_track_audio(uint32_t pos, int ismsf) -{ - if (ismsf) - { - int m = (pos >> 16) & 0xff; - int s = (pos >> 8) & 0xff; - int f = pos & 0xff; - pos = MSFtoLBA(m, s, f); - } - return is_track_audio(pos); -} - -static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf) -{ -// pclog("Play audio - %08X %08X %i\n", pos, len, ismsf); - if (ismsf) - { - pos = (pos & 0xff) + (((pos >> 8) & 0xff) * 75) + (((pos >> 16) & 0xff) * 75 * 60); - len = (len & 0xff) + (((len >> 8) & 0xff) * 75) + (((len >> 16) & 0xff) * 75 * 60); -// pclog("MSF - pos = %08X len = %08X\n", pos, len); - } - else - len += pos; - ioctl_cd_pos = pos;// + 150; - ioctl_cd_end = pos+len;// + 150; - ioctl_cd_state = CD_PLAYING; - if (ioctl_cd_pos < 150) - ioctl_cd_pos = 150; -// pclog("Audio start %08X %08X %i %i %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, 0, len); -} - -static void ioctl_pause(void) -{ - if (ioctl_cd_state == CD_PLAYING) - ioctl_cd_state = CD_PAUSED; -} - -static void ioctl_resume(void) -{ - if (ioctl_cd_state == CD_PAUSED) - ioctl_cd_state = CD_PLAYING; -} - -static void ioctl_stop(void) -{ - ioctl_cd_state = CD_STOPPED; -} - -static void ioctl_seek(uint32_t pos) -{ -// pclog("Seek %08X\n", pos); - ioctl_cd_pos = pos; - ioctl_cd_state = CD_STOPPED; -} - -static int read_toc(int fd, struct cdrom_tocentry *btoc) -{ - struct cdrom_tochdr toc_hdr; - int track, err; -//pclog("read_toc\n"); - err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr); - if (err == -1) - { - pclog("read_toc: CDROMREADTOCHDR failed\n"); - return 0; - } - - first_track = toc_hdr.cdth_trk0; - last_track = toc_hdr.cdth_trk1; -//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track); - memset(btoc, 0, sizeof(cdrom_tocentry)); - - for (track = toc_hdr.cdth_trk0; track <= toc_hdr.cdth_trk1; track++) - { - btoc[track].cdte_track = track; - btoc[track].cdte_format = CDROM_MSF; - err = ioctl(fd, CDROMREADTOCENTRY, &btoc[track]); - if (err == -1) - { -// pclog("read_toc: CDROMREADTOCENTRY failed on track %i\n", track); - return 0; - } -// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame); - } - return 1; -} - -static int ioctl_ready(void) -{ - long size; - int temp; - struct cdrom_tochdr toc_hdr; - struct cdrom_tocentry toc_entry; - int err; - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (fd <= 0) - return 0; - - err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr); - if (err == -1) - { - close(fd); - return 0; - } -// pclog("CDROMREADTOCHDR: start track=%i end track=%i\n", toc_hdr.cdth_trk0, toc_hdr.cdth_trk1); - toc_entry.cdte_track = toc_hdr.cdth_trk1; - toc_entry.cdte_format = CDROM_MSF; - err = ioctl(fd, CDROMREADTOCENTRY, &toc_entry); - if (err == -1) - { - close(fd); - return 0; - } -// pclog("CDROMREADTOCENTRY: addr=%02i:%02i:%02i\n", toc_entry.cdte_addr.msf.minute, toc_entry.cdte_addr.msf.second, toc_entry.cdte_addr.msf.frame); - if ((toc_entry.cdte_addr.msf.minute != toc[toc_hdr.cdth_trk1].cdte_addr.msf.minute) || - (toc_entry.cdte_addr.msf.second != toc[toc_hdr.cdth_trk1].cdte_addr.msf.second) || - (toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ) || - !tocvalid) - { - int track; - ioctl_cd_state = CD_STOPPED; - - tocvalid = read_toc(fd, toc); - close(fd); - return 1; - } - close(fd); - return 1; -} - -static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, int single) -{ - int c; - int lb = 0; - int tv = 0; - struct cdrom_tocentry lbtoc[100]; - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (fd <= 0) - return 0; - - ioctl_cd_state = CD_STOPPED; - - tv = read_toc(fd, lbtoc); - - close(fd); - - if (!tv) - return 0; - - last_block = 0; - for (c = 0; c <= last_track; c++) - { - uint32_t address; - address = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame); - if (address > last_block) - lb = address; - } - return lb; -} - -static int ioctl_medium_changed(void) -{ - long size; - int temp; - struct cdrom_tochdr toc_hdr; - struct cdrom_tocentry toc_entry; - int err; - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (fd <= 0) - return 0; - - err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr); - if (err == -1) - { - close(fd); - return 0; - } - toc_entry.cdte_track = toc_hdr.cdth_trk1; - toc_entry.cdte_format = CDROM_MSF; - err = ioctl(fd, CDROMREADTOCENTRY, &toc_entry); - if (err == -1) - { - close(fd); - return 0; - } -// pclog("CDROMREADTOCENTRY: addr=%02i:%02i:%02i\n", toc_entry.cdte_addr.msf.minute, toc_entry.cdte_addr.msf.second, toc_entry.cdte_addr.msf.frame); - if ((toc_entry.cdte_addr.msf.minute != toc[toc_hdr.cdth_trk1].cdte_addr.msf.minute) || - (toc_entry.cdte_addr.msf.second != toc[toc_hdr.cdth_trk1].cdte_addr.msf.second) || - (toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame )) - { - cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); - return 1; - } - return 0; -} - -static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf) -{ - struct cdrom_subchnl sub; - uint32_t cdpos = ioctl_cd_pos; - int track = get_track_nr(cdpos); - uint32_t track_address = toc[track].cdte_addr.msf.frame + - (toc[track].cdte_addr.msf.second * 75) + - (toc[track].cdte_addr.msf.minute * 75 * 60); - long size; - int pos=0; - int err; - uint8_t ret; -//pclog("ioctl_getsubchannel: cdpos=%x track_address=%x track=%i\n", cdpos, track_address, track); - if (ioctl_cd_state == CD_PLAYING) - ret = 0x11; - else if (ioctl_cd_state == CD_PAUSED) - ret = 0x12; - else - ret = 0x13; - - b[pos++] = (toc[track].cdte_adr << 4) | toc[track].cdte_ctrl; - b[pos++] = track; - b[pos++] = 0; - - if (msf) - { - uint32_t dat = cdpos; - b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; - b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; - b[pos + 1] = (uint8_t)dat; - b[pos] = 0; - pos += 4; - dat = cdpos - track_address; - b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; - b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; - b[pos + 1] = (uint8_t)dat; - b[pos] = 0; - pos += 4; - } - else - { - b[pos++] = (cdpos >> 24) & 0xff; - b[pos++] = (cdpos >> 16) & 0xff; - b[pos++] = (cdpos >> 8) & 0xff; - b[pos++] = cdpos & 0xff; - cdpos -= track_address; - b[pos++] = (cdpos >> 24) & 0xff; - b[pos++] = (cdpos >> 16) & 0xff; - b[pos++] = (cdpos >> 8) & 0xff; - b[pos++] = cdpos & 0xff; - } - - return ret; -} - -static void ioctl_eject(void) -{ - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (fd <= 0) - return; - - ioctl(fd, CDROMEJECT); - - close(fd); -} - -static void ioctl_load(void) -{ - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (fd <= 0) - return; - - ioctl(fd, CDROMEJECT); - - close(fd); - - cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); -} - -union -{ - struct cdrom_msf *msf; - char b[CD_FRAMESIZE_RAW]; -} raw_read_params; - -static int lba_to_msf(int lba) -{ - return (((lba / 75) / 60) << 16) + (((lba / 75) % 60) << 8) + (lba % 75); -} - -static int ioctl_sector_data_type(int sector, int ismsf) -{ - return 2; /* Always Mode 1 */ -} - -static void ioctl_readsector_raw(uint8_t *b, int sector) -{ - int err; - int imsf = lba_to_msf(sector); - int cdrom = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (cdrom <= 0) - return; - - raw_read_params.msf = malloc(sizeof(struct cdrom_msf)); - raw_read_params.msf->cdmsf_frame0 = imsf & 0xff; - raw_read_params.msf->cdmsf_sec0 = (imsf >> 8) & 0xff; - raw_read_params.msf->cdmsf_min0 = (imsf >> 16) & 0xff; - - /* This will read the actual raw sectors from the disc. */ - err = ioctl(cdrom, CDROMREADRAW, (void *) &raw_read_params); - if (err == -1) - { - pclog("read_toc: CDROMREADTOCHDR failed\n"); - return; - } - - memcpy(b, raw_read_params.b, 2352); - - close(cdrom); - - free(raw_read_params.msf); -} - -static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) -{ - int len=4; - long size; - int c,d; - uint32_t temp; - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (fd <= 0) - return 0; - - ioctl_cd_state = CD_STOPPED; - - tocvalid = read_toc(fd, toc); - - close(fd); - - if (!tocvalid) - return 4; - -// pclog("Read TOC done! %i\n",single); - b[2] = first_track; - b[3] = last_track; - d = 0; -//pclog("Read TOC starttrack=%i\n", starttrack); - for (c = 1; c <= last_track; c++) - { - if (toc[c].cdte_track >= starttrack) - { - d = c; - break; - } - } - b[2] = toc[c].cdte_track; - last_block = 0; - for (c = d; c <= last_track; c++) - { - uint32_t address; - if ((len + 8) > maxlen) - break; -// pclog("Len %i max %i Track %02X - %02X %02X %02i:%02i:%02i %08X\n",len,maxlen,toc[c].cdte_track,toc[c].cdte_adr,toc[c].cdte_ctrl,toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame,MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame)); - b[len++] = 0; /*Reserved*/ - b[len++] = (toc[c].cdte_adr << 4) | toc[c].cdte_ctrl; - b[len++] = toc[c].cdte_track; - b[len++] = 0; /*Reserved*/ - address = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame); - if (address > last_block) - last_block = address; - - if (msf) - { - b[len++] = 0; - b[len++] = toc[c].cdte_addr.msf.minute; - b[len++] = toc[c].cdte_addr.msf.second; - b[len++] = toc[c].cdte_addr.msf.frame; - } - else - { - temp = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame); - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - if (single) - break; - } - b[0] = (uint8_t)(((len-2) >> 8) & 0xff); - b[1] = (uint8_t)((len-2) & 0xff); -/* pclog("Table of Contents (%i bytes) : \n", size); - pclog("First track - %02X\n", first_track); - pclog("Last track - %02X\n", last_track); - for (c = 0; c <= last_track; c++) - pclog("Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", c, toc[c].cdte_track, toc[c].cdte_ctrl, toc[c].cdte_adr, 0, toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame); - for (c = 0;c <= last_track; c++) - pclog("Track %02X - number %02X control %02X adr %02X address %06X\n", c, toc[c].cdte_track, toc[c].cdte_ctrl, toc[c].cdte_adr, MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame));*/ - return len; -} - -static int ioctl_readtoc_session(unsigned char *b, int msf, int maxlen) -{ - struct cdrom_multisession session; - int len = 4; - int err; - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - - if (fd <= 0) - return 0; - - session.addr_format = CDROM_MSF; - err = ioctl(fd, CDROMMULTISESSION, &session); - - if (err == -1) - { - close(fd); - return 0; - } - - b[2] = 0; - b[3] = 0; - b[len++] = 0; /*Reserved*/ - b[len++] = (toc[0].cdte_adr << 4) | toc[0].cdte_ctrl; - b[len++] = toc[0].cdte_track; - b[len++] = 0; /*Reserved*/ - if (msf) - { - b[len++] = 0; - b[len++] = session.addr.msf.minute; - b[len++] = session.addr.msf.second; - b[len++] = session.addr.msf.frame; - } - else - { - uint32_t temp = MSFtoLBA(session.addr.msf.minute, session.addr.msf.second, session.addr.msf.frame); - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - - return len; -} - -static int ioctl_readtoc_raw(unsigned char *b, int maxlen) -{ - struct cdrom_tochdr toc_hdr; - struct cdrom_tocentry toc2[100]; - int track, err; - int len = 4; - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); -//pclog("read_toc\n"); - if (fd <= 0) - return 0; - - err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr); - if (err == -1) - { - pclog("read_toc: CDROMREADTOCHDR failed\n"); - return 0; - } - - b[2] = toc_hdr.cdth_trk0; - b[3] = toc_hdr.cdth_trk1; - - //pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track); - memset(toc, 0, sizeof(toc)); - - for (track = toc_hdr.cdth_trk0; track <= toc_hdr.cdth_trk1; track++) - { - if ((len + 11) > maxlen) - { - pclog("ioctl_readtocraw: This iteration would fill the buffer beyond the bounds, aborting...\n"); - close(fd); - return len; - } - - toc2[track].cdte_track = track; - toc2[track].cdte_format = CDROM_MSF; - err = ioctl(fd, CDROMREADTOCENTRY, &toc2[track]); - if (err == -1) - { -// pclog("read_toc: CDROMREADTOCENTRY failed on track %i\n", track); - close(fd); - return 0; - } -// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame); - - b[len++] = toc2[track].cdte_track; - b[len++]= (toc2[track].cdte_adr << 4) | toc[track].cdte_ctrl; - b[len++]=0; - b[len++]=0; - b[len++]=0; - b[len++]=0; - b[len++]=0; - b[len++]=0; - b[len++] = toc2[track].cdte_addr.msf.minute; - b[len++] = toc2[track].cdte_addr.msf.second; - b[len++] = toc2[track].cdte_addr.msf.frame; - } - close(fd); - return len; -} - -static uint32_t ioctl_size() -{ - return cdrom_capacity; -} - -static int ioctl_status() -{ - if (!(ioctl_ready) && (cdrom_drive <= 0)) return CD_STATUS_EMPTY; - - switch(ioctl_cd_state) - { - case CD_PLAYING: - return CD_STATUS_PLAYING; - case CD_PAUSED: - return CD_STATUS_PAUSED; - case CD_STOPPED: - return CD_STATUS_STOPPED; - } -} -void ioctl_reset() -{ - int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); -//pclog("ioctl_reset: fd=%i\n", fd); - tocvalid = 0; - - if (fd <= 0) - return; - - tocvalid = read_toc(fd, toc); - - close(fd); -} - -int ioctl_open(char d) -{ - atapi=&ioctl_atapi; - return 0; -} - -void ioctl_close(void) -{ -} - -static void ioctl_exit(void) -{ - ioctl_stop(); - ioctl_inited = 0; - tocvalid=0; -} - -static ATAPI ioctl_atapi= -{ - ioctl_ready, - ioctl_medium_changed, - ioctl_readtoc, - ioctl_readtoc_session, - ioctl_readtoc_raw, - ioctl_getcurrentsubchannel, - NULL, - NULL, - NULL, - ioctl_sector_data_type, - ioctl_readsector_raw, - ioctl_playaudio, - ioctl_seek, - ioctl_load, - ioctl_eject, - ioctl_pause, - ioctl_resume, - ioctl_size, - ioctl_status, - ioctl_is_track_audio, - ioctl_stop, - ioctl_exit -}; diff --git a/src/lnx/lnx_thread.c b/src/lnx/lnx_thread.c deleted file mode 100644 index d9f16a0ef..000000000 --- a/src/lnx/lnx_thread.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include -#include -#include -#include -#include "plat_thread.h" - - -typedef struct { - pthread_cond_t cond; - pthread_mutex_t mutex; -} event_pthread_t; - - -thread_t *thread_create(void (*thread_rout)(void *param), void *param) -{ - pthread_t *thread = malloc(sizeof(pthread_t)); - - if (thread != NULL) - pthread_create(thread, NULL, thread_rout, param); - - return(thread); -} - - -void thread_kill(thread_t *handle) -{ - pthread_t *thread = (pthread_t *)handle; - - if (thread != NULL) { - pthread_cancel(*thread); - pthread_join(*thread, NULL); - - free(thread); - } -} - - -event_t *thread_create_event(void) -{ - event_pthread_t *event = malloc(sizeof(event_pthread_t)); - - if (event != NULL) { - pthread_cond_init(&event->cond, NULL); - pthread_mutex_init(&event->mutex, NULL); - } - - return((event_t *)event); -} - - -void thread_set_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - if (event != NULL) { - pthread_mutex_lock(&event->mutex); - pthread_cond_broadcast(&event->cond); - pthread_mutex_unlock(&event->mutex); - } -} - - -void thread_reset_event(event_t *handle) -{ -} - - -int thread_wait_event(event_t *handle, int timeout) -{ - event_pthread_t *event = (event_pthread_t *)handle; - struct timespec abstime; - - clock_gettime(CLOCK_REALTIME, &abstime); - abstime.tv_nsec += (timeout % 1000) * 1000000; - abstime.tv_sec += (timeout / 1000); - if (abstime.tv_nsec > 1000000000) { - abstime.tv_nsec -= 1000000000; - abstime.tv_sec++; - } - - pthread_mutex_lock(&event->mutex); - pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); - pthread_mutex_unlock(&event->mutex); - - return(0); -} - - -void thread_destroy_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - if (event != NULL) { - pthread_cond_destroy(&event->cond); - pthread_mutex_destroy(&event->mutex); - - free(event); - } -} - - -void thread_sleep(int t) -{ - usleep(t * 1000); -} diff --git a/src/lnx/plat_thread.h b/src/lnx/plat_thread.h deleted file mode 100644 index dfb3a9c26..000000000 --- a/src/lnx/plat_thread.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#ifndef PLAT_THREAD_H -# define PLAT_THREAD_H - - -typedef void thread_t; -typedef void event_t; - - -extern thread_t *thread_create(void (*thread_rout)(void *param), void *param); -extern void thread_kill(thread_t *handle); - -extern event_t *thread_create_event(void); -extern void thread_set_event(event_t *event); -extern void thread_reset_event(event_t *_event); -extern int thread_wait_event(event_t *event, int timeout); -extern void thread_destroy_event(event_t *_event); - -extern void thread_sleep(int t); - - -#endif /*PLAT_THREAD_H*/ diff --git a/src/lpt.c b/src/lpt.c index 459346bf0..b510f62ce 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -1,15 +1,20 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" - #include "lpt.h" #include "sound/snd_lpt_dac.h" #include "sound/snd_lpt_dss.h" + char lpt1_device_name[16]; + static struct { char name[64]; diff --git a/src/machine/machine.c b/src/machine/machine.c index 6f9d905b2..04d9540e4 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -8,55 +8,29 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.c 1.0.11 2017/09/03 + * Version: @(#)machine.c 1.0.19 2017/10/12 * * Authors: Sarah Walker, * Miran Grca, + * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. */ -#include #include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" -#include "../io.h" +#include "../mem.h" +#include "../rom.h" #include "../device.h" #include "../floppy/floppy.h" #include "../floppy/fdc.h" #include "../floppy/fdd.h" #include "machine.h" -#include "machine_common.h" - -#include "machine_amstrad.h" -#include "machine_europc.h" -#include "machine_olivetti_m24.h" -#include "machine_pcjr.h" -#include "machine_tandy.h" - -#include "machine_xt.h" -#include "machine_xt_laserxt.h" - -#include "machine_at.h" -#include "machine_at_ali1429.h" -#include "machine_at_commodore.h" -#include "machine_at_headland.h" -#include "machine_at_neat.h" -#include "machine_at_opti495.h" -#include "machine_at_scat.h" -#include "machine_at_wd76c10.h" - -#include "machine_ps1.h" -#include "machine_ps2_isa.h" -#include "machine_ps2_mca.h" - -#include "machine_at_sis_85c471.h" -#include "machine_at_sis_85c496.h" - -#include "machine_at_430lx_nx.h" -#include "machine_at_430fx.h" -#include "machine_at_430hx.h" -#include "machine_at_430vx.h" -#include "machine_at_440fx.h" #include "../video/vid_pcjr.h" #include "../video/vid_tandy.h" @@ -72,192 +46,202 @@ int romset; machine_t machines[] = { - {"[8088] AMI XT clone", ROM_AMIXT, "amixt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, machine_xt_init, NULL }, - {"[8088] Compaq Portable", ROM_PORTABLE, "portable", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 128, 640, 128, 0, machine_xt_init, NULL }, - {"[8088] DTK XT clone", ROM_DTKXT, "dtk", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, machine_xt_init, NULL }, - {"[8088] IBM PC", ROM_IBMPC, "ibmpc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 32, 0, machine_xt_init, NULL }, - {"[8088] IBM PCjr", ROM_IBMPCJR, "ibmpcjr", {{"", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, 0, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, - {"[8088] IBM XT", ROM_IBMXT, "ibmxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, machine_xt_init, NULL }, - {"[8088] Generic XT clone", ROM_GENXT, "genxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, machine_xt_init, NULL }, - {"[8088] Juko XT clone", ROM_JUKOPC, "jukopc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, machine_xt_init, NULL }, - {"[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 640, 64, 0, machine_xt_init, NULL }, - {"[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 512, 640, 128, 0, machine_europc_init, NULL }, - {"[8088] Tandy 1000", ROM_TANDY, "tandy", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, 0, 128, 640, 128, 0, machine_tandy1k_init, tandy1000_get_device }, - {"[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, 0, 256, 640, 128, 0, machine_tandy1k_init, tandy1000hx_get_device }, - {"[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 1152, 64, 0, machine_xt_laserxt_init, NULL }, - {"[8088] VTech Laser XT3", ROM_LXT3, "lxt3", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 64, 1152, 64, 0, machine_xt_laserxt_init, NULL }, + {"[8088] AMI XT clone", ROM_AMIXT, "amixt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + {"[8088] Compaq Portable", ROM_PORTABLE, "portable", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 128, 640, 128, 0, machine_xt_init, NULL }, + {"[8088] DTK XT clone", ROM_DTKXT, "dtk", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + {"[8088] IBM PC", ROM_IBMPC, "ibmpc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_xt_init, NULL }, + {"[8088] IBM PCjr", ROM_IBMPCJR, "ibmpcjr", {{"", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, + {"[8088] IBM XT", ROM_IBMXT, "ibmxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + {"[8088] Generic XT clone", ROM_GENXT, "genxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + {"[8088] Juko XT clone", ROM_JUKOPC, "jukopc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + {"[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + {"[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"Siemens",cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HAS_HDC, 512, 640, 128, 0, machine_europc_init, NULL }, + {"[8088] Tandy 1000", ROM_TANDY, "tandy", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, tandy1000_get_device }, + {"[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, tandy1000hx_get_device }, + {"[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 1152, 64, 0, machine_xt_laserxt_init, NULL }, + {"[8088] VTech Laser XT3", ROM_LXT3, "lxt3", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 1152, 64, 0, machine_xt_laserxt_init, NULL }, - {"[8086] Amstrad PC1512", ROM_PC1512, "pc1512", {{"", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_AMSTRAD, 512, 640, 128, 63, machine_amstrad_init, NULL }, - {"[8086] Amstrad PC1640", ROM_PC1640, "pc1640", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_AMSTRAD, 640, 640, 0, 63, machine_amstrad_init, NULL }, - {"[8086] Amstrad PC2086", ROM_PC2086, "pc2086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_AMSTRAD, 640, 640, 0, 63, machine_amstrad_init, NULL }, - {"[8086] Amstrad PC3086", ROM_PC3086, "pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_AMSTRAD, 640, 640, 0, 63, machine_amstrad_init, NULL }, - {"[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_OLIM24, 128, 640, 128, 0, machine_olim24_init, NULL }, - {"[8086] Sinclair PC200", ROM_PC200, "pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_AMSTRAD, 512, 640, 128, 63, machine_amstrad_init, NULL }, - {"[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, 0, 512, 768, 128, 0, machine_tandy1ksl2_init, NULL }, + {"[8086] Amstrad PC1512", ROM_PC1512, "pc1512", {{"", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AMSTRAD, 512, 640, 128, 63, machine_amstrad_init, NULL }, + {"[8086] Amstrad PC1640", ROM_PC1640, "pc1640", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AMSTRAD, 640, 640, 0, 63, machine_amstrad_init, NULL }, + {"[8086] Amstrad PC2086", ROM_PC2086, "pc2086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AMSTRAD, 640, 640, 0, 63, machine_amstrad_init, NULL }, + {"[8086] Amstrad PC3086", ROM_PC3086, "pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AMSTRAD, 640, 640, 0, 63, machine_amstrad_init, NULL }, + {"[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_OLIM24, 128, 640, 128, 0, machine_olim24_init, NULL }, + {"[8086] Sinclair PC200", ROM_PC200, "pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AMSTRAD, 512, 640, 128, 63, machine_amstrad_init, NULL }, + {"[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1ksl2_init, NULL }, - {"[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 512,16384, 128, 127, machine_at_neat_init, NULL }, - {"[286 ISA] Award 286 clone", ROM_AWARD286, "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 512,16384, 128, 127, machine_at_scat_init, NULL }, - {"[286 ISA] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 640,16384, 128, 127, machine_at_cmdpc_init, NULL }, - {"[286 ISA] Hyundai Super-286TR", ROM_SUPER286TR, "super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 512,16384, 128, 127, machine_at_scat_init, NULL }, - {"[286 ISA] IBM AT", ROM_IBMAT, "ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT, 256,15872, 128, 63, machine_at_top_remap_init, NULL }, - {"[286 ISA] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD, 512,16384, 512, 127, machine_ps1_m2011_init, NULL }, - {"[286 ISA] IBM PS/2 model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, - {"[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE, 512,16384, 128, 127, machine_at_scat_init, NULL }, + {"[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_neat_init, NULL }, + {"[286 ISA] Award 286 clone", ROM_AWARD286, "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL }, + {"[286 ISA] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_cmdpc_init, NULL }, + {"[286 ISA] Hyundai Super-286TR", ROM_SUPER286TR, "super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL }, + {"[286 ISA] IBM AT", ROM_IBMAT, "ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_top_remap_init, NULL }, + {"[286 ISA] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD, 512,16384, 512, 127, machine_ps1_m2011_init, NULL }, + {"[286 ISA] IBM PS/2 model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, + {"[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 0, machine_at_top_remap_init, NULL }, + {"[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512,16384, 128, 127, machine_at_scat_init, NULL }, - {"[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD | MACHINE_MCA, 1, 16, 1, 63, machine_ps2_model_50_init, NULL }, + {"[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD, 1, 16, 1, 63, machine_ps2_model_50_init, NULL }, - {"[386SX ISA] AMI 386SX clone", ROM_AMI386SX, "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 512,16384, 128, 127, machine_at_headland_init, NULL }, - {"[386SX ISA] Amstrad MegaPC", ROM_MEGAPC, "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE, 1, 16, 1, 127, machine_at_wd76c10_init, NULL }, - {"[386SX ISA] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award386sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 1, 64, 1, 127, machine_at_opti495_init, NULL }, - {"[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 512,16384, 128, 127, machine_at_neat_init, NULL }, - {"[386SX ISA] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE, 1, 16, 1, 127, machine_ps1_m2121_init, NULL }, - {"[386SX ISA] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE, 1, 16, 1, 127, machine_ps1_m2121_init, NULL }, + {"[386SX ISA] AMI 386SX clone", ROM_AMI386SX, "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL }, + {"[386SX ISA] Amstrad MegaPC", ROM_MEGAPC, "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 1, 16, 1, 127, machine_at_wd76c10_init, NULL }, + {"[386SX ISA] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award386sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, + {"[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 512,16384, 128, 127, machine_at_neat_init, NULL }, + {"[386SX ISA] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 1, 16, 1, 127, machine_ps1_m2121_init, NULL }, + {"[386SX ISA] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 1, 16, 1, 127, machine_ps1_m2121_init, NULL }, - {"[386SX MCA] IBM PS/2 model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD | MACHINE_MCA, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, + {"[386SX MCA] IBM PS/2 model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, - {"[386DX ISA] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 1, 64, 1, 127, machine_at_opti495_init, NULL }, - {"[386DX ISA] Amstrad MegaPC 386DX", ROM_MEGAPCDX, "megapcdx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE, 1, 16, 1, 127, machine_at_wd76c10_init, NULL }, - {"[386DX ISA] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 1, 64, 1, 127, machine_at_opti495_init, NULL }, - {"[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 1, 64, 1, 127, machine_at_opti495_init, NULL }, + {"[386DX ISA] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, + {"[386DX ISA] Amstrad MegaPC 386DX", ROM_MEGAPCDX, "megapcdx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 1, 16, 1, 127, machine_at_wd76c10_init, NULL }, + {"[386DX ISA] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, + {"[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, - {"[386DX MCA] IBM PS/2 model 80", ROM_IBMPS2_M80, "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD | MACHINE_MCA, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, + {"[386DX MCA] IBM PS/2 model 80", ROM_IBMPS2_M80, "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, - {"[486 ISA] AMI 486 clone", ROM_AMI486, "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 1, 64, 1, 127, machine_at_ali1429_init, NULL }, - {"[486 ISA] AMI WinBIOS 486", ROM_WIN486, "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 1, 64, 1, 127, machine_at_ali1429_init, NULL }, - {"[486 ISA] Award 486 clone", ROM_AWARD486_OPTI495, "award486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 1, 64, 1, 127, machine_at_opti495_init, NULL }, - {"[486 ISA] DTK PKM-0038S E-2", ROM_DTK486, "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE, 1, 128, 1, 127, machine_at_dtk486_init, NULL }, - {"[486 ISA] IBM PS/1 machine 2133", ROM_IBMPS1_2133, "ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, + {"[486 ISA] AMI 486 clone", ROM_AMI486, "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 1, 64, 1, 127, machine_at_ali1429_init, NULL }, + {"[486 ISA] AMI WinBIOS 486", ROM_WIN486, "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 1, 64, 1, 127, machine_at_ali1429_init, NULL }, + {"[486 ISA] Award 486 clone", ROM_AWARD486_OPTI495, "award486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, + {"[486 ISA] DTK PKM-0038S E-2", ROM_DTK486, "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HAS_HDC, 1, 128, 1, 127, machine_at_dtk486_init, NULL }, + {"[486 ISA] IBM PS/1 machine 2133", ROM_IBMPS1_2133, "ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, - {"[486 MCA] IBM PS/2 model 80-486", ROM_IBMPS2_M80_486, "ibmps2_m80-486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 1, MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD | MACHINE_MCA, 1, 32, 1, 63, machine_ps2_model_80_486_init, NULL }, + {"[486 MCA] IBM PS/2 model 80-486", ROM_IBMPS2_M80_486, "ibmps2_m80-486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_PS2_HDD, 1, 32, 1, 63, machine_ps2_model_80_486_init, NULL }, - {"[486 PCI] Rise Computer R418", ROM_R418, "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE | MACHINE_PCI, 1, 255, 1, 127, machine_at_r418_init, NULL }, + {"[486 PCI] Rise Computer R418", ROM_R418, "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HAS_HDC, 1, 255, 1, 127, machine_at_r418_init, NULL }, - {"[Socket 4 LX] Intel Premiere/PCI", ROM_REVENGE, "revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 2, 128, 2, 127, machine_at_batman_init, NULL }, + {"[Socket 4 LX] Intel Premiere/PCI", ROM_REVENGE, "revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL }, - {"[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 2, 128, 2, 127, machine_at_plato_init, NULL }, + {"[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL }, - {"[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL }, - {"[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_endeavor_init, NULL }, - {"[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_zappa_init, NULL }, - {"[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, - {"[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_president_init, NULL }, + {"[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL }, + {"[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_endeavor_init, NULL }, + {"[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL }, + {"[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, + {"[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_president_init, NULL }, - {"[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_thor_init, NULL }, - {"[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_thor_init, NULL }, + {"[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, + {"[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, - {"[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, - {"[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 192, 8, 127, machine_at_acerv35n_init, NULL }, - {"[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 512, 8, 127, machine_at_ap53_init, NULL }, - {"[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 512, 8, 127, machine_at_p55t2p4_init, NULL }, - {"[Socket 7 HX] SuperMicro Super P55T2S",ROM_P55T2S, "p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, + {"[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, + {"[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL }, + {"[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL }, + {"[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 512, 8, 127, machine_at_p55t2p4_init, NULL }, + {"[Socket 7 HX] SuperMicro Super P55T2S",ROM_P55T2S, "p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, - {"[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL }, - {"[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, - {"[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 128, 8, 127, machine_at_p55va_init, NULL }, + {"[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL }, + {"[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, + {"[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL }, - {"[Socket 8 FX] Tyan Titan-Pro AT", ROM_440FX, "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 1024, 8, 127, machine_at_i440fx_init, NULL }, - {"[Socket 8 FX] Tyan Titan-Pro ATX", ROM_S1668, "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_IDE | MACHINE_PCI, 8, 1024, 8, 127, machine_at_s1668_init, NULL }, - {"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0,0, 0 } + {"[Socket 8 FX] Tyan Titan-Pro AT", ROM_440FX, "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL }, + {"[Socket 8 FX] Tyan Titan-Pro ATX", ROM_S1668, "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HAS_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL }, + {"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0,0, 0 } }; -int machine_count(void) +void +machine_init(void) { - return (sizeof(machines) / sizeof(machine)) - 1; + pclog("Initializing as \"%s\"\n", machine_getname()); + + /* Set up the architecture flags. */ + AT = IS_ARCH(machine, MACHINE_AT); + PCI = IS_ARCH(machine, MACHINE_PCI); + AMSTRAD = IS_ARCH(machine, MACHINE_AMSTRAD); + TANDY = 0; + + /* Load the machine's ROM BIOS. */ + rom_load_bios(romset); + mem_add_bios(); + + if (machines[machine].get_device) + device_add(machines[machine].get_device()); + + machines[machine].init(&machines[machine]); } -int machine_getromset(void) +int +machine_count(void) { - return machines[machine].id; + return((sizeof(machines) / sizeof(machine)) - 1); } -int machine_getromset_ex(int m) +int +machine_getromset(void) { - return machines[m].id; + return(machines[machine].id); } -int machine_getmachine(int romset) +int +machine_getromset_ex(int m) { - int c = 0; - - while (machines[c].id != -1) - { - if (machines[c].id == romset) - return c; - c++; - } - - return 0; + return(machines[m].id); } -char *machine_getname(void) +int +machine_getmachine(int romset) { - return machines[machine].name; + int c = 0; + + while (machines[c].id != -1) { + if (machines[c].id == romset) + return(c); + c++; + } + + return(0); } -device_t *machine_getdevice(int machine) +char * +machine_getname(void) { - if (machines[machine].get_device) - { - return machines[machine].get_device(); - } - else - { - return NULL; - } + return(machines[machine].name); } -char *machine_get_internal_name(void) +device_t * +machine_getdevice(int machine) { - return machines[machine].internal_name; + if (machines[machine].get_device) + return(machines[machine].get_device()); + + return(NULL); } -char *machine_get_internal_name_ex(int m) +char * +machine_get_internal_name(void) { - return machines[m].internal_name; + return(machines[machine].internal_name); } -int machine_get_nvrmask(int m) +char * +machine_get_internal_name_ex(int m) { - return machines[m].nvrmask; + return(machines[m].internal_name); } -int machine_get_machine_from_internal_name(char *s) +int +machine_get_nvrmask(int m) { - int c = 0; - - while (machines[c].id != -1) - { - if (!strcmp(machines[c].internal_name, s)) - return c; - c++; - } - - return 0; + return(machines[m].nvrmask); } -void machine_init(void) +int +machine_get_machine_from_internal_name(char *s) { - pclog("Initializing as %s\n", machine_getname()); + int c = 0; - AMSTRAD = AT = PCI = TANDY = 0; + while (machines[c].id != -1) { + if (!strcmp(machines[c].internal_name, s)) + return(c); + c++; + } - io_init(); - - fdc_update_is_nsc(0); - - machines[machine].init(); - - if (machines[machine].get_device) - device_add(machines[machine].get_device()); + return(0); } diff --git a/src/machine/machine.h b/src/machine/machine.h index 52fc9659e..590d13a07 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,45 +8,65 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.3 2017/09/02 + * Version: @(#)machine.h 1.0.7 2017/10/12 * * Authors: Sarah Walker, * Miran Grca, + * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. */ #ifndef EMU_MACHINE_H # define EMU_MACHINE_H -#define MACHINE_AT 1 -#define MACHINE_PS2 2 -#define MACHINE_AMSTRAD 4 -#define MACHINE_OLIM24 8 -#define MACHINE_HAS_IDE 16 -#define MACHINE_MCA 32 -#define MACHINE_PCI 64 -#define MACHINE_PS2_HDD 128 -#define MACHINE_NEC 256 -#define MACHINE_FUJITSU 512 -#define MACHINE_RM 1024 +/* Machine feature flags. */ +#define MACHINE_PC 0x000000 /* PC architecture */ +#define MACHINE_AT 0x000001 /* PC/AT architecture */ +#define MACHINE_PS2 0x000002 /* PS/2 architecture */ +#define MACHINE_ISA 0x000010 /* machine has ISA bus */ +#define MACHINE_CBUS 0x000020 /* machine has C-BUS bus */ +#define MACHINE_EISA 0x000040 /* machine has EISA bus */ +#define MACHINE_VLB 0x000080 /* machine has VL bus */ +#define MACHINE_MCA 0x000100 /* machine has MCA bus */ +#define MACHINE_PCI 0x000200 /* machine has PCI */ +#define MACHINE_AGP 0x000400 /* machine has AGP */ +#define MACHINE_HAS_HDC 0x001000 /* machine has internal HDC */ +#define MACHINE_PS2_HDD 0x002000 // can now remove? --FvK +#define MACHINE_NEC 0x010000 +#define MACHINE_FUJITSU 0x020000 +#define MACHINE_AMSTRAD 0x040000 +#define MACHINE_OLIM24 0x080000 +#define MACHINE_RM 0x100000 + +#define IS_ARCH(m, a) (machines[(m)].flags & (a)) ? 1 : 0; -typedef struct { +typedef struct _machine_ { char name[64]; int id; char internal_name[24]; struct { char name[16]; +#ifdef EMU_CPU_H CPU *cpus; +#else + void *cpus; +#endif } cpu[5]; int fixed_gfxcard; int flags; int min_ram, max_ram; int ram_granularity; int nvrmask; - void (*init)(void); + void (*init)(struct _machine_ *); +#ifdef EMU_DEVICE_H device_t *(*get_device)(void); +#else + void *get_device; +#endif } machine_t; @@ -63,7 +83,9 @@ extern char *machine_getname(void); extern char *machine_get_internal_name(void); extern int machine_get_machine_from_internal_name(char *s); extern void machine_init(void); +#ifdef EMU_DEVICE_H extern device_t *machine_getdevice(int machine); +#endif extern int machine_getromset_ex(int m); extern char *machine_get_internal_name_ex(int m); extern int machine_get_nvrmask(int m); @@ -76,4 +98,72 @@ extern mouse_t mouse_olim24; #endif +/* Initialization functions for boards and systems. */ +extern void machine_common_init(machine_t *); + +extern void machine_at_init(machine_t *); +extern void machine_at_ide_init(machine_t *); +extern void machine_at_top_remap_init(machine_t *); +extern void machine_at_ide_top_remap_init(machine_t *); + +extern void machine_at_p54tp4xe_init(machine_t *); +extern void machine_at_endeavor_init(machine_t *); +extern void machine_at_zappa_init(machine_t *); +extern void machine_at_mb500n_init(machine_t *); +extern void machine_at_president_init(machine_t *); +extern void machine_at_thor_init(machine_t *); + +extern void machine_at_acerm3a_init(machine_t *); +extern void machine_at_acerv35n_init(machine_t *); +extern void machine_at_ap53_init(machine_t *); +extern void machine_at_p55t2p4_init(machine_t *); +extern void machine_at_p55t2s_init(machine_t *); + +extern void machine_at_batman_init(machine_t *); +extern void machine_at_plato_init(machine_t *); + +extern void machine_at_p55tvp4_init(machine_t *); +extern void machine_at_i430vx_init(machine_t *); +extern void machine_at_p55va_init(machine_t *); + +extern void machine_at_i440fx_init(machine_t *); +extern void machine_at_s1668_init(machine_t *); +extern void machine_at_ali1429_init(machine_t *); +extern void machine_at_cmdpc_init(machine_t *); + +extern void machine_at_headland_init(machine_t *); +extern void machine_at_neat_init(machine_t *); +extern void machine_at_opti495_init(machine_t *); +extern void machine_at_scat_init(machine_t *); + +extern void machine_at_dtk486_init(machine_t *); +extern void machine_at_r418_init(machine_t *); + +extern void machine_at_wd76c10_init(machine_t *); + +extern void machine_ps1_m2011_init(machine_t *); +extern void machine_ps1_m2121_init(machine_t *); +extern void machine_ps1_m2133_init(machine_t *); +extern void machine_ps2_m30_286_init(machine_t *); + +extern void machine_ps2_model_50_init(machine_t *); +extern void machine_ps2_model_55sx_init(machine_t *); +extern void machine_ps2_model_80_init(machine_t *); +extern void machine_ps2_model_80_486_init(machine_t *); + +extern void machine_amstrad_init(machine_t *); + +extern void machine_europc_init(machine_t *); + +extern void machine_olim24_init(machine_t *); + +extern void machine_pcjr_init(machine_t *); + +extern void machine_tandy1k_init(machine_t *); +extern void machine_tandy1ksl2_init(machine_t *); + +extern void machine_xt_init(machine_t *); +extern void machine_xt_laserxt_init(machine_t *); + + #endif /*EMU_MACHINE_H*/ diff --git a/src/machine/machine_amstrad.c b/src/machine/machine_amstrad.c index 7808f4086..d2eb674cf 100644 --- a/src/machine/machine_amstrad.c +++ b/src/machine/machine_amstrad.c @@ -1,12 +1,16 @@ +#include +#include +#include #include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../io.h" #include "../nmi.h" #include "../mem.h" +#include "../rom.h" #include "../device.h" #include "../nvr.h" -#include "../gameport.h" +#include "../game/gameport.h" #include "../keyboard.h" #include "../keyboard_amstrad.h" #include "../mouse.h" @@ -14,7 +18,7 @@ #include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" -#include "machine_common.h" +#include "machine.h" static uint8_t amstrad_dead; @@ -131,15 +135,17 @@ static void amstrad_init(void) } -void machine_amstrad_init(void) +void +machine_amstrad_init(machine_t *model) { - AMSTRAD = 1; + machine_common_init(model); - machine_common_init(); - mem_add_bios(); amstrad_init(); keyboard_amstrad_init(); - nvr_init(); + + /* FIXME: make sure this is correct? */ + nvr_at_init(1); + nmi_init(); fdc_set_dskchg_activelow(); if (joystick_type != 7) diff --git a/src/machine/machine_amstrad.h b/src/machine/machine_amstrad.h deleted file mode 100644 index d2ba5d483..000000000 --- a/src/machine/machine_amstrad.h +++ /dev/null @@ -1 +0,0 @@ -void machine_amstrad_init(void); diff --git a/src/machine/machine_at.c b/src/machine/machine_at.c index 93483af9c..0c6faab0c 100644 --- a/src/machine/machine_at.c +++ b/src/machine/machine_at.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../pic.h" #include "../pit.h" @@ -6,47 +10,60 @@ #include "../device.h" #include "../nvr.h" #include "../bugger.h" -#include "../gameport.h" +#include "../game/gameport.h" #include "../keyboard_at.h" #include "../lpt.h" -#include "../hdd/hdd_ide_at.h" -#include "machine_common.h" -#include "machine_at.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" +#include "machine.h" -void machine_at_init(void) +void +machine_at_init(machine_t *model) { - AT = 1; + machine_common_init(model); - machine_common_init(); - if (lpt_enabled) - lpt2_remove(); - mem_add_bios(); - pit_set_out_func(&pit, 1, pit_refresh_timer_at); - dma16_init(); - keyboard_at_init(); - nvr_init(); - pic2_init(); - if (joystick_type != 7) - device_add(&gameport_device); - if (bugger_enabled) - bugger_init(); + pit_set_out_func(&pit, 1, pit_refresh_timer_at); + pic2_init(); + dma16_init(); + + if (lpt_enabled) + lpt2_remove(); + + nvr_at_init(8); + + keyboard_at_init(); + + if (joystick_type != 7) + device_add(&gameport_device); + + if (bugger_enabled) + bugger_init(); } -void machine_at_ide_init(void) + +void +machine_at_ide_init(machine_t *model) { - machine_at_init(); - ide_init(); + machine_at_init(model); + + ide_init(); } -void machine_at_top_remap_init(void) + +void +machine_at_top_remap_init(machine_t *model) { - machine_at_init(); - mem_remap_top_384k(); + machine_at_init(model); + + mem_remap_top_384k(); } -void machine_at_ide_top_remap_init(void) + +void +machine_at_ide_top_remap_init(machine_t *model) { - machine_at_ide_init(); - mem_remap_top_384k(); + machine_at_ide_init(model); + + mem_remap_top_384k(); } diff --git a/src/machine/machine_at.h b/src/machine/machine_at.h deleted file mode 100644 index 5d6c91ca4..000000000 --- a/src/machine/machine_at.h +++ /dev/null @@ -1,4 +0,0 @@ -void machine_at_init(void); -void machine_at_ide_init(void); -void machine_at_top_remap_init(void); -void machine_at_ide_top_remap_init(void); diff --git a/src/machine/machine_at_430fx.c b/src/machine/machine_at_430fx.c index bc2aa9900..e50ad18cf 100644 --- a/src/machine/machine_at_430fx.c +++ b/src/machine/machine_at_430fx.c @@ -8,25 +8,28 @@ * * Implementation of the Intel 430FX PCISet chip. * - * Version: @(#)machine_at_430fx.c 1.0.4 2017/09/03 + * Version: @(#)machine_at_430fx.c 1.0.6 2017/10/07 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ +#include +#include #include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../mem.h" #include "../memregs.h" +#include "../rom.h" #include "../pci.h" #include "../device.h" #include "../piix.h" #include "../intel_flash.h" #include "../sio.h" -#include "machine_at.h" -#include "machine_at_430fx.h" +#include "machine.h" static uint8_t card_i430fx[256]; @@ -194,9 +197,11 @@ static void i430fx_init(void) } -void machine_at_p54tp4xe_init(void) +void +machine_at_p54tp4xe_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -208,13 +213,16 @@ void machine_at_p54tp4xe_init(void) i430fx_init(); piix3_init(7); fdc37c665_init(); + device_add(&intel_flash_bxt_device); } -void machine_at_endeavor_init(void) +void +machine_at_endeavor_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -227,13 +235,16 @@ void machine_at_endeavor_init(void) i430fx_init(); piix_init(7); pc87306_init(); + device_add(&intel_flash_bxt_ami_device); } -void machine_at_zappa_init(void) +void +machine_at_zappa_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -244,13 +255,16 @@ void machine_at_zappa_init(void) i430fx_init(); piix_init(7); pc87306_init(); + device_add(&intel_flash_bxt_ami_device); } -void machine_at_mb500n_init(void) +void +machine_at_mb500n_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -261,13 +275,16 @@ void machine_at_mb500n_init(void) i430fx_init(); piix_init(7); fdc37c665_init(); + device_add(&intel_flash_bxt_device); } -void machine_at_president_init(void) +void +machine_at_president_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -279,13 +296,16 @@ void machine_at_president_init(void) i430fx_init(); piix_init(7); w83877f_init(); + device_add(&intel_flash_bxt_device); } -void machine_at_thor_init(void) +void +machine_at_thor_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -298,5 +318,6 @@ void machine_at_thor_init(void) i430fx_init(); piix_init(7); pc87306_init(); + device_add(&intel_flash_bxt_ami_device); } diff --git a/src/machine/machine_at_430fx.h b/src/machine/machine_at_430fx.h deleted file mode 100644 index bb4949910..000000000 --- a/src/machine/machine_at_430fx.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Header of the implementation of the Intel 430FX PCISet chip. - * - * Version: @(#)machine_at_430fx.h 1.0.0 2017/09/02 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. - */ -void machine_at_p54tp4xe_init(void); -void machine_at_endeavor_init(void); -void machine_at_zappa_init(void); -void machine_at_mb500n_init(void); -void machine_at_president_init(void); -void machine_at_thor_init(void); diff --git a/src/machine/machine_at_430hx.c b/src/machine/machine_at_430hx.c index 508aba2a0..ca110dd60 100644 --- a/src/machine/machine_at_430hx.c +++ b/src/machine/machine_at_430hx.c @@ -8,16 +8,19 @@ * * Implementation of the Intel 430HX PCISet chip. * - * Version: @(#)machine_at_430hx.c 1.0.4 2017/09/03 + * Version: @(#)machine_at_430hx.c 1.0.6 2017/10/07 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016-2017 Miran Grca. */ +#include +#include #include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" #include "../memregs.h" @@ -26,8 +29,7 @@ #include "../piix.h" #include "../intel_flash.h" #include "../sio.h" -#include "machine_at.h" -#include "machine_at_430hx.h" +#include "machine.h" static uint8_t card_i430hx[256]; @@ -182,9 +184,11 @@ static void i430hx_init(void) } -void machine_at_acerm3a_init(void) +void +machine_at_acerm3a_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + powermate_memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -197,13 +201,16 @@ void machine_at_acerm3a_init(void) i430hx_init(); piix3_init(7); fdc37c932fr_init(); + device_add(&intel_flash_bxb_device); } -void machine_at_acerv35n_init(void) +void +machine_at_acerv35n_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + powermate_memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -216,13 +223,16 @@ void machine_at_acerv35n_init(void) i430hx_init(); piix3_init(7); fdc37c932fr_init(); + device_add(&intel_flash_bxb_device); } -void machine_at_ap53_init(void) +void +machine_at_ap53_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); powermate_memregs_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -236,13 +246,16 @@ void machine_at_ap53_init(void) i430hx_init(); piix3_init(7); fdc37c669_init(); + device_add(&intel_flash_bxt_device); } -void machine_at_p55t2p4_init(void) +void +machine_at_p55t2p4_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -254,13 +267,16 @@ void machine_at_p55t2p4_init(void) i430hx_init(); piix3_init(7); w83877f_init(); + device_add(&intel_flash_bxt_device); } -void machine_at_p55t2s_init(void) +void +machine_at_p55t2s_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); powermate_memregs_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -273,5 +289,6 @@ void machine_at_p55t2s_init(void) i430hx_init(); piix3_init(7); pc87306_init(); + device_add(&intel_flash_bxt_device); } diff --git a/src/machine/machine_at_430hx.h b/src/machine/machine_at_430hx.h deleted file mode 100644 index 6c38b0898..000000000 --- a/src/machine/machine_at_430hx.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Header of the implementation of the Intel 430HX PCISet chip. - * - * Version: @(#)machine_at_430hx.h 1.0.0 2017/09/02 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. - */ -void machine_at_acerm3a_init(void); -void machine_at_acerv35n_init(void); -void machine_at_ap53_init(void); -void machine_at_p55t2p4_init(void); -void machine_at_p55t2s_init(void); diff --git a/src/machine/machine_at_430lx_nx.c b/src/machine/machine_at_430lx_nx.c index 981e62aab..2f7530435 100644 --- a/src/machine/machine_at_430lx_nx.c +++ b/src/machine/machine_at_430lx_nx.c @@ -8,26 +8,29 @@ * * Implementation of the Intel 430LX and 430NX PCISet chips. * - * Version: @(#)machine_at_430lx_nx.c 1.0.4 2017/09/03 + * Version: @(#)machine_at_430lx_nx.c 1.0.6 2017/10/07 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include #include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../mem.h" #include "../memregs.h" +#include "../rom.h" #include "../pci.h" #include "../device.h" #include "../intel.h" #include "../intel_flash.h" #include "../intel_sio.h" #include "../sio.h" -#include "machine_at.h" -#include "machine_at_430lx_nx.h" +#include "machine.h" static uint8_t card_i430_lx_nx[256]; @@ -206,9 +209,11 @@ static void i430nx_init(void) } -static void machine_at_premiere_common_init(void) +static void +machine_at_premiere_common_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -220,19 +225,24 @@ static void machine_at_premiere_common_init(void) sio_init(2); fdc37c665_init(); intel_batman_init(); + device_add(&intel_flash_bxt_ami_device); } -void machine_at_batman_init(void) +void +machine_at_batman_init(machine_t *model) { - machine_at_premiere_common_init(); + machine_at_premiere_common_init(model); + i430lx_init(); } -void machine_at_plato_init(void) +void +machine_at_plato_init(machine_t *model) { - machine_at_premiere_common_init(); + machine_at_premiere_common_init(model); + i430nx_init(); } diff --git a/src/machine/machine_at_430lx_nx.h b/src/machine/machine_at_430lx_nx.h deleted file mode 100644 index ce08d96f7..000000000 --- a/src/machine/machine_at_430lx_nx.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Header of the implementation of the Intel 430LX and 430NX - * PCISet chips. - * - * Version: @(#)machine_at_430lx_nx.h 1.0.0 2017/09/02 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. - */ -void machine_at_batman_init(void); -void machine_at_plato_init(void); diff --git a/src/machine/machine_at_430vx.c b/src/machine/machine_at_430vx.c index 3f8971cc5..54171e2a4 100644 --- a/src/machine/machine_at_430vx.c +++ b/src/machine/machine_at_430vx.c @@ -8,16 +8,19 @@ * * Implementation of the Intel 430VX PCISet chip. * - * Version: @(#)machine_at_430vx.c 1.0.5 2017/09/03 + * Version: @(#)machine_at_430vx.c 1.0.7 2017/10/07 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include #include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../io.h" #include "../pci.h" #include "../mem.h" @@ -26,8 +29,7 @@ #include "../piix.h" #include "../intel_flash.h" #include "../sio.h" -#include "machine_at.h" -#include "machine_at_430vx.h" +#include "machine.h" static uint8_t card_i430vx[256]; @@ -185,9 +187,11 @@ void i430vx_init(void) } -void machine_at_p55tvp4_init(void) +void +machine_at_p55tvp4_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -199,13 +203,16 @@ void machine_at_p55tvp4_init(void) i430vx_init(); piix3_init(7); w83877f_init(); + device_add(&intel_flash_bxt_device); } -void machine_at_i430vx_init(void) +void +machine_at_i430vx_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -217,13 +224,16 @@ void machine_at_i430vx_init(void) i430vx_init(); piix3_init(7); um8669f_init(); + device_add(&intel_flash_bxt_device); } -void machine_at_p55va_init(void) +void +machine_at_p55va_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -234,5 +244,6 @@ void machine_at_p55va_init(void) i430vx_init(); piix3_init(7); fdc37c932fr_init(); + device_add(&intel_flash_bxt_device); } diff --git a/src/machine/machine_at_430vx.h b/src/machine/machine_at_430vx.h deleted file mode 100644 index 5d930e8c4..000000000 --- a/src/machine/machine_at_430vx.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Header of the implementation of the Intel 430VX PCISet chip. - * - * Version: @(#)machine_at_430vx.h 1.0.0 2017/09/02 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. - */ -void machine_at_p55tvp4_init(void); -void machine_at_i430vx_init(void); -void machine_at_p55va_init(void); diff --git a/src/machine/machine_at_440fx.c b/src/machine/machine_at_440fx.c index cd42685e6..fcb579111 100644 --- a/src/machine/machine_at_440fx.c +++ b/src/machine/machine_at_440fx.c @@ -8,16 +8,19 @@ * * Implementation of the Intel 440FX PCISet chip. * - * Version: @(#)machine_at_440fx.c 1.0.4 2017/09/03 + * Version: @(#)machine_at_440fx.c 1.0.6 2017/10/07 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include #include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../io.h" #include "../pci.h" #include "../mem.h" @@ -26,8 +29,7 @@ #include "../piix.h" #include "../intel_flash.h" #include "../sio.h" -#include "machine_at.h" -#include "machine_at_440fx.h" +#include "machine.h" static uint8_t card_i440fx[256]; @@ -186,9 +188,11 @@ static void i440fx_init(void) } -void machine_at_i440fx_init(void) +void +machine_at_i440fx_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -201,13 +205,16 @@ void machine_at_i440fx_init(void) i440fx_init(); piix3_init(7); fdc37c665_init(); + device_add(&intel_flash_bxt_device); } -void machine_at_s1668_init(void) +void +machine_at_s1668_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -220,5 +227,6 @@ void machine_at_s1668_init(void) i440fx_init(); piix3_init(7); fdc37c665_init(); + device_add(&intel_flash_bxt_device); } diff --git a/src/machine/machine_at_440fx.h b/src/machine/machine_at_440fx.h deleted file mode 100644 index 3ee3d50bc..000000000 --- a/src/machine/machine_at_440fx.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Header of the implementation of the Intel 440FX PCISet chip. - * - * Version: @(#)machine_at_440fx.h 1.0.0 2017/09/02 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. - */ -void machine_at_i440fx_init(void); -void machine_at_s1668_init(void); diff --git a/src/machine/machine_at_ali1429.c b/src/machine/machine_at_ali1429.c index d991dfb06..36c689419 100644 --- a/src/machine/machine_at_ali1429.c +++ b/src/machine/machine_at_ali1429.c @@ -1,14 +1,18 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include #include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" -#include "../hdd/hdd_ide_at.h" -#include "machine_at.h" -#include "machine_at_ali1429.h" +#include "../device.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" +#include "machine.h" static int ali1429_index; @@ -89,11 +93,14 @@ static void ali1429_init(void) io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, NULL); } -void machine_at_ali1429_init(void) + +void +machine_at_ali1429_init(machine_t *model) { ali1429_reset(); - machine_at_ide_init(); + machine_at_ide_init(model); + ali1429_init(); secondary_ide_check(); diff --git a/src/machine/machine_at_ali1429.h b/src/machine/machine_at_ali1429.h deleted file mode 100644 index 03bfacd7a..000000000 --- a/src/machine/machine_at_ali1429.h +++ /dev/null @@ -1 +0,0 @@ -void machine_at_ali1429_init(void); diff --git a/src/machine/machine_at_commodore.c b/src/machine/machine_at_commodore.c index 5651fdb96..05bcbad86 100644 --- a/src/machine/machine_at_commodore.c +++ b/src/machine/machine_at_commodore.c @@ -1,9 +1,12 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../io.h" #include "../lpt.h" #include "../serial.h" -#include "machine_at.h" -#include "machine_at_commodore.h" +#include "machine.h" static void cbm_io_write(uint16_t port, uint8_t val, void *p) @@ -38,8 +41,11 @@ static void cbm_io_init() io_sethandler(0x0230, 0x0001, NULL,NULL,NULL, cbm_io_write,NULL,NULL, NULL); } -void machine_at_cmdpc_init(void) + +void +machine_at_cmdpc_init(machine_t *model) { - machine_at_ide_top_remap_init(); + machine_at_ide_top_remap_init(model); + cbm_io_init(); } diff --git a/src/machine/machine_at_commodore.h b/src/machine/machine_at_commodore.h deleted file mode 100644 index 5d3e0c5a0..000000000 --- a/src/machine/machine_at_commodore.h +++ /dev/null @@ -1 +0,0 @@ -void machine_at_cmdpc_init(void); diff --git a/src/machine/machine_at_compaq.c b/src/machine/machine_at_compaq.c index 098b6c350..9ed973abb 100644 --- a/src/machine/machine_at_compaq.c +++ b/src/machine/machine_at_compaq.c @@ -1,11 +1,14 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../mem.h" -#include "machine_at.h" -#include "machine_at_compaq.h" +#include "machine.h" /* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */ diff --git a/src/machine/machine_at_compaq.h b/src/machine/machine_at_compaq.h deleted file mode 100644 index 14aeeac86..000000000 --- a/src/machine/machine_at_compaq.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * Emulation of the Compaq chips. - * - * Version: @(#)machine_at_compaq.h 1.0.0 2017/09/02 - * - * Author: Miran Grca, - * Copyright 2017 Miran Grca. - */ diff --git a/src/machine/machine_at_headland.c b/src/machine/machine_at_headland.c index b5f5ae512..74778e83f 100644 --- a/src/machine/machine_at_headland.c +++ b/src/machine/machine_at_headland.c @@ -1,12 +1,15 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" -#include "machine_at.h" -#include "machine_at_headland.h" +#include "machine.h" static int headland_index; @@ -52,8 +55,10 @@ static void headland_init(void) } -void machine_at_headland_init(void) +void +machine_at_headland_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + headland_init(); } diff --git a/src/machine/machine_at_headland.h b/src/machine/machine_at_headland.h deleted file mode 100644 index 054294427..000000000 --- a/src/machine/machine_at_headland.h +++ /dev/null @@ -1 +0,0 @@ -void machine_at_headland_init(void); diff --git a/src/machine/machine_at_neat.c b/src/machine/machine_at_neat.c index 4e69a1d02..d43872a16 100644 --- a/src/machine/machine_at_neat.c +++ b/src/machine/machine_at_neat.c @@ -2,11 +2,13 @@ see COPYING for more details */ /*This is the chipset used in the AMI 286 clone model*/ +#include +#include +#include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../io.h" -#include "machine_at.h" -#include "machine_at_neat.h" +#include "machine.h" static uint8_t neat_regs[256]; @@ -81,8 +83,10 @@ static void neat_init(void) } -void machine_at_neat_init(void) +void +machine_at_neat_init(machine_t *model) { - machine_at_ide_init(); + machine_at_init(model); + neat_init(); } diff --git a/src/machine/machine_at_neat.h b/src/machine/machine_at_neat.h deleted file mode 100644 index c736bde13..000000000 --- a/src/machine/machine_at_neat.h +++ /dev/null @@ -1 +0,0 @@ -void machine_at_neat_init(void); diff --git a/src/machine/machine_at_opti495.c b/src/machine/machine_at_opti495.c index f838efd2a..7570c7922 100644 --- a/src/machine/machine_at_opti495.c +++ b/src/machine/machine_at_opti495.c @@ -251,12 +251,15 @@ Note: the block address is forced to be a multiple of the block size by ignoring the appropriate number of the least-significant bits SeeAlso: #P0178,#P0187 */ +#include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" -#include "machine_at.h" -#include "machine_at_opti495.h" +#include "machine.h" static uint8_t optiregs[0x10]; @@ -315,8 +318,10 @@ static void opti495_init(void) } -void machine_at_opti495_init(void) +void +machine_at_opti495_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + opti495_init(); } diff --git a/src/machine/machine_at_opti495.h b/src/machine/machine_at_opti495.h deleted file mode 100644 index 38862e579..000000000 --- a/src/machine/machine_at_opti495.h +++ /dev/null @@ -1 +0,0 @@ -void machine_at_opti495_init(void); diff --git a/src/machine/machine_at_scat.c b/src/machine/machine_at_scat.c index 35bba379b..26ecdb6d5 100644 --- a/src/machine/machine_at_scat.c +++ b/src/machine/machine_at_scat.c @@ -1,556 +1,765 @@ -/*This is the chipset used in the Award 286 clone model*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of Chips&Technology's SCAT (82C235) chipset. + * + * Re-worked version based on the 82C235 datasheet and errata. + * + * Version: @(#)at_scat.c 1.0.2 2017/10/07 + * + * Authors: Original by GreatPsycho for PCem. + * Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../cpu/x86.h" #include "../io.h" #include "../mem.h" -#include "machine_at.h" -#include "machine_at_scat.h" +#include "machine.h" -#define SCAT_DMA_WAIT_STATE_CONTROL 0x01 -#define SCAT_VERSION 0x40 -#define SCAT_CLOCK_CONTROL 0x41 -#define SCAT_PERIPHERAL_CONTROL 0x44 -#define SCAT_MISCELLANEOUS_STATUS 0x45 -#define SCAT_POWER_MANAGEMENT 0x46 -#define SCAT_ROM_ENABLE 0x48 -#define SCAT_RAM_WRITE_PROTECT 0x49 -#define SCAT_SHADOW_RAM_ENABLE_1 0x4A -#define SCAT_SHADOW_RAM_ENABLE_2 0x4B -#define SCAT_SHADOW_RAM_ENABLE_3 0x4C -#define SCAT_DRAM_CONFIGURATION 0x4D -#define SCAT_EXTENDED_BOUNDARY 0x4E -#define SCAT_EMS_CONTROL 0x4F +#define SCAT_DEBUG 2 -typedef struct scat_t +#define SCAT_DMA_WS_CTL 0x01 +#define SCAT_VERSION 0x40 +#define SCAT_CLOCK_CTL 0x41 +#define SCAT_PERIPH_CTL 0x44 +#define SCAT_MISC_STATUS 0x45 +#define SCAT_POWER_MGMT 0x46 +#define SCAT_ROM_ENABLE 0x48 +#define SCAT_RAM_WR_PROTECT 0x49 +#define SCAT_SHADOW_RAM_EN_1 0x4a +#define SCAT_SHADOW_RAM_EN_2 0x4b +#define SCAT_SHADOW_RAM_EN_3 0x4c +#define SCAT_DRAM_CONFIG 0x4d +#define SCAT_EXT_BOUNDARY 0x4e +#define SCAT_EMS_CTL 0x4f +#define SCAT_SYS_CTL 0x7f /* port 92 */ + + +typedef struct { + uint8_t regs_2x8; + uint8_t regs_2x9; +} ems_t; + + +static uint8_t scat_regs[128]; +static int scat_index; +static uint32_t scat_xms_bound; +static uint8_t scat_ems_reg = 0; +static ems_t scat_ems[32]; /* EMS page regs */ +static mem_mapping_t scat_mapping[32]; /* EMS pages */ +static mem_mapping_t scat_top_mapping[24]; /* top 384K mapping */ +static mem_mapping_t scat_A000_mapping; /* A000-C000 mapping */ +static mem_mapping_t scat_shadowram_mapping[6]; /* BIOS shadowing */ +static mem_mapping_t scat_high_mapping[16]; /* >1M mapping */ + + +static void +shadow_state_update(void) { - uint8_t regs_2x8; - uint8_t regs_2x9; -} scat_t; + int i, val; -static uint8_t scat_regs[256]; -static int scat_index; -static uint8_t scat_port_92 = 0; -static uint8_t scat_ems_reg_2xA = 0; -static mem_mapping_t scat_mapping[32]; -static mem_mapping_t scat_high_mapping[16]; -static scat_t scat_stat[32]; -static uint32_t scat_xms_bound; -static mem_mapping_t scat_shadowram_mapping[6]; -static mem_mapping_t scat_4000_9FFF_mapping[24]; -static mem_mapping_t scat_A000_BFFF_mapping; + /* TODO - ROMCS enable features should be implemented later. */ + for (i=0; i<24; i++) { + val = ((scat_regs[SCAT_SHADOW_RAM_EN_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL; + if (i < 8) { + val |= ((scat_regs[SCAT_SHADOW_RAM_EN_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; + } else { + if ((scat_regs[SCAT_RAM_WR_PROTECT] >> ((i - 8) >> 1)) & 1) + val |= MEM_WRITE_DISABLED; + else + val |= ((scat_regs[SCAT_SHADOW_RAM_EN_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; + } + mem_set_mem_state((i + 40) << 14, 0x4000, val); + } - -uint8_t scat_read(uint16_t port, void *priv); -void scat_write(uint16_t port, uint8_t val, void *priv); - - -void scat_shadow_state_update(void) -{ - int i, val; - - /* TODO - ROMCS enable features should be implemented later. */ - for (i = 0; i < 24; i++) - { - val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL; - if (i < 8) - { - val |= ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; - } - else - { - if ((scat_regs[SCAT_RAM_WRITE_PROTECT] >> ((i - 8) >> 1)) & 1) - { - val |= MEM_WRITE_DISABLED; - } - else - { - val |= ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; - } - } - mem_set_mem_state((i + 40) << 14, 0x4000, val); - } - - flushmmucache(); + flushmmucache(); } -void scat_set_xms_bound(uint8_t val) +static void +set_xms_bound(uint8_t val) { - uint32_t max_xms_size = (mem_size >= 16384) ? 0xFC0000 : mem_size << 10; - int i; + uint32_t max_xms, max_mem; + int i; - switch (val & 0x0F) - { - case 1: - scat_xms_bound = 0x100000; - break; - case 2: - scat_xms_bound = 0x140000; - break; - case 3: - scat_xms_bound = 0x180000; - break; - case 4: - scat_xms_bound = 0x200000; - break; - case 5: - scat_xms_bound = 0x300000; - break; - case 6: - scat_xms_bound = 0x400000; - break; - case 7: - scat_xms_bound = 0x600000; - break; - case 8: - scat_xms_bound = 0x800000; - break; - case 9: - scat_xms_bound = 0xA00000; - break; - case 10: - scat_xms_bound = 0xC00000; - break; - case 11: - scat_xms_bound = 0xE00000; - break; - default: - scat_xms_bound = (mem_size >= 16384 ? 0xFC0000 : mem_size << 10); - break; - } + max_mem = (mem_size << 10); + max_xms = (mem_size >= 16384) ? 0xFC0000 : max_mem; + pclog("SCAT: set_xms_bound(%02x): max_mem=%d, max_xms=%d\n", + val, max_mem, max_xms); - if ((val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) - { - if (val != 1) - { - if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping); - for(i=0;i<6;i++) - mem_mapping_enable(&scat_shadowram_mapping[i]); - if ((val & 0x0F) == 0) - scat_xms_bound = 0x160000; - } - else - { - for(i=0;i<6;i++) - mem_mapping_disable(&scat_shadowram_mapping[i]); - if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); - } - pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, (0x160000 - scat_xms_bound) >> 10); - if (scat_xms_bound > 0x100000) - mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (scat_xms_bound < 0x160000) - mem_set_mem_state(scat_xms_bound, 0x160000 - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } - else - { - for(i=0;i<6;i++) - mem_mapping_disable(&scat_shadowram_mapping[i]); - if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); + switch (val & 0x0f) { + case 1: + scat_xms_bound = 0x100000; + break; - if (scat_xms_bound > max_xms_size) - scat_xms_bound = max_xms_size; - pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, ((mem_size << 10) - scat_xms_bound) >> 10); - if (scat_xms_bound > 0x100000) - mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (scat_xms_bound < (mem_size << 10)) - mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } -} + case 2: + scat_xms_bound = 0x140000; + break; + case 3: + scat_xms_bound = 0x180000; + break; -uint32_t get_scat_addr(uint32_t addr, scat_t *p) -{ - if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80)) - { - addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; - } + case 4: + scat_xms_bound = 0x200000; + break; - if (mem_size < 2048 && ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 7 || (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) != 0)) - addr = (addr & ~0x780000) | ((addr & 0x600000) >> 2); - else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) - { - addr &= ~0x600000; - if(mem_size > 2048 || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 6)) - addr |= (addr & 0x180000) << 2; - } + case 5: + scat_xms_bound = 0x300000; + break; - if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) - addr ^= mem_size < 2048 ? 0x1F0000 : 0x670000; - return addr; -} + case 6: + scat_xms_bound = 0x400000; + break; + case 7: + scat_xms_bound = 0x600000; + break; -void scat_memmap_state_update(void) -{ - int i; - uint32_t addr; + case 8: + scat_xms_bound = 0x800000; + break; - for(i=16;i<24;i++) - { - addr = get_scat_addr(0x40000 + (i << 14), NULL); - mem_mapping_set_exec(&scat_4000_9FFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); - } - addr = get_scat_addr(0xA0000, NULL); - mem_mapping_set_exec(&scat_A000_BFFF_mapping, addr < (mem_size << 10) ? ram + addr : NULL); - for(i=0;i<6;i++) - { - addr = get_scat_addr(0x100000 + (i << 16), NULL); - mem_mapping_set_exec(&scat_shadowram_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); - } + case 9: + scat_xms_bound = 0xA00000; + break; - flushmmucache(); -} + case 10: + scat_xms_bound = 0xC00000; + break; + case 11: + scat_xms_bound = 0xE00000; + break; -void scat_set_global_EMS_state(int state) -{ - int i; - uint32_t base_addr, virt_addr; + default: + scat_xms_bound = max_xms; + break; + } - for(i=0; i<32; i++) - { - base_addr = (i + 16) << 14; - if(i >= 24) - base_addr += 0x30000; - if(state && (scat_stat[i].regs_2x9 & 0x80)) - { - virt_addr = get_scat_addr(base_addr, &scat_stat[i]); - if(i < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[i]); - mem_mapping_enable(&scat_mapping[i]); - if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[i], ram + virt_addr); - else mem_mapping_set_exec(&scat_mapping[i], NULL); - } - else - { - mem_mapping_set_exec(&scat_mapping[i], ram + base_addr); - mem_mapping_disable(&scat_mapping[i]); - if(i < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[i]); - } - } -} + if ((val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIG] & 0x0f) == 3) { + if (val != 1) { + if (mem_size > 1024) + mem_mapping_disable(&ram_high_mapping); + for (i=0; i<6; i++) + mem_mapping_enable(&scat_shadowram_mapping[i]); + if ((val & 0x0f) == 0) + scat_xms_bound = 0x160000; + } else { + for (i=0; i<6; i++) + mem_mapping_disable(&scat_shadowram_mapping[i]); + if (mem_size > 1024) + mem_mapping_enable(&ram_high_mapping); + } + pclog("SCAT: set XMS bound(%02X) = %06X (%dK for EMS)\n", + val, scat_xms_bound, (0x160000-scat_xms_bound)>>10); - -void scat_write(uint16_t port, uint8_t val, void *priv) -{ - uint8_t scat_reg_valid = 0, scat_shadow_update = 0, scat_map_update = 0, index; - uint32_t base_addr, virt_addr; - - switch (port) - { - case 0x22: - scat_index = val; - break; - - case 0x23: - switch (scat_index) - { - case SCAT_CLOCK_CONTROL: - case SCAT_PERIPHERAL_CONTROL: - scat_reg_valid = 1; - break; - case SCAT_EMS_CONTROL: - if(val & 0x40) - { - if(val & 1) - { - io_sethandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - } - else - { - io_sethandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - } - } - else - { - io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - } - scat_set_global_EMS_state(val & 0x80); - scat_reg_valid = 1; - break; - case SCAT_POWER_MANAGEMENT: - val &= 0x40; - scat_reg_valid = 1; - break; - case SCAT_DRAM_CONFIGURATION: - if((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) - { - if((val & 0x0F) == 3) - { - if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping); - for(index=0;index<6;index++) - mem_mapping_enable(&scat_shadowram_mapping[index]); - } - else - { - for(index=0;index<6;index++) - mem_mapping_disable(&scat_shadowram_mapping[index]); - if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); - } - } - else - { - for(index=0;index<6;index++) - mem_mapping_disable(&scat_shadowram_mapping[index]); - if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); - } - scat_map_update = 1; - - cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; - cpu_update_waitstates(); - - scat_reg_valid = 1; - break; - case SCAT_EXTENDED_BOUNDARY: - scat_set_xms_bound(val & 0x4f); - mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0x40) scat_map_update = 1; - scat_reg_valid = 1; - break; - case SCAT_ROM_ENABLE: - case SCAT_RAM_WRITE_PROTECT: - case SCAT_SHADOW_RAM_ENABLE_1: - case SCAT_SHADOW_RAM_ENABLE_2: - case SCAT_SHADOW_RAM_ENABLE_3: - scat_reg_valid = 1; - scat_shadow_update = 1; - break; - default: - break; - } - if (scat_reg_valid) - scat_regs[scat_index] = val; -#ifndef RELEASE_BUILD - else pclog("Attemped to write unimplemented SCAT register %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc); + if (scat_xms_bound > 0x100000) + mem_set_mem_state(0x100000, + scat_xms_bound - 0x100000, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (scat_xms_bound < 0x160000) + mem_set_mem_state(scat_xms_bound, + 0x160000 - scat_xms_bound, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } else { +#if 0 + for (i=0; i<6; i++) + mem_mapping_disable(&scat_shadowram_mapping[i]); + if (mem_size > 1024) + mem_mapping_enable(&ram_high_mapping); #endif - if (scat_shadow_update) - scat_shadow_state_update(); - if (scat_map_update) - scat_memmap_state_update(); - break; - case 0x92: - if ((mem_a20_alt ^ val) & 2) - { - mem_a20_alt = val & 2; - mem_a20_recalc(); - } - if ((~scat_port_92 & val) & 1) - { - softresetx86(); - cpu_set_edx(); - } - scat_port_92 = val; - break; + if (scat_xms_bound > max_xms) + scat_xms_bound = max_xms; + pclog("SCAT: set XMS bound(%02X) = %06X (%dK for EMS)\n", + val, scat_xms_bound, (max_mem-scat_xms_bound)>>10); - case 0x208: - case 0x218: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { - index = scat_ems_reg_2xA & 0x1F; - scat_stat[index].regs_2x8 = val; - base_addr = (index + 16) << 14; - if(index >= 24) - base_addr += 0x30000; - - if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80)) - { - virt_addr = get_scat_addr(base_addr, &scat_stat[index]); - if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); - else mem_mapping_set_exec(&scat_mapping[index], NULL); - flushmmucache(); - } - } - break; - case 0x209: - case 0x219: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { - index = scat_ems_reg_2xA & 0x1F; - scat_stat[index].regs_2x9 = val; - base_addr = (index + 16) << 14; - if(index >= 24) - base_addr += 0x30000; - - if (scat_regs[SCAT_EMS_CONTROL] & 0x80) - { - if (val & 0x80) - { - virt_addr = get_scat_addr(base_addr, &scat_stat[index]); - if(index < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[index]); - if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); - else mem_mapping_set_exec(&scat_mapping[index], NULL); - mem_mapping_enable(&scat_mapping[index]); - } - else - { - mem_mapping_set_exec(&scat_mapping[index], ram + base_addr); - mem_mapping_disable(&scat_mapping[index]); - if(index < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[index]); - } - flushmmucache(); - } - - if (scat_ems_reg_2xA & 0x80) - { - scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & 0x1f); - } - } - break; - case 0x20A: - case 0x21A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { - scat_ems_reg_2xA = val; - } - break; - } + if (scat_xms_bound > 0x100000) + mem_set_mem_state(0x100000, + scat_xms_bound-0x100000, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (scat_xms_bound < max_mem) + mem_set_mem_state(scat_xms_bound, + (mem_size<<10)-scat_xms_bound, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } } -uint8_t scat_read(uint16_t port, void *priv) +static uint32_t +get_addr(uint32_t addr, ems_t *p) { - uint8_t val = 0xff, index; - switch (port) - { - case 0x23: - switch (scat_index) - { - case SCAT_MISCELLANEOUS_STATUS: - val = (scat_regs[scat_index] & 0xbf) | ((mem_a20_key & 2) << 5); - break; - case SCAT_DRAM_CONFIGURATION: - val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); - break; - default: - val = scat_regs[scat_index]; - break; - } - break; + if (p && (scat_regs[SCAT_EMS_CTL] & 0x80) && (p->regs_2x9 & 0x80)) { + addr = (addr & 0x3fff) | (((p->regs_2x9 & 3)<<8) | p->regs_2x8)<<14; + } - case 0x92: - val = scat_port_92; - break; + if (mem_size < 2048 && + ((scat_regs[SCAT_DRAM_CONFIG] & 0x0F) > 7 || + (scat_regs[SCAT_EXT_BOUNDARY] & 0x40) != 0)) + addr = (addr & ~0x780000) | ((addr & 0x600000) >> 2); + else + if ((scat_regs[SCAT_DRAM_CONFIG] & 0x0F) < 8 && + (scat_regs[SCAT_EXT_BOUNDARY] & 0x40) == 0) { + addr &= ~0x600000; + if (mem_size > 2048 || (mem_size == 2048 && + (scat_regs[SCAT_DRAM_CONFIG] & 0x0F) < 6)) + addr |= (addr & 0x180000) << 2; + } - case 0x208: - case 0x218: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { - index = scat_ems_reg_2xA & 0x1F; - val = scat_stat[index].regs_2x8; - } - break; - case 0x209: - case 0x219: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { - index = scat_ems_reg_2xA & 0x1F; - val = scat_stat[index].regs_2x9; - } - break; - case 0x20A: - case 0x21A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { - val = scat_ems_reg_2xA; - } - break; - } - return val; + if ((scat_regs[SCAT_EXT_BOUNDARY] & 0x40) == 0 && + (scat_regs[SCAT_DRAM_CONFIG] & 0x0F) == 3 && + (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) + addr ^= mem_size < 2048 ? 0x1F0000 : 0x670000; + + return(addr); } -uint8_t mem_read_scatems(uint32_t addr, void *priv) +static void +memmap_state_update(void) { - uint8_t val = 0xff; - scat_t *stat = (scat_t *)priv; + uint32_t addr; + int i; - addr = get_scat_addr(addr, stat); - if (addr < (mem_size << 10)) - val = mem_read_ram(addr, priv); + for (i=16; i<24; i++) { + addr = get_addr(0x40000 + (i<<14), NULL); + mem_mapping_set_exec(&scat_top_mapping[i], + addr < (mem_size<<10) ? ram+addr : NULL); + } - return val; + addr = get_addr(0xA0000, NULL); + mem_mapping_set_exec(&scat_A000_mapping, + addr < (mem_size<<10) ? ram+addr : NULL); + + for (i=0; i<6; i++) { + addr = get_addr(0x100000 + (i<<16), NULL); + mem_mapping_set_exec(&scat_shadowram_mapping[i], + addr < (mem_size<<10) ? ram+addr : NULL); + } + + flushmmucache(); } -void mem_write_scatems(uint32_t addr, uint8_t val, void *priv) +static void +ems_state(int state) { - scat_t *stat = (scat_t *)priv; + uint32_t base_addr, virt_addr; + int i; - addr = get_scat_addr(addr, stat); - if (addr < (mem_size << 10)) - mem_write_ram(addr, val, priv); + for (i=0; i<32; i++) { + base_addr = (i + 16) << 14; + + if (i >= 24) + base_addr += 0x30000; + + if (state && (scat_ems[i].regs_2x9 & 0x80)) { + virt_addr = get_addr(base_addr, &scat_ems[i]); + if (i < 24) + mem_mapping_disable(&scat_top_mapping[i]); + mem_mapping_enable(&scat_mapping[i]); + if (virt_addr < (mem_size<<10)) + mem_mapping_set_exec(&scat_mapping[i], ram+virt_addr); + else + mem_mapping_set_exec(&scat_mapping[i], NULL); + } else { + mem_mapping_set_exec(&scat_mapping[i], ram+base_addr); + mem_mapping_disable(&scat_mapping[i]); +#if 0 + if (i < 24) + mem_mapping_enable(&scat_top_mapping[i]); +#endif + } + } } -static void scat_init(void) +/* Read a byte from a LIM/EMS page. */ +static uint8_t +ems_pgrd(uint32_t vaddr, void *priv) { - int i; + ems_t *ems = (ems_t *)priv; + uint32_t addr; + uint8_t val = 0xff; - io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + addr = get_addr(vaddr, ems); + if (addr < (mem_size << 10)) + val = mem_read_ram(addr, priv); +#if SCAT_DEBUG > 1 + pclog("SCAT: ems_pgrd(%06x->%06x) = %02x\n", vaddr, addr, val); +#endif - for (i = 0; i < 256; i++) - { - scat_regs[i] = 0xff; - } - - scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; - scat_regs[SCAT_VERSION] = 10; - scat_regs[SCAT_CLOCK_CONTROL] = 2; - scat_regs[SCAT_PERIPHERAL_CONTROL] = 0x80; - scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; - scat_regs[SCAT_POWER_MANAGEMENT] = 0; - scat_regs[SCAT_ROM_ENABLE] = 0xC0; - scat_regs[SCAT_RAM_WRITE_PROTECT] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; - scat_regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12; - scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; - scat_regs[SCAT_EMS_CONTROL] = 0; - scat_port_92 = 0; - - mem_mapping_set_addr(&ram_low_mapping, 0, 0x40000); - - for (i = 0; i < 24; i++) - { - mem_mapping_add(&scat_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&scat_4000_9FFF_mapping[i]); - } - - mem_mapping_add(&scat_A000_BFFF_mapping, 0xA0000, 0x20000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&scat_A000_BFFF_mapping); - - for (i = 0; i < 32; i++) - { - scat_stat[i].regs_2x8 = 0xff; - scat_stat[i].regs_2x9 = 0x03; - mem_mapping_add(&scat_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); - mem_mapping_disable(&scat_mapping[i]); - } - - for(i=4;i<10;i++) isram[i] = 0; - - for (i = 12; i < 16; i++) - { - mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (i << 14), 0, NULL); - } - - for(i=0;i<6;i++) - mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); - - scat_set_xms_bound(0); - scat_shadow_state_update(); + return(val); } -void machine_at_scat_init(void) +/* Write a byte to a LIM/EMS page. */ +static void +ems_pgwr(uint32_t vaddr, uint8_t val, void *priv) { - machine_at_ide_init(); - scat_init(); + ems_t *ems = (ems_t *)priv; + uint32_t addr; + + addr = get_addr(vaddr, ems); +#if SCAT_DEBUG > 1 + pclog("SCAT: ems_pgwr(%06x->%06x, %02x)\n", vaddr, addr, val); +#endif + if (addr < (mem_size << 10)) + mem_write_ram(addr, val, priv); +} + + +/* Read from a LIM/EMS control register. */ +static uint8_t +ems_read(uint16_t port, void *priv) +{ + uint8_t val = 0xff; + uint8_t idx; + + switch (port) { + case 0x208: + case 0x218: + if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + idx = scat_ems_reg & 0x1f; + val = scat_ems[idx].regs_2x8; + } + break; + + case 0x209: + case 0x219: + if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + idx = scat_ems_reg & 0x1f; + val = scat_ems[idx].regs_2x9; + } + break; + + case 0x20A: + case 0x21A: + if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + val = scat_ems_reg; + } + break; + } + +#if SCAT_DEBUG > 2 + pclog("SCAT: ems_read(%04x) = %02x\n", port, val); +#endif + return(val); +} + + +/* Write to one of the LIM/EMS control registers. */ +static void +ems_write(uint16_t port, uint8_t val, void *priv) +{ + uint32_t base_addr, virt_addr; + uint8_t idx; + +#if SCAT_DEBUG > 1 + pclog("SCAT: ems_write(%04x, %02x)\n", port, val); +#endif + switch(port) { + case 0x208: + case 0x218: + if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + idx = scat_ems_reg & 0x1f; + scat_ems[idx].regs_2x8 = val; + base_addr = (idx + 16) << 14; + if (idx >= 24) + base_addr += 0x30000; + + if ((scat_regs[SCAT_EMS_CTL] & 0x80) && (scat_ems[idx].regs_2x9 & 0x80)) { + virt_addr = get_addr(base_addr, &scat_ems[idx]); + if (virt_addr < (mem_size << 10)) + mem_mapping_set_exec(&scat_mapping[idx], ram + virt_addr); + else + mem_mapping_set_exec(&scat_mapping[idx], NULL); + flushmmucache(); + } + } + break; + + case 0x209: + case 0x219: + if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + idx = scat_ems_reg & 0x1f; + scat_ems[idx].regs_2x9 = val; + base_addr = (idx + 16) << 14; + if (idx >= 24) + base_addr += 0x30000; + + if (scat_regs[SCAT_EMS_CTL] & 0x80) { + if (val & 0x80) { + virt_addr = get_addr(base_addr, &scat_ems[idx]); + if (idx < 24) + mem_mapping_disable(&scat_top_mapping[idx]); + if (virt_addr < (mem_size << 10)) + mem_mapping_set_exec(&scat_mapping[idx], ram+virt_addr); + else + mem_mapping_set_exec(&scat_mapping[idx], NULL); + mem_mapping_enable(&scat_mapping[idx]); + } else { + mem_mapping_set_exec(&scat_mapping[idx], ram + base_addr); + mem_mapping_disable(&scat_mapping[idx]); + if (idx < 24) + mem_mapping_enable(&scat_top_mapping[idx]); + } + flushmmucache(); + } + + if (scat_ems_reg & 0x80) { + scat_ems_reg = (scat_ems_reg & 0xe0) | ((scat_ems_reg + 1) & 0x1f); + } + } + break; + + case 0x20A: + case 0x21A: + if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + scat_ems_reg = val; + } + break; + } +} + + +static uint8_t +scat_read(uint16_t port, void *priv) +{ + uint8_t val = 0xff; + + switch (port) { + case 0x23: + switch (scat_index) { + case SCAT_MISC_STATUS: + val = (scat_regs[scat_index] & 0xbf) | ((mem_a20_key & 2) << 5); + break; + + case SCAT_DRAM_CONFIG: + val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); + break; + + default: + val = scat_regs[scat_index]; + break; + } + break; + + case 0x92: + val = scat_regs[SCAT_SYS_CTL]; + break; + + } + +#if SCAT_DEBUG > 2 + pclog("SCAT: read(%04x) = %02x\n", port, val); +#endif + return(val); +} + + +/* Write to one of the Internal Control Registers. */ +static void +ics_write(uint8_t idx, uint8_t val) +{ + uint8_t reg_valid = 0; + uint8_t shadow_update = 0; + uint8_t map_update = 0; + +#if SCAT_DEBUG > 1 + pclog("SCAT: icr_write(%02x, %02x)\n", idx, val); +#endif + switch (idx) { + case SCAT_CLOCK_CTL: + case SCAT_PERIPH_CTL: + reg_valid = 1; + break; + + case SCAT_EMS_CTL: +pclog("SCAT: EMSctrl(%02x)\n", val); + if (val & 0x40) { + if (val & 1) { + io_sethandler(0x0218, 3, + ems_read, NULL, NULL, + ems_write, NULL, NULL, NULL); + io_removehandler(0x0208, 3, + ems_read, NULL, NULL, + ems_write, NULL, NULL, NULL); + } else { + io_sethandler(0x0208, 3, + ems_read, NULL, NULL, + ems_write, NULL, NULL, NULL); + io_removehandler(0x0218, 3, + ems_read, NULL, NULL, + ems_write, NULL, NULL, NULL); + } + } else { + io_removehandler(0x0208, 3, + ems_read, NULL, NULL, + ems_write, NULL, NULL, NULL); + io_removehandler(0x0218, 3, + ems_read, NULL, NULL, + ems_write, NULL, NULL, NULL); + } + ems_state(val & 0x80); + reg_valid = 1; + break; + + case SCAT_POWER_MGMT: + val &= 0x40; + reg_valid = 1; + break; + + case SCAT_DRAM_CONFIG: + if ((scat_regs[SCAT_EXT_BOUNDARY] & 0x40) == 0) { +pclog("SCAT: 0\n"); + if ((val & 0x0f) == 3) { +pclog("SCAT: 3\n"); + if (mem_size > 1024) + mem_mapping_disable(&ram_high_mapping); + for (idx=0; idx<6; idx++) + mem_mapping_enable(&scat_shadowram_mapping[idx]); + } else { +pclog("SCAT: 0\n"); + for (idx=0; idx<6; idx++) + mem_mapping_disable(&scat_shadowram_mapping[idx]); +#if 0 + if (mem_size > 1024) + mem_mapping_enable(&ram_high_mapping); +#endif + } + } else { +pclog("SCAT: 1\n"); + for (idx=0; idx<6; idx++) + mem_mapping_disable(&scat_shadowram_mapping[idx]); + if (mem_size > 1024) + mem_mapping_enable(&ram_high_mapping); + } + map_update = 1; + + cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; + cpu_update_waitstates(); + + reg_valid = 1; + break; + + case SCAT_EXT_BOUNDARY: + set_xms_bound(val & 0x4f); + mem_set_mem_state(0x40000, 0x60000, + (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if ((val ^ scat_regs[SCAT_EXT_BOUNDARY]) & 0x40) + map_update = 1; + reg_valid = 1; + break; + + case SCAT_ROM_ENABLE: + case SCAT_RAM_WR_PROTECT: + case SCAT_SHADOW_RAM_EN_1: + case SCAT_SHADOW_RAM_EN_2: + case SCAT_SHADOW_RAM_EN_3: + reg_valid = 1; + shadow_update = 1; + break; + + default: + break; + } + + if (reg_valid) + scat_regs[scat_index] = val; +#ifndef RELEASE_BUILD + else + pclog("SCAT: attemped write to register %02X at %04X:%04X\n", + idx, val, CS, cpu_state.pc); +#endif + + if (shadow_update) + shadow_state_update(); + + if (map_update) + memmap_state_update(); +} + + +static void +scat_write(uint16_t port, uint8_t val, void *priv) +{ +#if SCAT_DEBUG > 2 + pclog("SCAT: write(%04x, %02x)\n", port, val); +#endif + switch (port) { + case 0x22: + scat_index = val; + break; + + case 0x23: + ics_write(scat_index, val); + break; + + case 0x92: + if ((mem_a20_alt ^ val) & 2) { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + + if ((~scat_regs[SCAT_SYS_CTL] & val) & 1) { + softresetx86(); + cpu_set_edx(); + } + scat_regs[SCAT_SYS_CTL] = val; + break; + } +} + + +static void +scat_init(void) +{ + int i; + +#if SCAT_DEBUG + pclog("SCAT: initializing..\n"); +#endif + io_sethandler(0x0022, 2, + scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0092, 1, + scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + + for (i=0; i<128; i++) + scat_regs[i] = 0xff; + scat_regs[SCAT_DMA_WS_CTL] = 0x00; + scat_regs[SCAT_VERSION] = 0x0a; + scat_regs[SCAT_CLOCK_CTL] = 0x02; + scat_regs[SCAT_PERIPH_CTL] = 0x80; + scat_regs[SCAT_MISC_STATUS] = 0x37; + scat_regs[SCAT_POWER_MGMT] = 0x00; + scat_regs[SCAT_ROM_ENABLE] = 0xC0; + scat_regs[SCAT_RAM_WR_PROTECT] = 0x00; + scat_regs[SCAT_SHADOW_RAM_EN_1] = 0x00; + scat_regs[SCAT_SHADOW_RAM_EN_2] = 0x00; + scat_regs[SCAT_SHADOW_RAM_EN_3] = 0x00; + scat_regs[SCAT_DRAM_CONFIG] = cpu_waitstates == 1 ? 0x00 : 0x10; + scat_regs[SCAT_EXT_BOUNDARY] = 0x00; + scat_regs[SCAT_EMS_CTL] = 0x00; + scat_regs[SCAT_SYS_CTL] = 0x00; + + /* Limit RAM size to 16MB. */ + mem_mapping_set_addr(&ram_low_mapping, 0x000000, 0x40000); + + /* + * Configure the DRAM controller. + * + * Since SCAT allows mixing of the various-sized DRAM chips, + * memory configuration is not simple. The SCAT datasheet + * tells us in table 6-6 how to set up the four banks: + * + * MEM SIZE MIX_EN RAMCFG Ext RAM Comments + * 0 K 0 0x00 No RAM installed + * 512 K 0 0x01 0 K + * 640 K 0 0x02 0 K + * 1 M 0 0x03 384K + * 1 M 0 0x04 0 K + * 1.5 M 0 0x05 512K + * 2 M 0 0x06 1 M 4x512K + * 2 M 0 0x08 1 M 1x2M + * 2.5 M 1 0x01 1.5M 2M+512K + * 3 M 1 0x04 2 M 1x2M + * 4 M 0 0x09 3 M 2x2M + * 4.5 M 1 0x02 3.5M 2x2M+512K + * 5 M 1 0x05 4 M 2x2M+2x512K + * 6 M 0 0x0a 5 M 3x2M + * 6.5 M 1 0x03 5.5M 3x2M+512K + * 8 M 0 0x0b 7 M 4x2M + */ + pclog("SCAT: mem_size=%d\n", mem_size); + + +#if 0 + /* Create the 32 EMS page frame mappings for 256-640K. */ + for (i=0; i<24; i++) { + mem_mapping_add(&scat_top_mapping[i], + 0x40000 + (i<<14), 0x4000, + ems_pgrd, NULL, NULL, + ems_pgwr, NULL, NULL, + mem_size > 256+(i<<4) ? ram+0x40000+(i<<14) : NULL, + MEM_MAPPING_INTERNAL, NULL); +// mem_mapping_enable(&scat_top_mapping[i]); + mem_mapping_disable(&scat_top_mapping[i]); + } +#endif + +#if 0 + /* Re-map the 128K at A0000 (video BIOS) to above 16MB+top. */ + mem_mapping_add(&scat_A000_mapping, + 0xA0000, 0x20000, + ems_pgrd, NULL, NULL, + ems_pgwr, NULL, NULL, + ram+0xA0000, + MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&scat_A000_mapping); +#endif + +#if 0 + /* Create 32 page frames for EMS, each 16K. */ + for (i=0; i<32; i++) { + scat_ems[i].regs_2x8 = 0xff; + scat_ems[i].regs_2x9 = 0x03; + mem_mapping_add(&scat_mapping[i], + (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, + ems_pgrd, NULL, NULL, + ems_pgwr, NULL, NULL, + ram + ((i + (i >= 24 ? 28 : 16)) << 14), + 0, &scat_ems[i]); + mem_mapping_disable(&scat_mapping[i]); + } +#endif + +// for (i=4; i<10; i++) isram[i] = 0; + + /* Re-map the BIOS ROM (C0000-FFFFF) area. */ + for (i=12; i<16; i++) { + mem_mapping_add(&scat_high_mapping[i], + (i<<14) + 0xFC0000, 0x04000, + mem_read_bios, mem_read_biosw, mem_read_biosl, + mem_write_null, mem_write_nullw, mem_write_nulll, + rom+(i<<14), + 0, NULL); + } + +#if 0 + for (i=0; i<6; i++) { + mem_mapping_add(&scat_shadowram_mapping[i], + 0x100000 + (i<<16), 0x10000, + ems_pgrd, NULL, NULL, + ems_pgwr, NULL, NULL, + mem_size >= 1024 ? ram+get_addr(0x100000+(i<<16), NULL) : NULL, + MEM_MAPPING_INTERNAL, NULL); + } +#endif + + set_xms_bound(0); + shadow_state_update(); +} + + +void +machine_at_scat_init(machine_t *model) +{ + machine_at_init(model); + + scat_init(); } diff --git a/src/machine/machine_at_scat.h b/src/machine/machine_at_scat.h deleted file mode 100644 index cfc699819..000000000 --- a/src/machine/machine_at_scat.h +++ /dev/null @@ -1 +0,0 @@ -extern void machine_at_scat_init(void); diff --git a/src/machine/machine_at_sis_85c471.c b/src/machine/machine_at_sis_85c471.c index 399c46b04..68b9b5ab1 100644 --- a/src/machine/machine_at_sis_85c471.c +++ b/src/machine/machine_at_sis_85c471.c @@ -9,22 +9,28 @@ * SiS sis85c471 Super I/O Chip * Used by DTK PKM-0038S E-2 * - * Version: @(#)sis85c471.c 1.0.4 2017/09/03 + * Version: @(#)sis85c471.c 1.0.6 2017/10/07 * * Author: Miran Grca, + * * Copyright 2017 Miran Grca. */ +#include +#include +#include +#include #include "../ibm.h" #include "../io.h" #include "../memregs.h" +#include "../device.h" #include "../lpt.h" #include "../serial.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" #include "../floppy/floppy.h" #include "../floppy/fdc.h" #include "../floppy/fdd.h" -#include "../hdd/hdd_ide_at.h" -#include "machine_at.h" -#include "machine_at_sis_85c471.h" +#include "machine.h" static int sis_85c471_curreg; @@ -237,9 +243,11 @@ static void sis_85c471_init(void) } -void machine_at_dtk486_init(void) +void +machine_at_dtk486_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); sis_85c471_init(); secondary_ide_check(); diff --git a/src/machine/machine_at_sis_85c471.h b/src/machine/machine_at_sis_85c471.h deleted file mode 100644 index 4e720242f..000000000 --- a/src/machine/machine_at_sis_85c471.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * Emulation of the SiS 85c471 chip. - * - * Version: @(#)machine_at_sis_85c471.h 1.0.2 2017/09/02 - * - * Author: Miran Grca, - * Copyright 2017 Miran Grca. - */ - -extern void machine_at_dtk486_init(void); diff --git a/src/machine/machine_at_sis_85c496.c b/src/machine/machine_at_sis_85c496.c index 7e3640c22..77a9c3580 100644 --- a/src/machine/machine_at_sis_85c496.c +++ b/src/machine/machine_at_sis_85c496.c @@ -1,7 +1,11 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../io.h" @@ -9,8 +13,7 @@ #include "../mem.h" #include "../memregs.h" #include "../sio.h" -#include "machine_at.h" -#include "machine_at_sis_85c496.h" +#include "machine.h" typedef struct sis_85c496_t @@ -156,9 +159,11 @@ static void sis_85c496_init(void) } -static void machine_at_sis_85c496_common_init(void) +static void +machine_at_sis_85c496_common_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); @@ -166,12 +171,15 @@ static void machine_at_sis_85c496_common_init(void) pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); + sis_85c496_init(); } -void machine_at_r418_init(void) +void +machine_at_r418_init(machine_t *model) { - machine_at_sis_85c496_common_init(); + machine_at_sis_85c496_common_init(model); + fdc37c665_init(); } diff --git a/src/machine/machine_at_sis_85c496.h b/src/machine/machine_at_sis_85c496.h deleted file mode 100644 index 9ea1ab4ea..000000000 --- a/src/machine/machine_at_sis_85c496.h +++ /dev/null @@ -1 +0,0 @@ -extern void machine_at_r418_init(void); diff --git a/src/machine/machine_at_sis_85c50x.c b/src/machine/machine_at_sis_85c50x.c index 4d17558c4..c6aa5dfb6 100644 --- a/src/machine/machine_at_sis_85c50x.c +++ b/src/machine/machine_at_sis_85c50x.c @@ -6,18 +6,22 @@ * * Emulation of the SiS 50x PCI chips. * - * Version: @(#)machine_at_sis_85c50x.c 1.0.2 2017/09/02 + * Version: @(#)machine_at_sis_85c50x.c 1.0.3 2017/10/07 * * Author: Miran Grca, + * * Copyright 2017 Miran Grca. */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../pci.h" #include "../mem.h" -#include "machine_at.h" -#include "machine_at_sis_85c50x.h" +#include "machine.h" typedef struct sis_85c501_t diff --git a/src/machine/machine_at_sis_85c50x.h b/src/machine/machine_at_sis_85c50x.h deleted file mode 100644 index 3e88158de..000000000 --- a/src/machine/machine_at_sis_85c50x.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * Emulation of the SiS 50x PCI chips. - * - * Version: @(#)machine_at_sis_85c50x.h 1.0.2 2017/09/02 - * - * Author: Miran Grca, - * Copyright 2017 Miran Grca. - */ diff --git a/src/machine/machine_at_wd76c10.c b/src/machine/machine_at_wd76c10.c index 430d7c8b7..acdb47245 100644 --- a/src/machine/machine_at_wd76c10.c +++ b/src/machine/machine_at_wd76c10.c @@ -1,14 +1,17 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" #include "../serial.h" #include "../floppy/floppy.h" #include "../floppy/fdc.h" -#include "machine_at.h" -#include "machine_at_wd76c10.h" +#include "machine.h" static uint16_t wd76c10_0092; @@ -131,8 +134,11 @@ static void wd76c10_init(void) wd76c10_writeb, wd76c10_write, NULL, NULL); } -void machine_at_wd76c10_init(void) + +void +machine_at_wd76c10_init(machine_t *model) { - machine_at_ide_init(); + machine_at_ide_init(model); + wd76c10_init(); } diff --git a/src/machine/machine_at_wd76c10.h b/src/machine/machine_at_wd76c10.h deleted file mode 100644 index 24eaae50a..000000000 --- a/src/machine/machine_at_wd76c10.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern void machine_at_wd76c10_init(void); diff --git a/src/machine/machine_common.c b/src/machine/machine_common.c index 23ed67310..bf22dca68 100644 --- a/src/machine/machine_common.c +++ b/src/machine/machine_common.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../dma.h" #include "../pic.h" @@ -7,30 +11,25 @@ #include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" -#include "machine_common.h" +#include "machine.h" -void machine_common_init(void) +void +machine_common_init(machine_t *model) { - /* System devices first. */ - dma_init(); - pic_init(); - pit_init(); + /* System devices first. */ + dma_init(); + pic_init(); + pit_init(); - fdc_add(); + if (lpt_enabled) + lpt_init(); - if (lpt_enabled) - { - lpt_init(); - } + if (serial_enabled[0]) + serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); - if (serial_enabled[0]) - { - serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); - } + if (serial_enabled[1]) + serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); - if (serial_enabled[1]) - { - serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); - } + fdc_add(); } diff --git a/src/machine/machine_common.h b/src/machine/machine_common.h deleted file mode 100644 index 445fadefa..000000000 --- a/src/machine/machine_common.h +++ /dev/null @@ -1 +0,0 @@ -extern void machine_common_init(void); diff --git a/src/machine/machine_europc.c b/src/machine/machine_europc.c index 5cd8daa4e..9328293a3 100644 --- a/src/machine/machine_europc.c +++ b/src/machine/machine_europc.c @@ -2,19 +2,20 @@ see COPYING for more details */ #include +#include #include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../io.h" #include "../nmi.h" #include "../mem.h" #include "../rom.h" #include "../device.h" -#include "../gameport.h" +#include "../nvr.h" +#include "../game/gameport.h" #include "../keyboard_xt.h" #include "../lpt.h" -#include "machine_common.h" -#include "machine_europc.h" +#include "machine.h" uint8_t europcdat[16]; @@ -32,7 +33,7 @@ static uint8_t jim_load_nvr(void) { FILE *f; - f = nvrfopen(L"europc_jim.nvr", L"rb"); + f = nvr_fopen(L"europc_jim.nvr", L"rb"); if (f) { fread(europcdat, 1, 16, f); @@ -49,7 +50,7 @@ void europc_save_nvr(void) { FILE *f; - f = nvrfopen(L"europc_jim.nvr", L"wb"); + f = nvr_fopen(L"europc_jim.nvr", L"wb"); if (f) { fwrite(europcdat, 1, 16, f); @@ -129,10 +130,11 @@ static void jim_init(void) } -void machine_europc_init(void) +void +machine_europc_init(machine_t *model) { - machine_common_init(); - mem_add_bios(); + machine_common_init(model); + lpt3_init(0x3bc); jim_init(); keyboard_xt_init(); diff --git a/src/machine/machine_europc.h b/src/machine/machine_europc.h deleted file mode 100644 index 2217a6500..000000000 --- a/src/machine/machine_europc.h +++ /dev/null @@ -1,3 +0,0 @@ -void europc_save_nvr(void); - -void machine_europc_init(void); diff --git a/src/machine/machine_olivetti_m24.c b/src/machine/machine_olivetti_m24.c index de2b301c9..36ca77f1f 100644 --- a/src/machine/machine_olivetti_m24.c +++ b/src/machine/machine_olivetti_m24.c @@ -1,17 +1,19 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "../ibm.h" -#include "../cpu/cpu.h" #include "../io.h" #include "../nmi.h" #include "../mem.h" #include "../device.h" #include "../nvr.h" -#include "../gameport.h" +#include "../game/gameport.h" #include "../keyboard_olim24.h" -#include "machine_common.h" -#include "machine_olivetti_m24.h" +#include "machine.h" static uint8_t olivetti_m24_read(uint16_t port, void *priv) @@ -33,12 +35,16 @@ static void olivetti_m24_init(void) } -void machine_olim24_init(void) +void +machine_olim24_init(machine_t *model) { - machine_common_init(); - mem_add_bios(); + machine_common_init(model); + keyboard_olim24_init(); - nvr_init(); + + /* FIXME: make sure this is correct?? */ + nvr_at_init(8); + olivetti_m24_init(); nmi_init(); if (joystick_type != 7) device_add(&gameport_device); diff --git a/src/machine/machine_olivetti_m24.h b/src/machine/machine_olivetti_m24.h deleted file mode 100644 index 3a17db6bd..000000000 --- a/src/machine/machine_olivetti_m24.h +++ /dev/null @@ -1 +0,0 @@ -void machine_olim24_init(void); diff --git a/src/machine/machine_pcjr.c b/src/machine/machine_pcjr.c index ba65cc113..aace2715e 100644 --- a/src/machine/machine_pcjr.c +++ b/src/machine/machine_pcjr.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../nmi.h" #include "../pic.h" @@ -10,12 +14,12 @@ #include "../floppy/fdc.h" #include "../floppy/fdd.h" #include "../sound/snd_sn76489.h" -#include "machine_pcjr.h" +#include "machine.h" -void machine_pcjr_init(void) +void +machine_pcjr_init(machine_t *model) { - mem_add_bios(); fdc_add_pcjr(); pic_init(); pit_init(); diff --git a/src/machine/machine_pcjr.h b/src/machine/machine_pcjr.h deleted file mode 100644 index fa8b85552..000000000 --- a/src/machine/machine_pcjr.h +++ /dev/null @@ -1 +0,0 @@ -void machine_pcjr_init(void); diff --git a/src/machine/machine_ps1.c b/src/machine/machine_ps1.c index 0fb45f05a..3e2be3012 100644 --- a/src/machine/machine_ps1.c +++ b/src/machine/machine_ps1.c @@ -1,6 +1,10 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../io.h" @@ -11,17 +15,17 @@ #include "../rom.h" #include "../device.h" #include "../nvr.h" -#include "../gameport.h" +#include "../game/gameport.h" #include "../lpt.h" #include "../serial.h" #include "../keyboard_at.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" #include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" -#include "../hdd/hdd_ide_at.h" #include "../sound/snd_ps1.h" -#include "machine_common.h" -#include "machine_ps1.h" +#include "machine.h" static rom_t ps1_high_rom; @@ -149,7 +153,8 @@ void ps1mb_init(void) io_sethandler(0x0320, 0x0001, ps1_read, NULL, NULL, ps1_write, NULL, NULL, NULL); io_sethandler(0x0322, 0x0001, ps1_read, NULL, NULL, ps1_write, NULL, NULL, NULL); io_sethandler(0x0324, 0x0001, ps1_read, NULL, NULL, ps1_write, NULL, NULL, NULL); - + +#if 0 if (!enable_xtide) { rom_init(&ps1_high_rom, @@ -160,14 +165,7 @@ void ps1mb_init(void) 0, MEM_MAPPING_EXTERNAL); } -/* rom_init_interleaved(&ps1_high_rom, - L"roms/machines/ibmps1es/ibm_1057757_24-05-90.bin", - L"roms/machines/ibmps1es/ibm_1057757_29-15-90.bin", - 0xfc0000, - 0x40000, - 0x3ffff, - 0, - MEM_MAPPING_EXTERNAL);*/ +#endif ps1_190 = 0; lpt1_remove(); @@ -336,12 +334,12 @@ static void ps1mb_m2133_init(void) mem_remap_top_384k(); } -static void machine_ps1_common_init(void) -{ - AT = 1; - machine_common_init(); - mem_add_bios(); +static void +machine_ps1_common_init(machine_t *model) +{ + machine_common_init(model); + pit_set_out_func(&pit, 1, pit_refresh_timer_at); dma16_init(); if (romset != ROM_IBMPS1_2011) @@ -349,7 +347,7 @@ static void machine_ps1_common_init(void) ide_init(); } keyboard_at_init(); - nvr_init(); + nvr_at_init(8); pic2_init(); if (romset != ROM_IBMPS1_2133) { @@ -362,22 +360,31 @@ static void machine_ps1_common_init(void) device_add(&gameport_201_device); } -void machine_ps1_m2011_init(void) + +void +machine_ps1_m2011_init(machine_t *model) { - machine_ps1_common_init(); + machine_ps1_common_init(model); + ps1mb_init(); mem_remap_top_384k(); } -void machine_ps1_m2121_init(void) + +void +machine_ps1_m2121_init(machine_t *model) { - machine_ps1_common_init(); + machine_ps1_common_init(model); + ps1mb_m2121_init(); fdc_set_ps1(); } -void machine_ps1_m2133_init(void) + +void +machine_ps1_m2133_init(machine_t *model) { - machine_ps1_common_init(); + machine_ps1_common_init(model); + ps1mb_m2133_init(); } diff --git a/src/machine/machine_ps1.h b/src/machine/machine_ps1.h deleted file mode 100644 index 6141632bd..000000000 --- a/src/machine/machine_ps1.h +++ /dev/null @@ -1,3 +0,0 @@ -void machine_ps1_m2011_init(void); -void machine_ps1_m2121_init(void); -void machine_ps1_m2133_init(void); diff --git a/src/machine/machine_ps2_isa.c b/src/machine/machine_ps2_isa.c index 3521570b3..c3b71007a 100644 --- a/src/machine/machine_ps2_isa.c +++ b/src/machine/machine_ps2_isa.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../io.h" @@ -15,8 +19,7 @@ #include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" -#include "machine_common.h" -#include "machine_ps2_isa.h" +#include "machine.h" static uint8_t ps2_92, ps2_94, ps2_102, ps2_103, ps2_104, ps2_105, ps2_190; @@ -150,16 +153,15 @@ static void ps2board_init(void) } -void machine_ps2_m30_286_init(void) +void +machine_ps2_m30_286_init(machine_t *model) { - AT = 1; + machine_common_init(model); - machine_common_init(); - mem_add_bios(); pit_set_out_func(&pit, 1, pit_refresh_timer_at); dma16_init(); keyboard_at_init(); - nvr_init(); + nvr_at_init(8); pic2_init(); ps2board_init(); fdc_set_dskchg_activelow(); diff --git a/src/machine/machine_ps2_isa.h b/src/machine/machine_ps2_isa.h deleted file mode 100644 index 22ee1482b..000000000 --- a/src/machine/machine_ps2_isa.h +++ /dev/null @@ -1 +0,0 @@ -void machine_ps2_m30_286_init(void); diff --git a/src/machine/machine_ps2_mca.c b/src/machine/machine_ps2_mca.c index 36336570e..c4ddc4ec9 100644 --- a/src/machine/machine_ps2_mca.c +++ b/src/machine/machine_ps2_mca.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../cpu/x86.h" @@ -15,8 +19,7 @@ #include "../lpt.h" #include "../mouse.h" #include "../serial.h" -#include "machine_common.h" -#include "machine_ps2_mca.h" +#include "machine.h" static struct @@ -798,47 +801,55 @@ static void ps2_mca_board_model_80_type2_init() } } -static void machine_ps2_common_init(void) -{ - AT = 1; - machine_common_init(); - mem_add_bios(); +static void +machine_ps2_common_init(machine_t *model) +{ + machine_common_init(model); + dma16_init(); ps2_dma_init(); keyboard_at_init(); keyboard_at_init_ps2(); mouse_ps2_init(); - nvr_init(); + nvr_at_init(8); pic2_init(); pit_ps2_init(); } -void machine_ps2_model_50_init(void) +void +machine_ps2_model_50_init(machine_t *model) { - machine_ps2_common_init(); + machine_ps2_common_init(model); + ps2_mca_board_model_50_init(); } -void machine_ps2_model_55sx_init(void) +void +machine_ps2_model_55sx_init(machine_t *model) { - machine_ps2_common_init(); + machine_ps2_common_init(model); + ps2_mca_board_model_55sx_init(); } -void machine_ps2_model_80_init(void) +void +machine_ps2_model_80_init(machine_t *model) { - machine_ps2_common_init(); + machine_ps2_common_init(model); + ps2_mca_board_model_80_type2_init(); } -void machine_ps2_model_80_486_init(void) +void +machine_ps2_model_80_486_init(machine_t *model) { - machine_ps2_common_init(); + machine_ps2_common_init(model); + ps2_mca_board_model_80_type2_init(); } diff --git a/src/machine/machine_ps2_mca.h b/src/machine/machine_ps2_mca.h deleted file mode 100644 index 5965592e9..000000000 --- a/src/machine/machine_ps2_mca.h +++ /dev/null @@ -1,4 +0,0 @@ -extern void machine_ps2_model_50_init(void); -extern void machine_ps2_model_55sx_init(void); -extern void machine_ps2_model_80_init(void); -extern void machine_ps2_model_80_486_init(void); diff --git a/src/machine/machine_tandy.c b/src/machine/machine_tandy.c index 2690089db..0698ad6f9 100644 --- a/src/machine/machine_tandy.c +++ b/src/machine/machine_tandy.c @@ -1,22 +1,28 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../nmi.h" #include "../mem.h" +#include "../rom.h" #include "../device.h" -#include "../gameport.h" +#include "../game/gameport.h" #include "../keyboard_xt.h" #include "../tandy_eeprom.h" #include "../tandy_rom.h" #include "../sound/snd_pssj.h" #include "../sound/snd_sn76489.h" -#include "machine_common.h" +#include "machine.h" -void machine_tandy1k_init(void) +void +machine_tandy1k_init(machine_t *model) { - TANDY = 1; + TANDY = 1; + + machine_common_init(model); - machine_common_init(); - mem_add_bios(); keyboard_tandy_init(); if (romset == ROM_TANDY) device_add(&sn76489_device); @@ -30,10 +36,11 @@ void machine_tandy1k_init(void) } -void machine_tandy1ksl2_init(void) +void +machine_tandy1ksl2_init(machine_t *model) { - machine_common_init(); - mem_add_bios(); + machine_common_init(model); + keyboard_tandy_init(); device_add(&pssj_device); nmi_init(); diff --git a/src/machine/machine_tandy.h b/src/machine/machine_tandy.h deleted file mode 100644 index 06792bbd0..000000000 --- a/src/machine/machine_tandy.h +++ /dev/null @@ -1,2 +0,0 @@ -void machine_tandy1k_init(void); -void machine_tandy1ksl2_init(void); diff --git a/src/machine/machine_xt.c b/src/machine/machine_xt.c index 6933069af..183482fd5 100644 --- a/src/machine/machine_xt.c +++ b/src/machine/machine_xt.c @@ -1,20 +1,22 @@ +#include +#include +#include +#include #include "../ibm.h" #include "../nmi.h" #include "../pit.h" #include "../mem.h" #include "../device.h" #include "../bugger.h" -#include "../gameport.h" +#include "../game/gameport.h" #include "../keyboard_xt.h" -#include "machine_common.h" -#include "machine_xt.h" +#include "machine.h" -void machine_xt_init(void) +void +machine_xt_init(machine_t *model) { - machine_common_init(); - - mem_add_bios(); + machine_common_init(model); pit_set_out_func(&pit, 1, pit_refresh_timer_xt); diff --git a/src/machine/machine_xt.h b/src/machine/machine_xt.h deleted file mode 100644 index d111551cf..000000000 --- a/src/machine/machine_xt.h +++ /dev/null @@ -1 +0,0 @@ -void machine_xt_init(void); diff --git a/src/machine/machine_xt_laserxt.c b/src/machine/machine_xt_laserxt.c index ab08e9e67..6cbadf648 100644 --- a/src/machine/machine_xt_laserxt.c +++ b/src/machine/machine_xt_laserxt.c @@ -1,10 +1,13 @@ /*This is the chipset used in the LaserXT series model*/ +#include +#include +#include +#include #include "../ibm.h" #include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" -#include "machine_xt.h" -#include "machine_xt_laserxt.h" +#include "machine.h" static int laserxt_emspage[4]; @@ -125,8 +128,10 @@ static void laserxt_init(void) } -void machine_xt_laserxt_init(void) +void +machine_xt_laserxt_init(machine_t *model) { - machine_xt_init(); + machine_xt_init(model); + laserxt_init(); } diff --git a/src/machine/machine_xt_laserxt.h b/src/machine/machine_xt_laserxt.h deleted file mode 100644 index c74b0417c..000000000 --- a/src/machine/machine_xt_laserxt.h +++ /dev/null @@ -1 +0,0 @@ -void machine_xt_laserxt_init(void); diff --git a/src/mca.c b/src/mca.c index 878b6f53d..65dcd9eda 100644 --- a/src/mca.c +++ b/src/mca.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "ibm.h" #include "io.h" #include "mem.h" diff --git a/src/mcr.c b/src/mcr.c index 1638afa1a..bdde8e27e 100644 --- a/src/mcr.c +++ b/src/mcr.c @@ -1,6 +1,10 @@ /*INTEL 82355 MCR emulation This chip was used as part of many 386 chipsets It controls memory addressing and shadowing*/ +#include +#include +#include +#include #include "ibm.h" diff --git a/src/mem.c b/src/mem.c index d19a70a52..5ef9e3c72 100644 --- a/src/mem.c +++ b/src/mem.c @@ -1,14 +1,11 @@ /* Copyright holders: Sarah Walker, Tenshi see COPYING for more details */ -/*MESS ROM notes : - - - pc2386 BIOS is corrupt (JMP at F000:FFF0 points to RAM) - - pc2386 video BIOS is underdumped (16k instead of 24k) - - c386sx16 BIOS fails checksum -*/ -#include +#include +#include #include +#include +#include #include "ibm.h" #include "cpu/cpu.h" #include "cpu/x86_ops.h" @@ -17,13 +14,16 @@ #include "io.h" #include "mem.h" #include "rom.h" +#ifdef USE_DYNAREC #include "cpu/codegen.h" -#include "video/video.h" +#else +#define PAGE_MASK_INDEX_MASK 3 +#define PAGE_MASK_INDEX_SHIFT 10 +#define PAGE_MASK_MASK 63 +#define PAGE_MASK_SHIFT 4 +#endif -page_t *pages; -page_t **page_lookup; - static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv); static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv); static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv); @@ -38,14 +38,17 @@ static mem_mapping_t *_mem_mapping_w[0x40000]; static int _mem_state[0x40000]; static mem_mapping_t base_mapping; +static mem_mapping_t ram_remapped_mapping; mem_mapping_t ram_low_mapping; mem_mapping_t ram_high_mapping; mem_mapping_t ram_mid_mapping; -static mem_mapping_t ram_remapped_mapping; mem_mapping_t bios_mapping[8]; mem_mapping_t bios_high_mapping[8]; mem_mapping_t romext_mapping; +page_t *pages; +page_t **page_lookup; + uint8_t *ram; uint32_t rammask; @@ -59,7 +62,8 @@ int writelookup[256],writelookupp[256]; uintptr_t *writelookup2; int writelnext; -int shadowbios,shadowbios_write; +int shadowbios = 0, + shadowbios_write; int mem_a20_state; @@ -67,814 +71,18 @@ unsigned char isram[0x10000]; static uint8_t ff_array[0x1000]; -int enable_xtide = 0; - int mem_size; uint32_t biosmask; int readlnum=0,writelnum=0; int cachesize=256; -uint8_t *ram,*rom; +uint8_t *rom; uint8_t romext[32768]; uint32_t ram_mapped_addr[64]; -static void mem_load_atide115_bios() -{ - FILE *f; - f=romfopen(L"roms/hdd/xtide/ide_at_1_1_5.bin",L"rb"); - if (f) - { - fread(romext,16384,1,f); - mem_mapping_enable(&romext_mapping); - fclose(f); - } -} - -int loadbios() -{ - FILE *f=NULL,*ff=NULL; - int c; - - loadfont(L"roms/video/mda/mda.rom", 0); - loadfont(L"roms/video/wyse700/wy700.rom", 3); - - biosmask = 0xffff; - - if (!rom) - rom = malloc(0x20000); - memset(romext,0xff,0x8000); - memset(rom, 0xff, 0x20000); - - pclog("Starting with romset %i\n", romset); - - mem_mapping_disable(&romext_mapping); - - switch (romset) - { - case ROM_PC1512: - f=romfopen(L"roms/machines/pc1512/40043.v1",L"rb"); - ff=romfopen(L"roms/machines/pc1512/40044.v1",L"rb"); - if (!f || !ff) break; - for (c=0xC000;c<0x10000;c+=2) - { - rom[c]=getc(f); - rom[c+1]=getc(ff); - } - fclose(ff); - fclose(f); - loadfont(L"roms/machines/pc1512/40078.ic127", 2); - return 1; - case ROM_PC1640: - f=romfopen(L"roms/machines/pc1640/40044.v3",L"rb"); - ff=romfopen(L"roms/machines/pc1640/40043.v3",L"rb"); - if (!f || !ff) break; - for (c=0xC000;c<0x10000;c+=2) - { - rom[c]=getc(f); - rom[c+1]=getc(ff); - } - fclose(ff); - fclose(f); - f=romfopen(L"roms/machines/pc1640/40100",L"rb"); - if (!f) break; - fclose(f); - return 1; - case ROM_PC200: - f=romfopen(L"roms/machines/pc200/pc20v2.1",L"rb"); - ff=romfopen(L"roms/machines/pc200/pc20v2.0",L"rb"); - if (!f || !ff) break; - for (c=0xC000;c<0x10000;c+=2) - { - rom[c]=getc(f); - rom[c+1]=getc(ff); - } - fclose(ff); - fclose(f); - loadfont(L"roms/machines/pc200/40109.bin", 1); - return 1; - case ROM_TANDY: - f=romfopen(L"roms/machines/tandy/tandy1t1.020",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - case ROM_TANDY1000HX: - f = romfopen(L"roms/machines/tandy1000hx/v020000.u12", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - case ROM_TANDY1000SL2: - f = romfopen(L"roms/machines/tandy1000sl2/8079047.hu1" ,L"rb"); - ff = romfopen(L"roms/machines/tandy1000sl2/8079048.hu2",L"rb"); - if (!f || !ff) break; - fseek(f, 0x30000/2, SEEK_SET); - fseek(ff, 0x30000/2, SEEK_SET); - for (c = 0x0000; c < 0x10000; c += 2) - { - rom[c] = getc(f); - rom[c + 1] = getc(ff); - } - fclose(ff); - fclose(f); - return 1; - case ROM_IBMXT: - f=romfopen(L"roms/machines/ibmxt/xt.rom",L"rb"); - if (!f) - { - f = romfopen(L"roms/machines/ibmxt/5000027.u19", L"rb"); - ff = romfopen(L"roms/machines/ibmxt/1501512.u18", L"rb"); - if (!f || !ff) break; - fread(rom, 0x8000, 1, f); - fread(rom + 0x8000, 0x8000, 1, ff); - fclose(ff); - fclose(f); - return 1; - } - else - { - fread(rom,65536,1,f); - fclose(f); - return 1; - } - break; - - case ROM_IBMPCJR: - f = romfopen(L"roms/machines/ibmpcjr/bios.rom", L"rb"); - if (!f) break; - fread(rom, 0x10000, 1, f); - fclose(f); - return 1; - - case ROM_PORTABLE: - f=romfopen(L"roms/machines/portable/Compaq Portable Plus 100666-001 Rev C u47.bin",L"rb"); - if (!f) break; - fread(rom+0xE000,8192,1,f); - fclose(f); - return 1; - -#if 0 - case ROM_PORTABLEII: - f = romfopen(L"roms/machines/portableii/106438-001.BIN", L"rb"); - ff =romfopen(L"roms/machines/portableii/106437-001.BIN", L"rb"); - if (!f || !ff) break; - for (c=0x0000;c<0x8000;c+=2) - { - rom[c]=getc(f); - rom[c+1]=getc(ff); - } - fclose(ff); - fclose(f); - biosmask = 0x7fff; - return 1; - - case ROM_PORTABLEIII: - case ROM_PORTABLEIII386: - f = romfopen(L"roms/machines/portableiii/109738-002.BIN", L"rb"); - ff =romfopen(L"roms/machines/portableiii/109737-002.BIN", L"rb"); - if (!f || !ff) break; - for (c=0x0000;c<0x10000;c+=2) - { - rom[c]=getc(f); - rom[c+1]=getc(ff); - } - fclose(ff); - fclose(f); - return 1; -#endif - - case ROM_GENXT: - f=romfopen(L"roms/machines/genxt/pcxt.rom",L"rb"); - if (!f) break; - fread(rom+0xE000,8192,1,f); - fclose(f); - return 1; - case ROM_DTKXT: - f=romfopen(L"roms/machines/dtk/DTK_ERSO_2.42_2764.bin",L"rb"); - if (!f) break; - fread(rom+0xE000,8192,1,f); - fclose(f); - return 1; - case ROM_OLIM24: - f = romfopen(L"roms/machines/olivetti_m24/olivetti_m24_version_1.43_low.bin" ,L"rb"); - ff = romfopen(L"roms/machines/olivetti_m24/olivetti_m24_version_1.43_high.bin",L"rb"); - if (!f || !ff) break; - for (c = 0x0000; c < 0x4000; c += 2) - { - rom[c + 0xc000] = getc(f); - rom[c + 0xc001] = getc(ff); - } - fclose(ff); - fclose(f); - return 1; - - case ROM_PC2086: - f = romfopen(L"roms/machines/pc2086/40179.ic129" ,L"rb"); - ff = romfopen(L"roms/machines/pc2086/40180.ic132",L"rb"); - if (!f || !ff) break; - pclog("Loading BIOS\n"); - for (c = 0x0000; c < 0x4000; c += 2) - { - rom[c + 0x0000] = getc(f); - rom[c + 0x0001] = getc(ff); - } - pclog("%02X %02X %02X\n", rom[0xfff0], rom[0xfff1], rom[0xfff2]); - fclose(ff); - fclose(f); - f = romfopen(L"roms/machines/pc2086/40186.ic171", L"rb"); - if (!f) break; - fclose(f); - biosmask = 0x3fff; - return 1; - - case ROM_PC3086: - f = romfopen(L"roms/machines/pc3086/fc00.bin", L"rb"); - if (!f) break; - fread(rom, 0x4000, 1, f); - fclose(f); - f = romfopen(L"roms/machines/pc3086/c000.bin", L"rb"); - if (!f) break; - fclose(f); - biosmask = 0x3fff; - return 1; - - case ROM_IBMAT: - f = romfopen(L"roms/machines/ibmat/62x0820.u27", L"rb"); - ff =romfopen(L"roms/machines/ibmat/62x0821.u47", L"rb"); - if (!f || !ff) break; - for (c=0x0000;c<0x10000;c+=2) - { - rom[c]=getc(f); - rom[c+1]=getc(ff); - } - fclose(ff); - fclose(f); - return 1; - - case ROM_CMDPC30: - f = romfopen(L"roms/machines/cmdpc30/commodore pc 30 iii even.bin", L"rb"); - ff = romfopen(L"roms/machines/cmdpc30/commodore pc 30 iii odd.bin", L"rb"); - if (!f || !ff) break; - for (c = 0x0000; c < 0x8000; c += 2) - { - rom[c] = getc(f); - rom[c + 1] = getc(ff); - } - fclose(ff); - fclose(f); - biosmask = 0x7fff; - return 1; - - case ROM_AMI386SX: - f=romfopen(L"roms/machines/ami386/ami386.bin",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - - case ROM_AMI386DX_OPTI495: /*This uses the OPTi 82C495 chipset*/ - f=romfopen(L"roms/machines/ami386dx/OPT495SX.AMI",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - case ROM_MR386DX_OPTI495: /*This uses the OPTi 82C495 chipset*/ - f=romfopen(L"roms/machines/mr386dx/OPT495SX.MR",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - - case ROM_AWARD386SX_OPTI495: /*This uses the OPTi 82C495 chipset*/ - case ROM_AWARD386DX_OPTI495: /*This uses the OPTi 82C495 chipset*/ - case ROM_AWARD486_OPTI495: /*This uses the OPTi 82C495 chipset*/ - f=romfopen(L"roms/machines/award495/OPT495S.AWA",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - - case ROM_AMI286: - f=romfopen(L"roms/machines/ami286/amic206.bin",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - - case ROM_AWARD286: - f=romfopen(L"roms/machines/award286/award.bin",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - - case ROM_EUROPC: - f=romfopen(L"roms/machines/europc/50145",L"rb"); - if (!f) break; - fread(rom+0x8000,32768,1,f); - fclose(f); - return 1; - - case ROM_IBMPC: - f=romfopen(L"roms/machines/ibmpc/pc102782.bin",L"rb"); - if (!f) break; - fread(rom+0xE000,8192,1,f); - fclose(f); - f=romfopen(L"roms/ibmpc/ibm-basic-1.10.rom",L"rb"); - if (!f) - { - f=romfopen(L"roms/machines/ibmpc/basicc11.f6",L"rb"); - if (!f) return 1; /*I don't really care if BASIC is there or not*/ - fread(rom+0x6000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/ibmpc/basicc11.f8",L"rb"); - if (!f) break; /*But if some of it is there, then all of it must be*/ - fread(rom+0x8000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/ibmpc/basicc11.fa",L"rb"); - if (!f) break; - fread(rom+0xA000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/ibmpc/basicc11.fc",L"rb"); - if (!f) break; - fread(rom+0xC000,8192,1,f); - fclose(f); - } - else - { - fread(rom+0x6000,32768,1,f); - fclose(f); - } - - return 1; - - case ROM_MEGAPC: - case ROM_MEGAPCDX: - f = romfopen(L"roms/machines/megapc/41651-bios lo.u18", L"rb"); - ff = romfopen(L"roms/machines/megapc/211253-bios hi.u19", L"rb"); - if (!f || !ff) break; - fseek(f, 0x8000, SEEK_SET); - fseek(ff, 0x8000, SEEK_SET); - for (c = 0x0000; c < 0x10000; c+=2) - { - rom[c]=getc(f); - rom[c+1]=getc(ff); - } - fclose(ff); - fclose(f); - return 1; - - case ROM_AMI486: - f=romfopen(L"roms/machines/ami486/ami486.BIN",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - - case ROM_WIN486: - f=romfopen(L"roms/machines/win486/ALI1429G.AMW",L"rb"); - if (!f) break; - fread(rom,65536,1,f); - fclose(f); - return 1; - - case ROM_430VX: - f = romfopen(L"roms/machines/430vx/55XWUQ0E.BIN", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_REVENGE: - f = romfopen(L"roms/machines/revenge/1009AF2_.BIO", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom + 0x10000, 0x10000, 1, f); - fclose(f); - f = romfopen(L"roms/machines/revenge/1009AF2_.BI1", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom, 0xc000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - case ROM_ENDEAVOR: - f = romfopen(L"roms/machines/endeavor/1006CB0_.BIO", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom + 0x10000, 0x10000, 1, f); - fclose(f); - f = romfopen(L"roms/machines/endeavor/1006CB0_.BI1", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom, 0xd000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_IBMPS1_2011: - f = romfopen(L"roms/machines/ibmps1es/f80000.bin", L"rb"); - if (!f) break; - fseek(f, 0x60000, SEEK_SET); - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_IBMPS1_2121: - case ROM_IBMPS1_2121_ISA: - f = romfopen(L"roms/machines/ibmps1_2121/fc0000.bin", L"rb"); - if (!f) break; - fseek(f, 0x20000, SEEK_SET); - fread(rom, 0x20000, 1, f); - fclose(f); - if (enable_xtide) - { - mem_load_atide115_bios(); - } - biosmask = 0x1ffff; - return 1; - - case ROM_IBMPS1_2133: - f = romfopen(L"roms/machines/ibmps1_2133/PS1_2133_52G2974_ROM.bin", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_DESKPRO_386: - f=romfopen(L"roms/machines/deskpro386/109592-005.U11.bin",L"rb"); - ff=romfopen(L"roms/machines/deskpro386/109591-005.U13.bin",L"rb"); - if (!f || !ff) break; - for (c = 0x0000; c < 0x8000; c += 2) - { - rom[c] = getc(f); - rom[c+1] = getc(ff); - } - fclose(ff); - fclose(f); - biosmask = 0x7fff; - return 1; - - case ROM_AMIXT: - f = romfopen(L"roms/machines/amixt/AMI_8088_BIOS_31JAN89.BIN", L"rb"); - if (!f) break; - fread(rom + 0xE000, 8192, 1, f); - fclose(f); - return 1; - - case ROM_LTXT: - f = romfopen(L"roms/machines/ltxt/27C64.bin", L"rb"); - if (!f) break; - fread(rom + 0xE000, 8192, 1, f); - fclose(f); - f=romfopen(L"roms/ltxt/ibm-basic-1.10.rom",L"rb"); - if (!f) - { - f=romfopen(L"roms/machines/ltxt/basicc11.f6",L"rb"); - if (!f) return 1; /*I don't really care if BASIC is there or not*/ - fread(rom+0x6000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/ltxt/basicc11.f8",L"rb"); - if (!f) break; /*But if some of it is there, then all of it must be*/ - fread(rom+0x8000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/ltxt/basicc11.fa",L"rb"); - if (!f) break; - fread(rom+0xA000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/ltxt/basicc11.fc",L"rb"); - if (!f) break; - fread(rom+0xC000,8192,1,f); - fclose(f); - } - else - { - fread(rom+0x6000,32768,1,f); - fclose(f); - } - - return 1; - - case ROM_LXT3: - f = romfopen(L"roms/machines/lxt3/27C64D.bin", L"rb"); - if (!f) break; - fread(rom + 0xE000, 8192, 1, f); - fclose(f); - f=romfopen(L"roms/machines/lxt3/ibm-basic-1.10.rom",L"rb"); - if (!f) - { - f=romfopen(L"roms/machines/lxt3/basicc11.f6",L"rb"); - if (!f) return 1; /*I don't really care if BASIC is there or not*/ - fread(rom+0x6000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/lxt3/basicc11.f8",L"rb"); - if (!f) break; /*But if some of it is there, then all of it must be*/ - fread(rom+0x8000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/lxt3/basicc11.fa",L"rb"); - if (!f) break; - fread(rom+0xA000,8192,1,f); - fclose(f); - f=romfopen(L"roms/machines/lxt3/basicc11.fc",L"rb"); - if (!f) break; - fread(rom+0xC000,8192,1,f); - fclose(f); - } - else - { - fread(rom+0x6000,32768,1,f); - fclose(f); - } - - return 1; - - case ROM_SPC4200P: /*Samsung SPC-4200P*/ - f = romfopen(L"roms/machines/spc4200p/U8.01", L"rb"); - if (!f) break; - fread(rom, 65536, 1, f); - fclose(f); - return 1; - - case ROM_SUPER286TR: /*Hyundai Super-286TR*/ - f = romfopen(L"roms/machines/super286tr/hyundai_award286.bin", L"rb"); - if (!f) break; - fread(rom, 65536, 1, f); - fclose(f); - return 1; - - case ROM_DTK386: /*Uses NEAT chipset*/ - f = romfopen(L"roms/machines/dtk386/3cto001.bin", L"rb"); - if (!f) break; - fread(rom, 65536, 1, f); - fclose(f); - return 1; - - case ROM_PXXT: - f = romfopen(L"roms/machines/pxxt/000p001.bin", L"rb"); - if (!f) break; - fread(rom + 0xE000, 8192, 1, f); - fclose(f); - return 1; - - case ROM_JUKOPC: - f = romfopen(L"roms/machines/jukopc/000o001.bin", L"rb"); - if (!f) break; - fread(rom + 0xE000, 8192, 1, f); - fclose(f); - return 1; - - case ROM_IBMPS2_M30_286: - f = romfopen(L"roms/machines/ibmps2_m30_286/33f5381a.bin", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - if (enable_xtide) - { - mem_load_atide115_bios(); - } - biosmask = 0x1ffff; - return 1; - - case ROM_DTK486: - f = romfopen(L"roms/machines/dtk486/4siw005.bin", L"rb"); - if (!f) break; - fread(rom, 0x10000, 1, f); - fclose(f); - return 1; - - case ROM_R418: - f = romfopen(L"roms/machines/r418/r418i.bin", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - pclog("Load R418 %x %x\n", rom[0x1fff0], rom[0xfff0]); - return 1; - -#if 0 - case ROM_586MC1: - f = romfopen(L"roms/machines/586mc1/IS.34", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; -#endif - - case ROM_PLATO: - f = romfopen(L"roms/machines/plato/1016AX1_.BIO", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom + 0x10000, 0x10000, 1, f); - fclose(f); - f = romfopen(L"roms/machines/plato/1016AX1_.BI1", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom, 0xd000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_MB500N: - f = romfopen(L"roms/machines/mb500n/031396S.BIN", L"rb"); /* Works */ - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_AP53: - f = romfopen(L"roms/machines/ap53/AP53R2C0.ROM", L"rb"); /* Works */ - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_P55T2S: - f = romfopen(L"roms/machines/p55t2s/S6Y08T.ROM", L"rb"); /* Works */ - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_PRESIDENT: - f = romfopen(L"roms/machines/president/BIOS.BIN", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_P54TP4XE: - f = romfopen(L"roms/machines/p54tp4xe/T15I0302.AWD", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_ACERM3A: - f = romfopen(L"roms/machines/acerm3a/r01-b3.bin", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_ACERV35N: - f = romfopen(L"roms/machines/acerv35n/V35ND1S1.BIN", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_P55VA: - f = romfopen(L"roms/machines/p55va/VA021297.BIN", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_P55T2P4: - f = romfopen(L"roms/machines/p55t2p4/0207_J2.BIN", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_P55TVP4: - f = romfopen(L"roms/machines/p55tvp4/TV5I0204.AWD", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_440FX: - f = romfopen(L"roms/machines/440fx/NTMAW501.BIN", L"rb"); /* Working Tyan BIOS. */ - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_S1668: - f = romfopen(L"roms/machines/tpatx/S1668P.ROM", L"rb"); /* Working Tyan BIOS. */ - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_THOR: - f = romfopen(L"roms/machines/thor/1006CN0_.BIO", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom + 0x10000, 0x10000, 1, f); - fclose(f); - f = romfopen(L"roms/machines/thor/1006CN0_.BI1", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom, 0x10000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_MRTHOR: - f = romfopen(L"roms/machines/mrthor/MR_ATX.BIO", L"rb"); - if (!f) break; - fread(rom, 0x20000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_ZAPPA: - f = romfopen(L"roms/machines/zappa/1006BS0_.BIO", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom + 0x10000, 0x10000, 1, f); - fclose(f); - f = romfopen(L"roms/machines/zappa/1006BS0_.BI1", L"rb"); - if (!f) break; - fseek(f, 0x80, SEEK_SET); - fread(rom, 0x10000, 1, f); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_IBMPS2_M50: - f=romfopen(L"roms/machines/ibmps2_m50/90x7423.zm14",L"rb"); - ff=romfopen(L"roms/machines/ibmps2_m50/90x7426.zm16",L"rb"); - if (!f || !ff) break; - for (c = 0x0000; c < 0x10000; c += 2) - { - rom[c] = getc(f); - rom[c+1] = getc(ff); - } - fclose(ff); - fclose(f); - f=romfopen(L"roms/machines/ibmps2_m50/90x7420.zm13",L"rb"); - ff=romfopen(L"roms/machines/ibmps2_m50/90x7429.zm18",L"rb"); - if (!f || !ff) break; - for (c = 0x10000; c < 0x20000; c += 2) - { - rom[c] = getc(f); - rom[c+1] = getc(ff); - } - fclose(ff); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_IBMPS2_M55SX: - f=romfopen(L"roms/machines/ibmps2_m55sx/33f8146.zm41",L"rb"); - ff=romfopen(L"roms/machines/ibmps2_m55sx/33f8145.zm40",L"rb"); - if (!f || !ff) break; - for (c = 0x0000; c < 0x20000; c += 2) - { - rom[c] = getc(f); - rom[c+1] = getc(ff); - } - fclose(ff); - fclose(f); - biosmask = 0x1ffff; - return 1; - - case ROM_IBMPS2_M80: - case ROM_IBMPS2_M80_486: - f=romfopen(L"roms/machines/ibmps2_m80/15f6637.bin",L"rb"); - ff=romfopen(L"roms/machines/ibmps2_m80/15f6639.bin",L"rb"); - if (!f || !ff) break; - for (c = 0x0000; c < 0x20000; c += 2) - { - rom[c] = getc(f); - rom[c+1] = getc(ff); - } - fclose(ff); - fclose(f); - biosmask = 0x1ffff; - return 1; - } - printf("Failed to load ROM!\n"); - if (f) fclose(f); - if (ff) fclose(ff); - return 0; -} - - - -void resetreadlookup() +void resetreadlookup(void) { int c; memset(readlookup2,0xFF,1024*1024*sizeof(uintptr_t)); @@ -890,7 +98,7 @@ void resetreadlookup() int mmuflush=0; int mmu_perm=4; -void flushmmucache() +void flushmmucache(void) { int c; for (c=0;c<256;c++) @@ -911,10 +119,12 @@ void flushmmucache() pccache=(uint32_t)0xFFFFFFFF; pccache2=(uint8_t *)0xFFFFFFFF; +#ifdef USE_DYNAREC codegen_flush(); +#endif } -void flushmmucache_nopc() +void flushmmucache_nopc(void) { int c; for (c=0;c<256;c++) @@ -933,7 +143,7 @@ void flushmmucache_nopc() } } -void flushmmucache_cr3() +void flushmmucache_cr3(void) { int c; for (c=0;c<256;c++) @@ -982,7 +192,7 @@ int pctrans=0; extern uint32_t testr[9]; -int mem_cpl3_check() +int mem_cpl3_check(void) { if ((CPL == 3) && !cpl_override) { @@ -1164,7 +374,11 @@ void addwritelookup(uint32_t virt, uint32_t phys) writelookup2[writelookup[writelnext]] = -1; } +#ifdef USE_DYNAREC if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) +#else + if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3]) +#endif page_lookup[virt >> 12] = &pages[phys >> 12]; else writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; @@ -1743,7 +957,11 @@ uint32_t mem_read_raml(uint32_t addr, void *priv) void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) { +#ifdef USE_DYNAREC if (val != p->mem[addr & 0xfff] || codegen_in_recompile) +#else + if (val != p->mem[addr & 0xfff]) +#endif { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; @@ -1752,7 +970,11 @@ void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) } void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) { +#ifdef USE_DYNAREC if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) +#else + if (val != *(uint16_t *)&p->mem[addr & 0xfff]) +#endif { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); if ((addr & 0xf) == 0xf) @@ -1763,7 +985,11 @@ void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) } void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) { +#ifdef USE_DYNAREC if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) +#else + if (val != *(uint32_t *)&p->mem[addr & 0xfff]) +#endif { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); if ((addr & 0xf) >= 0xd) @@ -2120,13 +1346,14 @@ void mem_add_bios() int mem_a20_key = 0, mem_a20_alt = 0; int mem_a20_state = 1; -void mem_init() +void mem_init(void) { int c; ram = malloc(mem_size * 1024); readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); + rom = NULL; biosmask = 0xffff; pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t)); page_lookup = malloc((1 << 20) * sizeof(page_t *)); @@ -2299,9 +1526,10 @@ void mem_reset_page_blocks() } } + static int port_92_reg = 0; -void mem_a20_recalc() +void mem_a20_recalc(void) { int state = mem_a20_key | mem_a20_alt; if (state && !mem_a20_state) @@ -2317,11 +1545,13 @@ void mem_a20_recalc() mem_a20_state = state; } + static uint8_t port_92_read(uint16_t port, void *priv) { return port_92_reg; } + static void port_92_write(uint16_t port, uint8_t val, void *priv) { if ((mem_a20_alt ^ val) & 2) @@ -2339,22 +1569,23 @@ static void port_92_write(uint16_t port, uint8_t val, void *priv) port_92_reg = val; } -void port_92_clear_reset() + +void port_92_clear_reset(void) { port_92_reg &= 2; } -void port_92_add() +void port_92_add(void) { io_sethandler(0x0092, 0x0001, port_92_read, NULL, NULL, port_92_write, NULL, NULL, NULL); } -void port_92_remove() +void port_92_remove(void) { io_removehandler(0x0092, 0x0001, port_92_read, NULL, NULL, port_92_write, NULL, NULL, NULL); } -void port_92_reset() +void port_92_reset(void) { port_92_reg = 0; mem_a20_alt = 0; diff --git a/src/mem.h b/src/mem.h index ec9c44740..29dd69b15 100644 --- a/src/mem.h +++ b/src/mem.h @@ -173,26 +173,23 @@ void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p); void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p); void mem_flush_write_page(uint32_t addr, uint32_t virt); -void mem_reset_page_blocks(); +extern void mem_reset_page_blocks(void); extern mem_mapping_t ram_low_mapping; extern mem_mapping_t ram_mid_mapping; -void mem_remap_top_256k(); -void mem_remap_top_384k(); +extern void mem_remap_top_256k(void); +extern void mem_remap_top_384k(void); -void flushmmucache_nopc(); +extern void flushmmucache_nopc(void); -int loadbios(); +extern void mem_add_bios(void); -void mem_add_bios(); +extern void mem_init(void); +extern void mem_resize(void); -void mem_init(); -void mem_resize(); - -void port_92_reset(); - -void port_92_add(); -void port_92_remove(); +extern void port_92_reset(void); +extern void port_92_add(void); +extern void port_92_remove(void); #endif diff --git a/src/memregs.c b/src/memregs.c index 75b8a1a58..018f07d84 100644 --- a/src/memregs.c +++ b/src/memregs.c @@ -9,12 +9,15 @@ * Emulation of the memory I/O scratch registers on ports 0xE1 * and 0xE2, used by just about any emulated machine. * - * Version: @(#)memregs.c 1.0.1 2017/08/23 + * Version: @(#)memregs.c 1.0.2 2017/09/24 * * Author: Miran Grca, * Copyright 2016-2017 Miran Grca. */ - +#include +#include +#include +#include #include "ibm.h" #include "io.h" #include "memregs.h" @@ -24,6 +27,7 @@ static uint8_t mem_regs[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0 static uint8_t mem_reg_ffff = 0; + void memregs_write(uint16_t port, uint8_t val, void *priv) { if (port == 0xffff) diff --git a/src/mouse.c b/src/mouse.c index 4bf146548..567fba71a 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -8,17 +8,21 @@ * * Common driver module for MOUSE devices. * - * Version: @(#)mouse.c 1.0.7 2017/09/02 + * Version: @(#)mouse.c 1.0.9 2017/10/09 * * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "ibm.h" -#include "cpu/cpu.h" #include "device.h" #include "mouse.h" #include "machine/machine.h" diff --git a/src/mouse_bus.c b/src/mouse_bus.c index 7b70ca712..fa2225685 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -32,14 +32,17 @@ * Based on an early driver for MINIX 1.5. * Based on the 86Box PS/2 mouse driver as a framework. * - * Version: @(#)mouse_bus.c 1.0.8 2017/08/03 + * Version: @(#)mouse_bus.c 1.0.9 2017/09/24 * * Authors: Fred N. van Kempen, * TheCollector1995 * Copyright 1989-2017 Fred N. van Kempen. */ #include +#include +#include #include +#include #include "ibm.h" #include "io.h" #include "pic.h" diff --git a/src/mouse_ps2.c b/src/mouse_ps2.c index 9d3b677f0..a7dd4319a 100644 --- a/src/mouse_ps2.c +++ b/src/mouse_ps2.c @@ -1,4 +1,8 @@ +#include +#include +#include #include +#include #include "ibm.h" #include "keyboard_at.h" #include "mouse.h" diff --git a/src/mouse_serial.c b/src/mouse_serial.c index 40b80f44a..69420b17f 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -10,11 +10,15 @@ * * Based on the 86Box Serial Mouse driver as a framework. * - * Version: @(#)mouse_serial.c 1.0.8 2017/08/03 + * Version: @(#)mouse_serial.c 1.0.9 2017/09/24 * * Author: Fred N. van Kempen, */ +#include +#include +#include #include +#include #include "ibm.h" #include "timer.h" #include "serial.h" @@ -24,8 +28,8 @@ typedef struct mouse_serial_t { int8_t port, type; - int pos, - delay; + int pos; + int64_t delay; int oldb; SERIAL *serial; } mouse_serial_t; @@ -43,7 +47,7 @@ sermouse_callback(struct SERIAL *serial, void *priv) /* Start a timer to wake us up in a little while. */ ms->pos = -1; - ms->delay = 5000 * (1 << TIMER_SHIFT); + ms->delay = 5000LL * (1LL << TIMER_SHIFT); } @@ -53,7 +57,7 @@ sermouse_timer(void *priv) { mouse_serial_t *ms = (mouse_serial_t *)priv; - ms->delay = 0; + ms->delay = 0LL; if (ms->pos != -1) return; diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 92c28fd89..449623715 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -10,7 +10,7 @@ * * NOTE: The file will also implement an NE1000 for 8-bit ISA systems. * - * Version: @(#)net_ne2000.c 1.0.14 2017/09/03 + * Version: @(#)net_ne2000.c 1.0.18 2017/10/09 * * Authors: Fred N. van Kempen, * Peter Grehan, grehan@iprg.nokia.com> @@ -18,11 +18,14 @@ * * Based on @(#)ne2k.cc v1.56.2.1 2004/02/02 22:37:22 cbothamy * Portions Copyright (C) 2002 MandrakeSoft S.A. + * Copyright 2017 Fred N. van Kempen. */ -#include #include -#include +#include #include +#include +#include +#include #include #include "../config.h" #include "../ibm.h" @@ -33,6 +36,7 @@ #include "../pic.h" #include "../random.h" #include "../device.h" +#include "../ui.h" #include "network.h" #include "net_ne2000.h" #include "bswap.h" @@ -495,6 +499,7 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) { nelog(3, "%s: ASIC write addr=0x%02x, value=0x%04x\n", dev->name, (unsigned)off, (unsigned) val); + switch(off) { case 0x00: /* Data register - see asic_read for a description */ if ((len > 1) && (dev->DCR.wdsize == 0)) { @@ -502,30 +507,25 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) dev->name, len); break; } - if (dev->remote_bytes == 0) { + if (dev->remote_bytes == 0) nelog(3, "%s: DMA write, byte count 0\n", dev->name); - } chipmem_write(dev, dev->remote_dma, val, len); - if (len == 4) { + if (len == 4) dev->remote_dma += len; - } else { + else dev->remote_dma += (dev->DCR.wdsize + 1); - } - if (dev->remote_dma == dev->page_stop << 8) { + if (dev->remote_dma == dev->page_stop << 8) dev->remote_dma = dev->page_start << 8; - } - if (len == 4) { + if (len == 4) dev->remote_bytes -= len; - } else { + else dev->remote_bytes -= (dev->DCR.wdsize + 1); - } - if (dev->remote_bytes > NE2K_MEMSIZ) { + if (dev->remote_bytes > NE2K_MEMSIZ) dev->remote_bytes = 0; - } /* If all bytes have been written, signal remote-DMA complete */ if (dev->remote_bytes == 0) { @@ -1421,13 +1421,10 @@ nic_update_bios(nic_t *dev) reg_bios_enable = 1; - if (!dev->has_bios) { - return; - } + if (! dev->has_bios) return; - if (PCI && dev->is_pci) { + if (PCI && dev->is_pci) reg_bios_enable = dev->pci_bar[1].addr_regs[0] & 0x01; - } /* PCI BIOS stuff, just enable_disable. */ if (reg_bios_enable) { @@ -1652,26 +1649,22 @@ static int mcast_index(const void *dst) { #define POLYNOMIAL 0x04c11db6 - unsigned long crc = 0xffffffffL; - int carry, i, j; - unsigned char b; - unsigned char *ep = (unsigned char *) dst; + uint32_t crc = 0xffffffffL; + int carry, i, j; + uint8_t b; + uint8_t *ep = (uint8_t *)dst; - for (i = 6; --i >= 0;) - { - b = *ep++; - for (j = 8; --j >= 0;) - { - carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); - crc <<= 1; - b >>= 1; - if (carry) - { - crc = ((crc ^ POLYNOMIAL) | carry); - } - } + for (i=6; --i>=0;) { + b = *ep++; + for (j = 8; --j >= 0;) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) + crc = ((crc ^ POLYNOMIAL) | carry); } - return (crc >> 26); + } + return(crc >> 26); #undef POLYNOMIAL } @@ -1679,7 +1672,7 @@ mcast_index(const void *dst) static void nic_tx(nic_t *dev, uint32_t val) { - update_status_bar_icon(SB_NETWORK, 1); + ui_sb_update_icon(SB_NETWORK, 1); dev->CR.tx_packet = 0; dev->TSR.tx_ok = 1; @@ -1690,7 +1683,7 @@ nic_tx(nic_t *dev, uint32_t val) nic_interrupt(dev, 1); dev->tx_timer_active = 0; - update_status_bar_icon(SB_NETWORK, 0); + ui_sb_update_icon(SB_NETWORK, 0); } @@ -1711,7 +1704,7 @@ nic_rx(void *priv, uint8_t *buf, int io_len) int idx, nextpage; int endbytes; - update_status_bar_icon(SB_NETWORK, 1); + ui_sb_update_icon(SB_NETWORK, 1); if (io_len != 60) nelog(2, "%s: rx_frame with length %d\n", dev->name, io_len); @@ -1742,14 +1735,14 @@ nic_rx(void *priv, uint8_t *buf, int io_len) ) { nelog(1, "%s: no space\n", dev->name); - update_status_bar_icon(SB_NETWORK, 0); + ui_sb_update_icon(SB_NETWORK, 0); return; } if ((io_len < 40/*60*/) && !dev->RCR.runts_ok) { nelog(1, "%s: rejected small packet, length %d\n", dev->name, io_len); - update_status_bar_icon(SB_NETWORK, 0); + ui_sb_update_icon(SB_NETWORK, 0); return; } @@ -1771,7 +1764,7 @@ nic_rx(void *priv, uint8_t *buf, int io_len) if (! dev->RCR.broadcast) { nelog(2, "%s: RX BC disabled\n", dev->name); - update_status_bar_icon(SB_NETWORK, 0); + ui_sb_update_icon(SB_NETWORK, 0); return; } } @@ -1784,7 +1777,7 @@ nic_rx(void *priv, uint8_t *buf, int io_len) nelog(2, "%s: RX MC disabled\n", dev->name); #endif - update_status_bar_icon(SB_NETWORK, 0); + ui_sb_update_icon(SB_NETWORK, 0); return; } @@ -1793,7 +1786,7 @@ nic_rx(void *priv, uint8_t *buf, int io_len) if (! (dev->mchash[idx>>3] & (1<<(idx&0x7)))) { nelog(2, "%s: RX MC not listed\n", dev->name); - update_status_bar_icon(SB_NETWORK, 0); + ui_sb_update_icon(SB_NETWORK, 0); return; } } @@ -1839,7 +1832,7 @@ nic_rx(void *priv, uint8_t *buf, int io_len) if (dev->IMR.rx_inte) nic_interrupt(dev, 1); - update_status_bar_icon(SB_NETWORK, 0); + ui_sb_update_icon(SB_NETWORK, 0); } @@ -1849,35 +1842,32 @@ nic_rom_init(nic_t *dev, wchar_t *s) uint32_t temp; FILE *f; - if (s == NULL) - { + if (s == NULL) return; + + if (dev->bios_addr == 0) return; + + if ((f = rom_fopen(s, L"rb")) != NULL) { + fseek(f, 0L, SEEK_END); + temp = ftell(f); + fclose(f); + dev->bios_size = 0x10000; + if (temp <= 0x8000) + dev->bios_size = 0x8000; + if (temp <= 0x4000) + dev->bios_size = 0x4000; + if (temp <= 0x2000) + dev->bios_size = 0x2000; + dev->bios_mask = (dev->bios_size >> 8) & 0xff; + dev->bios_mask = (0x100 - dev->bios_mask) & 0xff; + } else { + dev->bios_addr = 0x00000; + dev->bios_size = 0; return; } - if (dev->bios_addr > 0) { - if ((f = romfopen(s, L"rb")) != NULL) { - fseek(f, 0L, SEEK_END); - temp = ftell(f); - fclose(f); - dev->bios_size = 0x10000; - if (temp <= 0x8000) - dev->bios_size = 0x8000; - if (temp <= 0x4000) - dev->bios_size = 0x4000; - if (temp <= 0x2000) - dev->bios_size = 0x2000; - dev->bios_mask = (dev->bios_size >> 8) & 0xff; - dev->bios_mask = (0x100 - dev->bios_mask) & 0xff; - } else { - dev->bios_addr = 0x00000; - dev->bios_size = 0; - return; - } - - /* Create a memory mapping for the space. */ - rom_init(&dev->bios_rom, s, dev->bios_addr, - dev->bios_size, dev->bios_size-1, 0, MEM_MAPPING_EXTERNAL); - } + /* Create a memory mapping for the space. */ + rom_init(&dev->bios_rom, s, dev->bios_addr, + dev->bios_size, dev->bios_size-1, 0, MEM_MAPPING_EXTERNAL); nelog(1, "%s: BIOS configured at %06lX (size %ld)\n", dev->name, dev->bios_addr, dev->bios_size); @@ -1885,7 +1875,7 @@ nic_rom_init(nic_t *dev, wchar_t *s) static void * -nic_init(int board) +nic_init(device_t *info) { uint32_t mac; wchar_t *rom; @@ -1898,9 +1888,10 @@ nic_init(int board) dev = malloc(sizeof(nic_t)); memset(dev, 0x00, sizeof(nic_t)); - dev->board = board; + dev->board = info->local; rom = NULL; switch(dev->board) { +#if defined(DEV_BRANCH) && defined(USE_NE1000) case NE2K_NE1000: strcpy(dev->name, "NE1000"); dev->maclocal[0] = 0x00; /* 00:00:D8 (NE1000 ISA OID) */ @@ -1908,6 +1899,7 @@ nic_init(int board) dev->maclocal[2] = 0xD8; rom = ROM_PATH_NE1000; break; +#endif case NE2K_NE2000: strcpy(dev->name, "NE2000"); @@ -1930,19 +1922,13 @@ nic_init(int board) if (dev->is_pci) { dev->base_address = 0x340; dev->base_irq = 10; + dev->bios_addr = 0xD0000; + dev->has_bios = device_get_config_int("bios"); } else { dev->base_address = device_get_config_hex16("base"); dev->base_irq = device_get_config_int("irq"); - } - - dev->bios_addr = device_get_config_hex20("bios_addr"); - if (dev->bios_addr) - { - dev->has_bios = 1; - } - else - { - dev->has_bios = 0; + dev->bios_addr = device_get_config_hex20("bios_addr"); + dev->has_bios = !!dev->bios_addr; } /* See if we have a local MAC address configured. */ @@ -2060,6 +2046,8 @@ nic_init(int board) nelog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name, dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq); + ui_sb_update_icon(SB_NETWORK, 0); + return(dev); } @@ -2080,27 +2068,7 @@ nic_close(void *priv) } -static void * -ne1000_init(void) -{ - return(nic_init(NE2K_NE1000)); -} - - -static void * -ne2000_init(void) -{ - return(nic_init(NE2K_NE2000)); -} - - -static void * -rtl8029as_init(void) -{ - return(nic_init(NE2K_RTL8029AS)); -} - - +#if defined(DEV_BRANCH) && defined(USE_NE1000) static device_config_t ne1000_config[] = { { @@ -2173,6 +2141,7 @@ static device_config_t ne1000_config[] = "", "", -1 } }; +#endif static device_config_t ne2000_config[] = { @@ -2255,31 +2224,8 @@ static device_config_t ne2000_config[] = static device_config_t rtl8029as_config[] = { - /* - * WTF. - * Even though it is PCI, the user should still have control - * over whether or not it's Option ROM BIOS will be enabled - * or not. - */ { - "bios_addr", "BIOS address", CONFIG_HEX20, "", 0, - { - { - "Disabled", 0x00000 - }, - { - "D000", 0xD0000 - }, - { - "D800", 0xD8000 - }, - { - "C800", 0xC8000 - }, - { - "" - } - }, + "bios", "Enable BIOS", CONFIG_BINARY, "", 0 }, { "mac", "MAC Address", CONFIG_MAC, "", -1 @@ -2290,39 +2236,31 @@ static device_config_t rtl8029as_config[] = }; - +#if defined(DEV_BRANCH) && defined(USE_NE1000) device_t ne1000_device = { "Novell NE1000", 0, - ne1000_init, - nic_close, - NULL, - NULL, - NULL, - NULL, + NE2K_NE1000, + nic_init, nic_close, NULL, + NULL, NULL, NULL, NULL, ne1000_config }; +#endif device_t ne2000_device = { "Novell NE2000", - 0, - ne2000_init, - nic_close, - NULL, - NULL, - NULL, - NULL, + DEVICE_AT, + NE2K_NE2000, + nic_init, nic_close, NULL, + NULL, NULL, NULL, NULL, ne2000_config }; device_t rtl8029as_device = { "Realtek RTL8029AS", - 0, - rtl8029as_init, - nic_close, - NULL, - NULL, - NULL, - NULL, + DEVICE_PCI, + NE2K_RTL8029AS, + nic_init, nic_close, NULL, + NULL, NULL, NULL, NULL, rtl8029as_config }; diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index f7e3ebf9d..96b14ad7f 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -8,21 +8,24 @@ * * Handle WinPcap library processing. * - * Version: @(#)net_pcap.c 1.0.5 2017/06/04 + * Version: @(#)net_pcap.c 1.0.9 2017/10/11 * * Author: Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen. */ -#include #include -#include +#include #include +#include +#include #include #include "../ibm.h" #include "../config.h" #include "../device.h" +#include "../plat.h" +#include "../plat_dynld.h" #include "network.h" -#include "../win/plat_dynld.h" -#include "../win/plat_thread.h" static void *pcap_handle; /* handle to WinPcap DLL */ diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 571ce204f..cbcf53069 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -8,27 +8,46 @@ * * Handle SLiRP library processing. * - * Version: @(#)net_slirp.c 1.0.4 2017/06/14 + * Version: @(#)net_slirp.c 1.0.9 2017/10/14 * * Author: Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen. */ -#include #include -#include +#include #include +#include +#include #include "slirp/slirp.h" #include "slirp/queue.h" #include "../ibm.h" #include "../config.h" #include "../device.h" +#include "../plat.h" #include "network.h" -#include "../win/plat_thread.h" static queueADT slirpq; /* SLiRP library handle */ static thread_t *poll_tid; static NETRXCB poll_rx; /* network RX function to call */ static void *poll_arg; /* network RX function arg */ +static mutex_t *slirpMutex; + + + +static void +startslirp(void) +{ + thread_wait_mutex(slirpMutex); +} + + +static void +endslirp(void) +{ + thread_release_mutex(slirpMutex); +} /* Instead of calling this and crashing some times @@ -128,6 +147,8 @@ poll_thread(void *arg) thread_destroy_event(evt); evt = poll_tid = NULL; + thread_close_mutex(slirpMutex); + pclog("SLiRP: polling stopped.\n"); } @@ -150,6 +171,8 @@ network_slirp_setup(uint8_t *mac, NETRXCB func, void *arg) poll_rx = func; poll_arg = arg; + slirpMutex = thread_create_mutex(L"86Box.SLiRPMutex"); + poll_data.wake_poll_thread = thread_create_event(); poll_data.poll_complete = thread_create_event(); @@ -182,6 +205,8 @@ network_slirp_close(void) ; #endif + thread_close_mutex(slirpMutex); + /* OK, now shut down SLiRP itself. */ QueueDestroy(sl); slirp_exit(0); diff --git a/src/network/network.c b/src/network/network.c index 03f781c88..f6866def0 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -12,26 +12,31 @@ * it should be malloc'ed and then linked to the NETCARD def. * Will be done later. * - * Version: @(#)network.c 1.0.10 2017/06/14 + * Version: @(#)network.c 1.0.13 2017/10/09 * * Author: Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen. */ -#include #include -#include +#include #include +#include +#include #include "../ibm.h" #include "../device.h" +#include "../ui.h" #include "network.h" #include "net_ne2000.h" -#include "../win/plat_ui.h" static netcard_t net_cards[] = { { "None", "none", NULL, NULL, NULL }, +#if defined(DEV_BRANCH) && defined(USE_NE1000) { "Novell NE1000", "ne1k", &ne1000_device, NULL, NULL }, +#endif { "Novell NE2000", "ne2k", &ne2000_device, NULL, NULL }, { "Realtek RTL8029AS", "ne2kpci", &rtl8029as_device, @@ -42,12 +47,12 @@ static netcard_t net_cards[] = { /* Global variables. */ -int network_card; int network_type; int network_ndev; -int nic_do_log; +int network_card; netdev_t network_devs[32]; char network_pcap[512]; +int nic_do_log; /* @@ -68,10 +73,9 @@ network_init(void) nic_do_log = 0; #endif -#if 0 + /* Initialize to a known state. */ network_type = NET_TYPE_NONE; network_card = 0; -#endif /* Create a first device entry that's always there, as needed by UI. */ strcpy(network_devs[0].device, "none"); @@ -111,7 +115,7 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx) case NET_TYPE_PCAP: ret = network_pcap_setup(mac, rx, dev); if (ret < 0) { - plat_msgbox_error(IDS_2139); + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2139); network_type = NET_TYPE_NONE; } break; diff --git a/src/network/network.h b/src/network/network.h index 6ec70e6c5..4c6103468 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -70,6 +70,7 @@ extern void network_pcap_close(void); extern int network_pcap_test(void); extern void network_pcap_in(uint8_t *, int); +extern void network_slirp_mutex_init(void); extern int network_slirp_setup(uint8_t *, NETRXCB, void *); extern void network_slirp_close(void); extern int network_slirp_test(void); diff --git a/src/network/pcap_if.c b/src/network/pcap_if.c index 31ec33f7d..2d1c525d1 100644 --- a/src/network/pcap_if.c +++ b/src/network/pcap_if.c @@ -10,16 +10,18 @@ * * Based on the "libpcap" examples. * - * Version: @(#)pcap_if.c 1.0.3 2017/06/04 + * Version: @(#)pcap_if.c 1.0.5 2017/10/10 * * Author: Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen. */ #include #include #include #include #include -#include "plat_dynld.h" +#include "../plat_dynld.h" static void *pcap_handle; /* handle to WinPcap DLL */ diff --git a/src/network/slirp/debug.c b/src/network/slirp/debug.c index 556e02672..50cae86a7 100644 --- a/src/network/slirp/debug.c +++ b/src/network/slirp/debug.c @@ -6,6 +6,9 @@ * terms and conditions of the copyright. */ +#ifndef WIN32 +# include +#endif #include "slirp.h" FILE *dfd = NULL; diff --git a/src/network/slirp/misc.c b/src/network/slirp/misc.c index 90bc2483e..0da04dee2 100644 --- a/src/network/slirp/misc.c +++ b/src/network/slirp/misc.c @@ -7,6 +7,9 @@ #define WANT_SYS_IOCTL_H #include +#ifndef WIN32 +# include +#endif #include "slirp.h" u_int curtime, time_fasttimo, last_slowtimo, detach_time; diff --git a/src/network/slirp/slirp.h b/src/network/slirp/slirp.h index 3f4efd0bd..0cacdb8ca 100644 --- a/src/network/slirp/slirp.h +++ b/src/network/slirp/slirp.h @@ -59,6 +59,12 @@ typedef unsigned long ioctlsockopt_t; # define init_udp slirp_init_udp # define final_udp slirp_final_udp #else +# include +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; +typedef char *SLIRPcaddr_t; typedef int ioctlsockopt_t; # define ioctlsocket ioctl # define closesocket(s) close(s) diff --git a/src/network/slirp/socket.c b/src/network/slirp/socket.c index 5e6fb2dc0..fba38fc79 100644 --- a/src/network/slirp/socket.c +++ b/src/network/slirp/socket.c @@ -7,6 +7,9 @@ #define WANT_SYS_IOCTL_H #include +#ifndef WIN32 +# include +#endif #include "slirp.h" #include "ip_icmp.h" #include "main.h" diff --git a/src/network/slirp/tcp_subr.c b/src/network/slirp/tcp_subr.c index cb0f0750a..5168e4ae4 100644 --- a/src/network/slirp/tcp_subr.c +++ b/src/network/slirp/tcp_subr.c @@ -40,6 +40,9 @@ #define WANT_SYS_IOCTL_H #include +#ifndef WIN32 +# include +#endif #include "slirp.h" /* patchable/settable parameters for tcp */ diff --git a/src/network/slirp/udp.c b/src/network/slirp/udp.c index fbeb3c340..7c7d0831b 100644 --- a/src/network/slirp/udp.c +++ b/src/network/slirp/udp.c @@ -39,6 +39,9 @@ */ #include +#ifndef WIN32 +# include +#endif #include "slirp.h" #include "ip_icmp.h" diff --git a/src/nmi.c b/src/nmi.c index 59b50fd65..fc6a2698e 100644 --- a/src/nmi.c +++ b/src/nmi.c @@ -1,6 +1,10 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" #include "nmi.h" diff --git a/src/nvr.c b/src/nvr.c index c888f8358..dea2717ef 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -6,322 +6,774 @@ * * This file is part of the 86Box distribution. * - * CMOS NVRAM emulation. + * Implement a more-or-less defacto-standard RTC/NVRAM. * - * Version: @(#)nvr.c 1.0.2 2017/09/03 + * When IBM released the PC/AT machine, it came standard with a + * battery-backed RTC chip to keep the time of day, something + * that was optional on standard PC's with a myriad variants + * being put on the market, often on cheap multi-I/O cards. + * + * The PC/AT had an on-board DS12885-series chip ("the black + * block") which was an RTC/clock chip with onboard oscillator + * and a backup battery (hence the big size.) The chip also had + * a smal amount of RAM bytes available to the user, which was + * used by IBM's ROM BIOS to store machine configuration data. + * + * Since then, pretty much any PC has an implementation of that + * device, which became known as the "nvr" or "cmos". + * + * NOTES Info extracted from the data sheets: + * + * * The century register at location 32h is a BCD register + * designed to automatically load the BCD value 20 as the + * year register changes from 99 to 00. The MSB of this + * register is not affected when the load of 20 occurs, + * and remains at the value written by the user. + * + * * Rate Selector (RS3:RS0) + * These four rate-selection bits select one of the 13 + * taps on the 15-stage divider or disable the divider + * output. The tap selected can be used to generate an + * output square wave (SQW pin) and/or a periodic interrupt. + * + * The user can do one of the following: + * - enable the interrupt with the PIE bit; + * - enable the SQW output pin with the SQWE bit; + * - enable both at the same time and the same rate; or + * - enable neither. + * + * Table 3 lists the periodic interrupt rates and the square + * wave frequencies that can be chosen with the RS bits. + * These four read/write bits are not affected by !RESET. + * + * * Oscillator (DV2:DV0) + * These three bits are used to turn the oscillator on or + * off and to reset the countdown chain. A pattern of 010 + * is the only combination of bits that turn the oscillator + * on and allow the RTC to keep time. A pattern of 11x + * enables the oscillator but holds the countdown chain in + * reset. The next update occurs at 500ms after a pattern + * of 010 is written to DV0, DV1, and DV2. + * + * * Update-In-Progress (UIP) + * This bit is a status flag that can be monitored. When the + * UIP bit is a 1, the update transfer occurs soon. When + * UIP is a 0, the update transfer does not occur for at + * least 244us. The time, calendar, and alarm information + * in RAM is fully available for access when the UIP bit + * is 0. The UIP bit is read-only and is not affected by + * !RESET. Writing the SET bit in Register B to a 1 + * inhibits any update transfer and clears the UIP status bit. + * + * * Daylight Saving Enable (DSE) + * This bit is a read/write bit that enables two daylight + * saving adjustments when DSE is set to 1. On the first + * Sunday in April (or the last Sunday in April in the + * MC146818A), the time increments from 1:59:59 AM to + * 3:00:00 AM. On the last Sunday in October when the time + * first reaches 1:59:59 AM, it changes to 1:00:00 AM. + * + * When DSE is enabled, the internal logic test for the + * first/last Sunday condition at midnight. If the DSE bit + * is not set when the test occurs, the daylight saving + * function does not operate correctly. These adjustments + * do not occur when the DSE bit is 0. This bit is not + * affected by internal functions or !RESET. + * + * * 24/12 + * The 24/12 control bit establishes the format of the hours + * byte. A 1 indicates the 24-hour mode and a 0 indicates + * the 12-hour mode. This bit is read/write and is not + * affected by internal functions or !RESET. + * + * * Data Mode (DM) + * This bit indicates whether time and calendar information + * is in binary or BCD format. The DM bit is set by the + * program to the appropriate format and can be read as + * required. This bit is not modified by internal functions + * or !RESET. A 1 in DM signifies binary data, while a 0 in + * DM specifies BCD data. + * + * * Square-Wave Enable (SQWE) + * When this bit is set to 1, a square-wave signal at the + * frequency set by the rate-selection bits RS3-RS0 is driven + * out on the SQW pin. When the SQWE bit is set to 0, the + * SQW pin is held low. SQWE is a read/write bit and is + * cleared by !RESET. SQWE is low if disabled, and is high + * impedance when VCC is below VPF. SQWE is cleared to 0 on + * !RESET. + * + * * Update-Ended Interrupt Enable (UIE) + * This bit is a read/write bit that enables the update-end + * flag (UF) bit in Register C to assert !IRQ. The !RESET + * pin going low or the SET bit going high clears the UIE bit. + * The internal functions of the device do not affect the UIE + * bit, but is cleared to 0 on !RESET. + * + * * Alarm Interrupt Enable (AIE) + * This bit is a read/write bit that, when set to 1, permits + * the alarm flag (AF) bit in Register C to assert !IRQ. An + * alarm interrupt occurs for each second that the three time + * bytes equal the three alarm bytes, including a don't-care + * alarm code of binary 11XXXXXX. The AF bit does not + * initiate the !IRQ signal when the AIE bit is set to 0. + * The internal functions of the device do not affect the AIE + * bit, but is cleared to 0 on !RESET. + * + * * Periodic Interrupt Enable (PIE) + * The PIE bit is a read/write bit that allows the periodic + * interrupt flag (PF) bit in Register C to drive the !IRQ pin + * low. When the PIE bit is set to 1, periodic interrupts are + * generated by driving the !IRQ pin low at a rate specified + * by the RS3-RS0 bits of Register A. A 0 in the PIE bit + * blocks the !IRQ output from being driven by a periodic + * interrupt, but the PF bit is still set at the periodic + * rate. PIE is not modified b any internal device functions, + * but is cleared to 0 on !RESET. + * + * * SET + * When the SET bit is 0, the update transfer functions + * normally by advancing the counts once per second. When + * the SET bit is written to 1, any update transfer is + * inhibited, and the program can initialize the time and + * calendar bytes without an update occurring in the midst of + * initializing. Read cycles can be executed in a similar + * manner. SET is a read/write bit and is not affected by + * !RESET or internal functions of the device. + * + * * Update-Ended Interrupt Flag (UF) + * This bit is set after each update cycle. When the UIE + * bit is set to 1, the 1 in UF causes the IRQF bit to be + * a 1, which asserts the !IRQ pin. This bit can be + * cleared by reading Register C or with a !RESET. + * + * * Alarm Interrupt Flag (AF) + * A 1 in the AF bit indicates that the current time has + * matched the alarm time. If the AIE bit is also 1, the + * !IRQ pin goes low and a 1 appears in the IRQF bit. This + * bit can be cleared by reading Register C or with a + * !RESET. + * + * * Periodic Interrupt Flag (PF) + * This bit is read-only and is set to 1 when an edge is + * detected on the selected tap of the divider chain. The + * RS3 through RS0 bits establish the periodic rate. PF is + * set to 1 independent of the state of the PIE bit. When + * both PF and PIE are 1s, the !IRQ signal is active and + * sets the IRQF bit. This bit can be cleared by reading + * Register C or with a !RESET. + * + * * Interrupt Request Flag (IRQF) + * The interrupt request flag (IRQF) is set to a 1 when one + * or more of the following are true: + * - PF == PIE == 1 + * - AF == AIE == 1 + * - UF == UIE == 1 + * Any time the IRQF bit is a 1, the !IRQ pin is driven low. + * All flag bits are cleared after Register C is read by the + * program or when the !RESET pin is low. + * + * * Valid RAM and Time (VRT) + * This bit indicates the condition of the battery connected + * to the VBAT pin. This bit is not writeable and should + * always be 1 when read. If a 0 is ever present, an + * exhausted internal lithium energy source is indicated and + * both the contents of the RTC data and RAM data are + * questionable. This bit is unaffected by !RESET. + * + * This file implements an internal RTC clock, plus a generic + * version of the RTC/NVRAM chip, including the later update + * (DS12887A) which implemented a "century" register to be + * compatible with Y2K. + * + * Version: @(#)nvr.c 1.0.9 2017/10/14 * * Authors: Sarah Walker, * Miran Grca, * Mahod, + * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. - * Copyright 2016,2017 Mahod. + * Copyright 2017 Fred N. van Kempen. */ #include -#include +#include #include +#include +#include #include +#include "86Box.h" #include "ibm.h" #include "cpu/cpu.h" -#include "device.h" -#include "io.h" -#include "machine/machine.h" -#include "machine/machine_europc.h" -#include "mem.h" -#include "nmi.h" -#include "nvr.h" #include "pic.h" -#include "rom.h" #include "timer.h" -#include "rtc.h" +#include "device.h" +#include "machine/machine.h" +#include "plat.h" +#include "nvr.h" -int oldmachine; -int nvrmask=63; -char nvrram[128]; -int nvraddr; -int nvr_dosave = 0; - -static int nvr_onesec_time = 0, nvr_onesec_cnt = 0; -static int rtctime; +int64_t enable_sync; /* configuration variable: enable time sync */ +int64_t nvr_dosave; /* NVR is dirty, needs saved */ -void getnvrtime(void) +static nvr_t *saved_nvr = NULL; +static int8_t days_in_month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; +static struct { + int64_t sec; + int64_t min; + int64_t hour; + int64_t mday; + int64_t mon; + int64_t year; +} intclk; /* the internal clock */ + + +/* Determine whether or not the year is leap. */ +static int +is_leap(int64_t year) { - time_get(nvrram); + if (year % 400 == 0) return(1); + if (year % 100 == 0) return(0); + if (year % 4 == 0) return(1); + + return(0); } -void nvr_recalc(void) + +/* Determine the days in the current month. */ +static int +get_days(int64_t month, int64_t year) { - int c; - int newrtctime; - c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - newrtctime=(int)(RTCCONST * c * (1 << TIMER_SHIFT)); - if (rtctime>newrtctime) rtctime=newrtctime; + if (month != 2) + return(days_in_month[month - 1]); + + return(is_leap(year) ? 29 : 28); } -void nvr_rtc(void *p) + +/* One more second has passed, update the internal clock. */ +static void +rtc_tick(void) { - int c; - if (!(nvrram[RTC_REGA] & RTC_RS)) - { - rtctime=0x7fffffff; - return; - } - c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); - nvrram[RTC_REGC] |= RTC_PF; - if (nvrram[RTC_REGB] & RTC_PIE) - { - nvrram[RTC_REGC] |= RTC_IRQF; - if (AMSTRAD) picint(2); - else picint(0x100); - } + /* Ping the internal clock. */ + if (++intclk.sec == 60) { + intclk.sec = 0; + intclk.min++; + } + if (intclk.min == 60) { + intclk.min = 0; + intclk.hour++; + } + if (intclk.hour == 24) { + intclk.hour = 0; + intclk.mday++; + } + if (intclk.mday == (get_days(intclk.mon, intclk.year) + 1)) { + intclk.mday = 1; + intclk.mon++; + } + if (intclk.mon == 13) { + intclk.mon = 1; + intclk.year++; + } } -int nvr_update_status = 0; -#define ALARM_DONTCARE 0xc0 - -int nvr_check_alarm(int nvraddr) +/* Store the broken-down local time into the NVR. */ +static void +rtc_getnvr(uint8_t *nvr, struct tm *tm) { - return (nvrram[nvraddr + 1] == nvrram[nvraddr] || (nvrram[nvraddr + 1] & ALARM_DONTCARE) == ALARM_DONTCARE); -} + if (nvr[RTC_REGB] & REGB_DM) { + /* NVR is in Binary data mode. */ + nvr[RTC_SECONDS] = tm->tm_sec; + nvr[RTC_MINUTES] = tm->tm_min; + nvr[RTC_DOW] = tm->tm_wday+1; + nvr[RTC_DOM] = tm->tm_mday; + nvr[RTC_MONTH] = tm->tm_mon+1; + nvr[RTC_YEAR] = tm->tm_year%100; -int nvr_update_end_count = 0; - -void nvr_update_end(void *p) -{ - if (!(nvrram[RTC_REGB] & RTC_SET)) - { - getnvrtime(); - /* Clear update status. */ - nvr_update_status = 0; - - if (nvr_check_alarm(RTC_SECONDS) && nvr_check_alarm(RTC_MINUTES) && nvr_check_alarm(RTC_HOURS)) - { - nvrram[RTC_REGC] |= RTC_AF; - if (nvrram[RTC_REGB] & RTC_AIE) - { - nvrram[RTC_REGC] |= RTC_IRQF; - if (AMSTRAD) picint(2); - else picint(0x100); - } - } - - /* The flag and interrupt should be issued on update ended, not started. */ - nvrram[RTC_REGC] |= RTC_UF; - if (nvrram[RTC_REGB] & RTC_UIE) - { - nvrram[RTC_REGC] |= RTC_IRQF; - if (AMSTRAD) picint(2); - else picint(0x100); - } - } - - nvr_update_end_count = 0; -} - -void nvr_onesec(void *p) -{ - nvr_onesec_cnt++; - if (nvr_onesec_cnt >= 100) - { - if (!(nvrram[RTC_REGB] & RTC_SET)) - { - nvr_update_status = RTC_UIP; - rtc_tick(); - - nvr_update_end_count = (int)((244.0 + 1984.0) * TIMER_USEC); - } - nvr_onesec_cnt = 0; - } - nvr_onesec_time += (int)(10000 * TIMER_USEC); -} - -void writenvr(uint16_t addr, uint8_t val, void *priv) -{ - int c, old; - if (addr&1) - { - if (nvraddr==RTC_REGC || nvraddr==RTC_REGD) - return; /* Registers C and D are read-only. There's no reason to continue. */ - if (nvraddr > RTC_REGD && nvrram[nvraddr] != val) - nvr_dosave = 1; - - old = nvrram[nvraddr]; - nvrram[nvraddr]=val; - - if (nvraddr == RTC_REGA) - { - if (val & RTC_RS) - { - c = 1 << ((val & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); - } - else - rtctime = 0x7fffffff; - } - else - { - if (nvraddr == RTC_REGB) - { - if (((old ^ val) & RTC_SET) && (val & RTC_SET)) - { - nvrram[RTC_REGA] &= ~RTC_UIP; /* This has to be done according to the datasheet. */ - nvrram[RTC_REGB] &= ~RTC_UIE; /* This also has to happen per the specification. */ - } - } - - if ((nvraddr < RTC_REGA) || (nvraddr == RTC_CENTURY)) - { - if ((nvraddr != 1) && (nvraddr != 3) && (nvraddr != 5)) - { - if ((old != val) && !enable_sync) - { - time_update(nvrram, nvraddr); - nvr_dosave = 1; - } - } - } - } - } - else - { - nvraddr=val&nvrmask; - nmi_mask = ~val & 0x80; - } -} - -uint8_t readnvr(uint16_t addr, void *priv) -{ - uint8_t temp; - if (addr&1) - { - if (nvraddr == RTC_REGA) - return ((nvrram[RTC_REGA] & 0x7F) | nvr_update_status); - if (nvraddr == RTC_REGD) - nvrram[RTC_REGD] |= RTC_VRT; - if (nvraddr == RTC_REGC) - { - if (AMSTRAD) picintc(2); - else picintc(0x100); - temp = nvrram[RTC_REGC]; - nvrram[RTC_REGC] = 0; - return temp; - } - return nvrram[nvraddr]; - } - return nvraddr; -} - -void loadnvr(void) -{ - FILE *f = NULL; - int c; - nvrmask=63; - oldmachine = machine; - - wchar_t *machine_name; - wchar_t *nvr_name; - - machine_name = (wchar_t *) malloc((strlen(machine_get_internal_name_ex(machine)) << 1) + 2); - mbstowcs(machine_name, machine_get_internal_name_ex(machine), strlen(machine_get_internal_name_ex(machine)) + 1); - nvr_name = (wchar_t *) malloc((wcslen(machine_name) << 1) + 2 + 8); - _swprintf(nvr_name, L"%s.nvr", machine_name); - - pclog_w(L"Opening NVR file: %s...\n", nvr_name); - - if (machine_get_nvrmask(machine) != 0) - { - f = nvrfopen(nvr_name, L"rb"); - nvrmask = machine_get_nvrmask(machine); + if (nvr[RTC_REGB] & REGB_2412) { + /* NVR is in 24h mode. */ + nvr[RTC_HOURS] = tm->tm_hour; + } else { + /* NVR is in 12h mode. */ + nvr[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12; + if (tm->tm_hour > 11) + nvr[RTC_HOURS] |= RTC_AMPM; } + } else { + /* NVR is in BCD data mode. */ + nvr[RTC_SECONDS] = RTC_BCD(tm->tm_sec); + nvr[RTC_MINUTES] = RTC_BCD(tm->tm_min); + nvr[RTC_DOW] = RTC_BCD(tm->tm_wday+1); + nvr[RTC_DOM] = RTC_BCD(tm->tm_mday); + nvr[RTC_MONTH] = RTC_BCD(tm->tm_mon+1); + nvr[RTC_YEAR] = RTC_BCD(tm->tm_year%100); - if (!f || (machine_get_nvrmask(machine) == 0)) - { - if (f) - { - fclose(f); + if (nvr[RTC_REGB] & REGB_2412) { + /* NVR is in 24h mode. */ + nvr[RTC_HOURS] = RTC_BCD(tm->tm_hour); + } else { + /* NVR is in 12h mode. */ + nvr[RTC_HOURS] = (tm->tm_hour % 12) + ? RTC_BCD(tm->tm_hour % 12) + : RTC_BCD(12); + if (tm->tm_hour > 11) + nvr[RTC_HOURS] |= RTC_AMPM; + } + } +} + + +/* Load local time from the NVR. */ +static void +rtc_setnvr(uint8_t *nvr) +{ + int64_t temp; + + if (nvr[RTC_REGB] & REGB_DM) { + intclk.sec = nvr[RTC_SECONDS]; + intclk.min = nvr[RTC_MINUTES]; + temp = nvr[RTC_HOURS]; + intclk.mday = nvr[RTC_DOM]; + intclk.mon = nvr[RTC_MONTH]; + intclk.year = nvr[RTC_YEAR]; + intclk.year += 1900; + } else { + intclk.sec = RTC_DCB(nvr[RTC_SECONDS]); + intclk.min = RTC_DCB(nvr[RTC_MINUTES]); + temp = RTC_DCB(nvr[RTC_HOURS]); + intclk.mday = RTC_DCB(nvr[RTC_DOM]); + intclk.mon = RTC_DCB(nvr[RTC_MONTH]); + intclk.year = RTC_DCB(nvr[RTC_YEAR]); + intclk.year += (RTC_DCB(nvr[RTC_CENTURY]) * 100); + } + + /* Adjust for 12/24 hour mode. */ + if (nvr[RTC_REGB] & REGB_2412) + intclk.hour = temp; + else + intclk.hour = ((temp & ~RTC_AMPM) % 12) + ((temp & RTC_AMPM) ? 12 : 0); +} + + +static void +rtc_sync(uint8_t *nvr) +{ + struct tm *tm; + time_t now; + + /* Get the current time of day, and convert to local time. */ + (void)time(&now); + tm = localtime(&now); + + /* Set the internal clock. */ + intclk.sec = tm->tm_sec; + intclk.min = tm->tm_min; + intclk.hour = tm->tm_hour; + intclk.mday = tm->tm_mday; + intclk.mon = tm->tm_mon+1; + intclk.year = tm->tm_year+1900; + + /* Set the NVR registers. */ + rtc_getnvr(nvr, tm); +} + + +/* This is the RTC one-second timer. */ +static void +onesec_timer(void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + + if (++nvr->onesec_cnt >= 100) { + if (! (nvr->regs[RTC_REGB] & REGB_SET)) { + nvr->upd_stat = REGA_UIP; + + /* Update the system RTC. */ + rtc_tick(); + + if (nvr->hook != NULL) + (*nvr->hook)(nvr); + + /* Re-calculate the timer. */ + nvr_recalc(); + + nvr->upd_ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC); + } + nvr->onesec_cnt = 0; + } + + nvr->onesec_time += (int64_t)(10000 * TIMER_USEC); +} + + +/* Check if the current time matches a set alarm time. */ +static int +check_alarm(nvr_t *nvr, int64_t addr) +{ +#define ALARM_DONTCARE 0xc0 + return((nvr->regs[addr+1] == nvr->regs[addr]) || + ((nvr->regs[addr+1] & ALARM_DONTCARE) == ALARM_DONTCARE)); +} + + +/* This is the general update timer. */ +static void +update_timer(void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + struct tm tm; + int64_t dom, mon, yr, cent, sum, wd; + + if (! (nvr->regs[RTC_REGB] & REGB_SET)) { + /* Get the current time from the internal clock. */ + tm.tm_sec = intclk.sec; + tm.tm_min = intclk.min; + tm.tm_hour = intclk.hour; + dom = intclk.mday; + mon = intclk.mon; + yr = intclk.year % 100; + cent = ((intclk.year - yr) / 100) % 4; + sum = dom+mon+yr+cent; + wd = ((sum + 6) % 7); + tm.tm_wday = wd; + tm.tm_mday = intclk.mday; + tm.tm_mon = intclk.mon-1; + tm.tm_year = intclk.year-1900; + rtc_getnvr(nvr->regs, &tm); + + /* Clear update status. */ + nvr->upd_stat = 0; + + if (check_alarm(nvr, RTC_SECONDS) && + check_alarm(nvr, RTC_MINUTES) && + check_alarm(nvr, RTC_HOURS)) { + nvr->regs[RTC_REGC] |= REGC_AF; + if (nvr->regs[RTC_REGB] & REGB_AIE) { + nvr->regs[RTC_REGC] |= REGC_IRQF; + + /* Generate an interrupt. */ + if (nvr->irq != -1) + picint(1<irq); } - memset(nvrram,0xFF,128); - if (!enable_sync) - { - nvrram[RTC_SECONDS] = nvrram[RTC_MINUTES] = nvrram[RTC_HOURS] = 0; - nvrram[RTC_DOM] = nvrram[RTC_MONTH] = 1; - nvrram[RTC_YEAR] = (char) BCD(80); - nvrram[RTC_CENTURY] = BCD(19); - nvrram[RTC_REGB] = RTC_2412; - } + } - free(nvr_name); - free(machine_name); - return; - } - fread(nvrram,128,1,f); - if (enable_sync) - time_internal_sync(nvrram); - else - time_internal_set_nvrram(nvrram); /* Update the internal clock state based on the NVR registers. */ - fclose(f); - nvrram[RTC_REGA] = 6; - nvrram[RTC_REGB] = RTC_2412; - c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); + /* + * The flag and interrupt should be issued + * on update ended, not started. + */ + nvr->regs[RTC_REGC] |= REGC_UF; + if (nvr->regs[RTC_REGB] & REGB_UIE) { + nvr->regs[RTC_REGC] |= REGC_IRQF; - free(nvr_name); - free(machine_name); + /* Generate an interrupt. */ + if (nvr->irq != -1) + picint(1<irq); + } + } + + nvr->upd_ecount = 0; } -void savenvr(void) + +static void +ticker_timer(void *priv) { - FILE *f = NULL; + nvr_t *nvr = (nvr_t *)priv; + int64_t c; - wchar_t *machine_name; - wchar_t *nvr_name; + if (! (nvr->regs[RTC_REGA] & REGA_RS)) { + nvr->rtctime = 0x7fffffff; + return; + } - if (romset == ROM_EUROPC) - { - europc_save_nvr(); - return; - } + /* Update our ticker interval. */ + c = 1 << ((nvr->regs[RTC_REGA] & REGA_RS) - 1); + nvr->rtctime += (int64_t)(RTCCONST*c*(1<regs[RTC_REGC] |= REGC_PF; + if (nvr->regs[RTC_REGB] & REGB_PIE) { + nvr->regs[RTC_REGC] |= REGC_IRQF; - pclog_w(L"Saving NVR file: %s...\n", nvr_name); + /* Generate an interrupt. */ + if (nvr->irq != -1) + picint(1<irq); + } +} - if (machine_get_nvrmask(oldmachine) != 0) - { - f = nvrfopen(nvr_name, L"wb"); - } - if (!f || (machine_get_nvrmask(oldmachine) == 0)) - { - if (f) - { - fclose(f); +/* Set one of the chip's registers. */ +static void +nvr_write(nvr_t *nvr, uint16_t reg, uint8_t val) +{ + int64_t c, old; + + old = nvr->regs[reg]; + switch(reg) { + case RTC_REGA: + nvr->regs[reg] = val; + if (val & REGA_RS) { + c = 1 << ((val & REGA_RS) - 1); + nvr->rtctime += (int64_t)(RTCCONST*c*(1<rtctime = 0x7fffffff; } + break; - free(nvr_name); - free(machine_name); - return; + case RTC_REGB: + nvr->regs[reg] = val; + if (((old^val) & REGB_SET) && (val®B_SET)) { + /* This has to be done according to the datasheet. */ + nvr->regs[RTC_REGA] &= ~REGA_UIP; + + /* This also has to happen per the specification. */ + nvr->regs[RTC_REGB] &= ~REGB_UIE; + } + break; + + case RTC_REGC: /* R/O */ + case RTC_REGD: /* R/O */ + break; + + default: /* non-RTC registers are just NVRAM */ + if (nvr->regs[reg] != val) { + nvr->regs[reg] = val; + + nvr_dosave = 1; + } + break; + } + + if ((reg < RTC_REGA) || (reg == RTC_CENTURY)) { + if ((reg != 1) && (reg != 3) && (reg != 5)) { + if ((old != val) && !enable_sync) { + /* Update internal clock. */ + rtc_setnvr(nvr->regs); + + nvr_dosave = 1; + } + } + } +} + + +/* Get one of the chip's registers. */ +static uint8_t +nvr_read(nvr_t *nvr, uint16_t reg) +{ + uint8_t ret = 0xff; + + switch(reg) { + case RTC_REGA: + ret = (nvr->regs[RTC_REGA] & 0x7f) | nvr->upd_stat; + break; + + case RTC_REGC: + picintc(1<irq); + ret = nvr->regs[RTC_REGC]; + nvr->regs[RTC_REGC] = 0x00; + break; + + case RTC_REGD: + nvr->regs[RTC_REGD] |= REGD_VRT; + ret = nvr->regs[RTC_REGD]; + break; + + default: + ret = nvr->regs[reg]; + break; + } + + return(ret); +} + + +/* Initialize the virtual RTC/NVRAM chip. */ +void +nvr_init(nvr_t *nvr) +{ + char temp[32]; + int64_t c; + + /* Clear some of it. */ + nvr->upd_stat = 0; + nvr->upd_ecount = 0; + nvr->onesec_time = 0; + nvr->onesec_cnt = 0; + memset(&intclk, 0x00, sizeof(intclk)); + + /* Pre-initialize the NVR file's name here. */ + sprintf(temp, "%s.nvr", machine_get_internal_name_ex(machine)); + c = strlen(temp)+1; + nvr->fname = (wchar_t *)malloc(c*sizeof(wchar_t)); + mbstowcs(nvr->fname, temp, c); + + /* Set up our local handlers. */ + nvr->get = nvr_read; + nvr->set = nvr_write; + + /* Set up our timers. */ + timer_add(ticker_timer, &nvr->rtctime, TIMER_ALWAYS_ENABLED, nvr); + + timer_add(onesec_timer, &nvr->onesec_time, TIMER_ALWAYS_ENABLED, nvr); + + timer_add(update_timer, &nvr->upd_ecount, &nvr->upd_ecount, nvr); + + /* It does not need saving yet. */ + nvr_dosave = 0; + + /* Save the NVR data pointer. */ + saved_nvr = nvr; +} + + +/* Re-calculate the timer values. */ +void +nvr_recalc(void) +{ + int64_t c, nt; + + /* Make sure we have been initialized. */ + if (saved_nvr == NULL) return; + + c = 1 << ((saved_nvr->regs[RTC_REGA] & REGA_RS) - 1); + nt = (int64_t)(RTCCONST * c * (1<rtctime > nt) + saved_nvr->rtctime = nt; +} + + +/* + * Load an NVR from file. + * + * This function does two things, really. It clear and initializes + * the RTC and NVRAM areas, sets up defaults for the RTC part, and + * then attempts to load data from a saved file. + * + * Either way, after that loading, it will continue to configure + * the local RTC to operate, so it can update either the local RTC, + * and/or the supplied by a client. + */ +int64_t +nvr_load(void) +{ + FILE *f; + int64_t c; + + /* Make sure we have been initialized. */ + if (saved_nvr == NULL) return(0); + + /* Clear out any old data. */ + memset(saved_nvr->regs, 0xff, sizeof(saved_nvr->regs)); + + /* Set the defaults. */ + memset(saved_nvr->regs, 0x00, RTC_REGS); + saved_nvr->regs[RTC_DOM] = 1; + saved_nvr->regs[RTC_MONTH] = 1; + saved_nvr->regs[RTC_YEAR] = RTC_BCD(80); + saved_nvr->regs[RTC_CENTURY] = RTC_BCD(19); + + if (saved_nvr->load == NULL) { + /* We are responsible for loading. */ + f = NULL; + if (saved_nvr->mask != 0) { + pclog("Opening NVR file: %ls...\n", saved_nvr->fname); + f = plat_fopen(nvr_path(saved_nvr->fname), L"rb"); } - fwrite(nvrram,128,1,f); - fclose(f); + if (f != NULL) { + /* Read NVR contents from file. */ + fread(saved_nvr->regs, sizeof(saved_nvr->regs), 1, f); + (void)fclose(f); + } + } else { + /* OK, use alternate function. */ + (*saved_nvr->load)(saved_nvr->fname); + } - free(nvr_name); - free(machine_name); + /* Update the internal clock state based on the NVR registers. */ + if (enable_sync) + rtc_sync(saved_nvr->regs); + else + rtc_setnvr(saved_nvr->regs); + + /* Get the local RTC running! */ + saved_nvr->regs[RTC_REGA] = (REGA_RS2|REGA_RS1); + saved_nvr->regs[RTC_REGB] = REGB_2412; + c = 1 << ((saved_nvr->regs[RTC_REGA] & REGA_RS) - 1); + saved_nvr->rtctime += (int64_t)(RTCCONST * c * (1<save == NULL) { + /* We are responsible for saving. */ + f = NULL; + if (saved_nvr->mask != 0) { + pclog("Saving NVR file: %ls...\n", saved_nvr->fname); + f = plat_fopen(nvr_path(saved_nvr->fname), L"wb"); + } + + if (f != NULL) { + /* Save NVR contents to file. */ + (void)fwrite(saved_nvr->regs, sizeof(saved_nvr->regs), 1, f); + (void)fclose(f); + } + } else { + /* OK, use alternate function. */ + (*saved_nvr->save)(saved_nvr->fname); + } + + /* Device is clean again. */ + nvr_dosave = 0; + + return(1); +} + + +/* Get an absolute path to the NVR folder. */ +wchar_t * +nvr_path(wchar_t *str) +{ + static wchar_t temp[1024]; + + /* Get the full prefix in place. */ + memset(temp, 0x00, sizeof(temp)); + wcscpy(temp, cfg_path); + wcscat(temp, NVR_PATH); + + /* Create the directory if needed. */ + if (! dir_check_exist(temp)) + dir_create(temp); + + /* Now append the actual filename. */ +#ifdef WIN32 + wcscat(temp, L"\\"); +#else + wcscat(temp, L"/"); +#endif + wcscat(temp, str); + + return(temp); +} + + +/* Open or create a file in the NVR area. */ +FILE * +nvr_fopen(wchar_t *str, wchar_t *mode) +{ + return(plat_fopen(nvr_path(str), mode)); } diff --git a/src/nvr.h b/src/nvr.h index 0c7780240..ad163fec0 100644 --- a/src/nvr.h +++ b/src/nvr.h @@ -6,30 +6,115 @@ * * This file is part of the 86Box distribution. * - * CMOS NVRAM emulation. + * Definitions for a defacto-standard RTC/NVRAM device. * - * Version: @(#)nvr.h 1.0.1 2017/06/03 + * Version: @(#)nvr.h 1.0.3 2017/10/02 * * Authors: Sarah Walker, * Miran Grca, * Mahod, + * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016-2017 Miran Grca. * Copyright 2016-2017 Mahod. + * Copyright 2017 Fred N. van Kempen. */ #ifndef EMU_NVR_H # define EMU_NVR_H -extern int enable_sync; -extern int nvr_dosave; +/* Conversion from BCD to Binary and vice versa. */ +#define RTC_BCD(x) (((x) % 10) | (((x) / 10) << 4)) +#define RTC_DCB(x) ((((x) & 0xf0) >> 4) * 10 + ((x) & 0x0f)) + +/* RTC registers and bit definitions. */ +#define RTC_SECONDS 0 +#define RTC_ALSECONDS 1 +#define RTC_MINUTES 2 +#define RTC_ALMINUTES 3 +#define RTC_HOURS 4 +# define RTC_AMPM 0x80 /* PM flag if 12h format in use */ +#define RTC_ALHOURS 5 +#define RTC_DOW 6 +#define RTC_DOM 7 +#define RTC_MONTH 8 +#define RTC_YEAR 9 +#define RTC_REGA 10 +# define REGA_UIP 0x80 +# define REGA_DV2 0x40 +# define REGA_DV1 0x20 +# define REGA_DV0 0x10 +# define REGA_DV 0x70 +# define REGA_RS3 0x08 +# define REGA_RS2 0x04 +# define REGA_RS1 0x02 +# define REGA_RS0 0x01 +# define REGA_RS 0x0f +#define RTC_REGB 11 +# define REGB_SET 0x80 +# define REGB_PIE 0x40 +# define REGB_AIE 0x20 +# define REGB_UIE 0x10 +# define REGB_SQWE 0x08 +# define REGB_DM 0x04 +# define REGB_2412 0x02 +# define REGB_DSE 0x01 +#define RTC_REGC 12 +# define REGC_IRQF 0x80 +# define REGC_PF 0x40 +# define REGC_AF 0x20 +# define REGC_UF 0x10 +#define RTC_REGD 13 +# define REGD_VRT 0x80 +#define RTC_CENTURY 0x32 /* century register */ +#define RTC_REGS 14 /* number of registers */ -extern void nvr_init(void); -extern void time_get(char *nvrram); -extern void nvr_recalc(void); -extern void loadnvr(void); -extern void savenvr(void); + +/* Define a (defacto-standard) RTC/NVRAM chip. */ +typedef struct _nvr_ { + uint8_t regs[RTC_REGS+114]; /* these are the registers */ + + int64_t mask, + irq, + addr; + + wchar_t *fname; + + int64_t upd_stat, + upd_ecount, + onesec_time, + onesec_cnt, + rtctime, + oldmachine; + + /* Hooks to internal RTC I/O functions. */ + void (*set)(struct _nvr_ *, uint16_t, uint8_t); + uint8_t (*get)(struct _nvr_ *, uint16_t); + + /* Hooks to alternative load/save functions. */ + int8_t (*load)(wchar_t *fname); + int8_t (*save)(wchar_t *fname); + + /* Hook to RTC ticker handler. */ + void (*hook)(struct _nvr_ *); +} nvr_t; + + +extern int64_t enable_sync; +extern int64_t nvr_dosave; + + +extern void nvr_init(nvr_t *); +extern int64_t nvr_load(void); +extern int64_t nvr_save(void); +extern void nvr_recalc(void); + +extern wchar_t *nvr_path(wchar_t *str); +extern FILE *nvr_fopen(wchar_t *str, wchar_t *mode); + +extern void nvr_at_init(int64_t irq); #endif /*EMU_NVR_H*/ diff --git a/src/nvr_at.c b/src/nvr_at.c new file mode 100644 index 000000000..6e14932cd --- /dev/null +++ b/src/nvr_at.c @@ -0,0 +1,111 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * IBM PC/AT RTC/NVRAM ("CMOS") emulation. + * + * The original PC/AT series had DS12885 series modules; later + * versions and clones used the 12886 and/or 1288(C)7 series, + * or the MC146818 series, all with an external battery. Many + * of those batteries would create corrosion issues later on + * in mainboard life... + * + * Version: @(#)nvr_at.c 1.0.6 2017/10/04 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include +#include "ibm.h" +#include "cpu/cpu.h" +#include "io.h" +#include "device.h" +#include "machine/machine.h" +#include "nvr.h" + + +static void +nvr_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + + if (! (addr & 1)) { + nvr->addr = (val & nvr->mask); +#if 0 + nvr->nmi_mask = (~val & 0x80); +#endif + + return; + } + + /* Write the chip's registers. */ + (*nvr->set)(nvr, nvr->addr, val); +} + + +static uint8_t +nvr_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t ret; + + if (addr & 1) { + /* Read from the chip's registers. */ + ret = (*nvr->get)(nvr, nvr->addr); + } else { + ret = nvr->addr; + } + + return(ret); +} + + +void +nvr_at_close(void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + + if (nvr->fname != NULL) + free(nvr->fname); + + free(nvr); +} + + +void +nvr_at_init(int64_t irq) +{ + nvr_t *nvr; + + /* Allocate an NVR for this machine. */ + nvr = (nvr_t *)malloc(sizeof(nvr_t)); + if (nvr == NULL) return; + memset(nvr, 0x00, sizeof(nvr_t)); + + /* This is machine specific. */ + nvr->mask = machines[machine].nvrmask; + nvr->irq = irq; + + /* Set up any local handlers here. */ + + /* Initialize the actual NVR. */ + nvr_init(nvr); + + /* Set up the PC/AT handler for this device. */ + io_sethandler(0x0070, 2, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + + /* Load the NVR into memory! */ + (void)nvr_load(); +} diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index 75ba968e4..2be9a2fba 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -1,9 +1,14 @@ +#include +#include +#include #include +#include #include "ibm.h" #include "device.h" #include "io.h" #include "mem.h" #include "rom.h" +#include "nvr.h" #include "nvr_ps2.h" @@ -49,7 +54,7 @@ static void ps2_nvr_write(uint16_t port, uint8_t val, void *p) } } -static void *ps2_nvr_init() +static void *ps2_nvr_init(device_t *info) { ps2_nvr_t *nvr = (ps2_nvr_t *)malloc(sizeof(ps2_nvr_t)); FILE *f = NULL; @@ -60,7 +65,7 @@ static void *ps2_nvr_init() switch (romset) { - case ROM_IBMPS2_M80: f = nvrfopen(L"ibmps2_m80_sec.nvr", L"rb"); break; + case ROM_IBMPS2_M80: f = nvr_fopen(L"ibmps2_m80_sec.nvr", L"rb"); break; } if (f) { @@ -80,7 +85,7 @@ static void ps2_nvr_close(void *p) switch (romset) { - case ROM_IBMPS2_M80: f = nvrfopen(L"ibmps2_m80_sec.nvr", L"wb"); break; + case ROM_IBMPS2_M80: f = nvr_fopen(L"ibmps2_m80_sec.nvr", L"wb"); break; } if (f) { @@ -95,10 +100,9 @@ device_t ps2_nvr_device = { "PS/2 NVRRAM", 0, + 0, ps2_nvr_init, ps2_nvr_close, - NULL, - NULL, - NULL, - NULL + NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/pc.c b/src/pc.c index bc7f6bf65..1832c56fc 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,65 +8,57 @@ * * Emulation core dispatcher. * - * Version: @(#)pc.c 1.0.8 2017/09/03 + * Version: @(#)pc.c 1.0.27 2017/10/14 * * Authors: Sarah Walker, * Miran Grca, + * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. */ #include +#include #include +#include #include +#include #include "86box.h" #include "config.h" #include "ibm.h" -#include "mem.h" -#include "cpu/codegen.h" #include "cpu/cpu.h" +#ifdef USE_DYNAREC +#include "cpu/codegen.h" +#endif +#include "cpu/x86_ops.h" +#include "io.h" +#include "mem.h" +#include "rom.h" #include "dma.h" +#include "pic.h" +#include "pit.h" #include "random.h" +#include "timer.h" +#include "mouse.h" #include "device.h" -#include "gameport.h" -#include "floppy/floppy.h" -#include "floppy/floppy_86f.h" -#include "floppy/floppy_fdi.h" -#include "floppy/floppy_imd.h" -#include "floppy/floppy_img.h" -#include "floppy/floppy_td0.h" -#include "floppy/fdc.h" -#include "floppy/fdd.h" -#include "cdrom/cdrom.h" -#include "cdrom/cdrom_image.h" -#include "cdrom/cdrom_ioctl.h" -#include "cdrom/cdrom_null.h" -#include "hdd/hdd.h" -#include "hdd/hdd_ide_at.h" +#include "nvr.h" +#include "machine/machine.h" +#include "game/gameport.h" #include "keyboard.h" #include "keyboard_at.h" #include "lpt.h" -#include "machine/machine.h" -#include "sound/midi.h" -#include "mouse.h" -#ifdef USE_NETWORK -#include "network/network.h" -#endif -#include "nvr.h" -#include "pic.h" -#include "pit.h" -#ifdef WALTJE -# define UNICODE -# include "win/plat_dir.h" -# undef UNICODE -#endif -#include "win/plat_joystick.h" -#include "win/plat_keyboard.h" -#include "win/plat_midi.h" -#include "win/plat_mouse.h" -#include "win/plat_ui.h" -#include "scsi/scsi.h" #include "serial.h" +#include "cdrom/cdrom.h" +#include "disk/hdd.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" +#include "floppy/floppy.h" +#include "floppy/fdc.h" +#include "scsi/scsi.h" +#include "network/network.h" #include "sound/sound.h" +#include "sound/midi.h" #include "sound/snd_cms.h" #include "sound/snd_dbopl.h" #include "sound/snd_mpu401.h" @@ -75,45 +67,45 @@ #include "sound/snd_sb.h" #include "sound/snd_speaker.h" #include "sound/snd_ssi2001.h" -#include "timer.h" #include "video/video.h" #include "video/vid_voodoo.h" -#include "cpu/x86_ops.h" +#include "ui.h" +#include "plat.h" +#include "plat_joystick.h" +#include "plat_keyboard.h" +#include "plat_midi.h" +#include "plat_mouse.h" -wchar_t pcempath[512]; +int window_w, window_h, window_x, window_y, window_remember; +int dump_on_exit = 0; +int start_in_fullscreen = 0; +int CPUID; +int vid_resize, vid_api; +int output; +int atfullspeed; +int cycles_lost = 0; +int clockrate; +int insc = 0; +float mips, flops; +int framecount, fps; +int win_title_update = 0; +int updatestatus = 0; +int pollmouse_delay = 2; +int mousecapture; +int suppress_overscan = 0; +int cpuspeed2; +wchar_t exe_path[1024]; +wchar_t cfg_path[1024]; -wchar_t nvr_path[1024]; -int path_len; -int window_w, window_h, window_x, window_y, window_remember; - -int dump_on_exit = 0; -int start_in_fullscreen = 0; - -int CPUID; -int vid_resize, vid_api; - -int cycles_lost = 0; - -int clockrate; -int insc=0; -float mips,flops; extern int mmuflush; extern int readlnum,writelnum; -void fullspeed(); - -int framecount,fps; - -int output; -int atfullspeed; - -void saveconfig(); -int infocus; -int mousecapture; -void pclog(const char *format, ...) +/* Log something to the logfile or stdout. */ +void +pclog(const char *format, ...) { #ifndef RELEASE_BUILD va_list ap; @@ -124,606 +116,668 @@ void pclog(const char *format, ...) #endif } -void pclog_w(const wchar_t *format, ...) -{ -#ifndef RELEASE_BUILD - va_list ap; - va_start(ap, format); - vwprintf(format, ap); - va_end(ap); - fflush(stdout); -#endif -} -#ifndef __unix -#ifndef _LIBC -# define __builtin_expect(expr, val) (expr) -#endif - -#undef memmem - - -/* Return the first occurrence of NEEDLE in HAYSTACK. */ -void *memmem (const void *haystack, size_t haystack_len, const void *needle, size_t needle_len) -{ - const char *begin; - const char *const last_possible = (const char *) haystack + haystack_len - needle_len; - - if (needle_len == 0) - /* The first occurrence of the empty string is deemed to occur at - the beginning of the string. */ - return (void *) haystack; - - /* Sanity check, otherwise the loop might search through the whole - memory. */ - if (__builtin_expect (haystack_len < needle_len, 0)) - return NULL; - - for (begin = (const char *) haystack; begin <= last_possible; ++begin) - if (begin[0] == ((const char *) needle)[0] && !memcmp ((const void *) &begin[1], (const void *) ((const char *) needle + 1), needle_len - 1)) - return (void *) begin; - - return NULL; -} -#endif - - -void fatal(const char *format, ...) +/* Log a fatal error, and display a UI message before exiting. */ +void +fatal(const char *format, ...) { char msg[1024]; -#ifndef __unix - char *newline; -#endif va_list ap; + char *sp; + va_start(ap, format); vsprintf(msg, format, ap); printf(msg); va_end(ap); fflush(stdout); - savenvr(); - saveconfig(); -#ifndef __unix - newline = memmem(msg, strlen(msg), "\n", strlen("\n")); - if (newline != NULL) - { - *newline = 0; - } - plat_msgbox_fatal(msg); -#endif + + nvr_save(); + + config_save(); + dumppic(); dumpregs(1); + + /* Make sure the message does not have a trailing newline. */ + if ((sp = strchr(msg, '\n')) != NULL) *sp = '\0'; + + ui_msgbox(MBX_ERROR|MBX_FATAL|MBX_ANSI, msg); + fflush(stdout); + exit(-1); } -uint8_t cgastat; - -int pollmouse_delay = 2; -void pollmouse(void) +/* + * This function returns the absolute pathname to a file (str) + * that is to be found in the user (formerly 'nvr_path' area. + */ +wchar_t * +pc_concat(wchar_t *str) { - int x, y, z; - pollmouse_delay--; - if (pollmouse_delay) return; - pollmouse_delay = 2; - mouse_poll_host(); - mouse_get_mickeys(&x, &y, &z); - mouse_poll(x, y, z, mouse_buttons); -} + static wchar_t temp[1024]; -/*PC1512 languages - - 7=English - 6=German - 5=French - 4=Spanish - 3=Danish - 2=Swedish - 1=Italian - 3,2,1 all cause the self test to fail for some reason - */ + /* Get the full prefix in place. */ + memset(temp, 0x00, sizeof(temp)); + wcscpy(temp, cfg_path); -int cpuspeed2; + /* Create the directory if needed. */ + if (! dir_check_exist(temp)) + dir_create(temp); -int clocks[3][12][4]= -{ - { - {4772728,13920,59660,5965}, /*4.77MHz*/ - {8000000,23333,110000,0}, /*8MHz*/ - {10000000,29166,137500,0}, /*10MHz*/ - {12000000,35000,165000,0}, /*12MHz*/ - {16000000,46666,220000,0}, /*16MHz*/ - }, - { - {8000000,23333,110000,0}, /*8MHz*/ - {12000000,35000,165000,0}, /*12MHz*/ - {16000000,46666,220000,0}, /*16MHz*/ - {20000000,58333,275000,0}, /*20MHz*/ - {25000000,72916,343751,0}, /*25MHz*/ - }, - { - {16000000, 46666,220000,0}, /*16MHz*/ - {20000000, 58333,275000,0}, /*20MHz*/ - {25000000, 72916,343751,0}, /*25MHz*/ - {33000000, 96000,454000,0}, /*33MHz*/ - {40000000,116666,550000,0}, /*40MHz*/ - {50000000, 72916*2,343751*2,0}, /*50MHz*/ - {33000000*2, 96000*2,454000*2,0}, /*66MHz*/ - {75000000, 72916*3,343751*3,0}, /*75MHz*/ - {80000000,116666*2,550000*2,0}, /*80MHz*/ - {100000000, 72916*4,343751*4,0}, /*100MHz*/ - {120000000,116666*3,550000*3,0}, /*120MHz*/ - {133000000, 96000*4,454000*4,0}, /*133MHz*/ - } -}; - -int updatestatus; -int win_title_update=0; - - -void onesec(void) -{ - fps=framecount; - framecount=0; - win_title_update=1; -} - -void pc_reset(void) -{ - cpu_set(); - resetx86(); - dma_reset(); - fdc_reset(); - pic_reset(); - serial_reset(); - - if (AT) - setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); - else - setpitclock(14318184.0); -} - - -#undef printf -void initpc(int argc, wchar_t *argv[]) -{ - wchar_t *p; - wchar_t *config_file = NULL; - int c; - get_executable_name(pcempath, 511); - pclog("executable_name = %S\n", pcempath); - p=get_filename_w(pcempath); - *p=L'\0'; - pclog("path = %S\n", pcempath); -#ifdef WALTJE - DIR *dir; - struct direct *dp; + /* Now append the actual filename. */ +#ifdef WIN32 + wcscat(temp, L"\\"); +#else + wcscat(temp, L"/"); #endif + wcscat(temp, str); - for (c = 1; c < argc; c++) - { - if (!_wcsicmp(argv[c], L"--help")) - { - printf("Command line options :\n\n"); - printf("--config file.cfg - use given config file as initial configuration\n"); - printf("--dump - always dump memory on exit\n"); - printf("--fullscreen - start in fullscreen mode\n"); - exit(-1); - } - else if (!_wcsicmp(argv[c], L"--config")) - { - if ((c+1) == argc) - break; - config_file = argv[c+1]; - c++; - } - else if (!_wcsicmp(argv[c], L"--dump")) - { - dump_on_exit = 1; - } - else if (!_wcsicmp(argv[c], L"--fullscreen")) - { - start_in_fullscreen = 1; - } - else if (!_wcsicmp(argv[c], L"--test")) - { - /* some (undocumented) test function here.. */ -#ifdef WALTJE - dir = opendirw(pcempath); - if (dir != NULL) { - printf("Directory '%S':\n", pcempath); - for (;;) { - dp = readdir(dir); - if (dp == NULL) break; - printf(">> '%S'\n", dp->d_name); - } - closedir(dir); - } else { - printf("Could not open '%S'..\n", pcempath); - } + return(temp); +} + + +/* + * Perform initial startup of the PC. + * + * This is the platform-indepenent part of the startup, + * where we check commandline arguments and loading a + * configuration file. + */ +int +pc_init(int argc, wchar_t *argv[]) +{ + wchar_t *cfg = NULL, *p; + int c; + + /* Grab the executable's full path. */ + get_executable_name(exe_path, sizeof(exe_path)-1); + p = get_filename_w(exe_path); + *p = L'\0'; + + /* + * Get the current working directory. + * This is normally the directory from where the + * program was run. If we have been started via + * a shortcut (desktop icon), however, the CWD + * could have been set to something else. + */ + plat_getcwd(cfg_path, sizeof(cfg_path)-1); + + for (c=1; c= 'A') && (cdrom_drives[i].host_drive <= 'Z')) - { - ioctl_open(i, cdrom_drives[i].host_drive); - } - else - { - cdrom_null_open(i, cdrom_drives[i].host_drive); - } - } - - sound_reset(); - fdc_init(); - floppy_init(); - fdi_init(); - img_init(); - d86f_init(); - td0_init(); - imd_init(); - - floppy_load(0, floppyfns[0]); - floppy_load(1, floppyfns[1]); - floppy_load(2, floppyfns[2]); - floppy_load(3, floppyfns[3]); - - loadnvr(); - sound_init(); - - resetide(); - scsi_card_init(); - - fullspeed(); - shadowbios=0; - - for (i = 0; i < CDROM_NUM; i++) - { - if (cdrom_drives[i].host_drive == 200) - { - image_reset(i); - } - else if ((cdrom_drives[i].host_drive >= 'A') && (cdrom_drives[i].host_drive <= 'Z')) - { - ioctl_reset(i); - } - } + /* All good! */ + return(1); } -void resetpc(void) -{ - pc_reset(); - shadowbios=0; -} -void pc_keyboard_send(uint8_t val) +void +pc_full_speed(void) { + cpuspeed2 = cpuspeed; + + if (! atfullspeed) { + pclog("Set fullspeed - %i %i %i\n", is386, AT, cpuspeed2); if (AT) - { - keyboard_at_adddata_keyboard_raw(val); + setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); + else + setpitclock(14318184.0); + } + atfullspeed = 1; + + nvr_recalc(); +} + + +void +pc_speed_changed(void) +{ + if (AT) + setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); + else + setpitclock(14318184.0); + + nvr_recalc(); +} + + +/* Initialize modules, ran once, after pc_init. */ +int +pc_init_modules(void) +{ + int c, i; + + pclog("Scanning for ROM images:\n"); + c = 0; + for (i=0; i=0; c--) { + if (gfx_present[c]) { + gfxcard = c; + config_save(); -void resetpc_cad(void) -{ - pc_keyboard_send(29); /* Ctrl key pressed */ - pc_keyboard_send(56); /* Alt key pressed */ - pc_keyboard_send(83); /* Delete key pressed */ - pc_keyboard_send(157); /* Ctrl key released */ - pc_keyboard_send(184); /* Alt key released */ - pc_keyboard_send(211); /* Delete key released */ + /* This can loop if all cards now bad.. */ + goto again2; + } + } + } + + cpuspeed2 = (AT) ? 2 : 1; + atfullspeed = 0; + + random_init(); + + mem_init(); + +#ifdef USE_DYNAREC + codegen_init(); +#endif + + mouse_init(); +#ifdef WALTJE + serial_init(); +#endif + joystick_init(); + video_init(); + + ide_init_first(); + + cdrom_global_reset(); + + device_init(); + + timer_reset(); + + sound_reset(); + + fdc_init(); + + floppy_general_init(); + + sound_init(); + + hdc_init(hdc_name); + + ide_reset(); + + cdrom_hard_reset(); + + scsi_card_init(); + + pc_full_speed(); + shadowbios = 0; + + return(1); } -void ctrl_alt_esc(void) +/* Insert keystrokes into the machine's keyboard buffer. */ +static void +pc_keyboard_send(uint8_t val) { - pc_keyboard_send(29); /* Ctrl key pressed */ - pc_keyboard_send(56); /* Alt key pressed */ - pc_keyboard_send(1); /* Esc key pressed */ - pc_keyboard_send(157); /* Ctrl key released */ - pc_keyboard_send(184); /* Alt key released */ - pc_keyboard_send(129); /* Esc key released */ + if (AT) + keyboard_at_adddata_keyboard_raw(val); + else + keyboard_send(val); } -int suppress_overscan = 0; -void resetpchard_close(void) +/* Send the machine a Control-Alt-DEL sequence. */ +void +pc_send_cad(void) { - suppress_overscan = 0; - - savenvr(); - - device_close_all(); - mouse_emu_close(); - closeal(); + pc_keyboard_send(29); /* Ctrl key pressed */ + pc_keyboard_send(56); /* Alt key pressed */ + pc_keyboard_send(83); /* Delete key pressed */ + pc_keyboard_send(157); /* Ctrl key released */ + pc_keyboard_send(184); /* Alt key released */ + pc_keyboard_send(211); /* Delete key released */ } -void resetpchard_init(void) + +/* Send the machine a Control-Alt-ESC sequence. */ +void +pc_send_cae(void) { - int i = 0; + pc_keyboard_send(29); /* Ctrl key pressed */ + pc_keyboard_send(56); /* Alt key pressed */ + pc_keyboard_send(1); /* Esc key pressed */ + pc_keyboard_send(157); /* Ctrl key released */ + pc_keyboard_send(184); /* Alt key released */ + pc_keyboard_send(129); /* Esc key released */ +} - sound_realloc_buffers(); - initalmain(0,NULL); +void +pc_reset_hard_close(void) +{ + suppress_overscan = 0; - device_init(); - midi_device_init(); - inital(); - - timer_reset(); - sound_reset(); - mem_resize(); - fdc_init(); - floppy_reset(); + nvr_save(); + + device_close_all(); + midi_close(); + mouse_emu_close(); + closeal(); +} + + +/* + * This is basically the spot where we start up the actual machine, + * by issuing a 'hard reset' to the entire configuration. Order is + * somewhat important here. Functions here should be named _reset + * really, as that is what they do. + */ +void +pc_reset_hard_init(void) +{ + /* First, we reset the modules that are not part of the + * actual machine, but which support some of the modules + * that are. + */ + sound_realloc_buffers(); + sound_cd_thread_reset(); + initalmain(0, NULL); + + /* Reset the general machine support modules. */ + mem_resize(); + io_init(); + device_init(); + timer_reset(); + + midi_device_init(); + inital(); + sound_reset(); + + fdc_init(); + fdc_update_is_nsc(0); + floppy_reset(); #ifndef WALTJE - serial_init(); -#endif - machine_init(); - video_init(); - speaker_init(); - lpt1_device_init(); - - ide_ter_disable(); - ide_qua_disable(); - - if (ide_enable[2]) - { - ide_ter_init(); - } - - if (ide_enable[3]) - { - ide_qua_init(); - } - - resetide(); - scsi_card_init(); -#ifdef USE_NETWORK - network_reset(); + /* This is needed to initialize the serial timer. */ + serial_init(); #endif - sound_card_init(); - if (mpu401_standalone_enable) - mpu401_device_add(); - if (GUS) - device_add(&gus_device); - if (GAMEBLASTER) - device_add(&cms_device); - if (SSI2001) - device_add(&ssi2001_device); - if (voodoo_enabled) - device_add(&voodoo_device); - hdd_controller_init(hdd_controller_name); - pc_reset(); - mouse_emu_init(); - - loadnvr(); + /* Initialize the actual machine and its basic modules. */ + machine_init(); - shadowbios = 0; + /* + * Once the machine has been initialized, all that remains + * should be resetting all devices set up for it, to their + * current configurations ! + * + * For now, we will call their reset functions here, but + * that will be a call to device_reset_all() later ! + */ + + /* Reset some basic devices. */ + speaker_init(); + serial_reset(); + lpt1_device_init(); + + /* Reset keyboard and/or mouse. */ + keyboard_at_reset(); + mouse_emu_init(); - keyboard_at_reset(); - - cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; + /* Reset the video card. */ + video_reset(); + if (voodoo_enabled) + device_add(&voodoo_device); - for (i = 0; i < CDROM_NUM; i++) - { - if (cdrom_drives[i].host_drive == 200) - { - image_reset(i); - } - else if ((cdrom_drives[i].host_drive >= 'A') && (cdrom_drives[i].host_drive <= 'Z')) - { - ioctl_reset(i); - } - } + /* Reset the Floppy Disk controller. */ + fdc_reset(); - sound_cd_thread_reset(); + /* Reset the Hard Disk Controller module. */ + hdc_reset(); + + /* Reconfire and reset the IDE layer. */ + ide_ter_disable(); + ide_qua_disable(); + if (ide_enable[2]) + ide_ter_init(); + if (ide_enable[3]) + ide_qua_init(); + ide_reset(); + + /* Reset and reconfigure the SCSI layer. */ + scsi_card_init(); + + cdrom_hard_reset(); + + /* Reset and reconfigure the Network Card layer. */ + network_reset(); + + /* Reset and reconfigure the Sound Card layer. */ + sound_card_init(); + if (mpu401_standalone_enable) + mpu401_device_add(); + if (GUS) + device_add(&gus_device); + if (GAMEBLASTER) + device_add(&cms_device); + if (SSI2001) + device_add(&ssi2001_device); + + /* Reset the CPU module. */ + cpu_set(); + cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; + resetx86(); + dma_reset(); + pic_reset(); + + shadowbios = 0; + + if (AT) + setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); + else + setpitclock(14318184.0); } -void resetpchard(void) + +void +pc_reset_hard(void) { - resetpchard_close(); - resetpchard_init(); + pc_reset_hard_close(); + + pc_reset_hard_init(); } + +void +pc_close(void) +{ + int i; + + for (i=0; iexit(i); + + dumppic(); + + for (i=0; i=100) - { - framecountx=0; - mips=(float)insc/1000000.0f; - insc=0; - flops=(float)fpucount/1000000.0f; - fpucount=0; - sreadlnum=readlnum; - swritelnum=writelnum; - segareads=egareads; - segawrites=egawrites; - scycles_lost = cycles_lost; - - cpu_recomp_blocks_latched = cpu_recomp_blocks; - cpu_recomp_ins_latched = cpu_state.cpu_recomp_ins; - cpu_recomp_full_ins_latched = cpu_recomp_full_ins; - cpu_new_blocks_latched = cpu_new_blocks; - cpu_recomp_flushes_latched = cpu_recomp_flushes; - cpu_recomp_evicted_latched = cpu_recomp_evicted; - cpu_recomp_reuse_latched = cpu_recomp_reuse; - cpu_recomp_removed_latched = cpu_recomp_removed; - cpu_reps_latched = cpu_reps; - cpu_notreps_latched = cpu_notreps; - - cpu_recomp_blocks = 0; - cpu_state.cpu_recomp_ins = 0; - cpu_recomp_full_ins = 0; - cpu_new_blocks = 0; - cpu_recomp_flushes = 0; - cpu_recomp_evicted = 0; - cpu_recomp_reuse = 0; - cpu_recomp_removed = 0; - cpu_reps = 0; - cpu_notreps = 0; - - updatestatus=1; - readlnum=writelnum=0; - egareads=egawrites=0; - cycles_lost = 0; - mmuflush=0; - emu_fps = frames; - frames = 0; - } - if (win_title_update) - { - win_title_update=0; - mbstowcs(wmachine, machine_getname(), strlen(machine_getname()) + 1); - mbstowcs(wcpu, machines[machine].cpu[cpu_manufacturer].cpus[cpu].name, strlen(machines[machine].cpu[cpu_manufacturer].cpus[cpu].name) + 1); - _swprintf(s, L"%s v%s - %i%% - %s - %s - %s", EMU_NAME_W, EMU_VERSION_W, fps, wmachine, wcpu, (!mousecapture) ? plat_get_string_from_id(IDS_2077) : ((mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON) ? plat_get_string_from_id(IDS_2078) : plat_get_string_from_id(IDS_2079))); - set_window_title(s); - } - done++; -} - -void fullspeed(void) -{ - cpuspeed2=cpuspeed; - if (!atfullspeed) - { - printf("Set fullspeed - %i %i %i\n",is386,AT,cpuspeed2); - if (AT) - setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); - else - setpitclock(14318184.0); - } - atfullspeed=1; - nvr_recalc(); -} - -void speedchanged(void) -{ - if (AT) - setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); - else - setpitclock(14318184.0); - nvr_recalc(); -} - -void closepc(void) -{ - int i = 0; - for (i = 0; i < CDROM_NUM; i++) - { - cdrom_drives[i].handler->exit(i); - } - dumppic(); - for (i = 0; i < FDD_NUM; i++) - { - floppy_close(i); - } - dumpregs(0); - closevideo(); - lpt1_device_close(); - device_close_all(); - midi_close(); -#ifdef USE_NETWORK - network_close(); + if (is386) { +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + exec386_dynarec(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); + else #endif + exec386(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); + } else if (AT) { + exec386(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); + } else { + execx86(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); + } + + keyboard_process(); + + pollmouse(); + + if (joystick_type != 7) + joystick_poll(); + + endblit(); + + framecountx++; + framecount++; + if (framecountx >= 100) { + framecountx = 0; + mips = (float)insc/1000000.0f; + insc = 0; + flops = (float)fpucount/1000000.0f; + fpucount = 0; + sreadlnum = readlnum; + swritelnum = writelnum; + segareads = egareads; + segawrites = egawrites; + scycles_lost = cycles_lost; + +#ifdef USE_DYNAREC + cpu_recomp_blocks_latched = cpu_recomp_blocks; + cpu_recomp_ins_latched = cpu_state.cpu_recomp_ins; + cpu_recomp_full_ins_latched = cpu_recomp_full_ins; + cpu_new_blocks_latched = cpu_new_blocks; + cpu_recomp_flushes_latched = cpu_recomp_flushes; + cpu_recomp_evicted_latched = cpu_recomp_evicted; + cpu_recomp_reuse_latched = cpu_recomp_reuse; + cpu_recomp_removed_latched = cpu_recomp_removed; + cpu_reps_latched = cpu_reps; + cpu_notreps_latched = cpu_notreps; + + cpu_recomp_blocks = 0; + cpu_state.cpu_recomp_ins = 0; + cpu_recomp_full_ins = 0; + cpu_new_blocks = 0; + cpu_recomp_flushes = 0; + cpu_recomp_evicted = 0; + cpu_recomp_reuse = 0; + cpu_recomp_removed = 0; + cpu_reps = 0; + cpu_notreps = 0; +#endif + + updatestatus = 1; + readlnum = writelnum = 0; + egareads = egawrites = 0; + cycles_lost = 0; + mmuflush = 0; + emu_fps = frames; + frames = 0; + } + + if (win_title_update) { + mbstowcs(wmachine, machine_getname(), strlen(machine_getname())+1); + mbstowcs(wcpu, machines[machine].cpu[cpu_manufacturer].cpus[cpu].name, + strlen(machines[machine].cpu[cpu_manufacturer].cpus[cpu].name)+1); + swprintf(temp, sizeof_w(temp), L"%ls v%ls - %i%% - %ls - %ls - %ls", + EMU_NAME_W, EMU_VERSION_W, fps, wmachine, wcpu, + (!mousecapture) ? plat_get_string(IDS_2077) + : ((mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079))); + set_window_title(temp); + + win_title_update = 0; + } + + done++; +} + + +void +onesec(void) +{ + fps = framecount; + framecount = 0; + win_title_update = 1; } diff --git a/src/pci.c b/src/pci.c index 21ac26687..e7aa6b7cc 100644 --- a/src/pci.c +++ b/src/pci.c @@ -1,14 +1,20 @@ +#include +#include +#include #include +#include #include "ibm.h" #include "io.h" #include "pic.h" #include "mem.h" +#include "device.h" #include "pci.h" #include "keyboard_at.h" +#include "cdrom/cdrom.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" #include "floppy/floppy.h" #include "floppy/fdc.h" -#include "hdd/hdd_ide_at.h" -#include "cdrom/cdrom.h" static uint64_t pci_irq_hold[16]; @@ -650,7 +656,7 @@ static void trc_reset(uint8_t val) pci_reset_handler.super_io_reset(); } - resetide(); + ide_reset(); for (i = 0; i < CDROM_NUM; i++) { if (!cdrom_drives[i].bus_type) diff --git a/src/pci_dummy.c b/src/pci_dummy.c index 128cd187b..da4ec9514 100644 --- a/src/pci_dummy.c +++ b/src/pci_dummy.c @@ -1,4 +1,8 @@ /* This can also serve as a sample PCI device. */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" #include "pci.h" diff --git a/src/pic.c b/src/pic.c index 441947fa4..0c413ebb6 100644 --- a/src/pic.c +++ b/src/pic.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "ibm.h" #include "io.h" #include "pci.h" diff --git a/src/piix.c b/src/piix.c index 4b4548127..de56b65a6 100644 --- a/src/piix.c +++ b/src/piix.c @@ -8,28 +8,30 @@ * * Emulation core dispatcher. * - * Version: @(#)piix.c 1.0.2 2017/08/24 + * PRD format : + * word 0 - base address + * word 1 - bits 1 - 15 = byte count, bit 31 = end of transfer + * + * Version: @(#)piix.c 1.0.5 2017/10/01 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ - -/*PRD format : - - word 0 - base address - word 1 - bits 1 - 15 = byte count, bit 31 = end of transfer -*/ +#include +#include #include - +#include #include "ibm.h" #include "dma.h" #include "io.h" +#include "device.h" #include "keyboard_at.h" #include "mem.h" #include "pci.h" -#include "hdd/hdd_ide_at.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" #include "piix.h" @@ -610,7 +612,9 @@ void piix_bus_master_set_irq(int channel) piix_busmaster[channel & 0x0F].status |= (channel >> 4); } -/* static int reset_reg = 0; + +#if 0 +static int reset_reg = 0; static uint8_t rc_read(uint16_t port, void *priv) { @@ -623,7 +627,7 @@ static void rc_write(uint16_t port, uint8_t val, void *priv) { if (reset_reg & 2) { - resetpchard(); + pc_reset_hard(); } else { @@ -635,12 +639,13 @@ static void rc_write(uint16_t port, uint8_t val, void *priv) { piix_reset(); } - resetide(); + ide_reset(); softresetx86(); } } reset_reg = val; -} */ +} +#endif void piix_reset(void) { diff --git a/src/pit.c b/src/pit.c index 79e918f04..493e0a130 100644 --- a/src/pit.c +++ b/src/pit.c @@ -2,8 +2,10 @@ Write B0 Write aa55 Expects aa55 back*/ - +#include +#include #include +#include #include "ibm.h" #include "cpu/cpu.h" #include "dma.h" @@ -19,7 +21,7 @@ /*B0 to 40, two writes to 43, then two reads - value does not change!*/ /*B4 to 40, two writes to 43, then two reads - value _does_ change!*/ -int displine; +int64_t displine; double PITCONST; float cpuclock; @@ -30,7 +32,7 @@ float MDACONST; float VGACONST1,VGACONST2; float RTCCONST; -int firsttime=1; +int64_t firsttime=1; void setpitclock(float clock) { cpuclock=clock; @@ -41,17 +43,17 @@ void setpitclock(float clock) VGACONST2=(clock/28322000.0); isa_timing = clock/8000000.0; bus_timing = clock/(double)cpu_busspeed; - video_updatetiming(); + video_update_timing(); - xt_cpu_multi = (int)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); + xt_cpu_multi = (int64_t)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); RTCCONST=clock/32768.0; - TIMER_USEC = (int)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); + TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); device_speed_changed(); } void pit_reset(PIT *pit) { - void (*old_set_out_funcs[3])(int new_out, int old_out); + void (*old_set_out_funcs[3])(int64_t new_out, int64_t old_out); PIT_nr old_pit_nr[3]; memcpy(old_set_out_funcs, pit->set_out_funcs, 3 * sizeof(void *)); @@ -60,9 +62,9 @@ void pit_reset(PIT *pit) memcpy(pit->set_out_funcs, old_set_out_funcs, 3 * sizeof(void *)); memcpy(pit->pit_nr, old_pit_nr, 3 * sizeof(PIT_nr)); - pit->l[0] = 0xFFFF; pit->c[0] = 0xFFFF*PITCONST; - pit->l[1] = 0xFFFF; pit->c[1] = 0xFFFF*PITCONST; - pit->l[2] = 0xFFFF; pit->c[2] = 0xFFFF*PITCONST; + pit->l[0] = 0xFFFF; pit->c[0] = 0xFFFFLL*PITCONST; + pit->l[1] = 0xFFFF; pit->c[1] = 0xFFFFLL*PITCONST; + pit->l[2] = 0xFFFF; pit->c[2] = 0xFFFFLL*PITCONST; pit->m[0] = pit->m[1] = pit->m[2] = 0; pit->ctrls[0] = pit->ctrls[1] = pit->ctrls[2] = 0; pit->thit[0]=1; @@ -84,15 +86,15 @@ float pit_timer0_freq() return (1193181.0 + (2.0 / 3.0))/(float)0x10000; } -static void pit_set_out(PIT *pit, int t, int out) +static void pit_set_out(PIT *pit, int64_t t, int64_t out) { pit->set_out_funcs[t](out, pit->out[t]); pit->out[t] = out; } -static void pit_load(PIT *pit, int t) +static void pit_load(PIT *pit, int64_t t) { - int l = pit->l[t] ? pit->l[t] : 0x10000; + int64_t l = pit->l[t] ? pit->l[t] : 0x10000LL; timer_process(); pit->newcount[t] = 0; pit->disabled[t] = 0; @@ -100,7 +102,7 @@ static void pit_load(PIT *pit, int t) { case 0: /*Interrupt on terminal count*/ pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((l << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 0); pit->thit[t] = 0; pit->enabled[t] = pit->gate[t]; @@ -112,7 +114,7 @@ static void pit_load(PIT *pit, int t) if (pit->initial[t]) { pit->count[t] = l - 1; - pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)(((l - 1) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -122,7 +124,7 @@ static void pit_load(PIT *pit, int t) if (pit->initial[t]) { pit->count[t] = l; - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -134,7 +136,7 @@ static void pit_load(PIT *pit, int t) else { pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((l << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 0); pit->thit[t] = 0; } @@ -149,9 +151,9 @@ static void pit_load(PIT *pit, int t) timer_update_outstanding(); } -void pit_set_gate_no_timer(PIT *pit, int t, int gate) +void pit_set_gate_no_timer(PIT *pit, int64_t t, int64_t gate) { - int l = pit->l[t] ? pit->l[t] : 0x10000; + int64_t l = pit->l[t] ? pit->l[t] : 0x10000LL; if (pit->disabled[t]) { @@ -170,7 +172,7 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((l << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 0); pit->thit[t] = 0; pit->enabled[t] = 1; @@ -180,7 +182,7 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l - 1; - pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)(((l - 1) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -190,7 +192,7 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l; - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -201,7 +203,7 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; } -void pit_set_gate(PIT *pit, int t, int gate) +void pit_set_gate(PIT *pit, int64_t t, int64_t gate) { if (pit->disabled[t]) { @@ -216,13 +218,13 @@ void pit_set_gate(PIT *pit, int t, int gate) timer_update_outstanding(); } -static void pit_over(PIT *pit, int t) +static void pit_over(PIT *pit, int64_t t) { - int l = pit->l[t] ? pit->l[t] : 0x10000; + int64_t l = pit->l[t] ? pit->l[t] : 0x10000LL; if (pit->disabled[t]) { pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((0xffff << TIMER_SHIFT) * PITCONST); return; } @@ -234,11 +236,11 @@ static void pit_over(PIT *pit, int t) pit_set_out(pit, t, 1); pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((0xffff << TIMER_SHIFT) * PITCONST); break; case 2: /*Rate generator*/ pit->count[t] += l; - pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((l << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 0); pit_set_out(pit, t, 1); break; @@ -247,13 +249,13 @@ static void pit_over(PIT *pit, int t) { pit_set_out(pit, t, 0); pit->count[t] += (l >> 1); - pit->c[t] += (int)(((l >> 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)(((l >> 1) << TIMER_SHIFT) * PITCONST); } else { pit_set_out(pit, t, 1); pit->count[t] += ((l + 1) >> 1); - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); } break; case 4: /*Software triggered strove*/ @@ -266,13 +268,13 @@ static void pit_over(PIT *pit, int t) { pit->newcount[t] = 0; pit->count[t] += l; - pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((l << TIMER_SHIFT) * PITCONST); } else { pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((0xffff << TIMER_SHIFT) * PITCONST); } break; case 5: /*Hardware triggered strove*/ @@ -283,52 +285,52 @@ static void pit_over(PIT *pit, int t) } pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((0xffff << TIMER_SHIFT) * PITCONST); break; } pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; } -int pit_get_timer_0() +int64_t pit_get_timer_0() { - int read = (int)((pit.c[0] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; + int64_t read = (int64_t)((pit.c[0] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; if (pit.m[0] == 2) read++; - if (read < 0) - read = 0; - if (read > 0x10000) - read = 0x10000; - if (pit.m[0] == 3) - read <<= 1; + if (read < 0LL) + read = 0LL; + if (read > 0x10000LL) + read = 0x10000LL; + if (pit.m[0] == 3LL) + read <<= 1LL; return read; } -static int pit_read_timer(PIT *pit, int t) +static int64_t pit_read_timer(PIT *pit, int64_t t) { timer_clock(); if (pit->using_timer[t]) { - int read = (int)((pit->c[t] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; + int64_t read = (int64_t)((pit->c[t] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; if (pit->m[t] == 2) read++; - if (read < 0) - read = 0; - if (read > 0x10000) - read = 0x10000; - if (pit->m[t] == 3) - read <<= 1; + if (read < 0LL) + read = 0LL; + if (read > 0x10000LL) + read = 0x10000LL; + if (pit->m[t] == 3LL) + read <<= 1LL; return read; } - if (pit->m[t] == 2) - return pit->count[t] + 1; + if (pit->m[t] == 2LL) + return pit->count[t] + 1LL; return pit->count[t]; } void pit_write(uint16_t addr, uint8_t val, void *p) { PIT *pit = (PIT *)p; - int t; - cycles -= (int)PITCONST; + int64_t t; + cycles -= (int64_t)PITCONST; switch (addr&3) { @@ -338,11 +340,11 @@ void pit_write(uint16_t addr, uint8_t val, void *p) if (!(val&0x20)) { if (val & 2) - pit->rl[0] = pit->using_timer[0] ? ((int)(pit->c[0] / PITCONST) >> TIMER_SHIFT) : pit->count[0]; + pit->rl[0] = pit->using_timer[0] ? ((int64_t)(pit->c[0] / PITCONST) >> TIMER_SHIFT) : pit->count[0]; if (val & 4) - pit->rl[1] = pit->using_timer[1] ? ((int)(pit->c[1] / PITCONST) >> TIMER_SHIFT) : pit->count[1]; + pit->rl[1] = pit->using_timer[1] ? ((int64_t)(pit->c[1] / PITCONST) >> TIMER_SHIFT) : pit->count[1]; if (val & 8) - pit->rl[2] = pit->using_timer[2] ? ((int)(pit->c[2] / PITCONST) >> TIMER_SHIFT) : pit->count[2]; + pit->rl[2] = pit->using_timer[2] ? ((int64_t)(pit->c[2] / PITCONST) >> TIMER_SHIFT) : pit->count[2]; } if (!(val & 0x10)) { @@ -435,9 +437,9 @@ void pit_write(uint16_t addr, uint8_t val, void *p) uint8_t pit_read(uint16_t addr, void *p) { PIT *pit = (PIT *)p; - int t; + int64_t t; uint8_t temp = 0xff; - cycles -= (int)PITCONST; + cycles -= (int64_t)PITCONST; switch (addr&3) { case 0: case 1: case 2: /*Timers*/ @@ -491,12 +493,12 @@ void pit_timer_over(void *p) { PIT_nr *pit_nr = (PIT_nr *)p; PIT *pit = pit_nr->pit; - int timer = pit_nr->nr; + int64_t timer = pit_nr->nr; pit_over(pit, timer); } -void pit_clock(PIT *pit, int t) +void pit_clock(PIT *pit, int64_t t) { if (pit->thit[t] || !pit->enabled[t]) return; @@ -509,28 +511,28 @@ void pit_clock(PIT *pit, int t) pit_over(pit, t); } -void pit_set_using_timer(PIT *pit, int t, int using_timer) +void pit_set_using_timer(PIT *pit, int64_t t, int64_t using_timer) { timer_process(); if (pit->using_timer[t] && !using_timer) pit->count[t] = pit_read_timer(pit, t); if (!pit->using_timer[t] && using_timer) - pit->c[t] = (int)((pit->count[t] << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((pit->count[t] << TIMER_SHIFT) * PITCONST); pit->using_timer[t] = using_timer; pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; timer_update_outstanding(); } -void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)) +void pit_set_out_func(PIT *pit, int64_t t, void (*func)(int64_t new_out, int64_t old_out)) { pit->set_out_funcs[t] = func; } -void pit_null_timer(int new_out, int old_out) +void pit_null_timer(int64_t new_out, int64_t old_out) { } -void pit_irq0_timer(int new_out, int old_out) +void pit_irq0_timer(int64_t new_out, int64_t old_out) { if (new_out && !old_out) picint(1); @@ -538,7 +540,7 @@ void pit_irq0_timer(int new_out, int old_out) picintc(1); } -void pit_irq0_timer_pcjr(int new_out, int old_out) +void pit_irq0_timer_pcjr(int64_t new_out, int64_t old_out) { if (new_out && !old_out) { @@ -549,7 +551,7 @@ void pit_irq0_timer_pcjr(int new_out, int old_out) picintc(1); } -void pit_irq0_ps2(int new_out, int old_out) +void pit_irq0_ps2(int64_t new_out, int64_t old_out) { if (new_out && !old_out) { @@ -562,21 +564,21 @@ void pit_irq0_ps2(int new_out, int old_out) pit_clock(&pit2, 0); } -void pit_refresh_timer_xt(int new_out, int old_out) +void pit_refresh_timer_xt(int64_t new_out, int64_t old_out) { if (new_out && !old_out) dma_channel_read(0); } -void pit_refresh_timer_at(int new_out, int old_out) +void pit_refresh_timer_at(int64_t new_out, int64_t old_out) { if (new_out && !old_out) ppi.pb ^= 0x10; } -void pit_speaker_timer(int new_out, int old_out) +void pit_speaker_timer(int64_t new_out, int64_t old_out) { - int l; + int64_t l; speaker_update(); @@ -589,7 +591,7 @@ void pit_speaker_timer(int new_out, int old_out) } -void pit_nmi_ps2(int new_out, int old_out) +void pit_nmi_ps2(int64_t new_out, int64_t old_out) { nmi = new_out; if (nmi) diff --git a/src/pit.h b/src/pit.h index 67db785b8..3fceeca27 100644 --- a/src/pit.h +++ b/src/pit.h @@ -3,15 +3,15 @@ extern double PITCONST; extern void pit_init(void); extern void pit_ps2_init(void); extern void pit_reset(PIT *pit); -extern void pit_set_gate(PIT *pit, int channel, int gate); -extern void pit_set_using_timer(PIT *pit, int t, int using_timer); -extern void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)); -extern void pit_clock(PIT *pit, int t); +extern void pit_set_gate(PIT *pit, int64_t channel, int64_t gate); +extern void pit_set_using_timer(PIT *pit, int64_t t, int64_t using_timer); +extern void pit_set_out_func(PIT *pit, int64_t t, void (*func)(int64_t new_out, int64_t old_out)); +extern void pit_clock(PIT *pit, int64_t t); -extern void pit_null_timer(int new_out, int old_out); -extern void pit_irq0_timer(int new_out, int old_out); -extern void pit_irq0_timer_pcjr(int new_out, int old_out); -extern void pit_refresh_timer_xt(int new_out, int old_out); -extern void pit_refresh_timer_at(int new_out, int old_out); -extern void pit_speaker_timer(int new_out, int old_out); +extern void pit_null_timer(int64_t new_out, int64_t old_out); +extern void pit_irq0_timer(int64_t new_out, int64_t old_out); +extern void pit_irq0_timer_pcjr(int64_t new_out, int64_t old_out); +extern void pit_refresh_timer_xt(int64_t new_out, int64_t old_out); +extern void pit_refresh_timer_at(int64_t new_out, int64_t old_out); +extern void pit_speaker_timer(int64_t new_out, int64_t old_out); diff --git a/src/plat.h b/src/plat.h new file mode 100644 index 000000000..1e0d0a9e9 --- /dev/null +++ b/src/plat.h @@ -0,0 +1,111 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Define the various platform support functions. + * + * Version: @(#)plat.h 1.0.7 2017/10/14 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#ifndef EMU_PLAT_H +# define EMU_PLAT_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Global variables residing in the platform module. */ + + +/* System-related functions. */ +extern FILE *plat_fopen(wchar_t *path, wchar_t *mode); +extern void plat_remove(wchar_t *path); +extern int plat_getcwd(wchar_t *bufp, int max); +extern int plat_chdir(wchar_t *path); +extern void get_executable_name(wchar_t *s, int size); +extern wchar_t *set_window_title(wchar_t *s); +extern int dir_check_exist(wchar_t *path); +extern int dir_create(wchar_t *path); + +extern void leave_fullscreen(void); +extern void plat_pause(int p); + + +/* Return the size (in wchar's) of a wchar_t array. */ +#define sizeof_w(x) (sizeof((x)) / sizeof(wchar_t)) + +/* The Win32 API uses _wcsicmp. */ +#ifdef WIN32 +# define wcscasecmp _wcsicmp +#endif + + +/* Resource management. */ +extern wchar_t *plat_get_string(int id); +extern wchar_t *plat_get_string_from_string(char *str); + + +/* Platform-specific device support. */ +extern uint8_t host_cdrom_drive_available[26]; +extern uint8_t host_cdrom_drive_available_num; +extern uint32_t cdrom_capacity; + +extern void cdrom_init_host_drives(void); +extern void cdrom_eject(uint8_t id); +extern void cdrom_reload(uint8_t id); +extern void removable_disk_unload(uint8_t id); +extern void removable_disk_eject(uint8_t id); +extern void removable_disk_reload(uint8_t id); +extern int ioctl_open(uint8_t id, char d); +extern void ioctl_reset(uint8_t id); +extern void ioctl_close(uint8_t id); + + +/* Thread support. */ +typedef void thread_t; +typedef void event_t; +typedef void mutex_t; + +extern thread_t *thread_create(void (*thread_rout)(void *param), void *param); +extern void thread_kill(thread_t *handle); + +extern void thread_sleep(int t); + +extern event_t *thread_create_event(void); +extern void thread_set_event(event_t *event); +extern void thread_reset_event(event_t *_event); +extern int thread_wait_event(event_t *event, int timeout); +extern void thread_destroy_event(event_t *_event); + +extern mutex_t *thread_create_mutex(wchar_t *name); +extern void thread_close_mutex(mutex_t *mutex); +extern int thread_wait_mutex(mutex_t *mutex); +extern int thread_release_mutex(mutex_t *mutex); + + +/* Other stuff. */ +extern void startblit(void); +extern void endblit(void); +extern void take_screenshot(void); + + +extern uint32_t get_ticks(void); +extern void delay_ms(uint32_t count); + + +#ifdef __cplusplus +} +#endif + + +#endif /*EMU_PLAT_H*/ diff --git a/src/win/plat_dir.h b/src/plat_dir.h similarity index 100% rename from src/win/plat_dir.h rename to src/plat_dir.h diff --git a/src/win/plat_dynld.h b/src/plat_dynld.h similarity index 100% rename from src/win/plat_dynld.h rename to src/plat_dynld.h diff --git a/src/win/plat_joystick.h b/src/plat_joystick.h similarity index 100% rename from src/win/plat_joystick.h rename to src/plat_joystick.h diff --git a/src/win/plat_keyboard.h b/src/plat_keyboard.h similarity index 100% rename from src/win/plat_keyboard.h rename to src/plat_keyboard.h diff --git a/src/win/plat_midi.h b/src/plat_midi.h similarity index 100% rename from src/win/plat_midi.h rename to src/plat_midi.h diff --git a/src/win/plat_mouse.h b/src/plat_mouse.h similarity index 100% rename from src/win/plat_mouse.h rename to src/plat_mouse.h diff --git a/src/win/plat_serial.h b/src/plat_serial.h similarity index 98% rename from src/win/plat_serial.h rename to src/plat_serial.h index 56cf08126..dc3fc338b 100644 --- a/src/win/plat_serial.h +++ b/src/plat_serial.h @@ -21,7 +21,7 @@ typedef struct { char name[80]; /* name of open port */ void (*rd_done)(void *, int); void *rd_arg; -#ifdef BHTTY_C +#ifdef PLAT_SERIAL_C HANDLE handle; OVERLAPPED rov, /* READ and WRITE events */ wov; diff --git a/src/ppi.c b/src/ppi.c index dfb315e2c..2fb10ec21 100644 --- a/src/ppi.c +++ b/src/ppi.c @@ -7,18 +7,22 @@ CX is loops between bit 4 of $62 changing BX is timer difference between calls */ - +#include +#include +#include +#include #include "ibm.h" #include "pit.h" #include "plat_keyboard.h" #include "plat_mouse.h" + PPI ppi; int ppispeakon; -void ppi_reset() + +void ppi_reset(void) { ppi.pa=0x0; ppi.pb=0x40; } - diff --git a/src/random.c b/src/random.c index 60caf02bb..9d7f1b229 100644 --- a/src/random.c +++ b/src/random.c @@ -9,7 +9,7 @@ * A better random number generation, used for floppy weak bits * and network MAC address generation. * - * Version: @(#)random.c 1.0.2 2017/09/03 + * Version: @(#)random.c 1.0.3 2017/09/24 * * Author: Miran Grca, * Copyright 2016,2017 Miran Grca. diff --git a/src/rom.c b/src/rom.c index 4114ee243..cc7bf154a 100644 --- a/src/rom.c +++ b/src/rom.c @@ -1,169 +1,806 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Handling of ROM image files. + * + * NOTES: - pc2386 BIOS is corrupt (JMP at F000:FFF0 points to RAM) + * - pc2386 video BIOS is underdumped (16k instead of 24k) + * - c386sx16 BIOS fails checksum + * - the loadfont() calls should be done elsewhere + * + * Version: @(#)rom.c 1.0.11 2017/10/14 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016-2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ #include +#include +#include +#include +#include #include "config.h" #include "ibm.h" #include "mem.h" #include "rom.h" +#include "video/video.h" /* for loadfont() */ +#include "plat.h" -FILE *romfopen(wchar_t *fn, wchar_t *mode) +int romspresent[ROM_MAX]; + + +FILE * +rom_fopen(wchar_t *fn, wchar_t *mode) { - wchar_t s[512]; - wcscpy(s, pcempath); - put_backslash_w(s); - wcscat(s, fn); - return _wfopen(s, mode); + wchar_t temp[1024]; + + wcscpy(temp, exe_path); + put_backslash_w(temp); + wcscat(temp, fn); + + return(plat_fopen(temp, mode)); } -FILE *nvrfopen(wchar_t *fn, wchar_t *mode) +int +rom_getfile(wchar_t *fn, wchar_t *s, int size) { - return _wfopen(nvr_concat(fn), mode); + FILE *f; + + wcscpy(s, exe_path); + put_backslash_w(s); + wcscat(s, fn); + + f = plat_fopen(s, L"rb"); + if (f != NULL) { + (void)fclose(f); + return(1); + } + + return(0); } -int rom_getfile(wchar_t *fn, wchar_t *s, int size) +int +rom_present(wchar_t *fn) { - FILE *f; + FILE *f; - wcscpy(s, pcempath); - put_backslash_w(s); - wcscat(s, fn); - f = _wfopen(s, L"rb"); - if (f) - { - fclose(f); - return 1; - } - return 0; -} + f = rom_fopen(fn, L"rb"); + if (f != NULL) { + (void)fclose(f); + return(1); + } -int rom_present(wchar_t *fn) -{ - FILE *f; - wchar_t s[512]; - - wcscpy(s, pcempath); - put_backslash_w(s); - wcscat(s, fn); - f = _wfopen(s, L"rb"); - if (f) - { - fclose(f); - return 1; - } - return 0; + return(0); } -uint8_t rom_read(uint32_t addr, void *p) +uint8_t +rom_read(uint32_t addr, void *priv) { - rom_t *rom = (rom_t *)p; + rom_t *rom = (rom_t *)priv; + #ifdef ROM_TRACE - if (rom->mapping.base==ROM_TRACE) - pclog("ROM: read byte from BIOS at %06lX\n", addr); + if (rom->mapping.base==ROM_TRACE) + pclog("ROM: read byte from BIOS at %06lX\n", addr); #endif - return rom->rom[addr & rom->mask]; + + return(rom->rom[addr & rom->mask]); } -uint16_t rom_readw(uint32_t addr, void *p) +uint16_t +rom_readw(uint32_t addr, void *priv) { - rom_t *rom = (rom_t *)p; + rom_t *rom = (rom_t *)priv; + #ifdef ROM_TRACE - if (rom->mapping.base==ROM_TRACE) - pclog("ROM: read word from BIOS at %06lX\n", addr); + if (rom->mapping.base==ROM_TRACE) + pclog("ROM: read word from BIOS at %06lX\n", addr); #endif - return *(uint16_t *)&rom->rom[addr & rom->mask]; + + return(*(uint16_t *)&rom->rom[addr & rom->mask]); } -uint32_t rom_readl(uint32_t addr, void *p) +uint32_t +rom_readl(uint32_t addr, void *priv) { - rom_t *rom = (rom_t *)p; + rom_t *rom = (rom_t *)priv; + #ifdef ROM_TRACE - if (rom->mapping.base==ROM_TRACE) - pclog("ROM: read long from BIOS at %06lX\n", addr); + if (rom->mapping.base==ROM_TRACE) + pclog("ROM: read long from BIOS at %06lX\n", addr); #endif - return *(uint32_t *)&rom->rom[addr & rom->mask]; + + return(*(uint32_t *)&rom->rom[addr & rom->mask]); } -int rom_init(rom_t *rom, wchar_t *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags) +/* Load a ROM BIOS from its chips, interleaved mode. */ +int +rom_load_linear(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { - FILE *f = romfopen(fn, L"rb"); + FILE *f = rom_fopen(fn, L"rb"); - if (!f) - { - pclog("ROM image not found : %ws\n", fn); - return -1; - } - - rom->rom = malloc(size); - fseek(f, file_offset, SEEK_SET); - fread(rom->rom, size, 1, f); - fclose(f); - - rom->mask = mask; - - mem_mapping_add(&rom->mapping, address, size, rom_read, - rom_readw, - rom_readl, - mem_write_null, - mem_write_nullw, - mem_write_nulll, - rom->rom, - flags, - rom); + if (f == NULL) { + pclog("ROM: image '%ls' not found\n", fn); + return(0); + } - return 0; + /* Make sure we only look at the base-256K offset. */ + if (addr >= 0x40000) + { + addr = 0; + } + else + { + addr &= 0x03ffff; + } + + (void)fseek(f, off, SEEK_SET); + (void)fread(ptr+addr, sz, 1, f); + (void)fclose(f); + + return(1); } -int rom_init_interleaved(rom_t *rom, wchar_t *fn_low, wchar_t *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags) +/* Load a ROM BIOS from its chips, interleaved mode. */ +int +rom_load_interleaved(wchar_t *fnl, wchar_t *fnh, uint32_t addr, int sz, int off, uint8_t *ptr) { - FILE *f_low = romfopen(fn_low, L"rb"); - FILE *f_high = romfopen(fn_high, L"rb"); - int c; - - if (!f_low || !f_high) - { - if (!f_low) - pclog("ROM image not found : %ws\n", fn_low); - else - fclose(f_low); - if (!f_high) - pclog("ROM image not found : %ws\n", fn_high); - else - fclose(f_high); - return -1; - } - - rom->rom = malloc(size); - fseek(f_low, file_offset, SEEK_SET); - fseek(f_high, file_offset, SEEK_SET); - for (c = 0; c < size; c += 2) - { - rom->rom[c] = getc(f_low); - rom->rom[c + 1] = getc(f_high); - } - fclose(f_high); - fclose(f_low); - - rom->mask = mask; - - mem_mapping_add(&rom->mapping, address, size, rom_read, - rom_readw, - rom_readl, - mem_write_null, - mem_write_nullw, - mem_write_nulll, - rom->rom, - flags, - rom); + FILE *fl = rom_fopen(fnl, L"rb"); + FILE *fh = rom_fopen(fnh, L"rb"); + int c; - return 0; + if (fl == NULL || fh == NULL) { + if (fl == NULL) pclog("ROM: image '%ls' not found\n", fnl); + else (void)fclose(fl); + if (fh == NULL) pclog("ROM: image '%ls' not found\n", fnh); + else (void)fclose(fh); + + return(0); + } + + /* Make sure we only look at the base-256K offset. */ + if (addr >= 0x40000) + { + addr = 0; + } + else + { + addr &= 0x03ffff; + } + + (void)fseek(fl, off, SEEK_SET); + (void)fseek(fh, off, SEEK_SET); + for (c=0; crom = malloc(sz); + memset(rom->rom, 0xff, sz); + + /* Load the image file into the buffer. */ + if (! rom_load_linear(fn, addr, sz, off, rom->rom)) { + /* Nope.. clean up. */ + free(rom->rom); + rom->rom = NULL; + return(-1); + } + + rom->mask = mask; + + mem_mapping_add(&rom->mapping, + addr, sz, + rom_read, rom_readw, rom_readl, + mem_write_null, mem_write_nullw, mem_write_nulll, + rom->rom, flags, rom); + + return(0); +} + + +int +rom_init_interleaved(rom_t *rom, wchar_t *fnl, wchar_t *fnh, uint32_t addr, int sz, int mask, int off, uint32_t flags) +{ + /* Allocate a buffer for the image. */ + rom->rom = malloc(sz); + memset(rom->rom, 0xff, sz); + + /* Load the image file into the buffer. */ + if (! rom_load_interleaved(fnl, fnh, addr, sz, off, rom->rom)) { + /* Nope.. clean up. */ + free(rom->rom); + rom->rom = NULL; + return(-1); + } + + rom->mask = mask; + + mem_mapping_add(&rom->mapping, + addr, sz, + rom_read, rom_readw, rom_readl, + mem_write_null, mem_write_nullw, mem_write_nulll, + rom->rom, flags, rom); + + return(0); +} + + +/* Load the ROM BIOS image(s) for the selected machine into memory. */ +int +rom_load_bios(int rom_id) +{ + FILE *f; + + loadfont(L"roms/video/mda/mda.rom", 0); + loadfont(L"roms/video/wyse700/wy700.rom", 3); + + /* If not done yet, allocate a 128KB buffer for the BIOS ROM. */ + if (rom == NULL) + rom = (uint8_t *)malloc(131072); + memset(rom, 0xff, 131072); + + /* Default to a 64K ROM BIOS image. */ + biosmask = 0xffff; + + /* Zap the BIOS ROM EXTENSION area. */ + memset(romext, 0xff, 0x8000); + mem_mapping_disable(&romext_mapping); + + switch (rom_id) { + case ROM_IBMPC: /* IBM PC */ + if (! rom_load_linear( + L"roms/machines/ibmpc/pc102782.bin", + 0x00e000, 8192, 0, rom)) break; + + /* Try to load the (full) BASIC ROM. */ + if (rom_load_linear( + L"roms/machines/ibmpc/ibm-basic-1.10.rom", + 0x006000, 32768, 0, rom)) return(1); + + /* Nope. Try to load the first BASIC ROM image. */ + if (! rom_load_linear( + L"roms/machines/ibmpc/basicc11.f6", + 0x006000, 8192, 0, rom)) return(1); /* nope */ + if (! rom_load_linear( + L"roms/machines/ibmpc/basicc11.f8", + 0x008000, 8192, 0, rom)) break; /* nope */ + if (! rom_load_linear( + L"roms/machines/ibmpc/basicc11.fa", + 0x00a000, 8192, 0, rom)) break; /* nope */ + if (! rom_load_linear( + L"roms/machines/ibmpc/basicc11.fc", + 0x00c000, 8192, 0, rom)) break; /* nope */ + return(1); + + case ROM_IBMXT: /* IBM PX-XT */ + if (rom_load_linear( + L"roms/machines/ibmxt/xt.rom", + 0x000000, 65536, 0, rom)) return(1); + + if (! rom_load_linear( + L"roms/machines/ibmxt/5000027.u19", + 0x000000, 32768, 0, rom)) break; + if (rom_load_linear( + L"roms/machines/ibmxt/1501512.u18", + 0x008000, 32768, 0, rom)) return(1); + break; + + case ROM_IBMXT286: /* IBM PX-XT 286 */ + if (rom_load_interleaved( + L"roms/machines/ibmxt286/BIOS_5162_21APR86_U34_78X7460_27256.BIN", + L"roms/machines/ibmxt286/BIOS_5162_21APR86_U35_78X7461_27256.BIN", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_IBMPCJR: /* IBM PCjr */ + if (rom_load_linear( + L"roms/machines/ibmpcjr/bios.rom", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_IBMAT: /* IBM PC-AT */ + if (rom_load_interleaved( + L"roms/machines/ibmat/62x0820.u27", + L"roms/machines/ibmat/62x0821.u47", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_GENXT: /* Generic PC-XT clone */ + if (rom_load_linear( + L"roms/machines/genxt/pcxt.rom", + 0x00e000, 8192, 0, rom)) return(1); + break; + + case ROM_PC1512: /* Amstrad PC-1512 */ + if (! rom_load_interleaved( + L"roms/machines/pc1512/40043.v1", + L"roms/machines/pc1512/40044.v1", + 0x00c000, 16384, 0, rom)) break; + loadfont(L"roms/machines/pc1512/40078.ic127", 2); + return(1); + + case ROM_PC1640: /* Amstrad PC-1640 */ + if (! rom_load_interleaved( + L"roms/machines/pc1640/40044.v3", + L"roms/machines/pc1640/40043.v3", + 0x00c000, 16384, 0, rom)) break; + f = rom_fopen(L"roms/machines/pc1640/40100", L"rb"); + if (f == NULL) break; + (void)fclose(f); + return(1); + + case ROM_PC200: + if (! rom_load_interleaved( + L"roms/machines/pc200/pc20v2.1", + L"roms/machines/pc200/pc20v2.0", + 0x00c000, 16384, 0, rom)) break; + loadfont(L"roms/machines/pc200/40109.bin", 1); + return(1); + + case ROM_TANDY: + if (rom_load_linear( + L"roms/machines/tandy/tandy1t1.020", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_TANDY1000HX: + if (! rom_load_linear( + L"roms/machines/tandy1000hx/v020000.u12", + 0x000000, 0x20000, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_TANDY1000SL2: + if (rom_load_interleaved( + L"roms/machines/tandy1000sl2/8079047.hu1", + L"roms/machines/tandy1000sl2/8079048.hu2", + 0x000000, 65536, 0x30000/2, rom)) return(1); + break; + + case ROM_PORTABLE: + if (rom_load_linear( + L"roms/machines/portable/Compaq Portable Plus 100666-001 Rev C u47.bin", + 0x00e000, 8192, 0, rom)) return(1); + break; + +#if NOT_USED + case ROM_PORTABLEII: + if (! rom_load_interleaved( + L"roms/machines/portableii/106438-001.BIN", + L"roms/machines/portableii/106437-001.BIN", + 0x000000, 32768, 0, rom)) break; + biosmask = 0x7fff; + return(1); + + case ROM_PORTABLEIII: + case ROM_PORTABLEIII386: + if (rom_load_interleaved( + L"roms/machines/portableiii/109738-002.BIN", + L"roms/machines/portableiii/109737-002.BIN", + 0x000000, 32768, 0, rom)) return(1); + biosmask = 0x7fff; + break; +#endif + + case ROM_DTKXT: + if (rom_load_linear( + L"roms/machines/dtk/DTK_ERSO_2.42_2764.bin", + 0x00e000, 8192, 0, rom)) return(1); + break; + + case ROM_OLIM24: + if (rom_load_interleaved( + L"roms/machines/olivetti_m24/olivetti_m24_version_1.43_low.bin", + L"roms/machines/olivetti_m24/olivetti_m24_version_1.43_high.bin", + 0x00c000, 16384, 0, rom)) return(1); + break; + + case ROM_PC2086: + if (! rom_load_interleaved( + L"roms/machines/pc2086/40179.ic129", + L"roms/machines/pc2086/40180.ic132", + 0x000000, 16384, 0, rom)) break; + f = rom_fopen(L"roms/machines/pc2086/40186.ic171", L"rb"); + if (f == NULL) break; + (void)fclose(f); + biosmask = 0x3fff; + return(1); + + case ROM_PC3086: + if (! rom_load_linear( + L"roms/machines/pc3086/fc00.bin", + 0x000000, 16384, 0, rom)) break; + f = rom_fopen(L"roms/machines/pc3086/c000.bin", L"rb"); + if (f == NULL) break; + (void)fclose(f); + biosmask = 0x3fff; + return(1); + + case ROM_CMDPC30: + if (! rom_load_interleaved( + L"roms/machines/cmdpc30/commodore pc 30 iii even.bin", + L"roms/machines/cmdpc30/commodore pc 30 iii odd.bin", + 0x000000, 32768, 0, rom)) break; + biosmask = 0x7fff; + return(1); + + case ROM_AMI386SX: + if (rom_load_linear( + L"roms/machines/ami386/ami386.bin", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_AMI386DX_OPTI495: /* uses the OPTi 82C495 chipset */ + if (rom_load_linear( + L"roms/machines/ami386dx/OPT495SX.AMI", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_MR386DX_OPTI495: /* uses the OPTi 82C495 chipset */ + if (rom_load_linear( + L"roms/machines/mr386dx/OPT495SX.MR", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_AWARD386SX_OPTI495: /* uses the OPTi 82C495 chipset */ + case ROM_AWARD386DX_OPTI495: /* uses the OPTi 82C495 chipset */ + case ROM_AWARD486_OPTI495: /* uses the OPTi 82C495 chipset */ + if (rom_load_linear( + L"roms/machines/award495/OPT495S.AWA", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_AMI286: + if (rom_load_linear( + L"roms/machines/ami286/amic206.bin", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_AWARD286: + if (rom_load_linear( + L"roms/machines/award286/award.bin", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_EUROPC: + if (rom_load_linear( + L"roms/machines/europc/50145", + 0x008000, 32768, 0, rom)) return(1); + break; + + case ROM_MEGAPC: + case ROM_MEGAPCDX: + if (rom_load_interleaved( + L"roms/machines/megapc/41651-bios lo.u18", + L"roms/machines/megapc/211253-bios hi.u19", + 0x000000, 65536, 0x08000, rom)) return(1); + break; + + case ROM_AMI486: + if (rom_load_linear( + L"roms/machines/ami486/ami486.BIN", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_WIN486: + if (rom_load_linear( + L"roms/machines/win486/ALI1429G.AMW", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_430VX: + if (! rom_load_linear( + L"roms/machines/430vx/55XWUQ0E.BIN", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_REVENGE: + if (! rom_load_linear( + L"roms/machines/revenge/1009AF2_.BIO", + 0x010000, 65536, 128, rom)) break; + if (! rom_load_linear( + L"roms/machines/revenge/1009AF2_.BI1", + 0x000000, 0x00c000, 128, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_ENDEAVOR: + if (! rom_load_linear( + L"roms/machines/endeavor/1006CB0_.BIO", + 0x010000, 65536, 128, rom)) break; + if (! rom_load_linear( + L"roms/machines/endeavor/1006CB0_.BI1", + 0x000000, 0x00d000, 128, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_IBMPS1_2011: + if (! rom_load_linear( + L"roms/machines/ibmps1es/f80000.bin", + 0x000000, 131072, 0x60000, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_IBMPS1_2121: + case ROM_IBMPS1_2121_ISA: + if (! rom_load_linear( + L"roms/machines/ibmps1_2121/fc0000.bin", + 0x000000, 131072, 0x20000, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_IBMPS1_2133: + if (! rom_load_linear( + L"roms/machines/ibmps1_2133/PS1_2133_52G2974_ROM.bin", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_DESKPRO_386: + if (rom_load_interleaved( + L"roms/machines/deskpro386/109592-005.U11.bin", + L"roms/machines/deskpro386/109591-005.U13.bin", + 0x000000, 32768, 0, rom)) break; + biosmask = 0x7fff; + return(1); + + case ROM_AMIXT: + if (rom_load_linear( + L"roms/machines/amixt/AMI_8088_BIOS_31JAN89.BIN", + 0x00e000, 8192, 0, rom)) return(1); + break; + + case ROM_LTXT: + if (rom_load_linear( + L"roms/machines/ltxt/27C64.bin", + 0x00e000, 8192, 0, rom)) return(1); + break; + + case ROM_LXT3: + if (rom_load_linear( + L"roms/machines/lxt3/27C64D.bin", + 0x00e000, 8192, 0, rom)) return(1); + break; + + case ROM_SPC4200P: /* Samsung SPC-4200P */ + if (rom_load_linear( + L"roms/machines/spc4200p/U8.01", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_SUPER286TR: /* Hyundai Super-286TR */ + if (rom_load_linear( + L"roms/machines/super286tr/hyundai_award286.bin", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_DTK386: /* uses NEAT chipset */ + if (rom_load_linear( + L"roms/machines/dtk386/3cto001.bin", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_PXXT: + if (rom_load_linear( + L"roms/machines/pxxt/000p001.bin", + 0x00e000, 8192, 0, rom)) return(1); + break; + + case ROM_JUKOPC: + if (rom_load_linear( + L"roms/machines/jukopc/000o001.bin", + 0x00e000, 8192, 0, rom)) return(1); + break; + + case ROM_IBMPS2_M30_286: + if (! rom_load_linear( + L"roms/machines/ibmps2_m30_286/33f5381a.bin", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_DTK486: + if (rom_load_linear( + L"roms/machines/dtk486/4siw005.bin", + 0x000000, 65536, 0, rom)) return(1); + break; + + case ROM_R418: + if (! rom_load_linear( + L"roms/machines/r418/r418i.bin", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + +#if 0 + case ROM_586MC1: + if (! rom_load_linear( + L"roms/machines/586mc1/IS.34", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); +#endif + + case ROM_PLATO: + if (! rom_load_linear( + L"roms/machines/plato/1016AX1_.BIO", + 0x010000, 65536, 128, rom)) break; + if (! rom_load_linear( + L"roms/machines/plato/1016AX1_.BI1", + 0x000000, 0x00d000, 128, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_MB500N: + if (! rom_load_linear( + L"roms/machines/mb500n/031396S.BIN", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_AP53: + if (! rom_load_linear( + L"roms/machines/ap53/AP53R2C0.ROM", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_P55T2S: + if (! rom_load_linear( + L"roms/machines/p55t2s/S6Y08T.ROM", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_PRESIDENT: + if (! rom_load_linear( + L"roms/machines/president/BIOS.BIN", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_P54TP4XE: + if (! rom_load_linear( + L"roms/machines/p54tp4xe/T15I0302.AWD", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_ACERM3A: + if (! rom_load_linear( + L"roms/machines/acerm3a/r01-b3.bin", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_ACERV35N: + if (! rom_load_linear( + L"roms/machines/acerv35n/V35ND1S1.BIN", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_P55VA: + if (! rom_load_linear( + L"roms/machines/p55va/VA021297.BIN", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_P55T2P4: + if (! rom_load_linear( + L"roms/machines/p55t2p4/0207_J2.BIN", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_P55TVP4: + if (! rom_load_linear( + L"roms/machines/p55tvp4/TV5I0204.AWD", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_440FX: /* working Tyan BIOS */ + if (! rom_load_linear( + L"roms/machines/440fx/NTMAW501.BIN", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_S1668: /* working Tyan BIOS */ + if (! rom_load_linear( + L"roms/machines/tpatx/S1668P.ROM", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_THOR: + if (! rom_load_linear( + L"roms/machines/thor/1006CN0_.BIO", + 0x010000, 65536, 128, rom)) break; + if (! rom_load_linear( + L"roms/machines/thor/1006CN0_.BI1", + 0x000000, 65536, 128, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_MRTHOR: + if (! rom_load_linear( + L"roms/machines/mrthor/MR_ATX.BIO", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_ZAPPA: + if (! rom_load_linear( + L"roms/machines/zappa/1006BS0_.BIO", + 0x010000, 65536, 128, rom)) break; + if (! rom_load_linear( + L"roms/machines/zappa/1006BS0_.BI1", + 0x000000, 65536, 128, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_IBMPS2_M50: + if (! rom_load_interleaved( + L"roms/machines/ibmps2_m50/90x7423.zm14", + L"roms/machines/ibmps2_m50/90x7426.zm16", + 0x000000, 65536, 0, rom)) break; + if (! rom_load_interleaved( + L"roms/machines/ibmps2_m50/90x7420.zm13", + L"roms/machines/ibmps2_m50/90x7429.zm18", + 0x010000, 65536, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_IBMPS2_M55SX: + if (! rom_load_interleaved( + L"roms/machines/ibmps2_m55sx/33f8146.zm41", + L"roms/machines/ibmps2_m55sx/33f8145.zm40", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + case ROM_IBMPS2_M80: + case ROM_IBMPS2_M80_486: + if (! rom_load_interleaved( + L"roms/machines/ibmps2_m80/15f6637.bin", + L"roms/machines/ibmps2_m80/15f6639.bin", + 0x000000, 131072, 0, rom)) break; + biosmask = 0x1ffff; + return(1); + + default: + pclog("ROM: don't know how to handle ROM set %d !\n", rom_id); + } + + return(0); } diff --git a/src/rom.h b/src/rom.h index a2f85d01f..21d52a695 100644 --- a/src/rom.h +++ b/src/rom.h @@ -1,21 +1,146 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern FILE *romfopen(wchar_t *fn, wchar_t *mode); -extern FILE *nvrfopen(wchar_t *fn, wchar_t *mode); -extern int rom_getfile(wchar_t *fn, wchar_t *s, int size); -extern int rom_present(wchar_t *fn); +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for the ROM image handler. + * + * Version: @(#)rom.h 1.0.2 2017/09/25 + * + * Author: Fred N. van Kempen, + * Copyright 2017 Fred N. van Kempen. + */ +#ifndef EMU_ROM_H +# define EMU_ROM_H -typedef struct rom_t -{ - uint8_t *rom; - uint32_t mask; - mem_mapping_t mapping; + +#define PCJR (romset==ROM_IBMPCJR) +#define AMIBIOS (romset==ROM_AMI386SX || \ + romset==ROM_AMI486 || \ + romset==ROM_WIN486) + + +typedef struct { + uint8_t *rom; + uint32_t mask; + mem_mapping_t mapping; } rom_t; -extern int rom_init(rom_t *rom, wchar_t *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags); -extern int rom_init_interleaved(rom_t *rom, wchar_t *fn_low, wchar_t *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags); -extern uint8_t rom_read(uint32_t addr, void *p); -extern uint16_t rom_readw(uint32_t addr, void *p); -extern uint32_t rom_readl(uint32_t addr, void *p); +enum { + ROM_IBMPC = 0, /* 301 keyboard error, 131 cassette (!!!) error */ + ROM_IBMXT, /* 301 keyboard error */ + ROM_IBMPCJR, + ROM_GENXT, /* 'Generic XT BIOS' */ + ROM_DTKXT, + ROM_EUROPC, + ROM_OLIM24, + ROM_TANDY, + ROM_PC1512, + ROM_PC200, + ROM_PC1640, + ROM_PC2086, + ROM_PC3086, + ROM_AMIXT, /* XT Clone with AMI BIOS */ + ROM_LTXT, + ROM_LXT3, + ROM_DTK386, + ROM_PXXT, + ROM_JUKOPC, + ROM_TANDY1000HX, + ROM_TANDY1000SL2, + ROM_IBMAT, + ROM_CMDPC30, + ROM_AMI286, + ROM_AWARD286, + ROM_MEGAPC, + ROM_AMI386SX, + ROM_AMI486, + ROM_WIN486, + ROM_430VX, + ROM_ENDEAVOR, + ROM_REVENGE, + ROM_IBMPS1_2011, + ROM_IBMXT286, + ROM_DESKPRO_386, + ROM_PORTABLE, + ROM_IBMPS1_2121, + + ROM_AMI386DX_OPTI495, + ROM_MR386DX_OPTI495, + + ROM_IBMPS2_M30_286, + ROM_IBMPS2_M50, + ROM_IBMPS2_M55SX, + ROM_IBMPS2_M80, + + ROM_DTK486, /* DTK PKM-0038S E-2/SiS 471/Award/SiS 85C471 */ + ROM_VLI486SV2G, /* ASUS VL/I-486SV2G/SiS 471/Award/SiS 85C471 */ /* 51 */ + ROM_R418, /* Rise Computer R418/SiS 496/497/Award/SMC FDC37C665 */ + ROM_PLATO, /* Intel Premiere/PCI II/430NX/AMI/SMC FDC37C665 */ + ROM_MB500N, /* PC Partner MB500N/430FX/Award/SMC FDC37C665 */ + ROM_P54TP4XE, /* ASUS P/I-P55TP4XE/430FX/Award/SMC FDC37C665 */ + ROM_AP53, /* AOpen AP53/430HX/AMI/SMC FDC37C665/669 */ + ROM_P55T2S, /* ASUS P/I-P55T2S/430HX/AMI/NS PC87306 */ + ROM_ACERM3A, /* Acer M3A/430HX/Acer/SMC FDC37C932FR */ + ROM_ACERV35N, /* Acer V35N/430HX/Acer/SMC FDC37C932FR */ + ROM_P55T2P4, /* ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/ + ROM_P55TVP4, /* ASUS P/I-P55TVP4/430HX/Award/Winbond W8387F*/ + ROM_P55VA, /* Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ + ROM_THOR, /* Intel Advanced_ATX/430FX/AMI/NS PC87306 */ + ROM_MRTHOR, /* Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ + ROM_POWERMATE_V, /* NEC PowerMate V/430FX/Phoenix/SMC FDC37C66 5*/ /* 68 */ + + ROM_440FX, /* Tyan Titan-Pro AT/440FX/Award BIOS/SMC FDC37C665 */ + + ROM_IBMPS1_2121_ISA,/* IBM PS/1 Model 2121 with ISA expansion bus */ + + ROM_SPC4200P, /* Samsung SPC-4200P/SCAT/Phoenix */ + ROM_SUPER286TR, /* Hyundai Super-286TR/SCAT/Award */ + + ROM_AWARD386SX_OPTI495, + ROM_AWARD386DX_OPTI495, + ROM_AWARD486_OPTI495, + + ROM_MEGAPCDX, /* 386DX mdl - Note: documentation (in German) clearly says such a model exists */ + ROM_ZAPPA, /* Intel Advanced_ZP/430FX/AMI/NS PC87306 */ + + ROM_S1668, /* Tyan Titan-Pro ATX/440FX/AMI/SMC FDC37C669 */ + ROM_IBMPS1_2133, + + ROM_PRESIDENT, /* President Award 430FX PCI/430FX/Award/Unknown SIO */ + ROM_IBMPS2_M80_486, + + ROM_MAX +}; + + +extern int romspresent[ROM_MAX]; + +extern uint8_t rom_read(uint32_t addr, void *p); +extern uint16_t rom_readw(uint32_t addr, void *p); +extern uint32_t rom_readl(uint32_t addr, void *p); + +extern FILE *rom_fopen(wchar_t *fn, wchar_t *mode); +extern int rom_getfile(wchar_t *fn, wchar_t *s, int size); +extern int rom_present(wchar_t *fn); + +extern int rom_load_linear(wchar_t *fn, uint32_t addr, int sz, + int off, uint8_t *ptr); +extern int rom_load_interleaved(wchar_t *fnl, wchar_t *fnh, uint32_t addr, + int sz, int off, uint8_t *ptr); + +extern int rom_init(rom_t *rom, wchar_t *fn, uint32_t address, int size, + int mask, int file_offset, uint32_t flags); +extern int rom_init_interleaved(rom_t *rom, wchar_t *fn_low, + wchar_t *fn_high, uint32_t address, + int size, int mask, int file_offset, + uint32_t flags); + +extern int rom_load_bios(int rom_id); + + +#endif /*EMU_ROM_H*/ diff --git a/src/rtc.c b/src/rtc.c deleted file mode 100644 index 478eba9e0..000000000 --- a/src/rtc.c +++ /dev/null @@ -1,247 +0,0 @@ -/* Emulation of: - Dallas Semiconductor DS12C887 Real Time Clock - - http://datasheets.maximintegrated.com/en/ds/DS12885-DS12C887A.pdf - - http://dev-docs.atariforge.org/files/MC146818A_RTC_1984.pdf - */ - -#include -#include -#include -#include -#include -#include "nvr.h" -#include "rtc.h" - -int enable_sync; - -struct -{ - int sec; - int min; - int hour; - int mday; - int mon; - int year; -} internal_clock; - -/* Table for days in each month */ -static int rtc_days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -/* Called to determine whether the year is leap or not */ -static int rtc_is_leap(int org_year) -{ - if (org_year % 400 == 0) return 1; - if (org_year % 100 == 0) return 0; - if (org_year % 4 == 0) return 1; - return 0; -} - -/* Called to determine the days in the current month */ -static int rtc_get_days(int org_month, int org_year) -{ - if (org_month != 2) - return rtc_days_in_month[org_month - 1]; - else - return rtc_is_leap(org_year) ? 29 : 28; -} - -/* Called when the internal clock gets updated */ -static void rtc_recalc(void) -{ - if (internal_clock.sec == 60) - { - internal_clock.sec = 0; - internal_clock.min++; - } - if (internal_clock.min == 60) - { - internal_clock.min = 0; - internal_clock.hour++; - } - if (internal_clock.hour == 24) - { - internal_clock.hour = 0; - internal_clock.mday++; - } - if (internal_clock.mday == (rtc_get_days(internal_clock.mon, internal_clock.year) + 1)) - { - internal_clock.mday = 1; - internal_clock.mon++; - } - if (internal_clock.mon == 13) - { - internal_clock.mon = 1; - internal_clock.year++; - } -} - -/* Called when ticking the second */ -void rtc_tick(void) -{ - internal_clock.sec++; - rtc_recalc(); -} - -/* Called when modifying the NVR registers */ -void time_update(char *nvrram, int reg) -{ - int temp; - - switch(reg) - { - case RTC_SECONDS: - internal_clock.sec = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_SECONDS] : DCB(nvrram[RTC_SECONDS]); - break; - case RTC_MINUTES: - internal_clock.min = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MINUTES] : DCB(nvrram[RTC_MINUTES]); - break; - case RTC_HOURS: - temp = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_HOURS] : DCB(nvrram[RTC_HOURS]); - - if (nvrram[RTC_REGB] & RTC_2412) - internal_clock.hour = temp; - else - internal_clock.hour = ((temp & ~RTC_AMPM) % 12) + ((temp & RTC_AMPM) ? 12 : 0); - break; - case RTC_DOM: - internal_clock.mday = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_DOM] : DCB(nvrram[RTC_DOM]); - break; - case RTC_MONTH: - internal_clock.mon = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MONTH] : DCB(nvrram[RTC_MONTH]); - break; - case RTC_YEAR: - internal_clock.year = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_YEAR] : DCB(nvrram[RTC_YEAR]); - internal_clock.year += (nvrram[RTC_REGB] & RTC_DM) ? 1900 : (DCB(nvrram[RTC_CENTURY]) * 100); - break; - case RTC_CENTURY: - if (nvrram[RTC_REGB] & RTC_DM) - return; - internal_clock.year %= 100; - internal_clock.year += (DCB(nvrram[RTC_CENTURY]) * 100); - break; - } -} - -/* Called to obtain the current day of the week based on the internal clock */ -static int time_week_day(void) -{ - int day_of_month = internal_clock.mday; - int month2 = internal_clock.mon; - int year2 = internal_clock.year % 100; - int century = ((internal_clock.year - year2) / 100) % 4; - int sum = day_of_month + month2 + year2 + century; - /* (Sum mod 7) gives 0 for Saturday, we need it for Sunday, so +6 for Saturday to get 6 and Sunday 0 */ - int raw_wd = ((sum + 6) % 7); - return raw_wd; -} - -/* Called to get time into the internal clock */ -static void time_internal_get(struct tm *time_var) -{ - time_var->tm_sec = internal_clock.sec; - time_var->tm_min = internal_clock.min; - time_var->tm_hour = internal_clock.hour; - time_var->tm_wday = time_week_day(); - time_var->tm_mday = internal_clock.mday; - time_var->tm_mon = internal_clock.mon - 1; - time_var->tm_year = internal_clock.year - 1900; -} - -static void time_internal_set(struct tm *time_var) -{ - internal_clock.sec = time_var->tm_sec; - internal_clock.min = time_var->tm_min; - internal_clock.hour = time_var->tm_hour; - internal_clock.mday = time_var->tm_mday; - internal_clock.mon = time_var->tm_mon + 1; - internal_clock.year = time_var->tm_year + 1900; -} - -static void time_set_nvrram(char *nvrram, struct tm *cur_time_tm) -{ - if (nvrram[RTC_REGB] & RTC_DM) - { - nvrram[RTC_SECONDS] = cur_time_tm->tm_sec; - nvrram[RTC_MINUTES] = cur_time_tm->tm_min; - nvrram[RTC_DOW] = cur_time_tm->tm_wday + 1; - nvrram[RTC_DOM] = cur_time_tm->tm_mday; - nvrram[RTC_MONTH] = cur_time_tm->tm_mon + 1; - nvrram[RTC_YEAR] = cur_time_tm->tm_year % 100; - - if (nvrram[RTC_REGB] & RTC_2412) - { - nvrram[RTC_HOURS] = cur_time_tm->tm_hour; - } - else - { - nvrram[RTC_HOURS] = (cur_time_tm->tm_hour % 12) ? (cur_time_tm->tm_hour % 12) : 12; - if (cur_time_tm->tm_hour > 11) - nvrram[RTC_HOURS] |= RTC_AMPM; - } - } - else - { - nvrram[RTC_SECONDS] = BCD(cur_time_tm->tm_sec); - nvrram[RTC_MINUTES] = BCD(cur_time_tm->tm_min); - nvrram[RTC_DOW] = BCD(cur_time_tm->tm_wday + 1); - nvrram[RTC_DOM] = BCD(cur_time_tm->tm_mday); - nvrram[RTC_MONTH] = BCD(cur_time_tm->tm_mon + 1); - nvrram[RTC_YEAR] = BCD(cur_time_tm->tm_year % 100); - - if (nvrram[RTC_REGB] & RTC_2412) - { - nvrram[RTC_HOURS] = BCD(cur_time_tm->tm_hour); - } - else - { - nvrram[RTC_HOURS] = (cur_time_tm->tm_hour % 12) ? BCD(cur_time_tm->tm_hour % 12) : BCD(12); - if (cur_time_tm->tm_hour > 11) - nvrram[RTC_HOURS] |= RTC_AMPM; - } - } -} - -void time_internal_set_nvrram(char *nvrram) -{ - int temp; - - /* Load the entire internal clock state from the NVR. */ - internal_clock.sec = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_SECONDS] : DCB(nvrram[RTC_SECONDS]); - internal_clock.min = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MINUTES] : DCB(nvrram[RTC_MINUTES]); - - temp = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_HOURS] : DCB(nvrram[RTC_HOURS]); - - if (nvrram[RTC_REGB] & RTC_2412) - internal_clock.hour = temp; - else - internal_clock.hour = ((temp & ~RTC_AMPM) % 12) + ((temp & RTC_AMPM) ? 12 : 0); - - internal_clock.mday = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_DOM] : DCB(nvrram[RTC_DOM]); - internal_clock.mon = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MONTH] : DCB(nvrram[RTC_MONTH]); - internal_clock.year = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_YEAR] : DCB(nvrram[RTC_YEAR]); - internal_clock.year += (nvrram[RTC_REGB] & RTC_DM) ? 1900 : (DCB(nvrram[RTC_CENTURY]) * 100); -} - -void time_internal_sync(char *nvrram) -{ - struct tm *cur_time_tm; - time_t cur_time; - - time(&cur_time); - cur_time_tm = localtime(&cur_time); - - time_internal_set(cur_time_tm); - - time_set_nvrram(nvrram, cur_time_tm); -} - -void time_get(char *nvrram) -{ - struct tm cur_time_tm; - - time_internal_get(&cur_time_tm); - - time_set_nvrram(nvrram, &cur_time_tm); -} diff --git a/src/rtc.h b/src/rtc.h deleted file mode 100644 index 151be0c7c..000000000 --- a/src/rtc.h +++ /dev/null @@ -1,174 +0,0 @@ -#define BCD(X) (((X) % 10) | (((X) / 10) << 4)) -#define DCB(X) ((((X) & 0xF0) >> 4) * 10 + ((X) & 0x0F)) - -enum RTC_ADDR -{ - RTC_SECONDS, - RTC_ALARMSECONDS, - RTC_MINUTES, - RTC_ALARMMINUTES, - RTC_HOURS, - RTC_ALARMHOURS, - RTC_DOW, - RTC_DOM, - RTC_MONTH, - RTC_YEAR, - RTC_REGA, - RTC_REGB, - RTC_REGC, - RTC_REGD -}; - -/* The century register at location 32h is a BCD register designed to automatically load the BCD value 20 as the year register changes from 99 to 00. - The MSB of this register is not affected when the load of 20 occurs, and remains at the value written by the user. */ -#define RTC_CENTURY 0x32 - -/* When the 12-hour format is selected, the higher-order bit of the hours byte represents PM when it is logic 1. */ -#define RTC_AMPM 0x80 - -/* Register A bitflags */ -enum RTC_RA_BITS -{ -/* Rate Selector (RS0) - - These four rate-selection bits select one of the 13 taps on the 15-stage divider or disable the divider output. - The tap selected can be used to generate an output square wave (SQW pin) and/or a periodic interrupt. - The user can do one of the following: - - Enable the interrupt with the PIE bit; - - Enable the SQW output pin with the SQWE bit; - - Enable both at the same time and the same rate; or - - Enable neither. - - Table 3 lists the periodic interrupt rates and the square wave frequencies that can be chosen with the RS bits. - These four read/write bits are not affected by !RESET. */ - RTC_RS = 0xF, -/* DV0 - - These three bits are used to turn the oscillator on or off and to reset the countdown chain. - A pattern of 010 is the only combination of bits that turn the oscillator on and allow the RTC to keep time. - A pattern of 11x enables the oscillator but holds the countdown chain in reset. - The next update occurs at 500ms after a pattern of 010 is written to DV0, DV1, and DV2. */ - RTC_DV0 = 0x70, -/* Update-In-Progress (UIP) - - This bit is a status flag that can be monitored. When the UIP bit is a 1, the update transfer occurs soon. - When UIP is a 0, the update transfer does not occur for at least 244us. - The time, calendar, and alarm information in RAM is fully available for access when the UIP bit is 0. - The UIP bit is read-only and is not affected by !RESET. - Writing the SET bit in Register B to a 1 inhibits any update transfer and clears the UIP status bit. */ - RTC_UIP = 0x80 -}; - -/* Register B bitflags */ -enum RTC_RB_BITS -{ -/* Daylight Saving Enable (DSE) - - This bit is a read/write bit that enables two daylight saving adjustments when DSE is set to 1. - On the first Sunday in April (or the last Sunday in April in the MC146818A), the time increments from 1:59:59 AM to 3:00:00 AM. - On the last Sunday in October when the time first reaches 1:59:59 AM, it changes to 1:00:00 AM. - When DSE is enabled, the internal logic test for the first/last Sunday condition at midnight. - If the DSE bit is not set when the test occurs, the daylight saving function does not operate correctly. - These adjustments do not occur when the DSE bit is 0. This bit is not affected by internal functions or !RESET. */ - RTC_DSE = 0x1, -/* 24/12 - - The 24/12 control bit establishes the format of the hours byte. A 1 indicates the 24-hour mode and a 0 indicates the 12-hour mode. - This bit is read/write and is not affected by internal functions or !RESET. */ - RTC_2412 = 0x2, -/* Data Mode (DM) - - This bit indicates whether time and calendar information is in binary or BCD format. - The DM bit is set by the program to the appropriate format and can be read as required. - This bit is not modified by internal functions or !RESET. A 1 in DM signifies binary data, while a 0 in DM specifies BCD data. */ - RTC_DM = 0x4, -/* Square-Wave Enable (SQWE) - - When this bit is set to 1, a square-wave signal at the frequency set by the rate-selection bits RS3-RS0 is driven out on the SQW pin. - When the SQWE bit is set to 0, the SQW pin is held low. SQWE is a read/write bit and is cleared by !RESET. - SQWE is low if disabled, and is high impedance when VCC is below VPF. SQWE is cleared to 0 on !RESET. */ - RTC_SQWE = 0x8, -/* Update-Ended Interrupt Enable (UIE) - - This bit is a read/write bit that enables the update-end flag (UF) bit in Register C to assert !IRQ. - The !RESET pin going low or the SET bit going high clears the UIE bit. - The internal functions of the device do not affect the UIE bit, but is cleared to 0 on !RESET. */ - RTC_UIE = 0x10, -/* Alarm Interrupt Enable (AIE) - - This bit is a read/write bit that, when set to 1, permits the alarm flag (AF) bit in Register C to assert !IRQ. - An alarm interrupt occurs for each second that the three time bytes equal the three alarm bytes, including a don't-care alarm code of binary 11XXXXXX. - The AF bit does not initiate the !IRQ signal when the AIE bit is set to 0. - The internal functions of the device do not affect the AIE bit, but is cleared to 0 on !RESET. */ - RTC_AIE = 0x20, -/* Periodic Interrupt Enable (PIE) - - The PIE bit is a read/write bit that allows the periodic interrupt flag (PF) bit in Register C to drive the !IRQ pin low. - When the PIE bit is set to 1, periodic interrupts are generated by driving the !IRQ pin low at a rate specified by the RS3-RS0 bits of Register A. - A 0 in the PIE bit blocks the !IRQ output from being driven by a periodic interrupt, but the PF bit is still set at the periodic rate. - PIE is not modified by any internal device functions, but is cleared to 0 on !RESET. */ - RTC_PIE = 0x40, -/* SET - - When the SET bit is 0, the update transfer functions normally by advancing the counts once per second. - When the SET bit is written to 1, any update transfer is inhibited, and the program can initialize the time and calendar bytes without an update - occurring in the midst of initializing. Read cycles can be executed in a similar manner. SET is a read/write bit and is not affected by !RESET or - internal functions of the device. */ - RTC_SET = 0x80 -}; - -/* Register C bitflags */ -enum RTC_RC_BITS -{ -/* Unused - - These bits are unused in Register C. These bits always read 0 and cannot be written. */ - RTC_RC = 0xF, -/* Update-Ended Interrupt Flag (UF) - - This bit is set after each update cycle. When the UIE bit is set to 1, the 1 in UF causes the IRQF bit to be a 1, which asserts the !IRQ pin. - This bit can be cleared by reading Register C or with a !RESET. */ - RTC_UF = 0x10, -/* Alarm Interrupt Flag (AF) - - A 1 in the AF bit indicates that the current time has matched the alarm time. - If the AIE bit is also 1, the !IRQ pin goes low and a 1 appears in the IRQF bit. This bit can be cleared by reading Register C or with a !RESET. */ - RTC_AF = 0x20, -/* Periodic Interrupt Flag (PF) - - This bit is read-only and is set to 1 when an edge is detected on the selected tap of the divider chain. - The RS3 through RS0 bits establish the periodic rate. PF is set to 1 independent of the state of the PIE bit. - When both PF and PIE are 1s, the !IRQ signal is active and sets the IRQF bit. This bit can be cleared by reading Register C or with a !RESET. */ - RTC_PF = 0x40, -/* Interrupt Request Flag (IRQF) - - The interrupt request flag (IRQF) is set to a 1 when one or more of the following are true: - - PF == PIE == 1 - - AF == AIE == 1 - - UF == UIE == 1 - - Any time the IRQF bit is a 1, the !IRQ pin is driven low. - All flag bits are cleared after Register C is read by the program or when the !RESET pin is low. */ - RTC_IRQF = 0x80 -}; - -/* Register D bitflags */ -enum RTC_RD_BITS -{ -/* Unused - - The remaining bits of Register D are not usable. They cannot be written and they always read 0. */ - RTC_RD = 0x7F, -/* Valid RAM and Time (VRT) - - This bit indicates the condition of the battery connected to the VBAT pin. This bit is not writeable and should always be 1 when read. - If a 0 is ever present, an exhausted internal lithium energy source is indicated and both the contents of the RTC data and RAM data are questionable. - This bit is unaffected by !RESET. */ - RTC_VRT = 0x80 -}; - -extern void rtc_tick(void); -extern void time_update(char *nvrram, int reg); -extern void time_get(char *nvrram); -extern void time_internal_set_nvrram(char *nvrram); -extern void time_internal_sync(char *nvrram); diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index 48561691e..1701f88a3 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -8,28 +8,38 @@ * * Handling of the SCSI controllers. * - * Version: @(#)scsi.c 1.0.4 2017/09/03 + * Version: @(#)scsi.c 1.0.10 2017/10/14 * * Authors: TheCollector1995, * Miran Grca, * Fred N. van Kempen, + * * Copyright 2016,2017 Miran Grca. * Copyright 2017 Fred N. van Kempen. */ -#include +#include +#include #include +#include +#include #include "../86box.h" #include "../ibm.h" +#include "../mem.h" +#include "../rom.h" #include "../timer.h" #include "../device.h" #include "../cdrom/cdrom.h" +#include "../disk/hdc.h" +#include "../plat.h" #include "scsi.h" #include "scsi_aha154x.h" #include "scsi_buslogic.h" +#include "scsi_ncr5380.h" +#include "scsi_x54x.h" scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; -uint8_t SCSIPhase = SCSI_PHASE_BUS_FREE; +uint8_t SCSIPhase = 0xff; uint8_t SCSIStatus = SCSI_STATUS_OK; uint8_t scsi_cdrom_id = 3; /*common setting*/ char scsi_fn[SCSI_NUM][512]; @@ -38,6 +48,9 @@ uint16_t scsi_hd_location[SCSI_NUM]; int scsi_card_current = 0; int scsi_card_last = 0; +uint32_t SCSI_BufferLength; +mutex_t *scsiMutex; + typedef struct { char name[64]; @@ -49,11 +62,16 @@ typedef struct { static SCSI_CARD scsi_cards[] = { { "None", "none", NULL, NULL }, - { "Adaptec AHA-1540B", "aha1540b", &aha1540b_device, aha_device_reset }, - { "Adaptec AHA-1542CF", "aha1542cf", &aha1542cf_device, aha_device_reset }, - { "Adaptec AHA-1640", "aha1640", &aha1640_device, aha_device_reset }, - { "BusLogic BT-545C", "bt545c", &buslogic_device, BuslogicDeviceReset }, - { "BusLogic BT-958D PCI", "bt958d", &buslogic_pci_device, BuslogicDeviceReset }, + { "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, x54x_device_reset }, + { "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, x54x_device_reset }, + { "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, x54x_device_reset }, + { "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, BuslogicDeviceReset }, + { "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,BuslogicDeviceReset }, + { "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,NULL }, + { "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, NULL }, + { "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, NULL }, + { "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, x54x_device_reset }, + { "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, BuslogicDeviceReset }, { "", "", NULL, NULL }, }; @@ -107,6 +125,18 @@ int scsi_card_get_from_internal_name(char *s) } +void scsi_mutex_init(void) +{ + scsiMutex = thread_create_mutex(L"86Box.SCSIMutex"); +} + + +void scsi_mutex_close(void) +{ + thread_close_mutex(scsiMutex); +} + + void scsi_card_init(void) { int i, j; @@ -125,6 +155,7 @@ void scsi_card_init(void) } else { SCSIDevices[i][j].LunType = SCSI_NONE; } + SCSIDevices[i][j].CmdBuffer = NULL; } } @@ -173,3 +204,17 @@ void SCSIReset(uint8_t id, uint8_t lun) SCSIDevices[id][lun].CmdBuffer = NULL; } } + + +void +startscsi(void) +{ + thread_wait_mutex(scsiMutex); +} + + +void +endscsi(void) +{ + thread_release_mutex(scsiMutex); +} diff --git a/src/scsi/scsi.h b/src/scsi/scsi.h index 3c975677f..5535846b0 100644 --- a/src/scsi/scsi.h +++ b/src/scsi/scsi.h @@ -8,7 +8,7 @@ * * SCSI controller handler header. * - * Version: @(#)scsi_h 1.0.5 2017/08/27 + * Version: @(#)scsi_h 1.0.7 2017/10/07 * * Authors: TheCollector1995, * Miran Grca, @@ -211,15 +211,6 @@ extern uint8_t page_current; #define PAGE_CHANGEABLE 1 #define PAGE_CHANGED 2 - -extern uint32_t DataLength; -extern uint32_t DataPointer; - -extern int SectorLBA; -extern int SectorLen; - -extern int MediaPresent; - extern uint8_t SCSIStatus; extern uint8_t SCSIPhase; extern uint8_t scsi_cdrom_id; @@ -242,21 +233,36 @@ extern int prev_status; #define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) -#define SCSI_PHASE_DATAOUT ( 0 ) -#define SCSI_PHASE_DATAIN ( 1 ) -#define SCSI_PHASE_COMMAND ( 2 ) -#define SCSI_PHASE_STATUS ( 3 ) -#define SCSI_PHASE_MESSAGE_OUT ( 6 ) -#define SCSI_PHASE_MESSAGE_IN ( 7 ) -#define SCSI_PHASE_BUS_FREE ( 8 ) -#define SCSI_PHASE_SELECT ( 9 ) +#define MSG_COMMAND_COMPLETE 0x00 +#define BUS_DBP 0x01 +#define BUS_SEL 0x02 +#define BUS_IO 0x04 +#define BUS_CD 0x08 +#define BUS_MSG 0x10 +#define BUS_REQ 0x20 +#define BUS_BSY 0x40 +#define BUS_RST 0x80 +#define BUS_ACK 0x200 +#define BUS_ATN 0x200 +#define BUS_ARB 0x8000 +#define BUS_SETDATA(val) ((uint32_t)val << 16) +#define BUS_GETDATA(val) ((val >> 16) & 0xff) +#define BUS_DATAMASK 0xff0000 + +#define BUS_IDLE (1 << 31) + +#define SCSI_PHASE_DATA_OUT 0 +#define SCSI_PHASE_DATA_IN BUS_IO +#define SCSI_PHASE_COMMAND BUS_CD +#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO) +#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD) +#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO) typedef struct { uint8_t *CmdBuffer; - uint32_t CmdBufferLength; int LunType; - uint32_t InitLength; + int32_t BufferLength; } scsi_device_t; @@ -281,11 +287,15 @@ extern int scsi_card_current; extern int scsi_card_available(int card); extern char *scsi_card_getname(int card); -extern struct device_t *scsi_card_getdevice(int card); +#ifdef EMU_DEVICE_H +extern device_t *scsi_card_getdevice(int card); +#endif extern int scsi_card_has_config(int card); extern char *scsi_card_get_internal_name(int card); extern int scsi_card_get_from_internal_name(char *s); -extern void scsi_card_init(); +extern void scsi_mutex_init(void); +extern void scsi_mutex_close(void); +extern void scsi_card_init(void); extern void scsi_card_reset(void); extern uint8_t scsi_hard_disks[16][8]; @@ -335,4 +345,13 @@ typedef struct { #pragma pack(pop) +#define MODE_SELECT_PHASE_IDLE 0 +#define MODE_SELECT_PHASE_HEADER 1 +#define MODE_SELECT_PHASE_BLOCK_DESC 2 +#define MODE_SELECT_PHASE_PAGE_HEADER 3 +#define MODE_SELECT_PHASE_PAGE 4 + #endif /*EMU_SCSI_H*/ + +extern void startscsi(void); +extern void endscsi(void); diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 782ed3450..dd0020c9e 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -10,136 +10,34 @@ * made by Adaptec, Inc. These controllers were designed for * the ISA bus. * - * NOTE: THIS IS CURRENTLY A MESS, but will be cleaned up as I go. - * - * Version: @(#)scsi_aha154x.c 1.0.16 2017/09/05 + * Version: @(#)scsi_aha154x.c 1.0.29 2017/10/14 * * Authors: Fred N. van Kempen, * Original Buslogic version by SA1988 and Miran Grca. + * * Copyright 2017 Fred N. van Kempen. */ -#include -#include #include +#include #include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mca.h" #include "../mem.h" #include "../mca.h" #include "../rom.h" +#include "../nvr.h" #include "../dma.h" #include "../pic.h" #include "../timer.h" #include "../device.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "scsi.h" -#include "scsi_bios_command.h" -#include "scsi_device.h" #include "scsi_aha154x.h" - - -#define SCSI_DELAY_TM 1 /* was 50 */ -#define AHA_RESET_DURATION_US UINT64_C(5000) - - -#define ROM_SIZE 16384 /* one ROM is 16K */ -#define NVR_SIZE 32 /* size of NVR */ - - -/* EEPROM map and bit definitions. */ -#define EE0_HOSTID 0x07 /* EE(0) [2:0] */ -#define EE0_ALTFLOP 0x80 /* EE(0) [7] FDC at 370h */ -#define EE1_IRQCH 0x07 /* EE(1) [3:0] */ -#define EE1_DMACH 0x70 /* EE(1) [7:4] */ -#define EE2_RMVOK 0x01 /* EE(2) [0] Support removable disks */ -#define EE2_HABIOS 0x02 /* EE(2) [1] HA Bios Space Reserved */ -#define EE2_INT19 0x04 /* EE(2) [2] HA Bios Controls INT19 */ -#define EE2_DYNSCAN 0x08 /* EE(2) [3] Dynamically scan bus */ -#define EE2_TWODRV 0x10 /* EE(2) [4] Allow more than 2 drives */ -#define EE2_SEEKRET 0x20 /* EE(2) [5] Immediate return on seek */ -#define EE2_EXT1G 0x80 /* EE(2) [7] Extended Translation >1GB */ -#define EE3_SPEED 0x00 /* EE(3) [7:0] DMA Speed */ -#define SPEED_33 0xFF -#define SPEED_50 0x00 -#define SPEED_56 0x04 -#define SPEED_67 0x01 -#define SPEED_80 0x02 -#define SPEED_10 0x03 -#define EE4_FLOPTOK 0x80 /* EE(4) [7] Support Flopticals */ -#define EE6_PARITY 0x01 /* EE(6) [0] parity check enable */ -#define EE6_TERM 0x02 /* EE(6) [1] host term enable */ -#define EE6_RSTBUS 0x04 /* EE(6) [2] reset SCSI bus on boot */ -#define EEE_SYNC 0x01 /* EE(E) [0] Enable Sync Negotiation */ -#define EEE_DISCON 0x02 /* EE(E) [1] Enable Disconnection */ -#define EEE_FAST 0x04 /* EE(E) [2] Enable FAST SCSI */ -#define EEE_START 0x08 /* EE(E) [3] Enable Start Unit */ - - -/* - * Host Adapter I/O ports. - * - * READ Port x+0: STATUS - * WRITE Port x+0: CONTROL - * - * READ Port x+1: DATA - * WRITE Port x+1: COMMAND - * - * READ Port x+2: INTERRUPT STATUS - * WRITE Port x+2: (undefined?) - * - * R/W Port x+3: (undefined) - */ - -/* WRITE CONTROL commands. */ -#define CTRL_HRST 0x80 /* Hard reset */ -#define CTRL_SRST 0x40 /* Soft reset */ -#define CTRL_IRST 0x20 /* interrupt reset */ -#define CTRL_SCRST 0x10 /* SCSI bus reset */ - -/* READ STATUS. */ -#define STAT_STST 0x80 /* self-test in progress */ -#define STAT_DFAIL 0x40 /* internal diagnostic failure */ -#define STAT_INIT 0x20 /* mailbox initialization required */ -#define STAT_IDLE 0x10 /* HBA is idle */ -#define STAT_CDFULL 0x08 /* Command/Data output port is full */ -#define STAT_DFULL 0x04 /* Data input port is full */ -#define STAT_INVCMD 0x01 /* Invalid command */ - -/* READ/WRITE DATA. */ -#define CMD_NOP 0x00 /* No operation */ -#define CMD_MBINIT 0x01 /* mailbox initialization */ -#define CMD_START_SCSI 0x02 /* Start SCSI command */ -#define CMD_BIOSCMD 0x03 /* Execute ROM BIOS command */ -#define CMD_INQUIRY 0x04 /* Adapter inquiry */ -#define CMD_EMBOI 0x05 /* enable Mailbox Out Interrupt */ -#define CMD_SELTIMEOUT 0x06 /* Set SEL timeout */ -#define CMD_BUSON_TIME 0x07 /* set bus-On time */ -#define CMD_BUSOFF_TIME 0x08 /* set bus-off time */ -#define CMD_DMASPEED 0x09 /* set ISA DMA speed */ -#define CMD_RETDEVS 0x0A /* return installed devices */ -#define CMD_RETCONF 0x0B /* return configuration data */ -#define CMD_TARGET 0x0C /* set HBA to target mode */ -#define CMD_RETSETUP 0x0D /* return setup data */ -#define CMD_ECHO 0x1F /* ECHO command data */ -#define CMD_OPTIONS 0x21 /* set adapter options */ -#define CMD_WRITE_EEPROM 0x22 /* UNDOC: Write EEPROM */ -#define CMD_READ_EEPROM 0x23 /* UNDOC: Read EEPROM */ -#define CMD_SHADOW_RAM 0x24 /* UNDOC: BIOS shadow ram */ -#define CMD_BIOS_MBINIT 0x25 /* UNDOC: BIOS mailbox initialization */ -#define CMD_MEMORY_MAP_1 0x26 /* UNDOC: Memory Mapper */ -#define CMD_MEMORY_MAP_2 0x27 /* UNDOC: Memory Mapper */ -#define CMD_EXTBIOS 0x28 /* UNDOC: return extended BIOS info */ -#define CMD_MBENABLE 0x29 /* set mailbox interface enable */ -#define CMD_BIOS_SCSI 0x82 /* start ROM BIOS SCSI command */ - -/* READ INTERRUPT STATUS. */ -#define INTR_ANY 0x80 /* any interrupt */ -#define INTR_SRCD 0x08 /* SCSI reset detected */ -#define INTR_HACC 0x04 /* HA command complete */ -#define INTR_MBOA 0x02 /* MBO empty */ -#define INTR_MBIF 0x01 /* MBI full */ +#include "scsi_x54x.h" enum { @@ -151,292 +49,37 @@ enum { }; -/* Structure for the INQUIRE_SETUP_INFORMATION reply. */ -#pragma pack(push,1) -typedef struct { - uint8_t uOffset :4, - uTransferPeriod :3, - fSynchronous :1; -} ReplyInquireSetupInformationSynchronousValue; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t fSynchronousInitiationEnabled :1, - fParityCheckingEnabled :1, - uReserved1 :6; - uint8_t uBusTransferRate; - uint8_t uPreemptTimeOnBus; - uint8_t uTimeOffBus; - uint8_t cMailbox; - addr24 MailboxAddress; - ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8]; - uint8_t uDisconnectPermittedId0To7; - uint8_t uSignature; - uint8_t uCharacterD; - uint8_t uHostBusType; - uint8_t uWideTransferPermittedId0To7; - uint8_t uWideTransfersActiveId0To7; - ReplyInquireSetupInformationSynchronousValue SynchronousValuesId8To15[8]; - uint8_t uDisconnectPermittedId8To15; - uint8_t uReserved2; - uint8_t uWideTransferPermittedId8To15; - uint8_t uWideTransfersActiveId8To15; -} ReplyInquireSetupInformation; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Count; - addr24 Address; -} MailboxInit_t; -#pragma pack(pop) - -/* - * Mailbox Definitions. - * - * Mailbox Out (MBO) command values. - */ -#define MBO_FREE 0x00 -#define MBO_START 0x01 -#define MBO_ABORT 0x02 - -/* Mailbox In (MBI) status values. */ -#define MBI_FREE 0x00 -#define MBI_SUCCESS 0x01 -#define MBI_ABORT 0x02 -#define MBI_NOT_FOUND 0x03 -#define MBI_ERROR 0x04 - -#pragma pack(push,1) -typedef struct { - uint8_t CmdStatus; - addr24 CCBPointer; -} Mailbox_t; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint32_t CCBPointer; - union { - struct { - uint8_t Reserved[3]; - uint8_t ActionCode; - } out; - struct { - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Reserved; - uint8_t CompletionCode; - } in; - } u; -} Mailbox32_t; -#pragma pack(pop) - -/* - * - * CCB - SCSI Command Control Block - * - * The CCB is a superset of the CDB (Command Descriptor Block) - * and specifies detailed information about a SCSI command. - * - */ -/* Byte 0 Command Control Block Operation Code */ -#define SCSI_INITIATOR_COMMAND 0x00 -#define TARGET_MODE_COMMAND 0x01 -#define SCATTER_GATHER_COMMAND 0x02 -#define SCSI_INITIATOR_COMMAND_RES 0x03 -#define SCATTER_GATHER_COMMAND_RES 0x04 -#define BUS_RESET 0x81 - -/* Byte 1 Address and Direction Control */ -#define CCB_TARGET_ID_SHIFT 0x06 /* CCB Op Code = 00, 02 */ -#define CCB_INITIATOR_ID_SHIFT 0x06 /* CCB Op Code = 01 */ -#define CCB_DATA_XFER_IN 0x01 -#define CCB_DATA_XFER_OUT 0x02 -#define CCB_LUN_MASK 0x07 /* Logical Unit Number */ - -/* Byte 2 SCSI_Command_Length - Length of SCSI CDB - Byte 3 Request Sense Allocation Length */ -#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ -#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ - -/* Bytes 4, 5 and 6 Data Length - Data transfer byte count */ -/* Bytes 7, 8 and 9 Data Pointer - SGD List or Data Buffer */ -/* Bytes 10, 11 and 12 Link Pointer - Next CCB in Linked List */ -/* Byte 13 Command Link ID - TBD (I don't know yet) */ -/* Byte 14 Host Status - Host Adapter status */ -#define CCB_COMPLETE 0x00 /* CCB completed without error */ -#define CCB_LINKED_COMPLETE 0x0A /* Linked command completed */ -#define CCB_LINKED_COMPLETE_INT 0x0B /* Linked complete with intr */ -#define CCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ -#define CCB_DATA_OVER_UNDER_RUN 0x12 -#define CCB_UNEXPECTED_BUS_FREE 0x13 /* Trg dropped SCSI BSY */ -#define CCB_PHASE_SEQUENCE_FAIL 0x14 /* Trg bus phase sequence fail */ -#define CCB_BAD_MBO_COMMAND 0x15 /* MBO command not 0, 1 or 2 */ -#define CCB_INVALID_OP_CODE 0x16 /* CCB invalid operation code */ -#define CCB_BAD_LINKED_LUN 0x17 /* Linked CCB LUN diff from 1st */ -#define CCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ -#define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */ -#define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */ - -/* Byte 15 Target Status - - See scsi.h files for these statuses. - Bytes 16 and 17 Reserved (must be 0) - Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block */ - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Reserved1 :3, - ControlByte :2, - TagQueued :1, - QueueTag :2; - uint8_t CdbLength; - uint8_t RequestSenseLength; - uint32_t DataLength; - uint32_t DataPointer; - uint8_t Reserved2[2]; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Id; - uint8_t Lun :5, - LegacyTagEnable :1, - LegacyQueueTag :2; - uint8_t Cdb[12]; - uint8_t Reserved3[6]; - uint32_t SensePointer; -} CCB32; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Lun :3, - ControlByte :2, - Id :3; - uint8_t CdbLength; - uint8_t RequestSenseLength; - addr24 DataLength; - addr24 DataPointer; - addr24 LinkPointer; - uint8_t LinkId; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Reserved[2]; - uint8_t Cdb[12]; -} CCB; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Pad1 :3, - ControlByte :2, - Pad2 :3; - uint8_t CdbLength; - uint8_t RequestSenseLength; - uint8_t Pad3[10]; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Pad4[2]; - uint8_t Cdb[12]; -} CCBC; -#pragma pack(pop) - -#pragma pack(push,1) -typedef union { - CCB32 new; - CCB old; - CCBC common; -} CCBU; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - CCBU CmdBlock; - uint8_t *RequestSenseBuffer; - uint32_t CCBPointer; - int Is24bit; - uint8_t TargetID; - uint8_t LUN; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t MailboxCompletionCode; -} Req_t; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - int8_t type; /* type of device */ - char name[16]; /* name of device */ - - int8_t Irq; - int8_t DmaChannel; - int8_t HostID; - uint32_t Base; - uint8_t pos_regs[8]; /* MCA */ - - uint8_t bid; /* board ID */ - char fwl, fwh; /* firmware info */ - - wchar_t *bios_path; /* path to BIOS image file */ - uint32_t rom_addr; /* address of BIOS ROM */ - uint16_t rom_ioaddr; /* offset in BIOS of I/O addr */ - uint16_t rom_shram; /* index to shared RAM */ - uint16_t rom_shramsz; /* size of shared RAM */ - uint16_t rom_fwhigh; /* offset in BIOS of ver ID */ - rom_t bios; /* BIOS memory descriptor */ - uint8_t *rom1; /* main BIOS image */ - uint8_t *rom2; /* SCSI-Select image */ - - wchar_t *nvr_path; /* path to NVR image file */ - uint8_t *nvr; /* EEPROM buffer */ - - int ResetCB; - - volatile uint8_t /* for multi-threading, keep */ - Status, /* these volatile */ - Interrupt; - - int ExtendedLUNCCBFormat; - Req_t Req; - uint8_t Geometry; - uint8_t Control; - uint8_t Command; - uint8_t CmdBuf[53]; - uint8_t CmdParam; - uint8_t CmdParamLeft; - uint8_t DataBuf[64]; - uint16_t DataReply; - uint16_t DataReplyLeft; - uint32_t MailboxCount; - uint32_t MailboxOutAddr; - uint32_t MailboxOutPosCur; - uint32_t MailboxInAddr; - uint32_t MailboxInPosCur; - int Mbx24bit; - int MailboxOutInterrupts; - int MbiActive[256]; - int PendingInterrupt; - int Lock; - event_t *evt; -} aha_t; -#pragma pack(pop) +#define AHA_RESET_DURATION_US UINT64_C(50000) -static uint16_t aha_ports[] = { +#define CMD_WRITE_EEPROM 0x22 /* UNDOC: Write EEPROM */ +#define CMD_READ_EEPROM 0x23 /* UNDOC: Read EEPROM */ +#define CMD_SHADOW_RAM 0x24 /* UNDOC: BIOS shadow ram */ +#define CMD_BIOS_MBINIT 0x25 /* UNDOC: BIOS mailbox initialization */ +#define CMD_MEMORY_MAP_1 0x26 /* UNDOC: Memory Mapper */ +#define CMD_MEMORY_MAP_2 0x27 /* UNDOC: Memory Mapper */ +#define CMD_EXTBIOS 0x28 /* UNDOC: return extended BIOS info */ +#define CMD_MBENABLE 0x29 /* set mailbox interface enable */ +#define CMD_BIOS_SCSI 0x82 /* start ROM BIOS SCSI command */ + + +uint16_t aha_ports[] = { 0x0330, 0x0334, 0x0230, 0x0234, 0x0130, 0x0134, 0x0000, 0x0000 }; -static void aha_cmd_thread(void *priv); -static thread_t *poll_tid; +typedef struct { + uint8_t CustomerSignature[20]; + uint8_t uAutoRetry; + uint8_t uBoardSwitches; + uint8_t uChecksum; + uint8_t uUnknown; + addr24 BIOSMailboxAddress; +} aha_setup_t; -#if ENABLE_AHA154X_LOG +#ifdef ENABLE_AHA154X_LOG int aha_do_log = ENABLE_AHA154X_LOG; #endif @@ -470,69 +113,65 @@ aha_log(const char *fmt, ...) static void aha_mem_write(uint32_t addr, uint8_t val, void *priv) { - rom_t *rom = (rom_t *)priv; + x54x_t *dev = (x54x_t *)priv; - if ((addr & rom->mask) >= 0x3F80) - rom->rom[addr & rom->mask] = val; + addr &= 0x3fff; + + if ((addr >= dev->rom_shram) && (dev->shram_mode & 1)) + dev->shadow_ram[addr & (dev->rom_shramsz - 1)] = val; } static uint8_t aha_mem_read(uint32_t addr, void *priv) { - rom_t *rom = (rom_t *)priv; + x54x_t *dev = (x54x_t *)priv; + rom_t *rom = &dev->bios; - return(rom->rom[addr & rom->mask]); -} + addr &= 0x3fff; + if ((addr >= dev->rom_shram) && (dev->shram_mode & 2)) + return dev->shadow_ram[addr & (dev->rom_shramsz - 1)]; -static uint16_t -aha_mem_readw(uint32_t addr, void *priv) -{ - rom_t *rom = (rom_t *)priv; - - return(*(uint16_t *)&rom->rom[addr & rom->mask]); -} - - -static uint32_t -aha_mem_readl(uint32_t addr, void *priv) -{ - rom_t *rom = (rom_t *)priv; - - return(*(uint32_t *)&rom->rom[addr & rom->mask]); + return(rom->rom[addr]); } static uint8_t -aha154x_shram(aha_t *dev, uint8_t cmd) +aha154x_shram(x54x_t *dev, uint8_t cmd) { /* If not supported, give up. */ if (dev->rom_shram == 0x0000) return(0x04); - switch(cmd) { - case 0x00: /* disable, make it look like ROM */ - memset(&dev->bios.rom[dev->rom_shram], 0xFF, dev->rom_shramsz); - break; - - case 0x02: /* clear it */ - memset(&dev->bios.rom[dev->rom_shram], 0x00, dev->rom_shramsz); - break; - - case 0x03: /* enable, clear for use */ - memset(&dev->bios.rom[dev->rom_shram], 0x00, dev->rom_shramsz); - break; - } + /* Bit 0 = Shadow RAM write enable; + Bit 1 = Shadow RAM read enable. */ + dev->shram_mode = cmd; /* Firmware expects 04 status. */ return(0x04); } +static void +aha_eeprom_save(x54x_t *dev) +{ + FILE *f; + + f = nvr_fopen(dev->nvr_path, L"wb"); + if (f) + { + fwrite(dev->nvr, 1, NVR_SIZE, f); + fclose(f); + f = NULL; + } +} + + static uint8_t -aha154x_eeprom(aha_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp) +aha154x_eeprom(x54x_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp) { uint8_t r = 0xff; + int c; aha_log("%s: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n", dev->name, cmd, arg, len, off); @@ -540,17 +179,19 @@ aha154x_eeprom(aha_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8 /* Only if we can handle it.. */ if (dev->nvr == NULL) return(r); - if ((off+len) > NVR_SIZE) return(r); /* no can do.. */ - if (cmd == 0x22) { /* Write data to the EEPROM. */ - memcpy(&dev->nvr[off], bufp, len); + for (c = 0; c < len; c++) + dev->nvr[(off + c) & 0xff] = bufp[c]; r = 0; + + aha_eeprom_save(dev); } if (cmd == 0x23) { /* Read data from the EEPROM. */ - memcpy(bufp, &dev->nvr[off], len); + for (c = 0; c < len; c++) + bufp[c] = dev->nvr[(off + c) & 0xff]; r = len; } @@ -558,9 +199,9 @@ aha154x_eeprom(aha_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8 } -/* Mess with the AHA-154xCF's Shadow RAM. */ +/* Map either the main or utility (Select) ROM into the memory space. */ static uint8_t -aha154x_mmap(aha_t *dev, uint8_t cmd) +aha154x_mmap(x54x_t *dev, uint8_t cmd) { aha_log("%s: MEMORY cmd=%02x\n", dev->name, cmd); @@ -580,1125 +221,279 @@ aha154x_mmap(aha_t *dev, uint8_t cmd) } -static void -RaiseIntr(aha_t *dev, int suppress, uint8_t Interrupt) +static uint8_t +aha_get_host_id(void *p) { - if (Interrupt & (INTR_MBIF | INTR_MBOA)) { - if (! (dev->Interrupt & INTR_HACC)) { - dev->Interrupt |= Interrupt; /* Report now. */ - } else { - dev->PendingInterrupt |= Interrupt; /* Report later. */ - } - } else if (Interrupt & INTR_HACC) { - if (dev->Interrupt == 0 || dev->Interrupt == (INTR_ANY | INTR_HACC)) { - aha_log("%s: RaiseInterrupt(): Interrupt=%02X\n", - dev->name, dev->Interrupt); - } - dev->Interrupt |= Interrupt; - } else { - aha_log("%s: RaiseInterrupt(): Invalid interrupt state!\n", dev->name); - } + x54x_t *dev = (x54x_t *)p; - dev->Interrupt |= INTR_ANY; - - if (! suppress) - picint(1 << dev->Irq); + return dev->nvr[0] & 0x07; } -static void -ClearIntr(aha_t *dev) +static uint8_t +aha_get_irq(void *p) { - dev->Interrupt = 0; - aha_log("%s: lowering IRQ %i (stat 0x%02x)\n", - dev->name, dev->Irq, dev->Interrupt); - picintc(1 << dev->Irq); - if (dev->PendingInterrupt) { - aha_log("%s: Raising Interrupt 0x%02X (Pending)\n", - dev->name, dev->Interrupt); - if (dev->MailboxOutInterrupts || !(dev->Interrupt & INTR_MBOA)) { - RaiseIntr(dev, 0, dev->PendingInterrupt); - } - dev->PendingInterrupt = 0; - } + x54x_t *dev = (x54x_t *)p; + + return (dev->nvr[1] & 0x07) + 9; } -static void -aha_reset(aha_t *dev) +static uint8_t +aha_get_dma(void *p) { - if (dev->evt) { - thread_destroy_event(dev->evt); - dev->evt = NULL; - if (poll_tid) { - thread_kill(poll_tid); - poll_tid = NULL; - } - } + x54x_t *dev = (x54x_t *)p; - dev->ResetCB = 0; - - dev->Status = STAT_IDLE | STAT_INIT; - dev->Geometry = 0x80; - dev->Command = 0xFF; - dev->CmdParam = 0; - dev->CmdParamLeft = 0; - dev->ExtendedLUNCCBFormat = 0; - dev->MailboxOutPosCur = 0; - dev->MailboxInPosCur = 0; - dev->MailboxOutInterrupts = 0; - dev->PendingInterrupt = 0; - dev->Lock = 0; - - ClearIntr(dev); + return (dev->nvr[1] >> 4) & 0x07; } -static void -aha_reset_ctrl(aha_t *dev, uint8_t Reset) +static uint8_t +aha_cmd_is_fast(void *p) { - /* Only if configured.. */ - if (dev->Base == 0x0000) return; + x54x_t *dev = (x54x_t *)p; - /* Say hello! */ - pclog("Adaptec %s (IO=0x%04X, IRQ=%d, DMA=%d, BIOS @%05lX) ID=%d\n", - dev->name, dev->Base, dev->Irq, dev->DmaChannel, - dev->rom_addr, dev->HostID); - - aha_reset(dev); - if (Reset) { - dev->Status |= STAT_STST; - dev->Status &= ~STAT_IDLE; - } - dev->ResetCB = AHA_RESET_DURATION_US * TIMER_USEC; + if (dev->Command == CMD_BIOS_SCSI) + return 1; + else + return 0; } -static void -aha_reset_poll(void *priv) +static uint8_t +aha_fast_cmds(void *p, uint8_t cmd) { - aha_t *dev = (aha_t *)priv; + x54x_t *dev = (x54x_t *)p; - dev->Status &= ~STAT_STST; - dev->Status |= STAT_IDLE; + if (cmd == CMD_BIOS_SCSI) { + x54x_busy_set(); + dev->BIOSMailboxReq++; - dev->ResetCB = 0; + x54x_thread_start(dev); + x54x_busy_clear(); + return 1; + } + + return 0; } -static void -aha_cmd_done(aha_t *dev, int suppress) +static uint8_t +aha_param_len(void *p) { - dev->DataReply = 0; - dev->Status |= STAT_IDLE; + x54x_t *dev = (x54x_t *)p; - if ((dev->Command != CMD_START_SCSI) && (dev->Command != CMD_BIOS_SCSI)) { - dev->Status &= ~STAT_DFULL; - aha_log("%s: Raising IRQ %i\n", dev->name, dev->Irq); - RaiseIntr(dev, suppress, INTR_HACC); - } + switch (dev->Command) { + case CMD_BIOS_MBINIT: + /* Same as 0x01 for AHA. */ + return sizeof(MailboxInit_t); + break; - dev->Command = 0xff; - dev->CmdParam = 0; -} + case CMD_SHADOW_RAM: + return 1; + break; + case CMD_WRITE_EEPROM: + return 3+32; + break; -static void -aha_mbi_setup(aha_t *dev, uint32_t CCBPointer, CCBU *CmdBlock, - uint8_t HostStatus, uint8_t TargetStatus, uint8_t mbcc) -{ - Req_t *req = &dev->Req; + case CMD_READ_EEPROM: + return 3; - req->CCBPointer = CCBPointer; - memcpy(&(req->CmdBlock), CmdBlock, sizeof(CCB32)); - req->Is24bit = dev->Mbx24bit; - req->HostStatus = HostStatus; - req->TargetStatus = TargetStatus; - req->MailboxCompletionCode = mbcc; + case CMD_MBENABLE: + return 2; - aha_log("Mailbox in setup\n"); -} - - -static void -aha_mbi(aha_t *dev) -{ - Req_t *req = &dev->Req; - uint32_t CCBPointer = req->CCBPointer; - CCBU *CmdBlock = &(req->CmdBlock); - uint8_t HostStatus = req->HostStatus; - uint8_t TargetStatus = req->TargetStatus; - uint8_t MailboxCompletionCode = req->MailboxCompletionCode; - Mailbox32_t Mailbox32; - Mailbox_t MailboxIn; - uint32_t Incoming; - - Mailbox32.CCBPointer = CCBPointer; - Mailbox32.u.in.HostStatus = HostStatus; - Mailbox32.u.in.TargetStatus = TargetStatus; - Mailbox32.u.in.CompletionCode = MailboxCompletionCode; - - Incoming = dev->MailboxInAddr + (dev->MailboxInPosCur * (dev->Mbx24bit ? sizeof(Mailbox_t) : sizeof(Mailbox32_t))); - - if (MailboxCompletionCode != MBI_NOT_FOUND) { - CmdBlock->common.HostStatus = HostStatus; - CmdBlock->common.TargetStatus = TargetStatus; - - /* Rewrite the CCB up to the CDB. */ - aha_log("CCB rewritten to the CDB (pointer %08X)\n", CCBPointer); - DMAPageWrite(CCBPointer, (char *)CmdBlock, 18); - } else { - aha_log("Mailbox not found!\n"); - } - - aha_log("Host Status 0x%02X, Target Status 0x%02X\n",HostStatus,TargetStatus); - - if (dev->Mbx24bit) { - MailboxIn.CmdStatus = Mailbox32.u.in.CompletionCode; - U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer); - aha_log("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer)); - - DMAPageWrite(Incoming, (char *)&MailboxIn, sizeof(Mailbox_t)); - aha_log("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); - } else { - aha_log("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer); - - DMAPageWrite(Incoming, (char *)&Mailbox32, sizeof(Mailbox32_t)); - aha_log("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); - } - - dev->MailboxInPosCur++; - if (dev->MailboxInPosCur >= dev->MailboxCount) - dev->MailboxInPosCur = 0; - - RaiseIntr(dev, 0, INTR_MBIF | INTR_ANY); - - while (dev->Interrupt) { - } -} - - -static void -aha_rd_sge(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG) -{ - SGE SGE24[MAX_SG_DESCRIPTORS]; - uint32_t i; - - if (Is24bit) { - DMAPageRead(SGList, (char *)&SGE24, Entries * sizeof(SGE)); - - for (i=0; iCmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); - } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; - } - aha_log("Data Buffer write: length %d, pointer 0x%04X\n", - DataLength, DataPointer); - - if (SCSIDevices[req->TargetID][req->LUN].CmdBuffer != NULL) { - free(SCSIDevices[req->TargetID][req->LUN].CmdBuffer); - SCSIDevices[req->TargetID][req->LUN].CmdBuffer = NULL; - } - - if ((req->CmdBlock.common.ControlByte != 0x03) && DataLength) { - if (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || - req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { - uint32_t SGRead; - uint32_t ScatterEntry; - SGE32 SGBuffer[MAX_SG_DESCRIPTORS]; - uint32_t SGLeft = DataLength / SGEntryLength; - uint32_t SGAddrCurrent = DataPointer; - uint32_t DataToTransfer = 0; - - do { - SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); - SGLeft -= SGRead; - - aha_rd_sge(Is24bit, SGAddrCurrent, SGRead, SGBuffer); - - for (ScatterEntry=0; ScatterEntry 0); - - aha_log("Data to transfer (S/G) %d\n", DataToTransfer); - - SCSIDevices[req->TargetID][req->LUN].InitLength = DataToTransfer; - - aha_log("Allocating buffer for Scatter/Gather (%i bytes)\n", DataToTransfer); - SCSIDevices[req->TargetID][req->LUN].CmdBuffer = (uint8_t *) malloc(DataToTransfer); - memset(SCSIDevices[req->TargetID][req->LUN].CmdBuffer, 0, DataToTransfer); - - /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without - checking its length, so do this procedure for both no read/write commands. */ - if ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || - (req->CmdBlock.common.ControlByte == 0x00)) { - SGLeft = DataLength / SGEntryLength; - SGAddrCurrent = DataPointer; - - do { - SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); - SGLeft -= SGRead; - - aha_rd_sge(Is24bit, SGAddrCurrent, - SGRead, SGBuffer); - - for (ScatterEntry=0; ScatterEntryTargetID][req->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); - sg_buffer_pos += DataToTransfer; - } - - SGAddrCurrent += SGRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); - } while (SGLeft > 0); - } - } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || - req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { - Address = DataPointer; - - SCSIDevices[req->TargetID][req->LUN].InitLength = DataLength; - - aha_log("Allocating buffer for direct transfer (%i bytes)\n", DataLength); - SCSIDevices[req->TargetID][req->LUN].CmdBuffer = (uint8_t *) malloc(DataLength); - memset(SCSIDevices[req->TargetID][req->LUN].CmdBuffer, 0, DataLength); - - if (DataLength > 0) { - DMAPageRead(Address, - (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, - SCSIDevices[req->TargetID][req->LUN].InitLength); - } - } - } -} - - -static void -aha_buf_free(Req_t *req) -{ - SGE32 SGBuffer[MAX_SG_DESCRIPTORS]; - uint32_t DataPointer = 0; - uint32_t DataLength = 0; - uint32_t sg_buffer_pos = 0; - uint32_t SGRead; - uint32_t ScatterEntry; - uint32_t SGEntrySize; - uint32_t SGLeft; - uint32_t SGAddrCurrent; - uint32_t Address; - uint32_t Residual; - uint32_t DataToTransfer; - - if (req->Is24bit) { - DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); - } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; - } - - if ((DataLength != 0) && (req->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY)) { - aha_log("Data length not 0 with TEST UNIT READY: %i (%i)\n", - DataLength, SCSIDevices[req->TargetID][req->LUN].InitLength); - } - - if (req->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) { - DataLength = 0; - } - - aha_log("Data Buffer read: length %d, pointer 0x%04X\n", - DataLength, DataPointer); - - /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without - checking its length, so do this procedure for both read/write commands. */ - if ((DataLength > 0) && - ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || - (req->CmdBlock.common.ControlByte == 0x00))) { - if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || - (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { - SGEntrySize = (req->Is24bit ? sizeof(SGE) : sizeof(SGE32)); - SGLeft = DataLength / SGEntrySize; - SGAddrCurrent = DataPointer; - - do { - SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); - SGLeft -= SGRead; - - aha_rd_sge(req->Is24bit, SGAddrCurrent, - SGRead, SGBuffer); - - for (ScatterEntry=0; ScatterEntryTargetID][req->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); - sg_buffer_pos += DataToTransfer; - } - - SGAddrCurrent += (SGRead * SGEntrySize); - } while (SGLeft > 0); - } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || - req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { - Address = DataPointer; - - aha_log("DMA: Writing %i bytes at %08X\n", - DataLength, Address); - DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, DataLength); - } - } - - if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || - (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { - /* Should be 0 when scatter/gather? */ - if (DataLength >= SCSIDevices[req->TargetID][req->LUN].InitLength) { - Residual = DataLength; - Residual -= SCSIDevices[req->TargetID][req->LUN].InitLength; - } else { - Residual = 0; - } - - if (req->Is24bit) { - U32_TO_ADDR(req->CmdBlock.old.DataLength, Residual); - aha_log("24-bit Residual data length for reading: %d\n", - ADDR_TO_U32(req->CmdBlock.old.DataLength)); - } else { - req->CmdBlock.new.DataLength = Residual; - aha_log("32-bit Residual data length for reading: %d\n", - req->CmdBlock.new.DataLength); - } - } - - if (SCSIDevices[req->TargetID][req->LUN].CmdBuffer != NULL) { - free(SCSIDevices[req->TargetID][req->LUN].CmdBuffer); - SCSIDevices[req->TargetID][req->LUN].CmdBuffer = NULL; + default: + return 0; } } static uint8_t -ConvertSenseLength(uint8_t RequestSenseLength) +aha_cmds(void *p) { - aha_log("Unconverted Request Sense length %i\n", RequestSenseLength); + x54x_t *dev = (x54x_t *)p; + MailboxInit_t *mbi; - if (RequestSenseLength == 0) - RequestSenseLength = 14; - else if (RequestSenseLength == 1) - RequestSenseLength = 0; + if (! dev->CmdParamLeft) { + aha_log("Running Operation Code 0x%02X\n", dev->Command); + switch (dev->Command) { + case CMD_WRITE_EEPROM: /* write EEPROM */ + /* Sent by CF BIOS. */ + dev->DataReplyLeft = + aha154x_eeprom(dev, + dev->Command, + dev->CmdBuf[0], + dev->CmdBuf[1], + dev->CmdBuf[2], + &(dev->CmdBuf[3])); + if (dev->DataReplyLeft == 0xff) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; - aha_log("Request Sense length %i\n", RequestSenseLength); + case CMD_READ_EEPROM: /* read EEPROM */ + /* Sent by CF BIOS. */ + dev->DataReplyLeft = + aha154x_eeprom(dev, + dev->Command, + dev->CmdBuf[0], + dev->CmdBuf[1], + dev->CmdBuf[2], + dev->DataBuf); + if (dev->DataReplyLeft == 0xff) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; - return(RequestSenseLength); -} + case CMD_SHADOW_RAM: /* Shadow RAM */ + /* + * For AHA1542CF, this is the command + * to play with the Shadow RAM. BIOS + * gives us one argument (00,02,03) + * and expects a 0x04 back in the INTR + * register. --FvK + */ + /* dev->Interrupt = aha154x_shram(dev,val); */ + dev->Interrupt = aha154x_shram(dev, dev->CmdBuf[0]); + break; + case CMD_BIOS_MBINIT: /* BIOS Mailbox Initialization */ + /* Sent by CF BIOS. */ + x54x_busy_set(); + dev->Mbx24bit = 1; -static void -SenseBufferFree(Req_t *req, int Copy) -{ - uint8_t SenseLength = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); - uint32_t SenseBufferAddress; - uint8_t temp_sense[256]; + mbi = (MailboxInit_t *)dev->CmdBuf; - if (SenseLength && Copy) { - scsi_device_request_sense(req->TargetID, req->LUN, temp_sense, SenseLength); + dev->BIOSMailboxInit = 1; + dev->BIOSMailboxCount = mbi->Count; + dev->BIOSMailboxOutAddr = ADDR_TO_U32(mbi->Address); - /* - * The sense address, in 32-bit mode, is located in the - * Sense Pointer of the CCB, but in 24-bit mode, it is - * located at the end of the Command Descriptor Block. - */ - if (req->Is24bit) { - SenseBufferAddress = req->CCBPointer; - SenseBufferAddress += req->CmdBlock.common.CdbLength + 18; - } else { - SenseBufferAddress = req->CmdBlock.new.SensePointer; + aha_log("Initialize BIOS Mailbox: MBO=0x%08lx, %d entries at 0x%08lx\n", + dev->BIOSMailboxOutAddr, + mbi->Count, + ADDR_TO_U32(mbi->Address)); + + dev->Status &= ~STAT_INIT; + dev->DataReplyLeft = 0; + x54x_busy_clear(); + break; + + case CMD_MEMORY_MAP_1: /* AHA memory mapper */ + case CMD_MEMORY_MAP_2: /* AHA memory mapper */ + /* Sent by CF BIOS. */ + dev->DataReplyLeft = + aha154x_mmap(dev, dev->Command); + break; + + case CMD_EXTBIOS: /* Return extended BIOS information */ + dev->DataBuf[0] = 0x08; + dev->DataBuf[1] = dev->Lock; + dev->DataReplyLeft = 2; + break; + + case CMD_MBENABLE: /* Mailbox interface enable Command */ + dev->DataReplyLeft = 0; + if (dev->CmdBuf[1] == dev->Lock) { + if (dev->CmdBuf[0] & 1) { + dev->Lock = 1; + } else { + dev->Lock = 0; + } + } + break; + + case 0x2C: /* AHA-1542CP sends this */ + dev->DataBuf[0] = 0x00; + dev->DataReplyLeft = 1; + break; + + case 0x33: /* AHA-1542CP sends this */ + dev->DataBuf[0] = 0x00; + dev->DataBuf[1] = 0x00; + dev->DataBuf[2] = 0x00; + dev->DataBuf[3] = 0x00; + dev->DataReplyLeft = 256; + break; + + default: + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; } - - aha_log("Request Sense address: %02X\n", SenseBufferAddress); - - aha_log("SenseBufferFree(): Writing %i bytes at %08X\n", - SenseLength, SenseBufferAddress); - DMAPageWrite(SenseBufferAddress, (char *)temp_sense, SenseLength); - aha_log("Sense data written to buffer: %02X %02X %02X\n", - temp_sense[2], temp_sense[12], temp_sense[13]); } + + return 0; } static void -aha_scsi_cmd(aha_t *dev) +aha_setup_data(void *p) { - Req_t *req = &dev->Req; - uint8_t id, lun; - uint8_t temp_cdb[12]; - uint32_t i; - int target_cdb_len = 12; + x54x_t *dev = (x54x_t *)p; + ReplyInquireSetupInformation *ReplyISI; + aha_setup_t *aha_setup; - id = req->TargetID; - lun = req->LUN; + ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; + aha_setup = (aha_setup_t *)ReplyISI->VendorSpecificData; - target_cdb_len = scsi_device_cdb_length(id, lun); - - if (!scsi_device_valid(id, lun)) - fatal("SCSI target on %02i:%02i has disappeared\n", id, lun); - - aha_log("SCSI command being executed on ID %i, LUN %i\n", id, lun); - - aha_log("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); - for (i=1; iCmdBlock.common.CdbLength; i++) - aha_log("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); - - memset(temp_cdb, 0x00, target_cdb_len); - if (req->CmdBlock.common.CdbLength <= target_cdb_len) { - memcpy(temp_cdb, req->CmdBlock.common.Cdb, - req->CmdBlock.common.CdbLength); - } else { - memcpy(temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len); - } - - scsi_device_command(id, lun, req->CmdBlock.common.CdbLength, temp_cdb); - - aha_buf_free(req); - - SenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK)); - - aha_log("Request complete\n"); - - if (SCSIStatus == SCSI_STATUS_OK) { - aha_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); - } else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) { - aha_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); - } - - if (temp_cdb[0] == 0x42) { - thread_wait_event(dev->evt, 10); - } + U32_TO_ADDR(aha_setup->BIOSMailboxAddress, dev->BIOSMailboxOutAddr); + aha_setup->uChecksum = 0xA3; + aha_setup->uUnknown = 0xC2; } static void -aha_req_setup(aha_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) -{ - Req_t *req = &dev->Req; - uint8_t id, lun; - uint8_t max_id = SCSI_ID_MAX-1; +aha_reset(void *p) +{ + x54x_t *dev = (x54x_t *)p; - /* Fetch data from the Command Control Block. */ - DMAPageRead(CCBPointer, (char *)&req->CmdBlock, sizeof(CCB32)); + dev->Lock = 0; + dev->shram_mode = 0; + dev->MailboxIsBIOS = 0; + dev->BIOSMailboxCount = 0; + dev->BIOSMailboxOutPosCur = 0; +} - req->Is24bit = dev->Mbx24bit; - req->CCBPointer = CCBPointer; - req->TargetID = dev->Mbx24bit ? req->CmdBlock.old.Id : req->CmdBlock.new.Id; - req->LUN = dev->Mbx24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; - id = req->TargetID; - lun = req->LUN; - if ((id > max_id) || (lun > 7)) { - aha_mbi_setup(dev, CCBPointer, &req->CmdBlock, - CCB_INVALID_CCB, SCSI_STATUS_OK, MBI_ERROR); - aha_log("%s: Callback: Send incoming mailbox\n", dev->name); - aha_mbi(dev); +static void +aha_do_bios_mail(x54x_t *dev) +{ + dev->MailboxIsBIOS = 1; + + if (!dev->BIOSMailboxCount) { + aha_log("aha_do_bios_mail(): No BIOS Mailboxes\n"); return; } - - aha_log("Scanning SCSI Target ID %i\n", id); - - SCSIStatus = SCSI_STATUS_OK; - SCSIDevices[id][lun].InitLength = 0; - - aha_buf_alloc(req, req->Is24bit); - - if (! scsi_device_present(id, lun)) { - aha_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun); - aha_buf_free(req); - SenseBufferFree(req, 0); - aha_mbi_setup(dev, CCBPointer, &req->CmdBlock, - CCB_SELECTION_TIMEOUT,SCSI_STATUS_OK,MBI_ERROR); - aha_log("%s: Callback: Send incoming mailbox\n", dev->name); - aha_mbi(dev); - } else { - aha_log("SCSI Target ID %i and LUN %i detected and working\n", id, lun); - - aha_log("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); - aha_log("CDB Length %i\n", req->CmdBlock.common.CdbLength); - aha_log("CCB Opcode %x\n", req->CmdBlock.common.Opcode); - if (req->CmdBlock.common.ControlByte > 0x03) { - aha_log("Invalid control byte: %02X\n", - req->CmdBlock.common.ControlByte); - } - - aha_log("%s: Callback: Process SCSI request\n", dev->name); - aha_scsi_cmd(dev); - - aha_log("%s: Callback: Send incoming mailbox\n", dev->name); - aha_mbi(dev); - } -} - - -static void -aha_req_abort(aha_t *dev, uint32_t CCBPointer) -{ - CCBU CmdBlock; - - /* Fetch data from the Command Control Block. */ - DMAPageRead(CCBPointer, (char *)&CmdBlock, sizeof(CCB32)); - - aha_mbi_setup(dev, CCBPointer, &CmdBlock, - 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); - aha_log("%s: Callback: Send incoming mailbox\n", dev->name); - aha_mbi(dev); -} - - -static uint32_t -aha_mbo(aha_t *dev, Mailbox32_t *Mailbox32) -{ - Mailbox_t MailboxOut; - uint32_t Outgoing; - - if (dev->Mbx24bit) { - Outgoing = dev->MailboxOutAddr + (dev->MailboxOutPosCur * sizeof(Mailbox_t)); - DMAPageRead(Outgoing, (char *)&MailboxOut, sizeof(Mailbox_t)); - - Mailbox32->CCBPointer = ADDR_TO_U32(MailboxOut.CCBPointer); - Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus; - } else { - Outgoing = dev->MailboxOutAddr + (dev->MailboxOutPosCur * sizeof(Mailbox32_t)); - - DMAPageRead(Outgoing, (char *)Mailbox32, sizeof(Mailbox32_t)); - } - - return(Outgoing); -} - - -static void -aha_mbo_adv(aha_t *dev) -{ - dev->MailboxOutPosCur = (dev->MailboxOutPosCur + 1) % dev->MailboxCount; -} - - -static void -aha_do_mail(aha_t *dev) -{ - Mailbox32_t mb32; - uint32_t Outgoing; - uint8_t CmdStatus = MBO_FREE; - uint32_t CodeOffset = 0; - - CodeOffset = dev->Mbx24bit ? 0 : 7; - - uint8_t MailboxCur = dev->MailboxOutPosCur; /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ - do { - /* Fetch mailbox from guest memory. */ - Outgoing = aha_mbo(dev, &mb32); - - /* Check the next mailbox. */ - aha_mbo_adv(dev); - } while ((mb32.u.out.ActionCode == MBO_FREE) && (MailboxCur != dev->MailboxOutPosCur)); - - if (mb32.u.out.ActionCode != MBO_FREE) { - /* We got the mailbox, mark it as free in the guest. */ - aha_log("aha_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset); - DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, sizeof(CmdStatus)); - } - else { - return; - } - - if (dev->MailboxOutInterrupts) { - RaiseIntr(dev, 0, INTR_MBOA | INTR_ANY); - - while (dev->Interrupt) { - } - } - - if (mb32.u.out.ActionCode == MBO_START) { - aha_log("Start Mailbox Command\n"); - aha_req_setup(dev, mb32.CCBPointer, &mb32); - } else if (mb32.u.out.ActionCode == MBO_ABORT) { - aha_log("Abort Mailbox Command\n"); - aha_req_abort(dev, mb32.CCBPointer); - } else { - aha_log("Invalid action code: %02X\n", mb32.u.out.ActionCode); + for (dev->BIOSMailboxOutPosCur = 0; dev->BIOSMailboxOutPosCur < dev->BIOSMailboxCount; dev->BIOSMailboxOutPosCur++) { + if (x54x_mbo_process(dev)) + break; } } static void -aha_cmd_thread(void *priv) +aha_thread(void *p) { - aha_t *dev = (aha_t *)priv; + x54x_t *dev = (x54x_t *)p; - /* Create a waitable event. */ - dev->evt = thread_create_event(); - - while (dev->MailboxCount) + if (dev->BIOSMailboxInit && dev->BIOSMailboxReq) { - aha_do_mail(dev); + x54x_wait_for_poll(); + + aha_do_bios_mail(dev); } - - if (!dev->MailboxCount) - { - thread_destroy_event(dev->evt); - dev->evt = NULL; - poll_tid = NULL; - return; - } - - thread_destroy_event(dev->evt); - dev->evt = poll_tid = NULL; - - aha_log("%s: Callback: polling stopped.\n", dev->name); -} - - -static uint8_t -aha_read(uint16_t port, void *priv) -{ - aha_t *dev = (aha_t *)priv; - uint8_t ret; - - switch (port & 3) { - case 0: - default: - ret = dev->Status; - break; - - case 1: - ret = dev->DataBuf[dev->DataReply]; - if (dev->DataReplyLeft) { - dev->DataReply++; - dev->DataReplyLeft--; - if (! dev->DataReplyLeft) - aha_cmd_done(dev, 0); - } - break; - - case 2: - ret = dev->Interrupt; - break; - - case 3: - ret = dev->Geometry; - break; - } - -#if 0 -#ifndef WALTJE - aha_log("%s: Read Port 0x%02X, Returned Value %02X\n", - dev->name, port, ret); -#endif -#endif - - return(ret); -} - - -static uint16_t -aha_readw(uint16_t port, void *priv) -{ - return(aha_read(port, priv)); -} - - -static void -aha_write(uint16_t port, uint8_t val, void *priv) -{ - ReplyInquireSetupInformation *ReplyISI; - aha_t *dev = (aha_t *)priv; - MailboxInit_t *mbi; - int i = 0; - uint8_t j = 0; - BIOSCMD *cmd; - uint16_t cyl = 0; - int suppress = 0; - - aha_log("%s: Write Port 0x%02X, Value %02X\n", dev->name, port, val); - - switch (port & 3) { - case 0: - if ((val & CTRL_HRST) || (val & CTRL_SRST)) { - uint8_t Reset = (val & CTRL_HRST); - aha_log("Reset completed = %x\n", Reset); - aha_reset_ctrl(dev, Reset); - break; - } - - if (val & CTRL_IRST) { - ClearIntr(dev); - } - break; - - case 1: - /* Fast path for the mailbox execution command. */ - if (((val == CMD_START_SCSI) || (val == CMD_BIOS_SCSI)) && - (dev->Command == 0xff)) { - /* If there are no mailboxes configured, don't even try to do anything. */ - if (dev->MailboxCount) { - if (! poll_tid) { - aha_log("%s: starting thread..\n", dev->name); - poll_tid = thread_create(aha_cmd_thread, dev); - } - } - return; - } - - if (dev->Command == 0xff) { - dev->Command = val; - dev->CmdParam = 0; - dev->CmdParamLeft = 0; - - dev->Status &= ~(STAT_INVCMD | STAT_IDLE); - aha_log("%s: Operation Code 0x%02X\n", dev->name, val); - switch (dev->Command) { - case CMD_MBINIT: - dev->CmdParamLeft = sizeof(MailboxInit_t); - break; - - case CMD_BIOSCMD: - dev->CmdParamLeft = 10; - break; - - case CMD_BIOS_MBINIT: - /* Same as 0x01 for AHA. */ - dev->CmdParamLeft = sizeof(MailboxInit_t); - break; - - case CMD_EMBOI: - case CMD_BUSON_TIME: - case CMD_BUSOFF_TIME: - case CMD_DMASPEED: - case CMD_RETSETUP: - case CMD_ECHO: - case CMD_OPTIONS: - case CMD_SHADOW_RAM: - dev->CmdParamLeft = 1; - break; - - case CMD_SELTIMEOUT: - dev->CmdParamLeft = 4; - break; - - case CMD_WRITE_EEPROM: - dev->CmdParamLeft = 3+32; - break; - - case CMD_READ_EEPROM: - dev->CmdParamLeft = 3; - break; - - case CMD_MBENABLE: - dev->CmdParamLeft = 2; - break; - } - } else { - dev->CmdBuf[dev->CmdParam] = val; - dev->CmdParam++; - dev->CmdParamLeft--; - } - - if (! dev->CmdParamLeft) { - aha_log("Running Operation Code 0x%02X\n", dev->Command); - switch (dev->Command) { - case CMD_NOP: /* No Operation */ - dev->DataReplyLeft = 0; - break; - - case CMD_MBINIT: /* mailbox initialization */ -aha_0x01: - { - dev->Mbx24bit = 1; - - mbi = (MailboxInit_t *)dev->CmdBuf; - - dev->MailboxCount = mbi->Count; - dev->MailboxOutAddr = ADDR_TO_U32(mbi->Address); - dev->MailboxInAddr = dev->MailboxOutAddr + (dev->MailboxCount * sizeof(Mailbox_t)); - - aha_log("Initialize Mailbox: MBI=0x%08lx, MBO=0x%08lx, %d entries at 0x%08lx\n", - dev->MailboxOutAddr, - dev->MailboxInAddr, - mbi->Count, - ADDR_TO_U32(mbi->Address)); - - dev->Status &= ~STAT_INIT; - dev->DataReplyLeft = 0; - } - break; - - case CMD_BIOSCMD: /* execute BIOS */ - cmd = (BIOSCMD *)dev->CmdBuf; - if (dev->type != AHA_1640) { - /* 1640 uses LBA. */ - cyl = ((cmd->u.chs.cyl & 0xff) << 8) | ((cmd->u.chs.cyl >> 8) & 0xff); - cmd->u.chs.cyl = cyl; - } - if (dev->type == AHA_1640) { - /* 1640 uses LBA. */ - aha_log("BIOS LBA=%06lx (%lu)\n", - lba32_blk(cmd), - lba32_blk(cmd)); - } else { - cmd->u.chs.head &= 0xf; - cmd->u.chs.sec &= 0x1f; - aha_log("BIOS CHS=%04X/%02X%02X\n", - cmd->u.chs.cyl, - cmd->u.chs.head, - cmd->u.chs.sec); - } - dev->DataBuf[0] = scsi_bios_command(7, cmd, (dev->type==AHA_1640)?1:0); - aha_log("BIOS Completion/Status Code %x\n", dev->DataBuf[0]); - dev->DataReplyLeft = 1; - break; - - case CMD_INQUIRY: /* Inquiry */ - dev->DataBuf[0] = dev->bid; - dev->DataBuf[1] = (dev->type != AHA_1640) ? 0x30 : 0x42; - dev->DataBuf[2] = dev->fwh; - dev->DataBuf[3] = dev->fwl; - dev->DataReplyLeft = 4; - break; - - case CMD_EMBOI: /* enable MBO Interrupt */ - if (dev->CmdBuf[0] <= 1) { - dev->MailboxOutInterrupts = dev->CmdBuf[0]; - aha_log("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); - suppress = 1; - } else { - dev->Status |= STAT_INVCMD; - } - dev->DataReplyLeft = 0; - break; - - case CMD_SELTIMEOUT: /* Selection Time-out */ - dev->DataReplyLeft = 0; - break; - - case CMD_BUSON_TIME: /* bus-on time */ - dev->DataReplyLeft = 0; - aha_log("Bus-on time: %d\n", dev->CmdBuf[0]); - break; - - case CMD_BUSOFF_TIME: /* bus-off time */ - dev->DataReplyLeft = 0; - aha_log("Bus-off time: %d\n", dev->CmdBuf[0]); - break; - - case CMD_DMASPEED: /* DMA Transfer Rate */ - dev->DataReplyLeft = 0; - aha_log("DMA transfer rate: %02X\n", dev->CmdBuf[0]); - break; - - case CMD_RETDEVS: /* return Installed Devices */ - memset(dev->DataBuf, 0x00, 8); - for (i=0; iDataBuf[i] = 0x00; - - /* Skip the HA .. */ - if (i == dev->HostID) continue; - - for (j=0; jDataBuf[i] |= (1<DataReplyLeft = i; - break; - - case CMD_RETCONF: /* return Configuration */ - dev->DataBuf[0] = (1<DmaChannel); - if (dev->Irq >= 8) - dev->DataBuf[1]=(1<<(dev->Irq-9)); - else - dev->DataBuf[1]=(1<Irq); - dev->DataBuf[2] = dev->HostID; - dev->DataReplyLeft = 3; - break; - - case CMD_RETSETUP: /* return Setup */ - { - dev->DataReplyLeft = dev->CmdBuf[0]; - - ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; - memset(ReplyISI, 0x00, sizeof(ReplyInquireSetupInformation)); - - ReplyISI->fSynchronousInitiationEnabled = 1; - ReplyISI->fParityCheckingEnabled = 1; - ReplyISI->cMailbox = dev->MailboxCount; - U32_TO_ADDR(ReplyISI->MailboxAddress, dev->MailboxOutAddr); - aha_log("Return Setup Information: %d\n", dev->CmdBuf[0]); - } - break; - - case CMD_ECHO: /* ECHO data */ - dev->DataBuf[0] = dev->CmdBuf[0]; - dev->DataReplyLeft = 1; - break; - - case CMD_OPTIONS: /* Set adapter options */ - if (dev->CmdParam == 1) - dev->CmdParamLeft = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - break; - - case CMD_WRITE_EEPROM: /* write EEPROM */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_eeprom(dev, - dev->Command, - dev->CmdBuf[0], - dev->CmdBuf[1], - dev->CmdBuf[2], - dev->DataBuf); - if (dev->DataReplyLeft == 0xff) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - - case CMD_READ_EEPROM: /* read EEPROM */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_eeprom(dev, - dev->Command, - dev->CmdBuf[0], - dev->CmdBuf[1], - dev->CmdBuf[2], - dev->DataBuf); - if (dev->DataReplyLeft == 0xff) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - - case CMD_SHADOW_RAM: /* Shadow RAM */ - /* - * For AHA1542CF, this is the command - * to play with the Shadow RAM. BIOS - * gives us one argument (00,02,03) - * and expects a 0x04 back in the INTR - * register. --FvK - */ - dev->Interrupt = aha154x_shram(dev,val); - break; - - case CMD_BIOS_MBINIT: /* BIOS Mailbox Initialization */ - /* Sent by CF BIOS. */ - goto aha_0x01; - - case CMD_MEMORY_MAP_1: /* AHA memory mapper */ - case CMD_MEMORY_MAP_2: /* AHA memory mapper */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_mmap(dev, dev->Command); - break; - - case CMD_EXTBIOS: /* Return extended BIOS information */ - dev->DataBuf[0] = 0x08; - dev->DataBuf[1] = dev->Lock; - dev->DataReplyLeft = 2; - break; - - case CMD_MBENABLE: /* Mailbox interface enable Command */ - dev->DataReplyLeft = 0; - if (dev->CmdBuf[1] == dev->Lock) { - if (dev->CmdBuf[0] & 1) { - dev->Lock = 1; - } else { - dev->Lock = 0; - } - } - break; - - case 0x2C: /* AHA-1542CP sends this */ - dev->DataBuf[0] = 0x00; - dev->DataReplyLeft = 1; - break; - - case 0x33: /* AHA-1542CP sends this */ - dev->DataBuf[0] = 0x00; - dev->DataBuf[1] = 0x00; - dev->DataBuf[2] = 0x00; - dev->DataBuf[3] = 0x00; - dev->DataReplyLeft = 256; - break; - - default: - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - } - - if (dev->DataReplyLeft) - dev->Status |= STAT_DFULL; - else if (!dev->CmdParamLeft) - aha_cmd_done(dev, suppress); - break; - - case 2: - break; - - case 3: - break; - } -} - - -static void -aha_writew(uint16_t Port, uint16_t Val, void *p) -{ - aha_write(Port, Val & 0xFF, p); } static uint8_t aha_mca_read(int port, void *priv) { - aha_t *dev = (aha_t *)priv; + x54x_t *dev = (x54x_t *)priv; return(dev->pos_regs[port & 7]); } @@ -1707,7 +502,7 @@ aha_mca_read(int port, void *priv) static void aha_mca_write(int port, uint8_t val, void *priv) { - aha_t *dev = (aha_t *)priv; + x54x_t *dev = (x54x_t *)priv; /* MCA does not write registers below 0x0100. */ if (port < 0x0102) return; @@ -1742,6 +537,9 @@ aha_mca_write(int port, uint8_t val, void *priv) break; } + /* This is always necessary so that the old handler doesn't remain. */ + x54x_io_remove(dev, dev->Base); + /* Save the new IRQ and DMA channel values. */ dev->Irq = (dev->pos_regs[4] & 0x07) + 8; dev->DmaChannel = dev->pos_regs[5] & 0x0f; @@ -1798,20 +596,15 @@ aha_mca_write(int port, uint8_t val, void *priv) * * So, remove current address, if any. */ - io_removehandler(dev->Base, 4, - aha_read, aha_readw, NULL, - aha_write, aha_writew, NULL, dev); mem_mapping_disable(&dev->bios.mapping); /* Initialize the device if fully configured. */ if (dev->pos_regs[2] & 0x01) { /* Card enabled; register (new) I/O handler. */ - io_sethandler(dev->Base, 4, - aha_read, aha_readw, NULL, - aha_write, aha_writew, NULL, dev); + x54x_io_set(dev, dev->Base); /* Reset the device. */ - aha_reset_ctrl(dev, CTRL_HRST); + x54x_reset_ctrl(dev, CTRL_HRST); /* Enable or disable the BIOS ROM. */ if (dev->rom_addr != 0x000000) { @@ -1824,7 +617,7 @@ aha_mca_write(int port, uint8_t val, void *priv) /* Initialize the board's ROM BIOS. */ static void -aha_setbios(aha_t *dev) +aha_setbios(x54x_t *dev) { uint32_t size; uint32_t mask; @@ -1836,9 +629,9 @@ aha_setbios(aha_t *dev) if (dev->bios_path == NULL) return; /* Open the BIOS image file and make sure it exists. */ - pclog_w(L"%S: loading BIOS from '%s'\n", dev->name, dev->bios_path); - if ((f = romfopen(dev->bios_path, L"rb")) == NULL) { - pclog("%s: BIOS ROM not found!\n", dev->name); + aha_log("%s: loading BIOS from '%ls'\n", dev->name, dev->bios_path); + if ((f = rom_fopen(dev->bios_path, L"rb")) == NULL) { + aha_log("%s: BIOS ROM not found!\n", dev->name); return; } @@ -1865,7 +658,7 @@ aha_setbios(aha_t *dev) dev->rom2 = NULL; } if (temp != 0) { - pclog("%s: BIOS ROM size invalid!\n", dev->name); + aha_log("%s: BIOS ROM size invalid!\n", dev->name); free(dev->rom1); if (dev->rom2 != NULL) free(dev->rom2); @@ -1886,7 +679,7 @@ aha_setbios(aha_t *dev) if (temp <= 0x2000) size = 0x2000; mask = (size - 1); - pclog("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n", + aha_log("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n", dev->name, dev->rom_addr, size, mask); /* Initialize the ROM entry for this BIOS. */ @@ -1900,9 +693,9 @@ aha_setbios(aha_t *dev) /* Map this system into the memory map. */ mem_mapping_add(&dev->bios.mapping, dev->rom_addr, size, - aha_mem_read, aha_mem_readw, aha_mem_readl, + aha_mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */ aha_mem_write, NULL, NULL, - dev->bios.rom, MEM_MAPPING_EXTERNAL, &dev->bios); + dev->bios.rom, MEM_MAPPING_EXTERNAL, dev); mem_mapping_disable(&dev->bios.mapping); /* @@ -1919,65 +712,20 @@ aha_setbios(aha_t *dev) for (i=0; i<8; i++) if (aha_ports[i] == dev->Base) break; if (i == 8) { - pclog("%s: invalid I/O address %04x selected!\n", + aha_log("%s: invalid I/O address %04x selected!\n", dev->name, dev->Base); return; } dev->bios.rom[dev->rom_ioaddr] = (uint8_t)i; - } - - /* - * The more recent BIOS images have their version ID - * encoded in the image, and we can use that info to - * report it back. - * - * Start out with a fake BIOS firmware version. - */ - dev->fwh = '1'; - dev->fwl = '0'; - if (dev->rom_fwhigh != 0x0000) { - /* Read firmware version from the BIOS. */ - dev->fwh = dev->bios.rom[dev->rom_fwhigh]; - dev->fwl = dev->bios.rom[dev->rom_fwhigh+1]; - } - - /* - * Do a checksum on the ROM. - * - * The BIOS ROMs on the 154xC(F) boards will always fail - * the checksum, because they are incomplete: on the real - * boards, a shadow RAM and some other (config) registers - * are mapped into its space. It is assumed that boards - * have logic that automatically generate a "fixup" byte - * at the end of the data to 'make up' for this. - * - * We emulated some of those in the patch routine, so now - * it is time to "fix up" the BIOS image so that the main - * (system) BIOS considers it valid. - */ -again: - mask = 0; - for (temp=0; tempbios.rom[temp]; - mask &= 0xff; - if (mask != 0x00) { - dev->bios.rom[temp-1] += (256 - mask); - goto again; + /* Negation of the DIP switches to satify the checksum. */ + dev->bios.rom[dev->rom_ioaddr + 1] = (uint8_t)((i ^ 0xff) + 1); } } -/* Initialize the board's EEPROM (NVR.) */ static void -aha_setnvr(aha_t *dev) +aha_initnvr(x54x_t *dev) { - /* Only if this device has an EEPROM. */ - if (dev->nvr_path == NULL) return; - - /* Allocate and initialize the EEPROM. */ - dev->nvr = (uint8_t *)malloc(NVR_SIZE); - memset(dev->nvr, 0x00, NVR_SIZE); - /* Initialize the on-board EEPROM. */ dev->nvr[0] = dev->HostID; /* SCSI ID 7 */ dev->nvr[0] |= (0x10 | 0x20 | 0x40); @@ -1992,17 +740,41 @@ aha_setnvr(aha_t *dev) } +/* Initialize the board's EEPROM (NVR.) */ +static void +aha_setnvr(x54x_t *dev) +{ + FILE *f; + + /* Only if this device has an EEPROM. */ + if (dev->nvr_path == NULL) return; + + /* Allocate and initialize the EEPROM. */ + dev->nvr = (uint8_t *)malloc(NVR_SIZE); + memset(dev->nvr, 0x00, NVR_SIZE); + + f = nvr_fopen(dev->nvr_path, L"rb"); + if (f) + { + fread(dev->nvr, 1, NVR_SIZE, f); + fclose(f); + f = NULL; + } + else + { + aha_initnvr(dev); + } +} + + /* General initialization routine for all boards. */ static void * -aha_init(int type) +aha_init(device_t *info) { - aha_t *dev; + x54x_t *dev; - /* Allocate control block and set up basic stuff. */ - dev = malloc(sizeof(aha_t)); - if (dev == NULL) return(dev); - memset(dev, 0x00, sizeof(aha_t)); - dev->type = type; + /* Call common initializer. */ + dev = x54x_init(info); /* * Set up the (initial) I/O address, IRQ and DMA info. @@ -2015,14 +787,25 @@ aha_init(int type) dev->Irq = device_get_config_int("irq"); dev->DmaChannel = device_get_config_int("dma"); dev->rom_addr = device_get_config_hex20("bios_addr"); -#if NOT_YET_USED - dev->HostID = device_get_config_int("hostid"); -#else dev->HostID = 7; /* default HA ID */ -#endif + dev->setup_info_len = sizeof(aha_setup_t); + dev->reset_duration = AHA_RESET_DURATION_US; + dev->max_id = 7; + dev->int_geom_writable = 0; + dev->cdrom_boot = 0; + + dev->ven_thread = aha_thread; + dev->ven_cmd_is_fast = aha_cmd_is_fast; + dev->ven_fast_cmds = aha_fast_cmds; + dev->get_ven_param_len = aha_param_len; + dev->ven_cmds = aha_cmds; + dev->get_ven_data = aha_setup_data; + dev->ven_reset = aha_reset; + + strcpy(dev->vendor, "Adaptec"); /* Perform per-board initialization. */ - switch(type) { + switch(dev->type) { case AHA_154xB: strcpy(dev->name, "AHA-154xB"); switch(dev->Base) { @@ -2036,45 +819,58 @@ aha_init(int type) L"roms/scsi/adaptec/aha1540b320_334.bin"; break; } - dev->bid = 'A'; + dev->fw_rev = "A001"; + /* This is configurable from the configuration for the 154xB, the rest of the controllers read it from the EEPROM. */ + dev->HostID = device_get_config_int("hostid"); break; case AHA_154xC: strcpy(dev->name, "AHA-154xC"); - dev->bios_path = L"roms/scsi/adaptec/aha1542c101.bin"; - dev->bid = 'D'; + dev->bios_path = L"roms/scsi/adaptec/aha1542c102.bin"; + dev->nvr_path = L"aha1542c.nvr"; + dev->fw_rev = "D001"; dev->rom_shram = 0x3F80; /* shadow RAM address base */ dev->rom_shramsz = 128; /* size of shadow RAM */ dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */ + dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ + dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ + dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ break; case AHA_154xCF: strcpy(dev->name, "AHA-154xCF"); dev->bios_path = L"roms/scsi/adaptec/aha1542cf211.bin"; - dev->nvr_path = L"aha1540cf.nvr"; - dev->bid = 'E'; + dev->nvr_path = L"aha1542cf.nvr"; + dev->fw_rev = "E001"; dev->rom_shram = 0x3F80; /* shadow RAM address base */ dev->rom_shramsz = 128; /* size of shadow RAM */ dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */ + dev->cdrom_boot = 1; + dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ + dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ + dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ break; case AHA_154xCP: strcpy(dev->name, "AHA-154xCP"); dev->bios_path = L"roms/scsi/adaptec/aha1542cp102.bin"; dev->nvr_path = L"aha1540cp.nvr"; - dev->bid = 'F'; + dev->fw_rev = "F001"; dev->rom_shram = 0x3F80; /* shadow RAM address base */ dev->rom_shramsz = 128; /* size of shadow RAM */ dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ dev->rom_fwhigh = 0x0055; /* firmware version (hi/lo) */ + dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ + dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ + dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ break; case AHA_1640: strcpy(dev->name, "AHA-1640"); dev->bios_path = L"roms/scsi/adaptec/aha1640.bin"; - dev->bid = 'B'; + dev->fw_rev = "BB01"; /* Enable MCA. */ dev->pos_regs[0] = 0x1F; /* MCA board ID */ @@ -2089,21 +885,19 @@ aha_init(int type) /* Initialize EEPROM (NVR) if needed. */ aha_setnvr(dev); - timer_add(aha_reset_poll, &dev->ResetCB, &dev->ResetCB, dev); - if (dev->Base != 0) { - /* Register our address space. */ - io_sethandler(dev->Base, 4, - aha_read, aha_readw, NULL, - aha_write, aha_writew, NULL, dev); - /* Initialize the device. */ - aha_reset_ctrl(dev, CTRL_HRST); + x54x_reset_ctrl(dev, CTRL_HRST); - /* Enable the memory. */ - if (dev->rom_addr != 0x000000) { - mem_mapping_enable(&dev->bios.mapping); - mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); + if (!(dev->bus & DEVICE_MCA)) { + /* Register our address space. */ + x54x_io_set(dev, dev->Base); + + /* Enable the memory. */ + if (dev->rom_addr != 0x000000) { + mem_mapping_enable(&dev->bios.mapping); + mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); + } } } @@ -2111,61 +905,135 @@ aha_init(int type) } -static void * -aha_154xB_init(void) -{ - return(aha_init(AHA_154xB)); -} - - -static void * -aha_154xCF_init(void) -{ - return(aha_init(AHA_154xCF)); -} - - -static void * -aha_1640_init(void) -{ - return(aha_init(AHA_1640)); -} - - -static void -aha_close(void *priv) -{ - aha_t *dev = (aha_t *)priv; - - if (dev) - { - dev->MailboxCount = 0; - - if (dev->evt) { - thread_destroy_event(dev->evt); - dev->evt = NULL; - if (poll_tid) { - thread_kill(poll_tid); - poll_tid = NULL; - } +static device_config_t aha_154xb_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x334, + { + { + "None", 0 + }, + { + "0x330", 0x330 + }, + { + "0x334", 0x334 + }, + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x130", 0x130 + }, + { + "0x134", 0x134 + }, + { + "" + } + }, + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 9, + { + { + "IRQ 9", 9 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "IRQ 14", 14 + }, + { + "IRQ 15", 15 + }, + { + "" + } + }, + }, + { + "dma", "DMA channel", CONFIG_SELECTION, "", 6, + { + { + "DMA 5", 5 + }, + { + "DMA 6", 6 + }, + { + "DMA 7", 7 + }, + { + "" + } + }, + }, + { + "hostid", "Host ID", CONFIG_SELECTION, "", 7, + { + { + "0", 0 + }, + { + "1", 1 + }, + { + "2", 2 + }, + { + "3", 3 + }, + { + "4", 4 + }, + { + "5", 5 + }, + { + "6", 6 + }, + { + "7", 7 + }, + { + "" + } + }, + }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, + { + { + "Disabled", 0 + }, + { + "C800H", 0xc8000 + }, + { + "D000H", 0xd0000 + }, + { + "D800H", 0xd8000 + }, + { + "" + } + }, + }, + { + "", "", -1 } - - if (dev->nvr != NULL) - free(dev->nvr); - - free(dev); - dev = NULL; - } -} - - -void -aha_device_reset(void *priv) -{ - aha_t *dev = (aha_t *)priv; - - aha_reset_ctrl(dev, 1); -} +}; static device_config_t aha_154x_config[] = { @@ -2269,35 +1137,36 @@ static device_config_t aha_154x_config[] = { device_t aha1540b_device = { "Adaptec AHA-1540B", - 0, - aha_154xB_init, - aha_close, - NULL, - NULL, - NULL, - NULL, + DEVICE_ISA | DEVICE_AT, + AHA_154xB, + aha_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + aha_154xb_config +}; + +device_t aha1542c_device = { + "Adaptec AHA-1542C", + DEVICE_ISA | DEVICE_AT, + AHA_154xC, + aha_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, aha_154x_config }; device_t aha1542cf_device = { "Adaptec AHA-1542CF", - 0, - aha_154xCF_init, - aha_close, - NULL, - NULL, - NULL, - NULL, + DEVICE_ISA | DEVICE_AT, + AHA_154xCF, + aha_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, aha_154x_config }; device_t aha1640_device = { "Adaptec AHA-1640", DEVICE_MCA, - aha_1640_init, - aha_close, - NULL, - NULL, - NULL, + AHA_1640, + aha_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/scsi/scsi_aha154x.h b/src/scsi/scsi_aha154x.h index 9634cda69..12c39b375 100644 --- a/src/scsi/scsi_aha154x.h +++ b/src/scsi/scsi_aha154x.h @@ -3,6 +3,7 @@ extern device_t aha1540b_device; +extern device_t aha1542c_device; extern device_t aha1542cf_device; extern device_t aha1640_device; diff --git a/src/scsi/scsi_bios_command.c b/src/scsi/scsi_bios_command.c deleted file mode 100644 index d085e2532..000000000 --- a/src/scsi/scsi_bios_command.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * The shared AHA and Buslogic SCSI BIOS command handler. - * - * Version: @(#)scsi_bios_command.c 1.0.1 2017/08/27 - * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * Copyright 2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. - */ -#include -#include -#include "../ibm.h" -#include "../dma.h" -#include "scsi.h" -#include "scsi_bios_command.h" -#include "scsi_device.h" - - -#if ENABLE_SCSI_BIOS_COMMAND_LOG -int scsi_bios_command_do_log = ENABLE_SCSI_BIOS_COMMAND_LOG; -#endif - - -static void -cmd_log(const char *fmt, ...) -{ -#if ENABLE_SCSI_BIOS_COMMAND_LOG - va_list ap; - - if (scsi_bios_command_do_log) { - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); - fflush(stdout); - } -#endif -} - - -static void -target_check(uint8_t id, uint8_t lun) -{ - if (! scsi_device_valid(id, lun)) { - fatal("BIOS INT13 device on %02i:%02i has disappeared\n", id, lun); - } -} - - -static uint8_t -completion_code(uint8_t *sense) -{ - switch (sense[12]) { - case 0x00: - return(0x00); - - case 0x20: - return(0x01); - - case 0x12: - case 0x21: - return(0x02); - - case 0x27: - return(0x03); - - case 0x14: - case 0x16: - return(0x04); - - case 0x10: - case 0x11: - return(0x10); - - case 0x17: - case 0x18: - return(0x11); - - case 0x01: - case 0x03: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - return(0x20); - - case 0x15: - case 0x02: - return(0x40); - - case 0x04: - case 0x28: - case 0x29: - case 0x2a: - return(0xaa); - - default: - break; - }; - - return(0xff); -} - - -uint8_t -scsi_bios_command_08(uint8_t id, uint8_t lun, uint8_t *buffer) -{ - uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; - uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; - uint32_t len = 0; - int i, ret, sc; - - ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len); - sc = completion_code(scsi_device_sense(id, lun)); - if (ret == 0) return(sc); - - memset(buffer, 0x00, 6); - for (i=0; i<4; i++) - buffer[i] = rcbuf[i]; - for (i=4; i<6; i++) - buffer[i] = rcbuf[(i + 2) ^ 1]; - cmd_log("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - - return(0); -} - - -int -scsi_bios_command_15(uint8_t id, uint8_t lun, uint8_t *buffer) -{ - uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; - uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; - uint32_t len = 0; - int i, ret, sc; - - ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len); - sc = completion_code(scsi_device_sense(id, lun)); - - memset(buffer, 0x00, 6); - for (i=0; i<4; i++) - buffer[i] = (ret == 0) ? 0 : rcbuf[i]; - - scsi_device_type_data(id, lun, &(buffer[4]), &(buffer[5])); - - cmd_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - - return(sc); -} - - -/* This returns the completion code. */ -uint8_t -scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba) -{ - uint8_t cdb[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; - scsi_device_t *dev; - uint32_t dma_address; - uint32_t lba; - int sector_len = cmd->secount; - int block_shift; - uint8_t ret; - - if (islba) - lba = lba32_blk(cmd); - else - lba = (cmd->u.chs.cyl << 9) + (cmd->u.chs.head << 5) + cmd->u.chs.sec; - - cmd_log("BIOS Command = 0x%02X\n", cmd->command); - - if ((cmd->id > max_id) || (cmd->lun > 7)) return(0x80); - - /* Get pointer to selected device. */ - dev = &SCSIDevices[cmd->id][cmd->lun]; - dev->InitLength = 0; - - if (! scsi_device_present(cmd->id, cmd->lun)) { - cmd_log("BIOS Target ID %i and LUN %i have no device attached\n", - cmd->id, cmd->lun); - return(0x80); - } - - dma_address = ADDR_TO_U32(cmd->dma_address); - - cmd_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n", - sector_len, dma_address); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - block_shift = scsi_device_block_shift(cmd->id, cmd->lun); - - switch(cmd->command) { - case 0x00: /* Reset Disk System, in practice it's a nop */ - return(0); - - case 0x01: /* Read Status of Last Operation */ - target_check(cmd->id, cmd->lun); - - /* - * Assuming 14 bytes because that is the default - * length for SCSI sense, and no command-specific - * indication is given. - */ - dev->InitLength = 14; - dev->CmdBuffer = (uint8_t *)malloc(14); - memset(dev->CmdBuffer, 0x00, 14); - -#if 0 - SCSIStatus = scsi_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer) ? SCSI_STATUS_OK : SCSI_STATUS_CHECK_CONDITION; -#endif - - if (sector_len > 0) { - cmd_log("BIOS DMA: Reading 14 bytes at %08X\n", - dma_address); - DMAPageWrite(dma_address, - (char *)scsi_device_sense(cmd->id, cmd->lun), 14); - } - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(0); - - case 0x02: /* Read Desired Sectors to Memory */ - target_check(cmd->id, cmd->lun); - - dev->InitLength = sector_len << block_shift; - dev->CmdBuffer = (uint8_t *)malloc(dev->InitLength); - memset(dev->CmdBuffer, 0x00, dev->InitLength); - - cdb[0] = GPCMD_READ_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = (sector_len >> 8) & 0xff; - cdb[8] = sector_len & 0xff; -#if 0 - cmd_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount); -#endif - - scsi_device_command(cmd->id, cmd->lun, 12, cdb); - if (sector_len > 0) { - cmd_log("BIOS DMA: Reading %i bytes at %08X\n", - dev->InitLength, dma_address); - DMAPageWrite(dma_address, - (char *)dev->CmdBuffer, dev->InitLength); - } - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x03: /* Write Desired Sectors from Memory */ - target_check(cmd->id, cmd->lun); - - dev->InitLength = sector_len << block_shift; - dev->CmdBuffer = (uint8_t *)malloc(dev->InitLength); - memset(dev->CmdBuffer, 0x00, dev->InitLength); - - if (sector_len > 0) { - cmd_log("BIOS DMA: Reading %i bytes at %08X\n", - dev->InitLength, dma_address); - DMAPageRead(dma_address, - (char *)dev->CmdBuffer, dev->InitLength); - } - - cdb[0] = GPCMD_WRITE_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = (sector_len >> 8) & 0xff; - cdb[8] = sector_len & 0xff; -#if 0 - cmd_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount); -#endif - - scsi_device_command(cmd->id, cmd->lun, 12, cdb); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x04: /* Verify Desired Sectors */ - target_check(cmd->id, cmd->lun); - - cdb[0] = GPCMD_VERIFY_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = (sector_len >> 8) & 0xff; - cdb[8] = sector_len & 0xff; - - scsi_device_command(cmd->id, cmd->lun, 12, cdb); - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x05: /* Format Track, invalid since SCSI has no tracks */ -//FIXME: add a longer delay here --FvK - return(1); - - case 0x06: /* Identify SCSI Devices, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x07: /* Format Unit */ - target_check(cmd->id, cmd->lun); - - cdb[0] = GPCMD_FORMAT_UNIT; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command(cmd->id, cmd->lun, 12, cdb); - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x08: /* Read Drive Parameters */ - target_check(cmd->id, cmd->lun); - - dev->InitLength = 6; - dev->CmdBuffer = (uint8_t *)malloc(dev->InitLength); - memset(dev->CmdBuffer, 0x00, dev->InitLength); - - ret = scsi_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer); - - cmd_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); - DMAPageWrite(dma_address, - (char *)dev->CmdBuffer, dev->InitLength); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(ret); - - case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x0c: /* Seek */ - target_check(cmd->id, cmd->lun); - -//FIXME: is this needed? Looks like a copy-paste leftover.. --FvK - dev->InitLength = sector_len << block_shift; - - cdb[0] = GPCMD_SEEK_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - - scsi_device_command(cmd->id, cmd->lun, 12, cdb); - - return((SCSIStatus == SCSI_STATUS_OK) ? 1 : 0); - - case 0x0d: /* Alternate Disk Reset, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x10: /* Test Drive Ready */ - target_check(cmd->id, cmd->lun); - - cdb[0] = GPCMD_TEST_UNIT_READY; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command(cmd->id, cmd->lun, 12, cdb); - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x11: /* Recalibrate */ - target_check(cmd->id, cmd->lun); - - cdb[0] = GPCMD_REZERO_UNIT; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command(cmd->id, cmd->lun, 12, cdb); - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x14: /* Controller Diagnostic */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x15: /* Read DASD Type */ - target_check(cmd->id, cmd->lun); - - dev->InitLength = 6; - dev->CmdBuffer = (uint8_t *)malloc(dev->InitLength); - memset(dev->CmdBuffer, 0x00, dev->InitLength); - - ret = scsi_bios_command_15(cmd->id, cmd->lun, dev->CmdBuffer); - - cmd_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); - DMAPageWrite(dma_address, - (char *)dev->CmdBuffer, dev->InitLength); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(ret); - - default: - cmd_log("BIOS: Unimplemented command: %02X\n", cmd->command); - return(1); - } - - cmd_log("BIOS Request complete\n"); -} diff --git a/src/scsi/scsi_bios_command.h b/src/scsi/scsi_bios_command.h deleted file mode 100644 index 5e66f035f..000000000 --- a/src/scsi/scsi_bios_command.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * The shared AHA and Buslogic SCSI BIOS command handler's - * headler. - * - * Version: @(#)scsi_bios_command.h 1.0.0 2017/08/26 - * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. - */ -#pragma pack(push,1) -typedef struct -{ - uint8_t command; - uint8_t lun:3, - reserved:2, - id:3; - union { - struct { - uint16_t cyl; - uint8_t head; - uint8_t sec; - } chs; - struct { - uint8_t lba0; /* MSB */ - uint8_t lba1; - uint8_t lba2; - uint8_t lba3; /* LSB */ - } lba; - } u; - uint8_t secount; - addr24 dma_address; -} BIOSCMD; -#pragma pack(pop) -#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \ - (p->u.lba.lba2<<8) | p->u.lba.lba3) - -extern uint8_t scsi_bios_command(uint8_t last_id, BIOSCMD *BiosCmd, int8_t islba); diff --git a/src/scsi/scsi_bus.c b/src/scsi/scsi_bus.c new file mode 100644 index 000000000..4ff706a41 --- /dev/null +++ b/src/scsi/scsi_bus.c @@ -0,0 +1,386 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * The generic SCSI bus operations handler. + * + * Version: @(#)scsi_bus.c 1.0.1 2017/10/04 + * + * NOTES: For now ported from PCem with some modifications + * but at least it's a start. + * + * Authors: TheCollector1995, + */ +#include +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "scsi.h" +#include "scsi_device.h" + +#define STATE_IDLE 0 +#define STATE_COMMAND 1 +#define STATE_COMMANDWAIT 2 +#define STATE_DATAIN 3 +#define STATE_DATAOUT 4 +#define STATE_STATUS 5 +#define STATE_MESSAGEIN 6 +#define STATE_PHASESEL 7 + +#define SET_BUS_STATE(bus, state) bus->bus_out = (bus->bus_out & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN)) + +uint32_t SCSI_BufferLength; + +int scsi_bus_do_log = 0; + + +void scsi_bus_log(const char *format, ...) +{ +#ifdef ENABLE_SCSI_BUS_LOG + if (scsi_bus_do_log) + { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif +} + + +/* get the length of a SCSI command based on its command byte type */ +static int get_cmd_len(int cbyte) +{ + int len; + int group; + + group = (cbyte>>5) & 7; + + if (group == 0) len = 6; + if (group == 1 || group == 2) len = 10; + if (group == 5) len = 12; + + //scsi_bus_log("Command group %d, length %d\n", group, len); + + return len; +} + +static int get_dev_id(uint8_t data) +{ + int c; + + for (c = 0; c < SCSI_ID_MAX; c++) + { + if (data & (1 << c)) + { + return c; + } + } + + return -1; +} + +int scsi_bus_update(scsi_bus_t *bus, int bus_assert) +{ + scsi_device_t *dev; + uint8_t lun = 0; + + if (bus_assert & BUS_ARB) + bus->state = STATE_IDLE; + + switch (bus->state) + { + case STATE_IDLE: + scsi_bus_log("State Idle\n"); + bus->clear_req = bus->change_state_delay = bus->new_req_delay = 0; + if ((bus_assert & BUS_SEL) && !(bus_assert & BUS_BSY)) + { + uint8_t sel_data = BUS_GETDATA(bus_assert); + + bus->dev_id = get_dev_id(sel_data); + if (scsi_device_present(bus->dev_id, 0)) + { + bus->bus_out |= BUS_BSY; + bus->state = STATE_PHASESEL; + } + //scsi_bus_log("Device id %i\n", bus->dev_id); + break; + } + break; + + case STATE_PHASESEL: + scsi_bus_log("State Phase Sel\n"); + if (!(bus_assert & BUS_SEL)) + { + if (!(bus_assert & BUS_ATN)) + { + if (scsi_device_present(bus->dev_id, 0)) + { + bus->state = STATE_COMMAND; + bus->bus_out = BUS_BSY | BUS_REQ; + bus->command_pos = 0; + SET_BUS_STATE(bus, SCSI_PHASE_COMMAND); + } + else + { + bus->state = STATE_IDLE; + bus->bus_out = 0; + } + } + else + fatal("dropped sel %x\n", bus_assert & BUS_ATN); + } + break; + + case STATE_COMMAND: + if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) + { + scsi_bus_log("State Command\n"); + bus->command[bus->command_pos++] = BUS_GETDATA(bus_assert); + + bus->clear_req = 3; + bus->new_state = bus->bus_out & SCSI_PHASE_MESSAGE_IN; + bus->bus_out &= ~BUS_REQ; + + if (get_cmd_len(bus->command[0]) == bus->command_pos) + { + lun = (bus->command[1] >> 5) & 7; + bus->data_pos = 0; + + dev = &SCSIDevices[bus->dev_id][lun]; + + scsi_bus_log("Command 0x%02X\n", bus->command[0]); + + dev->BufferLength = -1; + + pclog("(%02X:%02X): Command %02X: Buffer length %i\n", bus->dev_id, lun, bus->command[0], dev->BufferLength); + + scsi_device_command_phase0(bus->dev_id, lun, get_cmd_len(bus->command[0]), bus->command); + + pclog("SCSI Phase: %02X\n", SCSIPhase); + + if ((SCSIPhase == SCSI_PHASE_DATA_IN) || (SCSIPhase == SCSI_PHASE_DATA_OUT)) + { + pclog("dev->CmdBuffer = %08X\n", dev->CmdBuffer); + dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength); + pclog("dev->CmdBuffer = %08X\n", dev->CmdBuffer); + } + + if (SCSIPhase == SCSI_PHASE_DATA_OUT) + { + /* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */ + scsi_bus_log("Next state is data out\n"); + + bus->state = STATE_COMMANDWAIT; + bus->clear_req = 0; + } + else + { + /* Other command - execute immediately. */ + bus->new_state = SCSIPhase; + if (SCSIPhase == SCSI_PHASE_DATA_IN) + { + scsi_device_command_phase1(bus->dev_id, lun); + } + + bus->change_state_delay = 4; + } + } + } + break; + + case STATE_COMMANDWAIT: + bus->new_state = SCSI_PHASE_DATA_OUT; + bus->change_state_delay = 4; + bus->clear_req = 4; + break; + + case STATE_DATAIN: + if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) + { + scsi_bus_log("State Data In\n"); + + /* This seems to be read, so we first execute the command, then we return the bytes to the host. */ + + lun = (bus->command[1] >> 5) & 7; + + dev = &SCSIDevices[bus->dev_id][lun]; + + if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength) + { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + bus->bus_out &= ~BUS_REQ; + bus->new_state = SCSI_PHASE_STATUS; + bus->change_state_delay = 4; + bus->new_req_delay = 8; + } + else + { + uint8_t val = dev->CmdBuffer[bus->data_pos++]; + + bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(val) | BUS_DBP | BUS_REQ; + bus->clear_req = 3; + bus->bus_out &= ~BUS_REQ; + bus->new_state = SCSI_PHASE_DATA_IN; + } + } + break; + + case STATE_DATAOUT: + if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) + { + scsi_bus_log("State Data Out\n"); + + lun = (bus->command[1] >> 5) & 7; + + dev = &SCSIDevices[bus->dev_id][lun]; + + /* This is write, so first get the data from the host, then execute the last phase of the command. */ + dev->CmdBuffer[bus->data_pos++] = BUS_GETDATA(bus_assert); + + if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength) + { + /* pclog("%04X bytes written (%02X %02X)\n", bus->data_pos, bus->command[0], bus->command[1]); */ + scsi_bus_log("Actually executing write command\n"); + scsi_device_command_phase1(bus->dev_id, lun); + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + bus->bus_out &= ~BUS_REQ; + bus->new_state = SCSI_PHASE_STATUS; + bus->change_state_delay = 4; + bus->new_req_delay = 8; + } + else + { + bus->bus_out |= BUS_REQ; + } + } + break; + + case STATE_STATUS: + scsi_bus_log("State Status\n"); + + if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) + { + /* pclog("Preparing for message in\n"); */ + bus->bus_out &= ~BUS_REQ; + bus->new_state = SCSI_PHASE_MESSAGE_IN; + bus->change_state_delay = 4; + bus->new_req_delay = 8; + } + break; + + case STATE_MESSAGEIN: + scsi_bus_log("State Message In\n"); + + if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) + { + bus->bus_out &= ~BUS_REQ; + bus->new_state = BUS_IDLE; + bus->change_state_delay = 4; + } + break; + } + bus->bus_in = bus_assert; + + return bus->bus_out | bus->bus_in; +} + +int scsi_bus_read(scsi_bus_t *bus) +{ + scsi_device_t *dev; + uint8_t lun = 0; + + if (bus->clear_req) + { + bus->clear_req--; + if (!bus->clear_req) + { + scsi_bus_log("Clear REQ\n"); + + SET_BUS_STATE(bus, bus->new_state); + bus->bus_out |= BUS_REQ; + } + } + + if (bus->change_state_delay) + { + bus->change_state_delay--; + if (!bus->change_state_delay) + { + uint8_t val; + + scsi_bus_log("Change state delay\n"); + + SET_BUS_STATE(bus, bus->new_state); + + switch (bus->bus_out & SCSI_PHASE_MESSAGE_IN) + { + case SCSI_PHASE_DATA_IN: + lun = (bus->command[1] >> 5) & 7; + dev = &SCSIDevices[bus->dev_id][lun]; + + scsi_bus_log("Phase data in\n"); + bus->state = STATE_DATAIN; + val = dev->CmdBuffer[bus->data_pos++]; + bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(val) | BUS_DBP; + break; + + case SCSI_PHASE_DATA_OUT: + scsi_bus_log("Phase data out\n"); + if (bus->new_state & BUS_IDLE) + { + bus->state = STATE_IDLE; + bus->bus_out &= ~BUS_BSY; + } + else + { + bus->state = STATE_DATAOUT; + } + break; + + case SCSI_PHASE_STATUS: + scsi_bus_log("Phase status\n"); + bus->state = STATE_STATUS; + bus->bus_out |= BUS_REQ; + bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(SCSIStatus) | BUS_DBP; + /* pclog("SCSI Status (command %02X): %02X (%08X)\n", bus->command[0], SCSIStatus, bus->bus_out); */ + break; + + case SCSI_PHASE_MESSAGE_IN: + scsi_bus_log("Phase message in\n"); + /* pclog("Message in\n"); */ + bus->state = STATE_MESSAGEIN; + bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; + break; + + default: + fatal("change_state_delay bad state %x\n", bus->bus_out); + } + } + } + if (bus->new_req_delay) + { + bus->new_req_delay--; + if (!bus->new_req_delay) + { + bus->bus_out |= BUS_REQ; + } + } + + return bus->bus_out; +} + +int scsi_bus_match(scsi_bus_t *bus, int bus_assert) +{ + return (bus_assert & (BUS_CD | BUS_IO | BUS_MSG)) == (bus->bus_out & (BUS_CD | BUS_IO | BUS_MSG)); +} diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index f6d0ee901..a1ddc7daa 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -7,94 +7,45 @@ * Emulation of BusLogic ISA and PCI SCSI controllers. Boards * supported: * - * 0 - BT-545C ISA; - * 1 - BT-958D PCI (but BT-545C ISA on non-PCI machines) + * 0 - BT-542BH ISA; + * 1 - BT-545S ISA; + * 2 - BT-958D PCI * - * Version: @(#)scsi_buslogic.c 1.0.12 2017/09/05 + * Version: @(#)scsi_buslogic.c 1.0.23 2017/10/14 * * Authors: TheCollector1995, * Miran Grca, * Fred N. van Kempen, + * * Copyright 2016,2017 Miran Grca. * Copyright 2017 Fred N. van Kempen. */ -#include #include -#include +#include #include +#include #include +#include #include "../ibm.h" #include "../io.h" +#include "../mca.h" #include "../mem.h" +#include "../mca.h" #include "../rom.h" +#include "../nvr.h" #include "../dma.h" #include "../pic.h" #include "../pci.h" #include "../timer.h" #include "../device.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "scsi.h" -#include "scsi_bios_command.h" -#include "scsi_device.h" #include "scsi_buslogic.h" +#include "scsi_device.h" +#include "scsi_x54x.h" -#define BUSLOGIC_RESET_DURATION_US UINT64_C(50) - - -/* - * Host Adapter I/O ports. - * - * READ Port x+0: STATUS - * WRITE Port x+0: CONTROL - * - * READ Port x+1: DATA - * WRITE Port x+1: COMMAND - * - * READ Port x+2: INTERRUPT STATUS - * WRITE Port x+2: (undefined?) - * - * R/W Port x+3: (undefined) - */ - -/* WRITE CONTROL commands. */ -#define CTRL_HRST 0x80 /* Hard reset */ -#define CTRL_SRST 0x40 /* Soft reset */ -#define CTRL_IRST 0x20 /* interrupt reset */ -#define CTRL_SCRST 0x10 /* SCSI bus reset */ - -/* READ STATUS. */ -#define STAT_STST 0x80 /* self-test in progress */ -#define STAT_DFAIL 0x40 /* internal diagnostic failure */ -#define STAT_INIT 0x20 /* mailbox initialization required */ -#define STAT_IDLE 0x10 /* HBA is idle */ -#define STAT_CDFULL 0x08 /* Command/Data output port is full */ -#define STAT_DFULL 0x04 /* Data input port is full */ -#define STAT_INVCMD 0x01 /* Invalid command */ - -/* READ/WRITE DATA. */ -#define CMD_NOP 0x00 /* No operation */ -#define CMD_MBINIT 0x01 /* mailbox initialization */ -#define CMD_START_SCSI 0x02 /* Start SCSI command */ -#define CMD_BIOS 0x03 /* Execute ROM BIOS command */ -#define CMD_INQUIRY 0x04 /* Adapter inquiry */ -#define CMD_EMBOI 0x05 /* enable Mailbox Out Interrupt */ -#define CMD_SELTIMEOUT 0x06 /* Set SEL timeout */ -#define CMD_BUSON_TIME 0x07 /* set bus-On time */ -#define CMD_BUSOFF_TIME 0x08 /* set bus-off time */ -#define CMD_DMASPEED 0x09 /* set ISA DMA speed */ -#define CMD_RETDEVS 0x0A /* return installed devices */ -#define CMD_RETCONF 0x0B /* return configuration data */ -#define CMD_TARGET 0x0C /* set HBA to target mode */ -#define CMD_RETSETUP 0x0D /* return setup data */ -#define CMD_ECHO 0x1F /* ECHO command data */ - -/* READ INTERRUPT STATUS. */ -#define INTR_ANY 0x80 /* any interrupt */ -#define INTR_SRCD 0x08 /* SCSI reset detected */ -#define INTR_HACC 0x04 /* HA command complete */ -#define INTR_MBOA 0x02 /* MBO empty */ -#define INTR_MBIF 0x01 /* MBI full */ +#define BUSLOGIC_RESET_DURATION_US UINT64_C(5000) /* @@ -177,24 +128,6 @@ typedef union { /** Structure for the INQUIRE_SETUP_INFORMATION reply. */ #pragma pack(push,1) typedef struct { - uint8_t uOffset :4, - uTransferPeriod :3, - fSynchronous :1; -} ReplyInquireSetupInformationSynchronousValue; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t fSynchronousInitiationEnabled :1, - fParityCheckingEnabled :1, - uReserved1 :6; - uint8_t uBusTransferRate; - uint8_t uPreemptTimeOnBus; - uint8_t uTimeOffBus; - uint8_t cMailbox; - addr24 MailboxAddress; - ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8]; - uint8_t uDisconnectPermittedId0To7; uint8_t uSignature; uint8_t uCharacterD; uint8_t uHostBusType; @@ -205,7 +138,7 @@ typedef struct { uint8_t uReserved2; uint8_t uWideTransferPermittedId8To15; uint8_t uWideTransfersActiveId8To15; -} ReplyInquireSetupInformation; +} buslogic_setup_t; #pragma pack(pop) /* Structure for the INQUIRE_EXTENDED_SETUP_INFORMATION. */ @@ -247,184 +180,6 @@ typedef struct { } BuslogicPCIInformation_t; #pragma pack(pop) -#pragma pack(push,1) -typedef struct { - uint8_t Count; - addr24 Address; -} MailboxInit_t; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Count; - uint32_t Address; -} MailboxInitExtended_t; -#pragma pack(pop) - - -/* - * Mailbox Definitions. - * - * Mailbox Out (MBO) command values. - */ -#define MBO_FREE 0x00 -#define MBO_START 0x01 -#define MBO_ABORT 0x02 - -/* Mailbox In (MBI) status values. */ -#define MBI_FREE 0x00 -#define MBI_SUCCESS 0x01 -#define MBI_ABORT 0x02 -#define MBI_NOT_FOUND 0x03 -#define MBI_ERROR 0x04 - - -#pragma pack(push,1) -typedef struct { - uint8_t CmdStatus; - addr24 CCBPointer; -} Mailbox_t; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint32_t CCBPointer; - union { - struct { - uint8_t Reserved[3]; - uint8_t ActionCode; - } out; - struct { - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Reserved; - uint8_t CompletionCode; - } in; - } u; -} Mailbox32_t; -#pragma pack(pop) - - -/* - * - * CCB - SCSI Command Control Block - * - * The CCB is a superset of the CDB (Command Descriptor Block) - * and specifies detailed information about a SCSI command. - * - */ -/* Byte 0 Command Control Block Operation Code */ -#define SCSI_INITIATOR_COMMAND 0x00 -#define TARGET_MODE_COMMAND 0x01 -#define SCATTER_GATHER_COMMAND 0x02 -#define SCSI_INITIATOR_COMMAND_RES 0x03 -#define SCATTER_GATHER_COMMAND_RES 0x04 -#define BUS_RESET 0x81 - -/* Byte 1 Address and Direction Control */ -#define CCB_TARGET_ID_SHIFT 0x06 /* CCB Op Code = 00, 02 */ -#define CCB_INITIATOR_ID_SHIFT 0x06 /* CCB Op Code = 01 */ -#define CCB_DATA_XFER_IN 0x01 -#define CCB_DATA_XFER_OUT 0x02 -#define CCB_LUN_MASK 0x07 /* Logical Unit Number */ - -/* Byte 2 SCSI_Command_Length - Length of SCSI CDB - Byte 3 Request Sense Allocation Length */ -#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ -#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ - -/* Bytes 4, 5 and 6 Data Length - Data transfer byte count */ -/* Bytes 7, 8 and 9 Data Pointer - SGD List or Data Buffer */ -/* Bytes 10, 11 and 12 Link Pointer - Next CCB in Linked List */ -/* Byte 13 Command Link ID - TBD (I don't know yet) */ -/* Byte 14 Host Status - Host Adapter status */ -#define CCB_COMPLETE 0x00 /* CCB completed without error */ -#define CCB_LINKED_COMPLETE 0x0A /* Linked command completed */ -#define CCB_LINKED_COMPLETE_INT 0x0B /* Linked complete with intr */ -#define CCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ -#define CCB_DATA_OVER_UNDER_RUN 0x12 -#define CCB_UNEXPECTED_BUS_FREE 0x13 /* Trg dropped SCSI BSY */ -#define CCB_PHASE_SEQUENCE_FAIL 0x14 /* Trg bus phase sequence fail */ -#define CCB_BAD_MBO_COMMAND 0x15 /* MBO command not 0, 1 or 2 */ -#define CCB_INVALID_OP_CODE 0x16 /* CCB invalid operation code */ -#define CCB_BAD_LINKED_LUN 0x17 /* Linked CCB LUN diff from 1st */ -#define CCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ -#define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */ -#define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */ - -/* Byte 15 Target Status - - See scsi.h files for these statuses. - Bytes 16 and 17 Reserved (must be 0) - Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block */ - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Reserved1 :3, - ControlByte :2, - TagQueued :1, - QueueTag :2; - uint8_t CdbLength; - uint8_t RequestSenseLength; - uint32_t DataLength; - uint32_t DataPointer; - uint8_t Reserved2[2]; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Id; - uint8_t Lun :5, - LegacyTagEnable :1, - LegacyQueueTag :2; - uint8_t Cdb[12]; - uint8_t Reserved3[6]; - uint32_t SensePointer; -} CCB32; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Lun :3, - ControlByte :2, - Id :3; - uint8_t CdbLength; - uint8_t RequestSenseLength; - addr24 DataLength; - addr24 DataPointer; - addr24 LinkPointer; - uint8_t LinkId; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Reserved[2]; - uint8_t Cdb[12]; -} CCB; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Pad1 :3, - ControlByte :2, - Pad2 :3; - uint8_t CdbLength; - uint8_t RequestSenseLength; - uint8_t Pad3[10]; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Pad4[2]; - uint8_t Cdb[12]; -} CCBC; -#pragma pack(pop) - -#pragma pack(push,1) -typedef union { - CCB32 new; - CCB old; - CCBC common; -} CCBU; -#pragma pack(pop) - #pragma pack(push,1) typedef struct { @@ -451,87 +206,43 @@ typedef struct #pragma pack(push,1) typedef struct { - CCBU CmdBlock; - uint8_t *RequestSenseBuffer; - uint32_t CCBPointer; - int Is24bit; - uint8_t TargetID; - uint8_t LUN; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t MailboxCompletionCode; -} Req_t; + uint8_t Count; + uint32_t Address; +} MailboxInitExtended_t; #pragma pack(pop) -#pragma pack(push,1) typedef struct { rom_t bios; - int UseLocalRAM; int ExtendedLUNCCBFormat; + int fAggressiveRoundRobinMode; HALocalRAM LocalRAM; - Req_t Req; - volatile uint8_t /* for multi-threading, keep */ - Status, /* these volatile */ - Interrupt; - uint8_t Geometry; - uint8_t Control; - uint8_t Command; - uint8_t CmdBuf[128]; - uint8_t CmdParam; - uint8_t CmdParamLeft; - uint8_t DataBuf[65536]; - uint16_t DataReply; - uint16_t DataReplyLeft; - uint32_t MailboxCount; - uint32_t MailboxOutAddr; - uint32_t MailboxOutPosCur; - uint32_t MailboxInAddr; - uint32_t MailboxInPosCur; - int Base; int PCIBase; int MMIOBase; - int Irq; - int DmaChannel; - int IrqEnabled; - int Mbx24bit; - int MailboxOutInterrupts; - int MbiActive[256]; - int PendingInterrupt; - int Lock; - mem_mapping_t mmio_mapping; int chip; - int Card; int has_bios; uint32_t bios_addr, bios_size, bios_mask; uint8_t AutoSCSIROM[32768]; uint8_t SCAMData[65536]; - event_t *evt; - int scan_restart; -} Buslogic_t; -#pragma pack(pop) - - -static int BuslogicResetCallback = 0; - - -static void BuslogicCommandThread(void *p); -static thread_t *poll_tid; +} buslogic_data_t; enum { + CHIP_BUSLOGIC_ISA_542, CHIP_BUSLOGIC_ISA, CHIP_BUSLOGIC_MCA, + CHIP_BUSLOGIC_EISA, CHIP_BUSLOGIC_VLB, CHIP_BUSLOGIC_PCI }; -/* #define ENABLE_BUSLOGIC_LOG 0 */ -int buslogic_do_log = 0; +#ifdef ENABLE_BUSLOGIC_LOG +int buslogic_do_log = ENABLE_BUSLOGIC_LOG; +#endif static void -BuslogicLog(const char *format, ...) +buslogic_log(const char *format, ...) { #ifdef ENABLE_BUSLOGIC_LOG va_list ap; @@ -544,56 +255,23 @@ BuslogicLog(const char *format, ...) } #endif } -#define pclog BuslogicLog - -static void -BuslogicInterrupt(Buslogic_t *bl, int set) -{ - if (bl->chip == CHIP_BUSLOGIC_PCI) - { - if (set) - { - pci_set_irq(bl->Card, PCI_INTA); - } - else - { - pci_clear_irq(bl->Card, PCI_INTA); - } - } - else - { - if (set) - { - if (bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt) - { - picintlevel(1 << bl->Irq); - } - else - { - picint(1 << bl->Irq); - } - /* pclog("Interrupt Set\n"); */ - } - else - { - picintc(1 << bl->Irq); - /* pclog("Interrupt Cleared\n"); */ - } - } -} static wchar_t * -BuslogicGetNVRFileName(Buslogic_t *bl) +BuslogicGetNVRFileName(buslogic_data_t *bl) { switch(bl->chip) { + case CHIP_BUSLOGIC_ISA_542: + return L"bt542bh.nvr"; case CHIP_BUSLOGIC_ISA: - return L"bt545c.nvr"; + return L"bt545s.nvr"; +#ifdef BUSLOGIC_NOT_WORKING case CHIP_BUSLOGIC_MCA: return L"bt640a.nvr"; case CHIP_BUSLOGIC_VLB: return L"bt445s.nvr"; +#endif case CHIP_BUSLOGIC_PCI: return L"bt958d.nvr"; default: @@ -604,134 +282,123 @@ BuslogicGetNVRFileName(Buslogic_t *bl) static void -BuslogicAutoSCSIRamSetDefaults(Buslogic_t *bl, uint8_t safe) +BuslogicAutoSCSIRamSetDefaults(x54x_t *dev, uint8_t safe) { - HALocalRAM *HALR = &bl->LocalRAM; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + HALocalRAM *HALR = &bl->LocalRAM; - memset(&(HALR->structured.autoSCSIData), 0, sizeof(AutoSCSIRam)); + memset(&(HALR->structured.autoSCSIData), 0, sizeof(AutoSCSIRam)); - HALR->structured.autoSCSIData.aInternalSignature[0] = 'F'; - HALR->structured.autoSCSIData.aInternalSignature[1] = 'A'; + HALR->structured.autoSCSIData.aInternalSignature[0] = 'F'; + HALR->structured.autoSCSIData.aInternalSignature[1] = 'A'; - HALR->structured.autoSCSIData.cbInformation = 64; + HALR->structured.autoSCSIData.cbInformation = 64; - HALR->structured.autoSCSIData.aHostAdaptertype[0] = ' '; - switch (bl->chip) - { - case CHIP_BUSLOGIC_ISA: - HALR->structured.autoSCSIData.aHostAdaptertype[1] = '5'; - HALR->structured.autoSCSIData.aHostAdaptertype[2] = '4'; - HALR->structured.autoSCSIData.aHostAdaptertype[3] = '5'; - HALR->structured.autoSCSIData.aHostAdaptertype[4] = 'C'; + HALR->structured.autoSCSIData.aHostAdaptertype[0] = ' '; + HALR->structured.autoSCSIData.aHostAdaptertype[5] = ' '; + switch (bl->chip) { + case CHIP_BUSLOGIC_ISA_542: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "542BH", 5); + break; + case CHIP_BUSLOGIC_ISA: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "545S", 4); + break; +#ifdef BUSLOGIC_NOT_WORKING + case CHIP_BUSLOGIC_VLB: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "445S", 4); + break; + case CHIP_BUSLOGIC_MCA: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "640A", 4); + break; +#endif + case CHIP_BUSLOGIC_PCI: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "958D", 4); + break; + } + + HALR->structured.autoSCSIData.fLevelSensitiveInterrupt = (bl->chip == CHIP_BUSLOGIC_PCI) ? 1 : 0; + HALR->structured.autoSCSIData.uSystemRAMAreForBIOS = 6; + + if (bl->chip != CHIP_BUSLOGIC_PCI) { + switch(dev->DmaChannel) { + case 5: + HALR->structured.autoSCSIData.uDMAChannel = 1; break; - case CHIP_BUSLOGIC_VLB: - HALR->structured.autoSCSIData.aHostAdaptertype[1] = '4'; - HALR->structured.autoSCSIData.aHostAdaptertype[2] = '4'; - HALR->structured.autoSCSIData.aHostAdaptertype[3] = '5'; - HALR->structured.autoSCSIData.aHostAdaptertype[4] = 'S'; + case 6: + HALR->structured.autoSCSIData.uDMAChannel = 2; break; - case CHIP_BUSLOGIC_MCA: - HALR->structured.autoSCSIData.aHostAdaptertype[1] = '6'; - HALR->structured.autoSCSIData.aHostAdaptertype[2] = '4'; - HALR->structured.autoSCSIData.aHostAdaptertype[3] = '0'; - HALR->structured.autoSCSIData.aHostAdaptertype[4] = 'A'; + case 7: + HALR->structured.autoSCSIData.uDMAChannel = 3; break; - case CHIP_BUSLOGIC_PCI: - HALR->structured.autoSCSIData.aHostAdaptertype[1] = '9'; - HALR->structured.autoSCSIData.aHostAdaptertype[2] = '5'; - HALR->structured.autoSCSIData.aHostAdaptertype[3] = '8'; - HALR->structured.autoSCSIData.aHostAdaptertype[4] = 'D'; + default: + HALR->structured.autoSCSIData.uDMAChannel = 0; break; } - HALR->structured.autoSCSIData.aHostAdaptertype[5] = ' '; + } + HALR->structured.autoSCSIData.fDMAAutoConfiguration = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 1; - HALR->structured.autoSCSIData.fLevelSensitiveInterrupt = (bl->chip == CHIP_BUSLOGIC_PCI) ? 1 : 0; - HALR->structured.autoSCSIData.uSystemRAMAreForBIOS = 6; - - if (bl->chip != CHIP_BUSLOGIC_PCI) - { - switch(bl->DmaChannel) - { - case 5: - HALR->structured.autoSCSIData.uDMAChannel = 1; - break; - case 6: - HALR->structured.autoSCSIData.uDMAChannel = 2; - break; - case 7: - HALR->structured.autoSCSIData.uDMAChannel = 3; - break; - default: - HALR->structured.autoSCSIData.uDMAChannel = 0; - break; - } + if (bl->chip != CHIP_BUSLOGIC_PCI) { + switch(dev->Irq) { + case 9: + HALR->structured.autoSCSIData.uIrqChannel = 1; + break; + case 10: + HALR->structured.autoSCSIData.uIrqChannel = 2; + break; + case 11: + HALR->structured.autoSCSIData.uIrqChannel = 3; + break; + case 12: + HALR->structured.autoSCSIData.uIrqChannel = 4; + break; + case 14: + HALR->structured.autoSCSIData.uIrqChannel = 5; + break; + case 15: + HALR->structured.autoSCSIData.uIrqChannel = 6; + break; + default: + HALR->structured.autoSCSIData.uIrqChannel = 0; + break; } - HALR->structured.autoSCSIData.fDMAAutoConfiguration = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 1; + } + HALR->structured.autoSCSIData.fIrqAutoConfiguration = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 1; - if (bl->chip != CHIP_BUSLOGIC_PCI) - { - switch(bl->Irq) - { - case 9: - HALR->structured.autoSCSIData.uIrqChannel = 1; - break; - case 10: - HALR->structured.autoSCSIData.uIrqChannel = 2; - break; - case 11: - HALR->structured.autoSCSIData.uIrqChannel = 3; - break; - case 12: - HALR->structured.autoSCSIData.uIrqChannel = 4; - break; - case 14: - HALR->structured.autoSCSIData.uIrqChannel = 5; - break; - case 15: - HALR->structured.autoSCSIData.uIrqChannel = 6; - break; - default: - HALR->structured.autoSCSIData.uIrqChannel = 0; - break; - } - } - HALR->structured.autoSCSIData.fIrqAutoConfiguration = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 1; + HALR->structured.autoSCSIData.uDMATransferRate = ((bl->chip == CHIP_BUSLOGIC_ISA_542) || (bl->chip == CHIP_BUSLOGIC_ISA)) ? 1 : 0; - HALR->structured.autoSCSIData.uDMATransferRate = (bl->chip == CHIP_BUSLOGIC_ISA) ? 1 : 0; + HALR->structured.autoSCSIData.uSCSIId = 7; + HALR->structured.autoSCSIData.uSCSIConfiguration = 0x3F; + HALR->structured.autoSCSIData.uBusOnDelay = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 7; + HALR->structured.autoSCSIData.uBusOffDelay = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 4; + HALR->structured.autoSCSIData.uBIOSConfiguration = (bl->has_bios) ? 0x33 : 0x32; + if (!safe) + HALR->structured.autoSCSIData.uBIOSConfiguration |= 0x04; - HALR->structured.autoSCSIData.uSCSIId = 7; - HALR->structured.autoSCSIData.uSCSIConfiguration = 0x3F; - HALR->structured.autoSCSIData.uBusOnDelay = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 7; - HALR->structured.autoSCSIData.uBusOffDelay = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 4; - HALR->structured.autoSCSIData.uBIOSConfiguration = (bl->has_bios) ? 0x33 : 0x32; - if (!safe) - { - HALR->structured.autoSCSIData.uBIOSConfiguration |= 0x04; - } + HALR->structured.autoSCSIData.u16DeviceEnabledMask = 0xffff; + HALR->structured.autoSCSIData.u16WidePermittedMask = 0xffff; + HALR->structured.autoSCSIData.u16FastPermittedMask = 0xffff; + HALR->structured.autoSCSIData.u16DisconnectPermittedMask = 0xffff; - HALR->structured.autoSCSIData.u16DeviceEnabledMask = 0xffff; - HALR->structured.autoSCSIData.u16WidePermittedMask = 0xffff; - HALR->structured.autoSCSIData.u16FastPermittedMask = 0xffff; - HALR->structured.autoSCSIData.u16DisconnectPermittedMask = 0xffff; + HALR->structured.autoSCSIData.uPCIInterruptPin = PCI_INTA; + HALR->structured.autoSCSIData.fVesaBusSpeedGreaterThan33MHz = 1; - HALR->structured.autoSCSIData.uPCIInterruptPin = PCI_INTA; - HALR->structured.autoSCSIData.fVesaBusSpeedGreaterThan33MHz = 1; + HALR->structured.autoSCSIData.uAutoSCSIMaximumLUN = 7; - HALR->structured.autoSCSIData.uAutoSCSIMaximumLUN = 7; - - HALR->structured.autoSCSIData.fForceBusDeviceScanningOrder = 1; - HALR->structured.autoSCSIData.fInt13Extension = safe ? 0 : 1; - HALR->structured.autoSCSIData.fCDROMBoot = safe ? 0 : 1; - HALR->structured.autoSCSIData.fMultiBoot = safe ? 0 : 1; - HALR->structured.autoSCSIData.fAggressiveRoundRobinMode = safe ? 0 : 1; /* 1 = aggressive, 0 = strict */ + HALR->structured.autoSCSIData.fForceBusDeviceScanningOrder = 1; + HALR->structured.autoSCSIData.fInt13Extension = safe ? 0 : 1; + HALR->structured.autoSCSIData.fCDROMBoot = safe ? 0 : 1; + HALR->structured.autoSCSIData.fMultiBoot = safe ? 0 : 1; + HALR->structured.autoSCSIData.fAggressiveRoundRobinMode = safe ? 0 : 1; /* 1 = aggressive, 0 = strict */ } -static void BuslogicInitializeAutoSCSIRam(Buslogic_t *bl) +static void +BuslogicInitializeAutoSCSIRam(x54x_t *dev) { + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; FILE *f; - f = nvrfopen(BuslogicGetNVRFileName(bl), L"rb"); + f = nvr_fopen(BuslogicGetNVRFileName(bl), L"rb"); if (f) { fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f); @@ -740,559 +407,169 @@ static void BuslogicInitializeAutoSCSIRam(Buslogic_t *bl) } else { - BuslogicAutoSCSIRamSetDefaults(bl, 0); + BuslogicAutoSCSIRamSetDefaults(dev, 0); } } static void -BuslogicRaiseInterrupt(Buslogic_t *bl, int suppress, uint8_t Interrupt) +buslogic_cmd_phase1(void *p) { - if (Interrupt & (INTR_MBIF | INTR_MBOA)) - { - if (!(bl->Interrupt & INTR_HACC)) - { - bl->Interrupt |= Interrupt; /* Report now. */ - } - else - { - bl->PendingInterrupt |= Interrupt; /* Report later. */ - } - } - else if (Interrupt & INTR_HACC) - { - if (bl->Interrupt == 0 || bl->Interrupt == (INTR_ANY | INTR_HACC)) - { - pclog("BuslogicRaiseInterrupt(): Interrupt=%02X\n", bl->Interrupt); - } - bl->Interrupt |= Interrupt; - } - else - { - pclog("BuslogicRaiseInterrupt(): Invalid interrupt state!\n"); - } + x54x_t *dev = (x54x_t *)p; - bl->Interrupt |= INTR_ANY; + if ((dev->CmdParam == 2) && (dev->Command == 0x90)) { + dev->CmdParamLeft = dev->CmdBuf[1]; + } - if (bl->IrqEnabled && !suppress) - { - BuslogicInterrupt(bl, 1); - } -} + if ((dev->CmdParam == 10) && ((dev->Command == 0x97) || (dev->Command == 0xA7))) { + dev->CmdParamLeft = dev->CmdBuf[6]; + dev->CmdParamLeft <<= 8; + dev->CmdParamLeft |= dev->CmdBuf[7]; + dev->CmdParamLeft <<= 8; + dev->CmdParamLeft |= dev->CmdBuf[8]; + } - -static void -BuslogicClearInterrupt(Buslogic_t *bl) -{ - /* pclog("Buslogic: Lowering Interrupt 0x%02X\n", bl->Interrupt); */ - bl->Interrupt = 0; - /* pclog("Lowering IRQ %i\n", bl->Irq); */ - BuslogicInterrupt(bl, 0); - if (bl->PendingInterrupt) { - /* pclog("Buslogic: Raising Interrupt 0x%02X (Pending)\n", bl->PendingInterrupt); */ - if (bl->MailboxOutInterrupts || !(bl->Interrupt & INTR_MBOA)) { - BuslogicRaiseInterrupt(bl, 0, bl->PendingInterrupt); - } - bl->PendingInterrupt = 0; + if ((dev->CmdParam == 4) && (dev->Command == 0xA9)) { + dev->CmdParamLeft = dev->CmdBuf[3]; + dev->CmdParamLeft <<= 8; + dev->CmdParamLeft |= dev->CmdBuf[2]; } } -static void -BuslogicReset(Buslogic_t *bl) -{ - /* pclog("BuslogicReset()\n"); */ - if (bl->evt) - { - thread_destroy_event(bl->evt); - bl->evt = NULL; - if (poll_tid) - { - thread_kill(poll_tid); - poll_tid = NULL; - } - } - - BuslogicResetCallback = 0; - bl->scan_restart = 0; - - bl->Geometry = 0x80; - bl->Status = STAT_IDLE | STAT_INIT; - bl->Command = 0xFF; - bl->CmdParam = 0; - bl->CmdParamLeft = 0; - bl->IrqEnabled = 1; - bl->ExtendedLUNCCBFormat = 0; - bl->MailboxOutPosCur = 0; - bl->MailboxInPosCur = 0; - bl->MailboxOutInterrupts = 0; - bl->PendingInterrupt = 0; - bl->Lock = 0; - - BuslogicClearInterrupt(bl); -} - - -static void -BuslogicResetControl(Buslogic_t *bl, uint8_t Reset) -{ - /* pclog("BuslogicResetControl()\n"); */ - BuslogicReset(bl); - if (Reset) { - bl->Status |= STAT_STST; - bl->Status &= ~STAT_IDLE; - } - BuslogicResetCallback = BUSLOGIC_RESET_DURATION_US * TIMER_USEC; -} - - -static void -BuslogicCommandComplete(Buslogic_t *bl, int suppress) -{ - pclog("BuslogicCommandComplete()\n"); - bl->DataReply = 0; - bl->Status |= STAT_IDLE; - - if (bl->Command != 0x02) - { - bl->Status &= ~STAT_DFULL; - - pclog("BuslogicCommandComplete(): Raising IRQ %i\n", bl->Irq); - BuslogicRaiseInterrupt(bl, suppress, INTR_HACC); - } - - bl->Command = 0xFF; - bl->CmdParam = 0; -} - - -static void -BuslogicMailboxInSetup(Buslogic_t *bl, uint32_t CCBPointer, CCBU *CmdBlock, - uint8_t HostStatus, uint8_t TargetStatus, - uint8_t MailboxCompletionCode) -{ - Req_t *req = &bl->Req; - - req->CCBPointer = CCBPointer; - memcpy(&(req->CmdBlock), CmdBlock, sizeof(CCB32)); - req->Is24bit = bl->Mbx24bit; - req->HostStatus = HostStatus; - req->TargetStatus = TargetStatus; - req->MailboxCompletionCode = MailboxCompletionCode; - - pclog("Mailbox in setup\n"); -} - - -static void -BuslogicMailboxIn(Buslogic_t *bl) -{ - Req_t *req = &bl->Req; - uint32_t CCBPointer = req->CCBPointer; - CCBU *CmdBlock = &(req->CmdBlock); - uint8_t HostStatus = req->HostStatus; - uint8_t TargetStatus = req->TargetStatus; - uint8_t MailboxCompletionCode = req->MailboxCompletionCode; - Mailbox32_t Mailbox32; - Mailbox_t MailboxIn; - uint32_t Incoming; - - Mailbox32.CCBPointer = CCBPointer; - Mailbox32.u.in.HostStatus = HostStatus; - Mailbox32.u.in.TargetStatus = TargetStatus; - Mailbox32.u.in.CompletionCode = MailboxCompletionCode; - - Incoming = bl->MailboxInAddr + (bl->MailboxInPosCur * (bl->Mbx24bit ? sizeof(Mailbox_t) : sizeof(Mailbox32_t))); - - if (MailboxCompletionCode != MBI_NOT_FOUND) { - CmdBlock->common.HostStatus = HostStatus; - CmdBlock->common.TargetStatus = TargetStatus; - - /* Rewrite the CCB up to the CDB. */ - pclog("CCB rewritten to the CDB (pointer %08X, length 18)\n", CCBPointer); - DMAPageWrite(CCBPointer, (char *)CmdBlock, 18); - } else { - pclog("Mailbox not found!\n"); - } - - pclog("Host Status 0x%02X, Target Status 0x%02X\n", - HostStatus, TargetStatus); - - if (bl->Mbx24bit) { - MailboxIn.CmdStatus = Mailbox32.u.in.CompletionCode; - U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer); - pclog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer)); - - DMAPageWrite(Incoming, (char *)&MailboxIn, sizeof(Mailbox_t)); - pclog("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); - } else { - pclog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer); - - DMAPageWrite(Incoming, (char *)&Mailbox32, sizeof(Mailbox32_t)); - pclog("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); - } - - bl->MailboxInPosCur++; - if (bl->MailboxInPosCur >= bl->MailboxCount) - bl->MailboxInPosCur = 0; - - BuslogicRaiseInterrupt(bl, 0, INTR_MBIF | INTR_ANY); - - while (bl->Interrupt) { - } -} - - -static void -BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG) -{ - uint32_t i; - SGE SGE24[MAX_SG_DESCRIPTORS]; - - if (Is24bit) { - DMAPageRead(SGList, (char *)&SGE24, Entries * sizeof(SGE)); - - for (i=0;iCmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); - } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; - } - pclog("Data Buffer write: length %d, pointer 0x%04X\n", - DataLength, DataPointer); - - if (SCSIDevices[req->TargetID][req->LUN].CmdBuffer != NULL) - { - free(SCSIDevices[req->TargetID][req->LUN].CmdBuffer); - SCSIDevices[req->TargetID][req->LUN].CmdBuffer = NULL; - } - - if ((req->CmdBlock.common.ControlByte != 0x03) && DataLength) { - if (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || - req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { - uint32_t SGRead; - uint32_t ScatterEntry; - SGE32 SGBuffer[MAX_SG_DESCRIPTORS]; - uint32_t SGLeft = DataLength / SGEntryLength; - uint32_t SGAddrCurrent = DataPointer; - uint32_t DataToTransfer = 0; - - do { - SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); - SGLeft -= SGRead; - - BuslogicReadSGEntries(Is24bit, SGAddrCurrent, SGRead, SGBuffer); - - for (ScatterEntry = 0; ScatterEntry < SGRead; ScatterEntry++) { - uint32_t Address; - - pclog("BusLogic S/G Write: ScatterEntry=%u\n", ScatterEntry); - - Address = SGBuffer[ScatterEntry].SegmentPointer; - DataToTransfer += SGBuffer[ScatterEntry].Segment; - - pclog("BusLogic S/G Write: Address=%08X DatatoTransfer=%u\n", Address, DataToTransfer); - } - - SGAddrCurrent += SGRead * SGEntryLength; - } while (SGLeft > 0); - - pclog("Data to transfer (S/G) %d\n", DataToTransfer); - - SCSIDevices[req->TargetID][req->LUN].InitLength = DataToTransfer; - - SCSIDevices[req->TargetID][req->LUN].CmdBuffer = (uint8_t *) malloc(DataToTransfer); - memset(SCSIDevices[req->TargetID][req->LUN].CmdBuffer, 0, DataToTransfer); - - /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without - checking its length, so do this procedure for both no read/write commands. */ - if ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || - (req->CmdBlock.common.ControlByte == 0x00)) { - SGLeft = DataLength / SGEntryLength; - SGAddrCurrent = DataPointer; - - do { - SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); - SGLeft -= SGRead; - - BuslogicReadSGEntries(Is24bit, SGAddrCurrent, - SGRead, SGBuffer); - - for (ScatterEntry = 0; ScatterEntry < SGRead; ScatterEntry++) { - uint32_t Address; - - pclog("BusLogic S/G Write: ScatterEntry=%u\n", ScatterEntry); - - Address = SGBuffer[ScatterEntry].SegmentPointer; - DataToTransfer = SGBuffer[ScatterEntry].Segment; - - pclog("BusLogic S/G Write: Address=%08X DatatoTransfer=%u\n", Address, DataToTransfer); - - DMAPageRead(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); - sg_buffer_pos += DataToTransfer; - } - - SGAddrCurrent += SGRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); - } while (SGLeft > 0); - } - } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || - req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { - uint32_t Address = DataPointer; - - SCSIDevices[req->TargetID][req->LUN].InitLength = DataLength; - - SCSIDevices[req->TargetID][req->LUN].CmdBuffer = (uint8_t *) malloc(DataLength); - memset(SCSIDevices[req->TargetID][req->LUN].CmdBuffer, 0, DataLength); - - if (DataLength > 0) { - DMAPageRead(Address, - (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, - SCSIDevices[req->TargetID][req->LUN].InitLength); - } - } - } -} - - -static void -BuslogicDataBufferFree(Req_t *req) -{ - uint32_t DataPointer = 0; - uint32_t DataLength = 0; - uint32_t sg_buffer_pos = 0; - uint32_t SGRead; - uint32_t ScatterEntry; - SGE32 SGBuffer[MAX_SG_DESCRIPTORS]; - uint32_t SGEntrySize; - uint32_t SGLeft; - uint32_t SGAddrCurrent; - uint32_t Address; - uint32_t Residual; - - if (req->Is24bit) { - DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); - } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; - } - - if ((DataLength != 0) && (req->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY)) { - pclog("Data length not 0 with TEST UNIT READY: %i (%i)\n", - DataLength, SCSIDevices[req->TargetID][req->LUN].InitLength); - } - - if (req->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) { - DataLength = 0; - } - - pclog("Data Buffer read: length %d, pointer 0x%04X\n", - DataLength, DataPointer); - - /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without - checking its length, so do this procedure for both read/write commands. */ - if ((DataLength > 0) && - ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || - (req->CmdBlock.common.ControlByte == 0x00))) { - if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || - (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { - SGEntrySize = (req->Is24bit ? sizeof(SGE) : sizeof(SGE32)); - SGLeft = DataLength / SGEntrySize; - SGAddrCurrent = DataPointer; - - do { - SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); - SGLeft -= SGRead; - - BuslogicReadSGEntries(req->Is24bit, SGAddrCurrent, - SGRead, SGBuffer); - - for (ScatterEntry = 0; ScatterEntry < SGRead; ScatterEntry++) { - uint32_t Address; - uint32_t DataToTransfer; - - pclog("BusLogic S/G: ScatterEntry=%u\n", ScatterEntry); - - Address = SGBuffer[ScatterEntry].SegmentPointer; - DataToTransfer = SGBuffer[ScatterEntry].Segment; - - pclog("BusLogic S/G: Writing %i bytes at %08X\n", DataToTransfer, Address); - - DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); - sg_buffer_pos += DataToTransfer; - } - - SGAddrCurrent += (SGRead * SGEntrySize); - } while (SGLeft > 0); - } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || - req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { - Address = DataPointer; - - pclog("BusLogic DMA: Writing %i bytes at %08X\n", DataLength, Address); - DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, DataLength); - } - } - - if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || - (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { - /* Should be 0 when scatter/gather? */ - if (DataLength >= SCSIDevices[req->TargetID][req->LUN].InitLength) { - Residual = DataLength; - Residual -= SCSIDevices[req->TargetID][req->LUN].InitLength; - } else { - Residual = 0; - } - - if (req->Is24bit) { - U32_TO_ADDR(req->CmdBlock.old.DataLength, Residual); - pclog("24-bit Residual data length for reading: %d\n", - ADDR_TO_U32(req->CmdBlock.old.DataLength)); - } else { - req->CmdBlock.new.DataLength = Residual; - pclog("32-bit Residual data length for reading: %d\n", - req->CmdBlock.new.DataLength); - } - } - - if (SCSIDevices[req->TargetID][req->LUN].CmdBuffer != NULL) - { - free(SCSIDevices[req->TargetID][req->LUN].CmdBuffer); - SCSIDevices[req->TargetID][req->LUN].CmdBuffer = NULL; - } -} static uint8_t -BuslogicConvertSenseLength(uint8_t RequestSenseLength) +buslogic_get_host_id(void *p) { - pclog("Unconverted Request Sense length %i\n", RequestSenseLength); + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - if (RequestSenseLength == 0) - RequestSenseLength = 14; - else if (RequestSenseLength == 1) - RequestSenseLength = 0; + HALocalRAM *HALR = &bl->LocalRAM; - pclog("Request Sense length %i\n", RequestSenseLength); - - return(RequestSenseLength); + if (bl->chip == CHIP_BUSLOGIC_ISA_542) + return dev->HostID; + else + return HALR->structured.autoSCSIData.uSCSIId; } -static void -BuslogicSCSIBIOSDataBufferAllocate(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN) +static uint8_t +buslogic_get_irq(void *p) { - uint32_t DataPointer, DataLength; - - DataPointer = ESCSICmd->DataPointer; - DataLength = ESCSICmd->DataLength; + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - pclog("BIOS Data Buffer write: length %d, pointer 0x%04X\n", - DataLength, DataPointer); + uint8_t bl_irq[7] = { 0, 9, 10, 11, 12, 14, 15 }; - if (SCSIDevices[TargetID][LUN].CmdBuffer != NULL) - { - free(SCSIDevices[TargetID][LUN].CmdBuffer); - SCSIDevices[TargetID][LUN].CmdBuffer = NULL; + HALocalRAM *HALR = &bl->LocalRAM; + + if (bl->chip == CHIP_BUSLOGIC_PCI) + return dev->Irq; + else + return bl_irq[HALR->structured.autoSCSIData.uIrqChannel]; +} + + +static uint8_t +buslogic_get_dma(void *p) +{ + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + + uint8_t bl_dma[4] = { 0, 5, 6, 7 }; + + HALocalRAM *HALR = &bl->LocalRAM; + + if (bl->chip == CHIP_BUSLOGIC_PCI) + return dev->DmaChannel; + else + return bl_dma[HALR->structured.autoSCSIData.uDMAChannel]; +} + + +static uint8_t +buslogic_param_len(void *p) +{ + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + + switch (dev->Command) { + case 0x21: + return 5; + case 0x25: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8F: + case 0x92: + case 0x96: + return 1; + case 0x81: + return sizeof(MailboxInitExtended_t); + case 0x83: + return 12; + case 0x90: + case 0x91: + return 2; + case 0x94: + return 3; + case 0x95: /* Valid only for PCI */ + return (bl->chip == CHIP_BUSLOGIC_PCI) ? 1 : 0; + case 0x97: /* Valid only for PCI */ + case 0xA7: /* Valid only for PCI */ + return (bl->chip == CHIP_BUSLOGIC_PCI) ? 10 : 0; + case 0xA8: /* Valid only for PCI */ + case 0xA9: /* Valid only for PCI */ + return (bl->chip == CHIP_BUSLOGIC_PCI) ? 4 : 0; + default: + return 0; } - - if ((ESCSICmd->DataDirection != 0x03) && DataLength) - { - uint32_t Address = DataPointer; - - SCSIDevices[TargetID][LUN].InitLength = DataLength; - - SCSIDevices[TargetID][LUN].CmdBuffer = (uint8_t *) malloc(DataLength); - memset(SCSIDevices[TargetID][LUN].CmdBuffer, 0, DataLength); - - if (DataLength > 0) { - DMAPageRead(Address, - (char *)SCSIDevices[TargetID][LUN].CmdBuffer, - SCSIDevices[TargetID][LUN].InitLength); - } - } } + static void -BuslogicSCSIBIOSDataBufferFree(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN) +BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN, int dir) { - uint32_t DataPointer = 0; - uint32_t DataLength = 0; + uint32_t DataPointer = ESCSICmd->DataPointer; + uint32_t DataLength = ESCSICmd->DataLength; uint32_t Address; - uint32_t Residual; + uint32_t TransferLength; - DataPointer = ESCSICmd->DataPointer; - DataLength = ESCSICmd->DataLength; - - if ((DataLength != 0) && (ESCSICmd->CDB[0] == GPCMD_TEST_UNIT_READY)) { - pclog("Data length not 0 with TEST UNIT READY: %i (%i)\n", - DataLength, SCSIDevices[TargetID][LUN].InitLength); + if (ESCSICmd->DataDirection == 0x03) { + /* Non-data command. */ + buslogic_log("BuslogicSCSIBIOSDMATransfer(): Non-data control byte\n"); + return; } - if (ESCSICmd->CDB[0] == GPCMD_TEST_UNIT_READY) { - DataLength = 0; - } - - pclog("BIOS Data Buffer read: length %d, pointer 0x%04X\n", - DataLength, DataPointer); + buslogic_log("BuslogicSCSIBIOSDMATransfer(): BIOS Data Buffer read: length %d, pointer 0x%04X\n", DataLength, DataPointer); /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without checking its length, so do this procedure for both read/write commands. */ - if ((DataLength > 0) && - ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || - (ESCSICmd->DataDirection == 0x00))) - { - Address = DataPointer; + if ((DataLength > 0) && (SCSIDevices[TargetID][LUN].BufferLength > 0)) { + Address = DataPointer; + TransferLength = MIN(DataLength, SCSIDevices[TargetID][LUN].BufferLength); - pclog("BusLogic BIOS DMA: Writing %i bytes at %08X\n", DataLength, Address); - DMAPageWrite(Address, (char *)SCSIDevices[TargetID][LUN].CmdBuffer, DataLength); - } - - /* Should be 0 when scatter/gather? */ - if (DataLength >= SCSIDevices[TargetID][LUN].InitLength) { - Residual = DataLength; - Residual -= SCSIDevices[TargetID][LUN].InitLength; - } else { - Residual = 0; + if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) { + buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); + DMAPageRead(Address, (char *)SCSIDevices[TargetID][LUN].CmdBuffer, TransferLength); + } else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) { + buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); + DMAPageWrite(Address, (char *)SCSIDevices[TargetID][LUN].CmdBuffer, TransferLength); } - - ESCSICmd->DataLength = Residual; - pclog("BIOS Residual data length for reading: %d\n", - ESCSICmd->DataLength); - - if (SCSIDevices[TargetID][LUN].CmdBuffer != NULL) - { - free(SCSIDevices[TargetID][LUN].CmdBuffer); - SCSIDevices[TargetID][LUN].CmdBuffer = NULL; } } -static void -BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t DataReply) -{ - ESCMD *ESCSICmd = (ESCMD *)CmdBuf; - uint32_t i; - uint8_t temp_cdb[12]; - int target_cdb_len = 12; - uint8_t target_id = 0; - DataInBuf[0] = DataInBuf[1] = 0; +static void +BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t DataReply) +{ + ESCMD *ESCSICmd = (ESCMD *)CmdBuf; + uint32_t i; + uint8_t temp_cdb[12]; + int target_cdb_len = 12; + uint8_t target_id = 0; + int phase; + + DataInBuf[0] = DataInBuf[1] = 0; if ((ESCSICmd->TargetId > 15) || (ESCSICmd->LogicalUnit > 7)) { DataInBuf[2] = CCB_INVALID_CCB; @@ -1300,39 +577,36 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf return; } - pclog("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); + buslogic_log("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); SCSIStatus = SCSI_STATUS_OK; - SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].InitLength = 0; - - BuslogicSCSIBIOSDataBufferAllocate(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); if (!scsi_device_present(ESCSICmd->TargetId, ESCSICmd->LogicalUnit)) { - pclog("SCSI Target ID %i and LUN %i have no device attached\n",ESCSICmd->TargetId,ESCSICmd->LogicalUnit); - BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - /* BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, 0, 0); */ + buslogic_log("SCSI Target ID %i and LUN %i have no device attached\n",ESCSICmd->TargetId,ESCSICmd->LogicalUnit); DataInBuf[2] = CCB_SELECTION_TIMEOUT; DataInBuf[3] = SCSI_STATUS_OK; } else { - pclog("SCSI Target ID %i and LUN %i detected and working\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + buslogic_log("SCSI Target ID %i and LUN %i detected and working\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - pclog("Transfer Control %02X\n", ESCSICmd->DataDirection); - pclog("CDB Length %i\n", ESCSICmd->CDBLength); + buslogic_log("Transfer Control %02X\n", ESCSICmd->DataDirection); + buslogic_log("CDB Length %i\n", ESCSICmd->CDBLength); if (ESCSICmd->DataDirection > 0x03) { - pclog("Invalid control byte: %02X\n", + buslogic_log("Invalid control byte: %02X\n", ESCSICmd->DataDirection); } } + x54x_buf_alloc(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->DataLength); + target_cdb_len = scsi_device_cdb_length(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); if (!scsi_device_valid(ESCSICmd->TargetId, ESCSICmd->LogicalUnit)) fatal("SCSI target on %02i:%02i has disappeared\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - pclog("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i, Target %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, target_id); + buslogic_log("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i, Target %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, target_id); - pclog("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); + buslogic_log("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); for (i = 1; i < ESCSICmd->CDBLength; i++) { - pclog("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); + buslogic_log("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); } memset(temp_cdb, 0, target_cdb_len); @@ -1342,12 +616,21 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf memcpy(temp_cdb, ESCSICmd->CDB, target_cdb_len); } - scsi_device_command(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->CDBLength, temp_cdb); + SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].BufferLength = ESCSICmd->DataLength; + scsi_device_command_phase0(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->CDBLength, temp_cdb); - BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - /* BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, (SCSIStatus != SCSI_STATUS_OK), 1); */ + phase = SCSIPhase; + if (phase != SCSI_PHASE_STATUS) { + if (phase == SCSI_PHASE_DATA_IN) + scsi_device_command_phase1(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + BuslogicSCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit, (phase == SCSI_PHASE_DATA_OUT)); + if (phase == SCSI_PHASE_DATA_OUT) + scsi_device_command_phase1(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + } - pclog("BIOS Request complete\n"); + x54x_buf_free(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + + buslogic_log("BIOS Request complete\n"); if (SCSIStatus == SCSI_STATUS_OK) { DataInBuf[2] = CCB_COMPLETE; @@ -1356,1261 +639,401 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf DataInBuf[2] = CCB_COMPLETE; DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; } - - bl->DataReplyLeft = DataReply; -} -static uint8_t -BuslogicRead(uint16_t Port, void *p) -{ - Buslogic_t *bl = (Buslogic_t *)p; - uint8_t Temp; - - switch (Port & 3) { - case 0: - default: - Temp = bl->Status; - break; - - case 1: - Temp = bl->DataBuf[bl->DataReply]; - if (bl->DataReplyLeft) - { - bl->DataReply++; - bl->DataReplyLeft--; - if (!bl->DataReplyLeft) { - BuslogicCommandComplete(bl, 0); - } - } - break; - - case 2: - Temp = bl->Interrupt; - break; - - case 3: - Temp = bl->Geometry; - break; - } - - /* if (Port < 0x1000) { */ - if (Port & 3) { - pclog("Buslogic: Read Port 0x%02X, Returned Value %02X\n", - Port, Temp); - } - - return(Temp); -} - - -static uint16_t -BuslogicReadW(uint16_t Port, void *p) -{ - return BuslogicRead(Port, p); -} - - -static uint32_t -BuslogicReadL(uint16_t Port, void *p) -{ - return BuslogicRead(Port, p); + dev->DataReplyLeft = DataReply; } static uint8_t -BuslogicMemRead(uint32_t addr, void *p) +buslogic_cmds(void *p) { - pclog("BuslogicMemRead(%08X, %08X)\n", addr, p); - return BuslogicRead(addr & 3, p); -} + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - -static uint16_t -BuslogicMemReadW(uint32_t addr, void *p) -{ - pclog("BuslogicMemReadW(%08X, %08X)\n", addr, p); - return BuslogicReadW(addr & 3, p); -} - -static uint32_t -BuslogicMemReadL(uint32_t addr, void *p) -{ - pclog("BuslogicMemReadL(%08X, %08X)\n", addr, p); - return BuslogicReadL(addr & 3, p); -} - - -static void BuslogicWriteW(uint16_t Port, uint16_t Val, void *p); -static void BuslogicWriteL(uint16_t Port, uint32_t Val, void *p); -static void -BuslogicWrite(uint16_t Port, uint8_t Val, void *p) -{ - int i = 0; - uint8_t j = 0; - Buslogic_t *bl = (Buslogic_t *)p; + FILE *f; + uint16_t TargetsPresentMask = 0; uint8_t Offset; - MailboxInit_t *MailboxInit; - BIOSCMD *BiosCmd; - ReplyInquireSetupInformation *ReplyISI; + int i = 0; + int j = 0; MailboxInitExtended_t *MailboxInitE; ReplyInquireExtendedSetupInformation *ReplyIESI; BuslogicPCIInformation_t *ReplyPI; - char aModelName[] = "542B "; /* Trailing \0 is fine, that's the filler anyway. */ int cCharsToTransfer; - int suppress = 0; - uint16_t cyl = 0; - FILE *f; - pclog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val); - - switch (Port & 3) - { - case 0: - if ((Val & CTRL_HRST) || (Val & CTRL_SRST)) - { - uint8_t Reset = (Val & CTRL_HRST); - BuslogicResetControl(bl, Reset); - break; - } - - if (Val & CTRL_IRST) { - BuslogicClearInterrupt(bl); - } + switch (dev->Command) { + case 0x20: + dev->DataReplyLeft = 0; + x54x_reset_ctrl(dev, 1); break; - - case 1: - /* Fast path for the mailbox execution command. */ - if ((Val == 0x02) && (bl->Command == 0xFF)) { - /* If there are no mailboxes configured, don't even try to do anything. */ - if (bl->MailboxCount) { - if (!poll_tid) { - pclog("Buslogic: starting thread..\n"); - poll_tid = thread_create(BuslogicCommandThread, bl); - bl->scan_restart = 0; - } - else { - bl->scan_restart = bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode ? 0 : 1; - } - } - return; + case 0x21: + if (dev->CmdParam == 1) + dev->CmdParamLeft = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + break; + case 0x23: + memset(dev->DataBuf, 0, 8); + for (i = 8; i < 15; i++) { + dev->DataBuf[i-8] = 0; + for (j=0; j<8; j++) { + if (scsi_device_present(i, j) && (i != buslogic_get_host_id(dev))) + dev->DataBuf[i-8] |= (1<DataReplyLeft = 8; + break; + case 0x24: + for (i=0; i<15; i++) { + if (scsi_device_present(i, 0) && (i != buslogic_get_host_id(dev))) + TargetsPresentMask |= (1 << i); + } + dev->DataBuf[0] = TargetsPresentMask & 0xFF; + dev->DataBuf[1] = TargetsPresentMask >> 8; + dev->DataReplyLeft = 2; + break; + case 0x25: + if (dev->CmdBuf[0] == 0) + dev->IrqEnabled = 0; + else + dev->IrqEnabled = 1; + return 1; + case 0x81: + x54x_busy_set(); + dev->Mbx24bit = 0; - if (bl->Command == 0xFF) { - bl->Command = Val; - bl->CmdParam = 0; - bl->CmdParamLeft = 0; - - bl->Status &= ~(STAT_INVCMD | STAT_IDLE); - pclog("Buslogic: Operation Code 0x%02X\n", Val); - switch (bl->Command) { - case 0x01: - bl->CmdParamLeft = sizeof(MailboxInit_t); - break; + MailboxInitE = (MailboxInitExtended_t *)dev->CmdBuf; - case 0x03: - bl->CmdParamLeft = 10; - break; - - case 0x25: - bl->CmdParamLeft = 1; - break; + dev->MailboxInit = 1; + dev->MailboxCount = MailboxInitE->Count; + dev->MailboxOutAddr = MailboxInitE->Address; + dev->MailboxInAddr = MailboxInitE->Address + (dev->MailboxCount * sizeof(Mailbox32_t)); - case 0x05: - case 0x07: - case 0x08: - case 0x09: - case 0x0D: - case 0x1F: - bl->CmdParamLeft = 1; - break; - - case 0x21: - bl->CmdParamLeft = 5; - break; + buslogic_log("Buslogic Extended Initialize Mailbox Command\n"); + buslogic_log("Mailbox Out Address=0x%08X\n", dev->MailboxOutAddr); + buslogic_log("Mailbox In Address=0x%08X\n", dev->MailboxInAddr); + buslogic_log("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInitE->Count, MailboxInitE->Address); - case 0x1A: - case 0x1B: - bl->CmdParamLeft = 3; - break; - - case 0x06: - bl->CmdParamLeft = 4; - break; - - case 0x8B: - case 0x8D: - case 0x8F: - case 0x96: - bl->CmdParamLeft = 1; - break; - - case 0x81: - bl->CmdParamLeft = sizeof(MailboxInitExtended_t); - break; - - case 0x83: - bl->CmdParamLeft = 12; - break; - - case 0x8C: - bl->CmdParamLeft = 1; - break; - - case 0x90: - bl->CmdParamLeft = 2; - break; - - case 0x91: - bl->CmdParamLeft = 2; - break; - - case 0x92: - bl->CmdParamLeft = 1; - break; - - case 0x94: - bl->CmdParamLeft = 3; - break; - - case 0x95: /* Valid only for PCI */ - bl->CmdParamLeft = (bl->chip == CHIP_BUSLOGIC_PCI) ? 1 : 0; - break; - - case 0x97: /* Valid only for PCI */ - case 0xA7: /* Valid only for PCI */ - bl->CmdParamLeft = (bl->chip == CHIP_BUSLOGIC_PCI) ? 10 : 0; - - case 0xA8: /* Valid only for PCI */ - case 0xA9: /* Valid only for PCI */ - bl->CmdParamLeft = (bl->chip == CHIP_BUSLOGIC_PCI) ? 4 : 0; - break; - } + dev->Status &= ~STAT_INIT; + dev->DataReplyLeft = 0; + x54x_busy_clear(); + break; + case 0x83: + if (dev->CmdParam == 12) { + dev->CmdParamLeft = dev->CmdBuf[11]; + buslogic_log("Execute SCSI BIOS Command: %u more bytes follow\n", dev->CmdParamLeft); } else { - bl->CmdBuf[bl->CmdParam] = Val; - bl->CmdParam++; - bl->CmdParamLeft--; - - if ((bl->CmdParam == 2) && (bl->Command == 0x90)) - { - bl->CmdParamLeft = bl->CmdBuf[1]; - } - - if ((bl->CmdParam == 10) && ((bl->Command == 0x97) || (bl->Command == 0xA7))) - { - bl->CmdParamLeft = bl->CmdBuf[6]; - bl->CmdParamLeft <<= 8; - bl->CmdParamLeft |= bl->CmdBuf[7]; - bl->CmdParamLeft <<= 8; - bl->CmdParamLeft |= bl->CmdBuf[8]; - } - - if ((bl->CmdParam == 4) && (bl->Command == 0xA9)) - { - bl->CmdParamLeft = bl->CmdBuf[3]; - bl->CmdParamLeft <<= 8; - bl->CmdParamLeft |= bl->CmdBuf[2]; - } - } - - if (!bl->CmdParamLeft) - { - pclog("Running Operation Code 0x%02X\n", bl->Command); - bl->DataReply = 0; - switch (bl->Command) { - case 0x00: - bl->DataReplyLeft = 0; - break; - - case 0x01: - bl->Mbx24bit = 1; - - MailboxInit = (MailboxInit_t *)bl->CmdBuf; - - bl->MailboxCount = MailboxInit->Count; - bl->MailboxOutAddr = ADDR_TO_U32(MailboxInit->Address); - bl->MailboxInAddr = bl->MailboxOutAddr + (bl->MailboxCount * sizeof(Mailbox_t)); - - pclog("Buslogic Initialize Mailbox Command\n"); - pclog("Mailbox Out Address=0x%08X\n", bl->MailboxOutAddr); - pclog("Mailbox In Address=0x%08X\n", bl->MailboxInAddr); - pclog("Initialized Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, ADDR_TO_U32(MailboxInit->Address)); - - bl->Status &= ~STAT_INIT; - bl->DataReplyLeft = 0; - break; - - case 0x03: - BiosCmd = (BIOSCMD *)bl->CmdBuf; - - if (bl->chip != CHIP_BUSLOGIC_MCA) { - cyl = ((BiosCmd->u.chs.cyl & 0xff) << 8) | ((BiosCmd->u.chs.cyl >> 8) & 0xff); - BiosCmd->u.chs.cyl = cyl; - } - - if (bl->chip == CHIP_BUSLOGIC_MCA) { - pclog("BIOS LBA=%06lx (%lu)\n", - lba32_blk(BiosCmd), - lba32_blk(BiosCmd)); - } else { - BiosCmd->u.chs.head &= 0xf; - BiosCmd->u.chs.sec &= 0x1f; - pclog("BIOS CHS=%04X/%02X%02X\n", - BiosCmd->u.chs.cyl, - BiosCmd->u.chs.head, - BiosCmd->u.chs.sec); - } - - BiosCmd->u.chs.cyl = cyl; - BiosCmd->u.chs.head &= 0x0f; - BiosCmd->u.chs.sec &= 0x1f; - pclog("C: %04X, H: %02X, S: %02X\n", BiosCmd->u.chs.cyl, BiosCmd->u.chs.head, BiosCmd->u.chs.sec); - bl->DataBuf[0] = scsi_bios_command(15, BiosCmd, (bl->chip == CHIP_BUSLOGIC_MCA) ? 1 : 0); - pclog("BIOS Completion/Status Code %x\n", bl->DataBuf[0]); - bl->DataReplyLeft = 1; - break; - - case 0x04: - pclog("Inquire Board\n"); - bl->DataBuf[0] = (bl->chip == CHIP_BUSLOGIC_MCA) ? 0x42 : 0x41; - bl->DataBuf[1] = 0x41; - bl->DataBuf[2] = (bl->chip == CHIP_BUSLOGIC_PCI) ? '5' : '4'; - bl->DataBuf[3] = (bl->chip == CHIP_BUSLOGIC_PCI) ? '0' : '2'; - bl->DataReplyLeft = 4; - break; - - case 0x05: - if (bl->CmdBuf[0] <= 1) { - bl->MailboxOutInterrupts = bl->CmdBuf[0]; - pclog("Mailbox out interrupts: %s\n", bl->MailboxOutInterrupts ? "ON" : "OFF"); - suppress = 1; - } else { - bl->Status |= STAT_INVCMD; - } - bl->DataReplyLeft = 0; - break; - - case 0x06: - pclog("Selection Time-Out\n"); - bl->DataReplyLeft = 0; - break; - - case 0x07: - bl->DataReplyLeft = 0; - bl->LocalRAM.structured.autoSCSIData.uBusOnDelay = bl->CmdBuf[0]; - pclog("Bus-on time: %d\n", bl->CmdBuf[0]); - break; - - case 0x08: - bl->DataReplyLeft = 0; - bl->LocalRAM.structured.autoSCSIData.uBusOffDelay = bl->CmdBuf[0]; - pclog("Bus-off time: %d\n", bl->CmdBuf[0]); - break; - - case 0x09: - bl->DataReplyLeft = 0; - bl->LocalRAM.structured.autoSCSIData.uDMATransferRate = bl->CmdBuf[0]; - pclog("DMA transfer rate: %02X\n", bl->CmdBuf[0]); - break; - - case 0x0A: - memset(bl->DataBuf, 0, 8); - for (i=0; i<8; i++) { - bl->DataBuf[i] = 0; - for (j=0; j<8; j++) { - if (scsi_device_present(i, j) && (i != bl->LocalRAM.structured.autoSCSIData.uSCSIId)) - bl->DataBuf[i] |= (1 << j); - } - } - bl->DataReplyLeft = 8; - break; - - case 0x0B: - pclog("Inquire Configuration\n"); - bl->DataBuf[0] = (1 << bl->DmaChannel); - if ((bl->Irq >= 9) && (bl->Irq <= 15)) - { - bl->DataBuf[1] = (1<<(bl->Irq-9)); - } - else - bl->DataBuf[1] = 0; - { - } - bl->DataBuf[2] = bl->LocalRAM.structured.autoSCSIData.uSCSIId; /* HOST ID */ - bl->DataReplyLeft = 3; - break; - - case 0x0D: - { - bl->DataReplyLeft = bl->CmdBuf[0]; - - ReplyISI = (ReplyInquireSetupInformation *)bl->DataBuf; - memset(ReplyISI, 0, sizeof(ReplyInquireSetupInformation)); - - ReplyISI->fSynchronousInitiationEnabled = 1; - ReplyISI->fParityCheckingEnabled = 1; - ReplyISI->cMailbox = bl->MailboxCount; - U32_TO_ADDR(ReplyISI->MailboxAddress, bl->MailboxOutAddr); - - ReplyISI->uSignature = 'B'; - /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too - * friendly with Adaptec hardware and upsetting the HBA state. - */ - ReplyISI->uCharacterD = 'D'; /* BusLogic model. */ - switch(bl->chip) - { - case CHIP_BUSLOGIC_ISA: - ReplyISI->uHostBusType = 'A'; - break; - case CHIP_BUSLOGIC_MCA: - ReplyISI->uHostBusType = 'B'; - break; - case CHIP_BUSLOGIC_VLB: - ReplyISI->uHostBusType = 'E'; - break; - case CHIP_BUSLOGIC_PCI: - ReplyISI->uHostBusType = 'F'; - break; - } - - pclog("Return Setup Information: %d\n", bl->CmdBuf[0]); - } - break; - - case 0x1A: - { - uint32_t FIFOBuf; - addr24 Address; - - bl->DataReplyLeft = 0; - Address.hi = bl->CmdBuf[0]; - Address.mid = bl->CmdBuf[1]; - Address.lo = bl->CmdBuf[2]; - FIFOBuf = ADDR_TO_U32(Address); - pclog("Buslogic LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); - DMAPageRead(FIFOBuf, (char *)bl->LocalRAM.u8View, 64); - } - break; - - case 0x1B: - { - uint32_t FIFOBuf; - addr24 Address; - - bl->DataReplyLeft = 0; - Address.hi = bl->CmdBuf[0]; - Address.mid = bl->CmdBuf[1]; - Address.lo = bl->CmdBuf[2]; - FIFOBuf = ADDR_TO_U32(Address); - pclog("Buslogic LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); - DMAPageWrite(FIFOBuf, (char *)bl->LocalRAM.u8View, 64); - } - break; - - case 0x1F: - bl->DataBuf[0] = bl->CmdBuf[0]; - bl->DataReplyLeft = 1; - break; - - case 0x20: - bl->DataReplyLeft = 0; - BuslogicResetControl(bl, 1); - break; - - case 0x21: - if (bl->CmdParam == 1) - bl->CmdParamLeft = bl->CmdBuf[0]; - bl->DataReplyLeft = 0; - break; - - case 0x23: - memset(bl->DataBuf, 0, 8); - for (i = 8; i < 15; i++) { - bl->DataBuf[i-8] = 0; - for (j=0; j<8; j++) { - if (scsi_device_present(i, j) && (i != bl->LocalRAM.structured.autoSCSIData.uSCSIId)) - bl->DataBuf[i-8] |= (1<DataReplyLeft = 8; - break; - - case 0x24: - { - uint16_t TargetsPresentMask = 0; - - for (i=0; i<15; i++) { - if (scsi_device_present(i, 0) && (i != bl->LocalRAM.structured.autoSCSIData.uSCSIId)) - TargetsPresentMask |= (1 << i); - } - bl->DataBuf[0] = TargetsPresentMask & 0xFF; - bl->DataBuf[1] = TargetsPresentMask >> 8; - bl->DataReplyLeft = 2; - } - break; - - case 0x25: - if (bl->CmdBuf[0] == 0) - bl->IrqEnabled = 0; - else - bl->IrqEnabled = 1; - /* pclog("Lowering IRQ %i\n", bl->Irq); - BuslogicInterrupt(bl, 0); */ - suppress = 1; - break; - - case 0x81: - { - bl->Mbx24bit = 0; - - MailboxInitE = (MailboxInitExtended_t *)bl->CmdBuf; - - bl->MailboxCount = MailboxInitE->Count; - bl->MailboxOutAddr = MailboxInitE->Address; - bl->MailboxInAddr = MailboxInitE->Address + (bl->MailboxCount * sizeof(Mailbox32_t)); - - pclog("Buslogic Extended Initialize Mailbox Command\n"); - pclog("Mailbox Out Address=0x%08X\n", bl->MailboxOutAddr); - pclog("Mailbox In Address=0x%08X\n", bl->MailboxInAddr); - pclog("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInitE->Count, MailboxInitE->Address); - - bl->Status &= ~STAT_INIT; - bl->DataReplyLeft = 0; - } - break; - - case 0x83: - if (bl->CmdParam == 12) - { - bl->CmdParamLeft = bl->CmdBuf[11]; - pclog("Execute SCSI BIOS Command: %u more bytes follow\n", bl->CmdParamLeft); - } - else - { - pclog("Execute SCSI BIOS Command: received %u bytes\n", bl->CmdBuf[0]); - BuslogicSCSIBIOSRequestSetup(bl, bl->CmdBuf, bl->DataBuf, 4); - } - break; - - case 0x84: - bl->DataBuf[0] = (bl->chip == CHIP_BUSLOGIC_PCI) ? '7' : '1'; - bl->DataReplyLeft = 1; - break; - - case 0x85: - bl->DataBuf[0] = (bl->chip == CHIP_BUSLOGIC_PCI) ? 'B' : 'E'; - bl->DataReplyLeft = 1; - break; - - case 0x86: - if (bl->chip == CHIP_BUSLOGIC_PCI) - { - ReplyPI = (BuslogicPCIInformation_t *) bl->DataBuf; - memset(ReplyPI, 0, sizeof(BuslogicPCIInformation_t)); - ReplyPI->InformationIsValid = 0; - switch(bl->Base) - { - case 0x330: - ReplyPI->IsaIOPort = 0; - break; - case 0x334: - ReplyPI->IsaIOPort = 1; - break; - case 0x230: - ReplyPI->IsaIOPort = 2; - break; - case 0x234: - ReplyPI->IsaIOPort = 3; - break; - case 0x130: - ReplyPI->IsaIOPort = 4; - break; - case 0x134: - ReplyPI->IsaIOPort = 5; - break; - default: - ReplyPI->IsaIOPort = 0xFF; - break; - } - ReplyPI->IRQ = bl->Irq; - bl->DataReplyLeft = sizeof(BuslogicPCIInformation_t); - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; - - case 0x8B: - { - /* The reply length is set by the guest and is found in the first byte of the command buffer. */ - bl->DataReplyLeft = bl->CmdBuf[0]; - memset(bl->DataBuf, 0, bl->DataReplyLeft); - switch(bl->chip) - { - case CHIP_BUSLOGIC_ISA: - aModelName[0] = '5'; - aModelName[1] = '4'; - aModelName[2] = '5'; - aModelName[3] = 'C'; - break; - case CHIP_BUSLOGIC_MCA: - aModelName[0] = '6'; - aModelName[1] = '4'; - aModelName[2] = '0'; - aModelName[3] = 'A'; - break; - case CHIP_BUSLOGIC_VLB: - aModelName[0] = '4'; - aModelName[1] = '4'; - aModelName[2] = '5'; - aModelName[3] = 'S'; - break; - case CHIP_BUSLOGIC_PCI: - aModelName[0] = '9'; - aModelName[1] = '5'; - aModelName[2] = '8'; - aModelName[3] = 'D'; - break; - } - cCharsToTransfer = bl->DataReplyLeft <= sizeof(aModelName) - ? bl->DataReplyLeft - : sizeof(aModelName); - - for (i = 0; i < cCharsToTransfer; i++) - bl->DataBuf[i] = aModelName[i]; - - pclog("Model Name\n"); - pclog("Buffer 0: %x\n", bl->DataBuf[0]); - pclog("Buffer 1: %x\n", bl->DataBuf[1]); - pclog("Buffer 2: %x\n", bl->DataBuf[2]); - pclog("Buffer 3: %x\n", bl->DataBuf[3]); - pclog("Buffer 4: %x\n", bl->DataBuf[4]); - } - break; - - case 0x8C: - bl->DataReplyLeft = bl->CmdBuf[0]; - memset(bl->DataBuf, 0, bl->DataReplyLeft); - break; - - case 0x8D: - bl->DataReplyLeft = bl->CmdBuf[0]; - ReplyIESI = (ReplyInquireExtendedSetupInformation *)bl->DataBuf; - memset(ReplyIESI, 0, sizeof(ReplyInquireExtendedSetupInformation)); - - switch (bl->chip) - { - case CHIP_BUSLOGIC_ISA: - case CHIP_BUSLOGIC_VLB: - ReplyIESI->uBusType = 'A'; /* ISA style */ - break; - case CHIP_BUSLOGIC_MCA: - ReplyIESI->uBusType = 'M'; /* MCA style */ - break; - case CHIP_BUSLOGIC_PCI: - ReplyIESI->uBusType = 'E'; /* PCI style */ - break; - } - ReplyIESI->uBiosAddress = 0xd8; - ReplyIESI->u16ScatterGatherLimit = 8192; - ReplyIESI->cMailbox = bl->MailboxCount; - ReplyIESI->uMailboxAddressBase = bl->MailboxOutAddr; - ReplyIESI->fHostWideSCSI = 1; /* This should be set for the BT-542B as well. */ - ReplyIESI->fLevelSensitiveInterrupt = bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; - if (bl->chip == CHIP_BUSLOGIC_PCI) { - ReplyIESI->fHostUltraSCSI = 1; - } - memcpy(ReplyIESI->aFirmwareRevision, (bl->chip == CHIP_BUSLOGIC_PCI) ? "07B" : "21E", sizeof(ReplyIESI->aFirmwareRevision)); - pclog("Return Extended Setup Information: %d\n", bl->CmdBuf[0]); - break; - - /* VirtualBox has these two modes implemented in reverse. - According to the BusLogic datasheet: - 0 is the strict round robin mode, which is also the one used by the AHA-154x according to the - Adaptec specification; - 1 is the aggressive round robin mode, which "hunts" for an active outgoing mailbox and then - processes it. */ - case 0x8F: - bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode = bl->CmdBuf[0] & 1; - - bl->DataReplyLeft = 0; - break; - - case 0x90: - pclog("Store Local RAM\n"); - Offset = bl->CmdBuf[0]; - bl->DataReplyLeft = 0; - memcpy(&(bl->LocalRAM.u8View[Offset]), &(bl->CmdBuf[2]), bl->CmdBuf[1]); - - bl->DataReply = 0; - break; - - case 0x91: - pclog("Fetch Local RAM\n"); - Offset = bl->CmdBuf[0]; - bl->DataReplyLeft = bl->CmdBuf[1]; - memcpy(bl->DataBuf, &(bl->LocalRAM.u8View[Offset]), bl->CmdBuf[1]); - - bl->DataReply = 0; - break; - - case 0x92: - bl->DataReplyLeft = 0; - - switch (bl->CmdBuf[0]) - { - case 0: - case 2: - BuslogicAutoSCSIRamSetDefaults(bl, 0); - break; - case 3: - BuslogicAutoSCSIRamSetDefaults(bl, 3); - break; - case 1: - f = nvrfopen(BuslogicGetNVRFileName(bl), L"wb"); - if (f) - { - fwrite(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f); - fclose(f); - f = NULL; - } - break; - default: - bl->Status |= STAT_INVCMD; - break; - } - break; - - case 0x94: - if (bl->CmdBuf[0]) - { - pclog("Invalid AutoSCSI command mode %x\n", bl->CmdBuf[0]); - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - else - { - bl->DataReplyLeft = bl->CmdBuf[2]; - bl->DataReplyLeft <<= 8; - bl->DataReplyLeft |= bl->CmdBuf[1]; - memcpy(bl->DataBuf, bl->AutoSCSIROM, bl->DataReplyLeft); - } - break; - - case 0x95: - if (bl->chip == CHIP_BUSLOGIC_PCI) { - if (bl->Base != 0) { - io_removehandler(bl->Base, 4, - BuslogicRead, - BuslogicReadW, - BuslogicReadL, - BuslogicWrite, - BuslogicWriteW, - BuslogicWriteL, - bl); - } - switch(bl->CmdBuf[0]) { - case 0: - bl->Base = 0x330; - break; - case 1: - bl->Base = 0x334; - break; - case 2: - bl->Base = 0x230; - break; - case 3: - bl->Base = 0x234; - break; - case 4: - bl->Base = 0x130; - break; - case 5: - bl->Base = 0x134; - break; - default: - bl->Base = 0; - break; - } - if (bl->Base != 0) { - io_sethandler(bl->Base, 4, - BuslogicRead, - BuslogicReadW, - BuslogicReadL, - BuslogicWrite, - BuslogicWriteW, - BuslogicWriteL, - bl); - } - bl->DataReplyLeft = 0; - suppress = 1; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; - - case 0x96: - if (bl->CmdBuf[0] == 0) - bl->ExtendedLUNCCBFormat = 0; - else if (bl->CmdBuf[0] == 1) - bl->ExtendedLUNCCBFormat = 1; - - bl->DataReplyLeft = 0; - break; - - case 0x97: - case 0xA7: - /* TODO: Actually correctly implement this whole SCSI BIOS Flash stuff. */ - bl->DataReplyLeft = 0; - break; - - case 0xA8: - if (bl->chip != CHIP_BUSLOGIC_PCI) - { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - break; - } - - Offset = bl->CmdBuf[1]; - Offset <<= 8; - Offset |= bl->CmdBuf[0]; - - bl->DataReplyLeft = bl->CmdBuf[3]; - bl->DataReplyLeft <<= 8; - bl->DataReplyLeft |= bl->CmdBuf[2]; - - memcpy(bl->DataBuf, &(bl->SCAMData[Offset]), bl->DataReplyLeft); - - bl->DataReply = 0; - break; - - case 0xA9: - if (bl->chip != CHIP_BUSLOGIC_PCI) - { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - break; - } - - Offset = bl->CmdBuf[1]; - Offset <<= 8; - Offset |= bl->CmdBuf[0]; - - bl->DataReplyLeft = bl->CmdBuf[3]; - bl->DataReplyLeft <<= 8; - bl->DataReplyLeft |= bl->CmdBuf[2]; - - memcpy(&(bl->SCAMData[Offset]), &(bl->CmdBuf[4]), bl->DataReplyLeft); - bl->DataReplyLeft = 0; - - bl->DataReply = 0; - break; - - default: - pclog("Invalid command %x\n", bl->Command); - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - break; - } - } - - if (bl->DataReplyLeft) - { - bl->Status |= STAT_DFULL; - pclog("Data Full\n"); - } - else if (!bl->CmdParamLeft) - { - BuslogicCommandComplete(bl, suppress); - pclog("No Command Parameters Left, completing command\n"); + buslogic_log("Execute SCSI BIOS Command: received %u bytes\n", dev->CmdBuf[0]); + BuslogicSCSIBIOSRequestSetup(dev, dev->CmdBuf, dev->DataBuf, 4); } break; - - case 2: - bl->Interrupt = Val; + case 0x84: + dev->DataBuf[0] = dev->fw_rev[4]; + dev->DataReplyLeft = 1; + break; + case 0x85: + if (strlen(dev->fw_rev) == 6) + dev->DataBuf[0] = dev->fw_rev[5]; + else + dev->DataBuf[0] = ' '; + dev->DataReplyLeft = 1; + break; + case 0x86: + if (bl->chip == CHIP_BUSLOGIC_PCI) { + ReplyPI = (BuslogicPCIInformation_t *) dev->DataBuf; + memset(ReplyPI, 0, sizeof(BuslogicPCIInformation_t)); + ReplyPI->InformationIsValid = 0; + switch(dev->Base) { + case 0x330: + ReplyPI->IsaIOPort = 0; + break; + case 0x334: + ReplyPI->IsaIOPort = 1; + break; + case 0x230: + ReplyPI->IsaIOPort = 2; + break; + case 0x234: + ReplyPI->IsaIOPort = 3; + break; + case 0x130: + ReplyPI->IsaIOPort = 4; + break; + case 0x134: + ReplyPI->IsaIOPort = 5; + break; + default: + ReplyPI->IsaIOPort = 0xFF; + break; + } + ReplyPI->IRQ = dev->Irq; + dev->DataReplyLeft = sizeof(BuslogicPCIInformation_t); + } else { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; + case 0x8B: + /* The reply length is set by the guest and is found in the first byte of the command buffer. */ + dev->DataReplyLeft = dev->CmdBuf[0]; + memset(dev->DataBuf, 0, dev->DataReplyLeft); + if (bl->chip == CHIP_BUSLOGIC_ISA_542) + i = 5; + else + i = 4; + cCharsToTransfer = MIN(dev->DataReplyLeft, i); + + memcpy(dev->DataBuf, &(bl->LocalRAM.structured.autoSCSIData.aHostAdaptertype[1]), cCharsToTransfer); + break; + case 0x8C: + dev->DataReplyLeft = dev->CmdBuf[0]; + memset(dev->DataBuf, 0, dev->DataReplyLeft); + break; + case 0x8D: + dev->DataReplyLeft = dev->CmdBuf[0]; + ReplyIESI = (ReplyInquireExtendedSetupInformation *)dev->DataBuf; + memset(ReplyIESI, 0, sizeof(ReplyInquireExtendedSetupInformation)); + + switch (bl->chip) { + case CHIP_BUSLOGIC_ISA_542: + case CHIP_BUSLOGIC_ISA: + case CHIP_BUSLOGIC_VLB: + ReplyIESI->uBusType = 'A'; /* ISA style */ + break; + case CHIP_BUSLOGIC_MCA: + ReplyIESI->uBusType = 'M'; /* MCA style */ + break; + case CHIP_BUSLOGIC_PCI: + ReplyIESI->uBusType = 'E'; /* PCI style */ + break; + } + ReplyIESI->uBiosAddress = 0xd8; + ReplyIESI->u16ScatterGatherLimit = 8192; + ReplyIESI->cMailbox = dev->MailboxCount; + ReplyIESI->uMailboxAddressBase = dev->MailboxOutAddr; + ReplyIESI->fHostWideSCSI = 1; /* This should be set for the BT-542B as well. */ + if (bl->chip != CHIP_BUSLOGIC_ISA_542) + ReplyIESI->fLevelSensitiveInterrupt = bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; + if (bl->chip == CHIP_BUSLOGIC_PCI) + ReplyIESI->fHostUltraSCSI = 1; + memcpy(ReplyIESI->aFirmwareRevision, &(dev->fw_rev[strlen(dev->fw_rev) - 3]), sizeof(ReplyIESI->aFirmwareRevision)); + buslogic_log("Return Extended Setup Information: %d\n", dev->CmdBuf[0]); + break; + case 0x8F: + if (bl->chip == CHIP_BUSLOGIC_ISA_542) + bl->fAggressiveRoundRobinMode = dev->CmdBuf[0] & 1; + else + bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode = dev->CmdBuf[0] & 1; + + dev->DataReplyLeft = 0; + break; + case 0x90: + buslogic_log("Store Local RAM\n"); + Offset = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + memcpy(&(bl->LocalRAM.u8View[Offset]), &(dev->CmdBuf[2]), dev->CmdBuf[1]); + + dev->DataReply = 0; + break; + case 0x91: + buslogic_log("Fetch Local RAM\n"); + Offset = dev->CmdBuf[0]; + dev->DataReplyLeft = dev->CmdBuf[1]; + memcpy(dev->DataBuf, &(bl->LocalRAM.u8View[Offset]), dev->CmdBuf[1]); + + dev->DataReply = 0; + break; + case 0x92: + if (bl->chip == CHIP_BUSLOGIC_ISA_542) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; break; - - case 3: - bl->Geometry = Val; + } + + dev->DataReplyLeft = 0; + + switch (dev->CmdBuf[0]) { + case 0: + case 2: + BuslogicAutoSCSIRamSetDefaults(dev, 0); + break; + case 3: + BuslogicAutoSCSIRamSetDefaults(dev, 3); + break; + case 1: + f = nvr_fopen(BuslogicGetNVRFileName(bl), L"wb"); + if (f) { + fwrite(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f); + fclose(f); + f = NULL; + } + break; + default: + dev->Status |= STAT_INVCMD; + break; + } + break; + case 0x94: + if (bl->chip == CHIP_BUSLOGIC_ISA_542) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; break; - } -} + } + if (dev->CmdBuf[0]) { + buslogic_log("Invalid AutoSCSI command mode %x\n", dev->CmdBuf[0]); + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } else { + dev->DataReplyLeft = dev->CmdBuf[2]; + dev->DataReplyLeft <<= 8; + dev->DataReplyLeft |= dev->CmdBuf[1]; + memcpy(dev->DataBuf, bl->AutoSCSIROM, dev->DataReplyLeft); + buslogic_log("Returning AutoSCSI ROM (%04X %04X %04X %04X)\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2], dev->DataBuf[3]); + } + break; + case 0x95: + if (bl->chip == CHIP_BUSLOGIC_PCI) { + if (dev->Base != 0) + x54x_io_remove(dev, dev->Base); + if (dev->CmdBuf[0] < 6) { + dev->Base = ((3 - (dev->CmdBuf[0] >> 1)) << 8) | ((dev->CmdBuf[0] & 1) ? 0x34 : 0x30); + x54x_io_set(dev, dev->Base); + } else + dev->Base = 0; + dev->DataReplyLeft = 0; + return 1; + } else { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; + case 0x96: + if (dev->CmdBuf[0] == 0) + bl->ExtendedLUNCCBFormat = 0; + else if (dev->CmdBuf[0] == 1) + bl->ExtendedLUNCCBFormat = 1; + + dev->DataReplyLeft = 0; + break; + case 0x97: + case 0xA7: + /* TODO: Actually correctly implement this whole SCSI BIOS Flash stuff. */ + dev->DataReplyLeft = 0; + break; + case 0xA8: + if (bl->chip != CHIP_BUSLOGIC_PCI) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } -static void -BuslogicWriteW(uint16_t Port, uint16_t Val, void *p) -{ - BuslogicWrite(Port, Val & 0xFF, p); -} + Offset = dev->CmdBuf[1]; + Offset <<= 8; + Offset |= dev->CmdBuf[0]; + dev->DataReplyLeft = dev->CmdBuf[3]; + dev->DataReplyLeft <<= 8; + dev->DataReplyLeft |= dev->CmdBuf[2]; -static void -BuslogicWriteL(uint16_t Port, uint32_t Val, void *p) -{ - BuslogicWrite(Port, Val & 0xFF, p); -} + memcpy(dev->DataBuf, &(bl->SCAMData[Offset]), dev->DataReplyLeft); + dev->DataReply = 0; + break; + case 0xA9: + if (bl->chip != CHIP_BUSLOGIC_PCI) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } -static void -BuslogicMemWrite(uint32_t addr, uint8_t Val, void *p) -{ - pclog("BuslogicMemWrite(%08X, %02X, %08X)\n", addr, Val, p); - BuslogicWrite(addr & 3, Val, p); -} + Offset = dev->CmdBuf[1]; + Offset <<= 8; + Offset |= dev->CmdBuf[0]; + dev->DataReplyLeft = dev->CmdBuf[3]; + dev->DataReplyLeft <<= 8; + dev->DataReplyLeft |= dev->CmdBuf[2]; -static void -BuslogicMemWriteW(uint32_t addr, uint16_t Val, void *p) -{ - pclog("BuslogicMemWriteW(%08X, %04X, %08X)\n", addr, Val, p); - BuslogicWriteW(addr & 3, Val, p); -} + memcpy(&(bl->SCAMData[Offset]), &(dev->CmdBuf[4]), dev->DataReplyLeft); + dev->DataReplyLeft = 0; - -static void -BuslogicMemWriteL(uint32_t addr, uint32_t Val, void *p) -{ - pclog("BuslogicMemWriteL(%08X, %08X, %08X)\n", addr, Val, p); - BuslogicWriteL(addr & 3, Val, p); -} - - -static void -BuslogicSenseBufferFree(Req_t *req, int Copy) -{ - uint8_t SenseLength = BuslogicConvertSenseLength(req->CmdBlock.common.RequestSenseLength); - uint32_t SenseBufferAddress; - uint8_t temp_sense[256]; - - if (SenseLength && Copy) { - scsi_device_request_sense(req->TargetID, req->LUN, temp_sense, SenseLength); - - /* - * The sense address, in 32-bit mode, is located in the - * Sense Pointer of the CCB, but in 24-bit mode, it is - * located at the end of the Command Descriptor Block. - */ - if (req->Is24bit) { - SenseBufferAddress = req->CCBPointer; - SenseBufferAddress += req->CmdBlock.common.CdbLength + 18; - } else { - SenseBufferAddress = req->CmdBlock.new.SensePointer; - } - - pclog("BuslogicSenseBufferFree(): Request Sense address: %02X\n", SenseBufferAddress); - - pclog("BuslogicSenseBufferFree(): Writing %i bytes at %08X\n", - SenseLength, SenseBufferAddress); - DMAPageWrite(SenseBufferAddress, (char *)temp_sense, SenseLength); - pclog("BuslogicSenseBufferFree(): Sense data written to buffer: %02X %02X %02X\n", - temp_sense[2], temp_sense[12], temp_sense[13]); + dev->DataReply = 0; + break; } + return 0; } static void -BuslogicSCSICommand(Buslogic_t *bl) +buslogic_setup_data(void *p) { - Req_t *req = &bl->Req; - uint8_t Id, Lun; - uint8_t temp_cdb[12]; - uint32_t i; - int target_cdb_len = 12; + x54x_t *dev = (x54x_t *)p; + ReplyInquireSetupInformation *ReplyISI; + buslogic_setup_t *bl_setup; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - Id = req->TargetID; - Lun = req->LUN; + ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; + bl_setup = (buslogic_setup_t *)ReplyISI->VendorSpecificData; - target_cdb_len = scsi_device_cdb_length(Id, Lun); - - if (!scsi_device_valid(Id, Lun)) fatal("BuslogicSCSICommand(): Target on %02i:%02i has disappeared\n", Id, Lun); - - pclog("BuslogicSCSICommand(): Target command being executed on: SCSI ID %i, SCSI LUN %i\n", Id, Lun); - - for (i = 0; i < req->CmdBlock.common.CdbLength; i++) { - pclog("BuslogicSCSICommand(): SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); - } - - memset(temp_cdb, 0, target_cdb_len); - if (req->CmdBlock.common.CdbLength <= target_cdb_len) { - memcpy(temp_cdb, req->CmdBlock.common.Cdb, - req->CmdBlock.common.CdbLength); - } else { - memcpy(temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len); - } - - scsi_device_command(Id, Lun, req->CmdBlock.common.CdbLength, temp_cdb); - - BuslogicDataBufferFree(req); - - BuslogicSenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK)); - - pclog("BuslogicSCSICommand(): Request complete\n"); - - if (SCSIStatus == SCSI_STATUS_OK) { - BuslogicMailboxInSetup(bl, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); - } else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) { - BuslogicMailboxInSetup(bl, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); - } - - if (temp_cdb[0] == 0x42) { - thread_wait_event(bl->evt, 10); - } -} - - -static void -BuslogicSCSIRequestSetup(Buslogic_t *bl, uint32_t CCBPointer, Mailbox32_t *Mailbox32) -{ - Req_t *req = &bl->Req; - uint8_t Id, Lun; - - /* Fetch data from the Command Control Block. */ - DMAPageRead(CCBPointer, (char *)&req->CmdBlock, sizeof(CCB32)); - - req->Is24bit = bl->Mbx24bit; - req->CCBPointer = CCBPointer; - req->TargetID = bl->Mbx24bit ? req->CmdBlock.old.Id : req->CmdBlock.new.Id; - req->LUN = bl->Mbx24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; - - if (!bl->Mbx24bit) + bl_setup->uSignature = 'B'; + /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too + * friendly with Adaptec hardware and upsetting the HBA state. + */ + bl_setup->uCharacterD = 'D'; /* BusLogic model. */ + switch(bl->chip) { - if (req->CmdBlock.new.TagQueued || req->CmdBlock.new.LegacyTagEnable) { - fatal("BuslogicSCSIRequestSetup(): Attempting to queue tags\n"); - BuslogicMailboxInSetup(bl, CCBPointer, &req->CmdBlock, - CCB_INVALID_CCB, SCSI_STATUS_OK, MBI_ERROR); - pclog("BusLogic Callback: Send incoming mailbox\n"); - BuslogicMailboxIn(bl); - return; - } + case CHIP_BUSLOGIC_ISA_542: + case CHIP_BUSLOGIC_ISA: + bl_setup->uHostBusType = 'A'; + break; +#ifdef BUSLOGIC_NOT_WORKING + case CHIP_BUSLOGIC_MCA: + bl_setup->uHostBusType = 'B'; + break; + case CHIP_BUSLOGIC_VLB: + bl_setup->uHostBusType = 'E'; + break; +#endif + case CHIP_BUSLOGIC_PCI: + bl_setup->uHostBusType = 'F'; + break; } - - Id = req->TargetID; - Lun = req->LUN; - if ((Id > 15) || (Lun > 7)) { - BuslogicMailboxInSetup(bl, CCBPointer, &req->CmdBlock, - CCB_INVALID_CCB, SCSI_STATUS_OK, MBI_ERROR); - return; - - pclog("BusLogic Callback: Send incoming mailbox\n"); - BuslogicMailboxIn(bl); - } - - pclog("BuslogicSCSIRequestSetup(): Scanning SCSI Target ID %i\n", Id); - - SCSIStatus = SCSI_STATUS_OK; - SCSIDevices[Id][Lun].InitLength = 0; - - BuslogicDataBufferAllocate(req, req->Is24bit); - - if (!scsi_device_present(Id, Lun)) { - pclog("BuslogicSCSIRequestSetup(): SCSI Target ID %i and LUN %i have no device attached\n",Id,Lun); - BuslogicDataBufferFree(req); - BuslogicSenseBufferFree(req, 0); - BuslogicMailboxInSetup(bl, CCBPointer, &req->CmdBlock, - CCB_SELECTION_TIMEOUT,SCSI_STATUS_OK,MBI_ERROR); - - pclog("BusLogic Callback: Send incoming mailbox\n"); - BuslogicMailboxIn(bl); - } else { - pclog("BuslogicSCSIRequestSetup(): SCSI Target ID %i and LUN %i detected and working\n", Id, Lun); - - pclog("BuslogicSCSIRequestSetup(): Transfer Control %02X\n", req->CmdBlock.common.ControlByte); - pclog("BuslogicSCSIRequestSetup(): CDB Length %i\n", req->CmdBlock.common.CdbLength); - pclog("BuslogicSCSIRequestSetup(): CCB Opcode %x\n", req->CmdBlock.common.Opcode); - if (req->CmdBlock.common.ControlByte > 0x03) { - pclog("BuslogicSCSIRequestSetup(): Invalid control byte: %02X\n", - req->CmdBlock.common.ControlByte); - } - - pclog("BusLogic Callback: Process SCSI request\n"); - BuslogicSCSICommand(bl); - - pclog("BusLogic Callback: Send incoming mailbox\n"); - BuslogicMailboxIn(bl); - } -} - - -static void -BuslogicSCSIRequestAbort(Buslogic_t *bl, uint32_t CCBPointer) -{ - CCBU CmdBlock; - - /* Fetch data from the Command Control Block. */ - DMAPageRead(CCBPointer, (char *)&CmdBlock, sizeof(CCB32)); - - /* Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon. */ - BuslogicMailboxInSetup(bl, CCBPointer, &CmdBlock, - 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); - - pclog("BusLogic Callback: Send incoming mailbox\n"); - BuslogicMailboxIn(bl); -} - - -static uint32_t -BuslogicMailboxOut(Buslogic_t *bl, Mailbox32_t *Mailbox32) -{ - Mailbox_t MailboxOut; - uint32_t Outgoing; - - if (bl->Mbx24bit) { - Outgoing = bl->MailboxOutAddr + (bl->MailboxOutPosCur * sizeof(Mailbox_t)); - DMAPageRead(Outgoing, (char *)&MailboxOut, sizeof(Mailbox_t)); - - Mailbox32->CCBPointer = ADDR_TO_U32(MailboxOut.CCBPointer); - Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus; - } else { - Outgoing = bl->MailboxOutAddr + (bl->MailboxOutPosCur * sizeof(Mailbox32_t)); - - DMAPageRead(Outgoing, (char *)Mailbox32, sizeof(Mailbox32_t)); - } - - return Outgoing; -} - - -static void -BuslogicMailboxOutAdvance(Buslogic_t *bl) -{ - bl->MailboxOutPosCur = (bl->MailboxOutPosCur + 1) % bl->MailboxCount; } static uint8_t -BuslogicProcessMailbox(Buslogic_t *bl) +buslogic_is_aggressive_mode(void *p) { - Mailbox32_t mb32; - uint32_t Outgoing; - uint8_t CmdStatus = MBO_FREE; - uint32_t CodeOffset = 0; + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - CodeOffset = bl->Mbx24bit ? 0 : 7; - -#if 0 - pclog("BuslogicProcessMailbox(): Operating in %s mode\n", bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode ? "aggressive" : "strict"); -#endif - - /* 0 = strict, 1 = aggressive */ - if (bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode) { - uint8_t MailboxCur = bl->MailboxOutPosCur; - - /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ - do { - /* Fetch mailbox from guest memory. */ - Outgoing = BuslogicMailboxOut(bl, &mb32); - - /* Check the next mailbox. */ - BuslogicMailboxOutAdvance(bl); - } while ((mb32.u.out.ActionCode == MBO_FREE) && (MailboxCur != bl->MailboxOutPosCur)); - } else { - Outgoing = BuslogicMailboxOut(bl, &mb32); - } - - if (mb32.u.out.ActionCode != MBO_FREE) { - /* We got the mailbox, mark it as free in the guest. */ - pclog("BuslogicProcessMailbox(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset); - DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, sizeof(CmdStatus)); - } + HALocalRAM *HALR = &bl->LocalRAM; + if (bl->chip == CHIP_BUSLOGIC_ISA_542) + return bl->fAggressiveRoundRobinMode; else - { + return HALR->structured.autoSCSIData.fAggressiveRoundRobinMode; +} + + +static uint8_t +buslogic_interrupt_type(void *p) +{ + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + + if (bl->chip == CHIP_BUSLOGIC_ISA_542) return 0; - } - - if (bl->MailboxOutInterrupts) { - BuslogicRaiseInterrupt(bl, 0, INTR_MBOA | INTR_ANY); - - while (bl->Interrupt) { - } - } - -#if 0 - pclog("BuslogicProcessMailbox(): Outgoing mailbox action code: %i\n", mb32.u.out.ActionCode); -#endif - - if (mb32.u.out.ActionCode == MBO_START) { - pclog("Start Mailbox Command\n"); - BuslogicSCSIRequestSetup(bl, mb32.CCBPointer, &mb32); - } else if (mb32.u.out.ActionCode == MBO_ABORT) { - pclog("Abort Mailbox Command\n"); - BuslogicSCSIRequestAbort(bl, mb32.CCBPointer); - } else { - pclog("Invalid action code: %02X\n", mb32.u.out.ActionCode); - } - - /* Advance to the next mailbox. */ - if (! bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode) - BuslogicMailboxOutAdvance(bl); - - return 1; -} - - -static void -BuslogicResetPoll(void *p) -{ - Buslogic_t *bl = (Buslogic_t *)p; - - bl->Status &= ~STAT_STST; - bl->Status |= STAT_IDLE; - - BuslogicResetCallback = 0; -} - - -static void -BuslogicCommandThread(void *p) -{ - Buslogic_t *bl = (Buslogic_t *)p; - -BuslogicEventRestart: - /* Create a waitable event. */ - bl->evt = thread_create_event(); - -BuslogicScanRestart: - if (bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode) - { - while (bl->MailboxCount) - { - BuslogicProcessMailbox(bl); - } - } else - { - while (BuslogicProcessMailbox(bl) && bl->MailboxCount) - { - } - } + return !!bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; +} - if (!bl->MailboxCount) - { - thread_destroy_event(bl->evt); - bl->evt = NULL; - poll_tid = NULL; - return; - } - if (bl->scan_restart) - { - bl->scan_restart = 0; - goto BuslogicScanRestart; - } +static void +buslogic_reset(void *p) +{ + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - thread_destroy_event(bl->evt); - bl->evt = NULL; - - if (bl->scan_restart) - { - bl->scan_restart = 0; - goto BuslogicEventRestart; - } - - poll_tid = NULL; - - pclog("Buslogic: polling stopped.\n"); + bl->ExtendedLUNCCBFormat = 0; } @@ -2619,7 +1042,7 @@ bar_t buslogic_pci_bar[3]; static void -BuslogicBIOSUpdate(Buslogic_t *bl) +BuslogicBIOSUpdate(buslogic_data_t *bl) { int bios_enabled = buslogic_pci_bar[2].addr_regs[0] & 0x01; @@ -2632,9 +1055,9 @@ BuslogicBIOSUpdate(Buslogic_t *bl) mem_mapping_enable(&bl->bios.mapping); mem_mapping_set_addr(&bl->bios.mapping, bl->bios_addr, bl->bios_size); - pclog("BT-958D: BIOS now at: %06X\n", bl->bios_addr); + buslogic_log("BT-958D: BIOS now at: %06X\n", bl->bios_addr); } else { - pclog("BT-958D: BIOS disabled\n"); + buslogic_log("BT-958D: BIOS disabled\n"); mem_mapping_disable(&bl->bios.mapping); } } @@ -2642,9 +1065,10 @@ BuslogicBIOSUpdate(Buslogic_t *bl) static uint8_t BuslogicPCIRead(int func, int addr, void *p) { - Buslogic_t *bl = (Buslogic_t *)p; + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - pclog("BT-958D: Reading register %02X\n", addr & 0xff); + buslogic_log("BT-958D: Reading register %02X\n", addr & 0xff); switch (addr) { case 0x00: @@ -2696,22 +1120,22 @@ BuslogicPCIRead(int func, int addr, void *p) case 0x2F: return 0x10; case 0x30: /* PCI_ROMBAR */ - pclog("BT-958D: BIOS BAR 00 = %02X\n", buslogic_pci_bar[2].addr_regs[0] & 0x01); + buslogic_log("BT-958D: BIOS BAR 00 = %02X\n", buslogic_pci_bar[2].addr_regs[0] & 0x01); return buslogic_pci_bar[2].addr_regs[0] & 0x01; case 0x31: /* PCI_ROMBAR 15:11 */ - pclog("BT-958D: BIOS BAR 01 = %02X\n", (buslogic_pci_bar[2].addr_regs[1] & bl->bios_mask)); + buslogic_log("BT-958D: BIOS BAR 01 = %02X\n", (buslogic_pci_bar[2].addr_regs[1] & bl->bios_mask)); return buslogic_pci_bar[2].addr_regs[1]; break; case 0x32: /* PCI_ROMBAR 23:16 */ - pclog("BT-958D: BIOS BAR 02 = %02X\n", buslogic_pci_bar[2].addr_regs[2]); + buslogic_log("BT-958D: BIOS BAR 02 = %02X\n", buslogic_pci_bar[2].addr_regs[2]); return buslogic_pci_bar[2].addr_regs[2]; break; case 0x33: /* PCI_ROMBAR 31:24 */ - pclog("BT-958D: BIOS BAR 03 = %02X\n", buslogic_pci_bar[2].addr_regs[3]); + buslogic_log("BT-958D: BIOS BAR 03 = %02X\n", buslogic_pci_bar[2].addr_regs[3]); return buslogic_pci_bar[2].addr_regs[3]; break; case 0x3C: - return bl->Irq; + return dev->Irq; case 0x3D: return PCI_INTA; } @@ -2723,32 +1147,26 @@ BuslogicPCIRead(int func, int addr, void *p) static void BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) { - Buslogic_t *bl = (Buslogic_t *)p; + x54x_t *dev = (x54x_t *)p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + uint8_t valxor; - pclog("BT-958D: Write value %02X to register %02X\n", val, addr & 0xff); + buslogic_log("BT-958D: Write value %02X to register %02X\n", val, addr & 0xff); switch (addr) { case 0x04: valxor = (val & 0x27) ^ buslogic_pci_regs[addr]; if (valxor & PCI_COMMAND_IO) { - io_removehandler(bl->PCIBase, 0x20, - BuslogicRead, BuslogicReadW, BuslogicReadL, - BuslogicWrite, BuslogicWriteW, BuslogicWriteL, - bl); + x54x_io_remove(dev, bl->PCIBase); if ((bl->PCIBase != 0) && (val & PCI_COMMAND_IO)) { - io_sethandler(bl->PCIBase, 0x0020, - BuslogicRead, BuslogicReadW, - BuslogicReadL, BuslogicWrite, - BuslogicWriteW, BuslogicWriteL, - bl); + x54x_io_set(dev, bl->PCIBase); } } if (valxor & PCI_COMMAND_MEM) { - mem_mapping_disable(&bl->mmio_mapping); + x54x_mem_disable(dev); if ((bl->MMIOBase != 0) & (val & PCI_COMMAND_MEM)) { - mem_mapping_set_addr(&bl->mmio_mapping, - bl->MMIOBase, 0x20); + x54x_mem_set_addr(dev, bl->MMIOBase); } } buslogic_pci_regs[addr] = val & 0x27; @@ -2761,24 +1179,17 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) case 0x11: case 0x12: case 0x13: /* I/O Base set. */ /* First, remove the old I/O. */ - io_removehandler(bl->PCIBase, 0x0020, - BuslogicRead, BuslogicReadW, BuslogicReadL, - BuslogicWrite, BuslogicWriteW, BuslogicWriteL, - bl); + x54x_io_remove(dev, bl->PCIBase); /* Then let's set the PCI regs. */ buslogic_pci_bar[0].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ bl->PCIBase = buslogic_pci_bar[0].addr & 0xffe0; /* Log the new base. */ - pclog("BusLogic PCI: New I/O base is %04X\n" , bl->PCIBase); + buslogic_log("BusLogic PCI: New I/O base is %04X\n" , bl->PCIBase); /* We're done, so get out of the here. */ if (buslogic_pci_regs[4] & PCI_COMMAND_IO) { if (bl->PCIBase != 0) { - io_sethandler(bl->PCIBase, 0x0020, - BuslogicRead, BuslogicReadW, - BuslogicReadL, BuslogicWrite, - BuslogicWriteW, BuslogicWriteL, - bl); + x54x_io_set(dev, bl->PCIBase); } } return; @@ -2787,20 +1198,19 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) val &= 0xe0; case 0x15: case 0x16: case 0x17: - /* I/O Base set. */ + /* MMIO Base set. */ /* First, remove the old I/O. */ - mem_mapping_disable(&bl->mmio_mapping); + x54x_mem_disable(dev); /* Then let's set the PCI regs. */ buslogic_pci_bar[1].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0; /* Log the new base. */ - pclog("BusLogic PCI: New MMIO base is %04X\n" , bl->MMIOBase); + buslogic_log("BusLogic PCI: New MMIO base is %04X\n" , bl->MMIOBase); /* We're done, so get out of the here. */ if (buslogic_pci_regs[4] & PCI_COMMAND_MEM) { if (bl->MMIOBase != 0) { - mem_mapping_set_addr(&bl->mmio_mapping, - bl->MMIOBase, 0x20); + x54x_mem_set_addr(dev, bl->MMIOBase); } } return; @@ -2812,15 +1222,15 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) buslogic_pci_bar[2].addr_regs[addr & 3] = val; buslogic_pci_bar[2].addr &= 0xffffc001; bl->bios_addr = buslogic_pci_bar[2].addr & 0xffffc000; - pclog("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); + buslogic_log("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); BuslogicBIOSUpdate(bl); return; case 0x3C: buslogic_pci_regs[addr] = val; if (val != 0xFF) { - BuslogicLog("BusLogic IRQ now: %i\n", val); - bl->Irq = val; + buslogic_log("BusLogic IRQ now: %i\n", val); + dev->Irq = val; } return; } @@ -2828,42 +1238,42 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) static void -BuslogicInitializeLocalRAM(Buslogic_t *bl) +BuslogicInitializeLocalRAM(buslogic_data_t *bl) { - memset(bl->LocalRAM.u8View, 0, sizeof(HALocalRAM)); - if (PCI && (bl->chip == CHIP_BUSLOGIC_PCI)) - { - bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; - } - else - { - bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 0; - } - bl->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16SynchronousPermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode = 0; - bl->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = ~0; + memset(bl->LocalRAM.u8View, 0, sizeof(HALocalRAM)); + if (bl->chip == CHIP_BUSLOGIC_PCI) { + bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; + } else { + bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 0; + } + + bl->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16SynchronousPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode = 0; + bl->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = ~0; } void BuslogicDeviceReset(void *p) { - Buslogic_t *dev = (Buslogic_t *) p; - BuslogicResetControl(dev, 1); + x54x_t *dev = (x54x_t *) p; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - BuslogicInitializeLocalRAM(dev); - BuslogicInitializeAutoSCSIRam(dev); + x54x_reset_ctrl(dev, 1); + + BuslogicInitializeLocalRAM(bl); + BuslogicInitializeAutoSCSIRam(dev); } static void * -BuslogicInit(int chip) +buslogic_init(device_t *info) { - Buslogic_t *bl; + x54x_t *dev; wchar_t *bios_rom_name; uint16_t bios_rom_size; uint16_t bios_rom_mask; @@ -2874,195 +1284,182 @@ BuslogicInit(int chip) wchar_t *scam_rom_name; uint16_t scam_rom_size; FILE *f; + buslogic_data_t *bl; + uint32_t bios_rom_addr; - bl = malloc(sizeof(Buslogic_t)); - memset(bl, 0x00, sizeof(Buslogic_t)); + /* Call common initializer. */ + dev = x54x_init(info); - if (!PCI && (chip == CHIP_BUSLOGIC_PCI)) - { - chip = CHIP_BUSLOGIC_ISA; - } - bl->chip = chip; - bl->Base = device_get_config_hex16("base"); + dev->ven_data = malloc(sizeof(buslogic_data_t)); + memset(dev->ven_data, 0x00, sizeof(buslogic_data_t)); + + bl = (buslogic_data_t *) dev->ven_data; + + dev->bus = info->flags; + dev->Base = device_get_config_hex16("base"); + dev->Irq = device_get_config_int("irq"); + dev->DmaChannel = device_get_config_int("dma"); + dev->HostID = 7; /* default HA ID */ + dev->setup_info_len = sizeof(buslogic_setup_t); + dev->reset_duration = BUSLOGIC_RESET_DURATION_US; + dev->max_id = 7; + dev->int_geom_writable = 1; + dev->cdrom_boot = 0; + + bl->chip = info->local; bl->PCIBase = 0; bl->MMIOBase = 0; - bl->Irq = device_get_config_int("irq"); - bl->DmaChannel = device_get_config_int("dma"); - bl->has_bios = device_get_config_int("bios"); - - - if (bl->Base != 0) { - if (bl->chip == CHIP_BUSLOGIC_PCI) { - io_sethandler(bl->Base, 4, - BuslogicRead, BuslogicReadW, BuslogicReadL, - BuslogicWrite, BuslogicWriteW, BuslogicWriteL, - bl); - } else { - io_sethandler(bl->Base, 4, - BuslogicRead, BuslogicReadW, NULL, - BuslogicWrite, BuslogicWriteW, NULL, bl); - } + if (info->flags & DEVICE_PCI) { + bios_rom_addr = 0xd8000; + bl->has_bios = device_get_config_int("bios"); + } else { + bios_rom_addr = device_get_config_hex20("bios_addr"); + bl->has_bios = !!bios_rom_addr; } + dev->ven_cmd_phase1 = buslogic_cmd_phase1; + dev->ven_get_host_id = buslogic_get_host_id; + dev->ven_get_irq = buslogic_get_irq; + dev->ven_get_dma = buslogic_get_dma; + dev->get_ven_param_len = buslogic_param_len; + dev->ven_cmds = buslogic_cmds; + dev->interrupt_type = buslogic_interrupt_type; + dev->is_aggressive_mode = buslogic_is_aggressive_mode; + dev->get_ven_data = buslogic_setup_data; + dev->ven_reset = buslogic_reset; - switch(bl->chip) - { - case CHIP_BUSLOGIC_ISA: - default: - bios_rom_name = L"roms/scsi/buslogic/BT-545C_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 1; - autoscsi_rom_name = L"roms/scsi/buslogic/BT-545C_AutoSCSI.rom"; - autoscsi_rom_size = 0x4000; - has_scam_rom = 0; - break; - case CHIP_BUSLOGIC_PCI: - bios_rom_name = L"roms/scsi/buslogic/BT-958D_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 1; - autoscsi_rom_name = L"roms/scsi/buslogic/BT-958D_AutoSCSI.rom"; - autoscsi_rom_size = 0x8000; - has_scam_rom = 1; - scam_rom_name = L"roms/scsi/buslogic/BT-958D_SCAM.rom"; - scam_rom_size = 0x0200; - break; - } + strcpy(dev->vendor, "BusLogic"); + if ((dev->Base != 0) && !(dev->bus & DEVICE_MCA)) { + x54x_io_set(dev, dev->Base); + } - memset(bl->AutoSCSIROM, 0xff, 32768); + switch(bl->chip) + { + case CHIP_BUSLOGIC_ISA_542: + strcpy(dev->name, "BT-542BH"); + bios_rom_name = L"roms/scsi/buslogic/BT-542BH_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 0; + has_scam_rom = 0; + dev->fw_rev = "AA335"; + bl->fAggressiveRoundRobinMode = 1; + break; + case CHIP_BUSLOGIC_ISA: + default: + strcpy(dev->name, "BT-545S"); + bios_rom_name = L"roms/scsi/buslogic/BT-545S_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 1; + autoscsi_rom_name = L"roms/scsi/buslogic/BT-545S_AutoSCSI.rom"; + autoscsi_rom_size = 0x4000; + has_scam_rom = 0; + dev->fw_rev = "AA421E"; + break; +#ifdef BUSLOGIC_NOT_WORKING + case CHIP_BUSLOGIC_MCA: + strcpy(dev->name, "BT-640A"); + bios_rom_name = L"roms/scsi/buslogic/BT-640_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 1; + autoscsi_rom_name = L"roms/scsi/buslogic/BT-640_AutoSCSI.rom"; + autoscsi_rom_size = 0x4000; + has_scam_rom = 0; + dev->fw_rev = "BA421E"; + break; +#endif + case CHIP_BUSLOGIC_PCI: + strcpy(dev->name, "BT-958D"); + bios_rom_name = L"roms/scsi/buslogic/BT-958D_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 1; + autoscsi_rom_name = L"roms/scsi/buslogic/BT-958D_AutoSCSI.rom"; + autoscsi_rom_size = 0x8000; + has_scam_rom = 1; + scam_rom_name = L"roms/scsi/buslogic/BT-958D_SCAM.rom"; + scam_rom_size = 0x0200; + dev->fw_rev = "AA507B"; + dev->cdrom_boot = 1; + break; + } - memset(bl->SCAMData, 0x00, 65536); + memset(bl->AutoSCSIROM, 0xff, 32768); + memset(bl->SCAMData, 0x00, 65536); - if (bl->has_bios) - { - bl->bios_size = bios_rom_size; + if (bl->has_bios) + { + bl->bios_size = bios_rom_size; - bl->bios_mask = 0xffffc000; + bl->bios_mask = 0xffffc000; - rom_init(&bl->bios, bios_rom_name, 0xd8000, bios_rom_size, bios_rom_mask, 0, MEM_MAPPING_EXTERNAL); + rom_init(&bl->bios, bios_rom_name, bios_rom_addr, bios_rom_size, bios_rom_mask, 0, MEM_MAPPING_EXTERNAL); - if (has_autoscsi_rom) - { - f = romfopen(autoscsi_rom_name, L"rb"); - if (f) - { - fread(bl->AutoSCSIROM, 1, autoscsi_rom_size, f); - fclose(f); - f = NULL; - } - } - - if (has_scam_rom) - { - f = romfopen(scam_rom_name, L"rb"); - if (f) - { - fread(bl->SCAMData, 1, scam_rom_size, f); - fclose(f); - f = NULL; - } + if (has_autoscsi_rom) { + f = rom_fopen(autoscsi_rom_name, L"rb"); + if (f) { + fread(bl->AutoSCSIROM, 1, autoscsi_rom_size, f); + fclose(f); + f = NULL; } } - else - { - bl->bios_size = 0; - bl->bios_mask = 0; + if (has_scam_rom) { + f = rom_fopen(scam_rom_name, L"rb"); + if (f) { + fread(bl->SCAMData, 1, scam_rom_size, f); + fclose(f); + f = NULL; + } } + } + else { + bl->bios_size = 0; - timer_add(BuslogicResetPoll, - &BuslogicResetCallback, &BuslogicResetCallback, bl); + bl->bios_mask = 0; + } if (bl->chip == CHIP_BUSLOGIC_PCI) { - bl->Card = pci_add_card(PCI_ADD_NORMAL, BuslogicPCIRead, BuslogicPCIWrite, bl); + dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, BuslogicPCIRead, BuslogicPCIWrite, dev); buslogic_pci_bar[0].addr_regs[0] = 1; buslogic_pci_bar[1].addr_regs[0] = 0; buslogic_pci_regs[0x04] = 3; -#if 0 - buslogic_pci_regs[0x05] = 0; - buslogic_pci_regs[0x07] = 2; -#endif /* Enable our BIOS space in PCI, if needed. */ - if (bl->has_bios) - { + if (bl->has_bios) { buslogic_pci_bar[2].addr = 0xFFFFC000; - } - else - { + } else { buslogic_pci_bar[2].addr = 0; } - mem_mapping_add(&bl->mmio_mapping, 0xfffd0000, 0x20, - BuslogicMemRead, BuslogicMemReadW, BuslogicMemReadL, - BuslogicMemWrite, BuslogicMemWriteW, BuslogicMemWriteL, - NULL, MEM_MAPPING_EXTERNAL, bl); - mem_mapping_disable(&bl->mmio_mapping); + x54x_mem_init(dev, 0xfffd0000); + x54x_mem_disable(dev); + mem_mapping_disable(&bl->bios.mapping); } - pclog("Buslogic on port 0x%04X\n", bl->Base); + buslogic_log("Buslogic on port 0x%04X\n", dev->Base); - BuslogicResetControl(bl, CTRL_HRST); + x54x_reset_ctrl(dev, CTRL_HRST); - BuslogicInitializeLocalRAM(bl); - BuslogicInitializeAutoSCSIRam(bl); - - return(bl); -} - - -static void * -Buslogic_545C_Init(void) -{ - return BuslogicInit(CHIP_BUSLOGIC_ISA); -} - - -static void * -Buslogic_958D_Init(void) -{ - return BuslogicInit(CHIP_BUSLOGIC_PCI); -} - - -static void -BuslogicClose(void *p) -{ - Buslogic_t *bl = (Buslogic_t *)p; - if (bl) - { - bl->MailboxCount = 0; - - if (bl->evt) - { - thread_destroy_event(bl->evt); - bl->evt = NULL; - - if (poll_tid) - { - thread_kill(poll_tid); - poll_tid = NULL; - } - } - - free(bl); - bl = NULL; + if (bl->chip != CHIP_BUSLOGIC_ISA_542) { + BuslogicInitializeLocalRAM(bl); + BuslogicInitializeAutoSCSIRam(dev); } + + return(dev); } -static device_config_t BuslogicConfig[] = { +static device_config_t BT_ISA_Config[] = { { "base", "Address", CONFIG_HEX16, "", 0x334, { - { - "None", 0 - }, { "0x330", 0x330 }, @@ -3129,6 +1526,62 @@ static device_config_t BuslogicConfig[] = { } }, }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, + { + { + "Disabled", 0 + }, + { + "C800H", 0xc8000 + }, + { + "D000H", 0xd0000 + }, + { + "D800H", 0xd8000 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + + +static device_config_t BT958D_Config[] = { + { + "base", "Legacy Address", CONFIG_HEX16, "", 0x334, + { + { + "None", 0 + }, + { + "0x330", 0x330 + }, + { + "0x334", 0x334 + }, + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x130", 0x130 + }, + { + "0x134", 0x134 + }, + { + "" + } + }, + }, { "bios", "Enable BIOS", CONFIG_BINARY, "", 0 }, @@ -3139,25 +1592,28 @@ static device_config_t BuslogicConfig[] = { device_t buslogic_device = { - "Buslogic BT-545C ISA", - 0, - Buslogic_545C_Init, - BuslogicClose, - NULL, - NULL, - NULL, - NULL, - BuslogicConfig + "Buslogic BT-542BH ISA", + DEVICE_ISA | DEVICE_AT, + CHIP_BUSLOGIC_ISA_542, + buslogic_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + BT_ISA_Config +}; + +device_t buslogic_545s_device = { + "Buslogic BT-545S ISA", + DEVICE_ISA | DEVICE_AT, + CHIP_BUSLOGIC_ISA, + buslogic_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + BT_ISA_Config }; device_t buslogic_pci_device = { "Buslogic BT-958D PCI", - 0, - Buslogic_958D_Init, - BuslogicClose, - NULL, - NULL, - NULL, - NULL, - BuslogicConfig + DEVICE_PCI, + CHIP_BUSLOGIC_PCI, + buslogic_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + BT958D_Config }; diff --git a/src/scsi/scsi_buslogic.h b/src/scsi/scsi_buslogic.h index f6d60f94d..398e3db25 100644 --- a/src/scsi/scsi_buslogic.h +++ b/src/scsi/scsi_buslogic.h @@ -7,7 +7,7 @@ * Emulation of BusLogic BT-542B ISA and BT-958D PCI SCSI * controllers. * - * Version: @(#)scsi_buslogic.h 1.0.1 2017/08/23 + * Version: @(#)scsi_buslogic.h 1.0.2 2017/10/14 * * Authors: TheCollector1995, * Miran Grca, @@ -21,6 +21,7 @@ extern device_t buslogic_device; +extern device_t buslogic_545s_device; extern device_t buslogic_pci_device; extern void BuslogicDeviceReset(void *p); diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c index 63412dcb8..87ca35848 100644 --- a/src/scsi/scsi_device.c +++ b/src/scsi/scsi_device.c @@ -8,15 +8,21 @@ * * The generic SCSI device command handler. * - * Version: @(#)scsi_device.c 1.0.2 2017/09/03 + * Version: @(#)scsi_device.c 1.0.7 2017/10/10 * * Authors: Miran Grca, * Fred N. van Kempen, * Copyright 2016,2017 Miran Grca. * Copyright 2017 Fred N. van Kempen. */ +#include +#include +#include +#include #include "../ibm.h" +#include "../device.h" #include "../cdrom/cdrom.h" +#include "../disk/hdd.h" #include "scsi.h" #include "scsi_disk.h" @@ -40,6 +46,7 @@ static void scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb) } else { + SCSIPhase = SCSI_PHASE_STATUS; SCSIStatus = SCSI_STATUS_CHECK_CONDITION; } } @@ -170,7 +177,7 @@ void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uin case SCSI_DISK: id = scsi_hard_disks[scsi_id][scsi_lun]; *type = 0x00; - *rmb = (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00; + *rmb = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00; break; case SCSI_CDROM: *type = 0x05; @@ -271,7 +278,7 @@ int scsi_device_block_shift(uint8_t scsi_id, uint8_t scsi_lun) } -void scsi_device_command(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb) +void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb) { uint8_t phase = 0; uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; @@ -288,7 +295,7 @@ void scsi_device_command(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t break; default: id = 0; - break; + return; } /* @@ -315,13 +322,46 @@ void scsi_device_command(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t scsi_device_target_phase_callback(lun_type, id); } else { /* Command first phase complete - call the callback to execute the second phase. */ - scsi_device_target_phase_callback(lun_type, id); - SCSIStatus = scsi_device_target_err_stat_to_scsi(lun_type, id); - /* Command second phase complete - call the callback to complete the command. */ - scsi_device_target_phase_callback(lun_type, id); + if (SCSIPhase == SCSI_PHASE_STATUS) + { + scsi_device_target_phase_callback(lun_type, id); + SCSIStatus = scsi_device_target_err_stat_to_scsi(lun_type, id); + /* Command second phase complete - call the callback to complete the command. */ + scsi_device_target_phase_callback(lun_type, id); + } } } else { /* Error (Check Condition) - call the phase callback to complete the command. */ scsi_device_target_phase_callback(lun_type, id); } } + +void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun) +{ + uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + + uint8_t id = 0; + + switch (lun_type) + { + case SCSI_DISK: + id = scsi_hard_disks[scsi_id][scsi_lun]; + break; + case SCSI_CDROM: + id = scsi_cdrom_drives[scsi_id][scsi_lun]; + break; + default: + id = 0; + return; + } + + scsi_device_target_phase_callback(lun_type, id); + SCSIStatus = scsi_device_target_err_stat_to_scsi(lun_type, id); + /* Command second phase complete - call the callback to complete the command. */ + scsi_device_target_phase_callback(lun_type, id); +} + +int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun) +{ + return &SCSIDevices[scsi_id][scsi_lun].BufferLength; +} diff --git a/src/scsi/scsi_device.h b/src/scsi/scsi_device.h index c369cc4e3..fd5f21c14 100644 --- a/src/scsi/scsi_device.h +++ b/src/scsi/scsi_device.h @@ -8,7 +8,7 @@ * * Definitions for the generic SCSI device command handler. * - * Version: @(#)scsi_device.h 1.0.2 2017/08/22 + * Version: @(#)scsi_device.h 1.0.4 2017/10/10 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -16,6 +16,21 @@ #ifndef SCSI_DEVICE_H # define SCSI_DEVICE_H +typedef struct +{ + int state; + int new_state; + int clear_req; + uint32_t bus_in, bus_out; + int dev_id; + + int command_pos; + uint8_t command[20]; + int data_pos; + + int change_state_delay; + int new_req_delay; +} scsi_bus_t; extern uint8_t *scsi_device_sense(uint8_t id, uint8_t lun); extern void scsi_device_type_data(uint8_t id, uint8_t lun, @@ -32,6 +47,13 @@ extern int scsi_device_cdb_length(uint8_t id, uint8_t lun); extern int scsi_device_block_shift(uint8_t id, uint8_t lun); extern void scsi_device_command(uint8_t id, uint8_t lun, int cdb_len, uint8_t *cdb); +extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, + int cdb_len, uint8_t *cdb); +extern void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun); +extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun); +extern int scsi_bus_update(scsi_bus_t *bus, int bus_assert); +extern int scsi_bus_read(scsi_bus_t *bus); +extern int scsi_bus_match(scsi_bus_t *bus, int bus_assert); #endif /*SCSI_DEVICE_H*/ diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index e6cde3904..03e7904c7 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -6,23 +6,29 @@ * * Emulation of SCSI fixed and removable disks. * - * Version: @(#)scsi_disk.c 1.0.7 2017/09/03 + * Version: @(#)scsi_disk.c 1.0.15 2017/10/14 * * Author: Miran Grca, * Copyright 2017 Miran Grca. */ -#include #include +#include +#include #include #include +#include #include "../86box.h" #include "../ibm.h" #include "../timer.h" +#include "../device.h" +#include "../nvr.h" #include "../piix.h" #include "../cdrom/cdrom.h" -#include "../hdd/hdd_image.h" -#include "../hdd/hdd_ide_at.h" -#include "../win/plat_iodev.h" +#include "../disk/hdd.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" +#include "../plat.h" +#include "../ui.h" #include "scsi.h" #include "scsi_disk.h" @@ -47,8 +53,8 @@ #define scsi_hd_ascq shdc[id].sense[13] -scsi_hard_disk_t shdc[HDC_NUM]; -FILE *shdf[HDC_NUM]; +scsi_hard_disk_t shdc[HDD_NUM]; +FILE *shdf[HDD_NUM]; uint8_t scsi_hard_disks[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, @@ -119,7 +125,320 @@ uint8_t scsi_hd_command_flags[0x100] = { }; -/* #define ENABLE_SCSI_HD_LOG 0 */ +uint64_t scsi_hd_mode_sense_page_flags[HDD_NUM] = { (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F), + (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F) }; + +/* This should be done in a better way but for time being, it's been done this way so it's not as huge and more readable. */ +const uint8_t scsi_hd_mode_sense_pages_default[HDD_NUM][0x40][0x40] = +{ + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } } +}; + +uint8_t scsi_hd_mode_sense_pages_changeable[HDD_NUM][0x40][0x40] = +{ + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } } +}; + +uint8_t scsi_hd_mode_sense_pages_saved[HDD_NUM][0x40][0x40] = +{ + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }, + { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } } +}; + int scsi_hd_do_log = 0; @@ -138,6 +457,8 @@ void scsi_hd_log(const char *format, ...) } +int scsi_hd_mode_select_terminate(uint8_t id, int force); + /* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ int scsi_hd_err_stat_to_scsi(uint8_t id) { @@ -188,21 +509,21 @@ int scsi_hd_phase_to_scsi(uint8_t id) } -int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) +int find_hdd_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) { uint8_t i = 0; - for (i = 0; i < HDC_NUM; i++) + for (i = 0; i < HDD_NUM; i++) { - if ((wcslen(hdc[i].fn) == 0) && (hdc[i].bus != HDD_BUS_SCSI_REMOVABLE)) + if ((wcslen(hdd[i].fn) == 0) && (hdd[i].bus != HDD_BUS_SCSI_REMOVABLE)) { continue; } - if (((hdc[i].spt == 0) || (hdc[i].hpc == 0) || (hdc[i].tracks == 0)) && (hdc[i].bus != HDD_BUS_SCSI_REMOVABLE)) + if (((hdd[i].spt == 0) || (hdd[i].hpc == 0) || (hdd[i].tracks == 0)) && (hdd[i].bus != HDD_BUS_SCSI_REMOVABLE)) { continue; } - if (((hdc[i].bus == HDD_BUS_SCSI) || (hdc[i].bus == HDD_BUS_SCSI_REMOVABLE)) && (hdc[i].scsi_id == scsi_id) && (hdc[i].scsi_lun == scsi_lun)) + if (((hdd[i].bus == HDD_BUS_SCSI) || (hdd[i].bus == HDD_BUS_SCSI_REMOVABLE)) && (hdd[i].scsi_id == scsi_id) && (hdd[i].scsi_lun == scsi_lun)) { return i; } @@ -213,19 +534,15 @@ int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) void scsi_disk_insert(uint8_t id) { - shdc[id].unit_attention = (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; + shdc[id].unit_attention = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; + scsi_hd_mode_select_terminate(id, 1); } void scsi_loadhd(int scsi_id, int scsi_lun, int id) { - int ret = 0; - - ret = hdd_image_load(id); - - if (!ret) - { - if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE) + if (! hdd_image_load(id)) { + if (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE) { scsi_hard_disks[scsi_id][scsi_lun] = 0xff; } @@ -241,14 +558,14 @@ void scsi_reloadhd(int id) { int ret = 0; - if(wcslen(hdc[id].prev_fn) == 0) + if (wcslen(hdd[id].prev_fn) == 0) { return; } else { - wcscpy(hdc[id].fn, hdc[id].prev_fn); - memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn)); + wcscpy(hdd[id].fn, hdd[id].prev_fn); + memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn)); } ret = hdd_image_load(id); @@ -280,11 +597,11 @@ void build_scsi_hd_map(void) { for (j = 0; j < 8; j++) { - scsi_hard_disks[i][j] = find_hdc_for_scsi_id(i, j); + scsi_hard_disks[i][j] = find_hdd_for_scsi_id(i, j); if (scsi_hard_disks[i][j] != 0xff) { memset(&(shdc[scsi_hard_disks[i][j]]), 0, sizeof(shdc[scsi_hard_disks[i][j]])); - if (wcslen(hdc[scsi_hard_disks[i][j]].fn) > 0) + if (wcslen(hdd[scsi_hard_disks[i][j]].fn) > 0) { scsi_loadhd(i, j, scsi_hard_disks[i][j]); } @@ -307,15 +624,332 @@ int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *l buffer[6] = 2; /* 512 = 0x0200 */ *len = 8; - scsi_hd_log("Read Capacity\n"); - scsi_hd_log("buffer[0]=%x\n", buffer[0]); - scsi_hd_log("buffer[1]=%x\n", buffer[1]); - scsi_hd_log("buffer[2]=%x\n", buffer[2]); - scsi_hd_log("buffer[3]=%x\n", buffer[3]); + return 1; +} + + +/*SCSI Mode Sense 6/10*/ +uint8_t scsi_hd_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +{ + switch (page_control) + { + case 0: + case 3: + return scsi_hd_mode_sense_pages_saved[id][page][pos]; + break; + case 1: + return scsi_hd_mode_sense_pages_changeable[id][page][pos]; + break; + case 2: + return scsi_hd_mode_sense_pages_default[id][page][pos]; + break; + } + + return 0; +} + +uint32_t scsi_hd_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) +{ + uint8_t page_control = (type >> 6) & 3; + + int i = 0; + int j = 0; + + uint8_t msplen; + + type &= 0x3f; + + if (block_descriptor_len) + { + buf[pos++] = 1; /* Density code. */ + buf[pos++] = 0; /* Number of blocks (0 = all). */ + buf[pos++] = 0; + buf[pos++] = 0; + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ + buf[pos++] = 8; + buf[pos++] = 0; + } + + for (i = 0; i < 0x40; i++) + { + if ((type == GPMODE_ALL_PAGES) || (type == i)) + { + if (scsi_hd_mode_sense_page_flags[id] & (1LL << shdc[id].current_page_code)) + { + buf[pos++] = scsi_hd_mode_sense_read(id, page_control, i, 0); + msplen = scsi_hd_mode_sense_read(id, page_control, i, 1); + buf[pos++] = msplen; + scsi_hd_log("SCSI HDD %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); + for (j = 0; j < msplen; j++) + { + buf[pos++] = scsi_hd_mode_sense_read(id, page_control, i, 2 + j); + } + } + } + } + + return pos; +} + +void scsi_hd_mode_sense_load(uint8_t id) +{ + FILE *f; + wchar_t temp[512]; + memset(temp, 0, 1024); + swprintf(temp, 512, L"scsi_hd_%02i_mode_sense.bin", id); + f = plat_fopen(nvr_path(temp), L"rb"); + if (!f) + { + return; + } + fread(scsi_hd_mode_sense_pages_saved[id][0x30], 1, 0x18, f); + fclose(f); +} + +void scsi_hd_mode_sense_save(uint8_t id) +{ + FILE *f; + wchar_t temp[512]; + memset(temp, 0, 1024); + swprintf(temp, 512, L"scsi_hd_%02i_mode_sense.bin", id); + f = plat_fopen(nvr_path(temp), L"wb"); + if (!f) + { + return; + } + fwrite(scsi_hd_mode_sense_pages_saved[id][0x30], 1, 0x18, f); + fclose(f); +} + +int scsi_hd_mode_select_init(uint8_t id, uint8_t command, uint16_t pl_length, uint8_t do_save) +{ + switch(command) + { + case GPCMD_MODE_SELECT_6: + shdc[id].current_page_len = 4; + break; + case GPCMD_MODE_SELECT_10: + shdc[id].current_page_len = 8; + break; + default: + scsi_hd_log("SCSI HDD %i: Attempting to initialize MODE SELECT with unrecognized command: %02X\n", id, command); + return -1; + } + if (pl_length == 0) + { + scsi_hd_log("SCSI HDD %i: Attempting to initialize MODE SELECT with zero parameter list length: %02X\n", id, command); + return -2; + } + shdc[id].current_page_pos = 0; + shdc[id].mode_select_phase = MODE_SELECT_PHASE_HEADER; + shdc[id].total_length = pl_length; + shdc[id].written_length = 0; + shdc[id].do_page_save = do_save; + return 1; +} + +int scsi_hd_mode_select_terminate(uint8_t id, int force) +{ + if (((shdc[id].written_length >= shdc[id].total_length) || force) && (shdc[id].mode_select_phase != MODE_SELECT_PHASE_IDLE)) + { + scsi_hd_log("SCSI HDD %i: MODE SELECT terminate: %i\n", id, force); + shdc[id].current_page_pos = shdc[id].current_page_len = shdc[id].block_descriptor_len = 0; + shdc[id].total_length = shdc[id].written_length = 0; + shdc[id].mode_select_phase = MODE_SELECT_PHASE_IDLE; + if (force) + { + scsi_hd_mode_sense_load(id); + } + return 1; + } + else + { + return 0; + } +} + +int scsi_hd_mode_select_header(uint8_t id, uint8_t val) +{ + if (shdc[id].current_page_pos == 0) + { + shdc[id].block_descriptor_len = 0; + } + else if (shdc[id].current_page_pos == (shdc[id].current_page_len - 2)) + { + if (shdc[id].current_page_len == 8) + { + shdc[id].block_descriptor_len |= ((uint16_t) val) << 8; + scsi_hd_log("SCSI HDD %i: Position: %02X, value: %02X, block descriptor length: %02X\n", id, shdc[id].current_page_pos, val, shdc[id].block_descriptor_len); + } + } + else if (shdc[id].current_page_pos == (shdc[id].current_page_len - 1)) + { + shdc[id].block_descriptor_len |= (uint16_t) val; + scsi_hd_log("SCSI HDD %i: Position: %02X, value: %02X, block descriptor length: %02X\n", id, shdc[id].current_page_pos, val, shdc[id].block_descriptor_len); + } + + shdc[id].current_page_pos++; + + if (shdc[id].current_page_pos >= shdc[id].current_page_len) + { + shdc[id].current_page_pos = 0; + if (shdc[id].block_descriptor_len) + { + shdc[id].mode_select_phase = MODE_SELECT_PHASE_BLOCK_DESC; + } + else + { + shdc[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER; + } + } return 1; } +int scsi_hd_mode_select_block_desc(uint8_t id) +{ + shdc[id].current_page_pos++; + if (shdc[id].current_page_pos >= 8) + { + shdc[id].current_page_pos = 0; + shdc[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER; + } + return 1; +} + +static void scsi_hd_invalid_field_pl(uint8_t id); + +int scsi_hd_mode_select_page_header(uint8_t id, uint8_t val) +{ + if (shdc[id].current_page_pos == 0) + { + shdc[id].current_page_code = val & 0x3f; + if (!(scsi_hd_mode_sense_page_flags[id] & (1LL << shdc[id].current_page_code))) + { + scsi_hd_log("SCSI HDD %i: Trying to modify an unimplemented page: %02X\n", id, shdc[id].current_page_code); + scsi_hd_mode_select_terminate(id, 1); + scsi_hd_invalid_field_pl(id); + } + shdc[id].current_page_pos++; + } + else if (shdc[id].current_page_pos == 1) + { + shdc[id].current_page_pos = 0; + shdc[id].current_page_len = val; + shdc[id].mode_select_phase = MODE_SELECT_PHASE_PAGE; + } + return 1; +} + +int scsi_hd_mode_select_page(uint8_t id, uint8_t val) +{ + if (scsi_hd_mode_sense_pages_changeable[id][shdc[id].current_page_code][shdc[id].current_page_pos + 2] != 0xFF) + { + if (val != scsi_hd_mode_sense_pages_saved[id][shdc[id].current_page_code][shdc[id].current_page_pos + 2]) + { + /* Trying to change an unchangeable value. */ + scsi_hd_log("SCSI HDD %i: Trying to change an unchangeable value: [%02X][%02X] = %02X (new: %02X)\n", id, shdc[id].current_page_code, shdc[id].current_page_pos + 2, scsi_hd_mode_sense_pages_saved[id][shdc[id].current_page_code][shdc[id].current_page_pos + 2], val); + scsi_hd_mode_select_terminate(id, 1); + scsi_hd_invalid_field_pl(id); + return 0; + } + } + else + { + if (shdc[id].current_page_code == 0xE) + { + if ((shdc[id].current_page_pos == 6) || (shdc[id].current_page_pos == 8)) + { + if (val > 3) + { + /* Trying to set an unsupported audio channel. */ + scsi_hd_log("SCSI HDD %i: Trying to set an unsupported value: [%02X][%02X] = %02X (new: %02X)\n", id, shdc[id].current_page_code, shdc[id].current_page_pos, scsi_hd_mode_sense_pages_saved[id][shdc[id].current_page_code][shdc[id].current_page_pos + 2], val); + return 0; + } + } + } + scsi_hd_mode_sense_pages_saved[id][shdc[id].current_page_code][shdc[id].current_page_pos + 2] = val; + } + shdc[id].current_page_pos++; + if (shdc[id].current_page_pos >= shdc[id].current_page_len) + { + shdc[id].current_page_pos = 0; + shdc[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER; + } + return 1; +} + +static void scsi_hd_command_complete(uint8_t id); + +int scsi_hd_mode_select_write(uint8_t id, uint8_t val) +{ + int ret = 0; + int ret2 = 0; + + if (id > HDD_NUM) + { + scsi_hd_log("MODE SELECT: attempted write to wrong SCSI HDD drive\n", val); + return -6; + } + + if (shdc[id].total_length == 0) + { + scsi_hd_log("SCSI HDD %i: MODE SELECT: attempted write when not initialized (%02X)\n", id, val); + return -3; + } + + shdc[id].written_length++; + + switch (shdc[id].mode_select_phase) + { + case MODE_SELECT_PHASE_IDLE: + scsi_hd_log("SCSI HDD %i: MODE SELECT idle (%02X)\n", id, val); + ret = 1; + break; + case MODE_SELECT_PHASE_HEADER: + scsi_hd_log("SCSI HDD %i: MODE SELECT header (%02X)\n", id, val); + ret = scsi_hd_mode_select_header(id, val); + break; + case MODE_SELECT_PHASE_BLOCK_DESC: + scsi_hd_log("SCSI HDD %i: MODE SELECT block descriptor (%02X)\n", id, val); + ret = scsi_hd_mode_select_block_desc(id); + break; + case MODE_SELECT_PHASE_PAGE_HEADER: + scsi_hd_log("SCSI HDD %i: MODE SELECT page header (%02X)\n", id, val); + ret = scsi_hd_mode_select_page_header(id, val); + break; + case MODE_SELECT_PHASE_PAGE: + scsi_hd_log("SCSI HDD %i: MODE SELECT page (%02X)\n", id, val); + ret = scsi_hd_mode_select_page(id, val); + if (shdc[id].mode_select_phase == MODE_SELECT_PHASE_PAGE_HEADER) + { + if (shdc[id].do_page_save && (scsi_hd_mode_sense_pages_default[id][shdc[id].current_page_code][0] & 0x80)) + { + scsi_hd_log("SCSI HDD %i: Page %i finished, saving it...\n", id, shdc[id].current_page_code); + scsi_hd_mode_sense_save(id); + } + } + break; + default: + scsi_hd_log("SCSI HDD %i: MODE SELECT unknown phase (%02X)\n", id, val); + ret = -4; + break; + } + + /* On termination, override the return value, but only if it is 1. */ + ret2 = scsi_hd_mode_select_terminate(id, 0); + if (ret2) + { + scsi_hd_command_complete(id); + } + if (ret2 && (ret == 1)) + { + ret = -5; + } + + return ret; +} void scsi_hd_update_request_length(uint8_t id, int len, int block_len) { @@ -392,6 +1026,12 @@ static void scsi_hd_command_read_dma(uint8_t id) } +static void scsi_hd_command_write(uint8_t id) +{ + shdc[id].packet_status = CDROM_PHASE_DATA_OUT; + scsi_hd_command_common(id); +} + static void scsi_hd_command_write_dma(uint8_t id) { shdc[id].packet_status = CDROM_PHASE_DATA_OUT_DMA; @@ -412,14 +1052,12 @@ void scsi_hd_data_command_finish(uint8_t id, int len, int block_len, int alloc_l } if (len == 0) { - SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength = 0; scsi_hd_command_complete(id); } else { if (direction == 0) { - SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength = alloc_len; scsi_hd_command_read_dma(id); } else @@ -441,6 +1079,7 @@ static void scsi_hd_sense_clear(int id, int command) static void scsi_hd_cmd_error(uint8_t id) { + SCSIPhase = SCSI_PHASE_STATUS; shdc[id].error = ((scsi_hd_sense_key & 0xf) << 4) | ABRT_ERR; if (shdc[id].unit_attention & 3) { @@ -456,6 +1095,7 @@ static void scsi_hd_cmd_error(uint8_t id) static void scsi_hd_unit_attention(uint8_t id) { + SCSIPhase = SCSI_PHASE_STATUS; shdc[id].error = (SENSE_NOT_READY << 4) | ABRT_ERR; if (shdc[id].unit_attention & 3) { @@ -492,6 +1132,7 @@ static void scsi_hd_invalid_lun(uint8_t id) scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; scsi_hd_asc = ASC_INV_LUN; scsi_hd_ascq = 0; + SCSIPhase = BUS_CD | BUS_IO; scsi_hd_cmd_error(id); } @@ -524,6 +1165,16 @@ static void scsi_hd_invalid_field(uint8_t id) } +static void scsi_hd_invalid_field_pl(uint8_t id) +{ + scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_hd_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + scsi_hd_ascq = 0; + scsi_hd_cmd_error(id); + shdc[id].status = 0x53; +} + + static void scsi_hd_data_phase_error(uint8_t id) { scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; @@ -546,7 +1197,7 @@ int scsi_hd_pre_execution_check(uint8_t id, uint8_t *cdb) { int ready = 1; - if (((shdc[id].request_length >> 5) & 7) != hdc[id].scsi_lun) + if (((shdc[id].request_length >> 5) & 7) != hdd[id].scsi_lun) { scsi_hd_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((shdc[id].request_length >> 5) & 7)); scsi_hd_invalid_lun(id); @@ -556,15 +1207,14 @@ int scsi_hd_pre_execution_check(uint8_t id, uint8_t *cdb) if (!(scsi_hd_command_flags[cdb[0]] & IMPLEMENTED)) { scsi_hd_log("SCSI HD %i: Attempting to execute unknown command %02X\n", id, cdb[0]); - /* pclog("SCSI HD %i: Attempting to execute unknown command %02X (%02X %02X)\n", id, cdb[0], ((cdb[1] >> 3) & 1) ? 0 : 1, cdb[2] & 0x3F); */ scsi_hd_illegal_opcode(id); return 0; } - if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) + if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { /* Removable disk, set ready state. */ - if (wcslen(hdc[id].fn) > 0) + if (wcslen(hdd[id].fn) > 0) { ready = 1; } @@ -667,6 +1317,10 @@ void scsi_hd_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length) memset(buffer, 0, alloc_length); memcpy(buffer, shdc[id].sense, alloc_length); } + else + { + return; + } buffer[0] = 0x70; @@ -677,7 +1331,7 @@ void scsi_hd_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length) buffer[13]=0x00; } - /* scsi_hd_log("SCSI HD %i: Reporting sense: %02X %02X %02X\n", id, hdbufferb[2], hdbufferb[12], hdbufferb[13]); */ + scsi_hd_log("SCSI HD %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); if (buffer[2] == SENSE_UNIT_ATTENTION) { @@ -695,10 +1349,10 @@ void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_l { int ready = 1; - if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) + if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { /* Removable disk, set ready state. */ - if (wcslen(hdc[id].fn) > 0) + if (wcslen(hdd[id].fn) > 0) { ready = 1; } @@ -730,7 +1384,7 @@ void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_l void scsi_hd_command(uint8_t id, uint8_t *cdb) { /* uint8_t *hdbufferb = (uint8_t *) shdc[id].buffer; */ - uint8_t *hdbufferb = SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].CmdBuffer; + uint8_t *hdbufferb = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].CmdBuffer; uint32_t len; int pos=0; int max_len; @@ -740,8 +1394,9 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) uint32_t alloc_length; char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - uint8_t *tempbuffer; uint32_t last_sector = 0; + int block_desc = 0; + int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength; #if 0 int CdbLength; @@ -762,7 +1417,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) device_identify_ex[12] = EMU_VERSION[2]; device_identify_ex[13] = EMU_VERSION[3]; - if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) + if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { device_identify[4] = 'R'; @@ -781,13 +1436,15 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) #if 0 for (CdbLength = 1; CdbLength < 12; CdbLength++) { - scsi_hd_log("SCSI HD %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]); + scsi_hd_log("SCSI HD %i: CDB[%d] = %d\n", id, CdbLength, cdb[CdbLength]); } #endif } shdc[id].sector_len = 0; + SCSIPhase = SCSI_PHASE_STATUS; + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ if (scsi_hd_pre_execution_check(id, cdb) == 0) { @@ -801,31 +1458,42 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) case GPCMD_VERIFY_6: case GPCMD_VERIFY_10: case GPCMD_VERIFY_12: + SCSIPhase = SCSI_PHASE_STATUS; scsi_hd_command_complete(id); break; case GPCMD_REZERO_UNIT: shdc[id].sector_pos = shdc[id].sector_len = 0; scsi_hd_seek(id, 0); + SCSIPhase = SCSI_PHASE_STATUS; break; case GPCMD_REQUEST_SENSE: /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE should forget about the not ready, and report unit attention straight away. */ - if (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength < cdb[4]) + if ((*BufLen == -1) || (cdb[4] < *BufLen)) { - cdb[4] = SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength; + *BufLen = cdb[4]; } - scsi_hd_request_sense(id, hdbufferb, cdb[4]); + + if (*BufLen < cdb[4]) + { + cdb[4] = *BufLen; + } + + SCSIPhase = SCSI_PHASE_DATA_IN; scsi_hd_data_command_finish(id, 18, 18, cdb[4], 0); break; case GPCMD_MECHANISM_STATUS: len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - memset(hdbufferb, 0, 8); - hdbufferb[5] = 1; + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + SCSIPhase = SCSI_PHASE_DATA_IN; scsi_hd_data_command_finish(id, 8, 8, len, 0); break; @@ -854,9 +1522,11 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) return; } - if ((!shdc[id].sector_len) || (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength == 0)) + if ((!shdc[id].sector_len) || (*BufLen == 0)) { - /* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */ + SCSIPhase = SCSI_PHASE_STATUS; + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + scsi_hd_log("SCSI HD %i: All done - callback set\n", id); shdc[id].packet_status = CDROM_PHASE_COMPLETE; shdc[id].callback = 20 * SCSI_TIME; break; @@ -867,18 +1537,13 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) alloc_length = shdc[id].packet_len = max_len << 9; - if ((shdc[id].requested_blocks > 0) && (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength > 0)) + if ((*BufLen == -1) || (alloc_length < *BufLen)) { - if (alloc_length > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength) - { - hdd_image_read(id, shdc[id].sector_pos, SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength >> 9, hdbufferb); - } - else - { - hdd_image_read(id, shdc[id].sector_pos, max_len, hdbufferb); - } + *BufLen = alloc_length; } + SCSIPhase = SCSI_PHASE_DATA_IN; + if (shdc[id].requested_blocks > 1) { scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 0); @@ -888,20 +1553,13 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 0); } shdc[id].all_blocks_total = shdc[id].block_total; - if (shdc[id].packet_status != CDROM_PHASE_COMPLETE) - { - update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); - } - else - { - update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - } + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); return; case GPCMD_WRITE_6: case GPCMD_WRITE_10: case GPCMD_WRITE_12: - if ((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdc[id].wp) + if ((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdd[id].wp) { scsi_hd_write_protected(id); return; @@ -912,6 +1570,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) case GPCMD_WRITE_6: shdc[id].sector_len = cdb[4]; shdc[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + scsi_hd_log("SCSI HD %i: Length: %i, LBA: %i\n", id, shdc[id].sector_len, shdc[id].sector_pos); break; case GPCMD_WRITE_10: shdc[id].sector_len = (cdb[7] << 8) | cdb[8]; @@ -930,9 +1589,11 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) return; } - if ((!shdc[id].sector_len) || (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength == 0)) + if ((!shdc[id].sector_len) || (*BufLen == 0)) { - /* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */ + SCSIPhase = SCSI_PHASE_STATUS; + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + scsi_hd_log("SCSI HD %i: All done - callback set\n", id); shdc[id].packet_status = CDROM_PHASE_COMPLETE; shdc[id].callback = 20 * SCSI_TIME; break; @@ -940,21 +1601,16 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) max_len = shdc[id].sector_len; shdc[id].requested_blocks = max_len; - + alloc_length = shdc[id].packet_len = max_len << 9; - if ((shdc[id].requested_blocks > 0) && (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength > 0)) + if ((*BufLen == -1) || (alloc_length < *BufLen)) { - if (alloc_length > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength) - { - hdd_image_write(id, shdc[id].sector_pos, SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength >> 9, hdbufferb); - } - else - { - hdd_image_write(id, shdc[id].sector_pos, max_len, hdbufferb); - } + *BufLen = alloc_length; } + SCSIPhase = SCSI_PHASE_DATA_OUT; + if (shdc[id].requested_blocks > 1) { scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 1); @@ -964,18 +1620,111 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 1); } shdc[id].all_blocks_total = shdc[id].block_total; - if (shdc[id].packet_status != CDROM_PHASE_COMPLETE) + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + SCSIPhase = SCSI_PHASE_DATA_IN; + + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { - update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); + len = cdb[4]; } else { - update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + len = (cdb[8] | (cdb[7] << 8)); } + + shdc[id].current_page_code = cdb[2] & 0x3F; + + if (!(scsi_hd_mode_sense_page_flags[id] & (1LL << shdc[id].current_page_code))) + { + scsi_hd_invalid_field(id); + return; + } + + memset(hdbufferb, 0, len); + alloc_length = len; + + shdc[id].temp_buffer = (uint8_t *) malloc(256); + if (cdb[0] == GPCMD_MODE_SENSE_6) + { + len = scsi_hd_mode_sense(id, shdc[id].temp_buffer, 4, cdb[2], block_desc); + if (len > alloc_length) + { + len = alloc_length; + } + shdc[id].temp_buffer[0] = len - 1; + shdc[id].temp_buffer[1] = 0; + if (block_desc) + { + hdbufferb[3] = 8; + } + } + else + { + len = scsi_hd_mode_sense(id, shdc[id].temp_buffer, 8, cdb[2], block_desc); + if (len > alloc_length) + { + len = alloc_length; + } + shdc[id].temp_buffer[0]=(len - 2) >> 8; + shdc[id].temp_buffer[1]=(len - 2) & 255; + shdc[id].temp_buffer[2] = 0; + if (block_desc) + { + shdc[id].temp_buffer[6] = 0; + shdc[id].temp_buffer[7] = 8; + } + } + + if (len > alloc_length) + { + len = alloc_length; + } + else if (len < alloc_length) + { + alloc_length = len; + } + + if ((*BufLen == -1) || (alloc_length < *BufLen)) + { + *BufLen = alloc_length; + } + + scsi_hd_log("SCSI HDD %i: Reading mode page: %02X...\n", id, cdb[2]); + + scsi_hd_data_command_finish(id, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + SCSIPhase = SCSI_PHASE_DATA_OUT; + + if (cdb[0] == GPCMD_MODE_SELECT_6) + { + len = cdb[4]; + } + else + { + len = (cdb[7] << 8) | cdb[8]; + } + + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + + scsi_hd_mode_select_init(id, cdb[0], len, cdb[1] & 1); + + scsi_hd_data_command_finish(id, len, len, len, 1); return; case GPCMD_START_STOP_UNIT: - if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE) + if (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE) { scsi_hd_illegal_opcode(id); break; @@ -994,6 +1743,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) break; } + SCSIPhase = SCSI_PHASE_STATUS; scsi_hd_command_complete(id); break; @@ -1002,44 +1752,47 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) max_len <<= 8; max_len |= cdb[4]; - if ((!max_len) || (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength == 0)) + if ((!max_len) || (*BufLen == 0)) { + SCSIPhase = SCSI_PHASE_STATUS; /* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */ shdc[id].packet_status = CDROM_PHASE_COMPLETE; shdc[id].callback = 20 * SCSI_TIME; break; - } - - tempbuffer = malloc(1024); + } + + shdc[id].temp_buffer = malloc(1024); if (cdb[1] & 1) { preamble_len = 4; size_idx = 3; - tempbuffer[idx++] = 05; - tempbuffer[idx++] = cdb[2]; - tempbuffer[idx++] = 0; + shdc[id].temp_buffer[idx++] = 05; + shdc[id].temp_buffer[idx++] = cdb[2]; + shdc[id].temp_buffer[idx++] = 0; idx++; switch (cdb[2]) { case 0x00: - tempbuffer[idx++] = 0x00; - tempbuffer[idx++] = 0x83; + shdc[id].temp_buffer[idx++] = 0x00; + shdc[id].temp_buffer[idx++] = 0x83; break; case 0x83: if (idx + 24 > max_len) { + free(shdc[id].temp_buffer); + shdc[id].temp_buffer = NULL; scsi_hd_data_phase_error(id); return; } - tempbuffer[idx++] = 0x02; - tempbuffer[idx++] = 0x00; - tempbuffer[idx++] = 0x00; - tempbuffer[idx++] = 20; + shdc[id].temp_buffer[idx++] = 0x02; + shdc[id].temp_buffer[idx++] = 0x00; + shdc[id].temp_buffer[idx++] = 0x00; + shdc[id].temp_buffer[idx++] = 20; ide_padstr8(hdbufferb + idx, 20, "53R141"); /* Serial */ idx += 20; @@ -1047,19 +1800,21 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) { goto atapi_out; } - tempbuffer[idx++] = 0x02; - tempbuffer[idx++] = 0x01; - tempbuffer[idx++] = 0x00; - tempbuffer[idx++] = 68; - ide_padstr8(tempbuffer + idx, 8, EMU_NAME); /* Vendor */ + shdc[id].temp_buffer[idx++] = 0x02; + shdc[id].temp_buffer[idx++] = 0x01; + shdc[id].temp_buffer[idx++] = 0x00; + shdc[id].temp_buffer[idx++] = 68; + ide_padstr8(shdc[id].temp_buffer + idx, 8, EMU_NAME); /* Vendor */ idx += 8; - ide_padstr8(tempbuffer + idx, 40, device_identify_ex); /* Product */ + ide_padstr8(shdc[id].temp_buffer + idx, 40, device_identify_ex); /* Product */ idx += 40; - ide_padstr8(tempbuffer + idx, 20, "53R141"); /* Product */ + ide_padstr8(shdc[id].temp_buffer + idx, 20, "53R141"); /* Product */ idx += 20; break; default: scsi_hd_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + free(shdc[id].temp_buffer); + shdc[id].temp_buffer = NULL; scsi_hd_invalid_field(id); return; } @@ -1069,48 +1824,53 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb) preamble_len = 5; size_idx = 4; - memset(tempbuffer, 0, 8); - tempbuffer[0] = 0; /*SCSI HD*/ - if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) + memset(shdc[id].temp_buffer, 0, 8); + shdc[id].temp_buffer[0] = 0; /*SCSI HD*/ + if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - tempbuffer[1] = 0x80; /*Removable*/ + shdc[id].temp_buffer[1] = 0x80; /*Removable*/ } else { - tempbuffer[1] = 0; /*Fixed*/ + shdc[id].temp_buffer[1] = 0; /*Fixed*/ } - tempbuffer[2] = 0x02; /*SCSI-2 compliant*/ - tempbuffer[3] = 0x02; - tempbuffer[4] = 31; + shdc[id].temp_buffer[2] = 0x02; /*SCSI-2 compliant*/ + shdc[id].temp_buffer[3] = 0x02; + shdc[id].temp_buffer[4] = 31; - ide_padstr8(tempbuffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(tempbuffer + 16, 16, device_identify); /* Product */ - ide_padstr8(tempbuffer + 32, 4, EMU_VERSION); /* Revision */ + ide_padstr8(shdc[id].temp_buffer + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(shdc[id].temp_buffer + 16, 16, device_identify); /* Product */ + ide_padstr8(shdc[id].temp_buffer + 32, 4, EMU_VERSION); /* Revision */ idx = 36; } atapi_out: - tempbuffer[size_idx] = idx - preamble_len; + shdc[id].temp_buffer[size_idx] = idx - preamble_len; len=idx; + scsi_hd_log("scsi_hd_command(): Inquiry (%08X, %08X)\n", hdbufferb, shdc[id].temp_buffer); + if (len > max_len) { len = max_len; } - - if (len > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength) + + if ((*BufLen == -1) || (len < *BufLen)) { - len = SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength; + *BufLen = len; } - memcpy(hdbufferb, tempbuffer, len); - - free(tempbuffer); + if (len > *BufLen) + { + len = *BufLen; + } + SCSIPhase = SCSI_PHASE_DATA_IN; scsi_hd_data_command_finish(id, len, len, max_len, 0); break; case GPCMD_PREVENT_REMOVAL: + SCSIPhase = SCSI_PHASE_STATUS; scsi_hd_command_complete(id); break; @@ -1126,28 +1886,199 @@ atapi_out: break; } scsi_hd_seek(id, pos); + + SCSIPhase = SCSI_PHASE_STATUS; scsi_hd_command_complete(id); break; case GPCMD_READ_CDROM_CAPACITY: - if (scsi_hd_read_capacity(id, shdc[id].current_cdb, hdbufferb, &len) == 0) + shdc[id].temp_buffer = (uint8_t *) malloc(8); + + if (scsi_hd_read_capacity(id, shdc[id].current_cdb, shdc[id].temp_buffer, &len) == 0) { + SCSIPhase = SCSI_PHASE_STATUS; return; } + if ((*BufLen == -1) || (len < *BufLen)) + { + *BufLen = len; + } + + SCSIPhase = SCSI_PHASE_DATA_IN; scsi_hd_data_command_finish(id, len, len, len, 0); break; default: - /* pclog("SCSI HD %i: Attempting to execute pseudo-implemented command %02X\n", id, cdb[0]); */ scsi_hd_illegal_opcode(id); break; } - + /* scsi_hd_log("SCSI HD %i: Phase: %02X, request length: %i\n", shdc[id].phase, shdc[id].request_length); */ } +/* 0 = Continue transfer; 1 = Continue transfer, IRQ; -1 = Terminate transfer; -2 = Terminate transfer with error */ +int scsi_hd_mode_select_return(uint8_t id, int ret) +{ + switch(ret) + { + case 0: + /* Invalid field in parameter list. */ + case -6: + /* Attempted to write to a non-existent SCSI HDD drive (should never occur, but you never know). */ + scsi_hd_invalid_field_pl(id); + return -2; + case 1: + /* Successful, more data needed. */ + if (shdc[id].pos >= (shdc[id].packet_len + 2)) + { + shdc[id].pos = 0; + scsi_hd_command_write(id); + return 1; + } + return 0; + case 2: + /* Successful, more data needed, second byte not yet processed. */ + return 0; + case -3: + /* Not initialized. */ + case -4: + /* Unknown phase. */ + scsi_hd_illegal_opcode(id); + return -2; + case -5: + /* Command terminated successfully. */ + /* scsi_hd_command_complete(id); */ + return -1; + default: + return -15; + } +} + +void scsi_hd_phase_data_in(uint8_t id) +{ + uint8_t *hdbufferb = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].CmdBuffer; + int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength; + + if (!*BufLen) + { + scsi_hd_log("scsi_hd_phase_data_in(): Buffer length is 0\n"); + SCSIPhase = SCSI_PHASE_STATUS; + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + + return; + } + + switch (shdc[id].current_cdb[0]) + { + case GPCMD_REQUEST_SENSE: + scsi_hd_log("SCSI HDD %i: %08X, %08X\n", id, hdbufferb, *BufLen); + scsi_hd_request_sense(id, hdbufferb, *BufLen); + break; + case GPCMD_MECHANISM_STATUS: + memset(hdbufferb, 0, *BufLen); + hdbufferb[5] = 1; + break; + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + if ((shdc[id].requested_blocks > 0) && (*BufLen > 0)) + { + if (shdc[id].packet_len > *BufLen) + { + hdd_image_read(id, shdc[id].sector_pos, *BufLen >> 9, hdbufferb); + } + else + { + hdd_image_read(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb); + } + } + break; + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + case GPCMD_INQUIRY: + case GPCMD_READ_CDROM_CAPACITY: + scsi_hd_log("scsi_hd_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, shdc[id].temp_buffer); + memcpy(hdbufferb, shdc[id].temp_buffer, *BufLen); + free(shdc[id].temp_buffer); + shdc[id].temp_buffer = NULL; + scsi_hd_log("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7], + hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]); + break; + default: + fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", shdc[id].current_cdb[0]); + break; + } + + SCSIPhase = SCSI_PHASE_STATUS; + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); +} + +void scsi_hd_phase_data_out(uint8_t id) +{ + int ret = 0; + uint8_t *hdbufferb = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].CmdBuffer; + + int in_data_length = 0; + int i; + + int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength; + + if (!*BufLen) + { + SCSIPhase = SCSI_PHASE_STATUS; + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + + return; + } + + switch (shdc[id].current_cdb[0]) + { + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_12: + if ((shdc[id].requested_blocks > 0) && (*BufLen > 0)) + { + if (shdc[id].packet_len > *BufLen) + { + hdd_image_write(id, shdc[id].sector_pos, *BufLen >> 9, hdbufferb); + } + else + { + hdd_image_write(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb); + } + } + break; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + in_data_length = *BufLen; + + for (i = 0; i < in_data_length; i++) + { + ret = scsi_hd_mode_select_write(id, hdbufferb[i]); + ret = scsi_hd_mode_select_return(id, ret); + if (ret == -1) + { + return; + } + else if (ret == -2) + { + scsi_hd_callback(id); + return; + } + } + break; + default: + fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", shdc[id].current_cdb[0]); + break; + } + + SCSIPhase = SCSI_PHASE_STATUS; + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); +} + /* If the result is 1, issue an IRQ, otherwise not. */ void scsi_hd_callback(uint8_t id) { @@ -1164,7 +2095,7 @@ void scsi_hd_callback(uint8_t id) shdc[id].status = READY_STAT; shdc[id].phase = 3; shdc[id].packet_status = 0xFF; - update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); return; case CDROM_PHASE_DATA_OUT: scsi_hd_log("SCSI HD %i: PHASE_DATA_OUT\n", id); @@ -1173,10 +2104,11 @@ void scsi_hd_callback(uint8_t id) return; case CDROM_PHASE_DATA_OUT_DMA: scsi_hd_log("SCSI HD %i: PHASE_DATA_OUT_DMA\n", id); + scsi_hd_phase_data_out(id); shdc[id].packet_status = CDROM_PHASE_COMPLETE; shdc[id].status = READY_STAT; shdc[id].phase = 3; - update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); return; case CDROM_PHASE_DATA_IN: scsi_hd_log("SCSI HD %i: PHASE_DATA_IN\n", id); @@ -1185,10 +2117,11 @@ void scsi_hd_callback(uint8_t id) return; case CDROM_PHASE_DATA_IN_DMA: scsi_hd_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", id); + scsi_hd_phase_data_in(id); shdc[id].packet_status = CDROM_PHASE_COMPLETE; shdc[id].status = READY_STAT; shdc[id].phase = 3; - update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); return; case CDROM_PHASE_ERROR: scsi_hd_log("SCSI HD %i: PHASE_ERROR\n", id); diff --git a/src/scsi/scsi_disk.h b/src/scsi/scsi_disk.h index c6c8991ad..5a1a48c4f 100644 --- a/src/scsi/scsi_disk.h +++ b/src/scsi/scsi_disk.h @@ -6,13 +6,13 @@ * * Emulation of SCSI fixed and removable disks. * - * Version: @(#)scsi_disk.h 1.0.1 2017/08/23 + * Version: @(#)scsi_disk.h 1.0.3 2017/10/14 * * Author: Miran Grca, * Copyright 2017 Miran Grca. */ -#pragma pack(push,1) + typedef struct { /* Stuff for SCSI hard disks. */ uint8_t cdb[16]; @@ -41,16 +41,31 @@ typedef struct { int old_len; int request_pos; uint8_t hd_cdb[16]; -} scsi_hard_disk_t; -#pragma pack(pop) -extern scsi_hard_disk_t shdc[HDC_NUM]; + uint64_t current_page_code; + int current_page_len; + + int current_page_pos; + + int mode_select_phase; + + int total_length; + int written_length; + + int do_page_save; + int block_descriptor_len; + + uint8_t *temp_buffer; +} scsi_hard_disk_t; + + +extern scsi_hard_disk_t shdc[HDD_NUM]; +extern FILE *shdf[HDD_NUM]; + extern void scsi_disk_insert(uint8_t id); extern void scsi_loadhd(int scsi_id, int scsi_lun, int id); extern void scsi_reloadhd(int id); extern void scsi_unloadhd(int scsi_id, int scsi_lun, int id); -extern FILE *shdf[HDC_NUM]; - int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c new file mode 100644 index 000000000..5f2f24ee2 --- /dev/null +++ b/src/scsi/scsi_ncr5380.c @@ -0,0 +1,869 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the NCR 5380 series of SCSI Host Adapters + * made by NCR. These controllers were designed for the ISA bus. + * + * Version: @(#)scsi_ncr5380.c 1.0.3 2017/10/10 + * + * Authors: Sarah Walker, + * TheCollector1995, + */ +#include +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../io.h" +#include "../mca.h" +#include "../mem.h" +#include "../mca.h" +#include "../rom.h" +#include "../nvr.h" +#include "../dma.h" +#include "../pic.h" +#include "../timer.h" +#include "../device.h" +#include "../plat.h" +#include "scsi.h" +#include "scsi_device.h" +#include "scsi_ncr5380.h" + + +//#define ENABLE_NCR5380_LOG 1 + + +#define LCS6821N_ROM L"roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin" +#define RT1000B_ROM L"roms/scsi/ncr5380/Rancho_RT1000_RTBios_version_8.10R.bin" +#define T130B_ROM L"roms/scsi/ncr5380/trantor_t130b_bios_v2.14.bin" + + +#define NCR_CURDATA 0 /* current SCSI data (read only) */ +#define NCR_OUTDATA 0 /* output data (write only) */ +#define NCR_INITCOMMAND 1 /* initiator command (read/write) */ +#define NCR_MODE 2 /* mode (read/write) */ +#define NCR_TARGETCMD 3 /* target command (read/write) */ +#define NCR_SELENABLE 4 /* select enable (write only) */ +#define NCR_BUSSTATUS 4 /* bus status (read only) */ +#define NCR_STARTDMA 5 /* start DMA send (write only) */ +#define NCR_BUSANDSTAT 5 /* bus and status (read only) */ +#define NCR_DMATARGET 6 /* DMA target (write only) */ +#define NCR_INPUTDATA 6 /* input data (read only) */ +#define NCR_DMAINIRECV 7 /* DMA initiator receive (write only) */ +#define NCR_RESETPARITY 7 /* reset parity/interrupt (read only) */ + +#define POLL_TIME_US 10LL +#define MAX_BYTES_TRANSFERRED_PER_POLL 50 +/*10us poll period with 50 bytes transferred per poll = 5MB/sec*/ + + +#define ICR_DBP 0x01 +#define ICR_ATN 0x02 +#define ICR_SEL 0x04 +#define ICR_BSY 0x08 +#define ICR_ACK 0x10 +#define ICR_ARB_LOST 0x20 +#define ICR_ARB_IN_PROGRESS 0x40 + +#define MODE_ARBITRATE 0x01 +#define MODE_DMA 0x02 +#define MODE_MONITOR_BUSY 0x04 +#define MODE_ENA_EOP_INT 0x08 + +#define STATUS_ACK 0x01 +#define STATUS_BUSY_ERROR 0x04 +#define STATUS_INT 0x10 +#define STATUS_DRQ 0x40 +#define STATUS_END_OF_DMA 0x80 + +#define TCR_IO 0x01 +#define TCR_CD 0x02 +#define TCR_MSG 0x04 +#define TCR_REQ 0x08 +#define TCR_LAST_BYTE_SENT 0x80 + +#define CTRL_DATA_DIR (1<<6) +#define STATUS_BUFFER_NOT_READY (1<<2) +#define STATUS_53C80_ACCESSIBLE (1<<7) + + +typedef struct { + uint8_t icr; + uint8_t mode; + uint8_t tcr; + uint8_t ser; + uint8_t isr; + uint8_t output_data; + + int target_bsy; + int target_req; + uint8_t target_id; + + uint8_t bus_status; + + int dma_mode; + + scsi_bus_t bus; +} ncr5380_t; + +typedef struct { + rom_t bios_rom; + mem_mapping_t mapping; + + uint8_t block_count; + int block_count_loaded; + + uint8_t status_ctrl; + + uint8_t buffer[0x80]; + int buffer_pos; + int buffer_host_pos; + + uint8_t int_ram[0x40]; + uint8_t ext_ram[0x600]; + + ncr5380_t ncr; + int ncr5380_dma_enabled; + + int64_t dma_callback; + int64_t dma_enabled; + + int ncr_busy; +} ncr_t; + + +enum { + DMA_IDLE = 0, + DMA_SEND, + DMA_TARGET_RECEIVE, + DMA_INITIATOR_RECEIVE +}; + + +#ifdef ENABLE_NCR5380_LOG +int ncr5380_do_log = ENABLE_NCR5380_LOG; +#endif + + +static void +ncr_log(const char *fmt, ...) +{ +#if ENABLE_NCR5380_LOG + va_list ap; + + if (ncr5380_do_log) { + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + fflush(stdout); + } +#endif +} + + +static void +ncr_dma_changed(void *p, int mode, int enable) +{ + ncr_t *scsi = (ncr_t *)p; + + scsi->ncr5380_dma_enabled = (mode && enable); + + scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded); +} + + +void +ncr5380_reset(ncr5380_t *ncr) +{ + memset(ncr, 0x00, sizeof(ncr5380_t)); +} + + +static uint32_t +get_bus_host(ncr5380_t *ncr) +{ + uint32_t bus_host = 0; + + if (ncr->icr & ICR_DBP) + bus_host |= BUS_DBP; + if (ncr->icr & ICR_SEL) + bus_host |= BUS_SEL; + if (ncr->icr & ICR_ATN) + bus_host |= BUS_ATN; + if (ncr->tcr & TCR_IO) + bus_host |= BUS_IO; + if (ncr->tcr & TCR_CD) + bus_host |= BUS_CD; + if (ncr->tcr & TCR_MSG) + bus_host |= BUS_MSG; + if (ncr->tcr & TCR_REQ) + bus_host |= BUS_REQ; + if (ncr->icr & ICR_BSY) + bus_host |= BUS_BSY; + if (ncr->icr & ICR_ACK) + bus_host |= BUS_ACK; + if (ncr->mode & MODE_ARBITRATE) + bus_host |= BUS_ARB; + + return(bus_host | BUS_SETDATA(ncr->output_data)); +} + + +static void +ncr_write(uint16_t port, uint8_t val, void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr = &scsi->ncr; + int bus_host = 0; + +#if ENABLE_NCR5380_LOG + ncr_log("ncr5380_write: addr=%06x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc); +#endif + switch (port & 7) { + case 0: /* Output data register */ + ncr->output_data = val; + break; + + case 1: /* Initiator Command Register */ + if ((val & (ICR_BSY | ICR_SEL)) == (ICR_BSY | ICR_SEL) && + (ncr->icr & (ICR_BSY | ICR_SEL)) == ICR_SEL) { + uint8_t temp = ncr->output_data & 0x7f; + + ncr->target_id = -1; + while (temp) { + temp >>= 1; + ncr->target_id++; + } + + ncr_log("Select - target ID = %i, temp data %x\n", ncr->target_id, temp); + } + ncr->icr = val; + break; + + case 2: /* Mode register */ + if ((val & MODE_ARBITRATE) && !(ncr->mode & MODE_ARBITRATE)) { + ncr->icr &= ~ICR_ARB_LOST; + ncr->icr |= ICR_ARB_IN_PROGRESS; + } + ncr->mode = val; + ncr_dma_changed(scsi, ncr->dma_mode, ncr->mode & MODE_DMA); + if (!(ncr->mode & MODE_DMA)) { + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + ncr->dma_mode = DMA_IDLE; + } + break; + + case 3: /* Target Command Register */ + ncr->tcr = val; + break; + + case 4: /* Select Enable Register */ + ncr->ser = val; + break; + + case 5: /* start DMA Send */ + ncr->dma_mode = DMA_SEND; + ncr_dma_changed(scsi, ncr->dma_mode, ncr->mode & MODE_DMA); + break; + + case 7: /* start DMA Initiator Receive */ + ncr->dma_mode = DMA_INITIATOR_RECEIVE; + ncr_dma_changed(scsi, ncr->dma_mode, ncr->mode & MODE_DMA); + break; + + default: +#if 1 + pclog("Bad NCR5380 write %06x %02x\n", port, val); +#endif + break; + } + + bus_host = get_bus_host(ncr); + + scsi_bus_update(&ncr->bus, bus_host); +} + + +static uint8_t +ncr_read(uint16_t port, void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr = &scsi->ncr; + uint32_t bus = 0; + uint8_t temp = 0xff; + + switch (port & 7) { + case 0: /* current SCSI data */ + if (ncr->icr & ICR_DBP) { + temp = ncr->output_data; + } else { + bus = scsi_bus_read(&ncr->bus); + temp = BUS_GETDATA(bus); + } + break; + + case 1: /* Initiator Command Register */ + temp = ncr->icr; + break; + + case 2: /* Mode register */ + temp = ncr->mode; + break; + + case 3: /* Target Command Register */ + temp = ncr->tcr; + break; + + case 4: /* Current SCSI Bus status */ + temp = 0; + bus = scsi_bus_read(&ncr->bus); + temp |= (bus & 0xff); + break; + + case 5: /* Bus and Status register */ + temp = 0; + + bus = get_bus_host(ncr); + if (scsi_bus_match(&ncr->bus, bus)) + temp |= 8; + bus = scsi_bus_read(&ncr->bus); + + if (bus & BUS_ACK) + temp |= STATUS_ACK; + if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) + temp |= STATUS_DRQ; + if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) { + int bus_state = 0; + + if (bus & BUS_IO) + bus_state |= TCR_IO; + if (bus & BUS_CD) + bus_state |= TCR_CD; + if (bus & BUS_MSG) + bus_state |= TCR_MSG; + if ((ncr->tcr & 7) != bus_state) + ncr->isr |= STATUS_INT; + } + if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) + temp |= STATUS_BUSY_ERROR; + temp |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA)); + break; + + case 7: /* reset Parity/Interrupt */ + ncr->isr &= ~STATUS_INT; + break; + + default: + ncr_log("Bad NCR5380 read %06x\n", port); + break; + } + +#if ENABLE_NCR5380_LOG + ncr_log("ncr5380_read: addr=%06x temp=%02x pc=%04x:%04x\n", port, temp, CS,cpu_state.pc); +#endif + return(temp); +} + + + +static void +ncr_dma_callback(void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr = &scsi->ncr; + int bytes_transferred = 0; + int c; + + scsi->dma_callback += POLL_TIME_US; + + switch (scsi->ncr.dma_mode) { + case DMA_SEND: + if (scsi->status_ctrl & CTRL_DATA_DIR) { + ncr_log("DMA_SEND with DMA direction set wrong\n"); + break; + } + + if (!(scsi->status_ctrl & STATUS_BUFFER_NOT_READY)) { + break; + } + + if (! scsi->block_count_loaded) break; + + while (bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL) { + int bus; + uint8_t data; + + for (c = 0; c < 10; c++) { + uint8_t status = scsi_bus_read(&ncr->bus); + + if (status & BUS_REQ) break; + } + if (c == 10) break; + + /* Data ready. */ + data = scsi->buffer[scsi->buffer_pos]; + bus = get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(data); + + scsi_bus_update(&ncr->bus, bus | BUS_ACK); + scsi_bus_update(&ncr->bus, bus & ~BUS_ACK); + + bytes_transferred++; + if (++scsi->buffer_pos == 128) { + scsi->buffer_pos = 0; + scsi->buffer_host_pos = 0; + scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + scsi->block_count = (scsi->block_count - 1) & 255; + scsi->ncr_busy = 0; + if (! scsi->block_count) { + scsi->block_count_loaded = 0; + scsi->dma_enabled = 0; + + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) + ncr->isr |= STATUS_INT; + } + break; + } + } + break; + + case DMA_INITIATOR_RECEIVE: + if (!(scsi->status_ctrl & CTRL_DATA_DIR)) { + ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); + break; + } + + if (!(scsi->status_ctrl & STATUS_BUFFER_NOT_READY)) break; + + if (!scsi->block_count_loaded) break; + + while (bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL) { + int bus; + uint8_t temp; + + for (c = 0; c < 10; c++) { + uint8_t status = scsi_bus_read(&ncr->bus); + + if (status & BUS_REQ) break; + } + if (c == 10) break; + + /* Data ready. */ + bus = scsi_bus_read(&ncr->bus); + temp = BUS_GETDATA(bus); + bus = get_bus_host(ncr); + + scsi_bus_update(&ncr->bus, bus | BUS_ACK); + scsi_bus_update(&ncr->bus, bus & ~BUS_ACK); + + bytes_transferred++; + scsi->buffer[scsi->buffer_pos++] = temp; + if (scsi->buffer_pos == 128) { + scsi->buffer_pos = 0; + scsi->buffer_host_pos = 0; + scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + scsi->block_count = (scsi->block_count - 1) & 255; + if (!scsi->block_count) { + scsi->block_count_loaded = 0; + scsi->dma_enabled = 0; + + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) + ncr->isr |= STATUS_INT; + } + break; + } + } + break; + + default: +#if 1 + pclog("DMA callback bad mode %i\n", scsi->ncr.dma_mode); +#endif + break; + } + + c = scsi_bus_read(&ncr->bus); + if (!(c & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + ncr->mode &= ~MODE_DMA; + ncr->dma_mode = DMA_IDLE; + ncr_dma_changed(scsi, ncr->dma_mode, ncr->mode & MODE_DMA); + } +} + + +/* I/O handlers for the LCS6821N and TR1000B. */ +static uint8_t +lcs6821n_read(uint32_t addr, void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + uint8_t temp = 0xff; + + addr &= 0x3fff; +#if ENABLE_NCR5380_LOG + ncr_log("lcs6821n_read %08x\n", addr); +#endif + + if (addr < 0x2000) + temp = scsi->bios_rom.rom[addr & 0x1fff]; + else if (addr < 0x3800) + temp = 0xff; + else if (addr >= 0x3a00) + temp = scsi->ext_ram[addr - 0x3a00]; + else switch (addr & 0x3f80) { + case 0x3800: +#if ENABLE_NCR5380_LOG + ncr_log("Read intRAM %02x %02x\n", addr & 0x3f, scsi->int_ram[addr & 0x3f]); +#endif + temp = scsi->int_ram[addr & 0x3f]; + break; + + case 0x3880: +#if ENABLE_NCR5380_LOG + ncr_log("Read 53c80 %04x\n", addr); +#endif + temp = ncr_read(addr, scsi); + break; + + case 0x3900: +#if ENABLE_NCR5380_LOG + ncr_log(" Read 3900 %i %02x\n", scsi->buffer_host_pos, scsi->status_ctrl); +#endif + if (scsi->buffer_host_pos >= 128 || !(scsi->status_ctrl & CTRL_DATA_DIR)) + temp = 0xff; + else { + temp = scsi->buffer[scsi->buffer_host_pos++]; + + if (scsi->buffer_host_pos == 128) + scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; + } + break; + + case 0x3980: + switch (addr) { + case 0x3980: /* status */ + temp = scsi->status_ctrl;// | 0x80; + if (! scsi->ncr_busy) + temp |= STATUS_53C80_ACCESSIBLE; + break; + + case 0x3981: /* block counter register*/ + temp = scsi->block_count; + break; + + case 0x3982: /* switch register read */ + temp = 0xff; + break; + + case 0x3983: + temp = 0xff; + break; + } + break; + } + +#if ENABLE_NCR5380_LOG + if (addr >= 0x3880) + ncr_log("lcs6821n_read: addr=%05x val=%02x\n", addr, temp); +#endif + + return(temp); +} + + +static void +lcs6821n_write(uint32_t addr, uint8_t val, void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + + addr &= 0x3fff; + +#if ENABLE_NCR5380_LOG + ncr_log("lcs6821n_write: addr=%05x val=%02x %04x:%04x %i %02x\n", addr, val, CS,cpu_state.pc, scsi->buffer_host_pos, scsi->status_ctrl); +#endif + + if (addr >= 0x3a00) + scsi->ext_ram[addr - 0x3a00] = val; + else switch (addr & 0x3f80) { + case 0x3800: +#if 0 + ncr_log("Write intram %02x %02x\n", addr & 0x3f, val); +#endif + scsi->int_ram[addr & 0x3f] = val; + break; + + case 0x3880: +#if ENABLE_NCR5380_LOG + ncr_log("Write 53c80 %04x %02x\n", addr, val); +#endif + ncr_write(addr, val, scsi); + break; + + case 0x3900: + if (!(scsi->status_ctrl & CTRL_DATA_DIR) && scsi->buffer_host_pos < 128) { + scsi->buffer[scsi->buffer_host_pos++] = val; + if (scsi->buffer_host_pos == 128) { + scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; + scsi->ncr_busy = 1; + } + } + break; + + case 0x3980: + switch (addr) { + case 0x3980: /* Control */ + if ((val & CTRL_DATA_DIR) && !(scsi->status_ctrl & CTRL_DATA_DIR)) { + scsi->buffer_host_pos = 128; + scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; + } + else if (!(val & CTRL_DATA_DIR) && (scsi->status_ctrl & CTRL_DATA_DIR)) { + scsi->buffer_host_pos = 0; + scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + } + scsi->status_ctrl = (scsi->status_ctrl & 0x87) | (val & 0x78); + break; + + case 0x3981: /* block counter register */ + scsi->block_count = val; + scsi->block_count_loaded = 1; + scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded); + if (scsi->status_ctrl & CTRL_DATA_DIR) { + scsi->buffer_host_pos = 128; + scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; + } else { + scsi->buffer_host_pos = 0; + scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + } + break; + } + break; + } +} + + +/* I/O handlers for the Trantor T130B. */ +static uint8_t +t130b_read(uint32_t addr, void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + uint8_t ret = 0xff; + + addr &= 0x3fff; + if (addr < 0x1800) + ret = scsi->bios_rom.rom[addr & 0x1fff]; + else + if (addr < 0x1880) + ret = scsi->ext_ram[addr & 0x7f]; + + return(ret); +} + + +static void +t130b_write(uint32_t addr, uint8_t val, void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + + addr &= 0x3fff; + if (addr >= 0x1800 && addr < 0x1880) + scsi->ext_ram[addr & 0x7f] = val; +} + + +static uint8_t +t130b_in(uint16_t port, void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + uint8_t ret = 0xff; + + switch (port & 0xf) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + ret = lcs6821n_read((port & 7) | 0x3980, scsi); + break; + + case 0x04: + case 0x05: + ret = lcs6821n_read(0x3900, scsi); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ret = ncr_read(port, scsi); + break; + } + + return(ret); +} + + +static void +t130b_out(uint16_t port, uint8_t val, void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + + switch (port & 0x0f) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + lcs6821n_write((port & 7) | 0x3980, val, scsi); + break; + + case 0x04: + case 0x05: + lcs6821n_write(0x3900, val, scsi); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ncr_write(port, val, scsi); + break; + } +} + + +static void * +ncr_init(device_t *info) +{ + ncr_t *scsi; + + scsi = malloc(sizeof(ncr_t)); + memset(scsi, 0x00, sizeof(ncr_t)); + + switch(info->local) { + case 0: /* Longshine LCS6821N */ + rom_init(&scsi->bios_rom, LCS6821N_ROM, + 0xdc000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_disable(&scsi->bios_rom.mapping); + + mem_mapping_add(&scsi->mapping, 0xdc000, 0x4000, + lcs6821n_read, NULL, NULL, + lcs6821n_write, NULL, NULL, + scsi->bios_rom.rom, 0, scsi); + break; + + case 1: /* Ranco RT1000B */ + rom_init(&scsi->bios_rom, RT1000B_ROM, + 0xdc000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_disable(&scsi->bios_rom.mapping); + + mem_mapping_add(&scsi->mapping, 0xdc000, 0x4000, + lcs6821n_read, NULL, NULL, + lcs6821n_write, NULL, NULL, + scsi->bios_rom.rom, 0, scsi); + break; + + case 2: /* Trantor T130B */ + rom_init(&scsi->bios_rom, T130B_ROM, + 0xdc000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_add(&scsi->mapping, 0xdc000, 0x4000, + t130b_read, NULL, NULL, + t130b_write, NULL, NULL, + scsi->bios_rom.rom, 0, scsi); + + io_sethandler(0x0350, 16, + t130b_in,NULL,NULL, t130b_out,NULL,NULL, scsi); + break; + } + + ncr5380_reset(&scsi->ncr); + + scsi->status_ctrl = STATUS_BUFFER_NOT_READY; + scsi->buffer_host_pos = 128; + + timer_add(ncr_dma_callback, &scsi->dma_callback, &scsi->dma_enabled, scsi); + + return(scsi); +} + + +static void +ncr_close(void *priv) +{ + ncr_t *scsi = (ncr_t *)priv; + + free(scsi); +} + + +static int +lcs6821n_available(void) +{ + return(rom_present(LCS6821N_ROM)); +} + + +static int +rt1000b_available(void) +{ + return(rom_present(RT1000B_ROM)); +} + + +static int +t130b_available(void) +{ + return(rom_present(T130B_ROM)); +} + + +device_t scsi_lcs6821n_device = +{ + "Longshine LCS-6821N (SCSI)", + DEVICE_ISA, + 0, + ncr_init, ncr_close, NULL, + lcs6821n_available, + NULL, NULL, NULL, + NULL +}; + +device_t scsi_rt1000b_device = +{ + "Ranco RT1000B (SCSI)", + DEVICE_ISA, + 1, + ncr_init, ncr_close, NULL, + rt1000b_available, + NULL, NULL, NULL, + NULL +}; + +device_t scsi_t130b_device = +{ + "Trantor T130B (SCSI)", + DEVICE_ISA, + 2, + ncr_init, ncr_close, NULL, + t130b_available, + NULL, NULL, NULL, + NULL +}; diff --git a/src/scsi/scsi_ncr5380.h b/src/scsi/scsi_ncr5380.h new file mode 100644 index 000000000..64f962528 --- /dev/null +++ b/src/scsi/scsi_ncr5380.h @@ -0,0 +1,27 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the NCR 5380 series of SCSI Host Adapters + * made by NCR. These controllers were designed for + * the ISA bus. + * + * Version: @(#)scsi_ncr5380.c 1.0.0 2017/10/04 + * + * Authors: Sarah Walker, + * TheCollector1995, + */ +#ifndef SCSI_NCR5380_H +# define SCSI_NCR5380_H + + +extern device_t scsi_lcs6821n_device; +extern device_t scsi_rt1000b_device; +extern device_t scsi_t130b_device; + + +#endif /*SCSI_NCR5380_H*/ diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c new file mode 100644 index 000000000..4854d6cee --- /dev/null +++ b/src/scsi/scsi_x54x.c @@ -0,0 +1,1977 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the code common to the AHA-154x series of + * SCSI Host Adapters made by Adaptec, Inc. and the BusLogic + * series of SCSI Host Adapters made by Mylex. + * These controllers were designed for various buses. + * + * Version: @(#)scsi_x54x.c 1.0.0 2017/10/14 + * + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../io.h" +#include "../mca.h" +#include "../mem.h" +#include "../mca.h" +#include "../rom.h" +#include "../nvr.h" +#include "../dma.h" +#include "../pci.h" +#include "../pic.h" +#include "../timer.h" +#include "../device.h" +#include "../plat.h" +#include "scsi.h" +#include "scsi_device.h" +#include "scsi_aha154x.h" +#include "scsi_x54x.h" + + +static void x54x_cmd_thread(void *priv); + +static thread_t *poll_tid; +static int busy; + +static event_t *evt; + +static event_t *poll_complete; + + +#ifdef ENABLE_X54X_LOG +int x54x_do_log = ENABLE_X54X_LOG; +#endif + + +static void +x54x_log(const char *fmt, ...) +{ +#if ENABLE_X54X_LOG + va_list ap; + + if (x54x_do_log) { + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + fflush(stdout); + } +#endif +} + + +static void +x54x_irq(x54x_t *dev, int set) +{ + int int_type = 0; + int irq; + + if (dev->ven_get_irq) + irq = dev->ven_get_irq(dev); + else + irq = dev->Irq; + + if (dev->bus & DEVICE_PCI) + { + x54x_log("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); + if (set) + { + pci_set_irq(dev->pci_slot, PCI_INTA); + } + else + { + pci_clear_irq(dev->pci_slot, PCI_INTA); + } + } + else + { + if (set) + { + if (dev->interrupt_type) + int_type = dev->interrupt_type(dev); + + if (int_type) + { + picintlevel(1 << irq); + } + else + { + picint(1 << irq); + } + } + else + { + picintc(1 << irq); + } + } +} + + +static void +raise_irq(x54x_t *dev, int suppress, uint8_t Interrupt) +{ + if (Interrupt & (INTR_MBIF | INTR_MBOA)) { + if (! (dev->Interrupt & INTR_HACC)) { + dev->Interrupt |= Interrupt; /* Report now. */ + } else { + dev->PendingInterrupt |= Interrupt; /* Report later. */ + } + } else if (Interrupt & INTR_HACC) { + if (dev->Interrupt == 0 || dev->Interrupt == (INTR_ANY | INTR_HACC)) { + x54x_log("%s: RaiseInterrupt(): Interrupt=%02X\n", + dev->name, dev->Interrupt); + } + dev->Interrupt |= Interrupt; + } else { + x54x_log("%s: RaiseInterrupt(): Invalid interrupt state!\n", dev->name); + } + + dev->Interrupt |= INTR_ANY; + + if (dev->IrqEnabled && !suppress) + x54x_irq(dev, 1); +} + + +static void +clear_irq(x54x_t *dev) +{ + dev->Interrupt = 0; + x54x_log("%s: lowering IRQ %i (stat 0x%02x)\n", + dev->name, dev->Irq, dev->Interrupt); + x54x_irq(dev, 0); + if (dev->PendingInterrupt) { + x54x_log("%s: Raising Interrupt 0x%02X (Pending)\n", + dev->name, dev->Interrupt); + if (dev->MailboxOutInterrupts || !(dev->Interrupt & INTR_MBOA)) { + raise_irq(dev, 0, dev->PendingInterrupt); + } + dev->PendingInterrupt = 0; + } +} + + +static void +x54x_reset(x54x_t *dev) +{ + dev->ResetCB = 0LL; + + dev->Status = STAT_IDLE | STAT_INIT; + dev->Geometry = 0x80; + dev->Command = 0xFF; + dev->CmdParam = 0; + dev->CmdParamLeft = 0; + dev->IrqEnabled = 1; + dev->MailboxCount = 0; + dev->MailboxOutPosCur = 0; + dev->MailboxInPosCur = 0; + dev->MailboxOutInterrupts = 0; + dev->PendingInterrupt = 0; + + if (dev->ven_reset) { + dev->ven_reset(dev); + } + + clear_irq(dev); +} + + +void +x54x_reset_ctrl(x54x_t *dev, uint8_t Reset) +{ + /* Only if configured.. */ + if (dev->Base == 0x0000) return; + + /* Say hello! */ + x54x_log("%s %s (IO=0x%04X, IRQ=%d, DMA=%d, BIOS @%05lX) ID=%d\n", + dev->vendor, dev->name, dev->Base, dev->Irq, dev->DmaChannel, + dev->rom_addr, dev->HostID); + + x54x_reset(dev); + if (Reset) { + dev->Status |= STAT_STST; + dev->Status &= ~STAT_IDLE; + } + dev->ResetCB = dev->reset_duration * TIMER_USEC; +} + + +static void +x54x_reset_poll(void *priv) +{ + x54x_t *dev = (x54x_t *)priv; + + dev->Status &= ~STAT_STST; + dev->Status |= STAT_IDLE; + + dev->ResetCB = 0LL; +} + + +static void +target_check(uint8_t id, uint8_t lun) +{ + if (! scsi_device_valid(id, lun)) { + fatal("BIOS INT13 device on %02i:%02i has disappeared\n", id, lun); + } +} + + +static uint8_t +completion_code(uint8_t *sense) +{ + switch (sense[12]) { + case 0x00: + return(0x00); + + case 0x20: + return(0x01); + + case 0x12: + case 0x21: + return(0x02); + + case 0x27: + return(0x03); + + case 0x14: + case 0x16: + return(0x04); + + case 0x10: + case 0x11: + return(0x10); + + case 0x17: + case 0x18: + return(0x11); + + case 0x01: + case 0x03: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + return(0x20); + + case 0x15: + case 0x02: + return(0x40); + + case 0x04: + case 0x28: + case 0x29: + case 0x2a: + return(0xaa); + + default: + break; + }; + + return(0xff); +} + + +static uint8_t +x54x_bios_command_08(uint8_t id, uint8_t lun, uint8_t *buffer) +{ + uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; + uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; + uint32_t len = 0; + int i, ret, sc; + + ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len); + sc = completion_code(scsi_device_sense(id, lun)); + if (ret == 0) return(sc); + + memset(buffer, 0x00, 6); + for (i=0; i<4; i++) + buffer[i] = rcbuf[i]; + for (i=4; i<6; i++) + buffer[i] = rcbuf[(i + 2) ^ 1]; + x54x_log("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + + return(0); +} + + +static int +x54x_bios_command_15(uint8_t id, uint8_t lun, uint8_t *buffer) +{ + uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; + uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; + uint32_t len = 0; + int i, ret, sc; + + ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len); + sc = completion_code(scsi_device_sense(id, lun)); + + memset(buffer, 0x00, 6); + for (i=0; i<4; i++) + buffer[i] = (ret == 0) ? 0 : rcbuf[i]; + + scsi_device_type_data(id, lun, &(buffer[4]), &(buffer[5])); + + x54x_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + + return(sc); +} + + +/* This returns the completion code. */ +static uint8_t +x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) +{ + uint8_t cdb[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; + scsi_device_t *dev; + uint32_t dma_address; + uint32_t lba; + int sector_len = cmd->secount; + int block_shift; + uint8_t ret; + + if (islba) + lba = lba32_blk(cmd); + else + lba = (cmd->u.chs.cyl << 9) + (cmd->u.chs.head << 5) + cmd->u.chs.sec; + + x54x_log("BIOS Command = 0x%02X\n", cmd->command); + + if ((cmd->id > max_id) || (cmd->lun > 7)) { + x54x_log("BIOS Target ID %i or LUN %i are above maximum\n", + cmd->id, cmd->lun); + return(0x80); + } + + /* Get pointer to selected device. */ + dev = &SCSIDevices[cmd->id][cmd->lun]; + dev->BufferLength = 0; + + if (! scsi_device_present(cmd->id, cmd->lun)) { + x54x_log("BIOS Target ID %i and LUN %i have no device attached\n", + cmd->id, cmd->lun); + return(0x80); + } + + if ((dev->LunType == SCSI_CDROM) && !x54x->cdrom_boot) { + x54x_log("BIOS Target ID %i and LUN %i is CD-ROM on unsupported BIOS\n", + cmd->id, cmd->lun); + return(0x80); + } + + dma_address = ADDR_TO_U32(cmd->dma_address); + + x54x_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n", + sector_len, dma_address); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + block_shift = scsi_device_block_shift(cmd->id, cmd->lun); + + switch(cmd->command) { + case 0x00: /* Reset Disk System, in practice it's a nop */ + return(0); + + case 0x01: /* Read Status of Last Operation */ + target_check(cmd->id, cmd->lun); + + /* + * Assuming 14 bytes because that is the default + * length for SCSI sense, and no command-specific + * indication is given. + */ + dev->BufferLength = 14; + dev->CmdBuffer = (uint8_t *)malloc(14); + memset(dev->CmdBuffer, 0x00, 14); + +#if 0 + SCSIStatus = x54x_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer) ? SCSI_STATUS_OK : SCSI_STATUS_CHECK_CONDITION; +#endif + + if (sector_len > 0) { + x54x_log("BIOS DMA: Reading 14 bytes at %08X\n", + dma_address); + DMAPageWrite(dma_address, + (char *)scsi_device_sense(cmd->id, cmd->lun), 14); + } + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + return(0); + + case 0x02: /* Read Desired Sectors to Memory */ + target_check(cmd->id, cmd->lun); + + dev->BufferLength = sector_len << block_shift; + dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); + memset(dev->CmdBuffer, 0x00, dev->BufferLength); + + cdb[0] = GPCMD_READ_10; + cdb[1] = (cmd->lun & 7) << 5; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + cdb[7] = (sector_len >> 8) & 0xff; + cdb[8] = sector_len & 0xff; +#if 0 + x54x_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount); +#endif + + scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + + if (SCSIPhase == SCSI_PHASE_STATUS) + goto skip_read_phase1; + + scsi_device_command_phase1(cmd->id, cmd->lun); + if (sector_len > 0) { + x54x_log("BIOS DMA: Reading %i bytes at %08X\n", + dev->BufferLength, dma_address); + DMAPageWrite(dma_address, + (char *)dev->CmdBuffer, dev->BufferLength); + } + +skip_read_phase1: + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + + case 0x03: /* Write Desired Sectors from Memory */ + target_check(cmd->id, cmd->lun); + + dev->BufferLength = sector_len << block_shift; + dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); + memset(dev->CmdBuffer, 0x00, dev->BufferLength); + + cdb[0] = GPCMD_WRITE_10; + cdb[1] = (cmd->lun & 7) << 5; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + cdb[7] = (sector_len >> 8) & 0xff; + cdb[8] = sector_len & 0xff; +#if 0 + x54x_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount); +#endif + + scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + + if (SCSIPhase == SCSI_PHASE_STATUS) + goto skip_write_phase1; + + if (sector_len > 0) { + x54x_log("BIOS DMA: Reading %i bytes at %08X\n", + dev->BufferLength, dma_address); + DMAPageRead(dma_address, + (char *)dev->CmdBuffer, dev->BufferLength); + } + + scsi_device_command_phase1(cmd->id, cmd->lun); + +skip_write_phase1: + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + + case 0x04: /* Verify Desired Sectors */ + target_check(cmd->id, cmd->lun); + + cdb[0] = GPCMD_VERIFY_10; + cdb[1] = (cmd->lun & 7) << 5; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + cdb[7] = (sector_len >> 8) & 0xff; + cdb[8] = sector_len & 0xff; + + scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + + return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + + case 0x05: /* Format Track, invalid since SCSI has no tracks */ +//FIXME: add a longer delay here --FvK + return(1); + + case 0x06: /* Identify SCSI Devices, in practice it's a nop */ +//FIXME: add a longer delay here --FvK + return(0); + + case 0x07: /* Format Unit */ + target_check(cmd->id, cmd->lun); + + cdb[0] = GPCMD_FORMAT_UNIT; + cdb[1] = (cmd->lun & 7) << 5; + + scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + + return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + + case 0x08: /* Read Drive Parameters */ + target_check(cmd->id, cmd->lun); + + dev->BufferLength = 6; + dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); + memset(dev->CmdBuffer, 0x00, dev->BufferLength); + + ret = x54x_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer); + + x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); + DMAPageWrite(dma_address, + (char *)dev->CmdBuffer, dev->BufferLength); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + return(ret); + + case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */ +//FIXME: add a longer delay here --FvK + return(0); + + case 0x0c: /* Seek */ + target_check(cmd->id, cmd->lun); + + cdb[0] = GPCMD_SEEK_10; + cdb[1] = (cmd->lun & 7) << 5; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + + scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + + return((SCSIStatus == SCSI_STATUS_OK) ? 1 : 0); + + case 0x0d: /* Alternate Disk Reset, in practice it's a nop */ +//FIXME: add a longer delay here --FvK + return(0); + + case 0x10: /* Test Drive Ready */ + target_check(cmd->id, cmd->lun); + + cdb[0] = GPCMD_TEST_UNIT_READY; + cdb[1] = (cmd->lun & 7) << 5; + + scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + + return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + + case 0x11: /* Recalibrate */ + target_check(cmd->id, cmd->lun); + + cdb[0] = GPCMD_REZERO_UNIT; + cdb[1] = (cmd->lun & 7) << 5; + + scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + + return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + + case 0x14: /* Controller Diagnostic */ +//FIXME: add a longer delay here --FvK + return(0); + + case 0x15: /* Read DASD Type */ + target_check(cmd->id, cmd->lun); + + dev->BufferLength = 6; + dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); + memset(dev->CmdBuffer, 0x00, dev->BufferLength); + + ret = x54x_bios_command_15(cmd->id, cmd->lun, dev->CmdBuffer); + + x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); + DMAPageWrite(dma_address, + (char *)dev->CmdBuffer, dev->BufferLength); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + return(ret); + + default: + x54x_log("BIOS: Unimplemented command: %02X\n", cmd->command); + return(1); + } + + x54x_log("BIOS Request complete\n"); +} + + +static void +x54x_cmd_done(x54x_t *dev, int suppress) +{ + int fast = 0; + + dev->DataReply = 0; + dev->Status |= STAT_IDLE; + + if (dev->ven_cmd_is_fast) { + fast = dev->ven_cmd_is_fast(dev); + } + + if ((dev->Command != CMD_START_SCSI) || fast) { + dev->Status &= ~STAT_DFULL; + x54x_log("%s: Raising IRQ %i\n", dev->name, dev->Irq); + raise_irq(dev, suppress, INTR_HACC); + } + + dev->Command = 0xff; + dev->CmdParam = 0; +} + + +static void +x54x_mbi_setup(x54x_t *dev, uint32_t CCBPointer, CCBU *CmdBlock, + uint8_t HostStatus, uint8_t TargetStatus, uint8_t mbcc) +{ + Req_t *req = &dev->Req; + + req->CCBPointer = CCBPointer; + memcpy(&(req->CmdBlock), CmdBlock, sizeof(CCB32)); + req->Is24bit = dev->Mbx24bit; + req->HostStatus = HostStatus; + req->TargetStatus = TargetStatus; + req->MailboxCompletionCode = mbcc; + + x54x_log("Mailbox in setup\n"); +} + + +static void +x54x_ccb(x54x_t *dev) +{ + Req_t *req = &dev->Req; + + /* Rewrite the CCB up to the CDB. */ + x54x_log("CCB completion code and statuses rewritten (pointer %08X)\n", req->CCBPointer); + DMAPageWrite(req->CCBPointer + 0x000D, (char *)&(req->MailboxCompletionCode), 1); + DMAPageWrite(req->CCBPointer + 0x000E, (char *)&(req->HostStatus), 1); + DMAPageWrite(req->CCBPointer + 0x000F, (char *)&(req->TargetStatus), 1); + + if (dev->MailboxOutInterrupts) + { + dev->ToRaise = INTR_MBOA | INTR_ANY; + } + else + { + dev->ToRaise = 0; + } +} + + +static void +x54x_mbi(x54x_t *dev) +{ + Req_t *req = &dev->Req; + // uint32_t CCBPointer = req->CCBPointer; + addr24 CCBPointer; + CCBU *CmdBlock = &(req->CmdBlock); + uint8_t HostStatus = req->HostStatus; + uint8_t TargetStatus = req->TargetStatus; + uint32_t MailboxCompletionCode = req->MailboxCompletionCode; + uint32_t Incoming; + + Incoming = dev->MailboxInAddr + (dev->MailboxInPosCur * (dev->Mbx24bit ? sizeof(Mailbox_t) : sizeof(Mailbox32_t))); + + if (MailboxCompletionCode != MBI_NOT_FOUND) { + CmdBlock->common.HostStatus = HostStatus; + CmdBlock->common.TargetStatus = TargetStatus; + + /* Rewrite the CCB up to the CDB. */ + x54x_log("CCB statuses rewritten (pointer %08X)\n", req->CCBPointer); + DMAPageWrite(req->CCBPointer + 0x000E, (char *)&(req->HostStatus), 1); + DMAPageWrite(req->CCBPointer + 0x000F, (char *)&(req->TargetStatus), 1); + } else { + x54x_log("Mailbox not found!\n"); + } + + x54x_log("Host Status 0x%02X, Target Status 0x%02X\n",HostStatus,TargetStatus); + + if (dev->Mbx24bit) { + U32_TO_ADDR(CCBPointer, req->CCBPointer); + x54x_log("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); + DMAPageWrite(Incoming, (char *)&(req->MailboxCompletionCode), 1); + DMAPageWrite(Incoming + 1, (char *)&CCBPointer, 3); + x54x_log("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); + } else { + x54x_log("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); + DMAPageWrite(Incoming, (char *)&(req->CCBPointer), 4); + DMAPageWrite(Incoming + 4, (char *)&(req->HostStatus), 1); + DMAPageWrite(Incoming + 5, (char *)&(req->TargetStatus), 1); + DMAPageWrite(Incoming + 7, (char *)&(req->MailboxCompletionCode), 1); + x54x_log("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); + } + + dev->MailboxInPosCur++; + if (dev->MailboxInPosCur >= dev->MailboxCount) + dev->MailboxInPosCur = 0; + + dev->ToRaise = INTR_MBIF | INTR_ANY; + if (dev->MailboxOutInterrupts) + { + dev->ToRaise |= INTR_MBOA; + } +} + + +static void +x54x_rd_sge(int Is24bit, uint32_t Address, SGE32 *SG) +{ + SGE SGE24; + + if (Is24bit) { + DMAPageRead(Address, (char *)&SGE24, sizeof(SGE)); + + /* Convert the 24-bit entries into 32-bit entries. */ + x54x_log("Read S/G block: %06X, %06X\n", SGE24.Segment, SGE24.SegmentPointer); + SG->Segment = ADDR_TO_U32(SGE24.Segment); + SG->SegmentPointer = ADDR_TO_U32(SGE24.SegmentPointer); + } else { + DMAPageRead(Address, (char *)SG, sizeof(SGE32)); + } +} + + +static int +x54x_get_length(Req_t *req, int Is24bit) +{ + uint32_t DataPointer, DataLength; + uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); + SGE32 SGBuffer; + uint32_t DataToTransfer = 0; + int i = 0; + + if (Is24bit) { + DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); + DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); + x54x_log("Data length: %08X\n", req->CmdBlock.old.DataLength); + } else { + DataPointer = req->CmdBlock.new.DataPointer; + DataLength = req->CmdBlock.new.DataLength; + } + x54x_log("Data Buffer write: length %d, pointer 0x%04X\n", + DataLength, DataPointer); + + if (!DataLength) + return 0; + + if (req->CmdBlock.common.ControlByte != 0x03) { + if (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || + req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { + for (i = 0; i < DataLength; i += SGEntryLength) { + x54x_rd_sge(Is24bit, DataPointer + i, &SGBuffer); + + DataToTransfer += SGBuffer.Segment; + } + return DataToTransfer; + } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || + req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { + return DataLength; + } else { + return 0; + } + } else { + return 0; + } +} + + +static void +x54x_set_residue(Req_t *req, int32_t TransferLength) +{ + uint32_t Residue = 0; + addr24 Residue24; + int32_t BufLen = SCSIDevices[req->TargetID][req->LUN].BufferLength; + + if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || + (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { + + if ((TransferLength > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { + TransferLength -= BufLen; + if (TransferLength > 0) + Residue = TransferLength; + } + + if (req->Is24bit) { + U32_TO_ADDR(Residue24, Residue); + DMAPageWrite(req->CCBPointer + 0x0004, (char *)&Residue24, 3); + x54x_log("24-bit Residual data length for reading: %d\n", Residue); + } else { + DMAPageWrite(req->CCBPointer + 0x0004, (char *)&Residue, 4); + x54x_log("32-bit Residual data length for reading: %d\n", Residue); + } + } +} + + +static void +x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) +{ + uint32_t DataPointer, DataLength; + uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); + uint32_t Address; + int i = 0; + int32_t BufLen = SCSIDevices[req->TargetID][req->LUN].BufferLength; + uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00))); + uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00))); + int sg_pos = 0; + SGE32 SGBuffer; + uint32_t DataToTransfer = 0; + + if (Is24bit) { + DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); + DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); + } else { + DataPointer = req->CmdBlock.new.DataPointer; + DataLength = req->CmdBlock.new.DataLength; + } + x54x_log("Data Buffer %s: length %d, pointer 0x%04X\n", + dir ? "write" : "read", BufLen, DataPointer); + + if ((req->CmdBlock.common.ControlByte != 0x03) && TransferLength && BufLen) { + if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || + (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { + + /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without + checking its length, so do this procedure for both no read/write commands. */ + if ((DataLength > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { + for (i = 0; i < DataLength; i += SGEntryLength) { + x54x_rd_sge(Is24bit, DataPointer + i, &SGBuffer); + + Address = SGBuffer.SegmentPointer; + DataToTransfer = MIN(SGBuffer.Segment, BufLen); + + if (read_from_host && DataToTransfer) { + x54x_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + DMAPageRead(Address, (char *)&(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer); + } + else if (write_to_host && DataToTransfer) { + x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + DMAPageWrite(Address, (char *)&(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer); + } + else { + x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + } + + sg_pos += SGBuffer.Segment; + + BufLen -= SGBuffer.Segment; + if (BufLen < 0) + BufLen = 0; + + x54x_log("After S/G segment done: %i, %i\n", sg_pos, BufLen); + } + } + } else if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND) || + (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES)) { + Address = DataPointer; + + if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { + if (read_from_host) + { + DMAPageRead(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, DataLength)); + } + else + if (write_to_host) + { + DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, DataLength)); + } + } + } + } +} + + +void +x54x_buf_alloc(uint8_t id, uint8_t lun, int length) +{ + if (SCSIDevices[id][lun].CmdBuffer != NULL) { + free(SCSIDevices[id][lun].CmdBuffer); + SCSIDevices[id][lun].CmdBuffer = NULL; + } + + x54x_log("Allocating data buffer (%i bytes)\n", length); + SCSIDevices[id][lun].CmdBuffer = (uint8_t *) malloc(length); + memset(SCSIDevices[id][lun].CmdBuffer, 0, length); +} + + +void +x54x_buf_free(uint8_t id, uint8_t lun) +{ + if (SCSIDevices[id][lun].CmdBuffer != NULL) { + free(SCSIDevices[id][lun].CmdBuffer); + SCSIDevices[id][lun].CmdBuffer = NULL; + } +} + + +static uint8_t +ConvertSenseLength(uint8_t RequestSenseLength) +{ + x54x_log("Unconverted Request Sense length %i\n", RequestSenseLength); + + if (RequestSenseLength == 0) + RequestSenseLength = 14; + else if (RequestSenseLength == 1) + RequestSenseLength = 0; + + x54x_log("Request Sense length %i\n", RequestSenseLength); + + return(RequestSenseLength); +} + + +uint32_t +SenseBufferPointer(Req_t *req) +{ + uint32_t SenseBufferAddress; + if (req->Is24bit) { + SenseBufferAddress = req->CCBPointer; + SenseBufferAddress += req->CmdBlock.common.CdbLength + 18; + } else { + SenseBufferAddress = req->CmdBlock.new.SensePointer; + } + + return SenseBufferAddress; +} + + +static void +SenseBufferFree(Req_t *req, int Copy) +{ + uint8_t SenseLength = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); + uint32_t SenseBufferAddress; + uint8_t temp_sense[256]; + + if (SenseLength && Copy) { + scsi_device_request_sense(req->TargetID, req->LUN, temp_sense, SenseLength); + + /* + * The sense address, in 32-bit mode, is located in the + * Sense Pointer of the CCB, but in 24-bit mode, it is + * located at the end of the Command Descriptor Block. + */ + SenseBufferAddress = SenseBufferPointer(req); + + x54x_log("Request Sense address: %02X\n", SenseBufferAddress); + + x54x_log("SenseBufferFree(): Writing %i bytes at %08X\n", + SenseLength, SenseBufferAddress); + DMAPageWrite(SenseBufferAddress, (char *)temp_sense, SenseLength); + x54x_log("Sense data written to buffer: %02X %02X %02X\n", + temp_sense[2], temp_sense[12], temp_sense[13]); + } +} + + +static void +x54x_scsi_cmd(x54x_t *dev) +{ + Req_t *req = &dev->Req; + uint8_t id, lun; + uint8_t temp_cdb[12]; + uint32_t i; + int target_cdb_len = 12; + int target_data_len; + uint8_t bit24 = !!req->Is24bit; + int32_t *BufLen; + uint8_t phase; + uint32_t SenseBufferAddress; + + id = req->TargetID; + lun = req->LUN; + + target_cdb_len = scsi_device_cdb_length(id, lun); + target_data_len = x54x_get_length(req, bit24); + + if (!scsi_device_valid(id, lun)) + fatal("SCSI target on %02i:%02i has disappeared\n", id, lun); + + x54x_log("target_data_len = %i\n", target_data_len); + + x54x_log("SCSI command being executed on ID %i, LUN %i\n", id, lun); + + x54x_log("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); + for (i=1; iCmdBlock.common.CdbLength; i++) + x54x_log("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); + + memset(temp_cdb, 0x00, target_cdb_len); + if (req->CmdBlock.common.CdbLength <= target_cdb_len) { + memcpy(temp_cdb, req->CmdBlock.common.Cdb, + req->CmdBlock.common.CdbLength); + } else { + memcpy(temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len); + } + + dev->Residue = 0; + + BufLen = scsi_device_get_buf_len(id, lun); + *BufLen = target_data_len; + + x54x_log("Command buffer: %08X\n", SCSIDevices[id][lun].CmdBuffer); + + scsi_device_command_phase0(id, lun, req->CmdBlock.common.CdbLength, temp_cdb); + + phase = SCSIPhase; + + x54x_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03)); + + if (phase != SCSI_PHASE_STATUS) { + if ((temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) { + /* Request sense in non-data mode - sense goes to sense buffer. */ + *BufLen = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); + x54x_buf_alloc(id, lun, *BufLen); + scsi_device_command_phase1(id, lun); + if ((SCSIStatus != SCSI_STATUS_OK) && (*BufLen > 0)) { + SenseBufferAddress = SenseBufferPointer(req); + DMAPageWrite(SenseBufferAddress, (char *)SCSIDevices[id][lun].CmdBuffer, *BufLen); + } + } else { + x54x_buf_alloc(id, lun, MIN(target_data_len, *BufLen)); + if (phase == SCSI_PHASE_DATA_OUT) + x54x_buf_dma_transfer(req, bit24, target_data_len, 1); + scsi_device_command_phase1(id, lun); + if (phase == SCSI_PHASE_DATA_IN) + x54x_buf_dma_transfer(req, bit24, target_data_len, 0); + + SenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK)); + } + } + + x54x_set_residue(req, target_data_len); + + x54x_buf_free(id, lun); + + x54x_log("Request complete\n"); + + if (SCSIStatus == SCSI_STATUS_OK) { + x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); + } else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) { + x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); + } + + x54x_log("SCSIStatus = %02X\n", SCSIStatus); + + if (temp_cdb[0] == 0x42) { + thread_wait_event(evt, 10); + } +} + + +static void +x54x_notify(x54x_t *dev) +{ + if (dev->MailboxIsBIOS) + { + x54x_ccb(dev); + } + else + { + x54x_mbi(dev); + } +} + + +static void +x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) +{ + Req_t *req = &dev->Req; + uint8_t id, lun; + uint8_t max_id = SCSI_ID_MAX-1; + + /* Fetch data from the Command Control Block. */ + DMAPageRead(CCBPointer, (char *)&req->CmdBlock, sizeof(CCB32)); + + req->Is24bit = dev->Mbx24bit; + req->CCBPointer = CCBPointer; + req->TargetID = dev->Mbx24bit ? req->CmdBlock.old.Id : req->CmdBlock.new.Id; + req->LUN = dev->Mbx24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; + + id = req->TargetID; + lun = req->LUN; + if ((id > max_id) || (lun > 7)) { + x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, + CCB_INVALID_CCB, SCSI_STATUS_OK, MBI_ERROR); + x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); + x54x_notify(dev); + return; + } + + x54x_log("Scanning SCSI Target ID %i\n", id); + + SCSIStatus = SCSI_STATUS_OK; + + if (! scsi_device_present(id, lun)) { + x54x_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun); + x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, + CCB_SELECTION_TIMEOUT,SCSI_STATUS_OK,MBI_ERROR); + x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); + x54x_notify(dev); + } else { + x54x_log("SCSI Target ID %i and LUN %i detected and working\n", id, lun); + + x54x_log("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); + x54x_log("CDB Length %i\n", req->CmdBlock.common.CdbLength); + x54x_log("CCB Opcode %x\n", req->CmdBlock.common.Opcode); + if (req->CmdBlock.common.ControlByte > 0x03) { + x54x_log("Invalid control byte: %02X\n", + req->CmdBlock.common.ControlByte); + } + + x54x_log("%s: Callback: Process SCSI request\n", dev->name); + x54x_scsi_cmd(dev); + + x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); + x54x_notify(dev); + } +} + + +static void +x54x_req_abort(x54x_t *dev, uint32_t CCBPointer) +{ + CCBU CmdBlock; + + /* Fetch data from the Command Control Block. */ + DMAPageRead(CCBPointer, (char *)&CmdBlock, sizeof(CCB32)); + + x54x_mbi_setup(dev, CCBPointer, &CmdBlock, + 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); + x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); + x54x_notify(dev); +} + + +static uint32_t +x54x_mbo(x54x_t *dev, Mailbox32_t *Mailbox32) +{ + Mailbox_t MailboxOut; + uint32_t Outgoing; + uint32_t ccbp; + uint32_t Addr; + uint32_t Cur; + + if (dev->MailboxIsBIOS) { + Addr = dev->BIOSMailboxOutAddr; + Cur = dev->BIOSMailboxOutPosCur; + } else { + Addr = dev->MailboxOutAddr; + Cur = dev->MailboxOutPosCur; + } + + if (dev->Mbx24bit) { + Outgoing = Addr + (Cur * sizeof(Mailbox_t)); + DMAPageRead(Outgoing, (char *)&MailboxOut, sizeof(Mailbox_t)); + + ccbp = *(uint32_t *) &MailboxOut; + Mailbox32->CCBPointer = (ccbp >> 24) | ((ccbp >> 8) & 0xff00) | ((ccbp << 8) & 0xff0000); + Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus; + } else { + Outgoing = Addr + (Cur * sizeof(Mailbox32_t)); + + DMAPageRead(Outgoing, (char *)Mailbox32, sizeof(Mailbox32_t)); + } + + return(Outgoing); +} + + +uint8_t +x54x_mbo_process(x54x_t *dev) +{ + Mailbox32_t mb32; + uint32_t Outgoing; + uint8_t CmdStatus = MBO_FREE; + uint32_t CodeOffset = 0; + + CodeOffset = dev->Mbx24bit ? 0 : 7; + + Outgoing = x54x_mbo(dev, &mb32); + + if (mb32.u.out.ActionCode == MBO_START) { + x54x_log("Start Mailbox Command\n"); + x54x_req_setup(dev, mb32.CCBPointer, &mb32); + } else if (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT)) { + x54x_log("Abort Mailbox Command\n"); + x54x_req_abort(dev, mb32.CCBPointer); + } /* else { + x54x_log("Invalid action code: %02X\n", mb32.u.out.ActionCode); + } */ + + if ((mb32.u.out.ActionCode == MBO_START) || (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT))) { + /* We got the mailbox, mark it as free in the guest. */ + x54x_log("x54x_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset); + DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, 1); + + if (dev->ToRaise) + { + raise_irq(dev, 0, dev->ToRaise); + + while (dev->Interrupt) { + } + } + + dev->MailboxReq--; + + return 1; + } + + return 0; +} + + +static void +x54x_do_mail(x54x_t *dev) +{ + int aggressive = 1; + + dev->MailboxIsBIOS = 0; + + if (dev->is_aggressive_mode) { + aggressive = dev->is_aggressive_mode(dev); + x54x_log("Processing mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); + } else { + x54x_log("Defaulting to process mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); + } + + if (!dev->MailboxCount) { + x54x_log("x54x_do_mail(): No Mailboxes\n"); + return; + } + + if (aggressive) { + /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ + for (dev->MailboxOutPosCur = 0; dev->MailboxOutPosCur < dev->MailboxCount; dev->MailboxOutPosCur++) { + if (x54x_mbo_process(dev)) + break; + } + } else { + /* Strict round robin mode - only process the current mailbox and advance the pointer if successful. */ + if (x54x_mbo_process(dev)) { + dev->MailboxOutPosCur++; + dev->MailboxOutPosCur %= dev->MailboxCount; + } + } +} + + +static void +x54x_cmd_done(x54x_t *dev, int suppress); + + +void +x54x_wait_for_poll(void) +{ + if (x54x_busy()) { + thread_wait_event(poll_complete, -1); + } + thread_reset_event(poll_complete); +} + + +static void +x54x_cmd_thread(void *priv) +{ + x54x_t *dev = (x54x_t *)priv; + + x54x_log("Polling thread started\n"); + + while (1) + { + if ((dev->Status & STAT_INIT) || (!dev->MailboxInit && !dev->BIOSMailboxInit) || (!dev->MailboxReq && !dev->BIOSMailboxReq)) { + /* If we did not get anything, wait a while. */ + thread_wait_event(evt, 10); + continue; + } + + startscsi(); + + if (!(dev->Status & STAT_INIT) && dev->MailboxInit && dev->MailboxReq) + { + x54x_wait_for_poll(); + + x54x_do_mail(dev); + } + + if (dev->ven_thread) { + dev->ven_thread(dev); + } + + endscsi(); + } + + if (poll_tid) { + thread_kill(poll_tid); + poll_tid = NULL; + } + + if (poll_complete) { + thread_destroy_event(poll_complete); + poll_complete = NULL; + } + + if (evt) { + thread_destroy_event(evt); + evt = NULL; + } + + scsi_mutex_close(); + + x54x_log("%s: Callback: polling stopped.\n", dev->name); +} + + +static uint8_t +x54x_in(uint16_t port, void *priv) +{ + x54x_t *dev = (x54x_t *)priv; + uint8_t ret; + + switch (port & 3) { + case 0: + default: + ret = dev->Status; + break; + + case 1: + ret = dev->DataBuf[dev->DataReply]; + if (dev->DataReplyLeft) { + dev->DataReply++; + dev->DataReplyLeft--; + if (! dev->DataReplyLeft) + x54x_cmd_done(dev, 0); + } + break; + + case 2: + ret = dev->Interrupt; + break; + + case 3: + ret = dev->Geometry; + break; + } + + return(ret); +} + + +static uint16_t +x54x_inw(uint16_t port, void *priv) +{ + return (uint16_t) x54x_in(port, priv); +} + + +static uint32_t +x54x_inl(uint16_t port, void *priv) +{ + return (uint32_t) x54x_in(port, priv); +} + + +static uint8_t +x54x_read(uint32_t port, void *priv) +{ + return x54x_in(port & 3, priv); +} + + +static uint16_t +x54x_readw(uint32_t port, void *priv) +{ + return x54x_inw(port & 3, priv); +} + + +static uint32_t +x54x_readl(uint32_t port, void *priv) +{ + return x54x_inl(port & 3, priv); +} + + +void +x54x_busy_set(void) +{ + busy = 1; +} + + +void +x54x_thread_start(x54x_t *dev) +{ + if (!poll_tid) { + x54x_log("Starting thread...\n"); + poll_tid = thread_create(x54x_cmd_thread, dev); + } +} + + +void +x54x_busy_clear(void) +{ + busy = 0; + x54x_log("Thread set event - poll complete\n"); + thread_set_event(poll_complete); +} + +uint8_t +x54x_busy(void) +{ + return !!busy; +} + + +static void +x54x_out(uint16_t port, uint8_t val, void *priv) +{ + ReplyInquireSetupInformation *ReplyISI; + x54x_t *dev = (x54x_t *)priv; + MailboxInit_t *mbi; + int i = 0; + uint8_t j = 0; + BIOSCMD *cmd; + uint16_t cyl = 0; + int suppress = 0; + uint32_t FIFOBuf; + uint8_t reset; + addr24 Address; + uint8_t host_id = dev->HostID; + uint8_t irq = 0; + + x54x_log("%s: Write Port 0x%02X, Value %02X\n", dev->name, port, val); + + switch (port & 3) { + case 0: + if ((val & CTRL_HRST) || (val & CTRL_SRST)) { + x54x_busy_set(); + reset = (val & CTRL_HRST); + x54x_log("Reset completed = %x\n", reset); + x54x_reset_ctrl(dev, reset); + x54x_busy_clear(); + break; + } + + if (val & CTRL_IRST) { + x54x_busy_set(); + clear_irq(dev); + x54x_busy_clear(); + } + break; + + case 1: + /* Fast path for the mailbox execution command. */ + if ((val == CMD_START_SCSI) && (dev->Command == 0xff)) { + x54x_busy_set(); + dev->MailboxReq++; + + x54x_thread_start(dev); + x54x_busy_clear(); + return; + } + if (dev->ven_fast_cmds) { + if (dev->Command == 0xff) { + if (dev->ven_fast_cmds(dev, val)) + return; + } + } + + if (dev->Command == 0xff) { + dev->Command = val; + dev->CmdParam = 0; + dev->CmdParamLeft = 0; + + dev->Status &= ~(STAT_INVCMD | STAT_IDLE); + x54x_log("%s: Operation Code 0x%02X\n", dev->name, val); + switch (dev->Command) { + case CMD_MBINIT: + dev->CmdParamLeft = sizeof(MailboxInit_t); + break; + + case CMD_BIOSCMD: + dev->CmdParamLeft = 10; + break; + + case CMD_EMBOI: + case CMD_BUSON_TIME: + case CMD_BUSOFF_TIME: + case CMD_DMASPEED: + case CMD_RETSETUP: + case CMD_ECHO: + case CMD_OPTIONS: + dev->CmdParamLeft = 1; + break; + + case CMD_SELTIMEOUT: + dev->CmdParamLeft = 4; + break; + + case CMD_WRITE_CH2: + case CMD_READ_CH2: + dev->CmdParamLeft = 3; + break; + + default: + if (dev->get_ven_param_len) + dev->CmdParamLeft = dev->get_ven_param_len(dev); + break; + } + } else { + dev->CmdBuf[dev->CmdParam] = val; + dev->CmdParam++; + dev->CmdParamLeft--; + + if (dev->ven_cmd_phase1) + dev->ven_cmd_phase1(dev); + } + + if (! dev->CmdParamLeft) { + x54x_log("Running Operation Code 0x%02X\n", dev->Command); + switch (dev->Command) { + case CMD_NOP: /* No Operation */ + dev->DataReplyLeft = 0; + break; + + case CMD_MBINIT: /* mailbox initialization */ + x54x_busy_set(); + dev->Mbx24bit = 1; + + mbi = (MailboxInit_t *)dev->CmdBuf; + + dev->MailboxInit = 1; + dev->MailboxCount = mbi->Count; + dev->MailboxOutAddr = ADDR_TO_U32(mbi->Address); + dev->MailboxInAddr = dev->MailboxOutAddr + (dev->MailboxCount * sizeof(Mailbox_t)); + + x54x_log("Initialize Mailbox: MBO=0x%08lx, MBI=0x%08lx, %d entries at 0x%08lx\n", + dev->MailboxOutAddr, + dev->MailboxInAddr, + mbi->Count, + ADDR_TO_U32(mbi->Address)); + + dev->Status &= ~STAT_INIT; + dev->DataReplyLeft = 0; + x54x_busy_clear(); + break; + + case CMD_BIOSCMD: /* execute BIOS */ + cmd = (BIOSCMD *)dev->CmdBuf; + if (!(dev->bus & DEVICE_MCA)) { + /* 1640 uses LBA. */ + cyl = ((cmd->u.chs.cyl & 0xff) << 8) | ((cmd->u.chs.cyl >> 8) & 0xff); + cmd->u.chs.cyl = cyl; + } + if (dev->bus & DEVICE_MCA) { + /* 1640 uses LBA. */ + x54x_log("BIOS LBA=%06lx (%lu)\n", + lba32_blk(cmd), + lba32_blk(cmd)); + } else { + cmd->u.chs.head &= 0xf; + cmd->u.chs.sec &= 0x1f; + x54x_log("BIOS CHS=%04X/%02X%02X\n", + cmd->u.chs.cyl, + cmd->u.chs.head, + cmd->u.chs.sec); + } + dev->DataBuf[0] = x54x_bios_command(dev, dev->max_id, cmd, (dev->bus & DEVICE_MCA)?1:0); + x54x_log("BIOS Completion/Status Code %x\n", dev->DataBuf[0]); + dev->DataReplyLeft = 1; + break; + + case CMD_INQUIRY: /* Inquiry */ + memcpy(dev->DataBuf, dev->fw_rev, 4); + dev->DataReplyLeft = 4; + break; + + case CMD_EMBOI: /* enable MBO Interrupt */ + if (dev->CmdBuf[0] <= 1) { + dev->MailboxOutInterrupts = dev->CmdBuf[0]; + x54x_log("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); + suppress = 1; + } else { + dev->Status |= STAT_INVCMD; + } + dev->DataReplyLeft = 0; + break; + + case CMD_SELTIMEOUT: /* Selection Time-out */ + dev->DataReplyLeft = 0; + break; + + case CMD_BUSON_TIME: /* bus-on time */ + dev->BusOnTime = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + x54x_log("Bus-on time: %d\n", dev->CmdBuf[0]); + break; + + case CMD_BUSOFF_TIME: /* bus-off time */ + dev->BusOffTime = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + x54x_log("Bus-off time: %d\n", dev->CmdBuf[0]); + break; + + case CMD_DMASPEED: /* DMA Transfer Rate */ + dev->ATBusSpeed = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + x54x_log("DMA transfer rate: %02X\n", dev->CmdBuf[0]); + break; + + case CMD_RETDEVS: /* return Installed Devices */ + memset(dev->DataBuf, 0x00, 8); + for (i=0; iDataBuf[i] = 0x00; + + /* Skip the HA .. */ + if (dev->ven_get_host_id) + host_id = dev->ven_get_host_id(dev); + + if (i == host_id) continue; + + for (j=0; jDataBuf[i] |= (1<DataReplyLeft = i; + break; + + case CMD_RETCONF: /* return Configuration */ + if (dev->ven_get_dma) + dev->DataBuf[0] = (1<ven_get_dma(dev)); + else + dev->DataBuf[0] = (1<DmaChannel); + + if (dev->ven_get_irq) + irq = dev->ven_get_irq(dev); + else + irq = dev->Irq; + + if (irq >= 9) + dev->DataBuf[1]=(1<<(irq-9)); + else + dev->DataBuf[1]=0; + if (dev->ven_get_host_id) + dev->DataBuf[2] = dev->ven_get_host_id(dev); + else + dev->DataBuf[2] = dev->HostID; + dev->DataReplyLeft = 3; + break; + + case CMD_RETSETUP: /* return Setup */ + { + ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; + memset(ReplyISI, 0x00, sizeof(ReplyInquireSetupInformation)); + + ReplyISI->uBusTransferRate = dev->ATBusSpeed; + ReplyISI->uPreemptTimeOnBus = dev->BusOnTime; + ReplyISI->uTimeOffBus = dev->BusOffTime; + ReplyISI->cMailbox = dev->MailboxCount; + U32_TO_ADDR(ReplyISI->MailboxAddress, dev->MailboxOutAddr); + + if (dev->get_ven_data) { + dev->get_ven_data(dev); + } + + dev->DataReplyLeft = dev->CmdBuf[0]; + x54x_log("Return Setup Information: %d (length: %i)\n", dev->CmdBuf[0], sizeof(ReplyInquireSetupInformation)); + } + break; + + case CMD_ECHO: /* ECHO data */ + dev->DataBuf[0] = dev->CmdBuf[0]; + dev->DataReplyLeft = 1; + break; + + case CMD_WRITE_CH2: /* write channel 2 buffer */ + dev->DataReplyLeft = 0; + Address.hi = dev->CmdBuf[0]; + Address.mid = dev->CmdBuf[1]; + Address.lo = dev->CmdBuf[2]; + FIFOBuf = ADDR_TO_U32(Address); + x54x_log("Adaptec LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); + DMAPageRead(FIFOBuf, (char *)dev->dma_buffer, 64); + break; + + case CMD_READ_CH2: /* write channel 2 buffer */ + dev->DataReplyLeft = 0; + Address.hi = dev->CmdBuf[0]; + Address.mid = dev->CmdBuf[1]; + Address.lo = dev->CmdBuf[2]; + FIFOBuf = ADDR_TO_U32(Address); + x54x_log("Adaptec LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); + DMAPageWrite(FIFOBuf, (char *)dev->dma_buffer, 64); + break; + + case CMD_OPTIONS: /* Set adapter options */ + if (dev->CmdParam == 1) + dev->CmdParamLeft = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + break; + + default: + if (dev->ven_cmds) + suppress = dev->ven_cmds(dev); + else { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; + } + } + + if (dev->DataReplyLeft) + dev->Status |= STAT_DFULL; + else if (!dev->CmdParamLeft) + x54x_cmd_done(dev, suppress); + break; + + case 2: + if (dev->int_geom_writable) + dev->Interrupt = val; + break; + + case 3: + if (dev->int_geom_writable) + dev->Geometry = val; + break; + } +} + + +static void +x54x_outw(uint16_t port, uint16_t val, void *priv) +{ + x54x_out(port, val & 0xFF, priv); +} + + +static void +x54x_outl(uint16_t port, uint32_t val, void *priv) +{ + x54x_out(port, val & 0xFF, priv); +} + + +static void +x54x_write(uint32_t port, uint8_t val, void *priv) +{ + x54x_out(port & 3, val, priv); +} + + +static void +x54x_writew(uint32_t port, uint16_t val, void *priv) +{ + x54x_outw(port & 3, val, priv); +} + + +static void +x54x_writel(uint32_t port, uint32_t val, void *priv) +{ + x54x_outl(port & 3, val, priv); +} + + +void +x54x_io_set(x54x_t *dev, uint32_t base) +{ + if (dev->bus & DEVICE_PCI) { + x54x_log("x54x: [PCI] Setting I/O handler at %04X\n", dev->Base); + io_sethandler(base, 4, + x54x_in, x54x_inw, x54x_inl, + x54x_out, x54x_outw, x54x_outl, dev); + } else { + x54x_log("x54x: [ISA] Setting I/O handler at %04X\n", dev->Base); + io_sethandler(base, 4, + x54x_in, x54x_inw, NULL, + x54x_out, x54x_outw, NULL, dev); + } +} + + +void +x54x_io_remove(x54x_t *dev, uint32_t base) +{ + x54x_log("x54x: Removing I/O handler at %04X\n", dev->Base); + + if (dev->bus & DEVICE_PCI) { + io_removehandler(base, 4, + x54x_in, x54x_inw, x54x_inl, + x54x_out, x54x_outw, x54x_outl, dev); + } else { + io_removehandler(base, 4, + x54x_in, x54x_inw, NULL, + x54x_out, x54x_outw, NULL, dev); + } +} + + +void +x54x_mem_init(x54x_t *dev, uint32_t addr) +{ + if (dev->bus & DEVICE_PCI) { + mem_mapping_add(&dev->mmio_mapping, addr, 0x20, + x54x_read, x54x_readw, x54x_readl, + x54x_write, x54x_writew, x54x_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); + } else { + mem_mapping_add(&dev->mmio_mapping, addr, 0x20, + x54x_read, x54x_readw, NULL, + x54x_write, x54x_writew, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + } +} + + +void +x54x_mem_enable(x54x_t *dev) +{ + mem_mapping_enable(&dev->mmio_mapping); +} + + +void +x54x_mem_set_addr(x54x_t *dev, uint32_t base) +{ + mem_mapping_set_addr(&dev->mmio_mapping, + base, 0x20); +} + + +void +x54x_mem_disable(x54x_t *dev) +{ + mem_mapping_disable(&dev->mmio_mapping); +} + + +/* General initialization routine for all boards. */ +void * +x54x_init(device_t *info) +{ + x54x_t *dev; + + /* Allocate control block and set up basic stuff. */ + dev = malloc(sizeof(x54x_t)); + if (dev == NULL) return(dev); + memset(dev, 0x00, sizeof(x54x_t)); + dev->type = info->local; + + dev->bus = info->flags; + + timer_add(x54x_reset_poll, &dev->ResetCB, &dev->ResetCB, dev); + + scsi_mutex_init(); + + poll_complete = thread_create_event(); + + /* Create a waitable event. */ + evt = thread_create_event(); + + return(dev); +} + + +void +x54x_close(void *priv) +{ + x54x_t *dev = (x54x_t *)priv; + + if (dev) + { + dev->MailboxInit = dev->BIOSMailboxInit = 0; + dev->MailboxCount = dev->BIOSMailboxCount = 0; + dev->MailboxReq = dev->BIOSMailboxReq = 0; + + if (dev->ven_data) + free(dev->ven_data); + + if (poll_tid) { + thread_kill(poll_tid); + poll_tid = NULL; + } + + if (poll_complete) { + thread_destroy_event(poll_complete); + poll_complete = NULL; + } + + if (evt) { + thread_destroy_event(evt); + evt = NULL; + } + + scsi_mutex_close(); + + if (dev->nvr != NULL) + free(dev->nvr); + + free(dev); + dev = NULL; + } +} + + +void +x54x_device_reset(void *priv) +{ + x54x_t *dev = (x54x_t *)priv; + + x54x_reset_ctrl(dev, 1); +} diff --git a/src/scsi/scsi_x54x.h b/src/scsi/scsi_x54x.h new file mode 100644 index 000000000..f6f435cf5 --- /dev/null +++ b/src/scsi/scsi_x54x.h @@ -0,0 +1,513 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Header of the code common to the AHA-154x series of SCSI + * Host Adapters made by Adaptec, Inc. and the BusLogic series + * of SCSI Host Adapters made by Mylex. + * These controllers were designed for various buses. + * + * Version: @(#)scsi_x54x.h 1.0.0 2017/10/14 + * + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#ifndef SCSI_X54X_H + +#define SCSI_X54X_H + +#define SCSI_DELAY_TM 1 /* was 50 */ + + +#define ROM_SIZE 16384 /* one ROM is 16K */ +#define NVR_SIZE 256 /* size of NVR */ + + +/* EEPROM map and bit definitions. */ +#define EE0_HOSTID 0x07 /* EE(0) [2:0] */ +#define EE0_ALTFLOP 0x80 /* EE(0) [7] FDC at 370h */ +#define EE1_IRQCH 0x07 /* EE(1) [3:0] */ +#define EE1_DMACH 0x70 /* EE(1) [7:4] */ +#define EE2_RMVOK 0x01 /* EE(2) [0] Support removable disks */ +#define EE2_HABIOS 0x02 /* EE(2) [1] HA Bios Space Reserved */ +#define EE2_INT19 0x04 /* EE(2) [2] HA Bios Controls INT19 */ +#define EE2_DYNSCAN 0x08 /* EE(2) [3] Dynamically scan bus */ +#define EE2_TWODRV 0x10 /* EE(2) [4] Allow more than 2 drives */ +#define EE2_SEEKRET 0x20 /* EE(2) [5] Immediate return on seek */ +#define EE2_EXT1G 0x80 /* EE(2) [7] Extended Translation >1GB */ +#define EE3_SPEED 0x00 /* EE(3) [7:0] DMA Speed */ +#define SPEED_33 0xFF +#define SPEED_50 0x00 +#define SPEED_56 0x04 +#define SPEED_67 0x01 +#define SPEED_80 0x02 +#define SPEED_10 0x03 +#define EE4_FLOPTOK 0x80 /* EE(4) [7] Support Flopticals */ +#define EE6_PARITY 0x01 /* EE(6) [0] parity check enable */ +#define EE6_TERM 0x02 /* EE(6) [1] host term enable */ +#define EE6_RSTBUS 0x04 /* EE(6) [2] reset SCSI bus on boot */ +#define EEE_SYNC 0x01 /* EE(E) [0] Enable Sync Negotiation */ +#define EEE_DISCON 0x02 /* EE(E) [1] Enable Disconnection */ +#define EEE_FAST 0x04 /* EE(E) [2] Enable FAST SCSI */ +#define EEE_START 0x08 /* EE(E) [3] Enable Start Unit */ + + +/* + * Host Adapter I/O ports. + * + * READ Port x+0: STATUS + * WRITE Port x+0: CONTROL + * + * READ Port x+1: DATA + * WRITE Port x+1: COMMAND + * + * READ Port x+2: INTERRUPT STATUS + * WRITE Port x+2: (undefined?) + * + * R/W Port x+3: (undefined) + */ + +/* WRITE CONTROL commands. */ +#define CTRL_HRST 0x80 /* Hard reset */ +#define CTRL_SRST 0x40 /* Soft reset */ +#define CTRL_IRST 0x20 /* interrupt reset */ +#define CTRL_SCRST 0x10 /* SCSI bus reset */ + +/* READ STATUS. */ +#define STAT_STST 0x80 /* self-test in progress */ +#define STAT_DFAIL 0x40 /* internal diagnostic failure */ +#define STAT_INIT 0x20 /* mailbox initialization required */ +#define STAT_IDLE 0x10 /* HBA is idle */ +#define STAT_CDFULL 0x08 /* Command/Data output port is full */ +#define STAT_DFULL 0x04 /* Data input port is full */ +#define STAT_INVCMD 0x01 /* Invalid command */ + +/* READ/WRITE DATA. */ +#define CMD_NOP 0x00 /* No operation */ +#define CMD_MBINIT 0x01 /* mailbox initialization */ +#define CMD_START_SCSI 0x02 /* Start SCSI command */ +#define CMD_BIOSCMD 0x03 /* Execute ROM BIOS command */ +#define CMD_INQUIRY 0x04 /* Adapter inquiry */ +#define CMD_EMBOI 0x05 /* enable Mailbox Out Interrupt */ +#define CMD_SELTIMEOUT 0x06 /* Set SEL timeout */ +#define CMD_BUSON_TIME 0x07 /* set bus-On time */ +#define CMD_BUSOFF_TIME 0x08 /* set bus-off time */ +#define CMD_DMASPEED 0x09 /* set ISA DMA speed */ +#define CMD_RETDEVS 0x0A /* return installed devices */ +#define CMD_RETCONF 0x0B /* return configuration data */ +#define CMD_TARGET 0x0C /* set HBA to target mode */ +#define CMD_RETSETUP 0x0D /* return setup data */ +#define CMD_WRITE_CH2 0x1A /* write channel 2 buffer */ +#define CMD_READ_CH2 0x1B /* read channel 2 buffer */ +#define CMD_ECHO 0x1F /* ECHO command data */ +#define CMD_OPTIONS 0x21 /* set adapter options */ + +/* READ INTERRUPT STATUS. */ +#define INTR_ANY 0x80 /* any interrupt */ +#define INTR_SRCD 0x08 /* SCSI reset detected */ +#define INTR_HACC 0x04 /* HA command complete */ +#define INTR_MBOA 0x02 /* MBO empty */ +#define INTR_MBIF 0x01 /* MBI full */ + + +/* Structure for the INQUIRE_SETUP_INFORMATION reply. */ +#pragma pack(push,1) +typedef struct { + uint8_t uOffset :4, + uTransferPeriod :3, + fSynchronous :1; +} ReplyInquireSetupInformationSynchronousValue; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + uint8_t fSynchronousInitiationEnabled :1, + fParityCheckingEnabled :1, + uReserved1 :6; + uint8_t uBusTransferRate; + uint8_t uPreemptTimeOnBus; + uint8_t uTimeOffBus; + uint8_t cMailbox; + addr24 MailboxAddress; + ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8]; + uint8_t uDisconnectPermittedId0To7; + uint8_t VendorSpecificData[28]; +} ReplyInquireSetupInformation; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + uint8_t Count; + addr24 Address; +} MailboxInit_t; +#pragma pack(pop) + +/* + * Mailbox Definitions. + * + * Mailbox Out (MBO) command values. + */ +#define MBO_FREE 0x00 +#define MBO_START 0x01 +#define MBO_ABORT 0x02 + +/* Mailbox In (MBI) status values. */ +#define MBI_FREE 0x00 +#define MBI_SUCCESS 0x01 +#define MBI_ABORT 0x02 +#define MBI_NOT_FOUND 0x03 +#define MBI_ERROR 0x04 + +#pragma pack(push,1) +typedef struct { + uint8_t CmdStatus; + addr24 CCBPointer; +} Mailbox_t; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + uint32_t CCBPointer; + union { + struct { + uint8_t Reserved[3]; + uint8_t ActionCode; + } out; + struct { + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Reserved; + uint8_t CompletionCode; + } in; + } u; +} Mailbox32_t; +#pragma pack(pop) + +/* + * + * CCB - SCSI Command Control Block + * + * The CCB is a superset of the CDB (Command Descriptor Block) + * and specifies detailed information about a SCSI command. + * + */ +/* Byte 0 Command Control Block Operation Code */ +#define SCSI_INITIATOR_COMMAND 0x00 +#define TARGET_MODE_COMMAND 0x01 +#define SCATTER_GATHER_COMMAND 0x02 +#define SCSI_INITIATOR_COMMAND_RES 0x03 +#define SCATTER_GATHER_COMMAND_RES 0x04 +#define BUS_RESET 0x81 + +/* Byte 1 Address and Direction Control */ +#define CCB_TARGET_ID_SHIFT 0x06 /* CCB Op Code = 00, 02 */ +#define CCB_INITIATOR_ID_SHIFT 0x06 /* CCB Op Code = 01 */ +#define CCB_DATA_XFER_IN 0x01 +#define CCB_DATA_XFER_OUT 0x02 +#define CCB_LUN_MASK 0x07 /* Logical Unit Number */ + +/* Byte 2 SCSI_Command_Length - Length of SCSI CDB + Byte 3 Request Sense Allocation Length */ +#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ +#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ + +/* Bytes 4, 5 and 6 Data Length - Data transfer byte count */ +/* Bytes 7, 8 and 9 Data Pointer - SGD List or Data Buffer */ +/* Bytes 10, 11 and 12 Link Pointer - Next CCB in Linked List */ +/* Byte 13 Command Link ID - TBD (I don't know yet) */ +/* Byte 14 Host Status - Host Adapter status */ +#define CCB_COMPLETE 0x00 /* CCB completed without error */ +#define CCB_LINKED_COMPLETE 0x0A /* Linked command completed */ +#define CCB_LINKED_COMPLETE_INT 0x0B /* Linked complete with intr */ +#define CCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ +#define CCB_DATA_OVER_UNDER_RUN 0x12 +#define CCB_UNEXPECTED_BUS_FREE 0x13 /* Trg dropped SCSI BSY */ +#define CCB_PHASE_SEQUENCE_FAIL 0x14 /* Trg bus phase sequence fail */ +#define CCB_BAD_MBO_COMMAND 0x15 /* MBO command not 0, 1 or 2 */ +#define CCB_INVALID_OP_CODE 0x16 /* CCB invalid operation code */ +#define CCB_BAD_LINKED_LUN 0x17 /* Linked CCB LUN diff from 1st */ +#define CCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ +#define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */ +#define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */ + +/* Byte 15 Target Status + + See scsi.h files for these statuses. + Bytes 16 and 17 Reserved (must be 0) + Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block */ + +#pragma pack(push,1) +typedef struct { + uint8_t Opcode; + uint8_t Reserved1 :3, + ControlByte :2, + TagQueued :1, + QueueTag :2; + uint8_t CdbLength; + uint8_t RequestSenseLength; + uint32_t DataLength; + uint32_t DataPointer; + uint8_t Reserved2[2]; + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Id; + uint8_t Lun :5, + LegacyTagEnable :1, + LegacyQueueTag :2; + uint8_t Cdb[12]; + uint8_t Reserved3[6]; + uint32_t SensePointer; +} CCB32; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + uint8_t Opcode; + uint8_t Lun :3, + ControlByte :2, + Id :3; + uint8_t CdbLength; + uint8_t RequestSenseLength; + addr24 DataLength; + addr24 DataPointer; + addr24 LinkPointer; + uint8_t LinkId; + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Reserved[2]; + uint8_t Cdb[12]; +} CCB; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + uint8_t Opcode; + uint8_t Pad1 :3, + ControlByte :2, + Pad2 :3; + uint8_t CdbLength; + uint8_t RequestSenseLength; + uint8_t Pad3[9]; + uint8_t CompletionCode; /* Only used by the 1542C/CF(/CP?) BIOS mailboxes */ + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Pad4[2]; + uint8_t Cdb[12]; +} CCBC; +#pragma pack(pop) + +#pragma pack(push,1) +typedef union { + CCB32 new; + CCB old; + CCBC common; +} CCBU; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + CCBU CmdBlock; + uint8_t *RequestSenseBuffer; + uint32_t CCBPointer; + int Is24bit; + uint8_t TargetID, + LUN, + HostStatus, + TargetStatus, + MailboxCompletionCode; +} Req_t; +#pragma pack(pop) + +typedef struct { + int8_t type; /* type of device */ + + char vendor[16]; /* name of device vendor */ + char name[16]; /* name of device */ + + volatile + int8_t Irq; + volatile + uint8_t IrqEnabled; + + int8_t DmaChannel; + int8_t HostID; + uint32_t Base; + uint8_t pos_regs[8]; /* MCA */ + + wchar_t *bios_path; /* path to BIOS image file */ + uint32_t rom_addr; /* address of BIOS ROM */ + uint16_t rom_ioaddr; /* offset in BIOS of I/O addr */ + uint16_t rom_shram; /* index to shared RAM */ + uint16_t rom_shramsz; /* size of shared RAM */ + uint16_t rom_fwhigh; /* offset in BIOS of ver ID */ + rom_t bios; /* BIOS memory descriptor */ + rom_t uppersck; /* BIOS memory descriptor */ + uint8_t *rom1; /* main BIOS image */ + uint8_t *rom2; /* SCSI-Select image */ + + wchar_t *nvr_path; /* path to NVR image file */ + uint8_t *nvr; /* EEPROM buffer */ + + int64_t ResetCB; + + volatile uint8_t /* for multi-threading, keep */ + Status, /* these volatile */ + Interrupt; + + Req_t Req; + uint8_t Geometry; + uint8_t Control; + uint8_t Command; + uint8_t CmdBuf[128]; + uint8_t CmdParam; + uint8_t CmdParamLeft; + uint8_t DataBuf[65536]; + uint16_t DataReply; + uint16_t DataReplyLeft; + + volatile + uint32_t MailboxInit, + MailboxCount, + MailboxOutAddr, + MailboxOutPosCur, + MailboxInAddr, + MailboxInPosCur, + MailboxReq; + + volatile + int Mbx24bit, + MailboxOutInterrupts; + + volatile + int PendingInterrupt, + Lock; + + volatile + uint8_t shadow_ram[128]; + + volatile + uint8_t MailboxIsBIOS, + ToRaise; + + uint8_t shram_mode; + + volatile + uint8_t dma_buffer[128]; + + volatile + uint32_t BIOSMailboxInit, + BIOSMailboxCount, + BIOSMailboxOutAddr, + BIOSMailboxOutPosCur, + BIOSMailboxReq, + Residue; + + volatile + uint8_t BusOnTime, + BusOffTime, + ATBusSpeed; + + char *fw_rev; /* The 4 bytes of the revision command information + 2 extra bytes for BusLogic */ + uint8_t bus; /* Basically a copy of device flags */ + uint8_t setup_info_len; + uint8_t max_id; + uint8_t pci_slot; + + uint32_t reset_duration; + + mem_mapping_t mmio_mapping; + + uint8_t int_geom_writable; + uint8_t cdrom_boot; + + /* Pointer to a structure of vendor-specific data that only the vendor-specific code can understand */ + void *ven_data; + + /* Pointer to a function that performs vendor-specific operation during the thread */ + void (*ven_thread)(void *p); + /* Pointer to a function that executes the second parameter phase of the vendor-specific command */ + void (*ven_cmd_phase1)(void *p); + /* Pointer to a function that gets the host adapter ID in case it has to be read from a non-standard location */ + uint8_t (*ven_get_host_id)(void *p); + /* Pointer to a function that updates the IRQ in the vendor-specific space */ + uint8_t (*ven_get_irq)(void *p); + /* Pointer to a function that updates the DMA channel in the vendor-specific space */ + uint8_t (*ven_get_dma)(void *p); + /* Pointer to a function that returns whether command is fast */ + uint8_t (*ven_cmd_is_fast)(void *p); + /* Pointer to a function that executes vendor-specific fast path commands */ + uint8_t (*ven_fast_cmds)(void *p, uint8_t cmd); + /* Pointer to a function that gets the parameter length for vendor-specific commands */ + uint8_t (*get_ven_param_len)(void *p); + /* Pointer to a function that executes vendor-specific commands and returns whether or not to suppress the IRQ */ + uint8_t (*ven_cmds)(void *p); + /* Pointer to a function that fills in the vendor-specific setup data */ + void (*get_ven_data)(void *p); + /* Pointer to a function that determines if the mode is aggressive */ + uint8_t (*is_aggressive_mode)(void *p); + /* Pointer to a function that returns interrupt type (0 = edge, 1 = level) */ + uint8_t (*interrupt_type)(void *p); + /* Pointer to a function that resets vendor-specific data */ + void (*ven_reset)(void *p); +} x54x_t; + + +#pragma pack(push,1) +typedef struct +{ + uint8_t command; + uint8_t lun:3, + reserved:2, + id:3; + union { + struct { + uint16_t cyl; + uint8_t head; + uint8_t sec; + } chs; + struct { + uint8_t lba0; /* MSB */ + uint8_t lba1; + uint8_t lba2; + uint8_t lba3; /* LSB */ + } lba; + } u; + uint8_t secount; + addr24 dma_address; +} BIOSCMD; +#pragma pack(pop) +#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \ + (p->u.lba.lba2<<8) | p->u.lba.lba3) + + + +extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset); +extern void x54x_busy_set(void); +extern void x54x_thread_start(x54x_t *dev); +extern void x54x_busy_clear(void); +extern uint8_t x54x_busy(void); +extern void x54x_buf_alloc(uint8_t id, uint8_t lun, int length); +extern void x54x_buf_free(uint8_t id, uint8_t lun); +extern uint8_t x54x_mbo_process(x54x_t *dev); +extern void x54x_wait_for_poll(void); +extern void x54x_io_set(x54x_t *dev, uint32_t base); +extern void x54x_io_remove(x54x_t *dev, uint32_t base); +extern void x54x_mem_init(x54x_t *dev, uint32_t addr); +extern void x54x_mem_enable(x54x_t *dev); +extern void x54x_mem_set_addr(x54x_t *dev, uint32_t base); +extern void x54x_mem_disable(x54x_t *dev); +extern void *x54x_init(device_t *info); +extern void x54x_close(void *priv); +extern void x54x_device_reset(void *priv); + + + +#endif diff --git a/src/serial.c b/src/serial.c index a195c310e..8470f7428 100644 --- a/src/serial.c +++ b/src/serial.c @@ -1,11 +1,17 @@ +#include +#include +#include #include - +#include #include "ibm.h" #include "io.h" -#include "mouse.h" #include "pic.h" +#include "mem.h" +#include "rom.h" #include "serial.h" #include "timer.h" +#include "mouse.h" + enum { @@ -183,7 +189,7 @@ uint8_t serial_read(uint16_t addr, void *p) serial_update_ints(serial); temp = serial_read_fifo(serial); if (serial->fifo_read != serial->fifo_write) - serial->recieve_delay = 1000 * TIMER_USEC; + serial->recieve_delay = 1000LL * TIMER_USEC; break; case 1: if (serial->lcr & 0x80) diff --git a/src/serial.h b/src/serial.h index 4decfec6f..f127d74f0 100644 --- a/src/serial.h +++ b/src/serial.h @@ -56,7 +56,7 @@ typedef struct _serial_ { uint8_t fifo[256]; int fifo_read, fifo_write; - int receive_delay; + int64_t receive_delay; void *bh; /* BottomHalf handler */ } SERIAL; @@ -99,7 +99,7 @@ typedef struct uint8_t fifo[256]; int fifo_read, fifo_write; - int recieve_delay; + int64_t recieve_delay; } SERIAL; void serial_write_fifo(SERIAL *serial, uint8_t dat); diff --git a/src/sio_detect.c b/src/sio_detect.c index b8f359b47..a51fd9006 100644 --- a/src/sio_detect.c +++ b/src/sio_detect.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "ibm.h" #include "io.h" #include "floppy/floppy.h" diff --git a/src/sio_fdc37c665.c b/src/sio_fdc37c665.c index 7a5716aff..c9cef0759 100644 --- a/src/sio_fdc37c665.c +++ b/src/sio_fdc37c665.c @@ -8,21 +8,27 @@ * * Implementation of the SMC FDC37C665 Super I/O Chip. * - * Version: @(#)sio_fdc37c665.c 1.0.4 2017/09/03 + * Version: @(#)sio_fdc37c665.c 1.0.6 2017/09/30 * * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" +#include "device.h" #include "lpt.h" #include "serial.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" #include "floppy/floppy.h" #include "floppy/fdc.h" #include "floppy/fdd.h" -#include "hdd/hdd_ide_at.h" #include "sio.h" diff --git a/src/sio_fdc37c669.c b/src/sio_fdc37c669.c index 3a7cfee81..bfff245b0 100644 --- a/src/sio_fdc37c669.c +++ b/src/sio_fdc37c669.c @@ -8,19 +8,25 @@ * * Implementation of the SMC FDC37C669 Super I/O Chip. * - * Version: @(#)sio_fdc37c669.c 1.0.2 2017/09/03 + * Version: @(#)sio_fdc37c669.c 1.0.4 2017/09/30 * * Author: Miran Grca, * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" +#include "device.h" #include "lpt.h" #include "serial.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" #include "floppy/floppy.h" #include "floppy/fdc.h" #include "floppy/fdd.h" -#include "hdd/hdd_ide_at.h" #include "sio.h" diff --git a/src/sio_fdc37c932fr.c b/src/sio_fdc37c932fr.c index 8d51eb094..205cfde23 100644 --- a/src/sio_fdc37c932fr.c +++ b/src/sio_fdc37c932fr.c @@ -8,19 +8,25 @@ * * Implementation of the SMC FDC37C932FR Super I/O Chip. * - * Version: @(#)sio_fdc37c932fr.c 1.0.3 2017/09/03 + * Version: @(#)sio_fdc37c932fr.c 1.0.5 2017/09/30 * * Author: Miran Grca, * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" +#include "device.h" #include "lpt.h" #include "serial.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" #include "floppy/floppy.h" #include "floppy/fdc.h" #include "floppy/fdd.h" -#include "hdd/hdd_ide_at.h" #include "sio.h" diff --git a/src/sio_pc87306.c b/src/sio_pc87306.c index c960c268c..c955c372e 100644 --- a/src/sio_pc87306.c +++ b/src/sio_pc87306.c @@ -8,19 +8,25 @@ * * Emulation of the NatSemi PC87306 Super I/O chip. * - * Version: @(#)sio_pc87306.c 1.0.3 2017/09/03 + * Version: @(#)sio_pc87306.c 1.0.5 2017/09/30 * * Author: Miran Grca, * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" +#include "device.h" #include "lpt.h" #include "serial.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" #include "floppy/floppy.h" #include "floppy/fdc.h" #include "floppy/fdd.h" -#include "hdd/hdd_ide_at.h" #include "sio.h" diff --git a/src/sio_um8669f.c b/src/sio_um8669f.c index 4e3215412..f94d3c92e 100644 --- a/src/sio_um8669f.c +++ b/src/sio_um8669f.c @@ -21,6 +21,10 @@ PnP registers : 70 - IRQ 74 - DMA*/ +#include +#include +#include +#include #include "ibm.h" #include "io.h" #include "lpt.h" diff --git a/src/sio_w83877f.c b/src/sio_w83877f.c index 9c48a9c00..d63414cc6 100644 --- a/src/sio_w83877f.c +++ b/src/sio_w83877f.c @@ -11,13 +11,19 @@ * Winbond W83877F Super I/O Chip * Used by the Award 430HX * - * Version: @(#)sio_w83877f.c 1.0.2 2017/09/03 + * Version: @(#)sio_w83877f.c 1.0.3 2017/09/24 * * Author: Miran Grca, * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "ibm.h" #include "io.h" +#include "mem.h" +#include "rom.h" #include "lpt.h" #include "serial.h" #include "floppy/floppy.h" diff --git a/src/sound/dbopl.cpp b/src/sound/dbopl.cpp index e8002b7cf..85228ae10 100644 --- a/src/sound/dbopl.cpp +++ b/src/sound/dbopl.cpp @@ -20,10 +20,9 @@ /* $Id: dbopl.cpp,v 1.10 2009-06-10 19:54:51 harekiet Exp $ */ -#include #include #include -//#include "dosbox.h" +#include #include "dbopl.h" diff --git a/src/sound/midi.c b/src/sound/midi.c index 476283853..1c70b252d 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -1,24 +1,26 @@ #include -#include #include #include +#include +#include #include "../device.h" -#include "midi.h" #include "../ibm.h" - -#include "../win/plat_midi.h" -#include "../win/plat_ticks.h" +#include "../plat.h" +#include "../plat_midi.h" +#include "midi.h" +#include "midi_system.h" #ifdef USE_FLUIDSYNTH # include "midi_fluidsynth.h" #endif #ifdef USE_MUNT # include "midi_mt32.h" #endif -#include "midi_system.h" + int midi_device_current = 0; static int midi_device_last = 0; + typedef struct { const char *name; diff --git a/src/sound/midi.h b/src/sound/midi.h index 371c79eb4..2b38c5a5f 100644 --- a/src/sound/midi.h +++ b/src/sound/midi.h @@ -1,8 +1,15 @@ +#ifndef EMU_SOUND_MIDI_H +# define EMU_SOUND_MIDI_H + + extern int midi_device_current; + int midi_device_available(int card); char *midi_device_getname(int card); -struct device_t *midi_device_getdevice(int card); +#ifdef EMU_DEVICE_H +device_t *midi_device_getdevice(int card); +#endif int midi_device_has_config(int card); char *midi_device_get_internal_name(int card); int midi_device_get_from_internal_name(char *s); @@ -32,4 +39,7 @@ void midi_poll(); #else #define SYSTEM_MIDI_NAME "System MIDI" #define SYSTEM_MIDI_INTERNAL_NAME "system_midi" -#endif \ No newline at end of file +#endif + + +#endif /*EMU_SOUND_MIDI_H*/ diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 101f0dad1..cce894675 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -1,23 +1,25 @@ /* some code borrowed from scummvm */ #ifdef USE_FLUIDSYNTH - - -#include +#include #include #include +#include +#include #include #include "../config.h" -#include "../win/plat_dynld.h" -#include "../win/plat_thread.h" -#include "../win/plat_ui.h" #include "../device.h" -#include "midi_fluidsynth.h" +#include "../plat.h" +#include "../plat_dynld.h" +#include "../ui.h" #include "midi.h" +#include "midi_fluidsynth.h" #include "sound.h" + #define RENDER_RATE 100 #define BUFFER_SEGMENTS 10 + extern void givealbuffer_midi(void *buf, uint32_t size); extern void pclog(const char *format, ...); extern void al_set_midi(int freq, int buf_size); @@ -213,7 +215,7 @@ void fluidsynth_sysex(uint8_t* data, unsigned int len) f_fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); } -void* fluidsynth_init(void) +void* fluidsynth_init(device_t *info) { fluidsynth_t* data = &fsdev; memset(data, 0, sizeof(fluidsynth_t)); @@ -222,7 +224,7 @@ void* fluidsynth_init(void) fluidsynth_handle = dynld_module("libfluidsynth.dll", fluidsynth_imports); if (fluidsynth_handle == NULL) { - plat_msgbox_error(IDS_2171); + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2171); return NULL; } @@ -324,10 +326,20 @@ void fluidsynth_close(void* p) fluidsynth_t* data = &fsdev; - if (data->sound_font != -1) + if (data->sound_font != -1) { f_fluid_synth_sfunload(data->synth, data->sound_font, 1); - f_delete_fluid_synth(data->synth); - f_delete_fluid_settings(data->settings); + data->sound_font = -1; + } + + if (data->synth) { + f_delete_fluid_synth(data->synth); + data->synth = NULL; + } + + if (data->settings) { + f_delete_fluid_settings(data->settings); + data->settings = NULL; + } midi_close(); @@ -533,8 +545,10 @@ device_t fluidsynth_device = { "FluidSynth", 0, + 0, fluidsynth_init, fluidsynth_close, + NULL, fluidsynth_available, NULL, NULL, diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index c3ffe49e3..eab3e7dab 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -1,15 +1,18 @@ +#include #include -#include #include +#include +#include #include "munt/c_interface/c_interface.h" -#include "../win/plat_thread.h" #include "../ibm.h" #include "../device.h" #include "../mem.h" #include "../rom.h" -#include "midi_mt32.h" -#include "midi.h" +#include "../plat.h" #include "sound.h" +#include "midi.h" +#include "midi_mt32.h" + extern void givealbuffer_midi(void *buf, uint32_t size); extern void pclog(const char *format, ...); @@ -219,12 +222,12 @@ void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) return dev; } -void *mt32_init() +void *mt32_init(device_t *info) { return mt32emu_init(L"roms/sound/mt32/mt32_control.rom", L"roms/sound/mt32/mt32_pcm.rom"); } -void *cm32l_init() +void *cm32l_init(device_t *info) { return mt32emu_init(L"roms/sound/cm32l/cm32l_control.rom", L"roms/sound/cm32l/cm32l_pcm.rom"); } @@ -313,8 +316,10 @@ device_t mt32_device = { "Roland MT-32 Emulation", 0, + 0, mt32_init, mt32_close, + NULL, mt32_available, NULL, NULL, @@ -326,8 +331,10 @@ device_t cm32l_device = { "Roland CM-32L Emulation", 0, + 0, cm32l_init, mt32_close, + NULL, cm32l_available, NULL, NULL, diff --git a/src/sound/midi_system.c b/src/sound/midi_system.c index f26c1dcbd..982049bdc 100644 --- a/src/sound/midi_system.c +++ b/src/sound/midi_system.c @@ -1,13 +1,16 @@ #include #include -#include #include +#include +#include #include "../device.h" -#include "../win/plat_midi.h" -#include "midi_system.h" +#include "../plat.h" +#include "../plat_midi.h" #include "midi.h" +#include "midi_system.h" -void* system_midi_init() + +void* system_midi_init(device_t *info) { midi_device_t* dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); @@ -30,7 +33,7 @@ void system_midi_close(void* p) midi_close(); } -int system_midi_available() +int system_midi_available(void) { return plat_midi_get_num_devs(); } @@ -51,9 +54,10 @@ static device_config_t system_midi_config[] = device_t system_midi_device = { SYSTEM_MIDI_NAME, - 0, + 0, 0, system_midi_init, system_midi_close, + NULL, system_midi_available, NULL, NULL, diff --git a/src/sound/munt/Partial.cpp b/src/sound/munt/Partial.cpp index da5e7c4a1..0b7231122 100644 --- a/src/sound/munt/Partial.cpp +++ b/src/sound/munt/Partial.cpp @@ -43,7 +43,7 @@ static Bit32s getPANFactor(Bit32s panSetting) { if (firstRun) { firstRun = false; - for (Bit32u i = 1; i < PAN_FACTORS_COUNT; i++) { + for (Bit32u i = 1; i < (Bit32u)PAN_FACTORS_COUNT; i++) { PAN_FACTORS[i] = Bit32s(0.5 + i * 8192.0 / double(PAN_FACTORS_COUNT - 1)); } } diff --git a/src/sound/openal.c b/src/sound/openal.c index c2d8d87fa..1c80de8fd 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -1,7 +1,9 @@ #define USE_OPENAL #include +#include #include #include +#include #ifdef USE_OPENAL # undef AL_API # undef ALC_API diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index 10ff8b2b3..4a22e4c76 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -2,6 +2,10 @@ AD1848 CODEC emulation (Windows Sound System compatible)*/ +#include +#include +#include +#include #include #include "../ibm.h" #include "../dma.h" @@ -58,7 +62,7 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) switch (ad1848->index) { case 8: - freq = (val & 1) ? 16934400 : 24576000; + freq = (val & 1) ? 16934400LL : 24576000LL; switch ((val >> 1) & 7) { case 0: freq /= 3072; break; @@ -71,7 +75,7 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) case 7: freq /= 2560; break; } ad1848->freq = freq; - ad1848->timer_latch = (int)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); + ad1848->timer_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); break; case 9: @@ -97,7 +101,7 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) void ad1848_speed_changed(ad1848_t *ad1848) { - ad1848->timer_latch = (int)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); + ad1848->timer_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); } void ad1848_update(ad1848_t *ad1848) diff --git a/src/sound/snd_ad1848.h b/src/sound/snd_ad1848.h index 3a0dd4e46..39dc60a5e 100644 --- a/src/sound/snd_ad1848.h +++ b/src/sound/snd_ad1848.h @@ -11,13 +11,13 @@ typedef struct ad1848_t int16_t out_l, out_r; - int enable; + int64_t enable; int irq, dma; - int freq; + int64_t freq; - int timer_count, timer_latch; + int64_t timer_count, timer_latch; int16_t buffer[SOUNDBUFLEN * 2]; int pos; diff --git a/src/sound/snd_adlib.c b/src/sound/snd_adlib.c index e131d04c3..964d6e475 100644 --- a/src/sound/snd_adlib.c +++ b/src/sound/snd_adlib.c @@ -1,4 +1,8 @@ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mca.h" @@ -59,7 +63,7 @@ void adlib_mca_write(int port, uint8_t val, void *p) adlib->pos_regs[port & 7] = val; } -void *adlib_init() +void *adlib_init(device_t *info) { adlib_t *adlib = malloc(sizeof(adlib_t)); memset(adlib, 0, sizeof(adlib_t)); @@ -71,9 +75,9 @@ void *adlib_init() return adlib; } -void *adlib_mca_init() +void *adlib_mca_init(device_t *info) { - adlib_t *adlib = adlib_init(); + adlib_t *adlib = adlib_init(info); io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); mca_add(adlib_mca_read, adlib_mca_write, adlib); @@ -93,12 +97,10 @@ void adlib_close(void *p) device_t adlib_device = { "AdLib", - 0, - adlib_init, - adlib_close, - NULL, - NULL, - NULL, + DEVICE_ISA, + 0, + adlib_init, adlib_close, NULL, + NULL, NULL, NULL, NULL, NULL }; @@ -106,10 +108,8 @@ device_t adlib_mca_device = { "AdLib (MCA)", DEVICE_MCA, - adlib_init, - adlib_close, - NULL, - NULL, - NULL, + 0, + adlib_init, adlib_close, NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 2d16bfd7b..3c8a76c19 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -1,5 +1,8 @@ -#include +#include +#include #include +#include +#include #include "../ibm.h" #include "../io.h" #include "../dma.h" @@ -7,6 +10,7 @@ #include "../pit.h" #include "../mem.h" #include "../rom.h" +#include "../nvr.h" #include "../timer.h" #include "../device.h" #include "sound.h" @@ -36,7 +40,7 @@ typedef struct adgold_t int16_t adgold_mma_out[2]; int adgold_mma_intpos[2]; - int adgold_mma_timer_count; + int64_t adgold_mma_timer_count; struct { @@ -575,9 +579,9 @@ void adgold_timer_poll(void *p) { adgold_t *adgold = (adgold_t *)p; - while (adgold->adgold_mma_timer_count <= 0) + while (adgold->adgold_mma_timer_count <= 0LL) { - adgold->adgold_mma_timer_count += (int)((double)TIMER_USEC * 1.88964); + adgold->adgold_mma_timer_count += (int64_t)((double)TIMER_USEC * 1.88964); if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/ { adgold->adgold_mma.timer0_count--; @@ -750,7 +754,7 @@ static void adgold_get_buffer(int32_t *buffer, int len, void *p) } -void *adgold_init() +void *adgold_init(device_t *info) { FILE *f; int c; @@ -773,7 +777,7 @@ void *adgold_init() for (; c >= 0; c--) attenuation[c] = 0; - f = nvrfopen(L"adgold.bin", L"rb"); + f = nvr_fopen(L"adgold.bin", L"rb"); if (f) { fread(adgold->adgold_eeprom, 0x18, 1, f); @@ -813,7 +817,7 @@ void adgold_close(void *p) FILE *f; adgold_t *adgold = (adgold_t *)p; - f = nvrfopen(L"adgold.bin", L"wb"); + f = nvr_fopen(L"adgold.bin", L"wb"); if (f) { fwrite(adgold->adgold_eeprom, 0x18, 1, f); @@ -836,9 +840,10 @@ static device_config_t adgold_config[] = device_t adgold_device = { "AdLib Gold", - 0, + DEVICE_ISA, 0, adgold_init, adgold_close, + NULL, NULL, NULL, NULL, diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c new file mode 100644 index 000000000..9349676b1 --- /dev/null +++ b/src/sound/snd_audiopci.c @@ -0,0 +1,1122 @@ +#include +#include +#include +#include "../ibm.h" +#include "../device.h" +#include "../io.h" +#include "../mem.h" +#include "../pci.h" +#include "../timer.h" +#include "sound.h" +#include "snd_audiopci.h" + +typedef struct es1371_t +{ + uint8_t pci_command, pci_serr; + + uint32_t base_addr; + + uint8_t int_line; + + uint16_t pmcsr; + + uint32_t int_ctrl; + uint32_t int_status; + + uint32_t legacy_ctrl; + + int mem_page; + + uint32_t si_cr; + + uint32_t sr_cir; + uint16_t sr_ram[128]; + + uint8_t uart_ctrl; + uint8_t uart_status; + + uint16_t codec_regs[64]; + uint32_t codec_ctrl; + + struct + { + uint32_t addr, addr_latch; + uint16_t count, size; + + uint16_t samp_ct, curr_samp_ct; + + int64_t time, latch; + + uint32_t vf, ac; + + int16_t buffer_l[64], buffer_r[64]; + int buffer_pos, buffer_pos_end; + + int16_t out_l, out_r; + + int32_t vol_l, vol_r; + } dac[2], adc; + + int64_t dac_latch, dac_time; + + int master_vol_l, master_vol_r; + + int card; + + int pos; + int16_t buffer[SOUNDBUFLEN * 2]; +} es1371_t; + +#define LEGACY_SB_ADDR (1 << 29) +#define LEGACY_SSCAPE_ADDR_SHIFT 27 +#define LEGACY_CODEC_ADDR_SHIFT 25 +#define LEGACY_FORCE_IRQ (1 << 24) +#define LEGACY_CAPTURE_SLAVE_DMA (1 << 23) +#define LEGACY_CAPTURE_SLAVE_PIC (1 << 22) +#define LEGACY_CAPTURE_MASTER_DMA (1 << 21) +#define LEGACY_CAPTURE_MASTER_PIC (1 << 20) +#define LEGACY_CAPTURE_ADLIB (1 << 19) +#define LEGACY_CAPTURE_SB (1 << 18) +#define LEGACY_CAPTURE_CODEC (1 << 17) +#define LEGACY_CAPTURE_SSCAPE (1 << 16) +#define LEGACY_EVENT_SSCAPE (0 << 8) +#define LEGACY_EVENT_CODEC (1 << 8) +#define LEGACY_EVENT_SB (2 << 8) +#define LEGACY_EVENT_ADLIB (3 << 8) +#define LEGACY_EVENT_MASTER_PIC (4 << 8) +#define LEGACY_EVENT_MASTER_DMA (5 << 8) +#define LEGACY_EVENT_SLAVE_PIC (6 << 8) +#define LEGACY_EVENT_SLAVE_DMA (7 << 8) +#define LEGACY_EVENT_MASK (7 << 8) +#define LEGACY_EVENT_ADDR_SHIFT 3 +#define LEGACY_EVENT_ADDR_MASK (0x1f << 3) +#define LEGACY_EVENT_TYPE_RW (1 << 2) +#define LEGACY_INT (1 << 0) + +#define SRC_RAM_WE (1 << 24) + +#define CODEC_READ (1 << 23) +#define CODEC_READY (1 << 31) + +#define INT_DAC1_EN (1 << 6) +#define INT_DAC2_EN (1 << 5) + +#define SI_P2_INTR_EN (1 << 9) +#define SI_P1_INTR_EN (1 << 8) + +#define INT_STATUS_INTR (1 << 31) +#define INT_STATUS_DAC1 (1 << 2) +#define INT_STATUS_DAC2 (1 << 1) + +#define FORMAT_MONO_8 0 +#define FORMAT_STEREO_8 1 +#define FORMAT_MONO_16 2 +#define FORMAT_STEREO_16 3 + +const int32_t codec_attn[]= +{ + 25,32,41,51,65,82,103,130,164,206,260,327,412,519,653, + 822,1036,1304,1641,2067,2602,3276,4125,5192,6537,8230,10362,13044, + 16422,20674,26027,32767 +}; + +static void es1371_fetch(es1371_t *es1371, int dac_nr); +static void update_legacy(es1371_t *es1371); + +static void es1371_update_irqs(es1371_t *es1371) +{ + int irq = 0; + + if ((es1371->int_status & INT_STATUS_DAC1) && (es1371->si_cr & SI_P1_INTR_EN)) + irq = 1; + if ((es1371->int_status & INT_STATUS_DAC2) && (es1371->si_cr & SI_P2_INTR_EN)) + irq = 1; + + if (irq) + es1371->int_status |= INT_STATUS_INTR; + else + es1371->int_status &= ~INT_STATUS_INTR; + + if (es1371->legacy_ctrl & LEGACY_FORCE_IRQ) + irq = 1; + + if (irq) + { + pci_set_irq(es1371->card, PCI_INTA); +// pclog("Raise IRQ\n"); + } + else + { + pci_clear_irq(es1371->card, PCI_INTA); +// pclog("Drop IRQ\n"); + } +} + +static uint8_t es1371_inb(uint16_t port, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + uint8_t ret = 0; + + switch (port & 0x3f) + { + case 0x00: + ret = es1371->int_ctrl & 0xff; + break; + case 0x01: + ret = (es1371->int_ctrl >> 8) & 0xff; + break; + case 0x02: + ret = (es1371->int_ctrl >> 16) & 0xff; + break; + case 0x03: + ret = (es1371->int_ctrl >> 24) & 0xff; + break; + + case 0x04: + ret = es1371->int_status & 0xff; + break; + case 0x05: + ret = (es1371->int_status >> 8) & 0xff; + break; + case 0x06: + ret = (es1371->int_status >> 16) & 0xff; + break; + case 0x07: + ret = (es1371->int_status >> 24) & 0xff; + break; + + + case 0x09: + ret = es1371->uart_status; + break; + + case 0x0c: + ret = es1371->mem_page; + break; + + case 0x1a: + ret = es1371->legacy_ctrl >> 16; + break; + case 0x1b: + ret = es1371->legacy_ctrl >> 24; + break; + + case 0x20: + ret = es1371->si_cr & 0xff; + break; + case 0x21: + ret = es1371->si_cr >> 8; + break; + case 0x22: + ret = (es1371->si_cr >> 16) | 0x80; + break; + case 0x23: + ret = 0xff; + break; + + default: + pclog("Bad es1371_inb: port=%04x\n", port); + } + +// pclog("es1371_inb: port=%04x ret=%02x\n", port, ret); +// output = 3; + return ret; +} +static uint16_t es1371_inw(uint16_t port, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + uint16_t ret = 0; + + switch (port & 0x3e) + { + case 0x00: + ret = es1371->int_ctrl & 0xffff; + break; + case 0x02: + ret = (es1371->int_ctrl >> 16) & 0xffff; + break; + + case 0x18: + ret = es1371->legacy_ctrl & 0xffff; +// pclog("Read legacy ctrl %04x\n", ret); + break; + + case 0x26: + ret = es1371->dac[0].curr_samp_ct; + break; + + case 0x2a: + ret = es1371->dac[1].curr_samp_ct; + break; + + case 0x36: + switch (es1371->mem_page) + { + case 0xc: + ret = es1371->dac[0].count; + break; + + default: + pclog("Bad es1371_inw: mem_page=%x port=%04x\n", es1371->mem_page, port); + } + break; + + case 0x3e: + switch (es1371->mem_page) + { + case 0xc: + ret = es1371->dac[1].count; + break; + + default: + pclog("Bad es1371_inw: mem_page=%x port=%04x\n", es1371->mem_page, port); + } + break; + + default: + pclog("Bad es1371_inw: port=%04x\n", port); + } + +// pclog("es1371_inw: port=%04x ret=%04x %04x:%08x\n", port, ret, CS,cpu_state.pc); + return ret; +} +static uint32_t es1371_inl(uint16_t port, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + uint32_t ret = 0; + + switch (port & 0x3c) + { + case 0x00: + ret = es1371->int_ctrl; + break; + case 0x04: + ret = es1371->int_status; + break; + + case 0x10: + ret = es1371->sr_cir & ~0xffff; + ret |= es1371->sr_ram[es1371->sr_cir >> 25]; + break; + + case 0x14: + ret = es1371->codec_ctrl & 0x00ff0000; + ret |= es1371->codec_regs[(es1371->codec_ctrl >> 16) & 0x3f]; + ret |= CODEC_READY; + break; + + case 0x34: + switch (es1371->mem_page) + { + + case 0xc: + ret = es1371->dac[0].size | (es1371->dac[0].count << 16); + break; + + case 0xd: + + ret = es1371->adc.size | (es1371->adc.count << 16); + break; + + default: + pclog("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port); + } + break; + + case 0x3c: + switch (es1371->mem_page) + { + case 0xc: + ret = es1371->dac[1].size | (es1371->dac[1].count << 16); + break; + + default: + pclog("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port); + } + break; + + default: + pclog("Bad es1371_inl: port=%04x\n", port); + } + +// pclog("es1371_inl: port=%04x ret=%08x %08x\n", port, ret, cpu_state.pc); + return ret; +} + +static void es1371_outb(uint16_t port, uint8_t val, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + +// pclog("es1371_outb: port=%04x val=%02x %04x:%08x\n", port, val, cs, cpu_state.pc); + switch (port & 0x3f) + { + case 0x00: + if (!(es1371->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) + { + es1371->dac[0].addr = es1371->dac[0].addr_latch; + es1371->dac[0].buffer_pos = 0; + es1371->dac[0].buffer_pos_end = 0; + es1371_fetch(es1371, 0); + } + if (!(es1371->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) + { + es1371->dac[1].addr = es1371->dac[1].addr_latch; + es1371->dac[1].buffer_pos = 0; + es1371->dac[1].buffer_pos_end = 0; + es1371_fetch(es1371, 1); + } + es1371->int_ctrl = (es1371->int_ctrl & 0xffffff00) | val; + break; + case 0x01: + es1371->int_ctrl = (es1371->int_ctrl & 0xffff00ff) | (val << 8); + break; + case 0x02: + es1371->int_ctrl = (es1371->int_ctrl & 0xff00ffff) | (val << 16); + break; + case 0x03: + es1371->int_ctrl = (es1371->int_ctrl & 0x00ffffff) | (val << 24); + break; + + case 0x09: + es1371->uart_ctrl = val; + break; + + case 0x0c: + es1371->mem_page = val & 0xf; + break; + + case 0x18: + es1371->legacy_ctrl |= LEGACY_INT; + nmi = 0; + break; + case 0x1a: + es1371->legacy_ctrl = (es1371->legacy_ctrl & 0xff00ffff) | (val << 16); + update_legacy(es1371); + break; + case 0x1b: + es1371->legacy_ctrl = (es1371->legacy_ctrl & 0x00ffffff) | (val << 24); + es1371_update_irqs(es1371); +// output = 3; + update_legacy(es1371); + break; + + case 0x20: + es1371->si_cr = (es1371->si_cr & 0xffff00) | val; + break; + case 0x21: + es1371->si_cr = (es1371->si_cr & 0xff00ff) | (val << 8); + if (!(es1371->si_cr & SI_P1_INTR_EN)) + es1371->int_status &= ~INT_STATUS_DAC1; + if (!(es1371->si_cr & SI_P2_INTR_EN)) + es1371->int_status &= ~INT_STATUS_DAC2; + es1371_update_irqs(es1371); + break; + case 0x22: + es1371->si_cr = (es1371->si_cr & 0x00ffff) | (val << 16); + break; + + default: + pclog("Bad es1371_outb: port=%04x val=%02x\n", port, val); + } +} +static void es1371_outw(uint16_t port, uint16_t val, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + +// pclog("es1371_outw: port=%04x val=%04x\n", port, val); + switch (port & 0x3f) + { + case 0x0c: + es1371->mem_page = val & 0xf; + break; + + case 0x24: + es1371->dac[0].samp_ct = val; + break; + + case 0x28: + es1371->dac[1].samp_ct = val; + break; + + default: + pclog("Bad es1371_outw: port=%04x val=%04x\n", port, val); + } +} +static void es1371_outl(uint16_t port, uint32_t val, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + +// pclog("es1371_outl: port=%04x val=%08x %04x:%08x\n", port, val, CS, cpu_state.pc); + switch (port & 0x3f) + { + case 0x04: + break; + + case 0x0c: + es1371->mem_page = val & 0xf; + break; + + case 0x10: + es1371->sr_cir = val; + if (es1371->sr_cir & SRC_RAM_WE) + { +// pclog("Write SR RAM %02x %04x\n", es1371->sr_cir >> 25, val & 0xffff); + es1371->sr_ram[es1371->sr_cir >> 25] = val & 0xffff; + switch (es1371->sr_cir >> 25) + { + case 0x71: + es1371->dac[0].vf = (es1371->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5); + es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15); + break; + case 0x72: + es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7fff) | (val & 0x7fff); + break; + case 0x73: + es1371->dac[0].vf = (es1371->dac[0].vf & ~0x7fff) | (val & 0x7fff); + break; + + case 0x75: + es1371->dac[1].vf = (es1371->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5); + es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15); + break; + case 0x76: + es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7fff) | (val & 0x7fff); + break; + case 0x77: + es1371->dac[1].vf = (es1371->dac[1].vf & ~0x7fff) | (val & 0x7fff); + break; + + case 0x7c: + es1371->dac[0].vol_l = (int32_t)(int16_t)(val & 0xffff); + break; + case 0x7d: + es1371->dac[0].vol_r = (int32_t)(int16_t)(val & 0xffff); + break; + case 0x7e: + es1371->dac[1].vol_l = (int32_t)(int16_t)(val & 0xffff); + break; + case 0x7f: + es1371->dac[1].vol_r = (int32_t)(int16_t)(val & 0xffff); + break; + } + } + break; + + case 0x14: + es1371->codec_ctrl = val; + if (!(val & CODEC_READ)) + { +// pclog("Write codec %02x %04x\n", (val >> 16) & 0x3f, val & 0xffff); + es1371->codec_regs[(val >> 16) & 0x3f] = val & 0xffff; + switch ((val >> 16) & 0x3f) + { + case 0x02: /*Master volume*/ + if (val & 0x8000) + es1371->master_vol_l = es1371->master_vol_r = 0; + else + { + if (val & 0x2000) + es1371->master_vol_l = codec_attn[0]; + else + es1371->master_vol_l = codec_attn[0x1f - ((val >> 8) & 0x1f)]; + if (val & 0x20) + es1371->master_vol_r = codec_attn[0]; + else + es1371->master_vol_r = codec_attn[0x1f - (val & 0x1f)]; + } + break; + case 0x12: /*CD volume*/ + if (val & 0x8000) + sound_set_cd_volume(0, 0); + else + sound_set_cd_volume(codec_attn[0x1f - ((val >> 8) & 0x1f)] * 2, codec_attn[0x1f - (val & 0x1f)] * 2); + break; + } + } + break; + + case 0x24: + es1371->dac[0].samp_ct = val & 0xffff; + break; + + case 0x28: + es1371->dac[1].samp_ct = val & 0xffff; + break; + + case 0x30: + switch (es1371->mem_page) + { + case 0x0: case 0x1: case 0x2: case 0x3: + case 0x4: case 0x5: case 0x6: case 0x7: + case 0x8: case 0x9: case 0xa: case 0xb: + break; + + case 0xc: + es1371->dac[0].addr_latch = val; +// pclog("DAC1 addr %08x\n", val); + break; + + default: + pclog("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + } + break; + case 0x34: + switch (es1371->mem_page) + { + case 0x0: case 0x1: case 0x2: case 0x3: + case 0x4: case 0x5: case 0x6: case 0x7: + case 0x8: case 0x9: case 0xa: case 0xb: + break; + + case 0xc: + es1371->dac[0].size = val & 0xffff; + es1371->dac[0].count = val >> 16; + if (es1371->dac[0].count) + es1371->dac[0].count -= 4; + break; + + case 0xd: + es1371->adc.size = val & 0xffff; + es1371->adc.count = val >> 16; + break; + + default: + pclog("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + } + break; + case 0x38: + switch (es1371->mem_page) + { + case 0x0: case 0x1: case 0x2: case 0x3: + case 0x4: case 0x5: case 0x6: case 0x7: + case 0x8: case 0x9: case 0xa: case 0xb: + break; + + case 0xc: + es1371->dac[1].addr_latch = val; + break; + + case 0xd: + break; + + default: + pclog("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + } + break; + case 0x3c: + switch (es1371->mem_page) + { + case 0x0: case 0x1: case 0x2: case 0x3: + case 0x4: case 0x5: case 0x6: case 0x7: + case 0x8: case 0x9: case 0xa: case 0xb: + break; + + case 0xc: + es1371->dac[1].size = val & 0xffff; + es1371->dac[1].count = val >> 16; + break; + + default: + pclog("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + } + break; + + default: + pclog("Bad es1371_outl: port=%04x val=%08x\n", port, val); + } +} + +static void capture_event(es1371_t *es1371, int type, int rw, uint16_t port) +{ + es1371->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK); + es1371->legacy_ctrl |= type; + if (rw) + es1371->legacy_ctrl |= LEGACY_EVENT_TYPE_RW; + else + es1371->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW; + es1371->legacy_ctrl |= ((port << LEGACY_EVENT_ADDR_SHIFT) & LEGACY_EVENT_ADDR_MASK); + es1371->legacy_ctrl &= ~LEGACY_INT; + nmi = 1; +// pclog("Event! %s %04x\n", rw ? "write" : "read", port); +} + +static void capture_write_sscape(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_SSCAPE, 1, port); +} +static void capture_write_codec(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_CODEC, 1, port); +} +static void capture_write_sb(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_SB, 1, port); +} +static void capture_write_adlib(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_ADLIB, 1, port); +} +static void capture_write_master_pic(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_MASTER_PIC, 1, port); +} +static void capture_write_master_dma(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_MASTER_DMA, 1, port); +} +static void capture_write_slave_pic(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_SLAVE_PIC, 1, port); +} +static void capture_write_slave_dma(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_SLAVE_DMA, 1, port); +} + +static uint8_t capture_read_sscape(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_SSCAPE, 0, port); + return 0xff; +} +static uint8_t capture_read_codec(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_CODEC, 0, port); + return 0xff; +} +static uint8_t capture_read_sb(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_SB, 0, port); + return 0xff; +} +static uint8_t capture_read_adlib(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_ADLIB, 0, port); + return 0xff; +} +static uint8_t capture_read_master_pic(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_MASTER_PIC, 0, port); + return 0xff; +} +static uint8_t capture_read_master_dma(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_MASTER_DMA, 0, port); + return 0xff; +} +static uint8_t capture_read_slave_pic(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_SLAVE_PIC, 0, port); + return 0xff; +} +static uint8_t capture_read_slave_dma(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_SLAVE_DMA, 0, port); + return 0xff; +} + +static void update_legacy(es1371_t *es1371) +{ + io_removehandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); + io_removehandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); + io_removehandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); + io_removehandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); + + io_removehandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); + io_removehandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); + io_removehandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); + + io_removehandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); + io_removehandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); + + io_removehandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371); + + io_removehandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371); + io_removehandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371); + io_removehandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371); + io_removehandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371); + + if (es1371->legacy_ctrl & LEGACY_CAPTURE_SSCAPE) + { + switch ((es1371->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) + { + case 0: io_sethandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; + case 1: io_sethandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; + case 2: io_sethandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; + case 3: io_sethandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; + } + } + if (es1371->legacy_ctrl & LEGACY_CAPTURE_CODEC) + { + switch ((es1371->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) + { + case 0: io_sethandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; + case 2: io_sethandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; + case 3: io_sethandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; + } + } + if (es1371->legacy_ctrl & LEGACY_CAPTURE_SB) + { + if (!(es1371->legacy_ctrl & LEGACY_SB_ADDR)) + io_sethandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); + else + io_sethandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); + } + if (es1371->legacy_ctrl & LEGACY_CAPTURE_ADLIB) + io_sethandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371); + if (es1371->legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) + io_sethandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371); + if (es1371->legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) + io_sethandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371); + if (es1371->legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) + io_sethandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371); + if (es1371->legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) + io_sethandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371); +} + + +static uint8_t es1371_pci_read(int func, int addr, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + + if (func) + return 0; + + //pclog("ES1371 PCI read %08X PC=%08x\n", addr, cpu_state.pc); + + switch (addr) + { + case 0x00: return 0x74; /*Ensoniq*/ + case 0x01: return 0x12; + + case 0x02: return 0x71; /*ES1371*/ + case 0x03: return 0x13; + + case 0x04: return es1371->pci_command; + case 0x05: return es1371->pci_serr; + + case 0x06: return 0x10; /*Supports ACPI*/ + case 0x07: return 0; + + case 0x08: return 2; /*Revision ID*/ + case 0x09: return 0x00; /*Multimedia audio device*/ + case 0x0a: return 0x01; + case 0x0b: return 0x04; + + case 0x10: return 0x01 | (es1371->base_addr & 0xc0); /*memBaseAddr*/ + case 0x11: return es1371->base_addr >> 8; + case 0x12: return es1371->base_addr >> 16; + case 0x13: return es1371->base_addr >> 24; + + case 0x2c: return 0x74; /*Subsystem vendor ID*/ + case 0x2d: return 0x12; + case 0x2e: return 0x71; + case 0x2f: return 0x13; + + case 0x34: return 0xdc; /*Capabilites pointer*/ + + case 0x3c: return es1371->int_line; + case 0x3d: return 0x01; /*INTA*/ + + case 0x3e: return 0xc; /*Minimum grant*/ + case 0x3f: return 0x80; /*Maximum latency*/ + + case 0xdc: return 0x01; /*Capabilities identifier*/ + case 0xdd: return 0x00; /*Next item pointer*/ + case 0xde: return 0x31; /*Power management capabilities*/ + case 0xdf: return 0x6c; + + case 0xe0: return es1371->pmcsr & 0xff; + case 0xe1: return es1371->pmcsr >> 8; + } + return 0; +} + +static void es1371_pci_write(int func, int addr, uint8_t val, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + + if (func) + return; + +// pclog("ES1371 PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc); + + switch (addr) + { + case 0x04: + if (es1371->pci_command & PCI_COMMAND_IO) + io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); + es1371->pci_command = val & 0x05; + if (es1371->pci_command & PCI_COMMAND_IO) + io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); + break; + case 0x05: + es1371->pci_serr = val & 1; + break; + + case 0x10: + if (es1371->pci_command & PCI_COMMAND_IO) + io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); + es1371->base_addr = (es1371->base_addr & 0xffffff00) | (val & 0xc0); + if (es1371->pci_command & PCI_COMMAND_IO) + io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); + break; + case 0x11: + if (es1371->pci_command & PCI_COMMAND_IO) + io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); + es1371->base_addr = (es1371->base_addr & 0xffff00c0) | (val << 8); + if (es1371->pci_command & PCI_COMMAND_IO) + io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); + break; + case 0x12: + es1371->base_addr = (es1371->base_addr & 0xff00ffc0) | (val << 16); + break; + case 0x13: + es1371->base_addr = (es1371->base_addr & 0x00ffffc0) | (val << 24); + break; + + case 0x3c: + es1371->int_line = val; + break; + + case 0xe0: + es1371->pmcsr = (es1371->pmcsr & 0xff00) | (val & 0x03); + break; + case 0xe1: + es1371->pmcsr = (es1371->pmcsr & 0x00ff) | ((val & 0x01) << 8); + break; + } +// pclog("es1371->base_addr %08x\n", es1371->base_addr); +} + +static void es1371_fetch(es1371_t *es1371, int dac_nr) +{ + int format = dac_nr ? ((es1371->si_cr >> 2) & 3) : (es1371->si_cr & 3); + int pos = es1371->dac[dac_nr].buffer_pos & 63; + int c; + +//pclog("Fetch format=%i %08x %08x %08x %08x %08x\n", format, es1371->dac[dac_nr].count, es1371->dac[dac_nr].size, es1371->dac[dac_nr].curr_samp_ct,es1371->dac[dac_nr].samp_ct, es1371->dac[dac_nr].addr); + switch (format) + { + case FORMAT_MONO_8: + for (c = 0; c < 32; c += 4) + { + es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr) ^ 0x80) << 8; + es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+1) ^ 0x80) << 8; + es1371->dac[dac_nr].buffer_l[(pos+c+2) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+2) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+2) ^ 0x80) << 8; + es1371->dac[dac_nr].buffer_l[(pos+c+3) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+3) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+3) ^ 0x80) << 8; + es1371->dac[dac_nr].addr += 4; + + es1371->dac[dac_nr].buffer_pos_end += 4; + es1371->dac[dac_nr].count++; + if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size) + { + es1371->dac[dac_nr].count = 0; + es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch; + break; + } + } + break; + case FORMAT_STEREO_8: + for (c = 0; c < 16; c += 2) + { + es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr) ^ 0x80) << 8; + es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 1) ^ 0x80) << 8; + es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 2) ^ 0x80) << 8; + es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 3) ^ 0x80) << 8; + es1371->dac[dac_nr].addr += 4; + + es1371->dac[dac_nr].buffer_pos_end += 2; + es1371->dac[dac_nr].count++; + if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size) + { + es1371->dac[dac_nr].count = 0; + es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch; + break; + } + } + break; + case FORMAT_MONO_16: + for (c = 0; c < 16; c += 2) + { + es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr); + es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr + 2); + es1371->dac[dac_nr].addr += 4; + + es1371->dac[dac_nr].buffer_pos_end += 2; + es1371->dac[dac_nr].count++; + if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size) + { + es1371->dac[dac_nr].count = 0; + es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch; + break; + } + } + break; + case FORMAT_STEREO_16: + for (c = 0; c < 4; c++) + { + es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr); + es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr + 2); +// pclog("Fetch %02x %08x %04x %04x\n", (pos+c) & 63, es1371->dac[dac_nr].addr, es1371->dac[dac_nr].buffer_l[(pos+c) & 63], es1371->dac[dac_nr].buffer_r[(pos+c) & 63]); + es1371->dac[dac_nr].addr += 4; + + es1371->dac[dac_nr].buffer_pos_end++; + es1371->dac[dac_nr].count++; + if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size) + { + es1371->dac[dac_nr].count = 0; + es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch; + break; + } + } + break; + } +} + +static void es1371_next_sample(es1371_t *es1371, int dac_nr) +{ + if ((es1371->dac[dac_nr].buffer_pos - es1371->dac[dac_nr].buffer_pos_end) >= 0) + { + es1371_fetch(es1371, dac_nr); + } + + es1371->dac[dac_nr].out_l = es1371->dac[dac_nr].buffer_l[es1371->dac[dac_nr].buffer_pos & 63]; + es1371->dac[dac_nr].out_r = es1371->dac[dac_nr].buffer_r[es1371->dac[dac_nr].buffer_pos & 63]; +// pclog("Use %02x %04x %04x\n", es1371->dac[dac_nr].buffer_pos & 63, es1371->dac[dac_nr].out_l, es1371->dac[dac_nr].out_r); + + es1371->dac[dac_nr].buffer_pos++; +// pclog("Next sample %08x %08x %08x\n", es1371->dac[dac_nr].buffer_pos, es1371->dac[dac_nr].buffer_pos_end, es1371->dac[dac_nr].curr_samp_ct); +} + +//static FILE *es1371_f;//,*es1371_f2; +static void es1371_poll(void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + + es1371->dac[1].time += es1371->dac[1].latch; + + if (es1371->int_ctrl & INT_DAC1_EN) + { +// pclog("1Samp %i %i %08x\n", es1371->dac[0].curr_samp_ct, es1371->dac[0].samp_ct, es1371->dac[0].ac); + es1371->dac[0].ac += es1371->dac[0].vf; + if (es1371->dac[0].ac & (~0 << (15+4))) + { + es1371->dac[0].ac &= ~(~0 << (15+4)); + es1371_next_sample(es1371, 0); + + es1371->dac[0].curr_samp_ct++; + if (es1371->dac[0].curr_samp_ct == es1371->dac[0].samp_ct) + { +// pclog("DAC1 IRQ\n"); + es1371->int_status |= INT_STATUS_DAC1; + es1371_update_irqs(es1371); + } + if (es1371->dac[0].curr_samp_ct > es1371->dac[0].samp_ct) + { + es1371->dac[0].curr_samp_ct = 0; + } + } + } + + if (es1371->int_ctrl & INT_DAC2_EN) + { +// pclog("2Samp %i %i %08x\n", es1371->dac[1].curr_samp_ct, es1371->dac[1].samp_ct, es1371->dac[1].ac); + es1371->dac[1].ac += es1371->dac[1].vf; + if (es1371->dac[1].ac & (~0 << (15+4))) + { + es1371->dac[1].ac &= ~(~0 << (15+4)); + es1371_next_sample(es1371, 1); + + es1371->dac[1].curr_samp_ct++; + if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct) + { + es1371->dac[1].curr_samp_ct = 0; +// pclog("DAC2 IRQ\n"); + es1371->int_status |= INT_STATUS_DAC2; + es1371_update_irqs(es1371); + } + } + } + + for (; es1371->pos < sound_pos_global; es1371->pos++) + { + int32_t l, r; + + l = (es1371->dac[0].out_l * es1371->dac[0].vol_l) >> 12; + l += ((es1371->dac[1].out_l * es1371->dac[1].vol_l) >> 12); + r = (es1371->dac[0].out_r * es1371->dac[0].vol_r) >> 12; + r += ((es1371->dac[1].out_r * es1371->dac[1].vol_r) >> 12); + + l >>= 1; + r >>= 1; + + l = (l * es1371->master_vol_l) >> 15; + r = (r * es1371->master_vol_r) >> 15; + + if (l < -32768) + l = -32768; + else if (l > 32767) + l = 32767; + if (r < -32768) + r = -32768; + else if (r > 32767) + r = 32767; + + es1371->buffer[es1371->pos*2] = l; + es1371->buffer[es1371->pos*2 + 1] = r; + } +} + +static void es1371_get_buffer(int32_t *buffer, int len, void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + int c; + + for (c = 0; c < len * 2; c++) + buffer[c] += (es1371->buffer[c] / 2); + + es1371->pos = 0; +} + +static void *es1371_init() +{ + es1371_t *es1371 = malloc(sizeof(es1371_t)); + memset(es1371, 0, sizeof(es1371_t)); + + sound_add_handler(es1371_get_buffer, es1371); + + es1371->card = pci_add_card(PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, es1371); + + timer_add(es1371_poll, &es1371->dac[1].time, TIMER_ALWAYS_ENABLED, es1371); + + return es1371; +} + +static void es1371_close(void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + + free(es1371); +} + +static void es1371_speed_changed(void *p) +{ + es1371_t *es1371 = (es1371_t *)p; + + es1371->dac[1].latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); +} + +device_t es1371_device = +{ + "Ensoniq AudioPCI (ES1371)", + DEVICE_PCI, + 0, + es1371_init, + es1371_close, + NULL, + NULL, + es1371_speed_changed, + NULL, + NULL, + NULL +}; diff --git a/src/sound/snd_audiopci.h b/src/sound/snd_audiopci.h new file mode 100644 index 000000000..5aff3d024 --- /dev/null +++ b/src/sound/snd_audiopci.h @@ -0,0 +1 @@ +extern device_t es1371_device; diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 1cbf723b2..9f148a57f 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -1,5 +1,8 @@ #include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../device.h" @@ -155,7 +158,7 @@ uint8_t cms_read(uint16_t addr, void *p) return cms->regs[chip][cms->addrs[chip] & 31]; } -void *cms_init() +void *cms_init(device_t *info) { cms_t *cms = malloc(sizeof(cms_t)); memset(cms, 0, sizeof(cms_t)); @@ -176,11 +179,8 @@ void cms_close(void *p) device_t cms_device = { "Creative Music System / Game Blaster", - 0, - cms_init, - cms_close, - NULL, - NULL, - NULL, + 0, 0, + cms_init, cms_close, NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_emu8k.c b/src/sound/snd_emu8k.c index cb2983a59..40d4bc221 100644 --- a/src/sound/snd_emu8k.c +++ b/src/sound/snd_emu8k.c @@ -1,23 +1,32 @@ +#include +#include +#include +#include #include +#include #include #include "../ibm.h" #include "../device.h" #include "../io.h" #include "../mem.h" #include "../rom.h" +#include "../timer.h" #include "sound.h" #include "snd_emu8k.h" -#include "../timer.h" -#include #if !defined FILTER_INITIAL && !defined FILTER_MOOG && !defined FILTER_CONSTANT +//#define FILTER_INITIAL #define FILTER_MOOG +//#define FILTER_CONSTANT #endif #if !defined RESAMPLER_LINEAR && !defined RESAMPLER_CUBIC +//#define RESAMPLER_LINEAR #define RESAMPLER_CUBIC #endif +//#define EMU8K_DEBUG_REGISTERS + char *PORT_NAMES[][8] = { /* Data 0 ( 0x620/0x622) */ @@ -49,8 +58,8 @@ char *PORT_NAMES[][8] = "AWE_HWCF2" "AWE_HWCF3" */ - 0, - 0, + 0,//"AWE_INIT1", + 0,//"AWE_INIT3", "AWE_ENVVOL", "AWE_DCYSUSV", "AWE_ENVVAL", @@ -59,8 +68,8 @@ char *PORT_NAMES[][8] = /* Data 2 0xA22 */ { "AWE_CCCA", 0, - 0, - 0, + 0,//"AWE_INIT2", + 0,//"AWE_INIT4", "AWE_ATKHLDV", "AWE_LFO1VAL", "AWE_ATKHLD", @@ -84,7 +93,9 @@ enum ENV_DELAY = 1, ENV_ATTACK = 2, ENV_HOLD = 3, + //ENV_DECAY = 4, ENV_SUSTAIN = 5, + //ENV_RELEASE = 6, ENV_RAMP_DOWN = 7, ENV_RAMP_UP = 8 }; @@ -227,15 +238,15 @@ uint32_t rep_count_w = 0; # define READ16(addr, var) READ16_SWITCH(addr, var) \ { \ const char *name=0; \ - switch(addr) \ + switch(addr&0xF02) \ { \ - case 0x620: case 0x622: \ + case 0x600: case 0x602: \ name = PORT_NAMES[0][emu8k->cur_reg]; \ break; \ - case 0xA20: \ + case 0xA00: \ name = PORT_NAMES[1][emu8k->cur_reg]; \ break; \ - case 0xA22: \ + case 0xA02: \ name = PORT_NAMES[2][emu8k->cur_reg]; \ break; \ } \ @@ -251,15 +262,15 @@ uint32_t rep_count_w = 0; # define WRITE16(addr, var, val) WRITE16_SWITCH(addr, var, val) \ { \ const char *name=0; \ - switch(addr) \ + switch(addr&0xF02) \ { \ - case 0x620: case 0x622: \ + case 0x600: case 0x602: \ name = PORT_NAMES[0][emu8k->cur_reg]; \ break; \ - case 0xA20: \ + case 0xA00: \ name = PORT_NAMES[1][emu8k->cur_reg]; \ break; \ - case 0xA22: \ + case 0xA02: \ name = PORT_NAMES[2][emu8k->cur_reg]; \ break; \ } \ @@ -276,7 +287,7 @@ uint32_t rep_count_w = 0; #else # define READ16(addr, var) READ16_SWITCH(addr, var) # define WRITE16(addr, var, val) WRITE16_SWITCH(addr, var, val) -#endif /* EMU8K_DEBUG_REGISTERS */ +#endif //EMU8K_DEBUG_REGISTERS static inline int16_t EMU8K_READ(emu8k_t *emu8k, uint32_t addr) @@ -308,7 +319,7 @@ static inline int32_t EMU8K_READ_INTERP_CUBIC(emu8k_t *emu8k, uint32_t int_addr, * the card could use two oscillators (usually 31 and 32) where it would * be writing the OPL3 output, and to which, chorus and reverb could be applied to get * those effects for OPL3 sounds.*/ -/* if ((addr & EMU8K_FM_MEM_ADDRESS) == EMU8K_FM_MEM_ADDRESS) {} */ +// if ((addr & EMU8K_FM_MEM_ADDRESS) == EMU8K_FM_MEM_ADDRESS) {} /* This is cubic interpolation. * Not the same than 3-point interpolation, but a better approximation than linear @@ -385,7 +396,7 @@ uint16_t emu8k_inw(uint16_t addr, void *p) last_read=tmpz; pclog("EMU8K READ RAM I/O or configuration or clock \n"); } - /* pclog("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); */ + //pclog("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); } else if ((addr&0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) { @@ -400,7 +411,7 @@ uint16_t emu8k_inw(uint16_t addr, void *p) last_read=tmpz; pclog("EMU8K READ INIT \n"); } - /* pclog("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); */ + //pclog("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); } else { @@ -468,7 +479,7 @@ uint16_t emu8k_inw(uint16_t addr, void *p) } rep_count_r++; } -#endif /* EMU8K_DEBUG_REGISTERS */ +#endif // EMU8K_DEBUG_REGISTERS switch (addr & 0xF02) @@ -720,7 +731,7 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) #ifdef EMU8K_DEBUG_REGISTERS if (addr == 0xE22) { - /* pclog("EMU8K WRITE POINTER: %d\n", val); */ + //pclog("EMU8K WRITE POINTER: %d\n", val); } else if ((addr&0xF00) == 0x600) { @@ -755,7 +766,7 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) last_write=tmpz; pclog("EMU8K WRITE RAM I/O or configuration \n"); } - /* pclog("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); */ + //pclog("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); } else if ((addr&0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) { @@ -770,12 +781,12 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) last_write=tmpz; pclog("EMU8K WRITE INIT \n"); } - /* pclog("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); */ + //pclog("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); } else if (addr != 0xE22) { uint32_t tmpz = (addr << 16)|(emu8k->cur_reg<<5)| emu8k->cur_voice; - /* if (tmpz != last_write) */ + //if (tmpz != last_write) if(1) { char* name = 0; @@ -810,7 +821,7 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) } rep_count_w++; } -#endif /* EMU8K_DEBUG_REGISTERS */ +#endif //EMU8K_DEBUG_REGISTERS switch (addr & 0xF02) @@ -950,15 +961,15 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) break; case 0x9: emu8k->reverb_engine.reflections[0].feedback = (val&0xF)/15.0; break; - case 0xB: /* emu8k->reverb_engine.reflections[0].feedback_r = (val&0xF)/15.0; */ + case 0xB: //emu8k->reverb_engine.reflections[0].feedback_r = (val&0xF)/15.0; break; case 0x11:emu8k->reverb_engine.reflections[1].feedback = (val&0xF)/15.0; break; - case 0x13: /* emu8k->reverb_engine.reflections[1].feedback_r = (val&0xF)/15.0; */ + case 0x13: //emu8k->reverb_engine.reflections[1].feedback_r = (val&0xF)/15.0; break; case 0x19: emu8k->reverb_engine.reflections[2].feedback = (val&0xF)/15.0; break; - case 0x1B: /* emu8k->reverb_engine.reflections[2].feedback_r = (val&0xF)/15.0; */ + case 0x1B: //emu8k->reverb_engine.reflections[2].feedback_r = (val&0xF)/15.0; break; } } @@ -975,12 +986,13 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) emu8k->chorus_engine.feedback = (val&0xFF); break; case 12: - emu8k->chorus_engine.delay_samples_central = val; + /* Limiting this to a sane value given our buffer. */ + emu8k->chorus_engine.delay_samples_central = (val&0x1FFF); break; case 1: emu8k->reverb_engine.refl_in_amp = val&0xFF; break; - case 3: /* emu8k->reverb_engine.refl_in_amp_r = val&0xFF; */ + case 3: //emu8k->reverb_engine.refl_in_amp_r = val&0xFF; break; } } @@ -1001,17 +1013,17 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) if (emu8k->voice[emu8k->cur_voice].env_engine_on && old_on != emu8k->voice[emu8k->cur_voice].env_engine_on) { - if (emu8k->hwcf3 != 0x04 && emu8k->cur_voice == 31) + if (emu8k->hwcf3 != 0x04) { /* This is a hack for some programs like Doom or cubic player 1.7 that don't initialize the hwcfg and init registers (doom does not init the card at all. only tests the cfg registers) */ emu8k->hwcf3 = 0x04; } - /* reset lfos. */ + //reset lfos. emu8k->voice[emu8k->cur_voice].lfo1_count.addr = 0; emu8k->voice[emu8k->cur_voice].lfo2_count.addr = 0; - /* Trigger envelopes */ + // Trigger envelopes if (ATKHLDV_TRIGGER(emu8k->voice[emu8k->cur_voice].atkhldv)) { vol_env->value_amp_hz = 0; @@ -1088,7 +1100,7 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) case 7: { - /* TODO: Look for a bug on delay (first trigger it works, next trigger it doesn't) */ + //TODO: Look for a bug on delay (first trigger it works, next trigger it doesn't) emu8k->voice[emu8k->cur_voice].dcysus = val; emu8k_envelope_t* const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; /* Converting the input in octaves to envelope value range. */ @@ -1133,7 +1145,9 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) if (emu8k->init1[0] != 0x03FF) { /*(1/256th of a 44Khz sample) */ - emu8k->chorus_engine.delay_offset_samples_right = ((double)emu8k->hwcf4)/256.0; + /* clip the value to a reasonable value given our buffer */ + int32_t tmp = emu8k->hwcf4&0x1FFFFF; + emu8k->chorus_engine.delay_offset_samples_right = ((double)tmp)/256.0; } return; case 10: @@ -1143,9 +1157,14 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) { /* The scale of this value is unknown. I've taken it as milliHz. * Another interpretation could be periods. (and so, Hz = 1/period)*/ - double osc_speed = emu8k->hwcf5;/* *1.316; */ + double osc_speed = emu8k->hwcf5;//*1.316; +#if 1 // milliHz /*milliHz to lfotable samples.*/ osc_speed *= 65.536/44100.0; +#elif 0 //periods + /* 44.1Khz ticks to lfotable samples.*/ + osc_speed = 65.536/osc_speed; +#endif /*left shift 32bits for 32.32 fixed.point*/ osc_speed *= 65536.0*65536.0; emu8k->chorus_engine.lfo_inc.addr = (uint64_t)osc_speed; @@ -1231,15 +1250,15 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) break; case 0x1: emu8k->reverb_engine.reflections[3].feedback = (val&0xF)/15.0; break; - case 0x3: /* emu8k->reverb_engine.reflections[3].feedback_r = (val&0xF)/15.0; */ + case 0x3: //emu8k->reverb_engine.reflections[3].feedback_r = (val&0xF)/15.0; break; case 0x9: emu8k->reverb_engine.reflections[4].feedback = (val&0xF)/15.0; break; - case 0xb: /* emu8k->reverb_engine.reflections[4].feedback_r = (val&0xF)/15.0; */ + case 0xb: //emu8k->reverb_engine.reflections[4].feedback_r = (val&0xF)/15.0; break; case 0x11: emu8k->reverb_engine.reflections[5].feedback = (val&0xF)/15.0; break; - case 0x13: /* emu8k->reverb_engine.reflections[5].feedback_r = (val&0xF)/15.0; */ + case 0x13: //emu8k->reverb_engine.reflections[5].feedback_r = (val&0xF)/15.0; break; } } @@ -1256,6 +1275,7 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) { int32_t samples = ((val&0xFF)*emu8k->chorus_engine.delay_samples_central) >> 8; emu8k->chorus_engine.lfodepth_multip = samples; + } break; @@ -1382,8 +1402,8 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) if ((val&0xFF) == 0 && the_voice->cvcf_curr_volume == 0 && the_voice->vtft_vol_target == 0 && the_voice->dcysusv == 0x80 && the_voice->ip == 0) { - /* Patch to avoid some clicking noises with Impulse tracker or other software that sets different values to 0 - to set noteoff, but here, 0 means no attenuation = full volume. */ + // Patch to avoid some clicking noises with Impulse tracker or other software that sets + // different values to 0 to set noteoff, but here, 0 means no attenuation = full volume. return; } the_voice->ifatn = val; @@ -1492,7 +1512,7 @@ void emu8k_work_chorus(int32_t *inbuf, int32_t *outbuf, emu8k_chorus_eng_t *engi for (pos = 0; pos < count; pos++) { double lfo_inter1 = chortable[engine->lfo_pos.int_address]; - /* double lfo_inter2 = chortable[(engine->lfo_pos.int_address+1)&0xFFFF]; */ + // double lfo_inter2 = chortable[(engine->lfo_pos.int_address+1)&0xFFFF]; double offset_lfo =lfo_inter1; //= lfo_inter1 + ((lfo_inter2-lfo_inter1)*engine->lfo_pos.fract_address/65536.0); offset_lfo *= engine->lfodepth_multip; @@ -1501,18 +1521,16 @@ void emu8k_work_chorus(int32_t *inbuf, int32_t *outbuf, emu8k_chorus_eng_t *engi double readdouble = (double)engine->write - (double)engine->delay_samples_central - offset_lfo; int read = (int32_t)floor(readdouble); int fraction_part = (readdouble - (double)read)*65536.0; - if (read < 0) - read = 0; int next_value = read + 1; if(read < 0) { - read += SOUNDBUFLEN; - if(next_value < 0) next_value += SOUNDBUFLEN; + read += EMU8K_LFOCHORUS_SIZE; + if(next_value < 0) next_value += EMU8K_LFOCHORUS_SIZE; } - else if(next_value >= SOUNDBUFLEN) + else if(next_value >= EMU8K_LFOCHORUS_SIZE) { - next_value -= SOUNDBUFLEN; - if(read >= SOUNDBUFLEN) read -= SOUNDBUFLEN; + next_value -= EMU8K_LFOCHORUS_SIZE; + if(read >= EMU8K_LFOCHORUS_SIZE) read -= EMU8K_LFOCHORUS_SIZE; } int32_t dat1 = engine->chorus_left_buffer[read]; int32_t dat2 = engine->chorus_left_buffer[next_value]; @@ -1524,18 +1542,16 @@ void emu8k_work_chorus(int32_t *inbuf, int32_t *outbuf, emu8k_chorus_eng_t *engi /* Work right */ readdouble = (double)engine->write - (double)engine->delay_samples_central - engine->delay_offset_samples_right - offset_lfo; read = (int32_t)floor(readdouble); - if (read < 0) - read = 0; next_value = read + 1; if(read < 0) { - read += SOUNDBUFLEN; - if(next_value < 0) next_value += SOUNDBUFLEN; + read += EMU8K_LFOCHORUS_SIZE; + if(next_value < 0) next_value += EMU8K_LFOCHORUS_SIZE; } - else if(next_value >= SOUNDBUFLEN) + else if(next_value >= EMU8K_LFOCHORUS_SIZE) { - next_value -= SOUNDBUFLEN; - if(read >= SOUNDBUFLEN) read -= SOUNDBUFLEN; + next_value -= EMU8K_LFOCHORUS_SIZE; + if(read >= EMU8K_LFOCHORUS_SIZE) read -= EMU8K_LFOCHORUS_SIZE; } int32_t dat3 = engine->chorus_right_buffer[read]; int32_t dat4 = engine->chorus_right_buffer[next_value]; @@ -1544,7 +1560,7 @@ void emu8k_work_chorus(int32_t *inbuf, int32_t *outbuf, emu8k_chorus_eng_t *engi engine->chorus_right_buffer[engine->write] = *inbuf + ((dat3 * engine->feedback)>>8); ++engine->write; - engine->write %= SOUNDBUFLEN; + engine->write %= EMU8K_LFOCHORUS_SIZE; engine->lfo_pos.addr +=engine->lfo_inc.addr; engine->lfo_pos.int_address &= 0xFFFF; @@ -1594,10 +1610,10 @@ int32_t emu8k_reverb_tail_work(emu8k_reverb_combfilter_t* comb, emu8k_reverb_com /* store new value in delayed buffer */ comb->reflection[comb->read_pos] = in; - /* output = emu8k_reverb_allpass_work(&allpasses[0],output); */ + //output = emu8k_reverb_allpass_work(&allpasses[0],output); output = emu8k_reverb_diffuser_work(&allpasses[1],output); output = emu8k_reverb_diffuser_work(&allpasses[2],output); - /* output = emu8k_reverb_allpass_work(&allpasses[3],output); */ + //output = emu8k_reverb_allpass_work(&allpasses[3],output); if(++comb->read_pos>=comb->bufsize) comb->read_pos = 0; @@ -1660,7 +1676,7 @@ void emu8k_work_reverb(int32_t *inbuf, int32_t *outbuf, emu8k_reverb_eng_t *engi } void emu8k_work_eq(int32_t *inoutbuf, int count) { - /* TODO: Work EQ over buf */ + // TODO: Work EQ over buf } @@ -1679,6 +1695,9 @@ int32_t emu8k_vol_slide(emu8k_slide_t* slide, int32_t target) return slide->last; } +//int32_t old_pitch[32]={0}; +//int32_t old_cut[32]={0}; +//int32_t old_vol[32]={0}; void emu8k_update(emu8k_t *emu8k) { int new_pos = (sound_pos_global * 44100) / 48000; @@ -2051,6 +2070,12 @@ I've recopilated these sentences to get an idea of how to loop /* Update EMU voice registers. */ emu_voice->ccca = (((uint32_t)emu_voice->ccca_qcontrol) << 24) | emu_voice->addr.int_address; emu_voice->cpf_curr_frac_addr = emu_voice->addr.fract_address; + + //if ( emu_voice->cvcf_curr_volume != old_vol[c]) { + // pclog("EMUVOL (%d):%d\n", c, emu_voice->cvcf_curr_volume); + // old_vol[c]=emu_voice->cvcf_curr_volume; + //} + //pclog("EMUFILT :%d\n", emu_voice->cvcf_curr_filt_ctoff); } @@ -2059,7 +2084,7 @@ I've recopilated these sentences to get an idea of how to loop emu8k_work_chorus(&emu8k->chorus_in_buffer[emu8k->pos], buf, &emu8k->chorus_engine, new_pos-emu8k->pos); emu8k_work_eq(buf, new_pos-emu8k->pos); - /* Clip signal */ + // Clip signal for (pos = emu8k->pos; pos < new_pos; pos++) { if (buf[0] < -32768) @@ -2081,14 +2106,14 @@ I've recopilated these sentences to get an idea of how to loop emu8k->pos = new_pos; } /* onboard_ram in kilobytes */ -void emu8k_init(emu8k_t *emu8k, int onboard_ram) +void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) { uint32_t const BLOCK_SIZE_WORDS = 0x10000; FILE *f; int c; double out; - f = romfopen(L"roms/sound/awe32.raw", L"rb"); + f = rom_fopen(L"roms/sound/awe32.raw", L"rb"); if (!f) fatal("AWE32.RAW not found\n"); @@ -2141,9 +2166,9 @@ void emu8k_init(emu8k_t *emu8k, int onboard_ram) } - io_sethandler(0x0620, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - io_sethandler(0x0a20, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - io_sethandler(0x0e20, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_sethandler(emu_addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_sethandler(emu_addr+0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_sethandler(emu_addr+0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); /*Create frequency table. (Convert initial pitch register value to a linear speed change) * The input is encoded such as 0xe000 is center note (no pitch shift) @@ -2174,6 +2199,8 @@ void emu8k_init(emu8k_t *emu8k, int onboard_ram) out = 65535.0; for (c = 0; c < 0x10000; c++) { + //double db = -(c*6.0205999/65535.0)*16.0; + //out = powf(10.f,db/20.f) * 65536.0; env_vol_db_to_vol_target[c] = (int32_t)out; /* calculated from the 65536th root of 65536 */ out /= 1.00016923970; @@ -2279,12 +2306,13 @@ void emu8k_init(emu8k_t *emu8k, int onboard_ram) filt_coeffs[qidx][c][0] = (int32_t)(coef0 * 16777216.0); filt_coeffs[qidx][c][1] = (int32_t)(coef1 * 16777216.0); filt_coeffs[qidx][c][2] = (int32_t)(coef2 * 16777216.0); -#endif /* FILTER_TYPE */ +#endif //FILTER_TYPE /* 42.66 divisions per octave (the doc says quarter seminotes which is 48, but then it would be almost an octave less) */ out *= 1.016378315; /* 42 divisions. This moves the max frequency to 8.5Khz.*/ - /* out *= 1.0166404394; */ + //out *= 1.0166404394; /* This is a linear increment method, that corresponds to the NRPN table, but contradicts the EMU8KPRM doc: */ + //out = 100.0 + (c+1.0)*31.25; //31.25Hz steps */ } } /* NOTE! read_pos and buffer content is implicitly initialized to zero by the sb_t structure memset on sb_awe32_init() */ @@ -2317,8 +2345,8 @@ void emu8k_init(emu8k_t *emu8k, int onboard_ram) cubic_table[c*4+2] = (-1.5 * x * x * x + 2.0 * x * x + 0.5 * x) ; cubic_table[c*4+3] = ( 0.5 * x * x * x - 0.5 * x * x) ; } - /* If this is not set here, AWE card is not detected on Windows with Aweman driver. It's weird that the EMU8k says that this - * has to be set by applications, and the AWE driver does not set it. */ + /* Even when the documentation says that this has to be written by applications to initialize the card, + * several applications and drivers ( aweman on windows, linux oss driver..) read it to detect an AWE card. */ emu8k->hwcf1 = 0x59; emu8k->hwcf2 = 0x20; /* Initial state is muted. 0x04 is unmuted. */ diff --git a/src/sound/snd_emu8k.h b/src/sound/snd_emu8k.h index aa0f0be02..16323a13b 100644 --- a/src/sound/snd_emu8k.h +++ b/src/sound/snd_emu8k.h @@ -1,34 +1,34 @@ + /* All these defines are in samples, not in bytes. */ #define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF #define EMU8K_RAM_MEM_START 0x200000 #define EMU8K_FM_MEM_ADDRESS 0xFFFFE0 #define EMU8K_RAM_POINTERS_MASK 0x3F #define EMU8K_LFOCHORUS_SIZE 0x4000 - /* - Everything in this file assumes little endian - - used for the increment of oscillator position */ + * Everything in this file assumes little endian + */ +/* used for the increment of oscillator position*/ typedef struct emu8k_mem_internal_t { union { - uint64_t addr; - struct { - uint16_t fract_lw_address; - uint16_t fract_address; - uint32_t int_address; - }; + uint64_t addr; + struct { + uint16_t fract_lw_address; + uint16_t fract_address; + uint32_t int_address; + }; }; } emu8k_mem_internal_t; /* used for access to ram pointers from oscillator position. */ typedef struct emu8k_mem_pointers_t { union { - uint32_t addr; - struct { - uint16_t lw_address; - uint8_t hb_address; - uint8_t unused_address; - }; + uint32_t addr; + struct { + uint16_t lw_address; + uint8_t hb_address; + uint8_t unused_address; + }; }; } emu8k_mem_pointers_t; @@ -58,23 +58,29 @@ typedef struct emu8k_mem_pointers_t { The volume envelope operates in dB, with the attack peak providing a full scale output, appropriately scaled by the initial volume. The zero value, however, is actually zero gain. The implementation in the EMU8000 provides for 96 dB of amplitude control. - When 96 dB of attenuation is reached in the final gain amplifier, an abrupt jump to zero gain (infinite dB of attenuation) occurs. In a 16-bit system, this jump is inaudible + When 96 dB of attenuation is reached in the final gain amplifier, an abrupt jump to zero gain + (infinite dB of attenuation) occurs. In a 16-bit system, this jump is inaudible */ /* It seems that the envelopes don't really have a decay/release stage, - but instead they have a volume ramper that can be triggered - automatically (after hold period), or manually (by activating release) - and the "sustain" value is the target of any of both cases. - Some programs like cubic player and AWEAmp use this, and it was - described in the following way in Vince Vu/Judge Dredd's awe32p10.txt: - If the MSB (most significant bit or bit 15) of this register is set, - the Decay/Release will begin immediately, overriding the Delay, Attack, - and Hold. Otherwise the Decay/Release will wait until the Delay, Attack, - and Hold are finished. If you set the MSB of this register, you can use - it as a volume ramper, as on the GUS. The upper byte (except the MSB), - contains the destination volume, and the lower byte contains the ramp time. */ + * but instead they have a volume ramper that can be triggered + * automatically (after hold period), or manually (by activating release) + * and the "sustain" value is the target of any of both cases. + * Some programs like cubic player and AWEAmp use this, and it was + * described in the following way in Vince Vu/Judge Dredd's awe32p10.txt: + * If the MSB (most significant bit or bit 15) of this register is set, + * the Decay/Release will begin immediately, overriding the Delay, Attack, + * and Hold. Otherwise the Decay/Release will wait until the Delay, Attack, + * and Hold are finished. If you set the MSB of this register, you can use + * it as a volume ramper, as on the GUS. The upper byte (except the MSB), + * contains the destination volume, and the lower byte contains the ramp time. + */ -/* attack_amount is linear amplitude (added directly to value). ramp_amount_db is linear dB (added directly to value too, but needs conversion to get linear amplitude). - value range is 21bits for both, linear amplitude being 1<<21 = 0dBFS and 0 = -96dBFS (which is shortcut to silence), and db amplutide being 0 = 0dBFS and -(1<<21) = -96dBFS (which is shortcut to silence). This allows to operate db values by simply adding them. */ +/* attack_amount is linear amplitude (added directly to value). + * ramp_amount_db is linear dB (added directly to value too, but needs conversion to get linear amplitude). + * value range is 21bits for both, linear amplitude being 1<<21 = 0dBFS and 0 = -96dBFS (which is shortcut to silence), + * and db amplutide being 0 = 0dBFS and -(1<<21) = -96dBFS (which is shortcut to silence). + * This allows to operate db values by simply adding them. + */ typedef struct emu8k_envelope_t { int state; int32_t delay_samples, hold_samples, attack_samples; @@ -351,8 +357,6 @@ typedef struct emu8k_t uint16_t wc; - uint16_t c02_read; - uint16_t id; /* The empty block is used to act as an unallocated memory returning zero. */ @@ -364,8 +368,6 @@ typedef struct emu8k_t int cur_reg, cur_voice; - int timer_count; - int16_t out_l, out_r; emu8k_chorus_eng_t chorus_engine; @@ -379,7 +381,395 @@ typedef struct emu8k_t -void emu8k_init(emu8k_t *emu8k, int onboard_ram); +void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram); void emu8k_close(emu8k_t *emu8k); void emu8k_update(emu8k_t *emu8k); + + + + +/* + +Section E - Introduction to the EMU8000 Chip + + The EMU8000 has its roots in E-mu's Proteus sample playback + modules and their renowned Emulator sampler. The EMU8000 has + 32 individual oscillators, each playing back at 44.1 kHz. By + incorporating sophisticated sample interpolation algorithms + and digital filtering, the EMU8000 is capable of producing + high fidelity sample playback. + + The EMU8000 has an extensive modulation capability using two + sine-wave LFOs (Low Frequency Oscillator) and two multi- + stage envelope generators. + + What exactly does modulation mean? Modulation means to + dynamically change a parameter of an audio signal, whether + it be the volume (amplitude modulation, or tremolo), pitch + (frequency modulation, or vibrato) or filter cutoff + frequency (filter modulation, or wah-wah). To modulate + something we would require a modulation source, and a + modulation destination. In the EMU8000, the modulation + sources are the LFOs and the envelope generators, and the + modulation destinations can be the pitch, the volume or the + filter cutoff frequency. + + The EMU8000's LFOs and envelope generators provide a complex + modulation environment. Each sound producing element of the + EMU8000 consists of a resonant low-pass filter, two LFOs, in + which one modulates the pitch (LFO2), and the other + modulates pitch, filter cutoff and volume (LFO1) + simultaneously. There are two envelope generators; envelope + 1 contours both pitch and filter cutoff simultaneously, and + envelope 2 contours volume. The output stage consists of an + effects engine that mixes the dry signals with the + Reverb/chorus level signals to produce the final mix. + + What are the EMU8000 sound elements? + + Each of the sound elements in an EMU8000 consists of the + following: + + Oscillator + An oscillator is the source of an audio signal. + + Low Pass Filter + The low pass filter is responsible for modifying the + timbres of an instrument. The low pass filter's filter + cutoff values can be varied from 100 Hz to 8000 Hz. By + changing the values of the filter cutoff, a myriad of + analogue sounding filter sweeps can be achieved. An + example of a GM instrument that makes use of filter sweep + is instrument number 87, Lead 7 (fifths). + + Amplifier + The amplifier determines the loudness of an audio signal. + + LFO1 + An LFO, or Low Frequency Oscillator, is normally used to + periodically modulate, that is, change a sound parameter, + whether it be volume (amplitude modulation), pitch + (frequency modulation) or filter cutoff (filter + modulation). It operates at sub-audio frequency from + 0.042 Hz to 10.71 Hz. The LFO1 in the EMU8000 modulates + the pitch, volume and filter cutoff simultaneously. + + LFO2 + The LFO2 is similar to the LFO1, except that it modulates + the pitch of the audio signal only. + + Resonance + A filter alone would be like an equalizer, making a + bright audio signal duller, but the addition of resonance + greatly increases the creative potential of a filter. + Increasing the resonance of a filter makes it emphasize + signals at the cutoff frequency, giving the audio signal + a subtle wah-wah, that is, imagine a siren sound going + from bright to dull to bright again periodically. + + LFO1 to Volume (Tremolo) + The LFO1's output is routed to the amplifier, with the + depth of oscillation determined by LFO1 to Volume. LFO1 + to Volume produces tremolo, which is a periodic + fluctuation of volume. Lets say you are listening to a + piece of music on your home stereo system. When you + rapidly increase and decrease the playback volume, you + are creating tremolo effect, and the speed in which you + increases and decreases the volume is the tremolo rate + (which corresponds to the speed at which the LFO is + oscillating). An example of a GM instrument that makes + use of LFO1 to Volume is instrument number 45, Tremolo + Strings. + + LFO1 to Filter Cutoff (Wah-Wah) + The LFO1's output is routed to the filter, with the depth + of oscillation determined by LFO1 to Filter. LFO1 to + Filter produces a periodic fluctuation in the filter + cutoff frequency, producing an effect very similar to + that of a wah-wah guitar (see resonance for a description + of wah-wah) An example of a GM instrument that makes + use of LFO1 to Filter Cutoff is instrument number 19, + Rock Organ. + + LFO1 to Pitch (Vibrato) + The LFO1's output is routed to the oscillator, with the + depth of oscillation determined by LFO1 to Pitch. LFO1 to + Pitch produces a periodic fluctuation in the pitch of the + oscillator, producing a vibrato effect. An example of a + GM instrument that makes use of LFO1 to Pitch is + instrument number 57, Trumpet. + + LFO2 to Pitch (Vibrato) + The LFO1 in the EMU8000 can simultaneously modulate + pitch, volume and filter. LFO2, on the other hand, + modulates only the pitch, with the depth of modulation + determined by LFO2 to Pitch. LFO2 to Pitch produces a + periodic fluctuation in the pitch of the oscillator, + producing a vibrato effect. When this is coupled with + LFO1 to Pitch, a complex vibrato effect can be achieved. + + Volume Envelope + The character of a musical instrument is largely + determined by its volume envelope, the way in which the + level of the sound changes with time. For example, + percussive sounds usually start suddenly and then die + away, whereas a bowed sound might take quite some time to + start and then sustain at a more or less fixed level. + + A six-stage envelope makes up the volume envelope of the + EMU8000. The six stages are delay, attack, hold, decay, + sustain and release. The stages can be described as + follows: + + Delay The time between when a key is played and when + the attack phase begins + Attack The time it takes to go from zero to the peak + (full) level. + Hold The time the envelope will stay at the peak + level before starting the decay phase. + Decay The time it takes the envelope to go from the + peak level to the sustain level. + Sustain The level at which the envelope remains as long + as a key is held down. + Release The time it takes the envelope to fall to the + zero level after the key is released. + + Using these six parameters can yield very realistic + reproduction of the volume envelope characteristics of + many musical instruments. + + Pitch and Filter Envelope + The pitch and filter envelope is similar to the volume + envelope in that it has the same envelope stages. The + difference between them is that whereas the volume + envelope contours the volume of the instrument over time, + the pitch and filter envelope contours the pitch and + filter values of the instrument over time. The pitch + envelope is particularly useful in putting the finishing + touches in simulating a natural instrument. For example, + some wind instruments tend to go slightly sharp when they + are first blown, and this characteristic can be simulated + by setting up a pitch envelope with a fairly fast attack + and decay. The filter envelope, on the other hand, is + useful in creating synthetic sci-fi sound textures. An + example of a GM instrument that makes use of the filter + envelope is instrument number 86, Pad 8 (Sweep). + + Pitch/Filter Envelope Modulation + These two parameters determine the modulation depth of + the pitch and filter envelope. In the wind instrument + example above, a small amount of pitch envelope + modulation is desirable to simulate its natural pitch + characteristics. + + This rich modulation capability of the EMU8000 is fully + exploited by the SB AWE32 MIDI drivers. The driver also + provides you with a means to change these parameters over + MIDI in real time. Refer to the section "How do I change an + instrument's sound parameter in real time" for more + information. + + + + + Room 1 - 3 + This group of reverb variation simulates the natural + ambiance of a room. Room 1 simulates a small room, Room 2 + simulates a slightly bigger room, and Room 3 simulates a + big room. + + Hall 1 - 2 + This group of reverb variation simulates the natural + ambiance of a concert hall. It has greater depth than the + room variations. Again, Hall 1 simulates a small hall, + and Hall 2 simulates a larger hall. + + Plate + Back in the old days, reverb effects were sometimes + produced using a metal plate, and this type of reverb + produces a metallic echo. The SB AWE32's Plate variation + simulates this form of reverb. + + Delay + This reverb produces a delay, that is, echo effect. + + Panning Delay + This reverb variation produces a delay effect that is + continuously panned left and right. + + Chorus 1 - 4 + Chorus produces a "beating" effect. The chorus effects + are more prominent going from chorus 1 to chorus 4. + + Feedback Chorus + This chorus variation simulates a soft "swishing" effect. + + Flanger + This chorus variation produces a more prominent feedback + chorus effect. + + Short Delay + This chorus variation simulates a delay repeated in a + short time. + + Short Delay (feed back) + This chorus variation simulates a short delay repeated + (feedback) many times. + + + +Registers to write the Chorus Parameters to (all are 16-bit, unless noted): +(codified as in register,port,voice. port 0=0x620, 2=0x622, 4=0xA20, 6=0xA22, 8=0xE20) +( 3409 = register 3, port A20, voice 9) + +0x3409 +0x340C +0x3603 +0x1409 (32-Bit) +0x140A (32-Bit) +then write 0x8000 to 0x140D (32-Bit) +and then 0x0000 to 0x140E (32-Bit) + +Chorus Parameters: + +Chorus 1 Chorus 2 Chorus 3 Chorus 4 Feedback Flanger + +0xE600 0xE608 0xE610 0xE620 0xE680 0xE6E0 +0x03F6 0x031A 0x031A 0x0269 0x04D3 0x044E +0xBC2C 0xBC6E 0xBC84 0xBC6E 0xBCA6 0xBC37 +0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 +0x006D 0x017C 0x0083 0x017C 0x005B 0x0026 + +Short Delay Short Delay + Feedback + +0xE600 0xE6C0 +0x0B06 0x0B06 +0xBC00 0xBC00 +0xE000 0xE000 +0x0083 0x0083 + +// Chorus Params +typedef struct { + WORD FbkLevel; // Feedback Level (0xE600-0xE6FF) + WORD Delay; // Delay (0-0x0DA3) [1/44100 sec] + WORD LfoDepth; // LFO Depth (0xBC00-0xBCFF) + DWORD DelayR; // Right Delay (0-0xFFFFFFFF) [1/256/44100 sec] + DWORD LfoFreq; // LFO Frequency (0-0xFFFFFFFF) + } CHORUS_TYPE; + + +Registers to write the Reverb Parameters to (they are all 16-bit): +(codified as in register,port,voice. port 0=0x620, 2=0x622, 4=0xA20, 6=0xA22, 8=0xE20) +( 3409 = register 3, port A20, voice 9) + +0x2403,0x2405,0x361F,0x2407,0x2614,0x2616,0x240F,0x2417, +0x241F,0x2607,0x260F,0x2617,0x261D,0x261F,0x3401,0x3403, +0x2409,0x240B,0x2411,0x2413,0x2419,0x241B,0x2601,0x2603, +0x2609,0x260B,0x2611,0x2613 + +Reverb Parameters: + +Room 1: + +0xB488,0xA450,0x9550,0x84B5,0x383A,0x3EB5,0x72F4,0x72A4, +0x7254,0x7204,0x7204,0x7204,0x4416,0x4516,0xA490,0xA590, +0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529, +0x8428,0x8528,0x8428,0x8528 + +Room 2: + +0xB488,0xA458,0x9558,0x84B5,0x383A,0x3EB5,0x7284,0x7254, +0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540, +0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529, +0x8428,0x8528,0x8428,0x8528 + +Room 3: + +0xB488,0xA460,0x9560,0x84B5,0x383A,0x3EB5,0x7284,0x7254, +0x7224,0x7224,0x7254,0x7284,0x4416,0x4516,0xA490,0xA590, +0x842C,0x852C,0x842C,0x852C,0x842B,0x852B,0x842B,0x852B, +0x842A,0x852A,0x842A,0x852A + +Hall 1: + +0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7284,0x7254, +0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540, +0x842B,0x852B,0x842B,0x852B,0x842A,0x852A,0x842A,0x852A, +0x8429,0x8529,0x8429,0x8529 + +Hall 2: + +0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7254,0x7234, +0x7224,0x7254,0x7264,0x7294,0x44C3,0x45C3,0xA404,0xA504, +0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529, +0x8428,0x8528,0x8428,0x8528 + +Plate: + +0xB4FF,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7234,0x7234, +0x7234,0x7234,0x7234,0x7234,0x4448,0x4548,0xA440,0xA540, +0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529, +0x8428,0x8528,0x8428,0x8528 + +Delay: + +0xB4FF,0xA470,0x9500,0x84B5,0x333A,0x39B5,0x7204,0x7204, +0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,0xA4FF,0xA5FF, +0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520, +0x8420,0x8520,0x8420,0x8520 + +Panning Delay: + +0xB4FF,0xA490,0x9590,0x8474,0x333A,0x39B5,0x7204,0x7204, +0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,0xA4FF,0xA5FF, +0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520, +0x8420,0x8520,0x8420,0x8520 + +Registers to write the EQ Parameters to (16-Bit): +(codified as in register,port,voice. port 0=0x620, 2=0x622, 4=0xA20, 6=0xA22, 8=0xE20) +( 3409 = register 3, port A20, voice 9) + +Bass: + +0x3601 +0x3611 + +Treble: + +0x3411 +0x3413 +0x341B +0x3607 +0x360B +0x360D +0x3617 +0x3619 + +Total: + +write the 0x0263 + 3rd parameter of the Bass EQ + 9th parameter of Treble EQ to 0x3615. +write the 0x8363 + 3rd parameter of the Bass EQ + 9th parameter of Treble EQ to 0x3615. + + +Bass Parameters: + +0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: + +0xD26A 0xD25B 0xD24C 0xD23D 0xD21F 0xC208 0xC219 0xC22A 0xC24C 0xC26E 0xC248 0xC26A +0xD36A 0xD35B 0xD34C 0xD33D 0xC31F 0xC308 0xC308 0xC32A 0xC34C 0xC36E 0xC384 0xC36A +0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 + +Treble Parameters: + +0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: +0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821D 0x821C +0xC26A 0xC25B 0xC24C 0xC23D 0xC21F 0xD208 0xD208 0xD208 0xD208 0xD208 0xD219 0xD22A +0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031D 0x031C +0xC36A 0xC35B 0xC34C 0xC33D 0xC31F 0xD308 0xD308 0xD308 0xD308 0xD308 0xD319 0xD32A +0x021E 0x021E 0x021E 0x021E 0x021E 0x021E 0x021D 0x021C 0x021A 0x0219 0x0219 0x0219 +0xD208 0xD208 0xD208 0xD208 0xD208 0xD208 0xD219 0xD22A 0xD24C 0xD26E 0xD26E 0xD26E +0x831E 0x831E 0x831E 0x831E 0x831E 0x831E 0x831D 0x831C 0x831A 0x8319 0x8319 0x8319 +0xD308 0xD308 0xD308 0xD308 0xD308 0xD308 0xD3019 0xD32A 0xD34C 0xD36E 0xD36E 0xD36E +0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 +*/ diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 837f3bfc1..860c93e77 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1,6 +1,8 @@ #include -#include +#include #include +#include +#include #include "../ibm.h" #include "../io.h" #include "../pic.h" @@ -42,13 +44,13 @@ typedef struct gus_t int16_t buffer[2][SOUNDBUFLEN]; int pos; - int samp_timer, samp_latch; + int64_t samp_timer, samp_latch; uint8_t *ram; int irqnext; - int timer_1, timer_2; + int64_t timer_1, timer_2; int irq, dma, irq_midi; int latch_enable; @@ -740,7 +742,7 @@ void gus_poll_timer_1(void *p) { gus_t *gus = (gus_t *)p; - gus->timer_1 += (TIMER_USEC * 80); + gus->timer_1 += (TIMER_USEC * 80LL); if (gus->t1on) { gus->t1++; @@ -771,7 +773,7 @@ void gus_poll_timer_2(void *p) { gus_t *gus = (gus_t *)p; - gus->timer_2 += (TIMER_USEC * 320); + gus->timer_2 += (TIMER_USEC * 320LL); if (gus->t2on) { gus->t2++; @@ -993,7 +995,7 @@ static void gus_get_buffer(int32_t *buffer, int len, void *p) } -void *gus_init() +void *gus_init(device_t *info) { int c; double out = 1.0; @@ -1020,7 +1022,7 @@ void *gus_init() printf("Top volume %f %f %f %f\n",vol16bit[4095],vol16bit[3800],vol16bit[3000],vol16bit[2048]); gus->voices=14; - gus->samp_timer = gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / 44100.0)); + gus->samp_timer = gus->samp_latch = (int64_t)(TIMER_USEC * (1000000.0 / 44100.0)); gus->t1l = gus->t2l = 0xff; @@ -1058,11 +1060,8 @@ void gus_speed_changed(void *p) device_t gus_device = { "Gravis UltraSound", - 0, - gus_init, - gus_close, - NULL, - gus_speed_changed, - NULL, + 0, 0, + gus_init, gus_close, NULL, NULL, + gus_speed_changed, NULL, NULL, NULL }; diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index de34fc5f2..ed424250d 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -1,11 +1,15 @@ +#include +#include +#include #include +#include #include "../ibm.h" #include "../cpu/cpu.h" -#include "filters.h" #include "../lpt.h" -#include "snd_lpt_dac.h" -#include "sound.h" #include "../timer.h" +#include "sound.h" +#include "filters.h" +#include "snd_lpt_dac.h" typedef struct lpt_dac_t { diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index 245d45548..8dfb1ddab 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -1,11 +1,15 @@ +#include +#include +#include #include +#include #include "../ibm.h" #include "../cpu/cpu.h" -#include "filters.h" -#include "../lpt.h" -#include "snd_lpt_dss.h" -#include "sound.h" #include "../timer.h" +#include "../lpt.h" +#include "sound.h" +#include "filters.h" +#include "snd_lpt_dss.h" typedef struct dss_t { @@ -14,7 +18,7 @@ typedef struct dss_t uint8_t dac_val; - int time; + int64_t time; int16_t buffer[SOUNDBUFLEN]; int pos; @@ -84,7 +88,7 @@ static void dss_callback(void *p) dss->read_idx++; } - dss->time += (TIMER_USEC * (1000000.0 / 7000.0)); + dss->time += (int64_t) (TIMER_USEC * (1000000.0 / 7000.0)); } static void *dss_init() diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 61e2890f7..3506764e3 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -8,29 +8,31 @@ * * Roland MPU-401 emulation. * - * Version: @(#)sound_mpu401.c 1.0.1 2017/06/19 + * Version: @(#)snd_mpu401.c 1.0.3 2017/10/04 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * DOSBox Team, * Miran Grca, * TheCollector1995, * Copyright 2008-2017 Sarah Walker. * Copyright 2008-2017 DOSBox Team. - * Copyright 2016-2017 Miran Grca. - * Copyright 2016-2017 TheCollector1995. + * Copyright 2016,2017 Miran Grca. */ - +#include +#include +#include +#include +#include +#include #include "../ibm.h" #include "../device.h" #include "../io.h" #include "../pic.h" #include "../timer.h" -#include "midi.h" #include "sound.h" #include "snd_mpu401.h" +#include "midi.h" -#include -#include enum { @@ -43,9 +45,9 @@ static void MPU401_EOIHandlerDispatch(void *p); int mpu401_standalone_enable = 0; -static int mpu401_event_callback = 0; -static int mpu401_eoi_callback = 0; -static int mpu401_reset_callback = 0; +static int64_t mpu401_event_callback = 0LL; +static int64_t mpu401_eoi_callback = 0LL; +static int64_t mpu401_reset_callback = 0LL; #ifdef ENABLE_MPU401_LOG static int mpu401_do_log = 1; @@ -149,7 +151,7 @@ static void MPU401_ResetDone(void *p) pclog("MPU-401 reset callback\n"); - mpu401_reset_callback = 0; + mpu401_reset_callback = 0LL; mpu->state.reset=0; if (mpu->state.cmd_pending) @@ -182,7 +184,7 @@ static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val) { case 0x4: /* Stop */ mpu->state.playing=0; - mpu401_event_callback = 0; + mpu401_event_callback = 0LL; for (i=0xb0;i<0xbf;i++) { /* All notes off */ midi_write(i); @@ -193,7 +195,7 @@ static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val) case 0x8: /* Play */ // LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Intelligent mode playback started"); mpu->state.playing=1; - mpu401_event_callback = (MPU401_TIMECONSTANT / (mpu->clock.tempo*mpu->clock.timebase)) * 1000 * TIMER_USEC; + mpu401_event_callback = (MPU401_TIMECONSTANT / (mpu->clock.tempo*mpu->clock.timebase)) * 1000LL * TIMER_USEC; ClrQueue(mpu); break; } @@ -298,7 +300,7 @@ static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; case 0xff: /* Reset MPU-401 */ pclog("MPU-401:Reset %X\n",val); - mpu401_reset_callback = MPU401_RESETBUSY * 33 * TIMER_USEC; + mpu401_reset_callback = MPU401_RESETBUSY * 33LL * TIMER_USEC; mpu->state.reset=1; MPU401_Reset(mpu); #if 0 @@ -563,7 +565,7 @@ static void MPU401_EOIHandler(void *p) pclog("MPU-401 end of input callback\n"); - mpu401_eoi_callback = 0; + mpu401_eoi_callback = 0LL; mpu->state.eoi_scheduled=0; if (mpu->state.send_now) { @@ -590,7 +592,7 @@ static void MPU401_EOIHandlerDispatch(void *p) if (mpu->state.send_now) { mpu->state.eoi_scheduled=1; - mpu401_eoi_callback = 60 * TIMER_USEC; /* Possible a bit longer */ + mpu401_eoi_callback = 60LL * TIMER_USEC; /* Possible a bit longer */ } else if (!mpu->state.eoi_scheduled) MPU401_EOIHandler(mpu); @@ -696,7 +698,7 @@ static void MPU401_Event(void *p) if (mpu->mode==M_UART) { - mpu401_event_callback = 0; + mpu401_event_callback = 0LL; return; } if (mpu->state.irq_pending) goto next_event; @@ -719,16 +721,16 @@ static void MPU401_Event(void *p) } if (!mpu->state.irq_pending && mpu->state.req_mask) MPU401_EOIHandler(mpu); next_event: - /* mpu401_event_callback = 0; */ + /* mpu401_event_callback = 0LL; */ new_time = (mpu->clock.tempo * mpu->clock.timebase); if (new_time == 0) { - mpu401_event_callback = 0; + mpu401_event_callback = 0LL; return; } else { - mpu401_event_callback += (MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC; + mpu401_event_callback += (MPU401_TIMECONSTANT/new_time) * 1000LL * TIMER_USEC; pclog("Next event after %i us (time constant: %i)\n", (int) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); } } @@ -752,9 +754,9 @@ void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0; pclog("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART"); - mpu401_event_callback = 0; - mpu401_eoi_callback = 0; - mpu401_reset_callback = 0; + mpu401_event_callback = 0LL; + mpu401_eoi_callback = 0LL; + mpu401_reset_callback = 0LL; io_sethandler(addr, 0x0002, mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); io_sethandler(0x2A20, 0x0010, NULL, NULL, NULL, imf_write, NULL, NULL, mpu); @@ -786,7 +788,7 @@ void mpu401_device_add(void) device_add(&mpu401_device); } -void *mpu401_standalone_init() +void *mpu401_standalone_init(device_t *info) { mpu_t *mpu; @@ -870,11 +872,10 @@ static device_config_t mpu401_standalone_config[] = device_t mpu401_device = { "MPU-401 (Standalone)", - 0, + 0, 0, mpu401_standalone_init, mpu401_standalone_close, - NULL, - NULL, + NULL, NULL, NULL, NULL, NULL, mpu401_standalone_config diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index c5ccc6070..990769d58 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -1,8 +1,11 @@ /* Copyright holders: Sarah Walker, SA1988 see COPYING for more details */ +#include #include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../timer.h" @@ -11,7 +14,7 @@ #include "snd_dbopl.h" -/*Interfaces between PCem and the actual OPL emulator*/ +/*Interfaces between 86Box and the actual OPL emulator*/ uint8_t opl2_read(uint16_t a, void *priv) @@ -111,7 +114,7 @@ void ym3812_timer_set_0(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[0][timer] = period * TIMER_USEC * 20; + opl->timers[0][timer] = period * TIMER_USEC * 20LL; if (!opl->timers[0][timer]) opl->timers[0][timer] = 1; opl->timers_enable[0][timer] = period ? 1 : 0; } @@ -119,7 +122,7 @@ void ym3812_timer_set_1(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[1][timer] = period * TIMER_USEC * 20; + opl->timers[1][timer] = period * TIMER_USEC * 20LL; if (!opl->timers[1][timer]) opl->timers[1][timer] = 1; opl->timers_enable[1][timer] = period ? 1 : 0; } @@ -128,7 +131,7 @@ void ymf262_timer_set(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[0][timer] = period * TIMER_USEC * 20; + opl->timers[0][timer] = period * TIMER_USEC * 20LL; if (!opl->timers[0][timer]) opl->timers[0][timer] = 1; opl->timers_enable[0][timer] = period ? 1 : 0; } diff --git a/src/sound/snd_opl.h b/src/sound/snd_opl.h index 14df05b9d..e99f716f9 100644 --- a/src/sound/snd_opl.h +++ b/src/sound/snd_opl.h @@ -5,8 +5,8 @@ typedef struct opl_t { int chip_nr[2]; - int timers[2][2]; - int timers_enable[2][2]; + int64_t timers[2][2]; + int64_t timers_enable[2][2]; int16_t filtbuf[2]; diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index e91b7a09a..bb7ab98cc 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -1,4 +1,8 @@ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../pic.h" @@ -7,10 +11,10 @@ #include "../timer.h" #include "../device.h" #include "sound.h" +#include "filters.h" #include "snd_opl.h" #include "snd_pas16.h" #include "snd_sb_dsp.h" -#include "filters.h" /* Original PAS uses @@ -118,7 +122,7 @@ typedef struct pas16_t struct { uint32_t l[3]; - int c[3]; + int64_t c[3]; uint8_t m[3]; uint8_t ctrl, ctrls[2]; int wp, rm[3], wm[3]; @@ -126,7 +130,7 @@ typedef struct pas16_t int thit[3]; int delay[3]; int rereadlatch[3]; - int enable[3]; + int64_t enable[3]; } pit; opl_t opl; @@ -714,7 +718,8 @@ void pas16_get_buffer(int32_t *buffer, int len, void *p) pas16->dsp.pos = 0; } -void *pas16_init() + +static void *pas16_init(device_t *info) { pas16_t *pas16 = malloc(sizeof(pas16_t)); memset(pas16, 0, sizeof(pas16_t)); @@ -731,7 +736,7 @@ void *pas16_init() return pas16; } -void pas16_close(void *p) +static void pas16_close(void *p) { pas16_t *pas16 = (pas16_t *)p; @@ -741,11 +746,9 @@ void pas16_close(void *p) device_t pas16_device = { "Pro Audio Spectrum 16", - DEVICE_NOT_WORKING, - pas16_init, - pas16_close, - NULL, - NULL, - NULL, - NULL + DEVICE_ISA | DEVICE_NOT_WORKING, + 0, + pas16_init, pas16_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; diff --git a/src/sound/snd_ps1.c b/src/sound/snd_ps1.c index 85334101a..60a836995 100644 --- a/src/sound/snd_ps1.c +++ b/src/sound/snd_ps1.c @@ -1,4 +1,8 @@ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../pic.h" @@ -15,7 +19,7 @@ typedef struct ps1_audio_t uint8_t status, ctrl; - int timer_latch, timer_count, timer_enable; + int64_t timer_latch, timer_count, timer_enable; uint8_t fifo[2048]; int fifo_read_idx, fifo_write_idx; @@ -85,7 +89,7 @@ static void ps1_audio_write(uint16_t port, uint8_t val, void *p) break; case 3: /*Timer reload value*/ ps1->timer_latch = val; - ps1->timer_count = (0xff-val) * TIMER_USEC; + ps1->timer_count = (int64_t) ((0xff-val) * TIMER_USEC); ps1->timer_enable = (val != 0); break; case 4: /*Almost empty*/ @@ -134,7 +138,7 @@ static void ps1_audio_get_buffer(int32_t *buffer, int len, void *p) ps1->pos = 0; } -static void *ps1_audio_init() +static void *ps1_audio_init(device_t *info) { ps1_audio_t *ps1 = malloc(sizeof(ps1_audio_t)); memset(ps1, 0, sizeof(ps1_audio_t)); @@ -159,9 +163,10 @@ static void ps1_audio_close(void *p) device_t ps1_audio_device = { "PS/1 Audio Card", - 0, + 0, 0, ps1_audio_init, ps1_audio_close, + NULL, NULL, NULL, NULL, diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index dc52aee46..395717350 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -1,4 +1,8 @@ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../dma.h" @@ -21,8 +25,8 @@ typedef struct pssj_t int amplitude; int irq; - int timer_count; - int enable; + int64_t timer_count; + int64_t enable; int wave_pos; int pulse_width; @@ -164,7 +168,7 @@ static void pssj_callback(void *p) pssj->wave_pos = (pssj->wave_pos + 1) & 31; } - pssj->timer_count += (int)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400)); + pssj->timer_count += (int64_t)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400)); } static void pssj_get_buffer(int32_t *buffer, int len, void *p) @@ -180,7 +184,7 @@ static void pssj_get_buffer(int32_t *buffer, int len, void *p) pssj->pos = 0; } -void *pssj_init() +void *pssj_init(device_t *info) { pssj_t *pssj = malloc(sizeof(pssj_t)); memset(pssj, 0, sizeof(pssj_t)); @@ -204,9 +208,10 @@ void pssj_close(void *p) device_t pssj_device = { "Tandy PSSJ", - 0, + 0, 0, pssj_init, pssj_close, + NULL, NULL, NULL, NULL, diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 5e38a22ce..8a43f1f3d 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -8,17 +8,19 @@ * * Sound Blaster emulation. * - * Version: @(#)sound_sb.c 1.0.0 2017/05/30 + * Version: @(#)sound_sb.c 1.0.2 2017/10/04 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. - * Copyright 2016-2017 TheCollector1995. + * Copyright 2016,2017 Miran Grca. */ - +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mca.h" @@ -26,42 +28,117 @@ #include "../rom.h" #include "../device.h" #include "sound.h" +#include "filters.h" #include "snd_dbopl.h" #include "snd_emu8k.h" #include "snd_mpu401.h" #include "snd_opl.h" #include "snd_sb.h" #include "snd_sb_dsp.h" -#include "filters.h" + +//#define SB_DSP_RECORD_DEBUG + +#ifdef SB_DSP_RECORD_DEBUG +FILE* soundfsb = 0/*NULL*/; +FILE* soundfsbin = 0/*NULL*/; +#endif -typedef struct sb_mixer_t + +/* SB 2.0 CD version */ +typedef struct sb_ct1335_mixer_t { - int master_l, master_r; - int voice_l, voice_r; - int fm_l, fm_r; - int cd_l, cd_r; + int32_t master; + int32_t voice; + int32_t fm; + int32_t cd; + + uint8_t index; + uint8_t regs[256]; +} sb_ct1335_mixer_t; +/* SB PRO */ +typedef struct sb_ct1345_mixer_t +{ + int32_t master_l, master_r; + int32_t voice_l, voice_r; + int32_t fm_l, fm_r; + int32_t cd_l, cd_r; + int32_t line_l, line_r; + int32_t mic; + /*see sb_ct1745_mixer for values for input selector*/ + int32_t input_selector; + + int input_filter; + int in_filter_freq; + int output_filter; + + int stereo; + int stereo_isleft; + + uint8_t index; + uint8_t regs[256]; + +} sb_ct1345_mixer_t; +/* SB16 and AWE32 */ +typedef struct sb_ct1745_mixer_t +{ + int32_t master_l, master_r; + int32_t voice_l, voice_r; + int32_t fm_l, fm_r; + int32_t cd_l, cd_r; + int32_t line_l, line_r; + int32_t mic; + int32_t speaker; + int bass_l, bass_r; int treble_l, treble_r; - int filter; + + int output_selector; + #define OUTPUT_MIC 1 + #define OUTPUT_CD_R 2 + #define OUTPUT_CD_L 4 + #define OUTPUT_LINE_R 8 + #define OUTPUT_LINE_L 16 - int index; + int input_selector_left; + int input_selector_right; + #define INPUT_MIC 1 + #define INPUT_CD_R 2 + #define INPUT_CD_L 4 + #define INPUT_LINE_R 8 + #define INPUT_LINE_L 16 + #define INPUT_MIDI_R 32 + #define INPUT_MIDI_L 64 + + int mic_agc; + + int32_t input_gain_L; + int32_t input_gain_R; + int32_t output_gain_L; + int32_t output_gain_R; + + uint8_t index; uint8_t regs[256]; -} sb_mixer_t; +} sb_ct1745_mixer_t; typedef struct sb_t { opl_t opl; sb_dsp_t dsp; - sb_mixer_t mixer; - mpu_t mpu; + union { + sb_ct1335_mixer_t mixer_sb2; + sb_ct1345_mixer_t mixer_sbpro; + sb_ct1745_mixer_t mixer_sb16; + }; + mpu_t mpu; emu8k_t emu8k; int pos; - + uint8_t pos_regs[8]; + + int opl_emu; } sb_t; - /* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps. Note that for positive dB values, this is not amplitude, it is amplitude-1. */ const float sb_bass_treble_4bits[]= { @@ -69,17 +146,27 @@ const float sb_bass_treble_4bits[]= { 0, 0.25892541, 0.584893192, 1, 1.511886431, 2.16227766, 3, 4.011872336 }; -static int sb_att[]= +/* Attenuation tables for the mixer. Max volume = 32767 in order to give 6dB of + * headroom and avoid integer overflow */ +const int32_t sb_att_2dbstep_5bits[]= { - 50,65,82,103,130,164,207,260,328,413,520,655,825,1038,1307, - 1645,2072,2608,3283,4134,5205,6553,8250,10385,13075,16461,20724,26089, - 32845,41349,52055,65535 + 25,32,41,51,65,82,103,130,164,206,260,327,412,519,653, + 822,1036,1304,1641,2067,2602,3276,4125,5192,6537,8230,10362,13044, + 16422,20674,26027,32767 +}; +const int32_t sb_att_4dbstep_3bits[]= +{ + 164,2067,3276,5193,8230,13045,20675,32767 +}; +const int32_t sb_att_7dbstep_2bits[]= +{ + 164,6537,14637,32767 }; -static void sb_get_buffer_opl2(int32_t *buffer, int len, void *p) +/* sb 1, 1.5, 2, 2 mvc do not have a mixer, so signal is hardwired */ +static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p) { sb_t *sb = (sb_t *)p; - sb_mixer_t *mixer = &sb->mixer; int c; @@ -87,40 +174,13 @@ static void sb_get_buffer_opl2(int32_t *buffer, int len, void *p) sb_dsp_update(&sb->dsp); for (c = 0; c < len * 2; c += 2) { - int32_t out_l, out_r; - - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * 51000) >> 16); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * 51000) >> 16); - - if (sb->mixer.filter) - { - out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16; - out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16; - } - else - { - out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16; - out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16; - } - - out_l = (out_l * mixer->master_l) >> 15; - out_r = (out_r * mixer->master_r) >> 15; - - if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8) - { - /* This is not exactly how one does bass/treble controls, but the end result is like it. A better implementation would reduce the cpu usage */ - if (mixer->bass_l>8) out_l += (int32_t)(low_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->bass_l]); - if (mixer->bass_r>8) out_r += (int32_t)(low_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->bass_r]); - if (mixer->treble_l>8) out_l += (int32_t)(high_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->treble_l]); - if (mixer->treble_r>8) out_r += (int32_t)(high_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->treble_r]); - if (mixer->bass_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->bass_l] + low_cut_iir(0, (float)out_l)*(1.0-sb_bass_treble_4bits[mixer->bass_l])); - if (mixer->bass_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->bass_r] + low_cut_iir(1, (float)out_r)*(1.0-sb_bass_treble_4bits[mixer->bass_r])); - if (mixer->treble_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->treble_l] + high_cut_iir(0, (float)out_l)*(1.0-sb_bass_treble_4bits[mixer->treble_l])); - if (mixer->treble_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->treble_r] + high_cut_iir(1, (float)out_r)*(1.0-sb_bass_treble_4bits[mixer->treble_r])); - } - - buffer[c] += out_l; - buffer[c + 1] += out_r; + int32_t out; + out = ((sb->opl.buffer[c] * 51000) >> 16); + //TODO: Recording: Mic and line In with AGC + out += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * 65536) / 3) >> 16; + + buffer[c] += out; + buffer[c + 1] += out; } sb->pos = 0; @@ -128,49 +188,71 @@ static void sb_get_buffer_opl2(int32_t *buffer, int len, void *p) sb->dsp.pos = 0; } -static void sb_get_buffer_opl3(int32_t *buffer, int len, void *p) +static void sb_get_buffer_sb2_mixer(int32_t *buffer, int len, void *p) { sb_t *sb = (sb_t *)p; - sb_mixer_t *mixer = &sb->mixer; + sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; int c; - opl3_update2(&sb->opl); + opl2_update2(&sb->opl); + sb_dsp_update(&sb->dsp); + for (c = 0; c < len * 2; c += 2) + { + int32_t out; + + out = ((((sb->opl.buffer[c] * mixer->fm) >> 16) * 51000) >> 15); + /* TODO: Recording : I assume it has direct mic and line in like sb2 */ + /* It is unclear from the docs if it has a filter, but it probably does */ + out += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice) / 3) >> 15; + + out = (out * mixer->master) >> 15; + + buffer[c] += out; + buffer[c + 1] += out; + } + + sb->pos = 0; + sb->opl.pos = 0; + sb->dsp.pos = 0; +} + +static void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + + int c; + + if (sb->dsp.sb_type == SBPRO) + opl2_update2(&sb->opl); + else + opl3_update2(&sb->opl); + sb_dsp_update(&sb->dsp); for (c = 0; c < len * 2; c += 2) { int32_t out_l, out_r; - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * (opl3_type ? 47000 : 51000)) >> 16); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * (opl3_type ? 47000 : 51000)) >> 16); - - if (sb->mixer.filter) + out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); + out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); + + /*TODO: Implement the stereo switch on the mixer instead of on the dsp? */ + if (mixer->output_filter) { - out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16; - out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16; + out_l += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 15; + out_r += (int32_t)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 15; } else { - out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16; - out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16; + out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 15; + out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 15; } + //TODO: recording CD, Mic with AGC or line in. Note: mic volume does not affect recording. out_l = (out_l * mixer->master_l) >> 15; out_r = (out_r * mixer->master_r) >> 15; - if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8) - { - /* This is not exactly how one does bass/treble controls, but the end result is like it. A better implementation would reduce the cpu usage */ - if (mixer->bass_l>8) out_l += (int32_t)(low_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->bass_l]); - if (mixer->bass_r>8) out_r += (int32_t)(low_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->bass_r]); - if (mixer->treble_l>8) out_l += (int32_t)(high_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->treble_l]); - if (mixer->treble_r>8) out_r += (int32_t)(high_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->treble_r]); - if (mixer->bass_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->bass_l] + low_cut_iir(0, (float)out_l)*(1.0-sb_bass_treble_4bits[mixer->bass_l])); - if (mixer->bass_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->bass_r] + low_cut_iir(1, (float)out_r)*(1.0-sb_bass_treble_4bits[mixer->bass_r])); - if (mixer->treble_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->treble_l] + high_cut_iir(0, (float)out_l)*(1.0-sb_bass_treble_4bits[mixer->treble_l])); - if (mixer->treble_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->treble_r] + high_cut_iir(1, (float)out_r)*(1.0-sb_bass_treble_4bits[mixer->treble_r])); - } - buffer[c] += out_l; buffer[c + 1] += out_r; } @@ -178,41 +260,114 @@ static void sb_get_buffer_opl3(int32_t *buffer, int len, void *p) sb->pos = 0; sb->opl.pos = 0; sb->dsp.pos = 0; - sb->emu8k.pos = 0; } +static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + + int c; + + opl3_update2(&sb->opl); + sb_dsp_update(&sb->dsp); + const int dsp_rec_pos = sb->dsp.record_pos_write; + for (c = 0; c < len * 2; c += 2) + { + int32_t out_l, out_r, in_l, in_r; + + out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); + out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); + + /*TODO: multi-recording mic with agc/+20db, cd and line in with channel inversion */ + in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0; + in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0; + + /*TODO: CT1745 features dynamic filtering. https://www.vogons.org/viewtopic.php?f=62&t=51514 */ + out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 15; + out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 15; + + out_l = (out_l * mixer->master_l) >> 15; + out_r = (out_r * mixer->master_r) >> 15; + + if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8) + { + /* This is not exactly how one does bass/treble controls, but the end result is like it. A better implementation would reduce the cpu usage */ + if (mixer->bass_l>8) out_l += (int32_t)(low_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->bass_l]); + if (mixer->bass_r>8) out_r += (int32_t)(low_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->bass_r]); + if (mixer->treble_l>8) out_l += (int32_t)(high_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->treble_l]); + if (mixer->treble_r>8) out_r += (int32_t)(high_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->treble_r]); + if (mixer->bass_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->bass_l] + low_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->bass_l])); + if (mixer->bass_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->bass_r] + low_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->bass_r])); + if (mixer->treble_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->treble_l] + high_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->treble_l])); + if (mixer->treble_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->treble_r] + high_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->treble_r])); + } + if (sb->dsp.sb_enable_i) + { + int c_record = dsp_rec_pos; + c_record +=(((c/2) * sb->dsp.sb_freq) / 48000)*2; + in_l <<= mixer->input_gain_L; + in_r <<= mixer->input_gain_R; + // Clip signal + if (in_l < -32768) + in_l = -32768; + else if (in_l > 32767) + in_l = 32767; + + if (in_r < -32768) + in_r = -32768; + else if (in_r > 32767) + in_r = 32767; + sb->dsp.record_buffer[c_record&0xFFFF] = in_l; + sb->dsp.record_buffer[(c_record+1)&0xFFFF] = in_r; + } + + buffer[c] += (out_l << mixer->output_gain_L); + buffer[c + 1] += (out_r << mixer->output_gain_R); + } + sb->dsp.record_pos_write+=((len * sb->dsp.sb_freq) / 48000)*2; + sb->dsp.record_pos_write&=0xFFFF; + + sb->pos = 0; + sb->opl.pos = 0; + sb->dsp.pos = 0; +} +#ifdef SB_DSP_RECORD_DEBUG +int old_dsp_rec_pos=0; +int buf_written=0; +int last_crecord=0; +#endif static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p) { sb_t *sb = (sb_t *)p; - sb_mixer_t *mixer = &sb->mixer; + sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; int c; opl3_update2(&sb->opl); - sb_dsp_update(&sb->dsp); emu8k_update(&sb->emu8k); + sb_dsp_update(&sb->dsp); + const int dsp_rec_pos = sb->dsp.record_pos_write; for (c = 0; c < len * 2; c += 2) { + int32_t out_l, out_r, in_l, in_r; int c_emu8k = (((c/2) * 44100) / 48000)*2; - int32_t out_l, out_r; - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * (opl3_type ? 47000 : 51000)) >> 16); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * (opl3_type ? 47000 : 51000)) >> 16); + out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 15) * (sb->opl_emu ? 47000 : 51000)) >> 16); + out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 15) * (sb->opl_emu ? 47000 : 51000)) >> 16); - out_l += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 16); - out_r += ((sb->emu8k.buffer[c_emu8k + 1] * mixer->fm_l) >> 16); - - if (sb->mixer.filter) - { - out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16; - out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16; - } - else - { - out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16; - out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16; - } + out_l += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 15); + out_r += ((sb->emu8k.buffer[c_emu8k + 1] * mixer->fm_r) >> 15); + /*TODO: multi-recording mic with agc/+20db, cd and line in with channel inversion */ + in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0; + in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0; + + + /*TODO: CT1745 features dynamic filtering. https://www.vogons.org/viewtopic.php?f=62&t=51514 */ + out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 15; + out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 15; + out_l = (out_l * mixer->master_l) >> 15; out_r = (out_r * mixer->master_r) >> 15; @@ -223,55 +378,240 @@ static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p) if (mixer->bass_r>8) out_r += (int32_t)(low_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->bass_r]); if (mixer->treble_l>8) out_l += (int32_t)(high_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->treble_l]); if (mixer->treble_r>8) out_r += (int32_t)(high_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->treble_r]); - if (mixer->bass_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->bass_l] + low_cut_iir(0, (float)out_l)*(1.0-sb_bass_treble_4bits[mixer->bass_l])); - if (mixer->bass_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->bass_r] + low_cut_iir(1, (float)out_r)*(1.0-sb_bass_treble_4bits[mixer->bass_r])); - if (mixer->treble_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->treble_l] + high_cut_iir(0, (float)out_l)*(1.0-sb_bass_treble_4bits[mixer->treble_l])); - if (mixer->treble_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->treble_r] + high_cut_iir(1, (float)out_r)*(1.0-sb_bass_treble_4bits[mixer->treble_r])); + if (mixer->bass_l<8) out_l = (int32_t)(out_l *sb_bass_treble_4bits[mixer->bass_l] + low_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->bass_l])); + if (mixer->bass_r<8) out_r = (int32_t)(out_r *sb_bass_treble_4bits[mixer->bass_r] + low_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->bass_r])); + if (mixer->treble_l<8) out_l = (int32_t)(out_l *sb_bass_treble_4bits[mixer->treble_l] + high_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->treble_l])); + if (mixer->treble_r<8) out_r = (int32_t)(out_r *sb_bass_treble_4bits[mixer->treble_r] + high_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->treble_r])); } - - buffer[c] += out_l; - buffer[c + 1] += out_r; - } + if (sb->dsp.sb_enable_i) + { +// in_l += (mixer->input_selector_left&INPUT_CD_L) ? audio_cd_buffer[cd_read_pos+c_emu8k] : 0 + (mixer->input_selector_left&INPUT_CD_R) ? audio_cd_buffer[cd_read_pos+c_emu8k+1] : 0; +// in_r += (mixer->input_selector_right&INPUT_CD_L) ? audio_cd_buffer[cd_read_pos+c_emu8k]: 0 + (mixer->input_selector_right&INPUT_CD_R) ? audio_cd_buffer[cd_read_pos+c_emu8k+1] : 0; + int c_record = dsp_rec_pos; + c_record +=(((c/2) * sb->dsp.sb_freq) / 48000)*2; + #ifdef SB_DSP_RECORD_DEBUG + if (c_record > 0xFFFF && !buf_written) + { + if (!soundfsb) soundfsb=plat_fopen(L"sound_sb.pcm",L"wb"); + fwrite(sb->dsp.record_buffer,2,0x10000,soundfsb); + old_dsp_rec_pos = dsp_rec_pos; + buf_written=1; + } + #endif + in_l <<= mixer->input_gain_L; + in_r <<= mixer->input_gain_R; + // Clip signal + if (in_l < -32768) + in_l = -32768; + else if (in_l > 32767) + in_l = 32767; + + if (in_r < -32768) + in_r = -32768; + else if (in_r > 32767) + in_r = 32767; + sb->dsp.record_buffer[c_record&0xFFFF] = in_l; + sb->dsp.record_buffer[(c_record+1)&0xFFFF] = in_r; + #ifdef SB_DSP_RECORD_DEBUG + if (c_record != last_crecord) + { + if (!soundfsbin) soundfsbin=plat_fopen(L"sound_sb_in.pcm",L"wb"); + fwrite(&sb->dsp.record_buffer[c_record&0xFFFF],2,2,soundfsbin); + last_crecord=c_record; + } + #endif + } + + buffer[c] += (out_l << mixer->output_gain_L); + buffer[c + 1] += (out_r << mixer->output_gain_R); + } + #ifdef SB_DSP_RECORD_DEBUG + if (old_dsp_rec_pos > dsp_rec_pos) + { + buf_written=0; + old_dsp_rec_pos=dsp_rec_pos; + } + #endif + + sb->dsp.record_pos_write+=((len * sb->dsp.sb_freq) / 48000)*2; + sb->dsp.record_pos_write&=0xFFFF; sb->pos = 0; sb->opl.pos = 0; sb->dsp.pos = 0; sb->emu8k.pos = 0; } -void sb_pro_mixer_write(uint16_t addr, uint8_t val, void *p) + +void sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *p) { sb_t *sb = (sb_t *)p; - sb_mixer_t *mixer = &sb->mixer; + sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; if (!(addr & 1)) - mixer->index = val & 0xff; + { + mixer->index = val; + mixer->regs[0x01] = val; + } else { - mixer->regs[mixer->index] = val; - - mixer->master_l = sb_att[(mixer->regs[0x22] >> 4) | 0x11]; - mixer->master_r = sb_att[(mixer->regs[0x22] & 0xf) | 0x11]; - mixer->voice_l = sb_att[(mixer->regs[0x04] >> 4) | 0x11]; - mixer->voice_r = sb_att[(mixer->regs[0x04] & 0xf) | 0x11]; - mixer->fm_l = sb_att[(mixer->regs[0x26] >> 4) | 0x11]; - mixer->fm_r = sb_att[(mixer->regs[0x26] & 0xf) | 0x11]; - mixer->cd_l = sb_att[(mixer->regs[0x28] >> 4) | 0x11]; - mixer->cd_r = sb_att[(mixer->regs[0x28] & 0xf) | 0x11]; - mixer->filter = !(mixer->regs[0xe] & 0x20); - mixer->bass_l = mixer->bass_r = 8; - mixer->treble_l = mixer->treble_r = 8; - sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 65535, - ((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 65535); - if (mixer->index == 0xe) - sb_dsp_set_stereo(&sb->dsp, val & 2); + if (mixer->index == 0) + { + /* Reset */ + mixer->regs[0x02] = 4 << 1; + mixer->regs[0x06] = 4 << 1; + mixer->regs[0x08] = 0 << 1; + /* changed default from -46dB to 0dB*/ + mixer->regs[0x0A] = 3 << 1; + } + else + { + mixer->regs[mixer->index] = val; + switch (mixer->index) + { + case 0x00: case 0x02: case 0x06: case 0x08: case 0x0A: + break; + + default: + pclog("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + } + mixer->master = sb_att_4dbstep_3bits[(mixer->regs[0x02] >> 1)&0x7]; + mixer->fm = sb_att_4dbstep_3bits[(mixer->regs[0x06] >> 1)&0x7]; + mixer->cd = sb_att_4dbstep_3bits[(mixer->regs[0x08] >> 1)&0x7]; + mixer->voice = sb_att_7dbstep_2bits[(mixer->regs[0x0A] >> 1)&0x3]; + + sound_set_cd_volume(((uint32_t)mixer->master * (uint32_t)mixer->cd) / 65535, + ((uint32_t)mixer->master * (uint32_t)mixer->cd) / 65535); } } -uint8_t sb_pro_mixer_read(uint16_t addr, void *p) +uint8_t sb_ct1335_mixer_read(uint16_t addr, void *p) { sb_t *sb = (sb_t *)p; - sb_mixer_t *mixer = &sb->mixer; + sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + + if (!(addr & 1)) + return mixer->index; + + switch (mixer->index) + { + case 0x00: case 0x02: case 0x06: case 0x08: case 0x0A: + return mixer->regs[mixer->index]; + default: + pclog("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + + return 0xff; +} + +void sb_ct1335_mixer_reset(sb_t* sb) +{ + sb_ct1335_mixer_write(0x254,0,sb); + sb_ct1335_mixer_write(0x255,0,sb); +} + +void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + + if (!(addr & 1)) + { + mixer->index = val; + mixer->regs[0x01] = val; + } + else + { + if (mixer->index == 0) + { + /* Reset */ + mixer->regs[0x0A] = 0 << 1; + mixer->regs[0x0C] = (0 << 5) | (0 << 3) | (0 << 1); + mixer->regs[0x0E] = (0 << 5) | (0 << 1); + /* changed default from -11dB to 0dB */ + mixer->regs[0x04] = (7 << 5) | (7 << 1); + mixer->regs[0x22] = (7 << 5) | (7 << 1); + mixer->regs[0x26] = (7 << 5) | (7 << 1); + mixer->regs[0x28] = (0 << 5) | (0 << 1); + mixer->regs[0x2E] = (0 << 5) | (0 << 1); + sb_dsp_set_stereo(&sb->dsp, mixer->regs[0x0E] & 2); + } + else + { + mixer->regs[mixer->index] = val; + switch (mixer->index) + { + /* Compatibility: chain registers 0x02 and 0x22 as well as 0x06 and 0x26 */ + case 0x02: case 0x06: + mixer->regs[mixer->index+0x20]=((val&0xE) << 4)|(val&0xE) << 4; + break; + + case 0x22: case 0x26: + mixer->regs[mixer->index-0x20]=(val&0xE); + break; + + /* More compatibility: SoundBlaster Pro selects register 020h for 030h, 022h for 032h, 026h for 036h,028h for 038h. */ + case 0x30: case 0x32: case 0x36: case 0x38: + mixer->regs[mixer->index-0x10]=(val&0xEE); + break; + + case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e: + case 0x28: case 0x2e: + break; + + + default: + pclog("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + } + + mixer->voice_l = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 5)&0x7]; + mixer->voice_r = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 1)&0x7]; + mixer->master_l = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 5)&0x7]; + mixer->master_r = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 1)&0x7]; + mixer->fm_l = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 5)&0x7]; + mixer->fm_r = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 1)&0x7]; + mixer->cd_l = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 5)&0x7]; + mixer->cd_r = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 1)&0x7]; + mixer->line_l = sb_att_4dbstep_3bits[(mixer->regs[0x2E] >> 5)&0x7]; + mixer->line_r = sb_att_4dbstep_3bits[(mixer->regs[0x2E] >> 1)&0x7]; + + mixer->mic = sb_att_7dbstep_2bits[(mixer->regs[0x0A] >> 1)&0x3]; + + mixer->output_filter = !(mixer->regs[0xE] & 0x20); + mixer->input_filter = !(mixer->regs[0xC] & 0x20); + mixer->in_filter_freq = ((mixer->regs[0xC] & 0x8) == 0) ? 3200 : 8800; + mixer->stereo = mixer->regs[0xE] & 2; + if (mixer->index == 0xE) + sb_dsp_set_stereo(&sb->dsp, val & 2); + + switch ((mixer->regs[0xc]&6)) + { + case 2: + mixer->input_selector = INPUT_CD_L|INPUT_CD_R; + break; + case 6: + mixer->input_selector = INPUT_LINE_L|INPUT_LINE_R; + break; + default: + mixer->input_selector = INPUT_MIC; + break; + } + + /* TODO: pcspeaker volume? Or is it not worth? */ + sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 65535, + ((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 65535); + } +} + +uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; if (!(addr & 1)) return mixer->index; @@ -279,144 +619,251 @@ uint8_t sb_pro_mixer_read(uint16_t addr, void *p) switch (mixer->index) { case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e: - case 0x22: case 0x26: case 0x28: case 0x2e: + case 0x22: case 0x26: case 0x28: case 0x2e: case 0x02: case 0x06: + case 0x30: case 0x32: case 0x36: case 0x38: return mixer->regs[mixer->index]; + + default: + pclog("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; } return 0xff; } +void sb_ct1345_mixer_reset(sb_t* sb) +{ + sb_ct1345_mixer_write(4,0,sb); + sb_ct1345_mixer_write(5,0,sb); +} -void sb_16_mixer_write(uint16_t addr, uint8_t val, void *p) +void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) { sb_t *sb = (sb_t *)p; - sb_mixer_t *mixer = &sb->mixer; + sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; if (!(addr & 1)) + { mixer->index = val; + } else { - mixer->regs[mixer->index] = val; + // TODO: and this? 001h: + /*DESCRIPTION + Contains previously selected register value. Mixer Data Register value + NOTES + * SoundBlaster 16 sets bit 7 if previous mixer index invalid. + * Status bytes initially 080h on startup for all but level bytes (SB16) + */ + + if (mixer->index == 0) + { + /* Reset */ + /* Changed defaults from -14dB to 0dB*/ + mixer->regs[0x30]=31 << 3; + mixer->regs[0x31]=31 << 3; + mixer->regs[0x32]=31 << 3; + mixer->regs[0x33]=31 << 3; + mixer->regs[0x34]=31 << 3; + mixer->regs[0x35]=31 << 3; + mixer->regs[0x36]=0 << 3; + mixer->regs[0x37]=0 << 3; + mixer->regs[0x38]=0 << 3; + mixer->regs[0x39]=0 << 3; + + mixer->regs[0x3A]=0 << 3; + mixer->regs[0x3B]=0 << 6; + mixer->regs[0x3C] = OUTPUT_MIC|OUTPUT_CD_R|OUTPUT_CD_L|OUTPUT_LINE_R|OUTPUT_LINE_L; + mixer->regs[0x3D] = INPUT_MIC|INPUT_CD_L|INPUT_LINE_L|INPUT_MIDI_L; + mixer->regs[0x3E] = INPUT_MIC|INPUT_CD_R|INPUT_LINE_R|INPUT_MIDI_R; + + mixer->regs[0x3F] = mixer->regs[0x40] = 0 << 6; + mixer->regs[0x41] = mixer->regs[0x42] = 0 << 6; + + mixer->regs[0x44] = mixer->regs[0x45] = 8 << 4; + mixer->regs[0x46] = mixer->regs[0x47] = 8 << 4; + + mixer->regs[0x43] = 0; + } + else + { + mixer->regs[mixer->index] = val; + } switch (mixer->index) { + /* SBPro compatibility. Copy values to sb16 registers. */ case 0x22: - mixer->regs[0x30] = ((mixer->regs[0x22] >> 4) | 0x11) << 3; - mixer->regs[0x31] = ((mixer->regs[0x22] & 0xf) | 0x11) << 3; + mixer->regs[0x30] = (mixer->regs[0x22] & 0xF0) | 0x8; + mixer->regs[0x31] = ((mixer->regs[0x22] & 0xf) << 4) | 0x8; break; case 0x04: - mixer->regs[0x32] = ((mixer->regs[0x04] >> 4) | 0x11) << 3; - mixer->regs[0x33] = ((mixer->regs[0x04] & 0xf) | 0x11) << 3; + mixer->regs[0x32] = (mixer->regs[0x04] & 0xF0) | 0x8; + mixer->regs[0x33] = ((mixer->regs[0x04] & 0xf) << 4) | 0x8; break; case 0x26: - mixer->regs[0x34] = ((mixer->regs[0x26] >> 4) | 0x11) << 3; - mixer->regs[0x35] = ((mixer->regs[0x26] & 0xf) | 0x11) << 3; + mixer->regs[0x34] = (mixer->regs[0x26] & 0xF0) | 0x8; + mixer->regs[0x35] = ((mixer->regs[0x26] & 0xf) << 4) | 0x8; break; case 0x28: - mixer->regs[0x36] = ((mixer->regs[0x28] >> 4) | 0x11) << 3; - mixer->regs[0x37] = ((mixer->regs[0x28] & 0xf) | 0x11) << 3; + mixer->regs[0x36] = (mixer->regs[0x28] & 0xF0) | 0x8; + mixer->regs[0x37] = ((mixer->regs[0x28] & 0xf) << 4) | 0x8; break; + case 0x2E: + mixer->regs[0x38] = (mixer->regs[0x2E] & 0xF0) | 0x8; + mixer->regs[0x39] = ((mixer->regs[0x2E] & 0xf) << 4) | 0x8; + break; + case 0x0A: + mixer->regs[0x3A] = (mixer->regs[0x0A]*3)+10; + break; + + /* + (DSP 4.xx feature) The Interrupt Setup register, addressed as register 80h on the Mixer register map, is used to configure or determine the Interrupt request line. The DMA setup register, addressed as register 81h on the Mixer register map, is used to configure or determine the DMA channels. + + Note: Registers 80h and 81h are Read-only for PnP boards. + */ case 0x80: - if (val & 1) sb->dsp.sb_irqnum = 2; - if (val & 2) sb->dsp.sb_irqnum = 5; - if (val & 4) sb->dsp.sb_irqnum = 7; - if (val & 8) sb->dsp.sb_irqnum = 10; - case 0x81: - if (val & 1) sb->dsp.sb_8_dmanum = 0; - if (val & 2) sb->dsp.sb_8_dmanum = 1; - if (val & 8) sb->dsp.sb_8_dmanum = 3; - if (val & 0x20) sb->dsp.sb_16_dmanum = 5; - if (val & 0x40) sb->dsp.sb_16_dmanum = 6; - if (val & 0x80) sb->dsp.sb_16_dmanum = 7; + if (val & 1) sb_dsp_setirq(&sb->dsp,2); + if (val & 2) sb_dsp_setirq(&sb->dsp,5); + if (val & 4) sb_dsp_setirq(&sb->dsp,7); + if (val & 8) sb_dsp_setirq(&sb->dsp,10); + break; + + case 0x81: + /* The documentation is confusing. sounds as if multple dma8 channels could be set. */ + if (val & 1) sb_dsp_setdma8(&sb->dsp,0); + if (val & 2) sb_dsp_setdma8(&sb->dsp,1); + if (val & 8) sb_dsp_setdma8(&sb->dsp,3); + if (val & 0x20) sb_dsp_setdma16(&sb->dsp,5); + if (val & 0x40) sb_dsp_setdma16(&sb->dsp,6); + if (val & 0x80) sb_dsp_setdma16(&sb->dsp,7); break; } - mixer->master_l = sb_att[mixer->regs[0x30] >> 3]; - mixer->master_r = sb_att[mixer->regs[0x31] >> 3]; - mixer->voice_l = sb_att[mixer->regs[0x32] >> 3]; - mixer->voice_r = sb_att[mixer->regs[0x33] >> 3]; - mixer->fm_l = sb_att[mixer->regs[0x34] >> 3]; - mixer->fm_r = sb_att[mixer->regs[0x35] >> 3]; - mixer->cd_l = sb_att[mixer->regs[0x36] >> 3]; - mixer->cd_r = sb_att[mixer->regs[0x37] >> 3]; + + mixer->output_selector = mixer->regs[0x3C]; + mixer->input_selector_left = mixer->regs[0x3D]; + mixer->input_selector_right = mixer->regs[0x3E]; + + mixer->master_l = sb_att_2dbstep_5bits[mixer->regs[0x30] >> 3]; + mixer->master_r = sb_att_2dbstep_5bits[mixer->regs[0x31] >> 3]; + mixer->voice_l = sb_att_2dbstep_5bits[mixer->regs[0x32] >> 3]; + mixer->voice_r = sb_att_2dbstep_5bits[mixer->regs[0x33] >> 3]; + mixer->fm_l = sb_att_2dbstep_5bits[mixer->regs[0x34] >> 3]; + mixer->fm_r = sb_att_2dbstep_5bits[mixer->regs[0x35] >> 3]; + mixer->cd_l = (mixer->output_selector&OUTPUT_CD_L) ? sb_att_2dbstep_5bits[mixer->regs[0x36] >> 3] : 0; + mixer->cd_r = (mixer->output_selector&OUTPUT_CD_R) ? sb_att_2dbstep_5bits[mixer->regs[0x37] >> 3] : 0; + mixer->line_l = (mixer->output_selector&OUTPUT_LINE_L) ? sb_att_2dbstep_5bits[mixer->regs[0x38] >> 3] : 0; + mixer->line_r = (mixer->output_selector&OUTPUT_LINE_R) ? sb_att_2dbstep_5bits[mixer->regs[0x39] >> 3] : 0; + + mixer->mic = sb_att_2dbstep_5bits[mixer->regs[0x3A] >> 3]; + mixer->speaker = sb_att_2dbstep_5bits[mixer->regs[0x3B]*3 + 22]; + + + mixer->input_gain_L = (mixer->regs[0x3F] >> 6); + mixer->input_gain_R = (mixer->regs[0x40] >> 6); + mixer->output_gain_L = (mixer->regs[0x41] >> 6); + mixer->output_gain_R = (mixer->regs[0x42] >> 6); + mixer->bass_l = mixer->regs[0x46] >> 4; mixer->bass_r = mixer->regs[0x47] >> 4; mixer->treble_l = mixer->regs[0x44] >> 4; mixer->treble_r = mixer->regs[0x45] >> 4; - mixer->filter = 0; + + /*TODO: pcspeaker volume, with "output_selector" check? or better not? */ sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 65535, ((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 65535); +// pclog("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); } } -uint8_t sb_16_mixer_read(uint16_t addr, void *p) +uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) { sb_t *sb = (sb_t *)p; - sb_mixer_t *mixer = &sb->mixer; - uint8_t temp = 0; + sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; if (!(addr & 1)) return mixer->index; +// pclog("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + + if (mixer->index>=0x30 && mixer->index<=0x47) + { + return mixer->regs[mixer->index]; + } switch (mixer->index) { + case 0x00: case 0x04: case 0x0A: case 0x22: case 0x26: case 0x28: case 0x2E: + return mixer->regs[mixer->index]; + + case 0x48: + // Undocumented. The Creative Windows Mixer calls this after calling 3C (input selector). even when writing. + // Also, the version I have (5.17) does not use the MIDI.L/R input selectors. it uses the volume to mute (Affecting the output, obviously) + return mixer->regs[mixer->index]; + case 0x80: + /*TODO: Unaffected by mixer reset or soft reboot. + * Enabling multiple bits enables multiple IRQs. + */ + switch (sb->dsp.sb_irqnum) { - case 2: return 1; /*IRQ 2*/ - case 5: return 2; /*IRQ 5*/ - case 7: return 4; /*IRQ 7*/ - case 10: return 8; /*IRQ 10*/ + case 2: return 1; + case 5: return 2; + case 7: return 4; + case 10: return 8; } break; + case 0x81: - switch (sb->dsp.sb_8_dmanum) - { - case 0: - temp = 1; - break; - case 1: - temp = 2; - break; - case 3: - temp = 8; - break; - default: - temp = 0; - break; - } - switch (sb->dsp.sb_16_dmanum) - { - case 5: - temp |= 0x20; - break; - case 6: - temp |= 0x40; - break; - case 7: - temp |= 0x80; - break; - default: - temp |= 0x00; - break; - } - return temp; + { + /* TODO: Unaffected by mixer reset or soft reboot. + * Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels. + * Disabling all 8-bit DMA channel bits disables 8-bit DMA requests, + including translated 16-bit DMA requests. + * Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA + requests to 8-bit ones, using the selected 8-bit DMA channel.*/ + + uint8_t result=0; + switch (sb->dsp.sb_8_dmanum) + { + case 0: result |= 1; break; + case 1: result |= 2; break; + case 3: result |= 8; break; + } + switch (sb->dsp.sb_16_dmanum) + { + case 5: result |= 0x20; break; + case 6: result |= 0x40; break; + case 7: result |= 0x80; break; + } + return result; + } + + /* The Interrupt status register, addressed as register 82h on the Mixer register map, + is used by the ISR to determine whether the interrupt is meant for it or for some other ISR, + in which case it should chain to the previous routine. + */ case 0x82: - return ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0); + /* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */ + /* 0x02000 DSP v4.04, 0x4000 DSP v4.05 0x8000 DSP v4.12. I haven't seen this making any difference, but I'm keeping it for now. */ + return ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | 0x4000; + + /* TODO: creative drivers read and write on 0xFE and 0xFF. not sure what they are supposed to be. */ + + + default: + pclog("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; } - return mixer->regs[mixer->index]; + + return 0xff; } -void sb_mixer_init(sb_mixer_t *mixer) +void sb_ct1745_mixer_reset(sb_t* sb) { - mixer->master_l = mixer->master_r = 65535; - mixer->voice_l = mixer->voice_r = 65535; - mixer->fm_l = mixer->fm_r = 65535; - mixer->cd_l = mixer->cd_r = 65535; - mixer->bass_l = mixer->bass_r = 8; - mixer->treble_l = mixer->treble_r = 8; - mixer->filter = 1; - sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 65535, - ((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 65535); + sb_ct1745_mixer_write(4,0,sb); + sb_ct1745_mixer_write(5,0,sb); } + static uint16_t sb_mcv_addr[8] = {0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270}; uint8_t sb_mcv_read(int port, void *p) @@ -441,6 +888,7 @@ void sb_mcv_write(int port, uint8_t val, void *p) addr = sb_mcv_addr[sb->pos_regs[4] & 7]; io_removehandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&sb->dsp, 0); sb->pos_regs[port & 7] = val; @@ -451,6 +899,7 @@ void sb_mcv_write(int port, uint8_t val, void *p) io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&sb->dsp, addr); } } @@ -480,7 +929,8 @@ void sb_pro_mcv_write(int port, uint8_t val, void *p) io_removehandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_removehandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_removehandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); + io_removehandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&sb->dsp, 0); sb->pos_regs[port & 7] = val; @@ -492,16 +942,20 @@ void sb_pro_mcv_write(int port, uint8_t val, void *p) io_sethandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); - + io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&sb->dsp, addr); } sb_dsp_setirq(&sb->dsp, sb_pro_mcv_irqs[(sb->pos_regs[5] >> 4) & 3]); sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); } - + void *sb_1_init() { + /*sb1/2 port mappings, 210h to 260h in 10h steps + 2x0 to 2x3 -> CMS chip + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip*/ sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -511,14 +965,19 @@ void *sb_1_init() sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_mixer_init(&sb->mixer); + /* CMS I/O handler is activated on the dedicated sound_cms module + DSP I/O handler is activated in sb_dsp_setaddr */ io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - sound_add_handler(sb_get_buffer_opl2, sb); + sound_add_handler(sb_get_buffer_sb2, sb); return sb; } void *sb_15_init() { + /*sb1/2 port mappings, 210h to 260h in 10h steps + 2x0 to 2x3 -> CMS chip + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip*/ sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -528,25 +987,29 @@ void *sb_15_init() sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_mixer_init(&sb->mixer); + /* CMS I/O handler is activated on the dedicated sound_cms module + DSP I/O handler is activated in sb_dsp_setaddr */ io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - sound_add_handler(sb_get_buffer_opl2, sb); + sound_add_handler(sb_get_buffer_sb2, sb); return sb; } void *sb_mcv_init() { + /*sb1/2 port mappings, 210h to 260h in 10h steps + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip*/ sb_t *sb = malloc(sizeof(sb_t)); memset(sb, 0, sizeof(sb_t)); opl2_init(&sb->opl); sb_dsp_init(&sb->dsp, SB15); - sb_dsp_setaddr(&sb->dsp, 0); + sb_dsp_setaddr(&sb->dsp, 0);//addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_mixer_init(&sb->mixer); - sound_add_handler(sb_get_buffer_opl2, sb); + sound_add_handler(sb_get_buffer_sb2, sb); + /* I/O handlers activated in sb_mcv_write */ mca_add(sb_mcv_read, sb_mcv_write, sb); sb->pos_regs[0] = 0x84; sb->pos_regs[1] = 0x50; @@ -554,6 +1017,13 @@ void *sb_mcv_init() } void *sb_2_init() { + /*sb2 port mappings. 220h or 240h. + 2x0 to 2x3 -> CMS chip + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip + "CD version" also uses 250h or 260h for + 2x0 to 2x3 -> CDROM interface + 2x4 to 2x5 -> Mixer interface*/ sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -563,15 +1033,32 @@ void *sb_2_init() sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_mixer_init(&sb->mixer); + sb_ct1335_mixer_reset(sb); + /* CMS I/O handler is activated on the dedicated sound_cms module + DSP I/O handler is activated in sb_dsp_setaddr */ io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - sound_add_handler(sb_get_buffer_opl2, sb); + + int mixer_addr = device_get_config_int("mixaddr"); + if (mixer_addr > 0) + { + io_sethandler(mixer_addr+4, 0x0002, sb_ct1335_mixer_read, NULL, NULL, sb_ct1335_mixer_write, NULL, NULL, sb); + sound_add_handler(sb_get_buffer_sb2_mixer, sb); + } + else + sound_add_handler(sb_get_buffer_sb2, sb); + return sb; } void *sb_pro_v1_init() { + /*sbpro port mappings. 220h or 240h. + 2x0 to 2x3 -> FM chip, Left and Right (9*2 voices) + 2x4 to 2x5 -> Mixer interface + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip (9 voices) + 2x0+10 to 2x0+13 CDROM interface.*/ sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -581,25 +1068,26 @@ void *sb_pro_v1_init() sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_mixer_init(&sb->mixer); + sb_ct1345_mixer_reset(sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ io_sethandler(addr+0, 0x0002, opl2_l_read, NULL, NULL, opl2_l_write, NULL, NULL, &sb->opl); io_sethandler(addr+2, 0x0002, opl2_r_read, NULL, NULL, opl2_r_write, NULL, NULL, &sb->opl); io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_get_buffer_opl2, sb); - - sb->mixer.regs[0x22] = 0xff; - sb->mixer.regs[0x04] = 0xff; - sb->mixer.regs[0x26] = 0xff; - sb->mixer.regs[0x28] = 0xff; - sb->mixer.regs[0xe] = 0; + io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); + sound_add_handler(sb_get_buffer_sbpro, sb); return sb; } void *sb_pro_v2_init() { + /*sbpro port mappings. 220h or 240h. + 2x0 to 2x3 -> FM chip (18 voices) + 2x4 to 2x5 -> Mixer interface + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip (9 voices) + 2x0+10 to 2x0+13 CDROM interface.*/ sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -609,38 +1097,34 @@ void *sb_pro_v2_init() sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_mixer_init(&sb->mixer); + sb_ct1345_mixer_reset(sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ io_sethandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_get_buffer_opl3, sb); - - sb->mixer.regs[0x22] = 0xff; - sb->mixer.regs[0x04] = 0xff; - sb->mixer.regs[0x26] = 0xff; - sb->mixer.regs[0x28] = 0xff; - sb->mixer.regs[0xe] = 0; + io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); + sound_add_handler(sb_get_buffer_sbpro, sb); return sb; } void *sb_pro_mcv_init() { + /*sbpro port mappings. 220h or 240h. + 2x0 to 2x3 -> FM chip, Left and Right (18 voices) + 2x4 to 2x5 -> Mixer interface + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip (9 voices)*/ sb_t *sb = malloc(sizeof(sb_t)); memset(sb, 0, sizeof(sb_t)); opl3_init(&sb->opl); sb_dsp_init(&sb->dsp, SBPRO2); - sb_mixer_init(&sb->mixer); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - sound_add_handler(sb_get_buffer_opl3, sb); - - sb->mixer.regs[0x22] = 0xff; - sb->mixer.regs[0x04] = 0xff; - sb->mixer.regs[0x26] = 0xff; - sb->mixer.regs[0xe] = 0; + sb_ct1345_mixer_reset(sb); + /* I/O handlers activated in sb_mcv_write */ + sound_add_handler(sb_get_buffer_sbpro, sb); + /* I/O handlers activated in sb_pro_mcv_write */ mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb); sb->pos_regs[0] = 0x03; sb->pos_regs[1] = 0x51; @@ -660,30 +1144,14 @@ void *sb_16_init() sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); - sb_mixer_init(&sb->mixer); - io_sethandler(addr + 0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + sb_ct1745_mixer_reset(sb); + io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 4, 0x0002, sb_16_mixer_read, NULL, NULL, sb_16_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_get_buffer_opl3, sb); + io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); + sound_add_handler(sb_get_buffer_sb16, sb); mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401")); - sb->mixer.regs[0x30] = 31 << 3; - sb->mixer.regs[0x31] = 31 << 3; - sb->mixer.regs[0x32] = 31 << 3; - sb->mixer.regs[0x33] = 31 << 3; - sb->mixer.regs[0x34] = 31 << 3; - sb->mixer.regs[0x35] = 31 << 3; - sb->mixer.regs[0x36] = 31 << 3; - sb->mixer.regs[0x37] = 31 << 3; - sb->mixer.regs[0x44] = 8 << 4; - sb->mixer.regs[0x45] = 8 << 4; - sb->mixer.regs[0x46] = 8 << 4; - sb->mixer.regs[0x47] = 8 << 4; - sb->mixer.regs[0x22] = (sb->mixer.regs[0x30] & 0xf0) | (sb->mixer.regs[0x31] >> 4); - sb->mixer.regs[0x04] = (sb->mixer.regs[0x32] & 0xf0) | (sb->mixer.regs[0x33] >> 4); - sb->mixer.regs[0x26] = (sb->mixer.regs[0x34] & 0xf0) | (sb->mixer.regs[0x35] >> 4); - sb->mixer.regs[0x28] = (sb->mixer.regs[0x36] & 0xf0) | (sb->mixer.regs[0x37] >> 4); return sb; } @@ -696,48 +1164,46 @@ int sb_awe32_available() void *sb_awe32_init() { sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); + uint16_t addr = device_get_config_hex16("base"); + uint16_t emu_addr = device_get_config_hex16("emu_base"); int onboard_ram = device_get_config_int("onboard_ram"); memset(sb, 0, sizeof(sb_t)); + opl3_init(&sb->opl); sb_dsp_init(&sb->dsp, SB16 + 1); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); - sb_mixer_init(&sb->mixer); - io_sethandler(addr + 0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + sb_ct1745_mixer_reset(sb); + io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 4, 0x0002, sb_16_mixer_read, NULL, NULL, sb_16_mixer_write, NULL, NULL, sb); + io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_emu8k, sb); mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401")); - emu8k_init(&sb->emu8k, onboard_ram); + emu8k_init(&sb->emu8k, emu_addr, onboard_ram); - sb->mixer.regs[0x30] = 31 << 3; - sb->mixer.regs[0x31] = 31 << 3; - sb->mixer.regs[0x32] = 31 << 3; - sb->mixer.regs[0x33] = 31 << 3; - sb->mixer.regs[0x34] = 31 << 3; - sb->mixer.regs[0x35] = 31 << 3; - sb->mixer.regs[0x36] = 31 << 3; - sb->mixer.regs[0x37] = 31 << 3; - sb->mixer.regs[0x44] = 8 << 4; - sb->mixer.regs[0x45] = 8 << 4; - sb->mixer.regs[0x46] = 8 << 4; - sb->mixer.regs[0x47] = 8 << 4; - sb->mixer.regs[0x22] = (sb->mixer.regs[0x30] & 0xf0) | (sb->mixer.regs[0x31] >> 4); - sb->mixer.regs[0x04] = (sb->mixer.regs[0x32] & 0xf0) | (sb->mixer.regs[0x33] >> 4); - sb->mixer.regs[0x26] = (sb->mixer.regs[0x34] & 0xf0) | (sb->mixer.regs[0x35] >> 4); - sb->mixer.regs[0x28] = (sb->mixer.regs[0x36] & 0xf0) | (sb->mixer.regs[0x37] >> 4); - return sb; } void sb_close(void *p) { sb_t *sb = (sb_t *)p; + sb_dsp_close(&sb->dsp); + #ifdef SB_DSP_RECORD_DEBUG + if (soundfsb != 0) + { + fclose(soundfsb); + soundfsb=0; + } + if (soundfsbin!= 0) + { + fclose(soundfsbin); + soundfsbin=0; + } + #endif free(sb); } @@ -748,7 +1214,7 @@ void sb_awe32_close(void *p) emu8k_close(&sb->emu8k); - free(sb); + sb_close(sb); } void sb_speed_changed(void *p) @@ -1070,6 +1536,26 @@ static device_config_t sb_awe32_config[] = } } }, + { + "emu_addr", "EMU8000 Address", CONFIG_HEX16, "", 0x620, + { + { + "0x620", 0x620 + }, + { + "0x640", 0x640 + }, + { + "0x660", 0x660 + }, + { + "0x680", 0x680 + }, + { + .description = "" + } + } + }, { "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, { @@ -1209,10 +1695,9 @@ static device_config_t sb_awe32_config[] = device_t sb_1_device = { "Sound Blaster v1.0", - 0, - sb_1_init, - sb_close, - NULL, + DEVICE_ISA, + 0, + sb_1_init, sb_close, NULL, NULL, sb_speed_changed, NULL, sb_add_status_info, @@ -1221,10 +1706,9 @@ device_t sb_1_device = device_t sb_15_device = { "Sound Blaster v1.5", - 0, - sb_15_init, - sb_close, - NULL, + DEVICE_ISA, + 0, + sb_15_init, sb_close, NULL, NULL, sb_speed_changed, NULL, sb_add_status_info, @@ -1234,9 +1718,8 @@ device_t sb_mcv_device = { "Sound Blaster MCV", DEVICE_MCA, - sb_mcv_init, - sb_close, - NULL, + 0, + sb_mcv_init, sb_close, NULL, NULL, sb_speed_changed, NULL, sb_add_status_info, @@ -1245,10 +1728,9 @@ device_t sb_mcv_device = device_t sb_2_device = { "Sound Blaster v2.0", - 0, - sb_2_init, - sb_close, - NULL, + DEVICE_ISA, + 0, + sb_2_init, sb_close, NULL, NULL, sb_speed_changed, NULL, sb_add_status_info, @@ -1257,10 +1739,9 @@ device_t sb_2_device = device_t sb_pro_v1_device = { "Sound Blaster Pro v1", - 0, - sb_pro_v1_init, - sb_close, - NULL, + DEVICE_ISA, + 0, + sb_pro_v1_init, sb_close, NULL, NULL, sb_speed_changed, NULL, sb_add_status_info, @@ -1269,10 +1750,9 @@ device_t sb_pro_v1_device = device_t sb_pro_v2_device = { "Sound Blaster Pro v2", - 0, - sb_pro_v2_init, - sb_close, - NULL, + DEVICE_ISA, + 0, + sb_pro_v2_init, sb_close, NULL, NULL, sb_speed_changed, NULL, sb_add_status_info, @@ -1282,9 +1762,8 @@ device_t sb_pro_mcv_device = { "Sound Blaster Pro MCV", DEVICE_MCA, - sb_pro_mcv_init, - sb_close, - NULL, + 0, + sb_pro_mcv_init, sb_close, NULL, NULL, sb_speed_changed, NULL, sb_add_status_info, @@ -1293,10 +1772,9 @@ device_t sb_pro_mcv_device = device_t sb_16_device = { "Sound Blaster 16", - 0, - sb_16_init, - sb_close, - NULL, + DEVICE_ISA, + 0, + sb_16_init, sb_close, NULL, NULL, sb_speed_changed, NULL, sb_add_status_info, @@ -1305,9 +1783,9 @@ device_t sb_16_device = device_t sb_awe32_device = { "Sound Blaster AWE32", - 0, - sb_awe32_init, - sb_close, + DEVICE_ISA, + 0, + sb_awe32_init, sb_close, NULL, sb_awe32_available, sb_speed_changed, NULL, diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 8ff2e4efc..c142065c8 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -3,24 +3,39 @@ 486-33 - 20kHz 486-50 - 32kHz Pentium - 45kHz*/ -#include + #include +#include +#include +#include +#include #include "../ibm.h" #include "../io.h" #include "../pic.h" #include "../dma.h" #include "../timer.h" #include "../device.h" -#include "midi.h" #include "sound.h" +#include "midi.h" #include "snd_mpu401.h" #include "snd_sb_dsp.h" -mpu_t mpu; +/*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/ +#define SB_DSP_REC_SAFEFTY_MARGIN 4096 void pollsb(void *p); void sb_poll_i(void *p); +//#define SB_DSP_RECORD_DEBUG +//#define SB_TEST_RECORDING_SAW + +#ifdef SB_DSP_RECORD_DEBUG +FILE* soundf = 0/*NULL*/; +#endif + +#ifdef SB_TEST_RECORDING_SAW +int counttest; +#endif static int sbe2dat[4][9] = { { 0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106 }, @@ -101,6 +116,7 @@ uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x void sb_irq(sb_dsp_t *dsp, int irq8) { +// pclog("IRQ %i %02X\n",irq8,pic.mask); if (irq8) dsp->sb_irq8 = 1; else dsp->sb_irq16 = 1; picint(1 << dsp->sb_irqnum); @@ -133,9 +149,20 @@ void sb_dsp_reset(sb_dsp_t *dsp) dsp->sbreset = 0; dsp->sbenable = dsp->sb_enable_i = dsp->sb_count_i = 0; + dsp->record_pos_read=0; + dsp->record_pos_write=SB_DSP_REC_SAFEFTY_MARGIN; + picintc(1 << dsp->sb_irqnum); dsp->asp_data_len = 0; + + #ifdef SB_DSP_RECORD_DEBUG + if (soundf != 0) + { + fclose(soundf); + soundf=0; + } + #endif } void sb_doreset(sb_dsp_t *dsp) @@ -193,6 +220,7 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len timer_update_outstanding(); dsp->sbleftright = 0; dsp->sbdacpos = 0; +// pclog("Start 8-bit DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } else { @@ -204,8 +232,9 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0; dsp->sb_16_output = 1; timer_process(); - dsp->sbenable = dsp->sb_16_enable; - timer_update_outstanding(); + dsp->sbenable = dsp->sb_16_enable; + timer_update_outstanding(); +// pclog("Start 16-bit DMA addr %06X len %04X\n",dma16.ac[1]+(dma16.page[1]<<16),len); } } @@ -213,6 +242,13 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l { if (dma8) { +#ifdef SB_TEST_RECORDING_SAW + switch (dsp->sb_8_format) + { + case 00:case 20:counttest=0x80;break; + case 10:case 30:counttest=0;break; + } +#endif dsp->sb_8_length = len; dsp->sb_8_format = format; dsp->sb_8_autoinit = autoinit; @@ -223,9 +259,17 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l timer_process(); dsp->sb_enable_i = dsp->sb_8_enable; timer_update_outstanding(); +// pclog("Start 8-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } else { +#ifdef SB_TEST_RECORDING_SAW + switch (dsp->sb_16_format) + { + case 00:case 20:counttest=0x8000;break; + case 10:case 30:counttest=0;break; + } +#endif dsp->sb_16_length = len; dsp->sb_16_format = format; dsp->sb_16_autoinit = autoinit; @@ -236,7 +280,18 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l timer_process(); dsp->sb_enable_i = dsp->sb_16_enable; timer_update_outstanding(); +// pclog("Start 16-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } + memset(dsp->record_buffer,0,sizeof(dsp->record_buffer)); + + #ifdef SB_DSP_RECORD_DEBUG + if (soundf != 0) + { + fclose(soundf); + soundf=0; + } + #endif + } int sb_8_read_dma(sb_dsp_t *dsp) @@ -246,14 +301,23 @@ int sb_8_read_dma(sb_dsp_t *dsp) void sb_8_write_dma(sb_dsp_t *dsp, uint8_t val) { dma_channel_write(dsp->sb_8_dmanum, val); +#ifdef SB_DSP_RECORD_DEBUG + if (!soundf) soundf=fopen("sound_dsp.pcm","wb"); + fwrite(&val,1,1,soundf); +#endif } uint16_t sb_16_read_dma(sb_dsp_t *dsp) { return dma_channel_read(dsp->sb_16_dmanum); } -void sb_16_write_dma(sb_dsp_t *dsp, uint16_t val) +int sb_16_write_dma(sb_dsp_t *dsp, uint16_t val) { - dma_channel_write(dsp->sb_16_dmanum, val); + int ret = dma_channel_write(dsp->sb_16_dmanum, val); +#ifdef SB_DSP_RECORD_DEBUG + if (!soundf) soundf=fopen("sound_dsp.pcm","wb"); + fwrite(&val,2,1,soundf); +#endif + return (ret == DMA_NODATA); } void sb_dsp_setirq(sb_dsp_t *dsp, int irq) @@ -270,10 +334,10 @@ void sb_dsp_setdma16(sb_dsp_t *dsp, int dma) { dsp->sb_16_dmanum = dma; } - void sb_exec_command(sb_dsp_t *dsp) { int temp,c; +// pclog("sb_exec_command : SB command %02X\n", dsp->sb_command); switch (dsp->sb_command) { case 0x01: /*???*/ @@ -293,6 +357,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x17: /*2-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; +// pclog("Ref byte 2 %02X\n",sbref); case 0x16: /*2-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -309,7 +374,19 @@ void sb_exec_command(sb_dsp_t *dsp) dsp->sb_8_length--; break; case 0x20: /*8-bit direct input*/ - sb_add_data(dsp, 0); + sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); + /*Due to the current implementation, I need to emulate a samplerate, even if this + * mode does not imply such samplerate. Position is increased in sb_poll_i*/ + if (dsp->sb_enable_i==0) + { + dsp->sb_timei = 256 - 22; + dsp->sblatchi = TIMER_USEC * 22; + temp = 1000000 / 22; + dsp->sb_freq = temp; + timer_process(); + dsp->sb_enable_i = 1; + timer_update_outstanding(); + } break; case 0x24: /*8-bit single cycle DMA input*/ sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); @@ -318,40 +395,36 @@ void sb_exec_command(sb_dsp_t *dsp) if (dsp->sb_type < SB15) break; sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); break; + case 0x30: + case 0x31: + break; + case 0x34: + dsp->uart_midi = 1; + dsp->uart_irq = 0; + break; + case 0x35: + dsp->uart_midi = 1; + dsp->uart_irq = 1; + break; + case 0x36: + case 0x37: + break; + case 0x38: + dsp->onebyte_midi = 1; + break; case 0x40: /*Set time constant*/ dsp->sb_timei = dsp->sb_timeo = dsp->sb_data[0]; dsp->sblatcho = dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_data[0]); temp = 256 - dsp->sb_data[0]; temp = 1000000 / temp; +// pclog("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); dsp->sb_freq = temp; break; - - case 0x30: - case 0x31: - break; - - case 0x34: - dsp->uart_midi = 1; - dsp->uart_irq = 0; - break; - - case 0x35: - dsp->uart_midi = 1; - dsp->uart_irq = 1; - break; - - case 0x36: - case 0x37: - break; - - case 0x38: - dsp->onebyte_midi = 1; - break; - case 0x41: /*Set output sampling rate*/ case 0x42: /*Set input sampling rate*/ if (dsp->sb_type < SB16) break; dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); +// pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); dsp->sb_timeo = 256 + dsp->sb_freq; dsp->sblatchi = dsp->sblatcho; @@ -363,6 +436,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x75: /*4-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; +// pclog("Ref byte 4 %02X\n",sbref); case 0x74: /*4-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -371,6 +445,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x77: /*2.6-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; +// pclog("Ref byte 26 %02X\n",sbref); case 0x76: /*2.6-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -390,28 +465,31 @@ void sb_exec_command(sb_dsp_t *dsp) break; case 0x80: /*Pause DAC*/ dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); - timer_process(); +// pclog("SB pause %04X\n",sb_pausetime); + timer_process(); dsp->sbenable = 1; timer_update_outstanding(); break; case 0x90: /*High speed 8-bit autoinit DMA output*/ - if (dsp->sb_type < SB2) break; + if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x91: /*High speed 8-bit single cycle DMA output*/ - if (dsp->sb_type < SB2) break; + if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0x98: /*High speed 8-bit autoinit DMA input*/ - if (dsp->sb_type < SB2) break; + if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x99: /*High speed 8-bit single cycle DMA input*/ - if (dsp->sb_type < SB2) break; + if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0xA0: /*Set input mode to mono*/ case 0xA8: /*Set input mode to stereo*/ + if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + //TODO: Implement. 3.xx-only command. break; case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: /*16-bit DMA output*/ @@ -441,9 +519,17 @@ void sb_exec_command(sb_dsp_t *dsp) dsp->sb_8_pause = 1; break; case 0xD1: /*Speaker on*/ + if (dsp->sb_type < SB15 ) + dsp->sb_8_pause = 1; + else if ( dsp->sb_type < SB16 ) + dsp->muted = 0; dsp->sb_speaker = 1; break; case 0xD3: /*Speaker off*/ + if (dsp->sb_type < SB15 ) + dsp->sb_8_pause = 1; + else if ( dsp->sb_type < SB16 ) + dsp->muted = 1; dsp->sb_speaker = 0; break; case 0xD4: /*Continue 8-bit DMA*/ @@ -495,8 +581,13 @@ void sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, dsp->sb_test); break; case 0xF2: /*Trigger 8-bit IRQ*/ +// pclog("Trigger IRQ\n"); sb_irq(dsp, 1); break; + case 0xF3: /*Trigger 16-bit IRQ*/ +// pclog("Trigger IRQ\n"); + sb_irq(dsp, 0); + break; case 0xE7: /*???*/ case 0xFA: /*???*/ break; @@ -510,10 +601,13 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x0E: /*ASP set register*/ if (dsp->sb_type < SB16) break; dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; +// pclog("ASP write reg %02X %02X\n", sb_data[0], sb_data[1]); break; case 0x0F: /*ASP get register*/ if (dsp->sb_type < SB16) break; +// sb_add_data(0); sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]); +// pclog("ASP read reg %02X %02X\n", sb_data[0], sb_asp_regs[sb_data[0]]); break; case 0xF8: if (dsp->sb_type >= SB16) break; @@ -528,12 +622,31 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x04: case 0x05: break; +// default: +// fatal("Exec bad SB command %02X\n",sb_command); + + + /*TODO: Some more data about the DSP registeres + * http://the.earth.li/~tfm/oldpage/sb_dsp.html + * http://www.synchrondata.com/pheaven/www/area19.htm + * http://www.dcee.net/Files/Programm/Sound/ + 0E3h DSP Copyright SBPro2??? + 0F0h Sine Generator SB + 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 + 0F2h IRQ Request, 8-bit SB + 0F3h IRQ Request, 16-bit SB16 + 0FBh DSP Status SB16 + 0FCh DSP Auxiliary Status SB16 + 0FDh DSP Command Status SB16 + */ + } } void sb_write(uint16_t a, uint8_t v, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *)priv; +// pclog("sb_write : Write soundblaster %04X %02X %04X:%04X %02X\n",a,v,CS,pc,dsp->sb_command); switch (a&0xF) { case 6: /*Reset*/ @@ -545,18 +658,13 @@ void sb_write(uint16_t a, uint8_t v, void *priv) dsp->sbreset = v; return; case 0xC: /*Command/data write*/ - if (dsp->uart_midi || dsp->onebyte_midi) - { - midi_write(v); - dsp->onebyte_midi = 0; - return; - } timer_process(); dsp->wb_time = TIMER_USEC * 1; dsp->wb_full = 1; timer_update_outstanding(); if (dsp->asp_data_len) { +// pclog("ASP data %i\n", dsp->asp_data_len); dsp->asp_data_len--; if (!dsp->asp_data_len) sb_add_data(dsp, 0); @@ -567,6 +675,8 @@ void sb_write(uint16_t a, uint8_t v, void *priv) dsp->sb_command = v; if (v == 0x01) sb_add_data(dsp, 0); +// if (sb_commands[v]==-1) +// fatal("Bad SB command %02X\n",v); dsp->sb_data_stat++; } else @@ -583,19 +693,17 @@ void sb_write(uint16_t a, uint8_t v, void *priv) uint8_t sb_read(uint16_t a, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *)priv; +// pclog("sb_read : Read soundblaster %04X %04X:%04X\n",a,CS,pc); switch (a & 0xf) { case 0xA: /*Read data*/ - if (dsp->uart_midi) - { - return MPU401_ReadData(&mpu); - } dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; if (dsp->sb_read_rp != dsp->sb_read_wp) { dsp->sb_read_rp++; dsp->sb_read_rp &= 0xFF; } +// pclog("SB read %02X\n",sbreaddat); return dsp->sbreaddat; case 0xC: /*Write data ready*/ if (dsp->wb_full) @@ -627,7 +735,8 @@ void sb_dsp_init(sb_dsp_t *dsp, int type) { dsp->sb_type = type; - dsp->sb_irqnum = 5; + // Default values. Use sb_dsp_setxxx() methods to change. + dsp->sb_irqnum = 7; dsp->sb_8_dmanum = 1; dsp->sb_16_dmanum = 5; @@ -640,6 +749,7 @@ void sb_dsp_init(sb_dsp_t *dsp, int type) void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr) { +// pclog("sb_dsp_setaddr : %04X\n", addr); io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); dsp->sb_addr = addr; @@ -661,11 +771,13 @@ void pollsb(void *p) int tempi,ref; dsp->sbcount += dsp->sblatcho; +// pclog("PollSB %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) { int data[2]; sb_dsp_update(dsp); +// pclog("Dopoll %i %02X %i\n", sb_8_length, sb_8_format, sblatcho); switch (dsp->sb_8_format) { case 0x00: /*Mono unsigned*/ @@ -682,7 +794,7 @@ void pollsb(void *p) dsp->sbleftright = !dsp->sbleftright; } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; dsp->sb_8_length--; break; case 0x10: /*Mono signed*/ @@ -697,7 +809,7 @@ void pollsb(void *p) dsp->sbleftright = !dsp->sbleftright; } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; dsp->sb_8_length--; break; case 0x20: /*Stereo unsigned*/ @@ -749,7 +861,7 @@ void pollsb(void *p) dsp->sbleftright = !dsp->sbleftright; } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; break; case ADPCM_26: @@ -783,7 +895,7 @@ void pollsb(void *p) dsp->sbleftright = !dsp->sbleftright; } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; break; case ADPCM_2: @@ -813,8 +925,11 @@ void pollsb(void *p) dsp->sbleftright = !dsp->sbleftright; } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; break; + +// default: + //fatal("Unrecognised SB 8-bit format %02X\n",sb_8_format); } if (dsp->sb_8_length < 0) @@ -848,10 +963,13 @@ void pollsb(void *p) dsp->sbdatr = sb_16_read_dma(dsp); dsp->sb_16_length -= 2; break; +// default: +// fatal("Unrecognised SB 16-bit format %02X\n",sb_16_format); } if (dsp->sb_16_length < 0) { +// pclog("16DMA over %i\n",dsp->sb_16_autoinit); if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; else dsp->sb_16_enable = dsp->sbenable = 0; sb_irq(dsp, 0); @@ -864,6 +982,7 @@ void pollsb(void *p) { sb_irq(dsp, 1); dsp->sbenable = dsp->sb_8_enable; +// pclog("SB pause over\n"); } } } @@ -871,80 +990,169 @@ void pollsb(void *p) void sb_poll_i(void *p) { sb_dsp_t *dsp = (sb_dsp_t *)p; - + int processed=0; dsp->sb_count_i += dsp->sblatchi; +// pclog("PollSBi %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) { switch (dsp->sb_8_format) { - case 0x00: /*Mono unsigned*/ - sb_8_write_dma(dsp, 0x80); +#ifdef SB_TEST_RECORDING_SAW + case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ + case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/ + sb_8_write_dma(dsp, counttest); + counttest+=0x10; + counttest&=0xFF; dsp->sb_8_length--; break; - case 0x10: /*Mono signed*/ - sb_8_write_dma(dsp, 0x00); + case 0x20: /*Unsigned stereo*/ + case 0x30: /*Signed stereo*/ + sb_8_write_dma(dsp, counttest); + sb_8_write_dma(dsp, counttest); + counttest+=0x10; + counttest&=0xFF; + dsp->sb_8_length -= 2; + break; +#else + case 0x00: /*Mono unsigned As the manual says, only the left channel is recorded*/ + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); dsp->sb_8_length--; + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; + break; + case 0x10: /*Mono signed As the manual says, only the left channel is recorded*/ + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)); + dsp->sb_8_length--; + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; break; case 0x20: /*Stereo unsigned*/ - sb_8_write_dma(dsp, 0x80); - sb_8_write_dma(dsp, 0x80); + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)^0x80); + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)^0x80); dsp->sb_8_length -= 2; + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; break; case 0x30: /*Stereo signed*/ - sb_8_write_dma(dsp, 0x00); - sb_8_write_dma(dsp, 0x00); + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)); + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)); dsp->sb_8_length -= 2; + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; break; +#endif +// default: +// fatal("Unrecognised SB 8-bit input format %02X\n",sb_8_format); } if (dsp->sb_8_length < 0) { +// pclog("Input DMA over %i\n",sb_8_autoinit); if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen; - else dsp->sb_8_enable = dsp->sbenable = 0; + else dsp->sb_8_enable = dsp->sb_enable_i = 0; sb_irq(dsp, 1); } + processed=1; } if (dsp->sb_16_enable && !dsp->sb_16_pause && dsp->sb_pausetime < 0 && !dsp->sb_16_output) { switch (dsp->sb_16_format) { - case 0x00: /*Unsigned mono*/ - sb_16_write_dma(dsp, 0x8000); - dsp->sb_16_length--; - break; - case 0x10: /*Signed mono*/ - sb_16_write_dma(dsp, 0); +#ifdef SB_TEST_RECORDING_SAW + case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ + case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/ + if (sb_16_write_dma(dsp, counttest)) + return; + counttest+=0x1000; + counttest&=0xFFFF; dsp->sb_16_length--; break; case 0x20: /*Unsigned stereo*/ - sb_16_write_dma(dsp, 0x8000); - sb_16_write_dma(dsp, 0x8000); + case 0x30: /*Signed stereo*/ + if (sb_16_write_dma(dsp, counttest)) + return; + sb_16_write_dma(dsp, counttest); + counttest+=0x1000; + counttest&=0xFFFF; dsp->sb_16_length -= 2; break; +#else + case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ + if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) + return; + dsp->sb_16_length--; + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; + break; + case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/ + if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read])) + return; + dsp->sb_16_length--; + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; + break; + case 0x20: /*Unsigned stereo*/ + if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) + return; + sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]^0x8000); + dsp->sb_16_length -= 2; + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; + break; case 0x30: /*Signed stereo*/ - sb_16_write_dma(dsp, 0); - sb_16_write_dma(dsp, 0); + if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read])) + return; + sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]); dsp->sb_16_length -= 2; + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; break; +#endif +// default: +// fatal("Unrecognised SB 16-bit input format %02X\n",sb_16_format); } if (dsp->sb_16_length < 0) { +// pclog("16iDMA over %i\n",sb_16_autoinit); if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; - else dsp->sb_16_enable = dsp->sbenable = 0; + else dsp->sb_16_enable = dsp->sb_enable_i = 0; sb_irq(dsp, 0); } + processed=1; + } + //Assume this is direct mode + if (!processed) + { + dsp->record_pos_read+=2; + dsp->record_pos_read&=0xFFFF; } } void sb_dsp_update(sb_dsp_t *dsp) { + /*this "if" implements two things: speaker on/off and buffer cleanup after stopping audio. */ + if (!dsp->sbenable || dsp->muted) + { + dsp->sbdatl=0; + dsp->sbdatr=0; + } for (; dsp->pos < sound_pos_global; dsp->pos++) { dsp->buffer[dsp->pos*2] = dsp->sbdatl; dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr; } } +void sb_dsp_close(sb_dsp_t *dsp) +{ + #ifdef SB_DSP_RECORD_DEBUG + if (soundf != 0) + { + fclose(soundf); + soundf=0; + } + #endif +} void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp) { diff --git a/src/sound/snd_sb_dsp.h b/src/sound/snd_sb_dsp.h index fb14284fa..60656be8f 100644 --- a/src/sound/snd_sb_dsp.h +++ b/src/sound/snd_sb_dsp.h @@ -1,9 +1,5 @@ typedef struct sb_dsp_t -{ - int uart_midi; - int uart_irq; - int onebyte_midi; - +{ int sb_type; int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output; @@ -15,8 +11,12 @@ typedef struct sb_dsp_t uint8_t sb_read_data[256]; int sb_read_wp, sb_read_rp; int sb_speaker; + int muted; int sb_data_stat; + int uart_midi; + int uart_irq; + int onebyte_midi; int sb_irqnum; @@ -42,17 +42,17 @@ typedef struct sb_dsp_t uint8_t sbreaddat; uint8_t sb_command; uint8_t sb_test; - int sb_timei, sb_timeo; + int64_t sb_timei, sb_timeo; int sb_irq8, sb_irq16; uint8_t sb_asp_regs[256]; - int sbenable, sb_enable_i; + int64_t sbenable, sb_enable_i; - int sbcount, sb_count_i; + int64_t sbcount, sb_count_i; - int sblatcho, sblatchi; + int64_t sblatcho, sblatchi; uint16_t sb_addr; @@ -60,13 +60,17 @@ typedef struct sb_dsp_t int asp_data_len; - int wb_time, wb_full; - + int64_t wb_time, wb_full; + + int record_pos_read; + int record_pos_write; + int16_t record_buffer[0xFFFF]; int16_t buffer[SOUNDBUFLEN * 2]; int pos; } sb_dsp_t; void sb_dsp_init(sb_dsp_t *dsp, int type); +void sb_dsp_close(sb_dsp_t *dsp); void sb_dsp_setirq(sb_dsp_t *dsp, int irq); void sb_dsp_setdma8(sb_dsp_t *dsp, int dma); diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index 574769322..7f7d02f2f 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -1,4 +1,8 @@ +#include +#include +#include #include +#include #include #include "../ibm.h" #include "../io.h" @@ -201,7 +205,7 @@ void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, in io_sethandler(base, size, NULL, NULL, NULL, sn76489_write, NULL, NULL, sn76489); } -void *sn76489_device_init() +void *sn76489_device_init(device_t *info) { sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); @@ -210,7 +214,7 @@ void *sn76489_device_init() return sn76489; } -void *ncr8496_device_init() +void *ncr8496_device_init(device_t *info) { sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); @@ -231,21 +235,19 @@ device_t sn76489_device = { "TI SN74689 PSG", 0, + 0, sn76489_device_init, sn76489_device_close, - NULL, - NULL, - NULL, + NULL, NULL, NULL, NULL, NULL }; device_t ncr8496_device = { "NCR8496 PSG", 0, + 0, ncr8496_device_init, sn76489_device_close, - NULL, - NULL, - NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_speaker.c b/src/sound/snd_speaker.c index 3ac8298a9..44d576941 100644 --- a/src/sound/snd_speaker.c +++ b/src/sound/snd_speaker.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "sound.h" #include "snd_speaker.h" diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index d42898b9d..cba259422 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -1,4 +1,8 @@ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../device.h" @@ -53,7 +57,7 @@ static void ssi2001_write(uint16_t addr, uint8_t val, void *p) sid_write(addr, val, p); } -void *ssi2001_init() +void *ssi2001_init(device_t *info) { ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t)); memset(ssi2001, 0, sizeof(ssi2001_t)); @@ -78,11 +82,8 @@ void ssi2001_close(void *p) device_t ssi2001_device = { "Innovation SSI-2001", - 0, - ssi2001_init, - ssi2001_close, - NULL, - NULL, - NULL, + 0, 0, + ssi2001_init, ssi2001_close, NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index a58bc0b64..7c47f38e4 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -2,7 +2,11 @@ Windows Sound System emulation*/ +#include +#include +#include #include +#include #include #include "../ibm.h" #include "../io.h" @@ -73,7 +77,7 @@ static void wss_get_buffer(int32_t *buffer, int len, void *p) wss->ad1848.pos = 0; } -void *wss_init() +void *wss_init(device_t *info) { wss_t *wss = malloc(sizeof(wss_t)); @@ -111,11 +115,10 @@ void wss_speed_changed(void *p) device_t wss_device = { "Windows Sound System", - 0, - wss_init, - wss_close, + DEVICE_ISA, 0, + wss_init, wss_close, NULL, NULL, wss_speed_changed, - NULL, + NULL, NULL, NULL }; diff --git a/src/sound/snd_ym7128.c b/src/sound/snd_ym7128.c index 4bea44f53..354b8b3b0 100644 --- a/src/sound/snd_ym7128.c +++ b/src/sound/snd_ym7128.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include "../ibm.h" #include "snd_ym7128.h" diff --git a/src/sound/sound.c b/src/sound/sound.c index f52ba16c3..825b2e955 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -8,30 +8,32 @@ * * Sound emulation core. * - * Version: @(#)sound.c 1.0.3 2017/09/03 + * Version: @(#)sound.c 1.0.5 2017/10/10 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ -#include #include +#include +#include #include +#include #include "../ibm.h" #include "../device.h" #include "../timer.h" #include "../cdrom/cdrom.h" -#include "../win/plat_thread.h" -#include "midi.h" +#include "../plat.h" #include "sound.h" +#include "midi.h" #include "snd_opl.h" #include "snd_adlib.h" #include "snd_adlibgold.h" -#ifdef DEV_BRANCH -# ifdef USE_PAS16 -# include "snd_pas16.h" -# endif +#include "snd_audiopci.h" +#if defined(DEV_BRANCH) && defined(USE_PAS16) +# include "snd_pas16.h" #endif #include "snd_sb.h" #include "snd_sb_dsp.h" @@ -52,25 +54,25 @@ typedef struct static SOUND_CARD sound_cards[] = { - { "None", "none", NULL }, - { "Adlib", "adlib", &adlib_device }, - { "Adlib MCA", "adlib_mca", &adlib_mca_device }, - { "Sound Blaster 1.0", "sb", &sb_1_device }, - { "Sound Blaster 1.5", "sb1.5", &sb_15_device }, - { "Sound Blaster MCV", "sbmcv", &sb_mcv_device }, - { "Sound Blaster 2.0", "sb2.0", &sb_2_device }, - { "Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device }, - { "Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device }, - { "Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device }, - { "Sound Blaster 16", "sb16", &sb_16_device }, - { "Sound Blaster AWE32", "sbawe32", &sb_awe32_device }, - { "Adlib Gold", "adlibgold", &adgold_device }, - { "Windows Sound System", "wss", &wss_device }, -#ifdef DEV_BRANCH -#ifdef USE_PAS16 - { "Pro Audio Spectrum 16", "pas16", &pas16_device }, -#endif + { "None", "none", NULL }, + { "[ISA] Adlib", "adlib", &adlib_device }, + { "[ISA] Adlib Gold", "adlibgold",&adgold_device }, + { "[ISA] Sound Blaster 1.0", "sb", &sb_1_device }, + { "[ISA] Sound Blaster 1.5", "sb1.5", &sb_15_device }, + { "[ISA] Sound Blaster 2.0", "sb2.0", &sb_2_device }, + { "[ISA] Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device }, + { "[ISA] Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device }, + { "[ISA] Sound Blaster 16", "sb16", &sb_16_device }, + { "[ISA] Sound Blaster AWE32", "sbawe32", &sb_awe32_device }, +#if defined(DEV_BRANCH) && defined(USE_PAS16) + { "[ISA] Pro Audio Spectrum 16","pas16", &pas16_device }, #endif + { "[ISA] Windows Sound System", "wss", &wss_device }, + { "[MCA] Adlib", "adlib_mca", &adlib_mca_device }, + { "[MCA] Sound Blaster MCV", "sbmcv", &sb_mcv_device }, + { "[MCA] Sound Blaster Pro MCV","sbpromcv", &sb_pro_mcv_device }, + { "[PCI] Ensoniq AudioPCI (ES1371)","es1371", &es1371_device}, + { "[PCI] Sound Blaster PCI 128", "sbpci128", &es1371_device}, { "", "", NULL } }; @@ -134,7 +136,7 @@ static struct static int sound_handlers_num; -static int sound_poll_time = 0, sound_poll_latch; +static int64_t sound_poll_time = 0LL, sound_poll_latch; int sound_pos_global = 0; int soundon = 1; @@ -401,7 +403,7 @@ void sound_poll(void *priv) void sound_speed_changed(void) { - sound_poll_latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); + sound_poll_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / 48000.0)); } void sound_reset(void) diff --git a/src/sound/sound.h b/src/sound/sound.h index 9afdaa902..53e043cb6 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -8,13 +8,16 @@ * * Sound emulation core. * - * Version: @(#)sound.h 1.0.1 2017/06/14 + * Version: @(#)sound.h 1.0.2 2017/10/04 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#ifndef EMU_SOUND_H +# define EMU_SOUND_H + void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p); @@ -22,7 +25,9 @@ extern int sound_card_current; int sound_card_available(int card); char *sound_card_getname(int card); -struct device_t *sound_card_getdevice(int card); +#ifdef EMU_DEVICE_H +device_t *sound_card_getdevice(int card); +#endif int sound_card_has_config(int card); char *sound_card_get_internal_name(int card); int sound_card_get_from_internal_name(char *s); @@ -48,3 +53,6 @@ void initalmain(int argc, char *argv[]); void inital(); void givealbuffer(void *buf); void givealbuffer_cd(void *buf); + + +#endif /*EMU_SOUND_H*/ diff --git a/src/tandy_eeprom.c b/src/tandy_eeprom.c index 8e9e9fc27..423b0e251 100644 --- a/src/tandy_eeprom.c +++ b/src/tandy_eeprom.c @@ -1,12 +1,17 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include #include +#include #include "ibm.h" #include "device.h" #include "mem.h" -#include "io.h" #include "rom.h" +#include "io.h" +#include "nvr.h" #include "tandy_eeprom.h" @@ -120,7 +125,7 @@ int tandy_eeprom_read(void) } -static void *tandy_eeprom_init(void) +static void *tandy_eeprom_init(device_t *info) { tandy_eeprom_t *eeprom = malloc(sizeof(tandy_eeprom_t)); FILE *f = NULL; @@ -131,10 +136,10 @@ static void *tandy_eeprom_init(void) switch (romset) { case ROM_TANDY1000HX: - f = nvrfopen(L"tandy1000hx.bin", L"rb"); + f = nvr_fopen(L"tandy1000hx.bin", L"rb"); break; case ROM_TANDY1000SL2: - f = nvrfopen(L"tandy1000sl2.bin", L"rb"); + f = nvr_fopen(L"tandy1000sl2.bin", L"rb"); break; } if (f) @@ -159,10 +164,10 @@ void tandy_eeprom_close(void *p) switch (eeprom->romset) { case ROM_TANDY1000HX: - f = nvrfopen(L"tandy1000hx.bin", L"wb"); + f = nvr_fopen(L"tandy1000hx.bin", L"wb"); break; case ROM_TANDY1000SL2: - f = nvrfopen(L"tandy1000sl2.bin", L"wb"); + f = nvr_fopen(L"tandy1000sl2.bin", L"wb"); break; } fwrite(eeprom->store, 128, 1, f); @@ -175,12 +180,9 @@ void tandy_eeprom_close(void *p) device_t tandy_eeprom_device = { "Tandy EEPROM", - 0, + 0, 0, tandy_eeprom_init, tandy_eeprom_close, - NULL, - NULL, - NULL, - NULL, + NULL, NULL, NULL, NULL, NULL, NULL }; diff --git a/src/tandy_rom.c b/src/tandy_rom.c index aa6ffb9fb..c2ba790ca 100644 --- a/src/tandy_rom.c +++ b/src/tandy_rom.c @@ -1,7 +1,11 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include +#include #include +#include #include "ibm.h" #include "device.h" #include "io.h" @@ -56,15 +60,15 @@ void tandy_rom_bank_write(uint16_t port, uint8_t val, void *p) } -void *tandy_rom_init(void) +void *tandy_rom_init(device_t *info) { FILE *f, *ff; int c; tandy_rom = malloc(0x80000); - f = romfopen(L"roms/machines/tandy1000sl2/8079047.hu1", L"rb"); - ff = romfopen(L"roms/machines/tandy1000sl2/8079048.hu2", L"rb"); + f = rom_fopen(L"roms/machines/tandy1000sl2/8079047.hu1", L"rb"); + ff = rom_fopen(L"roms/machines/tandy1000sl2/8079048.hu2", L"rb"); for (c = 0x0000; c < 0x80000; c += 2) { tandy_rom[c] = getc(f); @@ -93,12 +97,8 @@ void tandy_rom_close(void *p) device_t tandy_rom_device = { "Tandy 1000SL/2 ROM", - 0, - tandy_rom_init, - tandy_rom_close, - NULL, - NULL, - NULL, - NULL, + 0, 0, + tandy_rom_init, tandy_rom_close, NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/timer.c b/src/timer.c index 2f3a92035..8313ebed6 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,13 +1,8 @@ +#include +#include +#include +#include #include "ibm.h" -#if 0 -//FIXME: Kotori, do we need to keep this? --FvK -#include "sound_opl.h" -#include "adlibgold.h" -#include "sound_pas16.h" -#include "sound_sb.h" -#include "sound_sb_dsp.h" -#include "sound_wss.h" -#endif #include "timer.h" @@ -16,29 +11,29 @@ static struct { - int present; + int64_t present; void (*callback)(void *priv); void *priv; - int *enable; - int *count; + int64_t *enable; + int64_t *count; } timers[TIMERS_MAX]; -int TIMER_USEC; -int timers_present = 0; -int timer_one = 1; +int64_t TIMER_USEC; +int64_t timers_present = 0; +int64_t timer_one = 1; -int timer_count = 0, timer_latch = 0; -int timer_start = 0; +int64_t timer_count = 0, timer_latch = 0; +int64_t timer_start = 0; void timer_process(void) { - int c; - int process = 0; + int64_t c; + int64_t process = 0; /*Get actual elapsed time*/ - int diff = timer_latch - timer_count; - int enable[TIMERS_MAX]; + int64_t diff = timer_latch - timer_count; + int64_t enable[TIMERS_MAX]; timer_latch = 0; @@ -63,7 +58,7 @@ void timer_process(void) while (1) { - int lowest = 1, lowest_c; + int64_t lowest = 1, lowest_c; for (c = 0; c < timers_present; c++) { @@ -88,8 +83,8 @@ void timer_process(void) void timer_update_outstanding(void) { - int c; - timer_latch = 0x7fffffff; + int64_t c; + timer_latch = 0x7fffffffffffffff; for (c = 0; c < timers_present; c++) { if (*timers[c].enable && *timers[c].count < timer_latch) @@ -107,9 +102,9 @@ void timer_reset(void) } -int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv) +int64_t timer_add(void (*callback)(void *priv), int64_t *count, int64_t *enable, void *priv) { - int i = 0; + int64_t i = 0; if (timers_present < TIMERS_MAX) { @@ -137,7 +132,7 @@ int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv) } -void timer_set_callback(int timer, void (*callback)(void *priv)) +void timer_set_callback(int64_t timer, void (*callback)(void *priv)) { timers[timer].callback = callback; } diff --git a/src/timer.h b/src/timer.h index bdc77493b..5806a4b6b 100644 --- a/src/timer.h +++ b/src/timer.h @@ -2,7 +2,7 @@ #define _TIMER_H_ -extern int timer_start; +extern int64_t timer_start; #define timer_start_period(cycles) \ timer_start = cycles; @@ -10,7 +10,7 @@ extern int timer_start; #define timer_end_period(cycles) \ do \ { \ - int diff = timer_start - (cycles); \ + int64_t diff = timer_start - (cycles); \ timer_count -= diff; \ timer_start = cycles; \ if (timer_count <= 0) \ @@ -23,7 +23,7 @@ extern int timer_start; #define timer_clock() \ do \ { \ - int diff; \ + int64_t diff; \ if (AT) \ { \ diff = timer_start - (cycles << TIMER_SHIFT); \ @@ -42,16 +42,16 @@ extern int timer_start; extern void timer_process(void); extern void timer_update_outstanding(void); extern void timer_reset(void); -extern int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv); -extern void timer_set_callback(int timer, void (*callback)(void *priv)); +extern int64_t timer_add(void (*callback)(void *priv), int64_t *count, int64_t *enable, void *priv); +extern void timer_set_callback(int64_t timer, void (*callback)(void *priv)); #define TIMER_ALWAYS_ENABLED &timer_one -extern int timer_count; -extern int timer_one; +extern int64_t timer_count; +extern int64_t timer_one; #define TIMER_SHIFT 6 -extern int TIMER_USEC; +extern int64_t TIMER_USEC; #endif /*_TIMER_H_*/ diff --git a/src/ui.h b/src/ui.h new file mode 100644 index 000000000..6b32fd7d4 --- /dev/null +++ b/src/ui.h @@ -0,0 +1,69 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Define the various UI functions. + * + * Version: @(#)ui.h 1.0.3 2017/10/14 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#ifndef EMU_UI_H +# define EMU_UI_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Strings. Those are defined within the platform. */ +#ifdef WIN32 +# include "win/resource.h" +#else +# include "lnx/strings.h" +#endif + + +/* Message Box functions. */ +#define MBX_INFO 1 +#define MBX_ERROR 2 +#define MBX_QUESTION 3 +#define MBX_FATAL 0x20 +#define MBX_ANSI 0x80 + +extern int ui_msgbox(int type, void *arg); + + +/* Status Bar functions. */ +#define SB_ICON_WIDTH 24 +#define SB_FLOPPY 0x00 +#define SB_CDROM 0x10 +#define SB_RDISK 0x20 +#define SB_HDD 0x40 +#define SB_NETWORK 0x50 +#define SB_TEXT 0x60 + +extern int ui_sb_find_part(int tag); +extern void ui_sb_update_panes(void); +extern void ui_sb_update_tip(int meaning); +extern void ui_sb_check_menu_item(int tag, int id, int chk); +extern void ui_sb_enable_menu_item(int tag, int id, int val); +extern void ui_sb_update_icon(int tag, int val); +extern void ui_sb_update_icon_state(int tag, int active); +extern void ui_sb_set_text_w(wchar_t *wstr); +extern void ui_sb_set_text(char *str); + +#ifdef __cplusplus +} +#endif + + +#endif /*EMU_UI_H*/ diff --git a/src/usb.c b/src/usb.c index 58a507216..a1638b2bb 100644 --- a/src/usb.c +++ b/src/usb.c @@ -1,7 +1,10 @@ /* Copyright holders: Melissa Goad see COPYING for more details */ +#include #include +#include +#include #include "ibm.h" #include "io.h" #include "mem.h" diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index 8cbb5c9c7..8794af217 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -1,8 +1,26 @@ -/* Copyright holders: Sarah Walker, Melissa Goad - see COPYING for more details -*/ -/*ATI 18800 emulation (VGA Edge-16)*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ATI 18800 emulation (VGA Edge-16) + * + * Version: @(#)vid_ati18800.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -25,7 +43,8 @@ typedef struct ati18800_t int index; } ati18800_t; -void ati18800_out(uint16_t addr, uint8_t val, void *p) + +static void ati18800_out(uint16_t addr, uint8_t val, void *p) { ati18800_t *ati18800 = (ati18800_t *)p; svga_t *svga = &ati18800->svga; @@ -99,7 +118,7 @@ void ati18800_out(uint16_t addr, uint8_t val, void *p) svga_out(addr, val, svga); } -uint8_t ati18800_in(uint16_t addr, void *p) +static uint8_t ati18800_in(uint16_t addr, void *p) { ati18800_t *ati18800 = (ati18800_t *)p; svga_t *svga = &ati18800->svga; @@ -158,7 +177,7 @@ void ati18800_recalctimings(svga_t *svga) } } -void *ati18800_init() +static void *ati18800_init(device_t *info) { ati18800_t *ati18800 = malloc(sizeof(ati18800_t)); memset(ati18800, 0, sizeof(ati18800_t)); @@ -181,12 +200,12 @@ void *ati18800_init() return ati18800; } -static int ati18800_available() +static int ati18800_available(void) { return rom_present(L"roms/video/ati18800/vga88.BIN"); } -void ati18800_close(void *p) +static void ati18800_close(void *p) { ati18800_t *ati18800 = (ati18800_t *)p; @@ -195,21 +214,21 @@ void ati18800_close(void *p) free(ati18800); } -void ati18800_speed_changed(void *p) +static void ati18800_speed_changed(void *p) { ati18800_t *ati18800 = (ati18800_t *)p; svga_recalctimings(&ati18800->svga); } -void ati18800_force_redraw(void *p) +static void ati18800_force_redraw(void *p) { ati18800_t *ati18800 = (ati18800_t *)p; ati18800->svga.fullchange = changeframecount; } -void ati18800_add_status_info(char *s, int max_len, void *p) +static void ati18800_add_status_info(char *s, int max_len, void *p) { ati18800_t *ati18800 = (ati18800_t *)p; @@ -219,12 +238,13 @@ void ati18800_add_status_info(char *s, int max_len, void *p) device_t ati18800_device = { "ATI-18800", - 0, + DEVICE_ISA, 0, ati18800_init, ati18800_close, + NULL, ati18800_available, ati18800_speed_changed, ati18800_force_redraw, - ati18800_add_status_info + ati18800_add_status_info, + NULL }; - diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 078ea47bf..99709def8 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -1,8 +1,26 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -/*ATI 28800 emulation (VGA Charger)*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ATI 28800 emulation (VGA Charger) + * + * Version: @(#)vid_ati28800.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -27,9 +45,11 @@ typedef struct ati28800_t int index; } ati28800_t; -void ati28800_svga_recalctimings(ati28800_t *ati28800); -void ati28800_out(uint16_t addr, uint8_t val, void *p) +static void ati28800_svga_recalctimings(ati28800_t *ati28800); + + +static void ati28800_out(uint16_t addr, uint8_t val, void *p) { ati28800_t *ati28800 = (ati28800_t *)p; svga_t *svga = &ati28800->svga; @@ -97,7 +117,7 @@ void ati28800_out(uint16_t addr, uint8_t val, void *p) svga_out(addr, val, svga); } -uint8_t ati28800_in(uint16_t addr, void *p) +static uint8_t ati28800_in(uint16_t addr, void *p) { ati28800_t *ati28800 = (ati28800_t *)p; svga_t *svga = &ati28800->svga; @@ -151,7 +171,7 @@ uint8_t ati28800_in(uint16_t addr, void *p) return temp; } -void ati28800_svga_recalctimings(ati28800_t *ati28800) +static void ati28800_svga_recalctimings(ati28800_t *ati28800) { double crtcconst; double _dispontime, _dispofftime, disptime; @@ -303,7 +323,8 @@ void ati28800_svga_recalctimings(ati28800_t *ati28800) pclog("svga->render %08X\n", svga->render);*/ } -void ati28800_recalctimings(svga_t *svga) + +static void ati28800_recalctimings(svga_t *svga) { ati28800_t *ati28800 = (ati28800_t *)svga->p; uint8_t clock_sel = (svga->miscout >> 2) & 3; @@ -350,7 +371,7 @@ void ati28800_recalctimings(svga_t *svga) } } -void *ati28800_init() +static void *ati28800_init(device_t *info) { uint32_t memory = 512; ati28800_t *ati28800; @@ -392,22 +413,22 @@ void *ati28800_init() return ati28800; } -static int ati28800_available() +static int ati28800_available(void) { return rom_present(L"roms/video/ati28800/bios.bin"); } -static int compaq_ati28800_available() +static int compaq_ati28800_available(void) { return (rom_present(L"roms/video/ati28800/XLEVEN.bin") && rom_present(L"roms/video/ati28800/XLODD.bin")); } -static int ati28800_wonderxl24_available() +static int ati28800_wonderxl24_available(void) { return (rom_present(L"roms/video/ati28800/112-14318-102.bin") && rom_present(L"roms/video/ati28800/112-14319-102.bin")); } -void ati28800_close(void *p) +static void ati28800_close(void *p) { ati28800_t *ati28800 = (ati28800_t *)p; @@ -416,21 +437,21 @@ void ati28800_close(void *p) free(ati28800); } -void ati28800_speed_changed(void *p) +static void ati28800_speed_changed(void *p) { ati28800_t *ati28800 = (ati28800_t *)p; ati28800_svga_recalctimings(ati28800); } -void ati28800_force_redraw(void *p) +static void ati28800_force_redraw(void *p) { ati28800_t *ati28800 = (ati28800_t *)p; ati28800->svga.fullchange = changeframecount; } -void ati28800_add_status_info(char *s, int max_len, void *p) +static void ati28800_add_status_info(char *s, int max_len, void *p) { ati28800_t *ati28800 = (ati28800_t *)p; @@ -485,9 +506,11 @@ static device_config_t ati28800_wonderxl_config[] = device_t ati28800_device = { "ATI-28800", - 0, + DEVICE_ISA, + 0, ati28800_init, ati28800_close, + NULL, ati28800_available, ati28800_speed_changed, ati28800_force_redraw, @@ -498,9 +521,11 @@ device_t ati28800_device = device_t compaq_ati28800_device = { "Compaq ATI-28800", - 0, + DEVICE_ISA, + 0, ati28800_init, ati28800_close, + NULL, compaq_ati28800_available, ati28800_speed_changed, ati28800_force_redraw, @@ -511,9 +536,11 @@ device_t compaq_ati28800_device = device_t ati28800_wonderxl24_device = { "ATI-28800 (VGA Wonder XL24)", - 0, + DEVICE_ISA, + 0, ati28800_init, ati28800_close, + NULL, ati28800_wonderxl24_available, ati28800_speed_changed, ati28800_force_redraw, diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index f1d1d6b84..c82dbc4bc 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -1,26 +1,45 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*ATI 68860 RAMDAC emulation (for Mach64)*/ /* -ATI 68860/68880 Truecolor DACs: -REG08 (R/W): -bit 0-? Always 2 ?? - -REG0A (R/W): -bit 0-? Always 1Dh ?? - -REG0B (R/W): (GMR ?) -bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp, A0h: 15bpp, A1h: 16bpp, C0h: 24bpp, - E3h: 32bpp (80h for VGA modes ?) - -REG0C (R/W): Device Setup Register A -bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT - 2-3 Depends on Video memory (= VRAM width ?) . 1: Less than 1Mb, 2: 1Mb, - 3: > 1Mb - 5-6 Always set ? - 7 If set can remove "snow" in some cases (A860_Delay_L ?) ?? -*/ + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ATI 68860 RAMDAC emulation (for Mach64) + * + * ATI 68860/68880 Truecolor DACs: + * REG08 (R/W): + * bit 0-? Always 2 ?? + * + * REG0A (R/W): + * bit 0-? Always 1Dh ?? + * + * REG0B (R/W): (GMR ?) + * bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp, + * A0h: 15bpp, A1h: 16bpp, C0h: 24bpp, + * E3h: 32bpp (80h for VGA modes ?) + * + * REG0C (R/W): Device Setup Register A + * bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT + * 2-3 Depends on Video memory (= VRAM width ?) . + * 1: Less than 1Mb, 2: 1Mb, 3: > 1Mb + * 5-6 Always set ? + * 7 If set can remove "snow" in some cases + * (A860_Delay_L ?) ?? + * + * Version: @(#)vid_ati68860.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "video.h" diff --git a/src/video/vid_ati_eeprom.c b/src/video/vid_ati_eeprom.c index 198575a60..b2d5ae6c8 100644 --- a/src/video/vid_ati_eeprom.c +++ b/src/video/vid_ati_eeprom.c @@ -1,9 +1,28 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the EEPROM on select ATI cards. + * + * Version: @(#)vid_ati_eeprom.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" -#include "../rom.h" +#include "../nvr.h" #include "vid_ati_eeprom.h" @@ -39,7 +58,7 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type) FILE *f; eeprom->type = type; wcscpy(eeprom->fn, fn); - f = nvrfopen(eeprom->fn, L"rb"); + f = nvr_fopen(eeprom->fn, L"rb"); if (!f) { memset(eeprom->data, 0, eeprom->type ? 512 : 128); @@ -51,7 +70,7 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type) void ati_eeprom_save(ati_eeprom_t *eeprom) { - FILE *f = nvrfopen(eeprom->fn, L"wb"); + FILE *f = nvr_fopen(eeprom->fn, L"wb"); if (!f) return; fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f); fclose(f); diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 824b9a11e..3f707d8cf 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -8,21 +8,26 @@ * * ATi Mach64 graphics card emulation. * - * Version: @(#)vid_ati_mach64.c 1.0.1 2017/06/04 + * Version: @(#)vid_ati_mach64.c 1.0.4 2017/10/10 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../device.h" #include "../io.h" #include "../mem.h" #include "../pci.h" #include "../rom.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -81,7 +86,7 @@ typedef struct mach64_t uint8_t regs[256]; int index; - + int type; uint8_t pci_regs[256]; @@ -3290,7 +3295,7 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p) } } -static void *mach64_common_init() +static void *mach64_common_init(device_t *info) { mach64_t *mach64 = malloc(sizeof(mach64_t)); memset(mach64, 0, sizeof(mach64_t)); @@ -3304,7 +3309,7 @@ static void *mach64_common_init() mach64_hwcursor_draw, mach64_overlay_draw); - if (PCI) + if (info->flags & DEVICE_PCI) mem_mapping_disable(&mach64->bios_rom.mapping); mem_mapping_add(&mach64->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &mach64->svga); @@ -3315,12 +3320,15 @@ static void *mach64_common_init() mach64_io_set(mach64); - mach64->card = pci_add_card(PCI_ADD_VIDEO, mach64_pci_read, mach64_pci_write, mach64); + if (info->flags & DEVICE_PCI) + { + mach64->card = pci_add_card(PCI_ADD_VIDEO, mach64_pci_read, mach64_pci_write, mach64); + } mach64->pci_regs[PCI_REG_COMMAND] = 3; - mach64->pci_regs[0x30] = 0x00; + mach64->pci_regs[0x30] = 0x00; mach64->pci_regs[0x32] = 0x0c; - mach64->pci_regs[0x33] = 0x00; + mach64->pci_regs[0x33] = 0x00; ati68860_ramdac_init(&mach64->ramdac); @@ -3333,16 +3341,16 @@ static void *mach64_common_init() return mach64; } -static void *mach64gx_init() +static void *mach64gx_init(device_t *info) { - mach64_t *mach64 = mach64_common_init(); + mach64_t *mach64 = mach64_common_init(info); mach64->type = MACH64_GX; mach64->pci_id = (int)'X' | ((int)'G' << 8); mach64->config_chip_id = 0x020000d7; mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/ mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI-68860, 256Kx16 DRAM*/ - if (PCI) + if (info->flags & DEVICE_PCI) mach64->config_stat0 |= 0; /*PCI, 256Kx16 DRAM*/ else mach64->config_stat0 |= 1; /*VLB, 256Kx16 DRAM*/ @@ -3353,9 +3361,9 @@ static void *mach64gx_init() return mach64; } -static void *mach64vt2_init() +static void *mach64vt2_init(device_t *info) { - mach64_t *mach64 = mach64_common_init(); + mach64_t *mach64 = mach64_common_init(info); svga_t *svga = &mach64->svga; mach64->type = MACH64_VT2; @@ -3374,11 +3382,11 @@ static void *mach64vt2_init() return mach64; } -int mach64gx_available() +int mach64gx_available(void) { return rom_present(L"roms/video/mach64/bios.bin"); } -int mach64vt2_available() +int mach64vt2_available(void) { return rom_present(L"roms/video/mach64/atimach64vt2pci.bin"); } @@ -3503,24 +3511,44 @@ static device_config_t mach64vt2_config[] = } }; -device_t mach64gx_device = +device_t mach64gx_vlb_device = { - "ATI Mach64GX", - 0, + "ATI Mach64GX VLB", + DEVICE_VLB, + 0, mach64gx_init, mach64_close, + NULL, mach64gx_available, mach64_speed_changed, mach64_force_redraw, mach64_add_status_info, mach64gx_config }; + +device_t mach64gx_pci_device = +{ + "ATI Mach64GX PCI", + DEVICE_PCI, + 0, + mach64gx_init, + mach64_close, + NULL, + mach64gx_available, + mach64_speed_changed, + mach64_force_redraw, + mach64_add_status_info, + mach64gx_config +}; + device_t mach64vt2_device = { "ATI Mach64VT2", DEVICE_PCI, + 0, mach64vt2_init, mach64_close, + NULL, mach64vt2_available, mach64_speed_changed, mach64_force_redraw, diff --git a/src/video/vid_ati_mach64.h b/src/video/vid_ati_mach64.h index c159a6b57..755619050 100644 --- a/src/video/vid_ati_mach64.h +++ b/src/video/vid_ati_mach64.h @@ -16,5 +16,6 @@ * Copyright 2016-2017 Miran Grca. */ -extern device_t mach64gx_device; +extern device_t mach64gx_vlb_device; +extern device_t mach64gx_pci_device; extern device_t mach64vt2_device; diff --git a/src/video/vid_bt485_ramdac.c b/src/video/vid_bt485_ramdac.c index e11f69132..ee97b6d60 100644 --- a/src/video/vid_bt485_ramdac.c +++ b/src/video/vid_bt485_ramdac.c @@ -1,8 +1,28 @@ -/* Copyright holders: Tenshi - see COPYING for more details -*/ -/*Brooktree BT485 true colour RAMDAC emulation*/ -/*Currently only a dummy stub for logging and passing output to the generic SVGA handler*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Brooktree BT485 true colour RAMDAC emulation. + * + * Currently only a dummy stub for logging and passing output + * to the generic SVGA handler. + * + * Version: @(#)vid_bt485_ramdac.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "video.h" diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 2bb16be22..384a0a5c5 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -8,28 +8,29 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.c 1.0.0 2017/05/30 + * Version: @(#)vid_cga.c 1.0.5 2017/10/13 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - -/*CGA emulation*/ +#include +#include +#include #include +#include #include #include "../ibm.h" #include "../io.h" #include "../mem.h" +#include "../rom.h" #include "../timer.h" #include "../device.h" #include "video.h" #include "vid_cga.h" #include "vid_cga_comp.h" -#ifndef __unix -# include "../win/win_cgapal.h" /*YUCK*/ -#endif #define CGA_RGB 0 @@ -73,13 +74,13 @@ void cga_out(uint16_t addr, uint8_t val, void *p) cga->cgamode = val; update_cga16_color(cga->cgamode); } -#ifndef __unix + if ((cga->cgamode ^ val) & 1) { cga_palette = (cga->rgb_type << 1); cgapal_rebuild(); } -#endif + cga->cgamode = val; return; case 0x3D9: @@ -151,8 +152,8 @@ void cga_recalctimings(cga_t *cga) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - cga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - cga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + cga->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + cga->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); } void cga_poll(void *p) @@ -465,7 +466,7 @@ void cga_init(cga_t *cga) cga->composite = 0; } -void *cga_standalone_init() +void *cga_standalone_init(device_t *info) { int display_type; cga_t *cga = malloc(sizeof(cga_t)); @@ -477,7 +478,7 @@ void *cga_standalone_init() cga->snow_enabled = device_get_config_int("snow_enabled"); cga->vram = malloc(0x4000); - + cga_comp_init(cga->revision); timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, cga); @@ -485,12 +486,10 @@ void *cga_standalone_init() overscan_x = overscan_y = 16; -#ifndef __unix cga->rgb_type = device_get_config_int("rgb_type"); cga_palette = (cga->rgb_type << 1); cgapal_rebuild(); -#endif - + return cga; } @@ -505,7 +504,7 @@ void cga_close(void *p) void cga_speed_changed(void *p) { cga_t *cga = (cga_t *)p; - + cga_recalctimings(cga); } @@ -539,7 +538,6 @@ static device_config_t cga_config[] = } } }, -#ifndef __unix { "rgb_type", "RGB type", CONFIG_SELECTION, "", 0, { @@ -563,7 +561,6 @@ static device_config_t cga_config[] = } } }, -#endif { "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 }, @@ -575,9 +572,10 @@ static device_config_t cga_config[] = device_t cga_device = { "CGA", - 0, + DEVICE_ISA, 0, cga_standalone_init, cga_close, + NULL, NULL, cga_speed_changed, NULL, diff --git a/src/video/vid_cga.h b/src/video/vid_cga.h index bd8d5dbc5..4ef61c4e2 100644 --- a/src/video/vid_cga.h +++ b/src/video/vid_cga.h @@ -35,8 +35,8 @@ typedef struct cga_t uint16_t ma, maback; int oddeven; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int firstline, lastline; @@ -49,9 +49,7 @@ typedef struct cga_t int revision; int composite; int snow_enabled; -#ifndef __unix int rgb_type; -#endif } cga_t; void cga_init(cga_t *cga); diff --git a/src/video/vid_cga_comp.c b/src/video/vid_cga_comp.c index 513788bec..407e38726 100644 --- a/src/video/vid_cga_comp.c +++ b/src/video/vid_cga_comp.c @@ -9,18 +9,20 @@ * IBM CGA composite filter, borrowed from reenigne's DOSBox * patch and ported to C. * - * Version: @(#)vid_cga.c 1.0.0 2017/05/30 + * Version: @(#)vid_cga_comp.c 1.0.2 2017/10/10 * - * Author: reenigne, + * Authors: reenigne, * Miran Grca, + * * Copyright 2015-2017 reenigne. * Copyright 2015-2017 Miran Grca. */ - -#include +#include #include +#include +#include +#include #include - #include "../ibm.h" #include "../device.h" #include "../mem.h" diff --git a/src/video/vid_cl_gd.c b/src/video/vid_cl_gd.c index 1d6932364..ffb58f4b3 100644 --- a/src/video/vid_cl_gd.c +++ b/src/video/vid_cl_gd.c @@ -1,5 +1,26 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of select Cirrus Logic cards. + * + * Version: @(#)vid_cl_gd.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ #include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -879,92 +900,93 @@ void *clgd_common_init(wchar_t *romfn, uint8_t id) return clgd; } -void *gd6235_init() + +void *gd6235_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/vga6235.rom", CIRRUS_ID_CLGD6235); } -void *gd5422_init() +void *gd5422_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/CL5422.ROM", CIRRUS_ID_CLGD5422); } -void *gd5429_init() +void *gd5429_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/5429.vbi", CIRRUS_ID_CLGD5429); } -void *gd5430_init() +void *gd5430_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/pci.BIN", CIRRUS_ID_CLGD5430); } -void *dia5430_init() +void *dia5430_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/diamondvlbus.BIN", CIRRUS_ID_CLGD5430); } -void *gd5434_init() +void *gd5434_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/japan.BIN", CIRRUS_ID_CLGD5434); } -void *gd5436_init() +void *gd5436_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/5436.VBI", CIRRUS_ID_CLGD5436); } -void *gd5440_init() +void *gd5440_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/5440BIOS.BIN", CIRRUS_ID_CLGD5440); } -void *gd5446_init() +void *gd5446_init(device_t *info) { return clgd_common_init(L"roms/video/cirruslogic/5446BV.VBI", CIRRUS_ID_CLGD5446); } -static int gd5422_available() +static int gd5422_available(void) { return rom_present(L"roms/video/cirruslogic/CL5422.ROM"); } -static int gd5429_available() +static int gd5429_available(void) { return rom_present(L"roms/video/cirruslogic/5429.vbi"); } -static int gd5430_available() +static int gd5430_available(void) { return rom_present(L"roms/video/cirruslogic/pci.BIN"); } -static int dia5430_available() +static int dia5430_available(void) { return rom_present(L"roms/video/cirruslogic/diamondvlbus.BIN"); } -static int gd5434_available() +static int gd5434_available(void) { return rom_present(L"roms/video/cirruslogic/japan.BIN"); } -static int gd5436_available() +static int gd5436_available(void) { return rom_present(L"roms/video/cirruslogic/5436.VBI"); } -static int gd5440_available() +static int gd5440_available(void) { return rom_present(L"roms/video/cirruslogic/5440BIOS.BIN"); } -static int gd5446_available() +static int gd5446_available(void) { return rom_present(L"roms/video/cirruslogic/5446BV.VBI"); } -static int gd6235_available() +static int gd6235_available(void) { return rom_present(L"roms/video/cirruslogic/vga6235.rom"); } @@ -1002,116 +1024,134 @@ void clgd_add_status_info(char *s, int max_len, void *p) device_t gd5422_device = { "Cirrus Logic GD5422", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, gd5422_init, clgd_close, + NULL, gd5422_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; device_t gd5429_device = { "Cirrus Logic GD5429", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, gd5429_init, clgd_close, + NULL, gd5429_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; device_t gd5430_device = { "Cirrus Logic GD5430", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, gd5430_init, clgd_close, + NULL, gd5430_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; device_t dia5430_device = { "Diamond CL-GD5430", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, dia5430_init, clgd_close, + NULL, dia5430_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; device_t gd5434_device = { "Cirrus Logic GD5434", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, gd5434_init, clgd_close, + NULL, gd5434_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; device_t gd5436_device = { "Cirrus Logic GD5436", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, gd5436_init, clgd_close, + NULL, gd5436_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; device_t gd5440_device = { "Cirrus Logic GD5440", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, gd5440_init, clgd_close, + NULL, gd5440_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; device_t gd5446_device = { "Cirrus Logic GD5446", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, gd5446_init, clgd_close, + NULL, gd5446_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; device_t gd6235_device = { "Cirrus Logic GD6235", - // DEVICE_NOT_WORKING, + DEVICE_ISA | DEVICE_NOT_WORKING, 0, gd6235_init, clgd_close, + NULL, gd6235_available, clgd_speed_changed, clgd_force_redraw, - clgd_add_status_info + clgd_add_status_info, + NULL }; diff --git a/src/video/vid_cl_gd_blit.c b/src/video/vid_cl_gd_blit.c index 472c1aa84..28c58b692 100644 --- a/src/video/vid_cl_gd_blit.c +++ b/src/video/vid_cl_gd_blit.c @@ -1,5 +1,24 @@ -/*This is the CL-GD 5446 blitter, directly from QEMU*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * This is the CL-GD 5446 blitter, directly from QEMU. + * + * Version: @(#)vid_cl_gd_blit.c 1.0.1 2017/10/10 + * + * Author: Miran Grca, + * + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" diff --git a/src/video/vid_cl_ramdac.c b/src/video/vid_cl_ramdac.c index 340d27c88..d33d0a7eb 100644 --- a/src/video/vid_cl_ramdac.c +++ b/src/video/vid_cl_ramdac.c @@ -1,3 +1,23 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Cirrus Logic RAMDAC. + * + * Version: @(#)vid_cl_ramdac.c 1.0.1 2017/10/10 + * + * Author: Miran Grca, + * + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "../rom.h" diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index ab07127f7..df85e2f9e 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -1,5 +1,26 @@ -/*Plantronics ColorPlus emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Plantronics ColorPlus emulation. + * + * Version: @(#)vid_colorplus.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include #include "../ibm.h" #include "../io.h" @@ -361,7 +382,7 @@ void colorplus_init(colorplus_t *colorplus) cga_init(&colorplus->cga); } -void *colorplus_standalone_init() +void *colorplus_standalone_init(device_t *info) { int display_type; @@ -441,10 +462,10 @@ static device_config_t colorplus_config[] = device_t colorplus_device = { "Colorplus", - 0, + DEVICE_ISA, 0, colorplus_standalone_init, colorplus_close, - NULL, + NULL, NULL, colorplus_speed_changed, NULL, NULL, diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 689080026..b199431f1 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -9,18 +9,20 @@ * Emulation of the EGA, Chips & Technologies SuperEGA, and * AX JEGA graphics cards. * - * Version: @(#)vid_ega.c 1.0.3 2017/07/21 + * Version: @(#)vid_ega.c 1.0.6 2017/10/10 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, - * akm, + * akm + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. - * Copyright 2017-2017 akm. + * Copyright 2016,2017 Miran Grca. */ - +#include #include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -510,8 +512,8 @@ void ega_recalctimings(ega_t *ega) _dispontime *= crtcconst; _dispofftime *= crtcconst; - ega->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - ega->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + ega->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + ega->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); } void ega_poll(void *p) @@ -1063,10 +1065,10 @@ void *ega_standalone_init() } ega->crtc[0] = 63; - ega->dispontime = 1000 * (1 << TIMER_SHIFT); - ega->dispofftime = 1000 * (1 << TIMER_SHIFT); - ega->dispontime <<= 1; - ega->dispofftime <<= 1; + ega->dispontime = 1000LL * (1LL << TIMER_SHIFT); + ega->dispofftime = 1000LL * (1LL << TIMER_SHIFT); + ega->dispontime <<= 1LL; + ega->dispofftime <<= 1LL; ega_init(ega); @@ -1120,7 +1122,7 @@ void *cpqega_standalone_init() return ega; } -void *sega_standalone_init() +void *sega_standalone_init(device_t *info) { ega_t *ega = malloc(sizeof(ega_t)); memset(ega, 0, sizeof(ega_t)); @@ -1254,7 +1256,7 @@ static void LoadFontxFile(wchar_t *fname) fclose(mfile); } -void *jega_standalone_init() +void *jega_standalone_init(device_t *info) { ega_t *ega = (ega_t *) sega_standalone_init(); @@ -1267,17 +1269,17 @@ void *jega_standalone_init() } #endif -static int ega_standalone_available() +static int ega_standalone_available(void) { return rom_present(L"roms/video/ega/ibm_6277356_ega_card_u44_27128.bin"); } -static int cpqega_standalone_available() +static int cpqega_standalone_available(void) { return rom_present(L"roms/video/ega/108281-001.bin"); } -static int sega_standalone_available() +static int sega_standalone_available(void) { return rom_present(L"roms/video/ega/lega.vbi"); } @@ -1324,9 +1326,11 @@ static device_config_t ega_config[] = device_t ega_device = { "EGA", - 0, + DEVICE_ISA, + 0, ega_standalone_init, ega_close, + NULL, ega_standalone_available, ega_speed_changed, NULL, @@ -1337,9 +1341,11 @@ device_t ega_device = device_t cpqega_device = { "Compaq EGA", - 0, + DEVICE_ISA, + 0, cpqega_standalone_init, ega_close, + NULL, cpqega_standalone_available, ega_speed_changed, NULL, @@ -1350,9 +1356,11 @@ device_t cpqega_device = device_t sega_device = { "SuperEGA", - 0, + DEVICE_ISA, + 0, sega_standalone_init, ega_close, + NULL, sega_standalone_available, ega_speed_changed, NULL, @@ -1364,9 +1372,11 @@ device_t sega_device = device_t jega_device = { "AX JEGA", - 0, + DEVICE_ISA, + 0, jega_standalone_init, ega_close, + NULL, sega_standalone_available, ega_speed_changed, NULL, diff --git a/src/video/vid_ega.h b/src/video/vid_ega.h index e9835d1fb..13fbde8ac 100644 --- a/src/video/vid_ega.h +++ b/src/video/vid_ega.h @@ -65,8 +65,8 @@ typedef struct ega_t int vres; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; uint8_t scrblank; diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 50ef6139e..2e6ca4357 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -8,15 +8,18 @@ * * EGA renderers. * - * Version: @(#)vid_ega_render.c 1.0.1 2017/06/05 + * Version: @(#)vid_ega_render.c 1.0.3 2017/10/10 * * Author: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - #include +#include +#include +#include #include "../ibm.h" #include "../device.h" #include "../mem.h" diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 3ea60d376..3b809da20 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -1,8 +1,26 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*ET4000 emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Tseng Labs ET4000. + * + * Version: @(#)vid_et4000.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -139,7 +157,7 @@ void et4000_recalctimings(svga_t *svga) } } -void *et4000_init() +void *et4000_init(device_t *info) { et4000_t *et4000 = malloc(sizeof(et4000_t)); memset(et4000, 0, sizeof(et4000_t)); @@ -157,7 +175,7 @@ void *et4000_init() return et4000; } -static int et4000_available() +static int et4000_available(void) { return rom_present(L"roms/video/et4000/et4000.BIN"); } @@ -195,9 +213,11 @@ void et4000_add_status_info(char *s, int max_len, void *p) device_t et4000_device = { "Tseng Labs ET4000AX", - 0, + DEVICE_ISA, + 0, et4000_init, et4000_close, + NULL, et4000_available, et4000_speed_changed, et4000_force_redraw, diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c01cf1810..fda5e2ff1 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -1,16 +1,35 @@ -/*ET4000/W32p emulation (Diamond Stealth 32)*/ -/*Known bugs : - - - Accelerator doesn't work in planar modes -*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ET4000/W32p emulation (Diamond Stealth 32) + * + * Known bugs: Accelerator doesn't work in planar modes + * + * Version: @(#)vid_et4000w32.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" #include "../pci.h" #include "../rom.h" #include "../device.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_icd2061.h" @@ -53,6 +72,7 @@ typedef struct et4000w32p_t icd2061_t icd2061; int index; + int pci; uint8_t regs[256]; uint32_t linearbase, linearbase_old; @@ -173,7 +193,7 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) } if (svga->crtcreg == 0x30) { - if (PCI) + if (et4000->pci) { et4000->linearbase &= 0xc0000000; et4000->linearbase = (val & 0xfc) << 22; @@ -244,8 +264,8 @@ uint8_t et4000w32p_in(uint16_t addr, void *p) return (et4000->regs[0xec] & 0xf) | 0x60; /*ET4000/W32p rev D*/ if (et4000->index == 0xef) { - if (PCI) return et4000->regs[0xef] | 0xe0; /*PCI*/ - else return et4000->regs[0xef] | 0x60; /*VESA local bus*/ + if (et4000->pci) return et4000->regs[0xef] | 0xe0; /*PCI*/ + else return et4000->regs[0xef] | 0x60; /*VESA local bus*/ } return et4000->regs[et4000->index]; } @@ -1136,7 +1156,7 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) } } -void *et4000w32p_init() +void *et4000w32p_init(device_t *info) { int vram_size; et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t)); @@ -1153,7 +1173,8 @@ void *et4000w32p_init() NULL); rom_init(&et4000->bios_rom, L"roms/video/et4000w32/et4000w32.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (PCI) + et4000->pci = !!(info->flags & DEVICE_PCI); + if (info->flags & DEVICE_PCI) mem_mapping_disable(&et4000->bios_rom.mapping); mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &et4000->svga); @@ -1161,7 +1182,8 @@ void *et4000w32p_init() et4000w32p_io_set(et4000); - pci_add_card(PCI_ADD_VIDEO, et4000w32p_pci_read, et4000w32p_pci_write, et4000); + if (info->flags & DEVICE_PCI) + pci_add_card(PCI_ADD_VIDEO, et4000w32p_pci_read, et4000w32p_pci_write, et4000); /* Hardwired bits: 00000000 1xx0x0xx */ /* R/W bits: xx xxxx */ @@ -1185,7 +1207,7 @@ void *et4000w32p_init() return et4000; } -int et4000w32p_available() +int et4000w32p_available(void) { return rom_present(L"roms/video/et4000w32/et4000w32.bin"); } @@ -1254,12 +1276,29 @@ static device_config_t et4000w32p_config[] = } }; -device_t et4000w32p_device = +device_t et4000w32p_vlb_device = { - "Tseng Labs ET4000/w32p", - 0, + "Tseng Labs ET4000/w32p VLB", + DEVICE_VLB, + 0, et4000w32p_init, et4000w32p_close, + NULL, + et4000w32p_available, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + et4000w32p_add_status_info, + et4000w32p_config +}; + +device_t et4000w32p_pci_device = +{ + "Tseng Labs ET4000/w32p PCI", + DEVICE_PCI, + 0, + et4000w32p_init, + et4000w32p_close, + NULL, et4000w32p_available, et4000w32p_speed_changed, et4000w32p_force_redraw, diff --git a/src/video/vid_et4000w32.h b/src/video/vid_et4000w32.h index 32a344259..4f62b98cb 100644 --- a/src/video/vid_et4000w32.h +++ b/src/video/vid_et4000w32.h @@ -1 +1,2 @@ -extern device_t et4000w32p_device; +extern device_t et4000w32p_vlb_device; +extern device_t et4000w32p_pci_device; diff --git a/src/video/vid_et4000w32i.c b/src/video/vid_et4000w32i.c index 62988adb9..d4208eaa2 100644 --- a/src/video/vid_et4000w32i.c +++ b/src/video/vid_et4000w32i.c @@ -1,14 +1,31 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*The below is (with some removals) a reasonable emulation of the ET4000/W32i blitter. - Unfortunately the Diamond Stealth 32 is actually an ET4000/W32p! Which has a different - blitter. If only I'd dug out and looked at the card before trying to emulate it. - - This might be of use for an attempt at emulating an ET4000/W32i. - */ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * The below is (with some removals) a reasonable emulation + * of the ET4000/W32i blitter. Unfortunately the Diamond + * Stealth 32 is actually an ET4000/W32p! Which has a different + * blitter. If only I'd dug out and looked at the card before + * trying to emulate it. + * + * This might be of use for an attempt at an ET4000/W32i. + * + * Version: @(#)vid_et4000w32i.c 1.0.1 2017/10/10 + * + * Author: Sarah Walker, + * + * Copyright 2008-2017 Sarah Walker. + */ #if 0 +#include +#include +#include +#include #include "ibm.h" int et4k_b8000; diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index 5596d79c0..de2ac599c 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -1,11 +1,33 @@ -/* MDSI Genius VHR emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * MDSI Genius VHR emulation. + * + * Version: @(#)vid_genius.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" #include "../rom.h" #include "../timer.h" #include "../device.h" +#include "../plat.h" #include "video.h" #include "vid_genius.h" @@ -14,10 +36,9 @@ #define GENIUS_YSIZE 1008 -void updatewindowsize(int x, int y); - extern uint8_t fontdat8x12[256][16]; + /* I'm at something of a disadvantage writing this emulation: I don't have an * MDSI Genius card, nor do I have the BIOS extension (VHRBIOS.SYS) that came * with it. What I do have are the GEM and Windows 1.04 drivers, plus a driver @@ -99,13 +120,13 @@ typedef struct genius_t int enabled; /* Display enabled, 0 or 1 */ int detach; /* Detach cursor, 0 or 1 */ - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int linepos, displine; int vc; int dispon, blink; - int vsynctime; + int64_t vsynctime; uint8_t *vram; } genius_t; @@ -245,8 +266,8 @@ void genius_recalctimings(genius_t *genius) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - genius->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - genius->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + genius->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + genius->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); } @@ -549,7 +570,7 @@ void genius_poll(void *p) } } -void *genius_init() +void *genius_init(device_t *info) { int c; genius_t *genius = malloc(sizeof(genius_t)); @@ -605,7 +626,7 @@ void genius_close(void *p) free(genius); } -static int genius_available() +static int genius_available(void) { return rom_present(L"roms/video/genius/8x12.bin"); } @@ -620,11 +641,13 @@ void genius_speed_changed(void *p) device_t genius_device = { "Genius VHR", - 0, + DEVICE_ISA, 0, genius_init, genius_close, + NULL, genius_available, genius_speed_changed, + NULL, NULL, NULL }; diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index bbb8b57b6..0329c9b7a 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -1,18 +1,34 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*Hercules emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Hercules emulation. + * + * Version: @(#)vid_hercules.c 1.0.2 2017/10/13 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../mem.h" +#include "../rom.h" #include "../io.h" #include "../timer.h" #include "../device.h" #include "video.h" #include "vid_hercules.h" -#ifndef __unix -# include "../win/win_cgapal.h" /*YUCK*/ -#endif typedef struct hercules_t @@ -24,8 +40,8 @@ typedef struct hercules_t uint8_t ctrl, ctrl2, stat; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int firstline, lastline; @@ -34,7 +50,8 @@ typedef struct hercules_t uint16_t ma, maback; int con, coff, cursoron; int dispon, blink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; uint8_t *vram; } hercules_t; @@ -120,8 +137,8 @@ void hercules_recalctimings(hercules_t *hercules) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - hercules->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - hercules->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + hercules->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + hercules->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } void hercules_poll(void *p) @@ -311,7 +328,8 @@ void hercules_poll(void *p) } } -void *hercules_init() + +void *hercules_init(device_t *info) { int c; hercules_t *hercules = malloc(sizeof(hercules_t)); @@ -344,14 +362,12 @@ void *hercules_init() overscan_x = overscan_y = 0; -#ifndef __unix cga_palette = device_get_config_int("rgb_type") << 1; if (cga_palette > 6) { cga_palette = 0; } cgapal_rebuild(); -#endif return hercules; } @@ -371,7 +387,6 @@ void hercules_speed_changed(void *p) hercules_recalctimings(hercules); } -#ifndef __unix static device_config_t hercules_config[] = { { @@ -398,21 +413,17 @@ static device_config_t hercules_config[] = "", "", -1 } }; -#endif device_t hercules_device = { "Hercules", - 0, + DEVICE_ISA, 0, hercules_init, hercules_close, + NULL, NULL, hercules_speed_changed, NULL, -#ifdef __unix - NULL -#else - NULL, + NULL, hercules_config -#endif }; diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 459107d03..c9ef61bd9 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -1,12 +1,30 @@ -/* Copyright holders: John Elliott - see COPYING for more details -*/ -/*Hercules InColor emulation*/ - +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Hercules InColor emulation. + * + * Version: @(#)vid_herculesplus.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" +#include "../rom.h" #include "../timer.h" #include "../device.h" #include "video.h" @@ -52,8 +70,8 @@ typedef struct herculesplus_t uint8_t ctrl, ctrl2, stat; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int firstline, lastline; @@ -62,7 +80,8 @@ typedef struct herculesplus_t uint16_t ma, maback; int con, coff, cursoron; int dispon, blink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; uint8_t *vram; } herculesplus_t; @@ -159,8 +178,8 @@ void herculesplus_recalctimings(herculesplus_t *herculesplus) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - herculesplus->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - herculesplus->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + herculesplus->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + herculesplus->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } @@ -658,7 +677,7 @@ void herculesplus_poll(void *p) } } -void *herculesplus_init() +void *herculesplus_init(device_t *info) { int c; herculesplus_t *herculesplus = malloc(sizeof(herculesplus_t)); @@ -710,11 +729,13 @@ void herculesplus_speed_changed(void *p) device_t herculesplus_device = { "Hercules Plus", - 0, + DEVICE_ISA, 0, herculesplus_init, herculesplus_close, + NULL, NULL, herculesplus_speed_changed, NULL, + NULL, NULL }; diff --git a/src/video/vid_icd2061.c b/src/video/vid_icd2061.c index 04c2db166..1292752b0 100644 --- a/src/video/vid_icd2061.c +++ b/src/video/vid_icd2061.c @@ -1,10 +1,27 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*PCem v8.1 by Tom Walker - - ICD2061 clock generator emulation - Used by ET4000w32/p (Diamond Stealth 32)*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ICD2061 clock generator emulation. + * + * Used by ET4000w32/p (Diamond Stealth 32) + * + * Version: @(#)vid_icd2061.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "vid_icd2061.h" diff --git a/src/video/vid_ics2595.c b/src/video/vid_ics2595.c index ffe6f504c..eb2aaf4a1 100644 --- a/src/video/vid_ics2595.c +++ b/src/video/vid_ics2595.c @@ -1,8 +1,25 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*ICS2595 clock chip emulation - Used by ATI Mach64*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ICS2595 clock chip emulation. Used by ATI Mach64. + * + * Version: @(#)vid_ics2595.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "vid_ics2595.h" diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index 636697c1a..6fdee5417 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -1,11 +1,30 @@ -/* Copyright holders: John Elliott - see COPYING for more details -*/ -/*Hercules InColor emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Hercules InColor emulation. + * + * Version: @(#)vid_incolor.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" +#include "../rom.h" #include "../timer.h" #include "../device.h" #include "video.h" @@ -13,7 +32,6 @@ /* extended CRTC registers */ - #define INCOLOR_CRTC_XMODE 20 /* xMode register */ #define INCOLOR_CRTC_UNDER 21 /* Underline */ #define INCOLOR_CRTC_OVER 22 /* Overstrike */ @@ -150,8 +168,8 @@ typedef struct incolor_t uint8_t ctrl, ctrl2, stat; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int firstline, lastline; @@ -160,7 +178,8 @@ typedef struct incolor_t uint16_t ma, maback; int con, coff, cursoron; int dispon, blink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; uint8_t palette[16]; /* EGA-style 16 -> 64 palette registers */ uint8_t palette_idx; /* Palette write index */ @@ -367,8 +386,8 @@ void incolor_recalctimings(incolor_t *incolor) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - incolor->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - incolor->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + incolor->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + incolor->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } @@ -1005,7 +1024,7 @@ void incolor_poll(void *p) } } -void *incolor_init() +void *incolor_init(device_t *info) { int c; incolor_t *incolor = malloc(sizeof(incolor_t)); @@ -1056,11 +1075,13 @@ void incolor_speed_changed(void *p) device_t incolor_device = { "Hercules InColor", - 0, + DEVICE_ISA, 0, incolor_init, incolor_close, + NULL, NULL, incolor_speed_changed, - NULL, + NULL, + NULL, NULL }; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index d9e254b3a..942425cda 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -1,18 +1,34 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*MDA emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * MDA emulation. + * + * Version: @(#)vid_mda.c 1.0.2 2017/10/13 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" +#include "../rom.h" #include "../timer.h" #include "../device.h" #include "video.h" #include "vid_mda.h" -#ifndef __unix -# include "../win/win_cgapal.h" /*YUCK*/ -#endif typedef struct mda_t @@ -24,8 +40,8 @@ typedef struct mda_t uint8_t ctrl, stat; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int firstline, lastline; @@ -34,7 +50,8 @@ typedef struct mda_t uint16_t ma, maback; int con, coff, cursoron; int dispon, blink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; uint8_t *vram; } mda_t; @@ -106,8 +123,8 @@ void mda_recalctimings(mda_t *mda) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - mda->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - mda->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + mda->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + mda->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } void mda_poll(void *p) @@ -260,7 +277,8 @@ void mda_poll(void *p) } } -void *mda_init() + +void *mda_init(device_t *info) { int c; mda_t *mda = malloc(sizeof(mda_t)); @@ -293,14 +311,12 @@ void *mda_init() overscan_x = overscan_y = 0; -#ifndef __unix cga_palette = device_get_config_int("rgb_type") << 1; if (cga_palette > 6) { cga_palette = 0; } cgapal_rebuild(); -#endif return mda; } @@ -320,7 +336,6 @@ void mda_speed_changed(void *p) mda_recalctimings(mda); } -#ifndef __unix static device_config_t mda_config[] = { { @@ -347,21 +362,17 @@ static device_config_t mda_config[] = "", "", -1 } }; -#endif device_t mda_device = { "MDA", - 0, + DEVICE_ISA, 0, mda_init, mda_close, + NULL, NULL, mda_speed_changed, NULL, -#ifdef __unix - NULL -#else NULL, mda_config -#endif }; diff --git a/src/video/vid_nv_riva128.c b/src/video/vid_nv_riva128.c index 0c3005ae7..c935cea45 100644 --- a/src/video/vid_nv_riva128.c +++ b/src/video/vid_nv_riva128.c @@ -1,8 +1,26 @@ -/* Copyright holders: Melissa Goad, Tenshi - see COPYING for more details -*/ -/*nVidia RIVA 128 emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * nVidia RIVA 128 emulation. + * + * Version: @(#)vid_nv_riva128.c 1.0.1 2017/10/10 + * + * Author: Melissa Goad + * Miran Grca, + * + * Copyright 2017 Melissa Goad. + * Copyright 2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -11,7 +29,7 @@ #include "../rom.h" #include "../timer.h" #include "../device.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "video.h" #include "vid_nv_riva128.h" #include "vid_svga.h" @@ -225,8 +243,10 @@ typedef struct riva128_t } edid_rom; } i2c; - int mtime, mfreq; - int nvtime, nvfreq; + int64_t mtime, mfreq; + int64_t nvtime, nvfreq; + int64_t menable; + int64_t nvenable; } riva128_t; //Internally, the RIVA 128 operates in a weird 38-bit color depth, with 10 bits for RGB, and 8 bits for alpha, according to envytools. @@ -1632,6 +1652,15 @@ void rivatnt_pgraph_ctx_switch(void *p) riva128_pgraph_interrupt(0, riva128); } +void riva128_pgraph_vblank_interrupt(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + + riva128->pgraph.invalid |= (1 << 8); + + riva128_pmc_interrupt(24, riva128); +} + uint8_t riva128_pramdac_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -2011,15 +2040,15 @@ void rivatnt_pgraph_ctx_switch(void *p) } } - void riva128_ptimer_tick(void *p) +void riva128_ptimer_tick(void *p) { riva128_t *riva128 = (riva128_t *)p; - double time = (double)riva128->ptimer.clock_mul / (double)riva128->ptimer.clock_div; + double time = ((double)riva128->ptimer.clock_mul * 1000000.0f) / (double)riva128->ptimer.clock_div; uint64_t tmp; int alarm_check; - time *= 10000; + //if(cs == 0x0008 && !riva128->pgraph.beta) pclog("RIVA 128 PTIMER time elapsed %f alarm %08x, time_low %08x\n", time, riva128->ptimer.alarm, riva128->ptimer.time & 0xffffffff); tmp = riva128->ptimer.time; riva128->ptimer.time += (uint64_t)time << 5; @@ -2037,25 +2066,27 @@ void rivatnt_pgraph_ctx_switch(void *p) { riva128_t *riva128 = (riva128_t *)p; - if(riva128->card_id == 0x03) riva128_ptimer_tick(riva128); + if(!riva128->pgraph.beta) pclog("RIVA 128 MCLK poll PMC enable %08x\n", riva128->pmc.enable); - riva128->mtime += cpuclock / riva128->mfreq; + if(!(riva128->pmc.enable & 0x00010000) && riva128->card_id == 0x03) riva128_ptimer_tick(riva128); + + riva128->mtime += (int)((TIMER_USEC * 1000000.0) / riva128->mfreq); } void riva128_nvclk_poll(void *p) { riva128_t *riva128 = (riva128_t *)p; - if(riva128->card_id < 0x40 && riva128->card_id != 0x03) riva128_ptimer_tick(riva128); + if(!(riva128->pmc.enable & 0x00010000) && riva128->card_id < 0x40 && riva128->card_id != 0x03) riva128_ptimer_tick(riva128); - riva128->nvtime += cpuclock / riva128->nvfreq; + riva128->nvtime += (int)((TIMER_USEC * 1000000.0) / riva128->nvfreq); } - void riva128_vblank_poll(svga_t *svga) + void riva128_vblank_start(svga_t *svga) { riva128_t *riva128 = (riva128_t *)svga->p; - riva128_pmc_interrupt(24, riva128); + riva128_pgraph_vblank_interrupt(riva128); } uint8_t riva128_rma_in(uint16_t addr, void *p) @@ -2601,9 +2632,9 @@ void rivatnt_pgraph_ctx_switch(void *p) } return; - /* case 0x3c: + case 0x3c: riva128->pci_regs[0x3c] = val & 0x0f; - return; */ + return; case 0x40: case 0x41: @@ -2712,9 +2743,9 @@ void rivatnt_pgraph_ctx_switch(void *p) } return; - /* case 0x3c: + case 0x3c: riva128->pci_regs[0x3c] = val & 0x0f; - return; */ + return; case 0x40: case 0x41: @@ -2782,7 +2813,21 @@ void rivatnt_pgraph_ctx_switch(void *p) svga->clock = cpuclock / freq; } - freq = 1350.0; + freq = 13500000.0; + + if(riva128->pramdac.m_m == 0) freq = 0; + else + { + freq = (freq * riva128->pramdac.m_n) / (1 << riva128->pramdac.m_p) / riva128->pramdac.m_m; + //pclog("RIVA 128 Memory clock is %f Hz\n", freq); + } + + riva128->mfreq = freq; + riva128->menable = 0; + riva128->mtime = (int)((TIMER_USEC * 1000000.0) / riva128->mfreq); + riva128->menable = 1; + + freq = 13500000.0; if(riva128->pramdac.nv_m == 0) freq = 0; else @@ -2791,21 +2836,14 @@ void rivatnt_pgraph_ctx_switch(void *p) //pclog("RIVA 128 Core clock is %f Hz\n", freq); } - riva128->mfreq = freq; - - freq = 1350.0; - - if(riva128->pramdac.m_m == 0) freq = 0; - else - { - freq = (freq * riva128->pramdac.m_n) / (1 << riva128->pramdac.m_p) / riva128->pramdac.m_m; - //pclog("RIVA 128 Core clock is %f Hz\n", freq); - } - riva128->nvfreq = freq; + riva128->nvenable = 0; + riva128->nvtime = (int)((TIMER_USEC * 1000000.0) / riva128->nvfreq); + riva128->nvenable = 1; } - void *riva128_init() + +void *riva128_init(device_t *info) { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -2888,7 +2926,7 @@ void rivatnt_pgraph_ctx_switch(void *p) riva128->ptimer.clock_mul = 1; riva128->ptimer.clock_div = 1; - //Some bullshit default values so that the emulator won't shit itself trying to boot. These'll be overwritten by the video BIOS anyway. + //default values so that the emulator can boot. These'll be overwritten by the video BIOS anyway. riva128->pramdac.m_m = 0x03; riva128->pramdac.m_n = 0xc2; riva128->pramdac.m_p = 0x0d; @@ -2926,15 +2964,20 @@ void rivatnt_pgraph_ctx_switch(void *p) } } - timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); - timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); + riva128->menable = 0; + riva128->nvenable = 0; - riva128->svga.vblank_start = riva128_vblank_poll; + timer_add(riva128_mclk_poll, &riva128->mtime, &riva128->menable, riva128); + timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128); + + riva128->svga.vblank_start = riva128_vblank_start; + + riva128->pgraph.beta = 0xffffffff; return riva128; } - void riva128_close(void *p) +void riva128_close(void *p) { riva128_t *riva128 = (riva128_t *)p; FILE *f = fopen("vram.dmp", "wb"); @@ -2946,12 +2989,12 @@ void rivatnt_pgraph_ctx_switch(void *p) free(riva128); } - int riva128_available() +int riva128_available(void) { return rom_present(L"roms/video/nv_riva128/Diamond_V330_rev-e.vbi"); } - void riva128_speed_changed(void *p) +void riva128_speed_changed(void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -2996,7 +3039,8 @@ device_config_t riva128_config[] = } }; -/* device_config_t riva128zx_config[] = +#if 0 +device_config_t riva128zx_config[] = { { .name = "memory", @@ -3029,14 +3073,17 @@ device_config_t riva128_config[] = { .type = -1 } -};*/ +}; +#endif device_t riva128_device = { "nVidia RIVA 128", + DEVICE_PCI, 0, riva128_init, riva128_close, + NULL, riva128_available, riva128_speed_changed, riva128_force_redraw, @@ -3044,7 +3091,8 @@ device_t riva128_device = riva128_config }; - void *rivatnt_init() + +void *rivatnt_init(device_t *info) { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -3111,7 +3159,7 @@ device_t riva128_device = riva128->pci_card = pci_add_card(PCI_ADD_VIDEO, riva128_pci_read, rivatnt_pci_write, riva128); - //Some bullshit default values so that the emulator won't shit itself trying to boot. These'll be overwritten by the video BIOS anyway. + //default values so that the emulator can boot. These'll be overwritten by the video BIOS anyway. riva128->pramdac.m_m = 0x03; riva128->pramdac.m_n = 0xc2; riva128->pramdac.m_p = 0x0d; @@ -3149,15 +3197,18 @@ device_t riva128_device = } } - timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); - timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); + riva128->menable = 0; + riva128->nvenable = 0; - riva128->svga.vblank_start = riva128_vblank_poll; + timer_add(riva128_mclk_poll, &riva128->mtime, &riva128->menable, riva128); + timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128); + + riva128->svga.vblank_start = riva128_vblank_start; return riva128; } - void rivatnt_close(void *p) +void rivatnt_close(void *p) { riva128_t *riva128 = (riva128_t *)p; FILE *f = fopen("vram.dmp", "wb"); @@ -3169,33 +3220,33 @@ device_t riva128_device = free(riva128); } - int rivatnt_available() +int rivatnt_available(void) { return rom_present(L"roms/video/nv_riva128/NV4_diamond_revB.rom"); } - void rivatnt_speed_changed(void *p) +void rivatnt_speed_changed(void *p) { riva128_t *riva128 = (riva128_t *)p; svga_recalctimings(&riva128->svga); } - void rivatnt_force_redraw(void *p) +void rivatnt_force_redraw(void *p) { riva128_t *riva128 = (riva128_t *)p; riva128->svga.fullchange = changeframecount; } - void rivatnt_add_status_info(char *s, int max_len, void *p) +void rivatnt_add_status_info(char *s, int max_len, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_add_status_info(s, max_len, &riva128->svga); } - device_config_t rivatnt_config[] = +device_config_t rivatnt_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 16, @@ -3222,9 +3273,11 @@ device_t riva128_device = device_t rivatnt_device = { "nVidia RIVA TNT", + DEVICE_PCI, 0, rivatnt_init, rivatnt_close, + NULL, rivatnt_available, rivatnt_speed_changed, rivatnt_force_redraw, @@ -3232,7 +3285,7 @@ device_t rivatnt_device = rivatnt_config }; - void *rivatnt2_init() +void *rivatnt2_init(device_t *info) { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -3312,7 +3365,7 @@ device_t rivatnt_device = riva128->pci_card = pci_add_card(PCI_ADD_VIDEO, riva128_pci_read, rivatnt_pci_write, riva128); - //Some bullshit default values so that the emulator won't shit itself trying to boot. These'll be overwritten by the video BIOS anyway. + //default values so that the emulator can boot. These'll be overwritten by the video BIOS anyway. riva128->pramdac.m_m = 0x03; riva128->pramdac.m_n = 0xc2; riva128->pramdac.m_p = 0x0d; @@ -3350,15 +3403,18 @@ device_t rivatnt_device = } } - timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); - timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); + riva128->menable = 0; + riva128->nvenable = 0; - riva128->svga.vblank_start = riva128_vblank_poll; + timer_add(riva128_mclk_poll, &riva128->mtime, &riva128->menable, riva128); + timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128); + + riva128->svga.vblank_start = riva128_vblank_start; return riva128; } - void rivatnt2_close(void *p) +void rivatnt2_close(void *p) { riva128_t *riva128 = (riva128_t *)p; FILE *f = fopen("vram.dmp", "wb"); @@ -3370,33 +3426,33 @@ device_t rivatnt_device = free(riva128); } - int rivatnt2_available() +int rivatnt2_available(void) { return rom_present(L"roms/video/nv_riva128/NV5diamond.bin") || rom_present(L"roms/video/nv_riva128/inno3d64bit.BIN") || rom_present(L"roms/video/nv_riva128/creative.BIN"); } - void rivatnt2_speed_changed(void *p) +void rivatnt2_speed_changed(void *p) { riva128_t *riva128 = (riva128_t *)p; svga_recalctimings(&riva128->svga); } - void rivatnt2_force_redraw(void *p) +void rivatnt2_force_redraw(void *p) { riva128_t *riva128 = (riva128_t *)p; riva128->svga.fullchange = changeframecount; } - void rivatnt2_add_status_info(char *s, int max_len, void *p) +void rivatnt2_add_status_info(char *s, int max_len, void *p) { riva128_t *riva128 = (riva128_t *)p; svga_add_status_info(s, max_len, &riva128->svga); } - device_config_t rivatnt2_config[] = +device_config_t rivatnt2_config[] = { { "model", "Card model", CONFIG_SELECTION, "", 0, @@ -3440,9 +3496,11 @@ device_t rivatnt_device = device_t rivatnt2_device = { "nVidia RIVA TNT2", + DEVICE_PCI, 0, rivatnt2_init, rivatnt2_close, + NULL, rivatnt2_available, rivatnt2_speed_changed, rivatnt2_force_redraw, diff --git a/src/video/vid_olivetti_m24.c b/src/video/vid_olivetti_m24.c index f130c69fb..5db33a6d2 100644 --- a/src/video/vid_olivetti_m24.c +++ b/src/video/vid_olivetti_m24.c @@ -1,9 +1,26 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*Olivetti M24 video emulation - Essentially double-res CGA*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Olivetti M24 video emulation- essentially double-res CGA. + * + * Version: @(#)vid_olivetti_m24.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -32,13 +49,14 @@ typedef struct m24_t int linepos, displine; int sc, vc; int con, coff, cursoron, blink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; int lineff; uint16_t ma, maback; int dispon; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int firstline, lastline; } m24_t; @@ -131,8 +149,8 @@ void m24_recalctimings(m24_t *m24) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST / 2; _dispofftime *= CGACONST / 2; - m24->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - m24->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + m24->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + m24->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } void m24_poll(void *p) @@ -445,7 +463,9 @@ void m24_poll(void *p) } } -void *m24_init() + +static void * +m24_init(device_t *info) { m24_t *m24 = malloc(sizeof(m24_t)); memset(m24, 0, sizeof(m24_t)); @@ -459,7 +479,9 @@ void *m24_init() return m24; } -void m24_close(void *p) + +static void +m24_close(void *p) { m24_t *m24 = (m24_t *)p; @@ -467,21 +489,22 @@ void m24_close(void *p) free(m24); } -void m24_speed_changed(void *p) + +static void +m24_speed_changed(void *p) { m24_t *m24 = (m24_t *)p; m24_recalctimings(m24); } + device_t m24_device = { "Olivetti M24 (video)", - 0, + 0, 0, m24_init, m24_close, - NULL, - m24_speed_changed, - NULL, - NULL + NULL, NULL, m24_speed_changed, + NULL, NULL, NULL }; diff --git a/src/video/vid_oti067.c b/src/video/vid_oti067.c index 7cfa434ba..4b0c45135 100644 --- a/src/video/vid_oti067.c +++ b/src/video/vid_oti067.c @@ -1,8 +1,26 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -/*Oak OTI067 emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Oak OTI067/077 emulation. + * + * Version: @(#)vid_oti067.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -13,294 +31,339 @@ #include "vid_svga.h" -typedef struct oti067_t +typedef struct { + svga_t svga; + + rom_t bios_rom; + + int index; + uint8_t regs[32]; + + uint8_t pos; + + uint32_t vram_size; + uint32_t vram_mask; + + uint8_t chip_id; +} oti_t; + + +static void +oti_out(uint16_t addr, uint8_t val, void *p) { - svga_t svga; - - rom_t bios_rom; - - int index; - uint8_t regs[32]; - - uint8_t pos; - - uint32_t vram_size; - uint32_t vram_mask; + oti_t *oti = (oti_t *)p; + svga_t *svga = &oti->svga; + uint8_t old; - uint8_t chip_id; -} oti067_t; + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && + !(svga->miscout & 1)) addr ^= 0x60; -void oti067_out(uint16_t addr, uint8_t val, void *p) -{ - oti067_t *oti067 = (oti067_t *)p; - svga_t *svga = &oti067->svga; - uint8_t old; + switch (addr) { + case 0x3D4: + svga->crtcreg = val & 31; + return; - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60; - - switch (addr) - { - case 0x3D4: - svga->crtcreg = val & 31; - return; - case 0x3D5: + case 0x3D5: if (svga->crtcreg <= 0x18) val &= mask_crtc[svga->crtcreg]; - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - 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(svga); - } - } - break; + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + 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(svga); + } + } + break; - case 0x3DE: - oti067->index = val & 0x1f; - return; - case 0x3DF: - oti067->regs[oti067->index] = val; - switch (oti067->index) - { - case 0xD: - svga->vrammask = (val & 0xc) ? oti067->vram_mask : 0x3ffff; - if ((val & 0x80) && oti067->vram_size == 256) - mem_mapping_disable(&svga->mapping); - else - mem_mapping_enable(&svga->mapping); - if (!(val & 0x80)) - svga->vrammask = 0x3ffff; - break; - case 0x11: - svga->read_bank = (val & 0xf) * 65536; - svga->write_bank = (val >> 4) * 65536; - break; - } - return; - } - svga_out(addr, val, svga); + case 0x3DE: + oti->index = val & 0x1f; + return; + + case 0x3DF: + oti->regs[oti->index] = val; + switch (oti->index) { + case 0xD: + svga->vrammask = (val & 0xc) ? oti->vram_mask : 0x3ffff; + if ((val & 0x80) && oti->vram_size == 256) + mem_mapping_disable(&svga->mapping); + else + mem_mapping_enable(&svga->mapping); + if (!(val & 0x80)) + svga->vrammask = 0x3ffff; + break; + + case 0x11: + svga->read_bank = (val & 0xf) * 65536; + svga->write_bank = (val >> 4) * 65536; + break; + } + return; + } + + svga_out(addr, val, svga); } -uint8_t oti067_in(uint16_t addr, void *p) -{ - oti067_t *oti067 = (oti067_t *)p; - svga_t *svga = &oti067->svga; - uint8_t temp; - - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60; - - switch (addr) - { - case 0x3D4: - temp = svga->crtcreg; - break; - case 0x3D5: - temp = svga->crtc[svga->crtcreg]; - break; - - case 0x3DE: - temp = oti067->index | (oti067->chip_id << 5); - break; - case 0x3DF: - if (oti067->index==0x10) temp = 0x18; - else temp = oti067->regs[oti067->index]; - break; - default: - temp = svga_in(addr, svga); - break; - } - return temp; +static uint8_t +oti_in(uint16_t addr, void *p) +{ + oti_t *oti = (oti_t *)p; + svga_t *svga = &oti->svga; + uint8_t temp; + + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && + !(svga->miscout & 1)) addr ^= 0x60; + + switch (addr) { + case 0x3D4: + temp = svga->crtcreg; + break; + + case 0x3D5: + temp = svga->crtc[svga->crtcreg]; + break; + + case 0x3DE: + temp = oti->index | (oti->chip_id << 5); + break; + + case 0x3DF: + if (oti->index==0x10) + temp = 0x18; + else + temp = oti->regs[oti->index]; + break; + + default: + temp = svga_in(addr, svga); + break; + } + + return(temp); } -void oti067_pos_out(uint16_t addr, uint8_t val, void *p) -{ - oti067_t *oti067 = (oti067_t *)p; - if ((val & 8) != (oti067->pos & 8)) - { - if (val & 8) - io_sethandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067); - else - io_removehandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067); - } - - oti067->pos = val; +static void +oti_pos_out(uint16_t addr, uint8_t val, void *p) +{ + oti_t *oti = (oti_t *)p; + + if ((val & 8) != (oti->pos & 8)) { + if (val & 8) + io_sethandler(0x03c0, 32, oti_in, NULL, NULL, + oti_out, NULL, NULL, oti); + else + io_removehandler(0x03c0, 32, oti_in, NULL, NULL, + oti_out, NULL, NULL, oti); + } + + oti->pos = val; } -uint8_t oti067_pos_in(uint16_t addr, void *p) -{ - oti067_t *oti067 = (oti067_t *)p; - return oti067->pos; -} - -void oti067_recalctimings(svga_t *svga) +static uint8_t +oti_pos_in(uint16_t addr, void *p) { - oti067_t *oti067 = (oti067_t *)svga->p; - - if (oti067->regs[0x14] & 0x08) svga->ma_latch |= 0x10000; - if (oti067->regs[0x0d] & 0x0c) svga->rowoffset <<= 1; - if (oti067->regs[0x14] & 0x80) - { - svga->vtotal *= 2; - svga->dispend *= 2; - svga->vblankstart *= 2; - svga->vsyncstart *=2; - svga->split *= 2; - } + oti_t *oti = (oti_t *)p; + + return(oti->pos); +} + + +static void +oti_recalctimings(svga_t *svga) +{ + oti_t *oti = (oti_t *)svga->p; + + if (oti->regs[0x14] & 0x08) svga->ma_latch |= 0x10000; + + if (oti->regs[0x0d] & 0x0c) svga->rowoffset <<= 1; + + if (oti->regs[0x14] & 0x80) { + svga->vtotal *= 2; + svga->dispend *= 2; + svga->vblankstart *= 2; + svga->vsyncstart *=2; + svga->split *= 2; + } } -void *oti067_common_init(wchar_t *bios_fn, int vram_size, int chip_id) + +static void * +oti_common_init(wchar_t *bios_fn, int vram_size, int chip_id) { - oti067_t *oti067 = malloc(sizeof(oti067_t)); - memset(oti067, 0, sizeof(oti067_t)); - - rom_init(&oti067->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + oti_t *oti = malloc(sizeof(oti_t)); - oti067->vram_size = vram_size; - oti067->vram_mask = (vram_size << 10) - 1; + memset(oti, 0x00, sizeof(oti_t)); - oti067->chip_id = chip_id; - - svga_init(&oti067->svga, oti067, vram_size << 10, - oti067_recalctimings, - oti067_in, oti067_out, - NULL, - NULL); + rom_init(&oti->bios_rom, bios_fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - io_sethandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067); - io_sethandler(0x46e8, 0x0001, oti067_pos_in, NULL, NULL, oti067_pos_out, NULL, NULL, oti067); - - oti067->svga.miscout = 1; - return oti067; + oti->vram_size = vram_size; + oti->vram_mask = (vram_size << 10) - 1; + + oti->chip_id = chip_id; + + svga_init(&oti->svga, oti, vram_size << 10, + oti_recalctimings, oti_in, oti_out, NULL, NULL); + + io_sethandler(0x03c0, 32, + oti_in, NULL, NULL, oti_out, NULL, NULL, oti); + io_sethandler(0x46e8, 1, oti_pos_in,NULL,NULL, oti_pos_out,NULL,NULL, oti); + + oti->svga.miscout = 1; + + return(oti); } -void *oti067_init() + +static void * +oti067_init(device_t *info) { - int vram_size = device_get_config_int("memory"); - return oti067_common_init(L"roms/video/oti/bios.bin", vram_size, 2); + int vram_size = device_get_config_int("memory"); + + return(oti_common_init(L"roms/video/oti/bios.bin", vram_size, 2)); } -void *oti077_init() + +static void * +oti077_init(device_t *info) { - int vram_size = device_get_config_int("memory"); - return oti067_common_init(L"roms/video/oti/oti077.vbi", vram_size, 5); + int vram_size = device_get_config_int("memory"); + + return(oti_common_init(L"roms/video/oti/oti077.vbi", vram_size, 5)); } -static int oti067_available() + +static int +oti067_available(void) { - return rom_present(L"roms/video/oti/bios.bin"); + return(rom_present(L"roms/video/oti/bios.bin")); } -static int oti077_available() + +static int +oti077_available(void) { - return rom_present(L"roms/video/oti/oti077.vbi"); + return(rom_present(L"roms/video/oti/oti077.vbi")); } -void oti067_close(void *p) -{ - oti067_t *oti067 = (oti067_t *)p; - svga_close(&oti067->svga); - - free(oti067); +static void +oti_close(void *p) +{ + oti_t *oti = (oti_t *)p; + + svga_close(&oti->svga); + + free(oti); } -void oti067_speed_changed(void *p) -{ - oti067_t *oti067 = (oti067_t *)p; - - svga_recalctimings(&oti067->svga); -} - -void oti067_force_redraw(void *p) -{ - oti067_t *oti067 = (oti067_t *)p; - oti067->svga.fullchange = changeframecount; +static void +oti_speed_changed(void *p) +{ + oti_t *oti = (oti_t *)p; + + svga_recalctimings(&oti->svga); +} + + +static void +oti_force_redraw(void *p) +{ + oti_t *oti = (oti_t *)p; + + oti->svga.fullchange = changeframecount; } -void oti067_add_status_info(char *s, int max_len, void *p) + +static void +oti_add_status_info(char *s, int max_len, void *p) { - oti067_t *oti067 = (oti067_t *)p; - - svga_add_status_info(s, max_len, &oti067->svga); + oti_t *oti = (oti_t *)p; + + svga_add_status_info(s, max_len, &oti->svga); } + static device_config_t oti067_config[] = { - { - "memory", "Memory size", CONFIG_SELECTION, "", 512, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Memory size", CONFIG_SELECTION, "", 512, + { + { + "256 kB", 256 + }, + { + "512 kB", 512 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; static device_config_t oti077_config[] = { - { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Memory size", CONFIG_SELECTION, "", 1024, + { + { + "256 kB", 256 + }, + { + "512 kB", 512 + }, + { + "1 MB", 1024 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; + device_t oti067_device = { - "Oak OTI-067", - 0, - oti067_init, - oti067_close, - oti067_available, - oti067_speed_changed, - oti067_force_redraw, - oti067_add_status_info, - oti067_config + "Oak OTI-067", + DEVICE_ISA, + 0, + oti067_init, + oti_close, + NULL, + oti067_available, + oti_speed_changed, + oti_force_redraw, + oti_add_status_info, + oti067_config }; + device_t oti077_device = { - "Oak OTI-077", - 0, - oti077_init, - oti067_close, - oti077_available, - oti067_speed_changed, - oti067_force_redraw, - oti067_add_status_info, - oti077_config + "Oak OTI-077", + DEVICE_ISA, + 0, + oti077_init, + oti_close, + NULL, + oti077_available, + oti_speed_changed, + oti_force_redraw, + oti_add_status_info, + oti077_config }; diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index 799ac8f65..744341afc 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -1,12 +1,28 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -/*Paradise VGA emulation - - PC2086, PC3086 use PVGA1A - MegaPC uses W90C11A - */ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Paradise VGA emulation + * PC2086, PC3086 use PVGA1A + * MegaPC uses W90C11A + * + * Version: @(#)vid_paradise.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -250,7 +266,8 @@ uint8_t paradise_read(uint32_t addr, void *p) return svga_read_linear(addr, ¶dise->svga); } -void *paradise_pvga1a_init() + +void *paradise_pvga1a_init(device_t *info) { paradise_t *paradise = malloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; @@ -283,7 +300,7 @@ void *paradise_pvga1a_init() return paradise; } -void *paradise_wd90c11_init() +void *paradise_wd90c11_init(device_t *info) { paradise_t *paradise = malloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; @@ -318,18 +335,18 @@ void *paradise_wd90c11_init() return paradise; } -static void *paradise_pvga1a_pc2086_init() +static void *paradise_pvga1a_pc2086_init(device_t *info) { - paradise_t *paradise = paradise_pvga1a_init(); + paradise_t *paradise = paradise_pvga1a_init(info); if (paradise) rom_init(¶dise->bios_rom, L"roms/machines/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); return paradise; } -static void *paradise_pvga1a_pc3086_init() +static void *paradise_pvga1a_pc3086_init(device_t *info) { - paradise_t *paradise = paradise_pvga1a_init(); + paradise_t *paradise = paradise_pvga1a_init(info); if (paradise) rom_init(¶dise->bios_rom, L"roms/machines/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -337,9 +354,9 @@ static void *paradise_pvga1a_pc3086_init() return paradise; } -static void *paradise_wd90c11_megapc_init() +static void *paradise_wd90c11_megapc_init(device_t *info) { - paradise_t *paradise = paradise_wd90c11_init(); + paradise_t *paradise = paradise_wd90c11_init(info); if (paradise) rom_init_interleaved(¶dise->bios_rom, @@ -350,7 +367,7 @@ static void *paradise_wd90c11_megapc_init() return paradise; } -static int paradise_wd90c11_standalone_available() +static int paradise_wd90c11_standalone_available(void) { return rom_present(L"roms/machines/megapc/41651-bios lo.u18") && rom_present(L"roms/machines/megapc/211253-bios hi.u19"); } @@ -385,13 +402,16 @@ void paradise_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, ¶dise->svga); } + device_t paradise_pvga1a_pc2086_device = { "Paradise PVGA1A (Amstrad PC2086)", 0, + 0, paradise_pvga1a_pc2086_init, paradise_close, NULL, + NULL, paradise_speed_changed, paradise_force_redraw, paradise_add_status_info @@ -400,8 +420,10 @@ device_t paradise_pvga1a_pc3086_device = { "Paradise PVGA1A (Amstrad PC3086)", 0, + 0, paradise_pvga1a_pc3086_init, paradise_close, + NULL, NULL, paradise_speed_changed, paradise_force_redraw, @@ -411,8 +433,10 @@ device_t paradise_wd90c11_megapc_device = { "Paradise WD90C11 (Amstrad MegaPC)", 0, + 0, paradise_wd90c11_megapc_init, paradise_close, + NULL, NULL, paradise_speed_changed, paradise_force_redraw, @@ -421,9 +445,11 @@ device_t paradise_wd90c11_megapc_device = device_t paradise_wd90c11_device = { "Paradise WD90C11", - 0, + DEVICE_ISA, + 0, paradise_wd90c11_megapc_init, paradise_close, + NULL, paradise_wd90c11_standalone_available, paradise_speed_changed, paradise_force_redraw, diff --git a/src/video/vid_pc1512.c b/src/video/vid_pc1512.c index 832bde2ea..5bfce6251 100644 --- a/src/video/vid_pc1512.c +++ b/src/video/vid_pc1512.c @@ -1,15 +1,33 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*PC1512 CGA emulation - - The PC1512 extends CGA with a bit-planar 640x200x16 mode. - - Most CRTC registers are fixed. - - The Technical Reference Manual lists the video waitstate time as between 12 - and 46 cycles. PCem currently always uses the lower number.*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * PC1512 CGA emulation + * + * The PC1512 extends CGA with a bit-planar 640x200x16 mode. + * Most CRTC registers are fixed. + * + * The Technical Reference Manual lists the video waitstate + * time as between 12 and 46 cycles. We currently always use + * the lower number. + * + * Version: @(#)vid_pc1512.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -34,13 +52,14 @@ typedef struct pc1512_t int sc, vc; int cgadispon; int con, coff, cursoron, cgablink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; uint16_t ma, maback; int dispon; int blink; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int firstline, lastline; uint8_t *vram; @@ -154,8 +173,8 @@ static void pc1512_recalctimings(pc1512_t *pc1512) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - pc1512->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - pc1512->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + pc1512->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + pc1512->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } static void pc1512_poll(void *p) @@ -444,7 +463,8 @@ static void pc1512_poll(void *p) } } -static void *pc1512_init() + +static void *pc1512_init(device_t *info) { pc1512_t *pc1512 = malloc(sizeof(pc1512_t)); memset(pc1512, 0, sizeof(pc1512_t)); @@ -479,9 +499,10 @@ static void pc1512_speed_changed(void *p) device_t pc1512_device = { "Amstrad PC1512 (video)", - 0, + 0, 0, pc1512_init, pc1512_close, + NULL, NULL, pc1512_speed_changed, NULL, diff --git a/src/video/vid_pc1640.c b/src/video/vid_pc1640.c index 2d6638ed4..77e4d0940 100644 --- a/src/video/vid_pc1640.c +++ b/src/video/vid_pc1640.c @@ -1,9 +1,27 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*PC1640 video emulation. - Mostly standard EGA, but with CGA & Hercules emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * PC1640 video emulation. + * Mostly standard EGA, but with CGA & Hercules emulation. + * + * Version: @(#)vid_pc1640.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -27,8 +45,8 @@ typedef struct pc1640_t rom_t bios_rom; int cga_enabled; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; } pc1640_t; void pc1640_out(uint16_t addr, uint8_t val, void *p) @@ -119,7 +137,8 @@ void pc1640_poll(void *p) } } -void *pc1640_init() + +void *pc1640_init(device_t *info) { pc1640_t *pc1640 = malloc(sizeof(pc1640_t)); cga_t *cga = &pc1640->cga; @@ -141,7 +160,7 @@ void *pc1640_init() return pc1640; } -void pc1640_close(void *p) +static void pc1640_close(void *p) { pc1640_t *pc1640 = (pc1640_t *)p; @@ -149,7 +168,7 @@ void pc1640_close(void *p) free(pc1640); } -void pc1640_speed_changed(void *p) +static void pc1640_speed_changed(void *p) { pc1640_t *pc1640 = (pc1640_t *)p; @@ -159,9 +178,10 @@ void pc1640_speed_changed(void *p) device_t pc1640_device = { "Amstrad PC1640 (video)", - 0, + 0, 0, pc1640_init, pc1640_close, + NULL, NULL, pc1640_speed_changed, NULL, diff --git a/src/video/vid_pc200.c b/src/video/vid_pc200.c index eef181c33..32811e8ea 100644 --- a/src/video/vid_pc200.c +++ b/src/video/vid_pc200.c @@ -1,10 +1,28 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*PC200 video emulation. - CGA with some NMI stuff. But we don't need that as it's only used for TV and - LCD displays, and we're emulating a CRT*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * PC200 video emulation. + * CGA with some NMI stuff. But we don't need that as it's only + * used for TV and LCD displays, and we're emulating a CRT. + * + * Version: @(#)vid_pc200.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -106,7 +124,8 @@ uint8_t pc200_in(uint16_t addr, void *p) return cga_in(addr, cga); } -void *pc200_init() + +static void *pc200_init(device_t *info) { pc200_t *pc200 = malloc(sizeof(pc200_t)); cga_t *cga = &pc200->cga; @@ -122,7 +141,7 @@ void *pc200_init() return pc200; } -void pc200_close(void *p) +static void pc200_close(void *p) { pc200_t *pc200 = (pc200_t *)p; @@ -130,7 +149,7 @@ void pc200_close(void *p) free(pc200); } -void pc200_speed_changed(void *p) +static void pc200_speed_changed(void *p) { pc200_t *pc200 = (pc200_t *)p; @@ -140,9 +159,10 @@ void pc200_speed_changed(void *p) device_t pc200_device = { "Amstrad PC200 (video)", - 0, + 0, 0, pc200_init, pc200_close, + NULL, NULL, pc200_speed_changed, NULL, diff --git a/src/video/vid_pcjr.c b/src/video/vid_pcjr.c index fe587e1bc..7610a5db7 100644 --- a/src/video/vid_pcjr.c +++ b/src/video/vid_pcjr.c @@ -1,4 +1,26 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Video emulation for IBM PCjr. + * + * Version: @(#)vid_pcjr.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include #include "../ibm.h" #include "../io.h" @@ -35,10 +57,11 @@ typedef struct pcjr_t int sc, vc; int dispon; int con, coff, cursoron, blink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; uint16_t ma, maback; - int dispontime, dispofftime, vidtime; + int64_t dispontime, dispofftime, vidtime; int firstline, lastline; int composite; @@ -162,8 +185,8 @@ void pcjr_recalctimings(pcjr_t *pcjr) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - pcjr->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - pcjr->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + pcjr->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + pcjr->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } @@ -513,7 +536,8 @@ void pcjr_poll(void *p) } } -static void *pcjr_video_init() + +static void *pcjr_video_init(device_t *info) { int display_type; pcjr_t *pcjr = malloc(sizeof(pcjr_t)); @@ -547,9 +571,10 @@ static void pcjr_speed_changed(void *p) device_t pcjr_video_device = { "IBM PCjr (video)", - 0, + 0, 0, pcjr_video_init, pcjr_video_close, + NULL, NULL, pcjr_speed_changed, NULL, @@ -582,9 +607,10 @@ static device_config_t pcjr_config[] = static device_t pcjr_device = { "IBM PCjr", - 0, + 0, 0, NULL, NULL, + NULL, NULL, NULL, NULL, diff --git a/src/video/vid_ps1_svga.c b/src/video/vid_ps1_svga.c index 9bb6acafc..93aff8732 100644 --- a/src/video/vid_ps1_svga.c +++ b/src/video/vid_ps1_svga.c @@ -1,13 +1,34 @@ -/*Emulation of the SVGA chip in the IBM PS/1 Model 2121, or at least the - 20 MHz version. - - I am not entirely sure what this chip actually is, possibly a CF62011? I can - not find any documentation on the chip so have implemented enough to pass - self-test in the PS/1 BIOS. It has 512kb video memory but I have not found any - native drivers for any operating system and there is no VBE implementation, so - it's just a VGA for now. -*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the SVGA chip in the IBM PS/1 Model 2121, or + * at least the 20 MHz version. + * + * I am not entirely sure what this chip actually is, possibly + * a CF62011? I can not find any documentation on the chip so + * have implemented enough to pass self-test in the PS/1 BIOS. + * It has 512kb video memory but I have not found any native + * drivers for any operating system and there is no VBE + * implementation, so it's just a VGA for now. + * + * Version: @(#)vid_ps1_svga.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -118,7 +139,8 @@ uint8_t ps1_m2121_svga_in(uint16_t addr, void *p) return temp; } -void *ps1_m2121_svga_init() + +static void *ps1_m2121_svga_init(device_t *info) { ps1_m2121_svga_t *ps1 = malloc(sizeof(ps1_m2121_svga_t)); memset(ps1, 0, sizeof(ps1_m2121_svga_t)); @@ -172,10 +194,11 @@ void ps1_m2121_svga_add_status_info(char *s, int max_len, void *p) device_t ps1_m2121_svga_device = { "PS/1 Model 2121 SVGA", - 0, + 0, 0, ps1_m2121_svga_init, ps1_m2121_svga_close, NULL, + NULL, ps1_m2121_svga_speed_changed, ps1_m2121_svga_force_redraw, ps1_m2121_svga_add_status_info diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index ecb7937b5..11c0221a1 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1,12 +1,33 @@ -/*S3 emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * S3 emulation. + * + * Version: @(#)vid_s3.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../device.h" #include "../io.h" #include "../mem.h" #include "../pci.h" #include "../rom.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "video.h" #include "vid_s3.h" #include "vid_svga.h" @@ -2139,7 +2160,7 @@ static int vram_sizes[] = 3 /*8 MB*/ }; -static void *s3_init(wchar_t *bios_fn, int chip) +static void *s3_init(device_t *info, wchar_t *bios_fn, int chip) { s3_t *s3 = malloc(sizeof(s3_t)); svga_t *svga = &s3->svga; @@ -2156,7 +2177,7 @@ static void *s3_init(wchar_t *bios_fn, int chip) s3->vram_mask = vram_size - 1; rom_init(&s3->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (PCI) + if (info->flags & DEVICE_PCI) mem_mapping_disable(&s3->bios_rom.mapping); mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &s3->svga); @@ -2169,7 +2190,7 @@ static void *s3_init(wchar_t *bios_fn, int chip) s3_hwcursor_draw, NULL); - if (PCI) + if (info->flags & DEVICE_PCI) svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5); else svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5); @@ -2179,12 +2200,15 @@ static void *s3_init(wchar_t *bios_fn, int chip) s3_io_set(s3); - s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); + if (info->flags & DEVICE_PCI) + { + s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); + } s3->pci_regs[0x04] = 7; s3->pci_regs[0x30] = 0x00; - s3->pci_regs[0x32] = 0x0c; + s3->pci_regs[0x32] = 0x0c; s3->pci_regs[0x33] = 0x00; s3->chip = chip; @@ -2198,9 +2222,9 @@ static void *s3_init(wchar_t *bios_fn, int chip) return s3; } -void *s3_vision864_init(wchar_t *bios_fn) +void *s3_vision864_init(device_t *info, wchar_t *bios_fn) { - s3_t *s3 = s3_init(bios_fn, S3_VISION864); + s3_t *s3 = s3_init(info, bios_fn, S3_VISION864); s3->id = 0xc1; /*Vision864P*/ s3->id_ext = s3->id_ext_pci = 0xc1; @@ -2212,31 +2236,32 @@ void *s3_vision864_init(wchar_t *bios_fn) return s3; } -void *s3_bahamas64_init() + +static void *s3_bahamas64_init(device_t *info) { - s3_t *s3 = s3_vision864_init(L"roms/video/s3/bahamas64.BIN"); + s3_t *s3 = s3_vision864_init(info, L"roms/video/s3/bahamas64.BIN"); return s3; } -void *s3_phoenix_vision864_init() +static void *s3_phoenix_vision864_init(device_t *info) { - s3_t *s3 = s3_vision864_init(L"roms/video/s3/86c864p.bin"); + s3_t *s3 = s3_vision864_init(info, L"roms/video/s3/86c864p.bin"); return s3; } -int s3_bahamas64_available() +static int s3_bahamas64_available(void) { return rom_present(L"roms/video/s3/bahamas64.BIN"); } -int s3_phoenix_vision864_available() +static int s3_phoenix_vision864_available(void) { return rom_present(L"roms/video/s3/86c864p.bin"); } -void *s3_phoenix_trio32_init() +static void *s3_phoenix_trio32_init(device_t *info) { - s3_t *s3 = s3_init(L"roms/video/s3/86C732P.bin", S3_TRIO32); + s3_t *s3 = s3_init(info, L"roms/video/s3/86C732P.bin", S3_TRIO32); s3->id = 0xe1; /*Trio32*/ s3->id_ext = 0x10; @@ -2249,14 +2274,14 @@ void *s3_phoenix_trio32_init() return s3; } -int s3_phoenix_trio32_available() +static int s3_phoenix_trio32_available(void) { return rom_present(L"roms/video/s3/86C732P.bin"); } -void *s3_trio64_init(wchar_t *bios_fn) +static void *s3_trio64_init(device_t *info, wchar_t *bios_fn) { - s3_t *s3 = s3_init(bios_fn, S3_TRIO64); + s3_t *s3 = s3_init(info, bios_fn, S3_TRIO64); s3->id = 0xe1; /*Trio64*/ s3->id_ext = s3->id_ext_pci = 0x11; @@ -2268,40 +2293,40 @@ void *s3_trio64_init(wchar_t *bios_fn) return s3; } -void *s3_9fx_init() +static void *s3_9fx_init(device_t *info) { - s3_t *s3 = s3_trio64_init(L"roms/video/s3/s3_764.bin"); + s3_t *s3 = s3_trio64_init(info, L"roms/video/s3/s3_764.bin"); return s3; } -void *s3_phoenix_trio64_init() +static void *s3_phoenix_trio64_init(device_t *info) { - s3_t *s3 = s3_trio64_init(L"roms/video/s3/86C764X1.bin"); + s3_t *s3 = s3_trio64_init(info, L"roms/video/s3/86C764X1.bin"); return s3; } -void *s3_diamond_stealth64_init() +static void *s3_diamond_stealth64_init(device_t *info) { - s3_t *s3 = s3_trio64_init(L"roms/video/s3/STEALT64.BIN"); + s3_t *s3 = s3_trio64_init(info, L"roms/video/s3/STEALT64.BIN"); return s3; } -int s3_9fx_available() +static int s3_9fx_available(void) { return rom_present(L"roms/video/s3/s3_764.bin"); } -int s3_phoenix_trio64_available() +static int s3_phoenix_trio64_available(void) { return rom_present(L"roms/video/s3/86c764x1.bin"); } -int s3_diamond_stealth64_available() +static int s3_diamond_stealth64_available(void) { return rom_present(L"roms/video/s3/STEALT64.BIN"); } -void s3_close(void *p) +static void s3_close(void *p) { s3_t *s3 = (s3_t *)p; @@ -2314,21 +2339,21 @@ void s3_close(void *p) free(s3); } -void s3_speed_changed(void *p) +static void s3_speed_changed(void *p) { s3_t *s3 = (s3_t *)p; svga_recalctimings(&s3->svga); } -void s3_force_redraw(void *p) +static void s3_force_redraw(void *p) { s3_t *s3 = (s3_t *)p; s3->svga.fullchange = changeframecount; } -void s3_add_status_info(char *s, int max_len, void *p) +static void s3_add_status_info(char *s, int max_len, void *p) { s3_t *s3 = (s3_t *)p; char temps[256]; @@ -2458,12 +2483,14 @@ static device_config_t s3_phoenix_trio64_config[] = } }; -device_t s3_bahamas64_device = +device_t s3_bahamas64_vlb_device = { - "Paradise Bahamas 64 (S3 Vision864)", - 0, + "Paradise Bahamas 64 (S3 Vision864) VLB", + DEVICE_VLB, + 0, s3_bahamas64_init, s3_close, + NULL, s3_bahamas64_available, s3_speed_changed, s3_force_redraw, @@ -2471,12 +2498,29 @@ device_t s3_bahamas64_device = s3_bahamas64_config }; -device_t s3_9fx_device = +device_t s3_bahamas64_pci_device = { - "Number 9 9FX (S3 Trio64)", - 0, + "Paradise Bahamas 64 (S3 Vision864) PCI", + DEVICE_PCI, + 0, + s3_bahamas64_init, + s3_close, + NULL, + s3_bahamas64_available, + s3_speed_changed, + s3_force_redraw, + s3_add_status_info, + s3_bahamas64_config +}; + +device_t s3_9fx_vlb_device = +{ + "Number 9 9FX (S3 Trio64) VLB", + DEVICE_VLB, + 0, s3_9fx_init, s3_close, + NULL, s3_9fx_available, s3_speed_changed, s3_force_redraw, @@ -2484,12 +2528,29 @@ device_t s3_9fx_device = s3_9fx_config }; -device_t s3_phoenix_trio32_device = +device_t s3_9fx_pci_device = { - "Phoenix S3 Trio32", - 0, + "Number 9 9FX (S3 Trio64) PCI", + DEVICE_PCI, + 0, + s3_9fx_init, + s3_close, + NULL, + s3_9fx_available, + s3_speed_changed, + s3_force_redraw, + s3_add_status_info, + s3_9fx_config +}; + +device_t s3_phoenix_trio32_vlb_device = +{ + "Phoenix S3 Trio32 VLB", + DEVICE_VLB, + 0, s3_phoenix_trio32_init, s3_close, + NULL, s3_phoenix_trio32_available, s3_speed_changed, s3_force_redraw, @@ -2497,12 +2558,29 @@ device_t s3_phoenix_trio32_device = s3_phoenix_trio32_config }; -device_t s3_phoenix_trio64_device = +device_t s3_phoenix_trio32_pci_device = { - "Phoenix S3 Trio64", - 0, + "Phoenix S3 Trio32 PCI", + DEVICE_PCI, + 0, + s3_phoenix_trio32_init, + s3_close, + NULL, + s3_phoenix_trio32_available, + s3_speed_changed, + s3_force_redraw, + s3_add_status_info, + s3_phoenix_trio32_config +}; + +device_t s3_phoenix_trio64_vlb_device = +{ + "Phoenix S3 Trio64 VLB", + DEVICE_VLB, + 0, s3_phoenix_trio64_init, s3_close, + NULL, s3_phoenix_trio64_available, s3_speed_changed, s3_force_redraw, @@ -2510,12 +2588,29 @@ device_t s3_phoenix_trio64_device = s3_phoenix_trio64_config }; -device_t s3_phoenix_vision864_device = +device_t s3_phoenix_trio64_pci_device = { - "Phoenix S3 Vision864", - 0, + "Phoenix S3 Trio64 PCI", + DEVICE_PCI, + 0, + s3_phoenix_trio64_init, + s3_close, + NULL, + s3_phoenix_trio64_available, + s3_speed_changed, + s3_force_redraw, + s3_add_status_info, + s3_phoenix_trio64_config +}; + +device_t s3_phoenix_vision864_vlb_device = +{ + "Phoenix S3 Vision864 VLB", + DEVICE_VLB, + 0, s3_phoenix_vision864_init, s3_close, + NULL, s3_phoenix_vision864_available, s3_speed_changed, s3_force_redraw, @@ -2523,12 +2618,44 @@ device_t s3_phoenix_vision864_device = s3_bahamas64_config }; -device_t s3_diamond_stealth64_device = +device_t s3_phoenix_vision864_pci_device = { - "S3 Trio64 (Diamond Stealth64 DRAM)", - 0, + "Phoenix S3 Vision864 PCI", + DEVICE_PCI, + 0, + s3_phoenix_vision864_init, + s3_close, + NULL, + s3_phoenix_vision864_available, + s3_speed_changed, + s3_force_redraw, + s3_add_status_info, + s3_bahamas64_config +}; + +device_t s3_diamond_stealth64_vlb_device = +{ + "S3 Trio64 (Diamond Stealth64 DRAM) VLB", + DEVICE_PCI, + 0, s3_diamond_stealth64_init, s3_close, + NULL, + s3_diamond_stealth64_available, + s3_speed_changed, + s3_force_redraw, + s3_add_status_info, + s3_phoenix_trio64_config +}; + +device_t s3_diamond_stealth64_pci_device = +{ + "S3 Trio64 (Diamond Stealth64 DRAM) PCI", + DEVICE_PCI, + 0, + s3_diamond_stealth64_init, + s3_close, + NULL, s3_diamond_stealth64_available, s3_speed_changed, s3_force_redraw, diff --git a/src/video/vid_s3.h b/src/video/vid_s3.h index 8ace7397d..096288ff4 100644 --- a/src/video/vid_s3.h +++ b/src/video/vid_s3.h @@ -17,10 +17,16 @@ * Copyright 2016-2017 Miran Grca. */ -device_t s3_bahamas64_device; -device_t s3_9fx_device; -device_t s3_phoenix_trio32_device; -device_t s3_phoenix_trio64_device; -device_t s3_phoenix_vision864_device; -device_t s3_diamond_stealth64_device; +device_t s3_bahamas64_vlb_device; +device_t s3_bahamas64_pci_device; +device_t s3_9fx_vlb_device; +device_t s3_9fx_pci_device; +device_t s3_phoenix_trio32_vlb_device; +device_t s3_phoenix_trio32_pci_device; +device_t s3_phoenix_trio64_vlb_device; +device_t s3_phoenix_trio64_pci_device; +device_t s3_phoenix_vision864_pci_device; +device_t s3_phoenix_vision864_vlb_device; +device_t s3_diamond_stealth64_pci_device; +device_t s3_diamond_stealth64_vlb_device; /* device_t s3_miro_vision964_device; */ diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 0b66093e3..b8937a349 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -1,15 +1,33 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*S3 ViRGE emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * S3 ViRGE emulation. + * + * Version: @(#)vid_s3_virge.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" #include "../pci.h" #include "../rom.h" #include "../device.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "video.h" #include "vid_s3_virge.h" #include "vid_svga.h" @@ -123,6 +141,7 @@ typedef struct virge_t uint8_t pci_regs[256]; int card; + int pci; int is_375; int bilinear_enabled; @@ -304,7 +323,7 @@ enum static void s3_virge_update_irqs(virge_t *virge) { - if (!PCI) + if (!virge->pci) { return; } @@ -438,7 +457,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) case 2: case 3: svga->bpp = 15; break; case 4: case 5: svga->bpp = 16; break; case 7: svga->bpp = 24; break; - case 13: svga->bpp = (gfxcard == GFX_VIRGEVX) ? 24 : 32; break; + case 13: svga->bpp = ((gfxcard == GFX_VIRGEVX_VLB) || (gfxcard == GFX_VIRGEVX_PCI)) ? 24 : 32; break; default: svga->bpp = 8; break; } break; @@ -553,7 +572,7 @@ static void s3_virge_recalctimings(svga_t *svga) } } - if (gfxcard != GFX_VIRGEVX) + if ((gfxcard != GFX_VIRGEVX_VLB) && (gfxcard != GFX_VIRGEVX_PCI)) { if ((svga->bpp == 15) || (svga->bpp == 16)) { @@ -617,7 +636,7 @@ static void s3_virge_recalctimings(svga_t *svga) if (((svga->miscout >> 2) & 3) == 3) { int n = svga->seqregs[0x12] & 0x1f; - int r = (svga->seqregs[0x12] >> 5) & ((virge->is_375 || (gfxcard == GFX_VIRGEVX)) ? 7 : 3); + int r = (svga->seqregs[0x12] >> 5) & ((virge->is_375 || ((gfxcard == GFX_VIRGEVX_VLB) || (gfxcard == GFX_VIRGEVX_PCI))) ? 7 : 3); int m = svga->seqregs[0x13] & 0x7f; double freq = (((double)m + 2) / (((double)n + 2) * (double)(1 << r))) * 14318184.0; @@ -3747,7 +3766,7 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) } } -static void *s3_virge_init() +static void *s3_virge_init(device_t *info) { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); @@ -3763,8 +3782,10 @@ static void *s3_virge_init() s3_virge_overlay_draw); virge->svga.vblank_start = s3_virge_vblank_start; + virge->pci = !!(info->flags & DEVICE_PCI); + rom_init(&virge->bios_rom, L"roms/video/s3virge/s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (PCI) + if (info->flags & DEVICE_PCI) mem_mapping_disable(&virge->bios_rom.mapping); mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, @@ -3798,13 +3819,13 @@ static void *s3_virge_init() io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; + virge->pci_regs[5] = 0; virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; + virge->pci_regs[7] = 2; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; + virge->pci_regs[0x3f] = 0xff; virge->virge_id_high = 0x56; virge->virge_id_low = 0x31; @@ -3828,7 +3849,10 @@ static void *s3_virge_init() virge->is_375 = 0; - virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); + if (info->flags & DEVICE_PCI) + { + virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); + } virge->wake_render_thread = thread_create_event(); virge->wake_main_thread = thread_create_event(); @@ -3842,7 +3866,7 @@ static void *s3_virge_init() return virge; } -static void *s3_virge_988_init() +static void *s3_virge_988_init(device_t *info) { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); @@ -3857,8 +3881,10 @@ static void *s3_virge_988_init() s3_virge_hwcursor_draw, s3_virge_overlay_draw); + virge->pci = !!(info->flags & DEVICE_PCI); + rom_init(&virge->bios_rom, L"roms/video/s3virge/diamondstealth3000.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (PCI) + if (info->flags & DEVICE_PCI) mem_mapping_disable(&virge->bios_rom.mapping); mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, @@ -3892,13 +3918,13 @@ static void *s3_virge_988_init() io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; + virge->pci_regs[5] = 0; virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; + virge->pci_regs[7] = 2; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; + virge->pci_regs[0x3f] = 0xff; virge->virge_id_high = 0x88; virge->virge_id_low = 0x3d; @@ -3922,7 +3948,10 @@ static void *s3_virge_988_init() virge->is_375 = 0; - virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); + if (info->flags & DEVICE_PCI) + { + virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); + } virge->wake_render_thread = thread_create_event(); virge->wake_main_thread = thread_create_event(); @@ -3936,7 +3965,7 @@ static void *s3_virge_988_init() return virge; } -static void *s3_virge_375_init(wchar_t *romfn) +static void *s3_virge_375_init(device_t *info, wchar_t *romfn) { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); @@ -3951,8 +3980,10 @@ static void *s3_virge_375_init(wchar_t *romfn) s3_virge_hwcursor_draw, s3_virge_overlay_draw); + virge->pci = !!(info->flags & DEVICE_PCI); + rom_init(&virge->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (PCI) + if (info->flags & DEVICE_PCI) mem_mapping_disable(&virge->bios_rom.mapping); mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, @@ -3986,13 +4017,13 @@ static void *s3_virge_375_init(wchar_t *romfn) io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; + virge->pci_regs[5] = 0; virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; + virge->pci_regs[7] = 2; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; + virge->pci_regs[0x3f] = 0xff; virge->virge_id_high = 0x8a; virge->virge_id_low = 0x01; @@ -4017,7 +4048,10 @@ static void *s3_virge_375_init(wchar_t *romfn) virge->is_375 = 1; - virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); + if (info->flags & DEVICE_PCI) + { + virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); + } virge->wake_render_thread = thread_create_event(); virge->wake_main_thread = thread_create_event(); @@ -4031,14 +4065,14 @@ static void *s3_virge_375_init(wchar_t *romfn) return virge; } -static void *s3_virge_375_1_init() +static void *s3_virge_375_1_init(device_t *info) { - return s3_virge_375_init(L"roms/video/s3virge/86c375_1.bin"); + return s3_virge_375_init(info, L"roms/video/s3virge/86c375_1.bin"); } -static void *s3_virge_375_4_init() +static void *s3_virge_375_4_init(device_t *info) { - return s3_virge_375_init(L"roms/video/s3virge/86c375_4.bin"); + return s3_virge_375_init(info, L"roms/video/s3virge/86c375_4.bin"); } static void s3_virge_close(void *p) @@ -4064,22 +4098,22 @@ static void s3_virge_close(void *p) free(virge); } -static int s3_virge_available() +static int s3_virge_available(void) { return rom_present(L"roms/video/s3virge/s3virge.bin"); } -static int s3_virge_988_available() +static int s3_virge_988_available(void) { return rom_present(L"roms/video/s3virge/diamondstealth3000.VBI"); } -static int s3_virge_375_1_available() +static int s3_virge_375_1_available(void) { return rom_present(L"roms/video/s3virge/86c375_1.bin"); } -static int s3_virge_375_4_available() +static int s3_virge_375_4_available(void) { return rom_present(L"roms/video/s3virge/86c375_4.bin"); } @@ -4146,12 +4180,14 @@ static device_config_t s3_virge_config[] = } }; -device_t s3_virge_device = +device_t s3_virge_vlb_device = { - "Diamond Stealth 3D 2000 (S3 ViRGE)", + "Diamond Stealth 3D 2000 (S3 ViRGE) VLB", + DEVICE_VLB, 0, s3_virge_init, s3_virge_close, + NULL, s3_virge_available, s3_virge_speed_changed, s3_virge_force_redraw, @@ -4159,12 +4195,29 @@ device_t s3_virge_device = s3_virge_config }; -device_t s3_virge_988_device = +device_t s3_virge_pci_device = { - "Diamond Stealth 3D 3000 (S3 ViRGE/VX)", + "Diamond Stealth 3D 2000 (S3 ViRGE) PCI", + DEVICE_PCI, + 0, + s3_virge_init, + s3_virge_close, + NULL, + s3_virge_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + s3_virge_add_status_info, + s3_virge_config +}; + +device_t s3_virge_988_vlb_device = +{ + "Diamond Stealth 3D 3000 (S3 ViRGE/VX) VLB", + DEVICE_VLB, 0, s3_virge_988_init, s3_virge_close, + NULL, s3_virge_988_available, s3_virge_speed_changed, s3_virge_force_redraw, @@ -4172,12 +4225,29 @@ device_t s3_virge_988_device = s3_virge_config }; -device_t s3_virge_375_device = +device_t s3_virge_988_pci_device = { - "S3 ViRGE/DX", + "Diamond Stealth 3D 3000 (S3 ViRGE/VX) PCI", + DEVICE_PCI, + 0, + s3_virge_988_init, + s3_virge_close, + NULL, + s3_virge_988_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + s3_virge_add_status_info, + s3_virge_config +}; + +device_t s3_virge_375_vlb_device = +{ + "S3 ViRGE/DX VLB", + DEVICE_VLB, 0, s3_virge_375_1_init, s3_virge_close, + NULL, s3_virge_375_1_available, s3_virge_speed_changed, s3_virge_force_redraw, @@ -4185,12 +4255,44 @@ device_t s3_virge_375_device = s3_virge_config }; -device_t s3_virge_375_4_device = +device_t s3_virge_375_pci_device = { - "S3 ViRGE/DX (VBE 2.0)", + "S3 ViRGE/DX PCI", + DEVICE_PCI, + 0, + s3_virge_375_1_init, + s3_virge_close, + NULL, + s3_virge_375_1_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + s3_virge_add_status_info, + s3_virge_config +}; + +device_t s3_virge_375_4_vlb_device = +{ + "S3 ViRGE/DX (VBE 2.0) VLB", + DEVICE_VLB, 0, s3_virge_375_4_init, s3_virge_close, + NULL, + s3_virge_375_4_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + s3_virge_add_status_info, + s3_virge_config +}; + +device_t s3_virge_375_4_pci_device = +{ + "S3 ViRGE/DX (VBE 2.0) PCI", + DEVICE_PCI, + 0, + s3_virge_375_4_init, + s3_virge_close, + NULL, s3_virge_375_4_available, s3_virge_speed_changed, s3_virge_force_redraw, diff --git a/src/video/vid_s3_virge.h b/src/video/vid_s3_virge.h index 74ee6454b..85389eb40 100644 --- a/src/video/vid_s3_virge.h +++ b/src/video/vid_s3_virge.h @@ -1,7 +1,11 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t s3_virge_device; -extern device_t s3_virge_988_device; -extern device_t s3_virge_375_device; -extern device_t s3_virge_375_4_device; +extern device_t s3_virge_vlb_device; +extern device_t s3_virge_pci_device; +extern device_t s3_virge_988_vlb_device; +extern device_t s3_virge_988_pci_device; +extern device_t s3_virge_375_vlb_device; +extern device_t s3_virge_375_pci_device; +extern device_t s3_virge_375_4_vlb_device; +extern device_t s3_virge_375_4_pci_device; diff --git a/src/video/vid_sc1502x_ramdac.c b/src/video/vid_sc1502x_ramdac.c index 6e2cc3839..3ef8830ac 100644 --- a/src/video/vid_sc1502x_ramdac.c +++ b/src/video/vid_sc1502x_ramdac.c @@ -1,10 +1,27 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -/*It is unknown exactly what RAMDAC this is - It is possibly a Sierra 1502x - It's addressed by the TLIVESA1 driver for ET4000*/ -/* Note by Tenshi: Not possibly, this *IS* a Sierra 1502x. */ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of a Sierra SC1502X RAMDAC. + * + * Used by the TLIVESA1 driver for ET4000. + * + * Version: @(#)vid_sc1502x_ramdac.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "video.h" diff --git a/src/video/vid_sdac_ramdac.c b/src/video/vid_sdac_ramdac.c index 3bff85104..2dbcdabbf 100644 --- a/src/video/vid_sdac_ramdac.c +++ b/src/video/vid_sdac_ramdac.c @@ -1,8 +1,27 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -/*87C716 'SDAC' true colour RAMDAC emulation*/ -/*Misidentifies as AT&T 21C504*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * 87C716 'SDAC' true colour RAMDAC emulation. + * + * Misidentifies as AT&T 21C504. + * + * Version: @(#)vid_sdac_ramdac.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "video.h" diff --git a/src/video/vid_stg_ramdac.c b/src/video/vid_stg_ramdac.c index 2881fff91..a2200163a 100644 --- a/src/video/vid_stg_ramdac.c +++ b/src/video/vid_stg_ramdac.c @@ -1,7 +1,25 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -/*STG1702 true colour RAMDAC emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * STG1702 true colour RAMDAC emulation. + * + * Version: @(#)vid_stg_ramdac.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "video.h" diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 7df65bea6..27e61cbc4 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -8,24 +8,30 @@ * * Generic SVGA handling. * - * Version: @(#)vid_svga.c 1.0.0 2017/05/30 + * This is intended to be used by another SVGA driver, + * and not as a card in it's own right. * - * Author: Sarah Walker, + * Version: @(#)vid_svga.c 1.0.5 2017/10/10 + * + * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - -/*This is intended to be used by another SVGA driver, and not as a card in it's own right*/ #include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" -#ifdef ENABLE_VRAM_DUMP #include "../rom.h" -#endif #include "../timer.h" +#ifdef ENABLE_VRAM_DUMP +# include "../nvr.h" +#endif #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -680,8 +686,8 @@ void svga_recalctimings(svga_t *svga) _dispontime *= crtcconst; _dispofftime *= crtcconst; - svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + svga->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + svga->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); /* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock); printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart); printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]); @@ -1934,7 +1940,7 @@ void svga_dump_vram() return; } - f = nvrfopen(L"svga_vram.dmp", L"wb"); + f = nvr_fopen(L"svga_vram.dmp", L"wb"); if (f == NULL) { return; diff --git a/src/video/vid_svga.h b/src/video/vid_svga.h index d4307dfde..139926ee3 100644 --- a/src/video/vid_svga.h +++ b/src/video/vid_svga.h @@ -70,8 +70,8 @@ typedef struct svga_t uint32_t ma_latch; int bpp; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; uint8_t scrblank; diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 7b4c0c136..145e26a26 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -8,15 +8,18 @@ * * SVGA renderers. * - * Version: @(#)vid_svga_render.c 1.0.0 2017/05/30 + * Version: @(#)vid_svga_render.c 1.0.2 2017/10/10 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - #include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "video.h" @@ -28,6 +31,7 @@ int invert_display = 0; int video_grayscale = 0; int video_graytype = 0; + uint32_t shade[5][256] = { {0}, // RGB Color (unused) diff --git a/src/video/vid_table.c b/src/video/vid_table.c new file mode 100644 index 000000000..2e3d69b37 --- /dev/null +++ b/src/video/vid_table.c @@ -0,0 +1,294 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Define all known video cards. + * + * Version: @(#)vid_table.c 1.0.2 2017/10/14 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../timer.h" +#include "../plat.h" +#include "video.h" +#include "vid_svga.h" + +#include "vid_ati18800.h" +#include "vid_ati28800.h" +#include "vid_ati_mach64.h" +#include "vid_cga.h" +#ifdef DEV_BRANCH +# ifdef USE_CIRRUS +# include "vid_cl_ramdac.h" /* vid_cl_gd.c needs this */ +# include "vid_cl_gd.h" +# endif +#endif +#include "vid_ega.h" +#include "vid_et4000.h" +#include "vid_et4000w32.h" +#include "vid_genius.h" +#include "vid_hercules.h" +#include "vid_herculesplus.h" +#include "vid_incolor.h" +#include "vid_colorplus.h" +#include "vid_mda.h" +#ifdef DEV_BRANCH +# ifdef USE_RIVA +# include "vid_nv_riva128.h" +# endif +#endif +#include "vid_olivetti_m24.h" +#include "vid_oti067.h" +#include "vid_paradise.h" +#include "vid_pc1512.h" +#include "vid_pc1640.h" +#include "vid_pc200.h" +#include "vid_pcjr.h" +#include "vid_ps1_svga.h" +#include "vid_s3.h" +#include "vid_s3_virge.h" +#include "vid_tandy.h" +#include "vid_tandysl.h" +#include "vid_tgui9440.h" +#include "vid_tvga.h" +#include "vid_vga.h" +#include "vid_wy700.h" + + +typedef struct { + char name[64]; + char internal_name[24]; + device_t *device; + int legacy_id; +} VIDEO_CARD; + + +static VIDEO_CARD +video_cards[] = { + {"[ISA] ATI VGA Charger (ATI-28800-5)", "ati28800", &ati28800_device, GFX_VGACHARGER }, + {"[ISA] ATI VGA Wonder XL24 (ATI-28800-6)", "ati28800w", &ati28800_wonderxl24_device, GFX_VGAWONDERXL24 }, + {"[ISA] ATI VGA Edge-16 (ATI-18800)", "ati18800", &ati18800_device, GFX_VGAEDGE16 }, + {"[ISA] CGA", "cga", &cga_device, GFX_CGA }, + {"[ISA] Chips & Technologies SuperEGA", "superega", &sega_device, GFX_SUPER_EGA }, + {"[ISA] Compaq ATI VGA Wonder XL (ATI-28800-5)","compaq_ati28800", &compaq_ati28800_device, GFX_VGAWONDERXL }, + {"[ISA] Compaq EGA", "compaq_ega", &cpqega_device, GFX_COMPAQ_EGA }, + {"[ISA] EGA", "ega", &ega_device, GFX_EGA }, + {"[ISA] Hercules", "hercules", &hercules_device, GFX_HERCULES }, + {"[ISA] Hercules Plus", "hercules_plus", &herculesplus_device, GFX_HERCULESPLUS }, + {"[ISA] Hercules InColor", "incolor", &incolor_device, GFX_INCOLOR }, + {"[ISA] MDA", "mda", &mda_device, GFX_MDA }, + {"[ISA] MDSI Genius", "genius", &genius_device, GFX_GENIUS }, + {"[ISA] OAK OTI-067", "oti067", &oti067_device, GFX_OTI067 }, + {"[ISA] OAK OTI-077", "oti077", &oti077_device, GFX_OTI077 }, + {"[ISA] Paradise WD90C11", "wd90c11", ¶dise_wd90c11_device, GFX_WD90C11 }, + {"[ISA] Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS }, + {"[ISA] Trident TVGA8900D", "tvga8900d", &tvga8900d_device, GFX_TVGA }, + {"[ISA] Tseng ET4000AX", "et4000ax", &et4000_device, GFX_ET4000 }, + {"[ISA] VGA", "vga", &vga_device, GFX_VGA }, + {"[ISA] Wyse 700", "wy700", &wy700_device, GFX_WY700 }, + {"[VLB] ATI Graphics Pro Turbo (Mach64 GX)", "mach64x_vlb", &mach64gx_vlb_device, GFX_MACH64GX_VLB }, + {"[VLB] Diamond Stealth 32 (Tseng ET4000/w32p)","stealth32_vlb", &et4000w32p_vlb_device, GFX_ET4000W32_VLB }, + {"[VLB] Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000_vlb", &s3_virge_vlb_device, GFX_VIRGE_VLB }, + {"[VLB] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_vlb", &s3_virge_988_vlb_device, GFX_VIRGEVX_VLB }, + {"[VLB] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_vlb", &s3_diamond_stealth64_vlb_device, GFX_STEALTH64_VLB }, + {"[VLB] Number Nine 9FX (S3 Trio64)", "n9_9fx_vlb", &s3_9fx_vlb_device, GFX_N9_9FX_VLB }, + {"[VLB] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_vlb", &s3_bahamas64_vlb_device, GFX_BAHAMAS64_VLB }, + {"[VLB] Phoenix S3 Vision864", "px_vision864_vlb", &s3_phoenix_vision864_vlb_device, GFX_PHOENIX_VISION864_VLB }, + {"[VLB] Phoenix S3 Trio32", "px_trio32_vlb", &s3_phoenix_trio32_vlb_device, GFX_PHOENIX_TRIO32_VLB }, + {"[VLB] Phoenix S3 Trio64", "px_trio64_vlb", &s3_phoenix_trio64_vlb_device, GFX_PHOENIX_TRIO64_VLB }, + {"[VLB] S3 ViRGE/DX", "virge375_vlb", &s3_virge_375_vlb_device, GFX_VIRGEDX_VLB }, + {"[VLB] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device, GFX_VIRGEDX4_VLB }, + {"[VLB] Trident TGUI9440", "tgui9440_vlb", &tgui9440_vlb_device, GFX_TGUI9440_VLB }, + {"[PCI] ATI Graphics Pro Turbo (Mach64 GX)", "mach64x_pci", &mach64gx_pci_device, GFX_MACH64GX_PCI }, + {"[PCI] ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2 }, + {"[PCI] Diamond Stealth 32 (Tseng ET4000/w32p)","stealth32_pci", &et4000w32p_pci_device, GFX_ET4000W32_PCI }, + {"[PCI] Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000_pci", &s3_virge_pci_device, GFX_VIRGE_PCI }, + {"[PCI] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_pci", &s3_virge_988_pci_device, GFX_VIRGEVX_PCI }, + {"[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device, GFX_STEALTH64_PCI }, +#if defined(DEV_BRANCH) && defined(USE_RIVA) + {"[PCI] nVidia RIVA 128", "riva128", &riva128_device, GFX_RIVA128 }, + {"[PCI] nVidia RIVA TNT", "rivatnt", &rivatnt_device, GFX_RIVATNT }, + {"[PCI] nVidia RIVA TNT2", "rivatnt2", &rivatnt2_device, GFX_RIVATNT2 }, +#endif + {"[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device, GFX_N9_9FX_PCI }, + {"[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device, GFX_BAHAMAS64_PCI }, + {"[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device, GFX_PHOENIX_VISION864_PCI }, + {"[PCI] Phoenix S3 Trio32", "px_trio32_pci", &s3_phoenix_trio32_pci_device, GFX_PHOENIX_TRIO32_PCI }, + {"[PCI] Phoenix S3 Trio64", "px_trio64_pci", &s3_phoenix_trio64_pci_device, GFX_PHOENIX_TRIO64_PCI }, + {"[PCI] S3 ViRGE/DX", "virge375_pci", &s3_virge_375_pci_device, GFX_VIRGEDX_PCI }, + {"[PCI] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_pci", &s3_virge_375_4_pci_device, GFX_VIRGEDX4_PCI }, + {"[PCI] Trident TGUI9440", "tgui9440_pci", &tgui9440_pci_device, GFX_TGUI9440_PCI }, + {"", "", NULL, -1 } +}; + + +/* This will be merged into machine.c soon. --FvK */ +void +video_reset_device(int rs, int gc) +{ + pclog("Video_reset_device(rom=%i, gfx=%i)\n", rs, gc); + + switch (rs) { + case ROM_IBMPCJR: + device_add(&pcjr_video_device); + return; + + case ROM_TANDY: + case ROM_TANDY1000HX: + device_add(&tandy_device); + return; + + case ROM_TANDY1000SL2: + device_add(&tandysl_device); + return; + + case ROM_PC1512: + device_add(&pc1512_device); + return; + + case ROM_PC1640: + device_add(&pc1640_device); + return; + + case ROM_PC200: + device_add(&pc200_device); + return; + + case ROM_OLIM24: + device_add(&m24_device); + return; + + case ROM_PC2086: + device_add(¶dise_pvga1a_pc2086_device); + return; + + case ROM_PC3086: + device_add(¶dise_pvga1a_pc3086_device); + return; + + case ROM_MEGAPC: + device_add(¶dise_wd90c11_megapc_device); + return; + + case ROM_IBMPS1_2011: + case ROM_IBMPS2_M30_286: + case ROM_IBMPS2_M50: + case ROM_IBMPS2_M55SX: + case ROM_IBMPS2_M80: + device_add(&ps1vga_device); + return; + + case ROM_IBMPS1_2121: + device_add(&ps1_m2121_svga_device); + return; + } + + device_add(video_cards[video_old_to_new(gc)].device); +} + + +int +video_card_available(int card) +{ + if (video_cards[card].device) + return(device_available(video_cards[card].device)); + + return(1); +} + + +char * +video_card_getname(int card) +{ + return(video_cards[card].name); +} + + +device_t * +video_card_getdevice(int card) +{ + return(video_cards[card].device); +} + + +int +video_card_has_config(int card) +{ + return(video_cards[card].device->config ? 1 : 0); +} + + +int +video_card_getid(char *s) +{ + int c = 0; + + while (video_cards[c].device) { + if (!strcmp(video_cards[c].name, s)) + return(c); + c++; + } + + return(0); +} + + +int +video_old_to_new(int card) +{ + int c = 0; + + while (video_cards[c].device) { + if (video_cards[c].legacy_id == card) + return(c); + c++; + } + + return(0); +} + + +int +video_new_to_old(int card) +{ + return(video_cards[card].legacy_id); +} + + +char * +video_get_internal_name(int card) +{ + return(video_cards[card].internal_name); +} + + +int +video_get_video_from_internal_name(char *s) +{ + int c = 0; + + while (video_cards[c].legacy_id != -1) { + if (!strcmp(video_cards[c].internal_name, s)) + return(video_cards[c].legacy_id); + c++; + } + + return(0); +} diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c index cf745dbdf..a83e32377 100644 --- a/src/video/vid_tandy.c +++ b/src/video/vid_tandy.c @@ -1,4 +1,26 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Tandy Model 1000 video. + * + * Version: @(#)vid_tandy.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include #include "../ibm.h" #include "../io.h" @@ -36,10 +58,11 @@ typedef struct tandy_t int sc, vc; int dispon; int con, coff, cursoron, blink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; uint16_t ma, maback; - int dispontime, dispofftime, vidtime; + int64_t dispontime, dispofftime, vidtime; int firstline, lastline; int composite; @@ -180,8 +203,8 @@ void tandy_recalctimings(tandy_t *tandy) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - tandy->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - tandy->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + tandy->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + tandy->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } void tandy_poll(void *p) @@ -581,7 +604,8 @@ void tandy_poll(void *p) } } -void *tandy_init() + +static void *tandy_init(device_t *info) { int display_type; tandy_t *tandy = malloc(sizeof(tandy_t)); @@ -606,14 +630,14 @@ void *tandy_init() return tandy; } -void tandy_close(void *p) +static void tandy_close(void *p) { tandy_t *tandy = (tandy_t *)p; free(tandy); } -void tandy_speed_changed(void *p) +static void tandy_speed_changed(void *p) { tandy_t *tandy = (tandy_t *)p; @@ -624,11 +648,14 @@ device_t tandy_device = { "Tandy 1000 (video)", 0, + 0, tandy_init, tandy_close, + NULL, NULL, tandy_speed_changed, NULL, + NULL, NULL }; @@ -658,8 +685,9 @@ static device_config_t tandy_config[] = static device_t tandy1000_device = { "Tandy 1000", - 0, + 0, 0, NULL, + NULL, NULL, NULL, NULL, @@ -670,8 +698,9 @@ static device_t tandy1000_device = static device_t tandy1000hx_device = { "Tandy 1000HX", - 0, + 0, 0, NULL, + NULL, NULL, NULL, NULL, diff --git a/src/video/vid_tandysl.c b/src/video/vid_tandysl.c index 0c4225525..84d21a3f7 100644 --- a/src/video/vid_tandysl.c +++ b/src/video/vid_tandysl.c @@ -1,7 +1,26 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Tandy Model 1000/SL video. + * + * Version: @(#)vid_tandysl.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include #include "../ibm.h" #include "../io.h" @@ -36,11 +55,12 @@ typedef struct tandysl_t int sc, vc; int dispon; int con, coff, cursoron, blink; - int vsynctime, vadj; + int64_t vsynctime; + int vadj; uint16_t ma, maback; - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int firstline, lastline; } tandysl_t; @@ -236,8 +256,8 @@ static void tandysl_recalctimings(tandysl_t *tandy) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - tandy->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - tandy->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + tandy->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + tandy->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } @@ -650,7 +670,8 @@ static void tandysl_poll(void *p) } } -static void *tandysl_init() + +static void *tandysl_init(device_t *info) { tandysl_t *tandy = malloc(sizeof(tandysl_t)); memset(tandy, 0, sizeof(tandysl_t)); @@ -690,10 +711,13 @@ device_t tandysl_device = { "Tandy 1000SL (video)", 0, + 0, tandysl_init, tandysl_close, + NULL, NULL, tandysl_speed_changed, NULL, + NULL, NULL }; diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index e13b76fa9..a51922a28 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -1,15 +1,33 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*Trident TGUI9440 emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Trident TGUI9440 emulation. + * + * Version: @(#)vid_tgui9440.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" #include "../pci.h" #include "../rom.h" #include "../device.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -51,6 +69,7 @@ typedef struct tgui_t rom_t bios_rom; svga_t svga; + int pci; struct { @@ -225,7 +244,7 @@ void tgui_out(uint16_t addr, uint8_t val, void *p) case 0x21: if (old != val) { - if (!PCI) + if (!tgui->pci) { tgui->linear_base = ((val & 0xf) | ((val >> 2) & 0x30)) << 20; tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000; @@ -503,7 +522,7 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p) } } -void *tgui9440_init() +void *tgui9440_init(device_t *info) { tgui_t *tgui = malloc(sizeof(tgui_t)); memset(tgui, 0, sizeof(tgui_t)); @@ -511,6 +530,8 @@ void *tgui9440_init() tgui->vram_size = device_get_config_int("memory") << 20; tgui->vram_mask = tgui->vram_size - 1; + tgui->pci = !!(info->flags & DEVICE_PCI); + rom_init(&tgui->bios_rom, L"roms/video/tgui9440/9440.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); svga_init(&tgui->svga, tgui, tgui->vram_size, @@ -526,7 +547,10 @@ void *tgui9440_init() io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); io_sethandler(0x43c8, 0x0002, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui); + if (info->flags & DEVICE_PCI) + { + pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui); + } tgui->wake_fifo_thread = thread_create_event(); tgui->fifo_not_full_event = thread_create_event(); @@ -535,7 +559,7 @@ void *tgui9440_init() return tgui; } -static int tgui9440_available() +static int tgui9440_available(void) { return rom_present(L"roms/video/tgui9440/9440.vbi"); } @@ -1267,12 +1291,29 @@ static device_config_t tgui9440_config[] = } }; -device_t tgui9440_device = +device_t tgui9440_vlb_device = { - "Trident TGUI 9440", - 0, + "Trident TGUI 9440 VLB", + DEVICE_VLB, + 0, tgui9440_init, tgui_close, + NULL, + tgui9440_available, + tgui_speed_changed, + tgui_force_redraw, + tgui_add_status_info, + tgui9440_config +}; + +device_t tgui9440_pci_device = +{ + "Trident TGUI 9440 PCI", + DEVICE_PCI, + 0, + tgui9440_init, + tgui_close, + NULL, tgui9440_available, tgui_speed_changed, tgui_force_redraw, diff --git a/src/video/vid_tgui9440.h b/src/video/vid_tgui9440.h index 066580f4b..257e7974b 100644 --- a/src/video/vid_tgui9440.h +++ b/src/video/vid_tgui9440.h @@ -1,4 +1,5 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t tgui9440_device; +extern device_t tgui9440_vlb_device; +extern device_t tgui9440_pci_device; diff --git a/src/video/vid_tkd8001_ramdac.c b/src/video/vid_tkd8001_ramdac.c index 553bc489f..123c9e118 100644 --- a/src/video/vid_tkd8001_ramdac.c +++ b/src/video/vid_tkd8001_ramdac.c @@ -1,7 +1,25 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*Trident TKD8001 RAMDAC emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Trident TKD8001 RAMDAC emulation. + * + * Version: @(#)vid_tkd8001_ramdac.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "video.h" diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index a277e0229..1112fd3fb 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -1,8 +1,26 @@ -/* Copyright holders: Sarah Walker, SA1988 - see COPYING for more details -*/ -/*Trident TVGA (8900D) emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Trident TVGA (8900D) emulation. + * + * Version: @(#)vid_tvga.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -278,7 +296,8 @@ void tvga_recalctimings(svga_t *svga) } } -void *tvga8900d_init() + +static void *tvga8900d_init(device_t *info) { tvga_t *tvga = malloc(sizeof(tvga_t)); memset(tvga, 0, sizeof(tvga_t)); @@ -299,7 +318,7 @@ void *tvga8900d_init() return tvga; } -static int tvga8900d_available() +static int tvga8900d_available(void) { return rom_present(L"roms/video/tvga/TRIDENT.BIN"); } @@ -362,9 +381,11 @@ static device_config_t tvga_config[] = device_t tvga8900d_device = { "Trident TVGA 8900D", - 0, + DEVICE_ISA, + 0, tvga8900d_init, tvga_close, + NULL, tvga8900d_available, tvga_speed_changed, tvga_force_redraw, diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 85bf30446..f11a4a81a 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -1,8 +1,26 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*IBM VGA emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * IBM VGA emulation. + * + * Version: @(#)vid_vga.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -80,7 +98,8 @@ uint8_t vga_in(uint16_t addr, void *p) return temp; } -void *vga_init() + +static void *vga_init(device_t *info) { vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); @@ -101,8 +120,9 @@ void *vga_init() return vga; } + #ifdef DEV_BRANCH -void *trigem_unk_init() +static void *trigem_unk_init(device_t *info) { vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); @@ -129,7 +149,7 @@ void *trigem_unk_init() #endif /*PS/1 uses a standard VGA controller, but with no option ROM*/ -void *ps1vga_init() +void *ps1vga_init(device_t *info) { vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); @@ -148,7 +168,7 @@ void *ps1vga_init() return vga; } -static int vga_available() +static int vga_available(void) { return rom_present(L"roms/video/vga/ibm_vga.bin"); } @@ -186,9 +206,11 @@ void vga_add_status_info(char *s, int max_len, void *p) device_t vga_device = { "VGA", - 0, + DEVICE_ISA, + 0, vga_init, vga_close, + NULL, vga_available, vga_speed_changed, vga_force_redraw, @@ -198,9 +220,11 @@ device_t vga_device = device_t trigem_unk_device = { "VGA", - 0, + DEVICE_ISA, + 0, trigem_unk_init, vga_close, + NULL, vga_available, vga_speed_changed, vga_force_redraw, @@ -211,8 +235,10 @@ device_t ps1vga_device = { "PS/1 VGA", 0, + 0, ps1vga_init, vga_close, + NULL, vga_available, vga_speed_changed, vga_force_redraw, diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index 91ae9ef3d..29bcb683c 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -1,5 +1,26 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the 3DFX Voodoo Graphics controller. + * + * Version: @(#)vid_voodoo.c 1.0.2 2017/10/11 + * + * Authors: Sarah Walker, + * leilei + * + * Copyright 2008-2017 Sarah Walker. + */ +#include +#include +#include #include #include +#include #include #include "../ibm.h" #include "../cpu/cpu.h" @@ -8,12 +29,13 @@ #include "../pci.h" #include "../timer.h" #include "../device.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_voodoo.h" #include "vid_voodoo_dither.h" + #ifdef MIN #undef MIN #endif @@ -35,6 +57,7 @@ #define TEX_CACHE_MAX 64 + enum { VOODOO_1 = 0, @@ -42,6 +65,7 @@ enum VOODOO_2 = 2 }; + static uint32_t texture_offset[LOD_MAX+3] = { 0, @@ -218,7 +242,7 @@ typedef struct voodoo_t uint16_t dac_pll_regs[16]; float pixel_clock; - int line_time; + int64_t line_time; voodoo_params_t params; @@ -252,7 +276,7 @@ typedef struct voodoo_t int swap_count; int disp_buffer, draw_buffer; - int timer_count; + int64_t timer_count; int line; svga_t *svga; @@ -261,7 +285,7 @@ typedef struct voodoo_t uint32_t videoDimensions; uint32_t hSync, vSync; - int h_total, v_total, v_disp; + int64_t h_total, v_total, v_disp; int h_disp; int v_retrace; @@ -388,9 +412,9 @@ typedef struct voodoo_t int fb_write_buffer, fb_draw_buffer; int buffer_cutoff; - int read_time, write_time, burst_time; + int64_t read_time, write_time, burst_time; - int wake_timer; + int64_t wake_timer; uint8_t thefilter[256][256]; // pixel filter, feeding from one or two uint8_t thefilterg[256][256]; // for green @@ -5763,7 +5787,7 @@ static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val; } -#define WAKE_DELAY (TIMER_USEC * 100) +#define WAKE_DELAY (TIMER_USEC * 100LL) static inline void wake_fifo_thread(voodoo_t *voodoo) { if (!voodoo->wake_timer) @@ -5787,7 +5811,7 @@ static void voodoo_wake_timer(void *p) { voodoo_t *voodoo = (voodoo_t *)p; - voodoo->wake_timer = 0; + voodoo->wake_timer = 0LL; thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } @@ -6098,7 +6122,7 @@ static void voodoo_pixelclock_update(voodoo_t *voodoo) int n2 = ((voodoo->dac_pll_regs[0] >> 13) & 0x07); float t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); double clock_const; - int line_length; + int64_t line_length; if ((voodoo->dac_data[6] & 0xf0) == 0x20 || (voodoo->dac_data[6] & 0xf0) == 0x60 || @@ -6112,7 +6136,7 @@ static void voodoo_pixelclock_update(voodoo_t *voodoo) voodoo->pixel_clock = t; clock_const = cpuclock / t; - voodoo->line_time = (int)((double)line_length * clock_const * (double)(1 << TIMER_SHIFT)); + voodoo->line_time = (int64_t)((double)line_length * clock_const * (double)(1 << TIMER_SHIFT)); } static void voodoo_writel(uint32_t addr, uint32_t val, void *p) @@ -7348,7 +7372,7 @@ skip_draw: if (voodoo->line_time) voodoo->timer_count += voodoo->line_time; else - voodoo->timer_count += TIMER_USEC * 32; + voodoo->timer_count += TIMER_USEC * 32LL; } static void voodoo_add_status_info(char *s, int max_len, void *p) @@ -7456,7 +7480,8 @@ static void voodoo_speed_changed(void *p) // pclog("Voodoo read_time=%i write_time=%i burst_time=%i %08x %08x\n", voodoo->read_time, voodoo->write_time, voodoo->burst_time, voodoo->fbiInit1, voodoo->fbiInit4); } -void *voodoo_card_init() + +void *voodoo_card_init(void) { int c; voodoo_t *voodoo = malloc(sizeof(voodoo_t)); @@ -7593,7 +7618,7 @@ void *voodoo_card_init() return voodoo; } -void *voodoo_init() +void *voodoo_init(device_t *info) { voodoo_set_t *voodoo_set = malloc(sizeof(voodoo_set_t)); uint32_t tmuConfig = 1; @@ -7834,8 +7859,10 @@ device_t voodoo_device = { "3DFX Voodoo Graphics", DEVICE_PCI, + 0, voodoo_init, voodoo_close, + NULL, NULL, voodoo_speed_changed, NULL, diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index ef2277280..1cf02cb6c 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -1,5 +1,26 @@ -/* Wyse-700 emulation*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Wyse-700 emulation. + * + * Version: @(#)vid_wy700.c 1.0.1 2017/10/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#include +#include +#include #include +#include #include "../ibm.h" #include "../io.h" #include "../mem.h" @@ -190,13 +211,13 @@ typedef struct wy700_t int enabled; /* Display enabled, 0 or 1 */ int detach; /* Detach cursor, 0 or 1 */ - int dispontime, dispofftime; - int vidtime; + int64_t dispontime, dispofftime; + int64_t vidtime; int linepos, displine; int vc; int dispon, blink; - int vsynctime; + int64_t vsynctime; uint8_t *vram; } wy700_t; @@ -490,8 +511,8 @@ void wy700_recalctimings(wy700_t *wy700) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - wy700->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - wy700->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + wy700->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + wy700->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } @@ -871,7 +892,8 @@ void wy700_poll(void *p) } } -void *wy700_init() + +void *wy700_init(device_t *info) { int c; wy700_t *wy700 = malloc(sizeof(wy700_t)); @@ -982,11 +1004,13 @@ void wy700_speed_changed(void *p) device_t wy700_device = { "Wyse 700", - 0, + DEVICE_ISA, 0, wy700_init, wy700_close, + NULL, NULL, wy700_speed_changed, NULL, + NULL, NULL }; diff --git a/src/video/video.c b/src/video/video.c index 463d898ea..bf745f7b7 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -1,763 +1,639 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -#include +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Main video-rendering module. + * + * Video timing settings - + * + * 8-bit - 1mb/sec + * B = 8 ISA clocks + * W = 16 ISA clocks + * L = 32 ISA clocks + * + * Slow 16-bit - 2mb/sec + * B = 6 ISA clocks + * W = 8 ISA clocks + * L = 16 ISA clocks + * + * Fast 16-bit - 4mb/sec + * B = 3 ISA clocks + * W = 3 ISA clocks + * L = 6 ISA clocks + * + * Slow VLB/PCI - 8mb/sec (ish) + * B = 4 bus clocks + * W = 8 bus clocks + * L = 16 bus clocks + * + * Mid VLB/PCI - + * B = 4 bus clocks + * W = 5 bus clocks + * L = 10 bus clocks + * + * Fast VLB/PCI - + * B = 3 bus clocks + * W = 3 bus clocks + * L = 4 bus clocks + * + * Version: @(#)video.c 1.0.2 2017/10/13 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ #include +#include +#include +#include +#include #include -#include +#include "../86box.h" #include "../ibm.h" #include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" #include "../rom.h" #include "../config.h" -#include "../device.h" #include "../timer.h" -#include "../win/plat_thread.h" +#include "../plat.h" #include "video.h" #include "vid_svga.h" -#ifndef __unix -# include "../win/win.h" /*YUCK*/ -# include "../win/win_cgapal.h" /*YUCK*/ -#endif -#include "vid_ati18800.h" -#include "vid_ati28800.h" -#include "vid_ati_mach64.h" -#include "vid_cga.h" -#ifdef DEV_BRANCH -#ifdef USE_CIRRUS -#include "vid_cl_ramdac.h" /* vid_cl_gd.c needs this */ -#include "vid_cl_gd.h" -#endif -#endif -#include "vid_ega.h" -#include "vid_et4000.h" -#include "vid_et4000w32.h" -#include "vid_genius.h" -#include "vid_hercules.h" -#include "vid_herculesplus.h" -#include "vid_incolor.h" -#include "vid_colorplus.h" -#include "vid_mda.h" -#ifdef DEV_BRANCH -#ifdef USE_RIVA -#include "vid_nv_riva128.h" -#endif -#endif -#include "vid_olivetti_m24.h" -#include "vid_oti067.h" -#include "vid_paradise.h" -#include "vid_pc1512.h" -#include "vid_pc1640.h" -#include "vid_pc200.h" -#include "vid_pcjr.h" -#include "vid_ps1_svga.h" -#include "vid_s3.h" -#include "vid_s3_virge.h" -#include "vid_tandy.h" -#include "vid_tandysl.h" -#include "vid_tgui9440.h" -#include "vid_tvga.h" -#include "vid_vga.h" -#include "vid_wy700.h" - - -int vid_cga_contrast = 0; -int cga_palette = 0; - -typedef struct -{ - char name[64]; - char internal_name[24]; - device_t *device; - int legacy_id; -} VIDEO_CARD; - -static VIDEO_CARD video_cards[] = -{ - {"ATI Graphics Pro Turbo (Mach64 GX)", "mach64x", &mach64gx_device, GFX_MACH64GX}, - {"ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2}, - {"ATI VGA Charger (ATI-28800-5)", "ati28800", &ati28800_device, GFX_VGACHARGER}, - {"ATI VGA Wonder XL24 (ATI-28800-6)", "ati28800w", &ati28800_wonderxl24_device, GFX_VGAWONDERXL24}, - {"ATI VGA Edge-16 (ATI-18800)", "ati18800", &ati18800_device, GFX_VGAEDGE16}, - {"CGA", "cga", &cga_device, GFX_CGA}, - {"Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32", &et4000w32p_device, GFX_ET4000W32}, - {"Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d", &s3_diamond_stealth64_device,GFX_STEALTH64}, - {"Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000", &s3_virge_device, GFX_VIRGE}, - {"Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000", &s3_virge_988_device, GFX_VIRGEVX}, - {"EGA", "ega", &ega_device, GFX_EGA}, - {"Chips & Technologies SuperEGA", "superega", &sega_device, GFX_SUPER_EGA}, - {"Compaq ATI VGA Wonder XL (ATI-28800-5)", "compaq_ati28800", &compaq_ati28800_device, GFX_VGAWONDERXL}, - {"Compaq EGA", "compaq_ega", &cpqega_device, GFX_COMPAQ_EGA}, - {"Hercules", "hercules", &hercules_device, GFX_HERCULES}, - {"Hercules Plus", "hercules_plus", &herculesplus_device, GFX_HERCULESPLUS}, - {"Hercules InColor", "incolor", &incolor_device, GFX_INCOLOR}, - {"MDA", "mda", &mda_device, GFX_MDA}, - {"MDSI Genius", "genius", &genius_device, GFX_GENIUS}, - {"Number Nine 9FX (S3 Trio64)", "n9_9fx", &s3_9fx_device, GFX_N9_9FX}, -#ifdef DEV_BRANCH -#ifdef USE_RIVA - {"nVidia RIVA 128", "riva128", &riva128_device, GFX_RIVA128}, - {"nVidia RIVA TNT", "rivatnt", &rivatnt_device, GFX_RIVATNT}, - {"nVidia RIVA TNT2", "rivatnt2", &rivatnt2_device, GFX_RIVATNT2}, -#endif -#endif - {"OAK OTI-067", "oti067", &oti067_device, GFX_OTI067}, - {"OAK OTI-077", "oti077", &oti077_device, GFX_OTI077}, - {"Paradise Bahamas 64 (S3 Vision864)", "bahamas64", &s3_bahamas64_device, GFX_BAHAMAS64}, - {"Paradise WD90C11", "wd90c11", ¶dise_wd90c11_device, GFX_WD90C11}, - {"Phoenix S3 Vision864", "px_vision864", &s3_phoenix_vision864_device,GFX_PHOENIX_VISION864}, - {"Phoenix S3 Trio32", "px_trio32", &s3_phoenix_trio32_device, GFX_PHOENIX_TRIO32}, - {"Phoenix S3 Trio64", "px_trio64", &s3_phoenix_trio64_device, GFX_PHOENIX_TRIO64}, - {"Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS}, - {"S3 ViRGE/DX", "virge375", &s3_virge_375_device, GFX_VIRGEDX}, - {"S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20", &s3_virge_375_4_device, GFX_VIRGEDX4}, - {"Trident TGUI9440", "tgui9440", &tgui9440_device, GFX_TGUI9440}, - {"Trident TVGA8900D", "tvga8900d", &tvga8900d_device, GFX_TVGA}, - {"Tseng ET4000AX", "et4000ax", &et4000_device, GFX_ET4000}, - {"VGA", "vga", &vga_device, GFX_VGA}, - {"Wyse 700", "wy700", &wy700_device, GFX_WY700}, - {"", "", NULL, 0} +enum { + VIDEO_ISA = 0, + VIDEO_BUS }; -int video_card_available(int card) -{ - if (video_cards[card].device) - return device_available(video_cards[card].device); - return 1; -} - -char *video_card_getname(int card) -{ - return video_cards[card].name; -} - -device_t *video_card_getdevice(int card) -{ - return video_cards[card].device; -} - -int video_card_has_config(int card) -{ - return video_cards[card].device->config ? 1 : 0; -} - -int video_card_getid(char *s) -{ - int c = 0; - - while (video_cards[c].device) - { - if (!strcmp(video_cards[c].name, s)) - return c; - c++; - } - - return 0; -} - -int video_old_to_new(int card) -{ - int c = 0; - - while (video_cards[c].device) - { - if (video_cards[c].legacy_id == card) - return c; - c++; - } - - return 0; -} - -int video_new_to_old(int card) -{ - return video_cards[card].legacy_id; -} - -char *video_get_internal_name(int card) -{ - return video_cards[card].internal_name; -} - -int video_get_video_from_internal_name(char *s) -{ - int c = 0; - - while (video_cards[c].legacy_id != -1) - { - if (!strcmp(video_cards[c].internal_name, s)) - return video_cards[c].legacy_id; - c++; - } - - return 0; -} - -int video_fullscreen = 0, video_fullscreen_scale, video_fullscreen_first; -uint32_t *video_6to8, *video_15to32, *video_16to32; - -int egareads=0,egawrites=0; -int changeframecount=2; - -uint8_t rotatevga[8][256]; - -int frames = 0; - -int fullchange; - -uint8_t edatlookup[4][4]; - -int enable_overscan; -int overscan_x, overscan_y; - -int force_43; - -/*Video timing settings - - -8-bit - 1mb/sec - B = 8 ISA clocks - W = 16 ISA clocks - L = 32 ISA clocks - -Slow 16-bit - 2mb/sec - B = 6 ISA clocks - W = 8 ISA clocks - L = 16 ISA clocks - -Fast 16-bit - 4mb/sec - B = 3 ISA clocks - W = 3 ISA clocks - L = 6 ISA clocks - -Slow VLB/PCI - 8mb/sec (ish) - B = 4 bus clocks - W = 8 bus clocks - L = 16 bus clocks - -Mid VLB/PCI - - B = 4 bus clocks - W = 5 bus clocks - L = 10 bus clocks - -Fast VLB/PCI - - B = 3 bus clocks - W = 3 bus clocks - L = 4 bus clocks -*/ - -enum -{ - VIDEO_ISA = 0, - VIDEO_BUS +int vid_cga_contrast = 0; +int cga_palette = 0; +int video_fullscreen = 0, + video_fullscreen_scale, + video_fullscreen_first; +uint32_t *video_6to8, + *video_15to32, + *video_16to32; +BITMAP *screen; +int egareads = 0, + egawrites = 0, + changeframecount = 2; +uint8_t rotatevga[8][256]; +int frames = 0; +int fullchange; +uint8_t edatlookup[4][4]; +int enable_overscan; +int overscan_x, + overscan_y; +int force_43; +int video_timing_b, + video_timing_w, + video_timing_l; +int video_res_x, + video_res_y, + video_bpp; +int video_speed = 0; +int video_timing[6][4] = { + { VIDEO_ISA, 8, 16, 32 }, + { VIDEO_ISA, 6, 8, 16 }, + { VIDEO_ISA, 3, 3, 6 }, + { VIDEO_BUS, 4, 8, 16 }, + { VIDEO_BUS, 4, 5, 10 }, + { VIDEO_BUS, 3, 3, 4 } }; +BITMAP *buffer, + *buffer32; +uint8_t fontdat[256][8]; +uint8_t fontdatm[256][16]; +uint8_t fontdatw[512][32]; /* Wyse700 font */ +uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ +int xsize=1, + ysize=1; +PALETTE cgapal = { + {0,0,0}, {0,42,0}, {42,0,0}, {42,21,0}, + {0,0,0}, {0,42,42}, {42,0,42}, {42,42,42}, + {0,0,0}, {21,63,21}, {63,21,21}, {63,63,21}, + {0,0,0}, {21,63,63}, {63,21,63}, {63,63,63}, -int video_speed = 0; -int video_timing[6][4] = -{ - {VIDEO_ISA, 8, 16, 32}, - {VIDEO_ISA, 6, 8, 16}, - {VIDEO_ISA, 3, 3, 6}, - {VIDEO_BUS, 4, 8, 16}, - {VIDEO_BUS, 4, 5, 10}, - {VIDEO_BUS, 3, 3, 4} + {0,0,0}, {0,0,42}, {0,42,0}, {0,42,42}, + {42,0,0}, {42,0,42}, {42,21,00}, {42,42,42}, + {21,21,21}, {21,21,63}, {21,63,21}, {21,63,63}, + {63,21,21}, {63,21,63}, {63,63,21}, {63,63,63}, + + {0,0,0}, {0,21,0}, {0,0,42}, {0,42,42}, + {42,0,21}, {21,10,21}, {42,0,42}, {42,0,63}, + {21,21,21}, {21,63,21}, {42,21,42}, {21,63,63}, + {63,0,0}, {42,42,0}, {63,21,42}, {41,41,41}, + + {0,0,0}, {0,42,42}, {42,0,0}, {42,42,42}, + {0,0,0}, {0,42,42}, {42,0,0}, {42,42,42}, + {0,0,0}, {0,63,63}, {63,0,0}, {63,63,63}, + {0,0,0}, {0,63,63}, {63,0,0}, {63,63,63}, }; - -void video_updatetiming() -{ - if (video_timing[video_speed][0] == VIDEO_ISA) - { - video_timing_b = (int)(isa_timing * video_timing[video_speed][1]); - video_timing_w = (int)(isa_timing * video_timing[video_speed][2]); - video_timing_l = (int)(isa_timing * video_timing[video_speed][3]); - } - else - { - video_timing_b = (int)(bus_timing * video_timing[video_speed][1]); - video_timing_w = (int)(bus_timing * video_timing[video_speed][2]); - video_timing_l = (int)(bus_timing * video_timing[video_speed][3]); - } - if (cpu_16bitbus) - video_timing_l = video_timing_w * 2; -} - -int video_timing_b, video_timing_w, video_timing_l; - -int video_res_x, video_res_y, video_bpp; - -void (*video_blit_memtoscreen_func)(int x, int y, int y1, int y2, int w, int h); -void (*video_blit_memtoscreen_8_func)(int x, int y, int w, int h); - -void video_init() -{ - pclog("Video_init %i %i\n",romset,gfxcard); - -#ifndef __unix - cga_palette = 0; - cgapal_rebuild(); -#endif - - switch (romset) - { - case ROM_IBMPCJR: - device_add(&pcjr_video_device); - return; - - case ROM_TANDY: - case ROM_TANDY1000HX: - device_add(&tandy_device); - return; - - case ROM_TANDY1000SL2: - device_add(&tandysl_device); - return; - - case ROM_PC1512: - device_add(&pc1512_device); - return; - - case ROM_PC1640: - device_add(&pc1640_device); - return; - - case ROM_PC200: - device_add(&pc200_device); - return; - - case ROM_OLIM24: - device_add(&m24_device); - return; - - case ROM_PC2086: - device_add(¶dise_pvga1a_pc2086_device); - return; - - case ROM_PC3086: - device_add(¶dise_pvga1a_pc3086_device); - return; - - case ROM_MEGAPC: - device_add(¶dise_wd90c11_megapc_device); - return; - - case ROM_ACER386: - device_add(&oti067_device); - return; - - case ROM_IBMPS1_2011: - case ROM_IBMPS2_M30_286: - case ROM_IBMPS2_M50: - case ROM_IBMPS2_M55SX: - case ROM_IBMPS2_M80: - device_add(&ps1vga_device); - return; - - case ROM_IBMPS1_2121: - device_add(&ps1_m2121_svga_device); - return; - } - device_add(video_cards[video_old_to_new(gfxcard)].device); -} +PALETTE cgapal_mono[6] = { + { /* 0 - green, 4-color-optimized contrast. */ + {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x17,0x05}, + {0x01,0x1a,0x06},{0x02,0x28,0x09},{0x02,0x2c,0x0a}, + {0x03,0x39,0x0d},{0x03,0x3c,0x0e},{0x00,0x07,0x01}, + {0x01,0x13,0x04},{0x01,0x1f,0x07},{0x01,0x23,0x08}, + {0x02,0x31,0x0b},{0x02,0x35,0x0c},{0x05,0x3f,0x11},{0x0d,0x3f,0x17}, + }, + { /* 1 - green, 16-color-optimized contrast. */ + {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x15,0x05}, + {0x01,0x17,0x05},{0x01,0x21,0x08},{0x01,0x24,0x08}, + {0x02,0x2e,0x0b},{0x02,0x31,0x0b},{0x01,0x22,0x08}, + {0x02,0x28,0x09},{0x02,0x30,0x0b},{0x02,0x32,0x0c}, + {0x03,0x39,0x0d},{0x03,0x3b,0x0e},{0x09,0x3f,0x14},{0x0d,0x3f,0x17}, + }, + { /* 2 - amber, 4-color-optimized contrast. */ + {0x00,0x00,0x00},{0x15,0x05,0x00},{0x20,0x0b,0x00}, + {0x24,0x0d,0x00},{0x33,0x18,0x00},{0x37,0x1b,0x00}, + {0x3f,0x26,0x01},{0x3f,0x2b,0x06},{0x0b,0x02,0x00}, + {0x1b,0x08,0x00},{0x29,0x11,0x00},{0x2e,0x14,0x00}, + {0x3b,0x1e,0x00},{0x3e,0x21,0x00},{0x3f,0x32,0x0a},{0x3f,0x38,0x0d}, + }, + { /* 3 - amber, 16-color-optimized contrast. */ + {0x00,0x00,0x00},{0x15,0x05,0x00},{0x1e,0x09,0x00}, + {0x21,0x0b,0x00},{0x2b,0x12,0x00},{0x2f,0x15,0x00}, + {0x38,0x1c,0x00},{0x3b,0x1e,0x00},{0x2c,0x13,0x00}, + {0x32,0x17,0x00},{0x3a,0x1e,0x00},{0x3c,0x1f,0x00}, + {0x3f,0x27,0x01},{0x3f,0x2a,0x04},{0x3f,0x36,0x0c},{0x3f,0x38,0x0d}, + }, + { /* 4 - grey, 4-color-optimized contrast. */ + {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x15,0x17,0x18}, + {0x18,0x1a,0x1b},{0x24,0x25,0x25},{0x27,0x28,0x28}, + {0x33,0x34,0x32},{0x37,0x38,0x35},{0x09,0x0a,0x0b}, + {0x11,0x12,0x13},{0x1c,0x1e,0x1e},{0x20,0x22,0x22}, + {0x2c,0x2d,0x2c},{0x2f,0x30,0x2f},{0x3c,0x3c,0x38},{0x3f,0x3f,0x3b}, + }, + { /* 5 - grey, 16-color-optimized contrast. */ + {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x13,0x14,0x15}, + {0x15,0x17,0x18},{0x1e,0x20,0x20},{0x20,0x22,0x22}, + {0x29,0x2a,0x2a},{0x2c,0x2d,0x2c},{0x1f,0x21,0x21}, + {0x23,0x25,0x25},{0x2b,0x2c,0x2b},{0x2d,0x2e,0x2d}, + {0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a},{0x3f,0x3f,0x3b}, + } +}; +uint32_t pal_lookup[256]; -BITMAP *buffer, *buffer32; +static struct { + int x, y, y1, y2, w, h, blit8; + int busy; + int buffer_in_use; -uint8_t fontdat[256][8]; -uint8_t fontdatm[256][16]; -uint8_t fontdatw[512][32]; /* Wyse700 font */ -uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ - -int xsize=1,ysize=1; - -PALETTE cgapal; - -void loadfont(wchar_t *s, int format) -{ - FILE *f=romfopen(s,L"rb"); - int c,d; - if (!f) - { - return; - } - switch (format) - { - case 0: /* MDA */ - for (c=0;c<256;c++) - { - for (d=0;d<8;d++) - { - fontdatm[c][d]=getc(f); - } - } - for (c=0;c<256;c++) - { - for (d=0;d<8;d++) - { - fontdatm[c][d+8]=getc(f); - } - } - fseek(f,4096+2048,SEEK_SET); - for (c=0;c<256;c++) - { - for (d=0;d<8;d++) - { - fontdat[c][d]=getc(f); - } - } - break; - case 1: /* PC200 */ - for (c=0;c<256;c++) - { - for (d=0;d<8;d++) - { - fontdatm[c][d]=getc(f); - } - } - for (c=0;c<256;c++) - { - for (d=0;d<8;d++) - { - fontdatm[c][d+8]=getc(f); - } - } - fseek(f, 4096, SEEK_SET); - for (c=0;c<256;c++) - { - for (d=0;d<8;d++) - { - fontdat[c][d]=getc(f); - } - for (d=0;d<8;d++) getc(f); - } - break; - default: - case 2: /* CGA */ - for (c=0;c<256;c++) - { - for (d=0;d<8;d++) - { - fontdat[c][d]=getc(f); - } - } - break; - case 3: /* Wyse 700 */ - for (c=0;c<512;c++) - { - for (d=0;d<32;d++) - { - fontdatw[c][d]=getc(f); - } - } - break; - case 4: /* MDSI Genius */ - for (c=0;c<256;c++) - { - for (d=0;d<16;d++) - { - fontdat8x12[c][d]=getc(f); - } - } - break; - - } - fclose(f); -} - -static struct -{ - int x, y, y1, y2, w, h, blit8; - int busy; - int buffer_in_use; - - thread_t *blit_thread; - event_t *wake_blit_thread; - event_t *blit_complete; - event_t *buffer_not_in_use; + thread_t *blit_thread; + event_t *wake_blit_thread; + event_t *blit_complete; + event_t *buffer_not_in_use; } blit_data; -static void blit_thread(void *param); -int calc_6to8(int c) +static void (*memtoscreen_func)(int x, int y, int y1, int y2, int w, int h); +static void (*memtoscreen_8_func)(int x, int y, int w, int h); + + +static +void blit_thread(void *param) { - int ic, i8; - double d8; - ic = c; - if (ic == 64) - { - ic = 63; - } + while (1) { + thread_wait_event(blit_data.wake_blit_thread, -1); + thread_reset_event(blit_data.wake_blit_thread); + + if (blit_data.blit8) + memtoscreen_8_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h); else - { - ic &= 0x3f; + memtoscreen_func(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); + + blit_data.busy = 0; + thread_set_event(blit_data.blit_complete); + } +} + + +void +video_setblit(void(*blit8)(int,int,int,int),void(*blit)(int,int,int,int,int,int)) +{ + memtoscreen_func = blit; + memtoscreen_8_func = blit8; +} + + +void +video_blit_complete(void) +{ + blit_data.buffer_in_use = 0; + + thread_set_event(blit_data.buffer_not_in_use); +} + + +void +video_wait_for_blit(void) +{ + while (blit_data.busy) + thread_wait_event(blit_data.blit_complete, -1); + thread_reset_event(blit_data.blit_complete); +} + + +void +video_wait_for_buffer(void) +{ + while (blit_data.buffer_in_use) + thread_wait_event(blit_data.buffer_not_in_use, -1); + thread_reset_event(blit_data.buffer_not_in_use); +} + + +void +video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +{ + if (h <= 0) return; + + video_wait_for_blit(); + + blit_data.busy = 1; + blit_data.buffer_in_use = 1; + blit_data.x = x; + blit_data.y = y; + blit_data.y1 = y1; + blit_data.y2 = y2; + blit_data.w = w; + blit_data.h = h; + blit_data.blit8 = 0; + + thread_set_event(blit_data.wake_blit_thread); +} + + +void +video_blit_memtoscreen_8(int x, int y, int w, int h) +{ + if (h <= 0) return; + + video_wait_for_blit(); + + blit_data.busy = 1; + blit_data.x = x; + blit_data.y = y; + blit_data.w = w; + blit_data.h = h; + blit_data.blit8 = 1; + + thread_set_event(blit_data.wake_blit_thread); +} + + +void +cgapal_rebuild(void) +{ + int c; + + for (c=0; c<256; c++) { + pal_lookup[c] = makecol(video_6to8[cgapal[c].r], + video_6to8[cgapal[c].g], + video_6to8[cgapal[c].b]); + } + + if ((cga_palette > 1) && (cga_palette < 8)) { + if (vid_cga_contrast != 0) { + for (c=0; c<16; c++) { + pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], + video_6to8[cgapal_mono[cga_palette - 2][c].g], + video_6to8[cgapal_mono[cga_palette - 2][c].b]); + pal_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], + video_6to8[cgapal_mono[cga_palette - 2][c].g], + video_6to8[cgapal_mono[cga_palette - 2][c].b]); + pal_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], + video_6to8[cgapal_mono[cga_palette - 2][c].g], + video_6to8[cgapal_mono[cga_palette - 2][c].b]); + pal_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], + video_6to8[cgapal_mono[cga_palette - 2][c].g], + video_6to8[cgapal_mono[cga_palette - 2][c].b]); + } + } else { + for (c=0; c<16; c++) { + pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], + video_6to8[cgapal_mono[cga_palette - 1][c].g], + video_6to8[cgapal_mono[cga_palette - 1][c].b]); + pal_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], + video_6to8[cgapal_mono[cga_palette - 1][c].g], + video_6to8[cgapal_mono[cga_palette - 1][c].b]); + pal_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], + video_6to8[cgapal_mono[cga_palette - 1][c].g], + video_6to8[cgapal_mono[cga_palette - 1][c].b]); + pal_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], + video_6to8[cgapal_mono[cga_palette - 1][c].g], + video_6to8[cgapal_mono[cga_palette - 1][c].b]); + } } - d8 = (ic / 63.0) * 255.0; - i8 = (int) d8; - return i8 & 0xff; + } + + if (cga_palette == 8) + pal_lookup[0x16] = makecol(video_6to8[42],video_6to8[42],video_6to8[0]); } -int calc_15to32(int c) + +void +video_update_timing(void) { - int b, g, r; - double db, dg, dr; - b = (c & 31); - g = ((c >> 5) & 31); - r = ((c >> 10) & 31); - db = (((double) b) / 31.0) * 255.0; - dg = (((double) g) / 31.0) * 255.0; - dr = (((double) r) / 31.0) * 255.0; - b = (int) db; - g = ((int) dg) << 8; - r = ((int) dr) << 16; - return (b | g | r); + if (video_timing[video_speed][0] == VIDEO_ISA) { + video_timing_b = (int)(isa_timing * video_timing[video_speed][1]); + video_timing_w = (int)(isa_timing * video_timing[video_speed][2]); + video_timing_l = (int)(isa_timing * video_timing[video_speed][3]); + } else { + video_timing_b = (int)(bus_timing * video_timing[video_speed][1]); + video_timing_w = (int)(bus_timing * video_timing[video_speed][2]); + video_timing_l = (int)(bus_timing * video_timing[video_speed][3]); + } + + if (cpu_16bitbus) + video_timing_l = video_timing_w * 2; } -int calc_16to32(int c) + +int +calc_6to8(int c) { - int b, g, r; - double db, dg, dr; - b = (c & 31); - g = ((c >> 5) & 63); - r = ((c >> 11) & 31); - db = (((double) b) / 31.0) * 255.0; - dg = (((double) g) / 63.0) * 255.0; - dr = (((double) r) / 31.0) * 255.0; - b = (int) db; - g = ((int) dg) << 8; - r = ((int) dr) << 16; - return (b | g | r); + int ic, i8; + double d8; + + ic = c; + if (ic == 64) + ic = 63; + else + ic &= 0x3f; + d8 = (ic / 63.0) * 255.0; + i8 = (int) d8; + + return(i8 & 0xff); } -void initvideo() + +int +calc_15to32(int c) { - int c, d, e; + int b, g, r; + double db, dg, dr; - /* Account for overscan. */ - buffer32 = create_bitmap(2048, 2048); + b = (c & 31); + g = ((c >> 5) & 31); + r = ((c >> 10) & 31); + db = (((double) b) / 31.0) * 255.0; + dg = (((double) g) / 31.0) * 255.0; + dr = (((double) r) / 31.0) * 255.0; + b = (int) db; + g = ((int) dg) << 8; + r = ((int) dr) << 16; - buffer = create_bitmap(2048, 2048); + return(b | g | r); +} - for (c = 0; c < 64; c++) - { - cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 64].b = (((c & 1) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - if ((c & 0x17) == 6) - cgapal[c + 64].g >>= 1; - } - for (c = 0; c < 64; c++) - { - cgapal[c + 128].r = (((c & 4) ? 2 : 0) | ((c & 0x20) ? 1 : 0)) * 21; - cgapal[c + 128].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 128].b = (((c & 1) ? 2 : 0) | ((c & 0x08) ? 1 : 0)) * 21; - } - for (c = 0; c < 256; c++) - { - e = c; - for (d = 0; d < 8; d++) - { - rotatevga[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } - } - for (c = 0; c < 4; c++) - { - for (d = 0; d < 4; d++) - { - edatlookup[c][d] = 0; - if (c & 1) edatlookup[c][d] |= 1; - if (d & 1) edatlookup[c][d] |= 2; - if (c & 2) edatlookup[c][d] |= 0x10; - if (d & 2) edatlookup[c][d] |= 0x20; - } - } +int +calc_16to32(int c) +{ + int b, g, r; + double db, dg, dr; - video_6to8 = malloc(4 * 256); - for (c = 0; c < 256; c++) - video_6to8[c] = calc_6to8(c); + b = (c & 31); + g = ((c >> 5) & 63); + r = ((c >> 11) & 31); + db = (((double) b) / 31.0) * 255.0; + dg = (((double) g) / 63.0) * 255.0; + dr = (((double) r) / 31.0) * 255.0; + b = (int) db; + g = ((int) dg) << 8; + r = ((int) dr) << 16; - video_15to32 = malloc(4 * 65536); + return(b | g | r); +} + + +void +hline(BITMAP *b, int x1, int y, int x2, uint32_t col) +{ + if (y < 0 || y >= buffer->h) + return; + + if (b == buffer) + memset(&b->line[y][x1], col, x2 - x1); + else + memset(&((uint32_t *)b->line[y])[x1], col, (x2 - x1) * 4); +} + + +void +blit(BITMAP *src, BITMAP *dst, int x1, int y1, int x2, int y2, int xs, int ys) +{ +} + + +void +stretch_blit(BITMAP *src, BITMAP *dst, int x1, int y1, int xs1, int ys1, int x2, int y2, int xs2, int ys2) +{ +} + + +void +rectfill(BITMAP *b, int x1, int y1, int x2, int y2, uint32_t col) +{ +} + + +void +set_palette(PALETTE p) +{ +} + + +void +destroy_bitmap(BITMAP *b) +{ +} + + +BITMAP * +create_bitmap(int x, int y) +{ + BITMAP *b = malloc(sizeof(BITMAP) + (y * sizeof(uint8_t *))); + int c; + + b->dat = malloc(x * y * 4); + for (c = 0; c < y; c++) + b->line[c] = b->dat + (c * x * 4); + b->w = x; + b->h = y; + + return(b); +} + + +void +video_init(void) +{ + int c, d, e; + + /* Account for overscan. */ + buffer32 = create_bitmap(2048, 2048); + + buffer = create_bitmap(2048, 2048); + for (c = 0; c < 64; c++) { + cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; + cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; + cgapal[c + 64].b = (((c & 1) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; + if ((c & 0x17) == 6) + cgapal[c + 64].g >>= 1; + } + for (c = 0; c < 64; c++) { + cgapal[c + 128].r = (((c & 4) ? 2 : 0) | ((c & 0x20) ? 1 : 0)) * 21; + cgapal[c + 128].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; + cgapal[c + 128].b = (((c & 1) ? 2 : 0) | ((c & 0x08) ? 1 : 0)) * 21; + } + + for (c = 0; c < 256; c++) { + e = c; + for (d = 0; d < 8; d++) { + rotatevga[d][c] = e; + e = (e >> 1) | ((e & 1) ? 0x80 : 0); + } + } + for (c = 0; c < 4; c++) { + for (d = 0; d < 4; d++) { + edatlookup[c][d] = 0; + if (c & 1) edatlookup[c][d] |= 1; + if (d & 1) edatlookup[c][d] |= 2; + if (c & 2) edatlookup[c][d] |= 0x10; + if (d & 2) edatlookup[c][d] |= 0x20; + } + } + + video_6to8 = malloc(4 * 256); + for (c = 0; c < 256; c++) + video_6to8[c] = calc_6to8(c); + video_15to32 = malloc(4 * 65536); #if 0 - for (c = 0; c < 65536; c++) - video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19); + for (c = 0; c < 65536; c++) + video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19); #endif - for (c = 0; c < 65536; c++) - video_15to32[c] = calc_15to32(c); + for (c = 0; c < 65536; c++) + video_15to32[c] = calc_15to32(c); - video_16to32 = malloc(4 * 65536); + video_16to32 = malloc(4 * 65536); #if 0 - for (c = 0; c < 65536; c++) - video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19); + for (c = 0; c < 65536; c++) + video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19); #endif - for (c = 0; c < 65536; c++) - video_16to32[c] = calc_16to32(c); + for (c = 0; c < 65536; c++) + video_16to32[c] = calc_16to32(c); - blit_data.wake_blit_thread = thread_create_event(); - blit_data.blit_complete = thread_create_event(); - blit_data.buffer_not_in_use = thread_create_event(); - blit_data.blit_thread = thread_create(blit_thread, NULL); -} - -void closevideo() -{ - thread_kill(blit_data.blit_thread); - thread_destroy_event(blit_data.buffer_not_in_use); - thread_destroy_event(blit_data.blit_complete); - thread_destroy_event(blit_data.wake_blit_thread); - - free(video_6to8); - free(video_15to32); - free(video_16to32); - destroy_bitmap(buffer); - destroy_bitmap(buffer32); + blit_data.wake_blit_thread = thread_create_event(); + blit_data.blit_complete = thread_create_event(); + blit_data.buffer_not_in_use = thread_create_event(); + blit_data.blit_thread = thread_create(blit_thread, NULL); } -static void blit_thread(void *param) +void +video_close(void) { - while (1) - { - thread_wait_event(blit_data.wake_blit_thread, -1); - thread_reset_event(blit_data.wake_blit_thread); - - if (blit_data.blit8) - video_blit_memtoscreen_8_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h); - else - video_blit_memtoscreen_func(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); - - blit_data.busy = 0; - thread_set_event(blit_data.blit_complete); - } + thread_kill(blit_data.blit_thread); + thread_destroy_event(blit_data.buffer_not_in_use); + thread_destroy_event(blit_data.blit_complete); + thread_destroy_event(blit_data.wake_blit_thread); + + free(video_6to8); + free(video_15to32); + free(video_16to32); + + destroy_bitmap(buffer); + destroy_bitmap(buffer32); } -void video_blit_complete() + +void +video_reset(void) { - blit_data.buffer_in_use = 0; - thread_set_event(blit_data.buffer_not_in_use); + pclog("Video_reset(rom=%i, gfx=%i)\n", romset, gfxcard); + + cga_palette = 0; + cgapal_rebuild(); + + /* + * Add and initialize the selected video card device. + * + * This will soon be moved into machine.c. + */ + video_reset_device(romset, gfxcard); } -void video_wait_for_blit() -{ - while (blit_data.busy) - thread_wait_event(blit_data.blit_complete, -1); - thread_reset_event(blit_data.blit_complete); -} -void video_wait_for_buffer() -{ - while (blit_data.buffer_in_use) - thread_wait_event(blit_data.buffer_not_in_use, -1); - thread_reset_event(blit_data.buffer_not_in_use); -} -void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +void +loadfont(wchar_t *s, int format) { - if (h <= 0) - return; - video_wait_for_blit(); - blit_data.busy = 1; - blit_data.buffer_in_use = 1; - blit_data.x = x; - blit_data.y = y; - blit_data.y1 = y1; - blit_data.y2 = y2; - blit_data.w = w; - blit_data.h = h; - blit_data.blit8 = 0; - thread_set_event(blit_data.wake_blit_thread); -} + FILE *f; + int c,d; -void video_blit_memtoscreen_8(int x, int y, int w, int h) -{ - if (h <= 0) - return; - video_wait_for_blit(); - blit_data.busy = 1; - blit_data.x = x; - blit_data.y = y; - blit_data.w = w; - blit_data.h = h; - blit_data.blit8 = 1; - thread_set_event(blit_data.wake_blit_thread); -} + f = rom_fopen(s, L"rb"); + if (f == NULL) return; -#ifdef __unix -void d3d_fs_take_screenshot(char *fn) -{ -} + switch (format) { + case 0: /* MDA */ + for (c=0; c<256; c++) + for (d=0; d<8; d++) + fontdatm[c][d] = fgetc(f); + for (c=0; c<256; c++) + for (d=0; d<8; d++) + fontdatm[c][d+8] = fgetc(f); + (void)fseek(f, 4096+2048, SEEK_SET); + for (c=0; c<256; c++) + for (d=0; d<8; d++) + fontdat[c][d] = fgetc(f); + break; -void d3d_take_screenshot(char *fn) -{ -} - -void ddraw_fs_take_screenshot(char *fn) -{ -} - -void ddraw_take_screenshot(char *fn) -{ -} - -void take_screenshot() -{ -} -#else -time_t now; -struct tm *info; -wchar_t screenshot_fn_partial[2048]; -wchar_t screenshot_fn[4096]; -wchar_t screenshot_path[4096]; - -BOOL DirectoryExists(LPCTSTR szPath) -{ - DWORD dwAttrib = GetFileAttributes(szPath); - - return (dwAttrib != INVALID_FILE_ATTRIBUTES && - (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); -} - -void take_screenshot() -{ - if ((vid_api < 0) || (vid_api > 1)) return; - time(&now); - info = localtime(&now); - memset(screenshot_fn, 0, 8192); - memset(screenshot_fn_partial, 0, 4096); - memset(screenshot_path, 0, 8192); - pclog("Video API is: %i\n", vid_api); - append_filename_w(screenshot_path, pcempath, L"screenshots", 4095); - if (!DirectoryExists(screenshot_path)) - { - CreateDirectory(screenshot_path, NULL); - } - if (vid_api == 1) - { - wcsftime(screenshot_fn_partial, 2048, L"screenshots\\%Y%m%d_%H%M%S.png", info); - append_filename_w(screenshot_fn, pcempath, screenshot_fn_partial, 4095); - if (video_fullscreen) - { - d3d_fs_take_screenshot(screenshot_fn); + case 1: /* PC200 */ + for (c=0; c<256; c++) + for (d=0; d<8; d++) + fontdatm[c][d] = fgetc(f); + for (c=0; c<256; c++) + for (d=0; d<8; d++) + fontdatm[c][d+8] = fgetc(f); + (void)fseek(f, 4096, SEEK_SET); + for (c=0; c<256; c++) { + for (d=0; d<8; d++) + fontdat[c][d] = fgetc(f); + for (d=0; d<8; d++) (void)fgetc(f); } - else - { - pclog("Direct 3D...\n"); - d3d_take_screenshot(screenshot_fn); - } - } - else if (vid_api == 0) - { - wcsftime(screenshot_fn_partial, 2048, L"screenshots\\%Y%m%d_%H%M%S.bmp", info); - append_filename_w(screenshot_fn, pcempath, screenshot_fn_partial, 4095); - if (video_fullscreen) - { - ddraw_fs_take_screenshot(screenshot_fn); - } - else - { - ddraw_take_screenshot(screenshot_fn); - } - } + break; + + default: + case 2: /* CGA */ + for (c=0; c<256; c++) + for (d=0; d<8; d++) + fontdat[c][d] = fgetc(f); + break; + + case 3: /* Wyse 700 */ + for (c=0; c<512; c++) + for (d=0; d<32; d++) + fontdatw[c][d] = fgetc(f); + break; + + case 4: /* MDSI Genius */ + for (c=0; c<256; c++) + for (d=0; d<16; d++) + fontdat8x12[c][d] = fgetc(f); + break; + + } + + (void)fclose(f); } -#endif diff --git a/src/video/video.h b/src/video/video.h index 53cb98c5c..1aaf09e84 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -1,130 +1,127 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -#ifdef __unix +#ifndef EMU_VIDEO_H +# define EMU_VIDEO_H -#include "allegro-main.h" - -#else - -typedef struct -{ - int w, h; - uint8_t *dat; - uint8_t *line[]; -} BITMAP; - -extern BITMAP *screen; - -BITMAP *create_bitmap(int w, int h); - -typedef struct -{ - uint8_t r, g, b; -} RGB; - -typedef RGB PALETTE[256]; #define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) #define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) -#endif -extern BITMAP *buffer, *buffer32; - -int video_card_available(int card); -char *video_card_getname(int card); -struct device_t *video_card_getdevice(int card); -int video_card_has_config(int card); -int video_card_getid(char *s); -int video_old_to_new(int card); -int video_new_to_old(int card); -char *video_get_internal_name(int card); -int video_get_video_from_internal_name(char *s); - -extern int video_fullscreen, video_fullscreen_scale, video_fullscreen_first; - -enum -{ - FULLSCR_SCALE_FULL = 0, - FULLSCR_SCALE_43, - FULLSCR_SCALE_SQ, - FULLSCR_SCALE_INT +enum { + FULLSCR_SCALE_FULL = 0, + FULLSCR_SCALE_43, + FULLSCR_SCALE_SQ, + FULLSCR_SCALE_INT }; -extern int egareads,egawrites; -extern int fullchange; -extern int changeframecount; +typedef struct { + int w, h; + uint8_t *dat; + uint8_t *line[]; +} BITMAP; -extern uint8_t fontdat[256][8]; -extern uint8_t fontdatm[256][16]; +typedef struct { + uint8_t r, g, b; +} RGB; + +typedef RGB PALETTE[256]; -extern uint32_t *video_6to8, *video_15to32, *video_16to32; -extern int xsize,ysize; +extern BITMAP *screen, + *buffer, + *buffer32; +extern PALETTE cgapal, + cgapal_mono[6]; +extern uint32_t pal_lookup[256]; +extern int video_fullscreen, + video_fullscreen_scale, + video_fullscreen_first; +extern int egareads,egawrites; +extern int fullchange; +extern int changeframecount; +extern uint8_t fontdat[256][8]; +extern uint8_t fontdatm[256][16]; +extern uint32_t *video_6to8, + *video_15to32, + *video_16to32; +extern int xsize,ysize; +extern int enable_overscan; +extern int overscan_x, + overscan_y; +extern int force_43; +extern int video_timing_b, + video_timing_w, + video_timing_l; +extern int video_speed; +extern int video_res_x, + video_res_y, + video_bpp; +extern int vid_resize; +extern int winsizex, + winsizey; +extern int cga_palette; +extern int vid_cga_contrast; +extern int video_grayscale; +extern int video_graytype; -extern float cpuclock; +extern float cpuclock; +extern int emu_fps, + frames; +extern int readflash; -extern int emu_fps, frames; - -extern int readflash; - -extern void (*video_recalctimings)(); - -void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); -void video_blit_memtoscreen_8(int x, int y, int w, int h); - -extern void (*video_blit_memtoscreen_func)(int x, int y, int y1, int y2, int w, int h); -extern void (*video_blit_memtoscreen_8_func)(int x, int y, int w, int h); - -/* Enable EGA/(S)VGA overscan border. */ -extern int enable_overscan; -extern int overscan_x, overscan_y; - -/* Forcibly stretch emulated video output to 4:3 or not. */ -extern int force_43; - -extern int video_timing_b, video_timing_w, video_timing_l; -extern int video_speed; - -extern int video_res_x, video_res_y, video_bpp; - -extern int vid_resize; - -void video_wait_for_blit(); -void video_wait_for_buffer(); - -extern int winsizex,winsizey; #ifdef __cplusplus extern "C" { #endif -void take_screenshot(); -void d3d_take_screenshot(wchar_t *fn); -void d3d_fs_take_screenshot(wchar_t *fn); -void ddraw_take_screenshot(wchar_t *fn); -void ddraw_fs_take_screenshot(wchar_t *fn); +/* Function handler pointers. */ +extern void (*video_recalctimings)(void); + + +/* Table functions. */ +extern int video_card_available(int card); +extern char *video_card_getname(int card); +#ifdef EMU_DEVICE_H +extern device_t *video_card_getdevice(int card); +#endif +extern int video_card_has_config(int card); +extern int video_card_getid(char *s); +extern int video_old_to_new(int card); +extern int video_new_to_old(int card); +extern char *video_get_internal_name(int card); +extern int video_get_video_from_internal_name(char *s); + + +extern void video_setblit(void(*blit8)(int,int,int,int), + void(*blit)(int,int,int,int,int,int)); +extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +extern void video_blit_memtoscreen_8(int x, int y, int w, int h); +extern void video_blit_complete(void); +extern void video_wait_for_blit(void); +extern void video_wait_for_buffer(void); + +extern BITMAP *create_bitmap(int w, int h); +extern void destroy_bitmap(BITMAP *b); +extern void cgapal_rebuild(void); +extern void hline(BITMAP *b, int x1, int y, int x2, uint32_t col); +extern void updatewindowsize(int x, int y); + +extern void video_init(void); +extern void video_close(void); +extern void video_reset(void); +extern void video_reset_device(int, int); +extern void video_update_timing(void); + +extern void loadfont(wchar_t *s, int format); + +#ifdef ENABLE_VRAM_DUMP +extern void svga_dump_vram(void); +#endif + #ifdef __cplusplus } #endif -extern int cga_palette; -extern int vid_cga_contrast; -extern int video_grayscale; -extern int video_graytype; +#endif /*EMU_VIDEO_H*/ -void loadfont(wchar_t *s, int format); -void initvideo(); -void video_init(); -void closevideo(); -void video_updatetiming(); - -void hline(BITMAP *b, int x1, int y, int x2, uint32_t col); -void updatewindowsize(int x, int y); - -#ifdef ENABLE_VRAM_DUMP -void svga_dump_vram(); -#endif diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 74b7c6c61..07a830da5 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -8,10 +8,11 @@ * * Windows resource script. * - * Version: @(#)86Box.rc 1.0.9 2017/09/07 + * Version: @(#)86Box.rc 1.0.17 2017/10/14 * * Authors: Miran Grca, * Fred N. van Kempen, + * * Copyright 2016,2017 Miran Grca. */ #include @@ -40,13 +41,17 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // Menu // -MAINMENU MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Action" BEGIN MENUITEM "&Hard Reset", IDM_ACTION_HRESET + MENUITEM SEPARATOR MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM SEPARATOR + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM SEPARATOR + MENUITEM "&Pause", IDM_ACTION_PAUSE MENUITEM SEPARATOR MENUITEM "E&xit", IDM_ACTION_EXIT END @@ -57,43 +62,49 @@ BEGIN MENUITEM SEPARATOR POPUP "Re&nderer" BEGIN - MENUITEM "&DirectDraw", IDM_VID_DDRAW - MENUITEM "Direct&3D 9", IDM_VID_D3D + MENUITEM "&DirectDraw", IDM_VID_DDRAW + MENUITEM "Direct&3D 9", IDM_VID_D3D +#ifdef USE_VNC + MENUITEM "&VNC", IDM_VID_VNC +#endif +#ifdef USE_RDP + MENUITEM "&RDP", IDM_VID_RDP +#endif END MENUITEM SEPARATOR POPUP "&Window scale factor" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X END MENUITEM SEPARATOR MENUITEM "&Fullscreen\tCtrl+Alt+PageUP", IDM_VID_FULLSCREEN POPUP "Fullscreen &stretch mode" BEGIN - MENUITEM "&Full screen stretch", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 - MENUITEM "&Square pixels", IDM_VID_FS_SQ - MENUITEM "&Integer scale", IDM_VID_FS_INT + MENUITEM "&Full screen stretch", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Square pixels", IDM_VID_FS_SQ + MENUITEM "&Integer scale", IDM_VID_FS_INT END POPUP "E&GA/(S)VGA settings" BEGIN - MENUITEM "&Inverted VGA monitor", IDM_VID_INVERT - MENUITEM "E&GA/(S)VGA overscan", IDM_VID_OVERSCAN + MENUITEM "&Inverted VGA monitor", IDM_VID_INVERT + MENUITEM "E&GA/(S)VGA overscan", IDM_VID_OVERSCAN POPUP "VGA screen &type" BEGIN - MENUITEM "RGB &Color", IDM_VID_GRAY_RGB - MENUITEM "&RGB Grayscale", IDM_VID_GRAY_MONO - MENUITEM "&Amber monitor", IDM_VID_GRAY_AMBER - MENUITEM "&Green monitor", IDM_VID_GRAY_GREEN - MENUITEM "&White monitor", IDM_VID_GRAY_WHITE + MENUITEM "RGB &Color", IDM_VID_GRAY_RGB + MENUITEM "&RGB Grayscale", IDM_VID_GRAY_MONO + MENUITEM "&Amber monitor", IDM_VID_GRAY_AMBER + MENUITEM "&Green monitor", IDM_VID_GRAY_GREEN + MENUITEM "&White monitor", IDM_VID_GRAY_WHITE END POPUP "Grayscale &conversion type" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Average", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Average", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR @@ -131,11 +142,9 @@ BEGIN # ifdef ENABLE_SERIAL_LOG MENUITEM "Enable Serial Port logs\tCtrl+F3", IDM_LOG_SERIAL # endif -#ifdef USE_NETWORK # ifdef ENABLE_NIC_LOG MENUITEM "Enable Network logs\tCtrl+F9", IDM_LOG_NIC # endif -#endif # ifdef ENABLE_LOG_COMMANDS # ifdef ENABLE_LOG_TOGGLES MENUITEM SEPARATOR @@ -155,13 +164,18 @@ BEGIN END END +StatusBarMenu MENU DISCARDABLE +BEGIN + MENUITEM SEPARATOR +END + ///////////////////////////////////////////////////////////////////////////// // // Accelerator // -MAINACCEL ACCELERATORS MOVEABLE PURE +MainAccel ACCELERATORS MOVEABLE PURE BEGIN #ifdef ENABLE_VRAM_DUMP VK_F1, IDM_DUMP_VRAM, CONTROL, VIRTKEY @@ -193,6 +207,7 @@ BEGIN VK_PRIOR,IDM_VID_FULLSCREEN, VIRTKEY, CONTROL , ALT VK_F11, IDM_ACTION_SCREENSHOT, VIRTKEY, CONTROL VK_F12, IDM_ACTION_RESET_CAD, VIRTKEY, CONTROL + VK_PAUSE,IDM_ACTION_PAUSE END @@ -263,15 +278,14 @@ BEGIN 12,12 LTEXT "MB",IDT_1705,123,64,10,10 LTEXT "Memory:",IDT_1706,7,64,30,10 - LTEXT "NVR Path:",IDT_1700,7,83,60,10 - EDITTEXT IDC_EDIT_NVR_PATH,71,82,138,12,ES_AUTOHSCROLL - PUSHBUTTON "&Specify...",IDC_BUTTON_NVR_PATH,214,82,46,12 - CONTROL "Dynamic Recompiler",IDC_CHECK_DYNAREC,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,100,94,10 + CONTROL "Enable time sync",IDC_CHECK_SYNC,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,100,102,10 CONTROL "Enable FPU",IDC_CHECK_FPU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,100,113,10 - CONTROL "Enable time sync",IDC_CHECK_SYNC,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,115,102,10 +#ifdef USE_DYNAREC + CONTROL "Dynamic Recompiler",IDC_CHECK_DYNAREC,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,115,94,10 +#endif END DLG_CFG_VIDEO DIALOG DISCARDABLE 97, 0, 267, 63 @@ -338,7 +352,6 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,7,99,94,10 END -#ifdef USE_NETWORK DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" @@ -356,7 +369,6 @@ BEGIN WS_TABSTOP PUSHBUTTON "Configure",IDC_CONFIGURE_NET,214,43,46,12 END -#endif DLG_CFG_PORTS DIALOG DISCARDABLE 97, 0, 267, 61 STYLE DS_CONTROL | WS_CHILD @@ -529,26 +541,17 @@ END 177 ICON DISCARDABLE "win/icons/removable_disk_active.ico" 192 ICON DISCARDABLE "win/icons/hard_disk.ico" 193 ICON DISCARDABLE "win/icons/hard_disk_active.ico" -#ifdef USE_NETWORK 208 ICON DISCARDABLE "win/icons/network.ico" 209 ICON DISCARDABLE "win/icons/network_active.ico" -#endif 256 ICON DISCARDABLE "win/icons/machine.ico" 257 ICON DISCARDABLE "win/icons/display.ico" 258 ICON DISCARDABLE "win/icons/input_devices.ico" 259 ICON DISCARDABLE "win/icons/sound.ico" -#ifdef USE_NETWORK 260 ICON DISCARDABLE "win/icons/network.ico" 261 ICON DISCARDABLE "win/icons/ports.ico" 262 ICON DISCARDABLE "win/icons/other_peripherals.ico" 263 ICON DISCARDABLE "win/icons/hard_disk.ico" 264 ICON DISCARDABLE "win/icons/removable_devices.ico" -#else -260 ICON DISCARDABLE "win/icons/ports.ico" -261 ICON DISCARDABLE "win/icons/other_peripherals.ico" -262 ICON DISCARDABLE "win/icons/hard_disk.ico" -263 ICON DISCARDABLE "win/icons/removable_devices.ico" -#endif 384 ICON DISCARDABLE "win/icons/floppy_525_empty.ico" 385 ICON DISCARDABLE "win/icons/floppy_525_empty_active.ico" 400 ICON DISCARDABLE "win/icons/floppy_35_empty.ico" @@ -639,7 +642,6 @@ BEGIN BOTTOMMARGIN, 109 END -#ifdef USE_NETWORK DLG_CFG_NETWORK, DIALOG BEGIN LEFTMARGIN, 7 @@ -647,7 +649,6 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 56 END -#endif DLG_CFG_PORTS, DIALOG BEGIN @@ -699,7 +700,7 @@ BEGIN IDS_2053 "Invalid number of sectors (valid values are between 1 and 63)" IDS_2054 "Invalid number of heads (valid values are between 1 and 16)" IDS_2055 "Invalid number of cylinders (valid values are between 1 and 266305)" - IDS_2056 "Specify the NVR Path" + IDS_2056 "No usable ROM images found!" IDS_2057 "(empty)" IDS_2058 "(host drive %c:)" IDS_2059 "Turbo" @@ -716,18 +717,11 @@ BEGIN IDS_2066 "Display" IDS_2067 "Input devices" IDS_2068 "Sound" -#ifdef USE_NETWORK IDS_2069 "Network" IDS_2070 "Ports (COM & LPT)" IDS_2071 "Other peripherals" IDS_2072 "Hard disks" IDS_2073 "Removable devices" -#else - IDS_2069 "Ports (COM & LPT)" - IDS_2070 "Other peripherals" - IDS_2071 "Hard disks" - IDS_2072 "Removable devices" -#endif IDS_2074 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" IDS_2075 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" IDS_2076 "Host CD/DVD Drive (%c:)" @@ -753,6 +747,7 @@ BEGIN IDS_2092 "Bus" IDS_2093 "DMA" IDS_2094 "KB" + IDS_2095 "Neither DirectDraw nor Direct3D available !" END STRINGTABLE DISCARDABLE @@ -811,11 +806,9 @@ END STRINGTABLE DISCARDABLE BEGIN -#ifdef USE_NETWORK IDS_2139 "PCap failed to set up because it may not be initialized" IDS_2140 "No PCap devices found" IDS_2141 "Invalid PCap device" -#endif IDS_2142 "&Notify disk change" IDS_2143 "Type" IDS_2144 "Standard 2-button joystick(s)" @@ -827,12 +820,12 @@ BEGIN IDS_2150 "Thrustmaster Flight Control System" IDS_2151 "Disabled" IDS_2152 "None" - IDS_2153 "AT Fixed Disk Adapter" - IDS_2154 "Internal IDE" + IDS_2153 "Unable to load Keyboard Accelerators!" + IDS_2154 "Unable to register Raw Input!" IDS_2155 "IRQ %i" IDS_2156 "%" PRIu64 IDS_2157 "%" PRIu64 " MB (CHS: %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")" - IDS_2158 "Floppy %i (%s): %ws" + IDS_2158 "Floppy %i (%s): %ls" IDS_2159"All floppy images (*.0??;*.12;*.144;*.360;*.720;*.86F;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMD;*.IMG;*.JSON;*.TD0;*.VFD;*.XDF)\0*.0??;*.12;*.144;*.360;*.720;*.86F;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMD;*.IMG;*.JSON;*.TD0;*.VFD;*.XDF\0Advanced sector-based images (*.IMD;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector-based images (*.0??;*.12;*.144;*.360;*.720;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMG;*.JSON;*.VFD;*.XDF)\0*.0??;*.12;*.144;*.360;*.720;*.BIN;*.CQ;*.CQM;*.DSK;*.FDI;*.FDF;*.FLP;*.HDM;*.IMA;*.IMG;*.JSON;*.VFD;*.XDF\0Flux images (*.FDI)\0*.FDI\0Surface-based images (*.86F)\0*.86F\0All files (*.*)\0*.*\0" IDS_2160 "Configuration files (*.CFG)\0*.CFG\0All files (*.*)\0*.*\0" IDS_2161 "&New image..." @@ -878,7 +871,7 @@ BEGIN IDS_4112 "Please enter a valid file name" IDS_4113 "Remember to partition and format the new drive" IDS_4114 "MFM/RLL or ESDI CD-ROM drives never existed" - IDS_4115 "Removable disk %i (SCSI): %ws" + IDS_4115 "Removable disk %i (SCSI): %ls" IDS_4352 "MFM/RLL" IDS_4353 "XT IDE" diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw new file mode 100644 index 000000000..c16b33be4 --- /dev/null +++ b/src/win/Makefile.mingw @@ -0,0 +1,536 @@ +# +# 86Box A hypervisor and IBM PC system emulator that specializes in +# running old operating systems and software designed for IBM +# PC systems and compatibles from 1981 through fairly recent +# system designs based on the PCI bus. +# +# This file is part of the 86Box distribution. +# +# Makefile for Win32 (MinGW32) environment. +# +# Version: @(#)Makefile.mingw 1.0.63 2017/10/14 +# +# Authors: Miran Grca, +# Fred N. van Kempen, +# + +# Name of the executable. +ifndef PROG +PROG := 86Box +endif + +# Various compile-time options. +# -DROM_TRACE=0xc800 traces ROM access from segment C800 +# -DIO_TRACE=0x66 traces I/O on port 0x66 +STUFF := + +# Add feature selections here. +# -DANSI_CFG forces the config file to ANSI encoding. +# -DENABLE_VRAM_DUMP enables Video Ram dumping. +# -DENABLE_LOG_BREAKPOINT enables extra logging. +# -DENABLE_SCSI_BIOS_COMMAND_LOG=n enables extra logging. +# -DENABLE_AHA154X_LOG=n enables extra logging. +# -DENABLE_BUSLOGIC_LOG=n enables extra logging. +# -DENABLE_CDROM_LOG enables extra logging. +# -DENABLE_D86F_LOG enables extra logging. +# -DENABLE_FDC_LOG enables extra logging. +# -DENABLE_HDD_IMAGE_LOG enables extra logging. +# -DENABLE_IDE_LOG enables extra logging. +# -DENABLE_SERIAL_LOG enables extra logging. +# -DENABLE_NIC_LOG enables extra logging. +# -DENABLE_KEYBOARD_LOG enables extra logging. +ifndef EXTRAS +EXTRAS := +endif + +# Defaults for several build options (possibly defined in a chained file.) +ifndef AUTODEP +AUTODEP := n +endif +ifndef DEBUG +DEBUG := n +endif +ifndef OPTIM +OPTIM := n +endif +ifndef RELEASE +RELEASE := n +endif +ifndef USB +USB := n +endif +ifndef VNC +VNC := n +endif +ifndef RDP +RDP := n +endif +ifndef DEV_BUILD +DEV_BUILD := n +endif +ifndef DEV_BRANCH +DEV_BRANCH := n +endif +ifndef CIRRUS +CIRRUS := n +endif +ifndef NE1000 +NE1000 := n +endif +ifndef NV_RIVA +NV_RIVA := n +endif +ifndef FLUIDSYNTH +FLUIDSYNTH := y +endif +ifndef MUNT +MUNT := y +endif +ifndef PAS16 +PAS16 = n +endif +ifndef DYNAREC +DYNAREC := y +endif +ifndef X64 +X64 := n +endif + +ifeq ($(DEV_BUILD), y) +DEV_BRANCH := y +CIRRUS := y +NE1000 := y +NV_RIVA := y +PAS16 := y +VNC := y +endif + + +######################################################################### +# Nothing should need changing from here on.. # +######################################################################### +VPATH := $(EXPATH) . cpu \ + cdrom disk floppy game machine \ + sound \ + sound/munt sound/munt/c_interface sound/munt/sha1 \ + sound/munt/srchelper \ + sound/resid-fp \ + scsi video lzf network network/slirp win +ifeq ($(X64), y) +CPP := g++ -m64 +CC := gcc -m64 +else +CPP := g++ -m32 +CC := gcc -m32 +endif +WINDRES := windres +DEPS = -MMD -MF $*.d -c $< +DEPFILE := win/.depends + +# Set up the correct toolchain flags. +OPTS := -DWIN32 $(EXTRAS) $(STUFF) +ifdef EXFLAGS +OPTS += $(EXFLAGS) +endif +ifdef EXINC +OPTS += -I$(EXINC) +endif +ifeq ($(X64), y) + ifeq ($(OPTIM), y) + DFLAGS := -march=native + else + DFLAGS := + endif +else + ifeq ($(OPTIM), y) + DFLAGS := -march=native + else + DFLAGS := -march=i686 + endif +endif +ifeq ($(DEBUG), y) + DFLAGS += -ggdb -DDEBUG + AOPTIM := + ifndef COPTIM + COPTIM := -Og + endif +else + ifeq ($(OPTIM), y) + AOPTIM := -mtune=native + ifndef COPTIM + COPTIM := -O6 + endif + else + ifndef COPTIM + COPTIM := -O3 + endif + endif +endif +AFLAGS := -msse -msse2 -mfpmath=sse +CFLAGS := $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) $(AFLAGS) \ + -fomit-frame-pointer -mstackrealign -Wall +RFLAGS := --input-format=rc -O coff +ifeq ($(RELEASE), y) +CFLAGS += -DRELEASE_BUILD +RFLAGS += -DRELEASE_BUILD +endif +ifeq ($(VRAMDUMP), y) +CFLAGS += -DENABLE_VRAM_DUMP +RFLAGS += -DENABLE_VRAM_DUMP +endif +ifeq ($(X64), y) +PLATCG := codegen_x86-64.o +CGOPS := codegen_ops_x86-64.h +VCG := vid_voodoo_codegen_x86-64.h +else +PLATCG := codegen_x86.o +CGOPS := codegen_ops_x86.h +VCG := vid_voodoo_codegen_x86.h +endif + + +# Optional modules. +ifeq ($(DYNAREC), y) +CFLAGS += -DUSE_DYNAREC +RFLAGS += -DUSE_DYNAREC +DYNARECOBJ := 386_dynarec_ops.o \ + codegen.o \ + codegen_ops.o \ + codegen_timing_common.o codegen_timing_486.o \ + codegen_timing_686.o codegen_timing_pentium.o \ + codegen_timing_winchip.o $(PLATCG) +endif + +ifeq ($(FLUIDSYNTH), y) +CFLAGS += -DUSE_FLUIDSYNTH +FSYNTHOBJ := midi_fluidsynth.o +endif + +ifeq ($(MUNT), y) +CFLAGS += -DUSE_MUNT +MUNTOBJ := midi_mt32.o \ + Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \ + LA32FloatWaveGenerator.o LA32WaveGenerator.o \ + MidiStreamParser.o Part.o Partial.o PartialManager.o \ + Poly.o ROMInfo.o SampleRateConverter_dummy.o Synth.o \ + Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o +endif + +ifeq ($(VNC), y) +CFLAGS += -DUSE_VNC +RFLAGS += -DUSE_VNC + ifneq ($(VNC_PATH), ) + CFLAGS += -I$(VNC_PATH)\INCLUDE + VNCLIB := -L$(VNC_PATH)\LIB + endif +VNCLIB += -lvncserver +VNCOBJ := win_vnc.o +endif + +ifeq ($(RDP), y) +CFLAGS += -DUSE_RDP +RFLAGS += -DUSE_RDP + ifneq ($(RDP_PATH), ) + CFLAGS += -I$(RDP_PATH)\INCLUDE + RDPLIB := -L$(RDP_PATH)\LIB + endif +RDPLIB += -lrdp +RDPOBJ := win_rdp.o +endif + +# Options for the DEV branch. +ifeq ($(DEV_BRANCH), y) +CFLAGS += -DDEV_BRANCH +DEVBROBJ := + +ifeq ($(CIRRUS), y) +CFLAGS += -DUSE_CIRRUS +DEVBROBJ += vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o +endif + +ifeq ($(NE1000), y) +CFLAGS += -DUSE_NE1000 +endif + +ifeq ($(NV_RIVA), y) +CFLAGS += -DUSE_RIVA +DEVBROBJ += vid_nv_riva128.o +endif + +ifeq ($(PAS16), y) +CFLAGS += -DUSE_PAS16 +DEVBROBJ += snd_pas16.o +endif + +endif + + +# Options for works-in-progress. +ifndef SERIAL +SERIAL := serial.o +endif +ifndef EUROPC +EUROPC := machine_europc.o +endif + + +MAINOBJ := pc.o config.o random.o timer.o io.o dma.o nmi.o pic.o \ + pit.o ppi.o pci.o mca.o mcr.o mem.o memregs.o rom.o \ + device.o nvr.o nvr_at.o nvr_ps2.o \ + intel.o intel_flash.o intel_sio.o + +CPUOBJ := cpu.o 386.o 386_dynarec.o 808x.o \ + x86seg.o x87.o \ + $(DYNARECOBJ) + +MCHOBJ := machine.o \ + machine_common.o \ + machine_amstrad.o $(EUROPC) \ + machine_olivetti_m24.o \ + machine_pcjr.o \ + machine_tandy.o \ + machine_xt.o machine_xt_laserxt.o \ + machine_at.o \ + machine_at_ali1429.o machine_at_commodore.o \ + machine_at_neat.o machine_at_headland.o \ + machine_at_opti495.o machine_at_scat.o \ + machine_at_wd76c10.o \ + machine_at_sis_85c471.o machine_at_sis_85c496.o \ + machine_at_430lx_nx.o machine_at_430fx.o \ + machine_at_430hx.o machine_at_430vx.o \ + machine_at_440fx.o \ + machine_ps1.o \ + machine_ps2_isa.o machine_ps2_mca.o + +DEVOBJ := bugger.o lpt.o $(SERIAL) \ + tandy_eeprom.o tandy_rom.o \ + sio_detect.o \ + sio_fdc37c665.o sio_fdc37c669.o sio_fdc37c932fr.o \ + sio_pc87306.o sio_w83877f.o sio_um8669f.o piix.o \ + keyboard.o \ + keyboard_xt.o keyboard_at.o keyboard_pcjr.o \ + keyboard_amstrad.o keyboard_olim24.o \ + gameport.o \ + joystick_standard.o joystick_ch_flightstick_pro.o \ + joystick_sw_pad.o joystick_tm_fcs.o \ + mouse.o \ + mouse_serial.o mouse_ps2.o mouse_bus.o + +FDDOBJ := fdd.o fdc.o fdi2raw.o \ + floppy.o floppy_common.o floppy_86f.o \ + floppy_fdi.o floppy_imd.o floppy_img.o floppy_json.o \ + floppy_td0.o + +HDDOBJ := hdd.o \ + hdd_image.o hdd_table.o \ + hdc.o \ + hdc_esdi_at.o hdc_esdi_mca.o hdc_ide.o hdc_mfm_at.o \ + hdc_mfm_xt.o hdc_xtide.o + +CDROMOBJ := cdrom.o \ + cdrom_dosbox.o cdrom_image.o cdrom_null.o + +ifeq ($(USB), y) +USBOBJ := usb.o +endif + +SCSIOBJ := scsi.o \ + scsi_bus.o scsi_device.o \ + scsi_disk.o \ + scsi_x54x.o \ + scsi_buslogic.o scsi_aha154x.o \ + scsi_ncr5380.o + +NETOBJ := network.o \ + net_pcap.o \ + net_slirp.o \ + bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o \ + ip_input.o queue.o tcp_input.o debug.o ip_output.o \ + sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o \ + net_ne2000.o + +SNDOBJ := sound.o \ + openal.o \ + dbopl.o nukedopl.o \ + snd_resid.o \ + convolve.o convolve-sse.o envelope.o extfilt.o \ + filter.o pot.o sid.o voice.o wave6581__ST.o \ + wave6581_P_T.o wave6581_PS_.o wave6581_PST.o \ + wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ + wave8580_PST.o wave.o \ + midi.o $(FSYNTHOBJ) $(MUNTOBJ) \ + midi_system.o \ + snd_speaker.o \ + snd_ps1.o snd_pssj.o \ + snd_lpt_dac.o snd_lpt_dss.o \ + snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \ + snd_sb.o snd_sb_dsp.o snd_cms.o snd_dbopl.o \ + snd_emu8k.o snd_gus.o snd_opl.o \ + snd_mpu401.o \ + snd_sn76489.o snd_ssi2001.o snd_wss.o \ + snd_ym7128.o + +VIDOBJ := video.o \ + vid_table.o \ + vid_cga.o vid_cga_comp.o vid_mda.o \ + vid_ega.o vid_ega_render.o \ + vid_vga.o vid_svga.o vid_svga_render.o \ + vid_hercules.o vid_herculesplus.o vid_incolor.o \ + vid_colorplus.o \ + vid_genius.o \ + vid_s3.o vid_s3_virge.o \ + vid_et4000.o vid_et4000w32.o vid_icd2061.o \ + vid_oti067.o \ + vid_paradise.o \ + vid_tvga.o vid_tgui9440.o vid_tkd8001_ramdac.o \ + vid_ati_eeprom.o vid_ati18800.o vid_ati28800.o \ + vid_ati68860_ramdac.o vid_ati_mach64.o \ + vid_ics2595.o \ + vid_sc1502x_ramdac.o \ + vid_sdac_ramdac.o \ + vid_stg_ramdac.o \ + vid_wy700.o \ + vid_voodoo.o \ + vid_pcjr.o \ + vid_ps1_svga.o \ + vid_olivetti_m24.o \ + vid_pc1512.o vid_pc1640.o \ + vid_pc200.o \ + vid_tandy.o vid_tandysl.o + +PLATOBJ := win.o \ + win_ddraw.o win_ddraw_fs.o win_d3d.o win_d3d_fs.o \ + $(VNCOBJ) $(RDPOBJ) \ + win_dynld.o win_thread.o $(WSERIAL) win_cdrom.o win_cdrom_ioctl.o \ + win_keyboard.o win_mouse.o win_joystick.o win_midi.o \ + win_dialog.o win_about.o win_status.o win_stbar.o \ + win_settings.o win_deviceconfig.o win_joystickconfig.o \ + $(OPENDIR) + +OBJ := $(MAINOBJ) $(CPUOBJ) $(MCHOBJ) $(DEVOBJ) \ + $(FDDOBJ) $(CDROMOBJ) $(HDDOBJ) \ + $(USBOBJ) $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \ + $(PLATOBJ) $(DEVBROBJ) +ifdef EXOBJ +OBJ += $(EXOBJ) +endif + +LZFOBJ := lzf_c.o lzf_d.o + +LIBS := -mwindows \ + -lopenal.dll \ + -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ + -lcomctl32 -lwinmm +ifeq ($(VNC), y) +LIBS += $(VNCLIB) -lws2_32 -lz +endif +ifeq ($(RDP), y) +LIBS += $(RDPLIB) +endif +LIBS += -lkernel32 -lwsock32 -liphlpapi -lpsapi +LIBS += -lpthread -static -lstdc++ -lgcc +LIBS += -Wl,--large-address-aware + + +# Build module rules. +ifeq ($(AUTODEP), y) +%.o: %.c + @echo $< + @$(CC) $(CFLAGS) $(DEPS) -c $< + +%.o: %.cc + @echo $< + @$(CPP) $(CFLAGS) $(DEPS) -c $< + +%.o: %.cpp + @echo $< + @$(CPP) $(CFLAGS) $(DEPS) -c $< +else +%.o: %.c + @echo $< + @$(CC) $(CFLAGS) -c $< + +%.o: %.cc + @echo $< + @$(CPP) $(CFLAGS) -c $< + +%.o: %.cpp + @echo $< + @$(CPP) $(CFLAGS) -c $< + +%.d: %.c $(wildcard $*.d) + @echo $< + @$(CC) $(CFLAGS) $(DEPS) -E $< >NUL + +%.d: %.cc $(wildcard $*.d) + @echo $< + @$(CPP) $(CFLAGS) $(DEPS) -E $< >NUL + +%.d: %.cpp $(wildcard $*.d) + @echo $< + @$(CPP) $(CFLAGS) $(DEPS) -E $< >NUL +endif + + +all: $(PROG).exe pcap_if.exe + + +86Box.res: 86Box.rc + @echo Processing $< + @$(WINDRES) $(RFLAGS) $(EXTRAS) -i $< -o 86Box.res + +$(PROG).exe: $(OBJ) $(LZFOBJ) 86Box.res + @echo Linking $(PROG).exe .. + @$(CC) -o $(PROG).exe $(OBJ) $(LZFOBJ) 86Box.res $(LIBS) +ifneq ($(DEBUG), y) + @strip $(PROG).exe +endif + +pcap_if.res: pcap_if.rc + @echo Processing $< + @$(WINDRES) $(RFLAGS) -i $< -o pcap_if.res + +pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res + @echo Linking pcap_if.exe .. + @$(CC) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res +ifneq ($(DEBUG), y) + @strip pcap_if.exe +endif + + +clean: + @echo Cleaning objects.. + @-rm -f *.o 2>NUL + @-rm -f *.res 2>NUL + +clobber: clean + @echo Cleaning executables.. + @-rm -f *.d 2>NUL + @-rm -f *.exe 2>NUL +# @-rm -f $(DEPFILE) 2>NUL + +ifneq ($(AUTODEP), y) +depclean: + @-rm -f $(DEPFILE) 2>NUL + @echo Creating dependencies.. + @echo # Run "make depends" to re-create this file. $(DEPFILE) + +depends: DEPOBJ=$(OBJ:%.o=%.d) +depends: depclean $(OBJ:%.o=%.d) + @-cat $(DEPOBJ) >>$(DEPFILE) + @-rm -f $(DEPOBJ) + +$(DEPFILE): +endif + + +# Module dependencies. +ifeq ($(AUTODEP), y) +#-include $(OBJ:%.o=%.d) (better, but sloooowwwww) +-include *.d +else +include $(wildcard $(DEPFILE)) +endif + + +# End of Makefile.mingw. diff --git a/src/Makefile.mingw64 b/src/win/Makefile.mingw64 similarity index 100% rename from src/Makefile.mingw64 rename to src/win/Makefile.mingw64 diff --git a/src/win/icons/cdrom.ico b/src/win/icons/cdrom.ico index 89757bd36..a3fb90a8b 100644 Binary files a/src/win/icons/cdrom.ico and b/src/win/icons/cdrom.ico differ diff --git a/src/win/icons/cdrom_active.ico b/src/win/icons/cdrom_active.ico index 1aa7bca69..91f4f3ec7 100644 Binary files a/src/win/icons/cdrom_active.ico and b/src/win/icons/cdrom_active.ico differ diff --git a/src/win/icons/cdrom_disabled.ico b/src/win/icons/cdrom_disabled.ico index dd2d9f026..02220893c 100644 Binary files a/src/win/icons/cdrom_disabled.ico and b/src/win/icons/cdrom_disabled.ico differ diff --git a/src/win/icons/cdrom_empty.ico b/src/win/icons/cdrom_empty.ico index 0653c8e27..647ebeae6 100644 Binary files a/src/win/icons/cdrom_empty.ico and b/src/win/icons/cdrom_empty.ico differ diff --git a/src/win/icons/cdrom_empty_active.ico b/src/win/icons/cdrom_empty_active.ico index 87948abe0..f14b71145 100644 Binary files a/src/win/icons/cdrom_empty_active.ico and b/src/win/icons/cdrom_empty_active.ico differ diff --git a/src/win/plat_dinput.h b/src/win/plat_dinput.h deleted file mode 100644 index b5d7eca06..000000000 --- a/src/win/plat_dinput.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern LPDIRECTINPUT lpdi; diff --git a/src/win/plat_iodev.h b/src/win/plat_iodev.h deleted file mode 100644 index 650973483..000000000 --- a/src/win/plat_iodev.h +++ /dev/null @@ -1,5 +0,0 @@ -extern void cdrom_eject(uint8_t id); -extern void cdrom_reload(uint8_t id); -extern void removable_disk_unload(uint8_t id); -extern void removable_disk_eject(uint8_t id); -extern void removable_disk_reload(uint8_t id); diff --git a/src/win/plat_thread.h b/src/win/plat_thread.h deleted file mode 100644 index db9fac030..000000000 --- a/src/win/plat_thread.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#ifndef PLAT_THREAD_H -# define PLAT_THREAD_H - - -typedef void thread_t; -typedef void event_t; - - -extern thread_t *thread_create(void (*thread_rout)(void *param), void *param); -extern void thread_kill(thread_t *handle); - -extern event_t *thread_create_event(void); -extern void thread_set_event(event_t *event); -extern void thread_reset_event(event_t *_event); -extern int thread_wait_event(event_t *event, int timeout); -extern void thread_destroy_event(event_t *_event); - -extern void thread_sleep(int t); - -extern void *thread_create_mutex(wchar_t *name); -extern void thread_close_mutex(void *mutex); -extern uint8_t thread_wait_mutex(void *mutex); -extern uint8_t thread_release_mutex(void *mutex); - -extern void startslirp(void); -extern void endslirp(void); - - -#endif /*PLAT_THREAD_H*/ diff --git a/src/win/plat_ticks.h b/src/win/plat_ticks.h deleted file mode 100644 index d6e48f37a..000000000 --- a/src/win/plat_ticks.h +++ /dev/null @@ -1,2 +0,0 @@ -uint32_t get_ticks(void); -void delay_ms(uint32_t count); diff --git a/src/win/plat_ui.h b/src/win/plat_ui.h deleted file mode 100644 index 92eed6ab6..000000000 --- a/src/win/plat_ui.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __unix -extern void plat_msgbox_error(int i); -extern wchar_t *plat_get_string_from_id(int i); - -#ifndef IDS_2077 -#define IDS_2077 2077 -#endif - -#ifndef IDS_2078 -#define IDS_2078 2078 -#endif - -#ifndef IDS_2079 -#define IDS_2079 2079 -#endif - -#ifndef IDS_2139 -#define IDS_2139 2139 -#endif - -#ifndef IDS_2171 -#define IDS_2171 2171 -#endif - -#ifndef IDS_2219 -#define IDS_2219 2219 -#endif -#endif - -extern void plat_msgbox_fatal(char *string); -extern void get_executable_name(wchar_t *s, int size); -extern void set_window_title(wchar_t *s); -extern void startblit(void); -extern void endblit(void); diff --git a/src/win/resource.h b/src/win/resource.h index f0b54be18..5e050383c 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -9,13 +9,13 @@ * Windows resource defines. * * NOTE: FIXME: Strings 2176 and 2193 are same. - * NOTE: FIXME: string 2095 not in use. * - * Version: @(#)resource.h 1.0.5 2017/08/24 + * Version: @(#)resource.h 1.0.12 2017/10/13 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempem, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ @@ -100,12 +100,12 @@ #define IDC_COMBO_CPU 1013 #define IDC_CHECK_FPU 1014 #define IDC_COMBO_WS 1015 +#ifdef USE_DYNAREC #define IDC_CHECK_DYNAREC 1016 +#endif #define IDC_MEMTEXT 1017 #define IDC_MEMSPIN 1018 #define IDC_TEXT_MB IDT_1705 -#define IDC_EDIT_NVR_PATH 1019 -#define IDC_BUTTON_NVR_PATH 1020 #define IDC_VIDEO 1030 /* video config */ #define IDC_COMBO_VIDEO 1031 @@ -211,7 +211,7 @@ #define IDS_2053 2053 // "Invalid number of sectors.." #define IDS_2054 2054 // "Invalid number of heads.." #define IDS_2055 2055 // "Invalid number of cylinders.." -#define IDS_2056 2056 // "Please enter a valid file name" +#define IDS_2056 2056 // "No usable ROM images found!" #define IDS_2057 2057 // "Unable to open the file for write" #define IDS_2058 2058 // "Attempting to create a HDI.." #define IDS_2059 2059 // "Remember to partition and.." @@ -250,7 +250,7 @@ #define IDS_2092 2092 // "Bus" #define IDS_2093 2093 // "DMA" #define IDS_2094 2094 // "KB" -#define IDS_2095 2095 +#define IDS_2095 2095 // "No renderer available!" #define IDS_2096 2096 // "Slave" #define IDS_2097 2097 // "SCSI (ID %s, LUN %s)" #define IDS_2098 2098 // "Adapter Type" @@ -308,10 +308,10 @@ #define IDS_2150 2150 // "Thrustmaster Flight Control System" #define IDS_2151 2151 // "Disabled" #define IDS_2152 2152 // "None" -#define IDS_2153 2153 // "AT Fixed Disk Adapter" -#define IDS_2154 2154 // "Internal IDE" +#define IDS_2153 2153 // "Unable to load Accelerators" +#define IDS_2154 2154 // "Unable to register Raw Input" #define IDS_2155 2155 // "IRQ %i" -#define IDS_2156 2156 // "MFM (%01i:%01i)" +#define IDS_2156 2156 // "MFM/RLL (%91i:%01i)" #define IDS_2157 2157 // "IDE (PIO+DMA) (%01i:%01i)" #define IDS_2158 2158 // "SCSI (%02i:%02i)" #define IDS_2159 2159 // "Invalid number of cylinders.." @@ -417,6 +417,7 @@ #define IDM_ACTION_RESET_CAD 40013 #define IDM_ACTION_EXIT 40014 #define IDM_ACTION_CTRL_ALT_ESC 40015 +#define IDM_ACTION_PAUSE 40016 #define IDM_CONFIG 40020 #define IDM_CONFIG_LOAD 40021 #define IDM_CONFIG_SAVE 40022 @@ -425,6 +426,8 @@ #define IDM_VID_REMEMBER 40051 #define IDM_VID_DDRAW 40060 #define IDM_VID_D3D 40061 +#define IDM_VID_VNC 40062 +#define IDM_VID_RDP 40063 #define IDM_VID_SCALE_1X 40064 #define IDM_VID_SCALE_2X 40065 #define IDM_VID_SCALE_3X 40066 diff --git a/src/win/win.c b/src/win/win.c index c8efeef12..ab12e005d 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,2775 +8,1716 @@ * * The Emulator's Windows core. * - * Version: @(#)win.c 1.0.8 2017/09/03 + * Version: @(#)win.c 1.0.24 2017/10/14 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. */ -#include +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#include +#include +#include +#include +#include +#include +#undef BITMAP #include -#include +#include #include +#include +#include +#include #include "../86box.h" #include "../config.h" -#include "../cpu/cpu.h" #include "../ibm.h" #include "../mem.h" #include "../rom.h" #include "../device.h" #include "../nvr.h" #include "../mouse.h" -#include "../machine/machine.h" #include "../cdrom/cdrom.h" -#include "../cdrom/cdrom_ioctl.h" #include "../cdrom/cdrom_image.h" #include "../cdrom/cdrom_null.h" #include "../floppy/floppy.h" -#include "../floppy/fdd.h" -#include "../hdd/hdd.h" -#include "../hdd/hdd_ide_at.h" #include "../scsi/scsi.h" -#include "../scsi/scsi_disk.h" -#ifdef USE_NETWORK -# include "../network/network.h" -#endif +#include "../network/network.h" #include "../video/video.h" #include "../video/vid_ega.h" #include "../sound/sound.h" #include "../sound/snd_dbopl.h" -#include "plat_keyboard.h" -#include "plat_iodev.h" -#include "plat_mouse.h" -#include "plat_midi.h" -#include "plat_thread.h" -#include "plat_ticks.h" -#include "plat_ui.h" +#include "../plat.h" +#include "../plat_keyboard.h" +#include "../plat_mouse.h" +#include "../plat_midi.h" +#include "../ui.h" #include "win.h" -#include "win_cgapal.h" #include "win_ddraw.h" #include "win_d3d.h" -#include "win_language.h" - -#include -#include -#include -#include - - -#ifndef MAPVK_VK_TO_VSC -#define MAPVK_VK_TO_VSC 0 +#ifdef USE_VNC +# include "win_vnc.h" #endif -/* Declare Windows procedure */ -LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -LRESULT CALLBACK subWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -LRESULT CALLBACK StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +#define TIMER_1SEC 1 + + +typedef struct { + WCHAR str[512]; +} rc_str_t; -#define TIMER_1SEC 1 extern int updatestatus; -typedef struct win_event_t -{ - HANDLE handle; -} win_event_t; - -LONG_PTR OriginalStatusBarProcedure; -HWND ghwnd; -HINSTANCE hinstance; -HMENU menu; -int pause = 0; +/* Public data, more or less non-specific to platform. */ int scale = 0; -HWND hwndRender, hwndStatus; uint64_t timer_freq; -int winsizex=640, winsizey=480; -int efwinsizey=480; +int winsizex = 640, + winsizey = 480; +int efwinsizey = 480; int gfx_present[GFX_MAX]; -HANDLE ghMutex; -HANDLE slirpMutex; -HANDLE mainthreadh; -int infocus=1; -int drawits=0; -int romspresent[ROM_MAX]; -int quited=0; -RECT oldclip; -int mousecapture=0; -int recv_key[272]; -HMENU *sb_menu_handles; +int infocus = 1; +int drawits = 0; +int quited = 0; +int mousecapture = 0; uint64_t main_time; +/* Public data, specific to platform. */ +HWND hwndMain; +HMENU menuMain; +HANDLE ghMutex; +HINSTANCE hinstance; +HICON hIcon[512]; +RECT oldclip; +LCID dwLanguage; +int recv_key[272]; +uint32_t dwLangID, + dwSubLangID; -static struct -{ - int (*init)(HWND h); - void (*close)(); - void (*resize)(int x, int y); -} vid_apis[2][2] = -{ { { ddraw_init, ddraw_close, NULL }, - { d3d_init, d3d_close, d3d_resize } }, - { { ddraw_fs_init, ddraw_fs_close, NULL }, - { d3d_fs_init, d3d_fs_close, NULL } } }; +char openfilestring[260]; +WCHAR wopenfilestring[260]; -static int save_window_pos = 0; +/* Local data. */ +static HANDLE thMain; +static HWND hwndRender; /* machine render window */ +static wchar_t wTitle[512]; static RAWINPUTDEVICE device; - +static HHOOK hKeyboardHook; +static int hook_enabled = 0; +static int save_window_pos = 0; static int win_doresize = 0; - static int leave_fullscreen_flag = 0; - static int unscaled_size_x = 0; static int unscaled_size_y = 0; - +static int pause; static uint64_t start_time; static uint64_t end_time; - -HMENU smenu; - -static uint8_t host_cdrom_drive_available[26]; - -static uint8_t host_cdrom_drive_available_num = 0; - static wchar_t **argv; static int argc; static wchar_t *argbuf; - -static HANDLE hinstAcc; - -static HICON hIcon[512]; - -static int *iStatusWidths; -static int *sb_icon_flags; -static int *sb_part_meanings; -static int *sb_part_icons; -static WCHAR **sbTips; - -static int sb_parts = 0; -static int sb_ready = 0; +static rc_str_t *lpRCstr2048, + *lpRCstr3072, + *lpRCstr4096, + *lpRCstr4352, + *lpRCstr4608, + *lpRCstr5120, + *lpRCstr5376, + *lpRCstr5632, + *lpRCstr6144; +static struct { + int local; + int (*init)(HWND h); + void (*close)(void); + void (*resize)(int x, int y); + int (*pause)(void); +} vid_apis[2][4] = { + { + { 1, ddraw_init, ddraw_close, NULL, ddraw_pause }, + { 1, d3d_init, d3d_close, d3d_resize, d3d_pause }, +#ifdef USE_VNC + { 0, vnc_init, vnc_close, vnc_resize, vnc_pause }, +#else + { 0, NULL, NULL, NULL, NULL }, +#endif +#ifdef USE_RDP + { 0, rdp_init, rdp_close, rdp_resize, rdp_pause } +#else + { 0, NULL, NULL, NULL, NULL } +#endif + }, + { + { 1, ddraw_fs_init, ddraw_fs_close, NULL, ddraw_fs_pause }, + { 1, d3d_fs_init, d3d_fs_close, NULL, d3d_fs_pause }, +#ifdef USE_VNC + { 0, vnc_init, vnc_close, vnc_resize, vnc_pause }, +#else + { 0, NULL, NULL, NULL, NULL }, +#endif +#ifdef USE_RDP + { 0, rdp_init, rdp_close, rdp_resize, rdp_pause } +#else + { 0, NULL, NULL, NULL, NULL } +#endif + } +}; -void updatewindowsize(int x, int y) +HICON +LoadIconEx(PCTSTR pszIconName) { - int owsx = winsizex; - int owsy = winsizey; + return((HICON)LoadImage(hinstance, pszIconName, IMAGE_ICON, + 16, 16, LR_SHARED)); +} - int temp_overscan_x = overscan_x; - int temp_overscan_y = overscan_y; - double dx, dy, dtx, dty; +#if 0 +static void +win_menu_update(void) +{ + menuMain = LoadMenu(hinstance, L"MainMenu")); - if (vid_resize) return; + menuSBAR = LoadMenu(hinstance, L"StatusBarMenu"); - if (x < 160) x = 160; - if (y < 100) y = 100; + initmenu(); - if (x > 2048) x = 2048; - if (y > 2048) y = 2048; + SetMenu(hwndMain, menu); - if (suppress_overscan) - { - temp_overscan_x = temp_overscan_y = 0; + win_title_update = 1; +} +#endif + + +static void +releasemouse(void) +{ + if (mousecapture) { + ClipCursor(&oldclip); + ShowCursor(TRUE); + mousecapture = 0; + } +} + + +static void +win_pc_reset(int hard) +{ + plat_pause(1); + + Sleep(100); + + nvr_save(); + + config_save(); + + if (hard) + pc_reset_hard(); + else + pc_send_cad(); + + plat_pause(vid_apis[video_fullscreen][vid_api].pause()); +} + + +static void +video_toggle_option(HMENU h, int *val, int id) +{ + startblit(); + video_wait_for_blit(); + *val ^= 1; + CheckMenuItem(h, id, *val ? MF_CHECKED : MF_UNCHECKED); + endblit(); + config_save(); + device_force_redraw(); +} + + +/* The main thread runs the actual emulator code. */ +static void +MainThread(LPVOID param) +{ + int sb_borders[3]; + DWORD old_time, new_time; + int frames = 0; + RECT r; + + drawits = 0; + old_time = GetTickCount(); + while (! quited) { + if (updatestatus) { + if (hwndStatus != NULL) + SendMessage(hwndStatus, WM_USER, 0, 0); + updatestatus = 0; } - unscaled_size_x=x; efwinsizey=y; + new_time = GetTickCount(); + drawits += new_time - old_time; + old_time = new_time; + if (drawits > 0 && !pause) { + start_time = timer_read(); + drawits -= 10; + if (drawits > 50) drawits = 0; + pc_run(); - if (force_43) - { - dx = (double) x; - dtx = (double) temp_overscan_x; - - dy = (double) y; - dty = (double) temp_overscan_y; - - /* Account for possible overscan. */ - if (temp_overscan_y == 16) - { - /* CGA */ - dy = (((dx - dtx) / 4.0) * 3.0) + dty; + if (++frames >= 200 && nvr_dosave) { + frames = 0; + nvr_save(); + nvr_dosave = 0; } - else if (temp_overscan_y < 16) - { - /* MDA/Hercules */ - dy = (x / 4.0) * 3.0; - } - else - { - if (enable_overscan) - { - /* EGA/(S)VGA with overscan */ - dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } - else - { - /* EGA/(S)VGA without overscan */ - dy = (x / 4.0) * 3.0; - } - } - unscaled_size_y = (int) dy; - } - else - { - unscaled_size_y = efwinsizey; - } - switch(scale) - { - case 0: - winsizex = unscaled_size_x >> 1; - winsizey = unscaled_size_y >> 1; - break; - case 1: - winsizex = unscaled_size_x; - winsizey = unscaled_size_y; - break; - case 2: - winsizex = (unscaled_size_x * 3) >> 1; - winsizey = (unscaled_size_y * 3) >> 1; - break; - case 3: - winsizex = unscaled_size_x << 1; - winsizey = unscaled_size_y << 1; - break; - } + end_time = timer_read(); + main_time += end_time - start_time; + } else + Sleep(1); + + if (!video_fullscreen && vid_apis[0][vid_api].local && + win_doresize && (winsizex>0) && (winsizey>0)) { + SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM) sb_borders); + GetWindowRect(hwndMain, &r); + MoveWindow(hwndRender, 0, 0, winsizex, winsizey, TRUE); + GetWindowRect(hwndRender, &r); + MoveWindow(hwndSBAR, + 0, r.bottom + GetSystemMetrics(SM_CYEDGE), + winsizex, 17, TRUE); + GetWindowRect(hwndMain, &r); + + MoveWindow(hwndMain, r.left, r.top, + winsizex + (GetSystemMetrics(vid_resize ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME) * 2), + winsizey + (GetSystemMetrics(SM_CYEDGE) * 2) + (GetSystemMetrics(vid_resize ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 17 + sb_borders[1] + 1, + TRUE); + + if (mousecapture) { + GetWindowRect(hwndRender, &r); + ClipCursor(&r); + } - if ((owsx != winsizex) || (owsy != winsizey)) - { - win_doresize = 1; - } - else - { win_doresize = 0; } -} -void uws_natural(void) -{ - updatewindowsize(unscaled_size_x, efwinsizey); -} + if (leave_fullscreen_flag) { + leave_fullscreen_flag = 0; -void releasemouse(void) -{ - if (mousecapture) - { - ClipCursor(&oldclip); - ShowCursor(TRUE); - mousecapture = 0; - } -} - -void startblit(void) -{ - WaitForSingleObject(ghMutex, INFINITE); -} - -void endblit(void) -{ - ReleaseMutex(ghMutex); -} - -void startslirp(void) -{ - WaitForSingleObject(slirpMutex, INFINITE); -} - -void endslirp(void) -{ - ReleaseMutex(slirpMutex); -} - -void leave_fullscreen(void) -{ - leave_fullscreen_flag = 1; -} - -uint32_t get_ticks(void) -{ - return GetTickCount(); -} - -void delay_ms(uint32_t count) -{ - Sleep(count); -} - -void mainthread(LPVOID param) -{ - int frames = 0; - DWORD old_time, new_time; - - RECT r; - int sb_borders[3]; - - drawits=0; - old_time = GetTickCount(); - while (!quited) - { - if (updatestatus) - { - updatestatus = 0; - if (status_is_open) - { - SendMessage(status_hwnd, WM_USER, 0, 0); - } - } - new_time = GetTickCount(); - drawits += new_time - old_time; - old_time = new_time; - if (drawits > 0 && !pause) - { - start_time = timer_read(); - drawits-=10; if (drawits>50) drawits=0; - runpc(); - frames++; - if (frames >= 200 && nvr_dosave) - { - frames = 0; - nvr_dosave = 0; - savenvr(); - } - end_time = timer_read(); - main_time += end_time - start_time; - } - else - Sleep(1); - - if (!video_fullscreen && win_doresize && (winsizex > 0) && (winsizey > 0)) - { - SendMessage(hwndStatus, SB_GETBORDERS, 0, (LPARAM) sb_borders); - GetWindowRect(ghwnd, &r); - MoveWindow(hwndRender, 0, 0, winsizex, winsizey, TRUE); - GetWindowRect(hwndRender, &r); - MoveWindow(hwndStatus, 0, r.bottom + GetSystemMetrics(SM_CYEDGE), winsizex, 17, TRUE); - GetWindowRect(ghwnd, &r); - - MoveWindow(ghwnd, r.left, r.top, - winsizex + (GetSystemMetrics(vid_resize ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME) * 2), - winsizey + (GetSystemMetrics(SM_CYEDGE) * 2) + (GetSystemMetrics(vid_resize ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 17 + sb_borders[1] + 1, - TRUE); - - if (mousecapture) - { - GetWindowRect(hwndRender, &r); - ClipCursor(&r); - } - - win_doresize = 0; - } - - if (leave_fullscreen_flag) - { - leave_fullscreen_flag = 0; - SendMessage(ghwnd, WM_LEAVEFULLSCREEN, 0, 0); - } - if (video_fullscreen && infocus) - { - SetCursorPos(9999, 9999); - } - } -} - -void *thread_create(void (*thread_rout)(void *param), void *param) -{ - return (void *)_beginthread(thread_rout, 0, param); -} - -void thread_kill(void *handle) -{ - TerminateThread(handle, 0); -} - -void thread_sleep(int t) -{ - Sleep(t); -} - -event_t *thread_create_event(void) -{ - win_event_t *event = malloc(sizeof(win_event_t)); - - event->handle = CreateEvent(NULL, FALSE, FALSE, NULL); - - return (event_t *)event; -} - -void thread_set_event(event_t *_event) -{ - win_event_t *event = (win_event_t *)_event; - - SetEvent(event->handle); -} - -void thread_reset_event(event_t *_event) -{ - win_event_t *event = (win_event_t *)_event; - - ResetEvent(event->handle); -} - -int thread_wait_event(event_t *_event, int timeout) -{ - win_event_t *event = (win_event_t *)_event; - - if (timeout == -1) - timeout = INFINITE; - - if (WaitForSingleObject(event->handle, timeout)) - return 1; - return 0; -} - -void thread_destroy_event(event_t *_event) -{ - win_event_t *event = (win_event_t *)_event; - - CloseHandle(event->handle); - - free(event); -} - -void *thread_create_mutex(wchar_t *name) -{ - return (void*) CreateMutex(NULL, FALSE, name); -} - -void thread_close_mutex(void *mutex) -{ - CloseHandle((HANDLE) mutex); -} - -uint8_t thread_wait_mutex(void *mutex) -{ - DWORD dwres = WaitForSingleObject((HANDLE) mutex, INFINITE); - - switch (dwres) - { - case WAIT_OBJECT_0: - return 1; - case WAIT_ABANDONED: - default: - return 0; + SendMessage(hwndMain, WM_LEAVEFULLSCREEN, 0, 0); } -} -uint8_t thread_release_mutex(void *mutex) -{ - return !!ReleaseMutex((HANDLE) mutex); -} - -static void init_cdrom_host_drives(void) -{ - int i = 0; - WCHAR s[64]; - - host_cdrom_drive_available_num = 0; - - for (i='A'; i<='Z'; i++) - { - _swprintf(s, L"%c:\\", i); - - if (GetDriveType(s)==DRIVE_CDROM) - { - host_cdrom_drive_available[i - 'A'] = 1; - - host_cdrom_drive_available_num++; - } - else - { - host_cdrom_drive_available[i - 'A'] = 0; - } - } + if (video_fullscreen && infocus) + SetCursorPos(9999, 9999); + } } -HMENU create_popup_menu(int part) -{ - HMENU newHandle; - newHandle = CreatePopupMenu(); - AppendMenu(smenu, MF_POPUP, (UINT_PTR) newHandle, 0); - return newHandle; -} - - -void create_floppy_submenu(HMENU m, int id) -{ - AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_NEW | id, win_language_get_string_from_id(IDS_2161)); - AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING | id, win_language_get_string_from_id(IDS_2162)); - AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING_WP | id, win_language_get_string_from_id(IDS_2163)); - AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_FLOPPY_EJECT | id, win_language_get_string_from_id(IDS_2164)); -} - -void create_cdrom_submenu(HMENU m, int id) -{ - int i = 0; - WCHAR s[64]; - - AppendMenu(m, MF_STRING, IDM_CDROM_MUTE | id, win_language_get_string_from_id(IDS_2165)); - AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_CDROM_EMPTY | id, win_language_get_string_from_id(IDS_2166)); - AppendMenu(m, MF_STRING, IDM_CDROM_RELOAD | id, win_language_get_string_from_id(IDS_2167)); - AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_CDROM_IMAGE | id, win_language_get_string_from_id(IDS_2168)); - - if (host_cdrom_drive_available_num == 0) - { - if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) - { - cdrom_drives[id].host_drive = 0; - } - - goto check_menu_items; - } - else - { - if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) - { - if (!host_cdrom_drive_available[cdrom_drives[id].host_drive - 'A']) - { - cdrom_drives[id].host_drive = 0; - } - } - } - - AppendMenu(m, MF_SEPARATOR, 0, 0); - - for (i = 0; i < 26; i++) - { - _swprintf(s, L"Host CD/DVD Drive (%c:)", i + 0x41); - if (host_cdrom_drive_available[i]) - { - AppendMenu(m, MF_STRING, IDM_CDROM_HOST_DRIVE | (i << 3) | id, s); - } - } - -check_menu_items: - if (!cdrom_drives[id].sound_on) - { - CheckMenuItem(m, IDM_CDROM_MUTE | id, MF_CHECKED); - } - - if (cdrom_drives[id].host_drive == 200) - { - CheckMenuItem(m, IDM_CDROM_IMAGE | id, MF_CHECKED); - } - else if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) - { - CheckMenuItem(m, IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); - } - else - { - cdrom_drives[id].host_drive = 0; - CheckMenuItem(m, IDM_CDROM_EMPTY | id, MF_CHECKED); - } -} - -void create_removable_disk_submenu(HMENU m, int id) -{ - AppendMenu(m, MF_STRING, IDM_RDISK_EJECT | id, win_language_get_string_from_id(IDS_2166)); - AppendMenu(m, MF_STRING, IDM_RDISK_RELOAD | id, win_language_get_string_from_id(IDS_2167)); - AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_RDISK_SEND_CHANGE | id, win_language_get_string_from_id(IDS_2142)); - AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE | id, win_language_get_string_from_id(IDS_2168)); - AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE_WP | id, win_language_get_string_from_id(IDS_2169)); -} - -void get_executable_name(wchar_t *s, int size) -{ - GetModuleFileName(hinstance, s, size); -} - -void set_window_title(wchar_t *s) -{ - if (video_fullscreen) - return; - SetWindowText(ghwnd, s); -} - -uint64_t timer_read(void) -{ - LARGE_INTEGER qpc_time; - QueryPerformanceCounter(&qpc_time); - return qpc_time.QuadPart; -} - -static void process_command_line(void) -{ - WCHAR *cmdline; - int argc_max; - int i, q; - - cmdline = GetCommandLine(); - i = wcslen(cmdline) + 1; - argbuf = malloc(i * 2); - memcpy(argbuf, cmdline, i * 2); - - argc = 0; - argc_max = 64; - argv = malloc(sizeof(wchar_t *) * argc_max); - if (!argv) - { - free(argbuf); - return; - } - - i = 0; - - /* parse commandline into argc/argv format */ - while (argbuf[i]) - { - while (argbuf[i] == L' ') - i++; - - if (argbuf[i]) - { - if ((argbuf[i] == L'\'') || (argbuf[i] == L'"')) - { - q = argbuf[i++]; - if (!argbuf[i]) - break; - } - else - q = 0; - - argv[argc++] = &argbuf[i]; - - if (argc >= argc_max) - { - argc_max += 64; - argv = realloc(argv, sizeof(wchar_t *) * argc_max); - if (!argv) - { - free(argbuf); - return; - } - } - - while ((argbuf[i]) && ((q) ? (argbuf[i] != q) : (argbuf[i] != L' '))) - i++; - - if (argbuf[i]) - { - argbuf[i] = 0; - i++; - } - } - } - - argv[argc] = NULL; -} - -int find_in_array(int *array, int val, int len, int menu_base) -{ - int i = 0; - int temp = 0; - for (i = 0; i < len; i++) - { - CheckMenuItem(menu, menu_base + array[i], MF_UNCHECKED); - if (array[i] == val) - { - temp = 1; - } - } - return temp; -} - -HICON LoadIconEx(PCTSTR pszIconName) -{ - return (HICON) LoadImage(hinstance, pszIconName, IMAGE_ICON, 16, 16, LR_SHARED); -} - -HICON LoadIconBig(PCTSTR pszIconName) -{ - return (HICON) LoadImage(hinstance, pszIconName, IMAGE_ICON, 64, 64, 0); -} - -int fdd_type_to_icon(int type) -{ - switch(type) - { - default: - case 0: - return 512; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - return 128; - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - return 144; - } -} - -int count_hard_disks(int bus) -{ - int i = 0; - - int c = 0; - - for (i = 0; i < HDC_NUM; i++) - { - if (hdc[i].bus == bus) - { - c++; - } - } - - return c; -} - -int find_status_bar_part(int tag) -{ - int i = 0; - int found = -1; - - if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) - { - return -1; - } - - for (i = 0; i < sb_parts; i++) - { - if (sb_part_meanings[i] == tag) - { - found = i; - break; - } - } - - return found; -} - -/* This is for the disk activity indicator. */ -void update_status_bar_icon(int tag, int active) -{ - int found = -1; - int temp_flags = 0; - - if (((tag & 0xf0) >= SB_TEXT) || !sb_ready || (sb_parts == 0) || (sb_icon_flags == NULL) || (sb_part_icons == NULL)) - { - return; - } - - temp_flags |= active; - - found = find_status_bar_part(tag); - - if (found != -1) - { - if (temp_flags != (sb_icon_flags[found] & 1)) - { - sb_icon_flags[found] &= ~1; - sb_icon_flags[found] |= active; - - sb_part_icons[found] &= ~257; - sb_part_icons[found] |= sb_icon_flags[found]; - - SendMessage(hwndStatus, SB_SETICON, found, (LPARAM) hIcon[sb_part_icons[found]]); - } - } -} - -/* This is for the drive state indicator. */ -void update_status_bar_icon_state(int tag, int state) -{ - int found = -1; - - if (((tag & 0xf0) >= SB_HDD) || !sb_ready || (sb_parts == 0) || (sb_icon_flags == NULL) || (sb_part_icons == NULL)) - { - return; - } - - found = find_status_bar_part(tag); - - if (found != -1) - { - sb_icon_flags[found] &= ~256; - sb_icon_flags[found] |= state ? 256 : 0; - - sb_part_icons[found] &= ~257; - sb_part_icons[found] |= sb_icon_flags[found]; - - SendMessage(hwndStatus, SB_SETICON, found, (LPARAM) hIcon[sb_part_icons[found]]); - } -} - -void create_floppy_tip(int part) -{ - WCHAR wtext[512]; - WCHAR tempTip[512]; - - int drive = sb_part_meanings[part] & 0xf; - - mbstowcs(wtext, fdd_getname(fdd_get_type(drive)), strlen(fdd_getname(fdd_get_type(drive))) + 1); - if (wcslen(floppyfns[drive]) == 0) - { - _swprintf(tempTip, win_language_get_string_from_id(IDS_2158), drive + 1, wtext, win_language_get_string_from_id(IDS_2057)); - } - else - { - _swprintf(tempTip, win_language_get_string_from_id(IDS_2158), drive + 1, wtext, floppyfns[drive]); - } - - if (sbTips[part] != NULL) - { - free(sbTips[part]); - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -void create_cdrom_tip(int part) -{ - WCHAR wtext[512]; - WCHAR tempTip[512]; - - WCHAR *szText; - int id; - - int drive = sb_part_meanings[part] & 0xf; - - int bus = cdrom_drives[drive].bus_type; - - id = IDS_4352 + (bus - 1); - - szText = (WCHAR *) win_language_get_string_from_id(id); - - if (cdrom_drives[drive].host_drive == 200) - { - if (wcslen(cdrom_image[drive].image_path) == 0) - { - _swprintf(tempTip, win_language_get_string_from_id(IDS_5120), drive + 1, szText, win_language_get_string_from_id(IDS_2057)); - } - else - { - _swprintf(tempTip, win_language_get_string_from_id(IDS_5120), drive + 1, szText, cdrom_image[drive].image_path); - } - } - else if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) - { - _swprintf(wtext, win_language_get_string_from_id(IDS_2058), cdrom_drives[drive].host_drive & ~0x20); - _swprintf(tempTip, win_language_get_string_from_id(IDS_5120), drive + 1, szText, wtext); - } - else - { - _swprintf(tempTip, win_language_get_string_from_id(IDS_5120), drive + 1, szText, win_language_get_string_from_id(IDS_2057)); - } - - if (sbTips[part] != NULL) - { - free(sbTips[part]); - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -void create_removable_hd_tip(int part) -{ - WCHAR tempTip[512]; - - int drive = sb_part_meanings[part] & 0x1f; - - if (wcslen(hdc[drive].fn) == 0) - { - _swprintf(tempTip, win_language_get_string_from_id(IDS_4115), drive, win_language_get_string_from_id(IDS_2057)); - } - else - { - _swprintf(tempTip, win_language_get_string_from_id(IDS_4115), drive, hdc[drive].fn); - } - - if (sbTips[part] != NULL) - { - free(sbTips[part]); - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -void create_hd_tip(int part) -{ - WCHAR tempTip[512]; - WCHAR *szText; - int id; - - int bus = sb_part_meanings[part] & 0xf; - - id = IDS_4352 + (bus - 1); - - szText = (WCHAR *) win_language_get_string_from_id(id); - - _swprintf(tempTip, win_language_get_string_from_id(IDS_4096), szText); - - if (sbTips[part] != NULL) - { - free(sbTips[part]); - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -#ifdef USE_NETWORK -void create_network_tip(int part) -{ - WCHAR tempTip[512]; - - _swprintf(tempTip, win_language_get_string_from_id(IDS_2069)); - - if (sbTips[part] != NULL) - { - free(sbTips[part]); - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} -#endif - -void update_tip(int meaning) -{ - int i = 0; - int part = -1; - - if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) - { - return; - } - - for (i = 0; i < sb_parts; i++) - { - if (sb_part_meanings[i] == meaning) - { - part = i; - } - } - - if (part != -1) - { - switch(meaning & 0xf0) - { - case SB_FLOPPY: - create_floppy_tip(part); - break; - case SB_CDROM: - create_cdrom_tip(part); - break; - case SB_RDISK: - create_removable_hd_tip(part); - break; - case SB_HDD: - create_hd_tip(part); - break; - default: - break; - } - - SendMessage(hwndStatus, SB_SETTIPTEXT, part, (LPARAM) sbTips[part]); - } -} - -void status_settextw(wchar_t *wstr) -{ - int i = 0; - int part = -1; - - if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) - { - return; - } - - for (i = 0; i < sb_parts; i++) - { - if (sb_part_meanings[i] == SB_TEXT) - { - part = i; - } - } - - if (part != -1) - { - SendMessage(hwndStatus, SB_SETTEXT, part | SBT_NOBORDERS, (LPARAM) wstr); - } -} - -static wchar_t cwstr[512]; - -void status_settext(char *str) -{ - memset(cwstr, 0, 1024); - mbstowcs(cwstr, str, strlen(str) + 1); - status_settextw(cwstr); -} - -void destroy_menu_handles(void) -{ - int i = 0; - - if (sb_parts == 0) - { - return; - } - - if (!sb_menu_handles) - { - return; - } - - for (i = 0; i < sb_parts; i++) - { - if (sb_menu_handles[i]) - { - DestroyMenu(sb_menu_handles[i]); - sb_menu_handles[i] = NULL; - } - } - - free(sb_menu_handles); -} - -void destroy_tips(void) -{ - int i = 0; - - if (sb_parts == 0) - { - return; - } - - if (!sbTips) - { - return; - } - - for (i = 0; i < sb_parts; i++) - { - if (sbTips[i]) - { - free(sbTips[i]); - sbTips[i] = NULL; - } - } - - free(sbTips); - sbTips = NULL; -} - -#ifdef USE_NETWORK -int display_network_icon(void) -{ - if (network_card == 0) - { - return 0; - } - else - { - if (network_type == 0) - { - return 0; - } - else - { - return network_test(); - } - } -} -#endif - -void update_status_bar_panes(HWND hwnds) -{ - int i, id; - int edge = 0; - - int c_mfm = 0; - int c_esdi = 0; - int c_xtide = 0; - int c_ide_pio = 0; - int c_ide_dma = 0; - int c_scsi = 0; - -#ifdef USE_NETWORK - int do_net = 0; -#endif - - sb_ready = 0; - - c_mfm = count_hard_disks(HDD_BUS_MFM); - c_esdi = count_hard_disks(HDD_BUS_ESDI); - c_xtide = count_hard_disks(HDD_BUS_XTIDE); - c_ide_pio = count_hard_disks(HDD_BUS_IDE_PIO_ONLY); - c_ide_dma = count_hard_disks(HDD_BUS_IDE_PIO_AND_DMA); - c_scsi = count_hard_disks(HDD_BUS_SCSI); - -#ifdef USE_NETWORK - do_net = display_network_icon(); -#endif - - if (sb_parts > 0) - { - for (i = 0; i < sb_parts; i++) - { - SendMessage(hwnds, SB_SETICON, i, (LPARAM) NULL); - } - - SendMessage(hwnds, SB_SETPARTS, (WPARAM) 0, (LPARAM) NULL); - - if (iStatusWidths) - { - free(iStatusWidths); - iStatusWidths = NULL; - } - if (sb_part_meanings) - { - free(sb_part_meanings); - sb_part_meanings = NULL; - } - if (sb_part_icons) - { - free(sb_part_icons); - sb_part_icons = NULL; - } - if (sb_icon_flags) - { - free(sb_icon_flags); - sb_icon_flags = NULL; - } - destroy_menu_handles(); - destroy_tips(); - } - - sb_parts = 0; - - for (i = 0; i < FDD_NUM; i++) - { - if (fdd_get_type(i) != 0) - { - /* pclog("update_status_bar_panes(): Found floppy drive %c:, type %i\n", 65 + i, fdd_get_type(i)); */ - sb_parts++; - } - } - for (i = 0; i < CDROM_NUM; i++) - { - if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) && !(machines[machine].flags & MACHINE_HAS_IDE)) - { - continue; - } - if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) && !(machines[machine].flags & MACHINE_HAS_IDE)) - { - continue; - } - if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (scsi_card_current == 0)) - { - continue; - } - if (cdrom_drives[i].bus_type != 0) - { - sb_parts++; - } - } - for (i = 0; i < HDC_NUM; i++) - { - if ((hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) && (scsi_card_current != 0)) - { - sb_parts++; - } - } - if (c_mfm && !(machines[machine].flags & MACHINE_HAS_IDE) && !!memcmp(hdd_controller_name, "none", 4) && !!memcmp(hdd_controller_name, "xtide", 5) && !!memcmp(hdd_controller_name, "esdi", 4)) - { - sb_parts++; - } - if (c_esdi && !memcmp(hdd_controller_name, "esdi", 4)) - { - sb_parts++; - } - if (c_xtide && !memcmp(hdd_controller_name, "xtide", 5)) - { - sb_parts++; - } - if (c_ide_pio && (machines[machine].flags & MACHINE_HAS_IDE)) - { - sb_parts++; - } - if (c_ide_dma && (machines[machine].flags & MACHINE_HAS_IDE)) - { - sb_parts++; - } - if (c_scsi && (scsi_card_current != 0)) - { - sb_parts++; - } -#ifdef USE_NETWORK - if (do_net) - { - sb_parts++; - } -#endif - sb_parts++; - - iStatusWidths = (int *) malloc(sb_parts * sizeof(int)); - sb_part_meanings = (int *) malloc(sb_parts * sizeof(int)); - sb_part_icons = (int *) malloc(sb_parts * sizeof(int)); - sb_icon_flags = (int *) malloc(sb_parts * sizeof(int)); - sb_menu_handles = (HMENU *) malloc(sb_parts * sizeof(HMENU)); - sbTips = (WCHAR **) malloc(sb_parts * sizeof(WCHAR *)); - - memset(iStatusWidths, 0, sb_parts * sizeof(int)); - memset(sb_part_meanings, 0, sb_parts * sizeof(int)); - memset(sb_part_icons, 0, sb_parts * sizeof(int)); - memset(sb_icon_flags, 0, sb_parts * sizeof(int)); - memset(sb_menu_handles, 0, sb_parts * sizeof(HMENU)); - memset(sbTips, 0, sb_parts * sizeof(WCHAR *)); - - sb_parts = 0; - - for (i = 0; i < FDD_NUM; i++) - { - if (fdd_get_type(i) != 0) - { - /* pclog("update_status_bar_panes(): Found floppy drive %c:, type %i\n", 65 + i, fdd_get_type(i)); */ - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_FLOPPY | i; - sb_parts++; - } - } - for (i = 0; i < CDROM_NUM; i++) - { - if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) && !(machines[machine].flags & MACHINE_HAS_IDE)) - { - continue; - } - if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) && !(machines[machine].flags & MACHINE_HAS_IDE)) - { - continue; - } - if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (scsi_card_current == 0)) - { - continue; - } - if (cdrom_drives[i].bus_type != 0) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_CDROM | i; - sb_parts++; - } - } - for (i = 0; i < HDC_NUM; i++) - { - if ((hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) && (scsi_card_current != 0)) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_RDISK | i; - sb_parts++; - } - } - if (c_mfm && !(machines[machine].flags & MACHINE_HAS_IDE) && !!memcmp(hdd_controller_name, "none", 4) && !!memcmp(hdd_controller_name, "xtide", 5) && !!memcmp(hdd_controller_name, "esdi", 4)) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_MFM; - sb_parts++; - } - if (c_esdi && !memcmp(hdd_controller_name, "esdi", 4)) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_ESDI; - sb_parts++; - } - if (c_xtide && !memcmp(hdd_controller_name, "xtide", 5)) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_XTIDE; - sb_parts++; - } - if (c_ide_pio && (machines[machine].flags & MACHINE_HAS_IDE)) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_IDE_PIO_ONLY; - sb_parts++; - } - if (c_ide_dma && (machines[machine].flags & MACHINE_HAS_IDE)) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_IDE_PIO_AND_DMA; - sb_parts++; - } - if (c_scsi && (scsi_card_current != 0)) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_SCSI; - sb_parts++; - } -#ifdef USE_NETWORK - if (do_net) - { - edge += SB_ICON_WIDTH; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_NETWORK; - sb_parts++; - } -#endif - if (sb_parts) - { - iStatusWidths[sb_parts - 1] += (24 - SB_ICON_WIDTH); - } - iStatusWidths[sb_parts] = -1; - sb_part_meanings[sb_parts] = SB_TEXT; - sb_parts++; - - SendMessage(hwnds, SB_SETPARTS, (WPARAM) sb_parts, (LPARAM) iStatusWidths); - - for (i = 0; i < sb_parts; i++) - { - switch (sb_part_meanings[i] & 0xf0) - { - case SB_FLOPPY: - /* Floppy */ - sb_icon_flags[i] = (wcslen(floppyfns[sb_part_meanings[i] & 0xf]) == 0) ? 256 : 0; - sb_part_icons[i] = fdd_type_to_icon(fdd_get_type(sb_part_meanings[i] & 0xf)) | sb_icon_flags[i]; - sb_menu_handles[i] = create_popup_menu(i); - create_floppy_submenu(sb_menu_handles[i], sb_part_meanings[i] & 0xf); - EnableMenuItem(sb_menu_handles[i], IDM_FLOPPY_EJECT | (sb_part_meanings[i] & 0xf), MF_BYCOMMAND | ((sb_icon_flags[i] & 256) ? MF_GRAYED : MF_ENABLED)); - create_floppy_tip(i); - break; - case SB_CDROM: - /* CD-ROM */ - id = sb_part_meanings[i] & 0xf; - if (cdrom_drives[id].host_drive == 200) - { - sb_icon_flags[i] = (wcslen(cdrom_image[id].image_path) == 0) ? 256 : 0; - } - else if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) - { - sb_icon_flags[i] = 0; - } - else - { - sb_icon_flags[i] = 256; - } - sb_part_icons[i] = 160 | sb_icon_flags[i]; - sb_menu_handles[i] = create_popup_menu(i); - create_cdrom_submenu(sb_menu_handles[i], sb_part_meanings[i] & 0xf); - EnableMenuItem(sb_menu_handles[i], IDM_CDROM_RELOAD | (sb_part_meanings[i] & 0xf), MF_BYCOMMAND | MF_GRAYED); - create_cdrom_tip(i); - break; - case SB_RDISK: - /* Removable hard disk */ - sb_icon_flags[i] = (wcslen(hdc[sb_part_meanings[i] & 0x1f].fn) == 0) ? 256 : 0; - sb_part_icons[i] = 176 + sb_icon_flags[i]; - sb_menu_handles[i] = create_popup_menu(i); - create_removable_disk_submenu(sb_menu_handles[i], sb_part_meanings[i] & 0x1f); - EnableMenuItem(sb_menu_handles[i], IDM_RDISK_EJECT | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | ((sb_icon_flags[i] & 256) ? MF_GRAYED : MF_ENABLED)); - EnableMenuItem(sb_menu_handles[i], IDM_RDISK_RELOAD | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[i], IDM_RDISK_SEND_CHANGE | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | ((sb_icon_flags[i] & 256) ? MF_GRAYED : MF_ENABLED)); - create_removable_hd_tip(i); - break; - case SB_HDD: - /* Hard disk */ - sb_part_icons[i] = 192; - create_hd_tip(i); - break; -#ifdef USE_NETWORK - case SB_NETWORK: - /* Hard disk */ - sb_part_icons[i] = 208; - create_network_tip(i); - break; -#endif - case SB_TEXT: - /* Status text */ - SendMessage(hwnds, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM) L""); - sb_part_icons[i] = -1; - break; - } - if (sb_part_icons[i] != -1) - { - SendMessage(hwnds, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM) ""); - SendMessage(hwnds, SB_SETICON, i, (LPARAM) hIcon[sb_part_icons[i]]); - SendMessage(hwnds, SB_SETTIPTEXT, i, (LPARAM) sbTips[i]); - /* pclog("Status bar part found: %02X (%i)\n", sb_part_meanings[i], sb_part_icons[i]); */ - } - else - { - SendMessage(hwnds, SB_SETICON, i, (LPARAM) NULL); - } - } - - sb_ready = 1; -} - -HWND EmulatorStatusBar(HWND hwndParent, int idStatus, HINSTANCE hinst) -{ - HWND hwndStatus; - int i; - RECT rectDialog; - int dw, dh; - - for (i = 128; i < 130; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - - for (i = 144; i < 146; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - - for (i = 160; i < 162; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - - for (i = 176; i < 178; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - - for (i = 192; i < 194; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - -#ifdef USE_NETWORK - for (i = 208; i < 210; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } -#endif - - for (i = 384; i < 386; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - - for (i = 400; i < 402; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - - for (i = 416; i < 418; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - - for (i = 432; i < 434; i++) - { - hIcon[i] = LoadIconEx((PCTSTR) i); - } - - GetWindowRect(hwndParent, &rectDialog); - dw = rectDialog.right - rectDialog.left; - dh = rectDialog.bottom - rectDialog.top; - - InitCommonControls(); - - hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, (PCTSTR) NULL, SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE | SBT_TOOLTIPS, 0, dh - 17, dw, 17, hwndParent, - (HMENU) idStatus, hinst, NULL); - - GetWindowRect(hwndStatus, &rectDialog); - - SetWindowPos(hwndStatus, HWND_TOPMOST, rectDialog.left, rectDialog.top, rectDialog.right - rectDialog.left, rectDialog.bottom - rectDialog.top, SWP_SHOWWINDOW); - - SendMessage(hwndStatus, SB_SETMINHEIGHT, (WPARAM) 17, (LPARAM) 0); - - sb_parts = 0; - - update_status_bar_panes(hwndStatus); - - return hwndStatus; -} - -void win_menu_update(void) -{ -#if 0 - menu = LoadMenu(hThisInstance, TEXT("MainMenu")); - - smenu = LoadMenu(hThisInstance, TEXT("StatusBarMenu")); - initmenu(); - - SetMenu(ghwnd, menu); - - win_title_update = 1; -#endif -} - -void reset_menus(void) +static void +ResetAllMenus(void) { #ifdef ENABLE_LOG_TOGGLES # ifdef ENABLE_BUSLOGIC_LOG - CheckMenuItem(menu, IDM_LOG_BUSLOGIC, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_BUSLOGIC, MF_UNCHECKED); # endif # ifdef ENABLE_CDROM_LOG - CheckMenuItem(menu, IDM_LOG_CDROM, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_CDROM, MF_UNCHECKED); # endif # ifdef ENABLE_D86F_LOG - CheckMenuItem(menu, IDM_LOG_D86F, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_D86F, MF_UNCHECKED); # endif # ifdef ENABLE_FDC_LOG - CheckMenuItem(menu, IDM_LOG_FDC, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_FDC, MF_UNCHECKED); # endif # ifdef ENABLE_IDE_LOG - CheckMenuItem(menu, IDM_LOG_IDE, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_IDE, MF_UNCHECKED); # endif # ifdef ENABLE_SERIAL_LOG - CheckMenuItem(menu, IDM_LOG_SERIAL, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_SERIAL, MF_UNCHECKED); # endif -#ifdef USE_NETWORK # ifdef ENABLE_NIC_LOG - /*FIXME: should be network_setlog(1:0) */ - CheckMenuItem(menu, IDM_LOG_NIC, MF_UNCHECKED); + /*FIXME: should be network_setlog(1:0) */ + CheckMenuItem(menuMain, IDM_LOG_NIC, MF_UNCHECKED); # endif #endif + + CheckMenuItem(menuMain, IDM_VID_FORCE43, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_OVERSCAN, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_INVERT, MF_UNCHECKED); + + CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_DDRAW+0, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_DDRAW+1, MF_UNCHECKED); +#ifdef USE_VNC + CheckMenuItem(menuMain, IDM_VID_DDRAW+2, MF_UNCHECKED); #endif +#ifdef USE_VNC + CheckMenuItem(menuMain, IDM_VID_DDRAW+3, MF_UNCHECKED); +#endif + CheckMenuItem(menuMain, IDM_VID_FS_FULL+0, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_FULL+1, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_FULL+2, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_FULL+3, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_REMEMBER, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_1X+0, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_1X+1, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_1X+2, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_1X+3, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_FORCE43, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_OVERSCAN, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_INVERT, MF_UNCHECKED); - - CheckMenuItem(menu, IDM_VID_RESIZE, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_DDRAW + 0, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_DDRAW + 1, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_FS_FULL + 0, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_FS_FULL + 1, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_FS_FULL + 2, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_FS_FULL + 3, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_REMEMBER, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_SCALE_1X + 0, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_SCALE_1X + 1, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_SCALE_1X + 2, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_SCALE_1X + 3, MF_UNCHECKED); - - CheckMenuItem(menu, IDM_VID_CGACON, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAYCT_601 + 0, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAYCT_601 + 1, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAYCT_601 + 2, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAY_RGB + 0, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAY_RGB + 1, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAY_RGB + 2, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAY_RGB + 3, MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAY_RGB + 4, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_CGACON, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+0, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+1, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+2, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+0, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+1, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+2, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+3, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+4, MF_UNCHECKED); #ifdef ENABLE_LOG_TOGGLES # ifdef ENABLE_BUSLOGIC_LOG - CheckMenuItem(menu, IDM_LOG_BUSLOGIC, buslogic_do_log ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_BUSLOGIC, buslogic_do_log?MF_CHECKED:MF_UNCHECKED); # endif # ifdef ENABLE_CDROM_LOG - CheckMenuItem(menu, IDM_LOG_CDROM, cdrom_do_log ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_CDROM, cdrom_do_log?MF_CHECKED:MF_UNCHECKED); # endif # ifdef ENABLE_D86F_LOG - CheckMenuItem(menu, IDM_LOG_D86F, d86f_do_log ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_D86F, d86f_do_log?MF_CHECKED:MF_UNCHECKED); # endif # ifdef ENABLE_FDC_LOG - CheckMenuItem(menu, IDM_LOG_FDC, fdc_do_log ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_FDC, fdc_do_log?MF_CHECKED:MF_UNCHECKED); # endif # ifdef ENABLE_IDE_LOG - CheckMenuItem(menu, IDM_LOG_IDE, ide_do_log ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_IDE, ide_do_log?MF_CHECKED:MF_UNCHECKED); # endif # ifdef ENABLE_SERIAL_LOG - CheckMenuItem(menu, IDM_LOG_SERIAL, serial_do_log ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_SERIAL, serial_do_log?MF_CHECKED:MF_UNCHECKED); # endif -#ifdef USE_NETWORK # ifdef ENABLE_NIC_LOG - /*FIXME: should be network_setlog(1:0) */ - CheckMenuItem(menu, IDM_LOG_NIC, nic_do_log ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_LOG_NIC, nic_do_log?MF_CHECKED:MF_UNCHECKED); # endif -#endif #endif - CheckMenuItem(menu, IDM_VID_FORCE43, force_43 ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_OVERSCAN, enable_overscan ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_INVERT, invert_display ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FORCE43, force_43?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_OVERSCAN, enable_overscan?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_INVERT, invert_display ? MF_CHECKED : MF_UNCHECKED); - if (vid_resize) CheckMenuItem(menu, IDM_VID_RESIZE, MF_CHECKED); - CheckMenuItem(menu, IDM_VID_DDRAW + vid_api, MF_CHECKED); - CheckMenuItem(menu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_CHECKED); - CheckMenuItem(menu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_SCALE_1X + scale, MF_CHECKED); + if (vid_resize) + CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_DDRAW+vid_api, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_FULL+video_fullscreen_scale, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_REMEMBER, window_remember?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_1X+scale, MF_CHECKED); - CheckMenuItem(menu, IDM_VID_CGACON, vid_cga_contrast ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_GRAYCT_601 + video_graytype, MF_CHECKED); - CheckMenuItem(menu, IDM_VID_GRAY_RGB + video_grayscale, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_CGACON, vid_cga_contrast?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+video_graytype, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+video_grayscale, MF_CHECKED); } -int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) + +static LRESULT CALLBACK +LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { - HWND hwnd; /* This is the handle for our window */ - MSG messages; /* Here messages to the application are saved */ - WNDCLASSEX wincl; /* Data structure for the windowclass */ - int c, d, bRet; - WCHAR emulator_title[200]; - LARGE_INTEGER qpc_freq; - HACCEL haccel; /* Handle to accelerator table */ + BOOL bControlKeyDown; + KBDLLHOOKSTRUCT* p; - memset(recv_key, 0, sizeof(recv_key)); - - process_command_line(); - - win_language_load_common_strings(); - - hinstance=hThisInstance; - /* The Window structure */ - wincl.hInstance = hThisInstance; - wincl.lpszClassName = szClassName; - wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ - wincl.style = CS_DBLCLKS; /* Catch double-clicks */ - wincl.cbSize = sizeof (WNDCLASSEX); - - /* Use default icon and mouse-pointer */ - wincl.hIcon = LoadIcon(hinstance, (LPCTSTR) 100); - wincl.hIconSm = LoadIcon(hinstance, (LPCTSTR) 100); - wincl.hCursor = NULL; - wincl.lpszMenuName = NULL; /* No menu */ - wincl.cbClsExtra = 0; /* No extra bytes after the window class */ - wincl.cbWndExtra = 0; /* structure or the window instance */ - /* Use Windows's default color as the background of the window */ - wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; - - /* Register the window class, and if it fails quit the program */ - if (!RegisterClassEx(&wincl)) - { - return 0; - } - - wincl.lpszClassName = szSubClassName; - wincl.lpfnWndProc = subWindowProcedure; /* This function is called by windows */ - - if (!RegisterClassEx(&wincl)) - { - return 0; - } - - menu = LoadMenu(hThisInstance, TEXT("MainMenu")); - - _swprintf(emulator_title, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); - - /* The class is registered, let's create the program*/ - hwnd = CreateWindowEx ( - 0, /* Extended possibilites for variation */ - szClassName, /* Classname */ - emulator_title, /* Title Text */ - (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX)/* | DS_3DLOOK*/, /* default window */ - CW_USEDEFAULT, /* Windows decides the position */ - CW_USEDEFAULT, /* where the window ends up on the screen */ - 640+(GetSystemMetrics(SM_CXFIXEDFRAME)*2), /* The programs width */ - 480+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1, /* and height in pixels */ - HWND_DESKTOP, /* The window is a child-window to desktop */ - menu, /* Menu */ - hThisInstance, /* Program Instance handler */ - NULL /* No Window Creation data */ - ); - - /* Make the window visible on the screen */ - ShowWindow (hwnd, nFunsterStil); - - /* Load the accelerator table */ - haccel = LoadAccelerators(hinstAcc, L"MainAccel"); - if (haccel == NULL) - { - fatal("haccel is null\n"); - } - - device.usUsagePage = 0x01; - device.usUsage = 0x06; - device.dwFlags = RIDEV_NOHOTKEYS; - device.hwndTarget = hwnd; + if (nCode < 0 || nCode != HC_ACTION) + return(CallNextHookEx(hKeyboardHook, nCode, wParam, lParam)); - if (RegisterRawInputDevices(&device, 1, sizeof(device))) - { - pclog("Raw input registered!\n"); - } - else - { - pclog("Raw input registration failed!\n"); - } + p = (KBDLLHOOKSTRUCT*)lParam; - get_registry_key_map(); + /* disable alt-tab */ + if (p->vkCode == VK_TAB && p->flags & LLKHF_ALTDOWN) return(1); - ghwnd=hwnd; + /* disable alt-space */ + if (p->vkCode == VK_SPACE && p->flags & LLKHF_ALTDOWN) return(1); - hwndRender = CreateWindow(L"STATIC", NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP, 0, 0, 1, 1, ghwnd, NULL, hinstance, NULL); + /* disable alt-escape */ + if (p->vkCode == VK_ESCAPE && p->flags & LLKHF_ALTDOWN) return(1); - initpc(argc, argv); + /* disable windows keys */ + if((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)) return(1); - init_cdrom_host_drives(); + /* checks ctrl key pressed */ + bControlKeyDown = GetAsyncKeyState(VK_CONTROL)>>((sizeof(SHORT)*8)-1); -#ifdef USE_NETWORK - network_init(); -#endif + /* disable ctrl-escape */ + if (p->vkCode == VK_ESCAPE && bControlKeyDown) return(1); - hwndStatus = EmulatorStatusBar(hwnd, IDC_STATUS, hThisInstance); - - OriginalStatusBarProcedure = GetWindowLongPtr(hwndStatus, GWLP_WNDPROC); - SetWindowLongPtr(hwndStatus, GWL_WNDPROC, (LONG_PTR) &StatusBarProcedure); - - smenu = LoadMenu(hThisInstance, TEXT("StatusBarMenu")); - - initmodules(); - - if (vid_apis[0][vid_api].init(hwndRender) == 0) - { - if (vid_apis[0][vid_api ^ 1].init(hwndRender) == 0) - { - fatal("Both DirectDraw and Direct3D renderers failed to initialize\n"); - } - else - { - vid_api ^= 1; - } - } - - if (vid_resize) SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_MINIMIZEBOX)|WS_VISIBLE); - else SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX&~WS_MINIMIZEBOX)|WS_VISIBLE); - - reset_menus(); - - d=romset; - for (c=0;c= 0; c--) - { - if (gfx_present[c]) - { - gfxcard = c; - saveconfig(); - resetpchard(); - break; - } - } - } - - loadbios(); - resetpchard(); - - timeBeginPeriod(1); - - atexit(releasemouse); - - ghMutex = CreateMutex(NULL, FALSE, L"86Box.BlitMutex"); - slirpMutex = CreateMutex(NULL, FALSE, L"86Box.SlirpMutex"); - mainthreadh=(HANDLE)_beginthread(mainthread,0,NULL); - SetThreadPriority(mainthreadh, THREAD_PRIORITY_HIGHEST); - - updatewindowsize(640, 480); - - QueryPerformanceFrequency(&qpc_freq); - timer_freq = qpc_freq.QuadPart; - - if (start_in_fullscreen) - { - startblit(); - mouse_close(); - vid_apis[0][vid_api].close(); - video_fullscreen = 1; - vid_apis[1][vid_api].init(hwndRender); - mouse_init(); - leave_fullscreen_flag = 0; - endblit(); - device_force_redraw(); - } - if (window_remember) - { - MoveWindow(hwnd, window_x, window_y, - window_w, - window_h, - TRUE); - } - else - { - MoveWindow(hwndRender, 0, 0, - winsizex, - winsizey, - TRUE); - MoveWindow(hwndStatus, 0, winsizey + 6, - winsizex, - 17, - TRUE); - } - - /* Run the message loop. It will run until GetMessage() returns 0 */ - while (!quited) - { - while (((bRet = GetMessage(&messages,NULL,0,0)) != 0) && !quited) - { - if (bRet == -1) - { - fatal("bRet is -1\n"); - } - - if (messages.message==WM_QUIT) quited=1; - if (!TranslateAccelerator(hwnd, haccel, &messages)) - { - TranslateMessage(&messages); - DispatchMessage(&messages); - } - - if (recv_key[0x58] && recv_key[0x42] && mousecapture) - { - ClipCursor(&oldclip); - ShowCursor(TRUE); - mousecapture=0; - } - - if ((recv_key[0x1D] || recv_key[0x9D]) && (recv_key[0x38] || recv_key[0xB8]) && (recv_key[0x51] || recv_key[0xD1]) && - video_fullscreen) - { - leave_fullscreen(); - } - } - - quited=1; - } - - startblit(); - Sleep(200); - TerminateThread(mainthreadh,0); - savenvr(); - saveconfig(); - closepc(); - - vid_apis[video_fullscreen][vid_api].close(); - - timeEndPeriod(1); - if (mousecapture) - { - ClipCursor(&oldclip); - ShowCursor(TRUE); - } - - UnregisterClass(szSubClassName, hinstance); - UnregisterClass(szClassName, hinstance); - - return messages.wParam; + return(CallNextHookEx(hKeyboardHook, nCode, wParam, lParam)); } -HHOOK hKeyboardHook; -int hook_enabled = 0; -LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) +static LRESULT CALLBACK +MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - BOOL bControlKeyDown; - KBDLLHOOKSTRUCT* p; + HMENU hmenu; + RECT rect; + int i = 0; - if (nCode < 0 || nCode != HC_ACTION) - { - return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam); - } - - p = (KBDLLHOOKSTRUCT*)lParam; + switch (message) { + case WM_CREATE: + SetTimer(hwnd, TIMER_1SEC, 1000, NULL); + hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, + LowLevelKeyboardProc, + GetModuleHandle(NULL), 0); + hook_enabled = 1; + break; - if (p->vkCode == VK_TAB && p->flags & LLKHF_ALTDOWN) return 1; /* disable alt-tab */ - if (p->vkCode == VK_SPACE && p->flags & LLKHF_ALTDOWN) return 1; /* disable alt-tab */ - if((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)) return 1; /* disable windows keys */ - if (p->vkCode == VK_ESCAPE && p->flags & LLKHF_ALTDOWN) return 1; /* disable alt-escape */ - bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1); /* checks ctrl key pressed */ - if (p->vkCode == VK_ESCAPE && bControlKeyDown) return 1; /* disable ctrl-escape */ + case WM_COMMAND: + hmenu = GetMenu(hwnd); + switch (LOWORD(wParam)) { + case IDM_ACTION_SCREENSHOT: + take_screenshot(); + break; - return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam ); -} + case IDM_ACTION_HRESET: + win_pc_reset(1); + break; -void cdrom_close(uint8_t id) -{ - switch (cdrom_drives[id].host_drive) - { - case 0: - null_close(id); - break; - default: - ioctl_close(id); - break; - case 200: - image_close(id); - break; - } -} + case IDM_ACTION_RESET_CAD: + win_pc_reset(0); + break; -static BOOL CALLBACK about_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - HWND h; + case IDM_ACTION_EXIT: + PostQuitMessage(0); + break; - switch (message) - { - case WM_INITDIALOG: - pause = 1; - h = GetDlgItem(hdlg, IDC_ABOUT_ICON); - SendMessage(h, STM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM) LoadIconBig((PCTSTR) 100)); - break; + case IDM_ACTION_CTRL_ALT_ESC: + pc_send_cae(); + break; - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - EndDialog(hdlg, 0); - pause = 0; - return TRUE; - default: - break; - } - break; - } + case IDM_ACTION_PAUSE: + plat_pause(pause ^ 1); + break; - return FALSE; -} + case IDM_CONFIG: + win_settings_open(hwnd); + break; -void about_open(HWND hwnd) -{ - DialogBox(hinstance, (LPCTSTR)DLG_ABOUT, hwnd, about_dlgproc); -} + case IDM_ABOUT: + AboutDialogCreate(hwnd); + break; -static void win_pc_reset(int hard) -{ - pause=1; - Sleep(100); - savenvr(); - saveconfig(); - if (hard) - { - resetpchard(); - } - else - { - resetpc_cad(); - } - pause=0; -} + case IDM_STATUS: + StatusWindowCreate(hwnd); + break; -void video_toggle_option(HMENU hmenu, int *val, int id) -{ - startblit(); - video_wait_for_blit(); - *val ^= 1; - CheckMenuItem(hmenu, id, *val ? MF_CHECKED : MF_UNCHECKED); - endblit(); - saveconfig(); - device_force_redraw(); -} - -LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - HMENU hmenu; - RECT rect; - int i = 0; - - switch (message) - { - case WM_CREATE: - SetTimer(hwnd, TIMER_1SEC, 1000, NULL); - hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 ); - hook_enabled = 1; - break; - - case WM_COMMAND: - hmenu=GetMenu(hwnd); - switch (LOWORD(wParam)) - { - case IDM_ACTION_SCREENSHOT: - take_screenshot(); - break; - - case IDM_ACTION_HRESET: - win_pc_reset(1); - break; - - case IDM_ACTION_RESET_CAD: - win_pc_reset(0); - break; - - case IDM_ACTION_EXIT: - PostQuitMessage (0); /* send a WM_QUIT to the message queue */ - break; - - case IDM_ACTION_CTRL_ALT_ESC: - ctrl_alt_esc(); - break; - - case IDM_CONFIG: - win_settings_open(hwnd); - break; - - case IDM_ABOUT: - about_open(hwnd); - break; - - case IDM_STATUS: - status_open(hwnd); - break; - - case IDM_VID_RESIZE: - vid_resize = !vid_resize; - CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize)? MF_CHECKED : MF_UNCHECKED); - if (vid_resize) SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_MINIMIZEBOX) | WS_VISIBLE); - else SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX) | WS_VISIBLE); - GetWindowRect(hwnd, &rect); - SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); - GetWindowRect(hwndStatus,&rect); - SetWindowPos(hwndStatus, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); - if (vid_resize) - { - CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_VID_SCALE_2X, MF_CHECKED); - scale = 1; - } - EnableMenuItem(hmenu, IDM_VID_SCALE_1X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_2X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_3X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_4X, vid_resize ? MF_GRAYED : MF_ENABLED); - win_doresize = 1; - saveconfig(); - break; - - case IDM_VID_REMEMBER: - window_remember = !window_remember; - CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); - GetWindowRect(hwnd, &rect); - if (window_remember) - { - window_x = rect.left; - window_y = rect.top; - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; - } - saveconfig(); - break; - - case IDM_VID_DDRAW: - case IDM_VID_D3D: - startblit(); - video_wait_for_blit(); - CheckMenuItem(hmenu, IDM_VID_DDRAW + vid_api, MF_UNCHECKED); - vid_apis[0][vid_api].close(); - vid_api = LOWORD(wParam) - IDM_VID_DDRAW; - CheckMenuItem(hmenu, IDM_VID_DDRAW + vid_api, MF_CHECKED); - vid_apis[0][vid_api].init(hwndRender); - endblit(); - saveconfig(); - device_force_redraw(); - cgapal_rebuild(); - break; - - case IDM_VID_FULLSCREEN: - if(video_fullscreen != 1) - { - if (video_fullscreen_first) - { - video_fullscreen_first = 0; - msgbox_info(ghwnd, IDS_2074); - } - - startblit(); - video_wait_for_blit(); - mouse_close(); - vid_apis[0][vid_api].close(); - video_fullscreen = 1; - vid_apis[1][vid_api].init(ghwnd); - mouse_init(); - leave_fullscreen_flag = 0; - endblit(); - saveconfig(); - device_force_redraw(); - cgapal_rebuild(); - } - break; - - case IDM_VID_FS_FULL: - case IDM_VID_FS_43: - case IDM_VID_FS_SQ: - case IDM_VID_FS_INT: - CheckMenuItem(hmenu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_UNCHECKED); - video_fullscreen_scale = LOWORD(wParam) - IDM_VID_FS_FULL; - CheckMenuItem(hmenu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_CHECKED); - saveconfig(); - device_force_redraw(); - break; - - case IDM_VID_SCALE_1X: - case IDM_VID_SCALE_2X: - case IDM_VID_SCALE_3X: - case IDM_VID_SCALE_4X: + case IDM_VID_RESIZE: + vid_resize = !vid_resize; + CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize)? MF_CHECKED : MF_UNCHECKED); + if (vid_resize) + SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_MINIMIZEBOX) | WS_VISIBLE); + else + SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX) | WS_VISIBLE); + GetWindowRect(hwnd, &rect); + SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); + GetWindowRect(hwndSBAR,&rect); + SetWindowPos(hwndSBAR, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); + if (vid_resize) { CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); - scale = LOWORD(wParam) - IDM_VID_SCALE_1X; - CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_CHECKED); - saveconfig(); - device_force_redraw(); - break; + CheckMenuItem(hmenu, IDM_VID_SCALE_2X, MF_CHECKED); + scale = 1; + } + EnableMenuItem(hmenu, IDM_VID_SCALE_1X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_2X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_3X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_4X, vid_resize ? MF_GRAYED : MF_ENABLED); + win_doresize = 1; + config_save(); + break; - case IDM_VID_FORCE43: - video_toggle_option(hmenu, &force_43, IDM_VID_FORCE43); - break; + case IDM_VID_REMEMBER: + window_remember = !window_remember; + CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); + GetWindowRect(hwnd, &rect); + if (window_remember) { + window_x = rect.left; + window_y = rect.top; + window_w = rect.right - rect.left; + window_h = rect.bottom - rect.top; + } + config_save(); + break; - case IDM_VID_INVERT: - video_toggle_option(hmenu, &invert_display, IDM_VID_INVERT); - break; + case IDM_VID_DDRAW: + case IDM_VID_D3D: +#ifdef USE_VNC + case IDM_VID_VNC: +#endif +#ifdef USE_RDP + case IDM_VID_RDP: +#endif + startblit(); + video_wait_for_blit(); + CheckMenuItem(hmenu, IDM_VID_DDRAW+vid_api, MF_UNCHECKED); + vid_apis[0][vid_api].close(); + vid_api = LOWORD(wParam) - IDM_VID_DDRAW; + if (vid_apis[0][vid_api].local) + ShowWindow(hwndRender, SW_SHOW); + else + ShowWindow(hwndRender, SW_HIDE); + CheckMenuItem(hmenu, IDM_VID_DDRAW+vid_api, MF_CHECKED); + vid_apis[0][vid_api].init(hwndRender); + endblit(); + config_save(); + device_force_redraw(); + cgapal_rebuild(); + break; - case IDM_VID_OVERSCAN: - update_overscan = 1; - video_toggle_option(hmenu, &enable_overscan, IDM_VID_OVERSCAN); - break; + case IDM_VID_FULLSCREEN: + if (video_fullscreen == 1) break; - case IDM_VID_CGACON: - vid_cga_contrast ^= 1; - CheckMenuItem(hmenu, IDM_VID_CGACON, vid_cga_contrast ? MF_CHECKED : MF_UNCHECKED); - cgapal_rebuild(); - saveconfig(); - break; + if (video_fullscreen_first) { + video_fullscreen_first = 0; + ui_msgbox(MBX_INFO, (wchar_t *)IDS_2074); + } - case IDM_VID_GRAYCT_601: - case IDM_VID_GRAYCT_709: - case IDM_VID_GRAYCT_AVE: - CheckMenuItem(hmenu, IDM_VID_GRAYCT_601 + video_graytype, MF_UNCHECKED); - video_graytype = LOWORD(wParam) - IDM_VID_GRAYCT_601; - CheckMenuItem(hmenu, IDM_VID_GRAYCT_601 + video_graytype, MF_CHECKED); - saveconfig(); - device_force_redraw(); - break; + startblit(); + video_wait_for_blit(); + mouse_close(); + vid_apis[0][vid_api].close(); + video_fullscreen = 1; + vid_apis[1][vid_api].init(hwndMain); + mouse_init(); + leave_fullscreen_flag = 0; + endblit(); + config_save(); + device_force_redraw(); + cgapal_rebuild(); + break; - case IDM_VID_GRAY_RGB: - case IDM_VID_GRAY_MONO: - case IDM_VID_GRAY_AMBER: - case IDM_VID_GRAY_GREEN: - case IDM_VID_GRAY_WHITE: - CheckMenuItem(hmenu, IDM_VID_GRAY_RGB + video_grayscale, MF_UNCHECKED); - video_grayscale = LOWORD(wParam) - IDM_VID_GRAY_RGB; - CheckMenuItem(hmenu, IDM_VID_GRAY_RGB + video_grayscale, MF_CHECKED); - saveconfig(); - device_force_redraw(); - break; + case IDM_VID_FS_FULL: + case IDM_VID_FS_43: + case IDM_VID_FS_SQ: + case IDM_VID_FS_INT: + CheckMenuItem(hmenu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_UNCHECKED); + video_fullscreen_scale = LOWORD(wParam) - IDM_VID_FS_FULL; + CheckMenuItem(hmenu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_CHECKED); + config_save(); + device_force_redraw(); + break; + + case IDM_VID_SCALE_1X: + case IDM_VID_SCALE_2X: + case IDM_VID_SCALE_3X: + case IDM_VID_SCALE_4X: + CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); + scale = LOWORD(wParam) - IDM_VID_SCALE_1X; + CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_CHECKED); + config_save(); + device_force_redraw(); + break; + + case IDM_VID_FORCE43: + video_toggle_option(hmenu, &force_43, IDM_VID_FORCE43); + break; + + case IDM_VID_INVERT: + video_toggle_option(hmenu, &invert_display, IDM_VID_INVERT); + break; + + case IDM_VID_OVERSCAN: + update_overscan = 1; + video_toggle_option(hmenu, &enable_overscan, IDM_VID_OVERSCAN); + break; + + case IDM_VID_CGACON: + vid_cga_contrast ^= 1; + CheckMenuItem(hmenu, IDM_VID_CGACON, vid_cga_contrast ? MF_CHECKED : MF_UNCHECKED); + cgapal_rebuild(); + config_save(); + break; + + case IDM_VID_GRAYCT_601: + case IDM_VID_GRAYCT_709: + case IDM_VID_GRAYCT_AVE: + CheckMenuItem(hmenu, IDM_VID_GRAYCT_601 + video_graytype, MF_UNCHECKED); + video_graytype = LOWORD(wParam) - IDM_VID_GRAYCT_601; + CheckMenuItem(hmenu, IDM_VID_GRAYCT_601 + video_graytype, MF_CHECKED); + config_save(); + device_force_redraw(); + break; + + case IDM_VID_GRAY_RGB: + case IDM_VID_GRAY_MONO: + case IDM_VID_GRAY_AMBER: + case IDM_VID_GRAY_GREEN: + case IDM_VID_GRAY_WHITE: + CheckMenuItem(hmenu, IDM_VID_GRAY_RGB + video_grayscale, MF_UNCHECKED); + video_grayscale = LOWORD(wParam) - IDM_VID_GRAY_RGB; + CheckMenuItem(hmenu, IDM_VID_GRAY_RGB + video_grayscale, MF_CHECKED); + config_save(); + device_force_redraw(); + break; #ifdef ENABLE_LOG_TOGGLES -#ifdef ENABLE_BUSLOGIC_LOG - case IDM_LOG_BUSLOGIC: - buslogic_do_log ^= 1; - CheckMenuItem(hmenu, IDM_LOG_BUSLOGIC, buslogic_do_log ? MF_CHECKED : MF_UNCHECKED); - break; -#endif +# ifdef ENABLE_BUSLOGIC_LOG + case IDM_LOG_BUSLOGIC: + buslogic_do_log ^= 1; + CheckMenuItem(hmenu, IDM_LOG_BUSLOGIC, buslogic_do_log ? MF_CHECKED : MF_UNCHECKED); + break; +# endif -#ifdef ENABLE_CDROM_LOG - case IDM_LOG_CDROM: - cdrom_do_log ^= 1; - CheckMenuItem(hmenu, IDM_LOG_CDROM, cdrom_do_log ? MF_CHECKED : MF_UNCHECKED); - break; -#endif +# ifdef ENABLE_CDROM_LOG + case IDM_LOG_CDROM: + cdrom_do_log ^= 1; + CheckMenuItem(hmenu, IDM_LOG_CDROM, cdrom_do_log ? MF_CHECKED : MF_UNCHECKED); + break; +# endif -#ifdef ENABLE_D86F_LOG - case IDM_LOG_D86F: - d86f_do_log ^= 1; - CheckMenuItem(hmenu, IDM_LOG_D86F, d86f_do_log ? MF_CHECKED : MF_UNCHECKED); - break; -#endif +# ifdef ENABLE_D86F_LOG + case IDM_LOG_D86F: + d86f_do_log ^= 1; + CheckMenuItem(hmenu, IDM_LOG_D86F, d86f_do_log ? MF_CHECKED : MF_UNCHECKED); + break; +# endif -#ifdef ENABLE_FDC_LOG - case IDM_LOG_FDC: - fdc_do_log ^= 1; - CheckMenuItem(hmenu, IDM_LOG_FDC, fdc_do_log ? MF_CHECKED : MF_UNCHECKED); - break; -#endif +# ifdef ENABLE_FDC_LOG + case IDM_LOG_FDC: + fdc_do_log ^= 1; + CheckMenuItem(hmenu, IDM_LOG_FDC, fdc_do_log ? MF_CHECKED : MF_UNCHECKED); + break; +# endif -#ifdef ENABLE_IDE_LOG - case IDM_LOG_IDE: - ide_do_log ^= 1; - CheckMenuItem(hmenu, IDM_LOG_IDE, ide_do_log ? MF_CHECKED : MF_UNCHECKED); - break; -#endif +# ifdef ENABLE_IDE_LOG + case IDM_LOG_IDE: + ide_do_log ^= 1; + CheckMenuItem(hmenu, IDM_LOG_IDE, ide_do_log ? MF_CHECKED : MF_UNCHECKED); + break; +# endif -#ifdef ENABLE_SERIAL_LOG - case IDM_LOG_SERIAL: - serial_do_log ^= 1; - CheckMenuItem(hmenu, IDM_LOG_SERIAL, serial_do_log ? MF_CHECKED : MF_UNCHECKED); - break; -#endif +# ifdef ENABLE_SERIAL_LOG + case IDM_LOG_SERIAL: + serial_do_log ^= 1; + CheckMenuItem(hmenu, IDM_LOG_SERIAL, serial_do_log ? MF_CHECKED : MF_UNCHECKED); + break; +# endif -#ifdef USE_NETWORK -#ifdef ENABLE_NIC_LOG - case IDM_LOG_NIC: - /*FIXME: should be network_setlog() */ - nic_do_log ^= 1; - CheckMenuItem(hmenu, IDM_LOG_NIC, nic_do_log ? MF_CHECKED : MF_UNCHECKED); - break; -#endif -#endif +# ifdef ENABLE_NIC_LOG + case IDM_LOG_NIC: + /*FIXME: should be network_setlog() */ + nic_do_log ^= 1; + CheckMenuItem(hmenu, IDM_LOG_NIC, nic_do_log ? MF_CHECKED : MF_UNCHECKED); + break; +# endif #endif #ifdef ENABLE_LOG_BREAKPOINT - case IDM_LOG_BREAKPOINT: - pclog("---- LOG BREAKPOINT ----\n"); - break; + case IDM_LOG_BREAKPOINT: + pclog("---- LOG BREAKPOINT ----\n"); + break; #endif #ifdef ENABLE_VRAM_DUMP - case IDM_DUMP_VRAM: - svga_dump_vram(); - break; + case IDM_DUMP_VRAM: + svga_dump_vram(); + break; #endif - case IDM_CONFIG_LOAD: - pause = 1; - if (!file_dlg_st(hwnd, IDS_2160, "", 0)) - { - if (msgbox_reset_yn(ghwnd) == IDYES) + case IDM_CONFIG_LOAD: + plat_pause(1); + if (! file_dlg_st(hwnd, IDS_2160, "", 0)) { + if (ui_msgbox(MBX_QUESTION, (wchar_t *)IDS_2051) == IDYES) { + config_write(config_file_default); + for (i = 0; i < FDD_NUM; i++) { - config_save(config_file_default); - for (i = 0; i < FDD_NUM; i++) - { - floppy_close(i); - } - for (i = 0; i < CDROM_NUM; i++) - { - cdrom_drives[i].handler->exit(i); - if (cdrom_drives[i].host_drive == 200) - { - image_close(i); - } - else if ((cdrom_drives[i].host_drive >= 'A') && (cdrom_drives[i].host_drive <= 'Z')) - { - ioctl_close(i); - } - else - { - null_close(i); - } - } - resetpchard_close(); - loadconfig(wopenfilestring); - for (i = 0; i < CDROM_NUM; i++) - { - if (cdrom_drives[i].bus_type) - { - SCSIReset(cdrom_drives[i].scsi_device_id, cdrom_drives[i].scsi_device_lun); - } - - if (cdrom_drives[i].host_drive == 200) - { - image_open(i, cdrom_image[i].image_path); - } - else if ((cdrom_drives[i].host_drive >= 'A') && (cdrom_drives[i].host_drive <= 'Z')) - { - ioctl_open(i, cdrom_drives[i].host_drive); - } - else - { - cdrom_null_open(i, cdrom_drives[i].host_drive); - } - } - - floppy_load(0, floppyfns[0]); - floppy_load(1, floppyfns[1]); - floppy_load(2, floppyfns[2]); - floppy_load(3, floppyfns[3]); - - /* pclog_w(L"NVR path: %s\n", nvr_path); */ - mem_resize(); - loadbios(); -#ifdef USE_NETWORK - network_init(); -#endif - reset_menus(); - update_status_bar_panes(hwndStatus); - resetpchard_init(); + floppy_close(i); } - } - pause = 0; - break; + for (i = 0; i < CDROM_NUM; i++) + { + cdrom_drives[i].handler->exit(i); + if (cdrom_drives[i].host_drive == 200) + { + image_close(i); + } + else if ((cdrom_drives[i].host_drive >= 'A') && (cdrom_drives[i].host_drive <= 'Z')) + { + ioctl_close(i); + } + else + { + null_close(i); + } + } + pc_reset_hard_close(); + config_load(wopenfilestring); + for (i = 0; i < CDROM_NUM; i++) + { + if (cdrom_drives[i].bus_type) + { + SCSIReset(cdrom_drives[i].scsi_device_id, cdrom_drives[i].scsi_device_lun); + } - case IDM_CONFIG_SAVE: - pause = 1; - if (!file_dlg_st(hwnd, IDS_2160, "", 1)) - { - config_save(wopenfilestring); - } - pause = 0; - break; - } - return 0; + if (cdrom_drives[i].host_drive == 200) + { + image_open(i, cdrom_image[i].image_path); + } + else if ((cdrom_drives[i].host_drive >= 'A') && (cdrom_drives[i].host_drive <= 'Z')) + { + ioctl_open(i, cdrom_drives[i].host_drive); + } + else + { + cdrom_null_open(i, cdrom_drives[i].host_drive); + } + } - case WM_INPUT: - process_raw_input(lParam, infocus); - break; + floppy_load(0, floppyfns[0]); + floppy_load(1, floppyfns[1]); + floppy_load(2, floppyfns[2]); + floppy_load(3, floppyfns[3]); - case WM_SETFOCUS: - infocus=1; - if (!hook_enabled) - { - hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 ); - hook_enabled = 1; - } - break; - - case WM_KILLFOCUS: - infocus=0; - if (mousecapture) - { - ClipCursor(&oldclip); - ShowCursor(TRUE); - mousecapture=0; - } - memset(recv_key, 0, sizeof(recv_key)); - if (video_fullscreen) - { - leave_fullscreen_flag = 1; - } - if (hook_enabled) - { - UnhookWindowsHookEx(hKeyboardHook); - hook_enabled = 0; - } - break; - - case WM_LBUTTONUP: - if (!mousecapture && !video_fullscreen) - { - GetClipCursor(&oldclip); - GetWindowRect(hwndRender, &rect); - - ClipCursor(&rect); - mousecapture = 1; - while (1) - { - if (ShowCursor(FALSE) < 0) - { - break; + mem_resize(); + rom_load_bios(romset); + network_init(); + ResetAllMenus(); + ui_sb_update_panes(); + pc_reset_hard_init(); } } + plat_pause(0); + break; + + case IDM_CONFIG_SAVE: + plat_pause(1); + if (! file_dlg_st(hwnd, IDS_2160, "", 1)) { + config_write(wopenfilestring); + } + plat_pause(0); + break; + } + return(0); + + case WM_INPUT: + process_raw_input(lParam, infocus); + break; + + case WM_SETFOCUS: + infocus = 1; + if (! hook_enabled) { + hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, + LowLevelKeyboardProc, + GetModuleHandle(NULL), + 0); + hook_enabled = 1; + } + break; + + case WM_KILLFOCUS: + infocus = 0; + releasemouse(); + memset(recv_key, 0, sizeof(recv_key)); + if (video_fullscreen) + leave_fullscreen_flag = 1; + if (hook_enabled) { + UnhookWindowsHookEx(hKeyboardHook); + hook_enabled = 0; + } + break; + + case WM_LBUTTONUP: + if (!mousecapture && !video_fullscreen) { + GetClipCursor(&oldclip); + GetWindowRect(hwndRender, &rect); + + ClipCursor(&rect); + mousecapture = 1; + while (1) { + if (ShowCursor(FALSE) < 0) break; } - break; + } + break; - case WM_MBUTTONUP: - if (!(mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON)) - { - releasemouse(); - } - break; + case WM_MBUTTONUP: + if (!(mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON)) { + releasemouse(); + } + break; - case WM_ENTERMENULOOP: - break; + case WM_ENTERMENULOOP: + break; - case WM_SIZE: - winsizex = (lParam & 0xFFFF); - winsizey = (lParam >> 16) - (17 + 6); + case WM_SIZE: + winsizex = (lParam & 0xFFFF); + winsizey = (lParam >> 16) - (17 + 6); + if (winsizey < 0) + winsizey = 0; - if (winsizey < 0) - { - winsizey = 0; - } + MoveWindow(hwndSBAR, 0, winsizey + 6, winsizex, 17, TRUE); + if (vid_apis[0][vid_api].local && (hwndRender != NULL)) { MoveWindow(hwndRender, 0, 0, winsizex, winsizey, TRUE); - if (vid_apis[video_fullscreen][vid_api].resize) - { + if (vid_apis[video_fullscreen][vid_api].resize) { startblit(); video_wait_for_blit(); vid_apis[video_fullscreen][vid_api].resize(winsizex, winsizey); endblit(); } - MoveWindow(hwndStatus, 0, winsizey + 6, winsizex, 17, TRUE); - - if (mousecapture) - { + if (mousecapture) { GetWindowRect(hwndRender, &rect); ClipCursor(&rect); } + } - if (window_remember) - { - GetWindowRect(hwnd, &rect); - window_x = rect.left; - window_y = rect.top; - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; - save_window_pos = 1; - } + if (window_remember) { + GetWindowRect(hwnd, &rect); + window_x = rect.left; + window_y = rect.top; + window_w = rect.right - rect.left; + window_h = rect.bottom - rect.top; + save_window_pos = 1; + } - saveconfig(); - break; + config_save(); + break; - case WM_MOVE: - if (window_remember) - { - GetWindowRect(hwnd, &rect); - window_x = rect.left; - window_y = rect.top; - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; - save_window_pos = 1; - } - break; + case WM_MOVE: + if (window_remember) { + GetWindowRect(hwnd, &rect); + window_x = rect.left; + window_y = rect.top; + window_w = rect.right - rect.left; + window_h = rect.bottom - rect.top; + save_window_pos = 1; + } + break; - case WM_TIMER: - if (wParam == TIMER_1SEC) - { - onesec(); - } - break; + case WM_TIMER: + if (wParam == TIMER_1SEC) { + onesec(); + } + break; - case WM_RESETD3D: - startblit(); - if (video_fullscreen) - { - d3d_fs_reset(); - } - else - { - d3d_reset(); - } - endblit(); - break; + case WM_RESETD3D: + startblit(); + if (video_fullscreen) + d3d_fs_reset(); + else + d3d_reset(); + endblit(); + break; - case WM_LEAVEFULLSCREEN: - startblit(); - mouse_close(); - vid_apis[1][vid_api].close(); - video_fullscreen = 0; - saveconfig(); - vid_apis[0][vid_api].init(hwndRender); - mouse_init(); - endblit(); - device_force_redraw(); - cgapal_rebuild(); - break; + case WM_LEAVEFULLSCREEN: + startblit(); + mouse_close(); + vid_apis[1][vid_api].close(); + video_fullscreen = 0; + config_save(); + vid_apis[0][vid_api].init(hwndRender); + mouse_init(); + endblit(); + device_force_redraw(); + cgapal_rebuild(); + break; - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - case WM_KEYUP: - case WM_SYSKEYUP: - return 0; + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + return(0); - case WM_DESTROY: - UnhookWindowsHookEx(hKeyboardHook); - KillTimer(hwnd, TIMER_1SEC); - PostQuitMessage (0); /* send a WM_QUIT to the message queue */ - break; + case WM_DESTROY: + UnhookWindowsHookEx(hKeyboardHook); + KillTimer(hwnd, TIMER_1SEC); + PostQuitMessage(0); + break; - case WM_SYSCOMMAND: - /* Disable ALT key *ALWAYS*, I don't think there's any use for reaching the menu that way. */ - if (wParam == SC_KEYMENU && HIWORD(lParam) <= 0) - { - return 0; /*disable ALT key for menu*/ - } + case WM_SYSCOMMAND: + /* + * Disable ALT key *ALWAYS*, + * I don't think there's any use for + * reaching the menu that way. + */ + if (wParam == SC_KEYMENU && HIWORD(lParam) <= 0) { + return 0; /*disable ALT key for menu*/ + } - default: - return DefWindowProc (hwnd, message, wParam, lParam); - } - return 0; + default: + return(DefWindowProc(hwnd, message, wParam, lParam)); + } + + return(0); } -LRESULT CALLBACK subWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + +static LRESULT CALLBACK +SubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - switch (message) - { - default: - return DefWindowProc(hwnd, message, wParam, lParam); - } - return 0; + return(DefWindowProc(hwnd, message, wParam, lParam)); } -VOID APIENTRY HandlePopupMenu(HWND hwnd, POINT pt, int id) + +static void +LoadCommonStrings(void) { - if (id >= (sb_parts - 1)) - { - return; - } - pt.x = id * SB_ICON_WIDTH; /* Justify to the left. */ - pt.y = 0; /* Justify to the top. */ - ClientToScreen(hwnd, (LPPOINT) &pt); - TrackPopupMenu(sb_menu_handles[id], TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_LEFTBUTTON, pt.x, pt.y, 0, hwndStatus, NULL); + int i; + + lpRCstr2048 = (rc_str_t *)malloc(STRINGS_NUM_2048*sizeof(rc_str_t)); + lpRCstr3072 = (rc_str_t *)malloc(STRINGS_NUM_3072*sizeof(rc_str_t)); + lpRCstr4096 = (rc_str_t *)malloc(STRINGS_NUM_4096*sizeof(rc_str_t)); + lpRCstr4352 = (rc_str_t *)malloc(STRINGS_NUM_4352*sizeof(rc_str_t)); + lpRCstr4608 = (rc_str_t *)malloc(STRINGS_NUM_4608*sizeof(rc_str_t)); + lpRCstr5120 = (rc_str_t *)malloc(STRINGS_NUM_5120*sizeof(rc_str_t)); + lpRCstr5376 = (rc_str_t *)malloc(STRINGS_NUM_5376*sizeof(rc_str_t)); + lpRCstr5632 = (rc_str_t *)malloc(STRINGS_NUM_5632*sizeof(rc_str_t)); + lpRCstr6144 = (rc_str_t *)malloc(STRINGS_NUM_6144*sizeof(rc_str_t)); + + for (i=0; iexit(id); - cdrom_close(id); - image_open(id, temp_image_path); - /* Signal media change to the emulated machine. */ - cdrom_insert(id); - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); - if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) - { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); - } - cdrom_drives[id].host_drive = (wcslen(cdrom_image[id].image_path) == 0) ? 0 : 200; - if (cdrom_drives[id].host_drive == 200) - { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_CHECKED); - update_status_bar_icon_state(SB_CDROM | id, 0); - } - else - { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_UNCHECKED); - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); - update_status_bar_icon_state(SB_CDROM | id, 1); - } - EnableMenuItem(sb_menu_handles[part], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - update_tip(SB_CDROM | id); - saveconfig(); - } - break; - - case IDM_CDROM_HOST_DRIVE: - id = item_params & 0x0007; - letter = ((item_params >> 3) & 0x001f) + 'A'; - part = find_status_bar_part(SB_CDROM | id); - if ((part == -1) || (sb_menu_handles == NULL)) - { - break; - } - - new_cdrom_drive = letter; - if (cdrom_drives[id].host_drive == new_cdrom_drive) - { - /* Switching to the same drive. Do nothing. */ - break; - } - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - cdrom_drives[id].handler->exit(id); - cdrom_close(id); - ioctl_open(id, new_cdrom_drive); - /* Signal media change to the emulated machine. */ - cdrom_insert(id); - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); - if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) - { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); - } - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_UNCHECKED); - cdrom_drives[id].host_drive = new_cdrom_drive; - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); - EnableMenuItem(sb_menu_handles[part], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - update_status_bar_icon_state(SB_CDROM | id, 0); - update_tip(SB_CDROM | id); - saveconfig(); - break; - - case IDM_RDISK_EJECT: - id = item_params & 0x001f; - removable_disk_eject(id); - break; - - case IDM_RDISK_RELOAD: - id = item_params & 0x001f; - removable_disk_reload(id); - break; - - case IDM_RDISK_SEND_CHANGE: - id = item_params & 0x001f; - scsi_disk_insert(id); - break; - - case IDM_RDISK_IMAGE: - case IDM_RDISK_IMAGE_WP: - id = item_params & 0x001f; - ret = file_dlg_w_st(hwnd, IDS_4106, hdc[id].fn, id); - if (!ret) - { - removable_disk_unload(id); - memset(hdc[id].fn, 0, sizeof(hdc[id].fn)); - wcscpy(hdc[id].fn, wopenfilestring); - hdc[id].wp = (item_id == IDM_RDISK_IMAGE_WP) ? 1 : 0; - scsi_loadhd(hdc[id].scsi_id, hdc[id].scsi_lun, id); - scsi_disk_insert(id); - if (wcslen(hdc[id].fn) > 0) - { - update_status_bar_icon_state(SB_RDISK | id, 0); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_ENABLED); - } - else - { - update_status_bar_icon_state(SB_RDISK | id, 1); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_GRAYED); - } - update_tip(SB_RDISK | id); - saveconfig(); - } - break; - - default: - break; - } - return 0; - - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - GetClientRect(hwnd, (LPRECT)& rc); - pt.x = GET_X_LPARAM(lParam); - pt.y = GET_Y_LPARAM(lParam); - if (PtInRect((LPRECT) &rc, pt)) - { - HandlePopupMenu(hwnd, pt, (pt.x / SB_ICON_WIDTH)); - } - break; - - default: - return CallWindowProc((WNDPROC) OriginalStatusBarProcedure, hwnd, message, wParam, lParam); - } - return 0; +#if 0 + /* Set up stdin as well. */ + h = GetStdHandle(STD_INPUT_HANDLE); + i = _open_osfhandle((long)h, _O_TEXT); + fp = _fdopen(i, "r"); + setvbuf(fp, NULL, _IONBF, 128); + *stdin = *fp; +#endif +} +#endif + + +/* Process the commandline, and create standard argc/argv array. */ +static void +ProcessCommandLine(void) +{ + WCHAR *cmdline; + int argc_max; + int i, q; + + cmdline = GetCommandLine(); + i = wcslen(cmdline) + 1; + argbuf = malloc(i * 2); + memcpy(argbuf, cmdline, i * 2); + + argc = 0; + argc_max = 64; + argv = malloc(sizeof(wchar_t *) * argc_max); + if (argv == NULL) { + free(argbuf); + return; + } + + /* parse commandline into argc/argv format */ + i = 0; + while (argbuf[i]) { + while (argbuf[i] == L' ') + i++; + + if (argbuf[i]) { + if ((argbuf[i] == L'\'') || (argbuf[i] == L'"')) { + q = argbuf[i++]; + if (!argbuf[i]) + break; + } else + q = 0; + + argv[argc++] = &argbuf[i]; + + if (argc >= argc_max) { + argc_max += 64; + argv = realloc(argv, sizeof(wchar_t *) * argc_max); + if (argv == NULL) { + free(argbuf); + return; + } + } + + while ((argbuf[i]) && ((q) + ? (argbuf[i]!=q) : (argbuf[i]!=L' '))) i++; + + if (argbuf[i]) { + argbuf[i] = 0; + i++; + } + } + } + + argv[argc] = NULL; +} + + +/* @@@ + * For the Windows platform, this is the start of the application. + */ +int WINAPI +WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) +{ + WCHAR title[200]; + WNDCLASSEX wincl; /* buffer for main window's class */ + MSG messages; /* received-messages buffer */ + HWND hwnd; /* handle for our window */ + HACCEL haccel; /* handle to accelerator table */ + int bRet; + LARGE_INTEGER qpc_freq; + +#ifdef USE_CONSOLE + /* Create console window. */ + CreateConsole(1); +#endif + + /* Process the command line for options. */ + ProcessCommandLine(); + + /* Pre-initialize the system, this loads the config file. */ + if (! pc_init(argc, argv)) { +#ifdef USE_CONSOLE + /* Detach from console. */ + CreateConsole(0); +#endif + return(1); + } + + /* We need this later. */ + hinstance = hInst; + + /* Load common strings from the resource file. */ + LoadCommonStrings(); + + /* Create our main window's class and register it. */ + wincl.hInstance = hInst; + wincl.lpszClassName = CLASS_NAME; + wincl.lpfnWndProc = MainWindowProcedure; + wincl.style = CS_DBLCLKS; /* Catch double-clicks */ + wincl.cbSize = sizeof(WNDCLASSEX); + wincl.hIcon = LoadIcon(hInst, (LPCTSTR)100); + wincl.hIconSm = LoadIcon(hInst, (LPCTSTR)100); + wincl.hCursor = NULL; + wincl.lpszMenuName = NULL; + wincl.cbClsExtra = 0; + wincl.cbWndExtra = 0; + wincl.hbrBackground = CreateSolidBrush(RGB(0,0,0)); + if (! RegisterClassEx(&wincl)) + return(2); + wincl.lpszClassName = SUB_CLASS_NAME; + wincl.lpfnWndProc = SubWindowProcedure; + if (! RegisterClassEx(&wincl)) + return(2); + + /* Load the Window Menu(s) from the resources. */ + menuMain = LoadMenu(hInst, MENU_NAME); + + /* Set the initial title for the program's main window. */ + _swprintf(title, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); + set_window_title(title); + + /* Now create our main window. */ + hwnd = CreateWindowEx ( + 0, /* no extended possibilites */ + CLASS_NAME, /* class name */ + title, /* Title Text */ + (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX) | DS_3DLOOK, + CW_USEDEFAULT, /* Windows decides the position */ + CW_USEDEFAULT, /* where window ends up on the screen */ + 640+(GetSystemMetrics(SM_CXFIXEDFRAME)*2), /* width */ + 480+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1, /* and height in pixels */ + HWND_DESKTOP, /* window is a child to desktop */ + menuMain, /* menu */ + hInst, /* Program Instance handler */ + NULL); /* no Window Creation data */ + hwndMain = hwnd; + + /* Resize the window if needed. */ + if (vid_resize) + SetWindowLongPtr(hwnd, GWL_STYLE, + (WS_OVERLAPPEDWINDOW&~WS_MINIMIZEBOX)); + else + SetWindowLongPtr(hwnd, GWL_STYLE, + (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX&~WS_MINIMIZEBOX)); + + if (window_remember) + MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); + + /* Reset all menus to their defaults. */ + ResetAllMenus(); + + /* Make the window visible on the screen. */ + ShowWindow(hwnd, nFunsterStil); + + /* Load the accelerator table */ + haccel = LoadAccelerators(hInst, ACCEL_NAME); + if (haccel == NULL) { + MessageBox(hwndMain, + plat_get_string(IDS_2053), + plat_get_string(IDS_2050), + MB_OK | MB_ICONERROR); + return(3); + } + + /* Initialize the input (keyboard, mouse, game) module. */ + memset(recv_key, 0x00, sizeof(recv_key)); + device.usUsagePage = 0x01; + device.usUsage = 0x06; + device.dwFlags = RIDEV_NOHOTKEYS; + device.hwndTarget = hwnd; + if (! RegisterRawInputDevices(&device, 1, sizeof(device))) { + MessageBox(hwndMain, + plat_get_string(IDS_2054), + plat_get_string(IDS_2050), + MB_OK | MB_ICONERROR); + return(4); + } + get_registry_key_map(); + + /* Create the status bar window. */ + StatusBarCreate(hwndMain, IDC_STATUS, hInst); + + /* + * Before we can create the Render window, we first have + * to prepare some other things that it depends on. + */ + ghMutex = CreateMutex(NULL, FALSE, L"86Box.BlitMutex"); + + /* Create the Machine Rendering window. */ + hwndRender = CreateWindow(L"STATIC", NULL, WS_CHILD|SS_BITMAP, + 0, 0, 1, 1, hwnd, NULL, hInst, NULL); + MoveWindow(hwndRender, 0, 0, winsizex, winsizey, TRUE); + + /* If this is a local renderer, enable it. */ + if (vid_apis[0][vid_api].local) + ShowWindow(hwndRender, SW_SHOW); + + /* Select the best system renderer available. */ + if (! vid_apis[0][vid_api].init(hwndRender)) { + vid_api ^= 1; + if (! vid_apis[0][vid_api].init(hwndRender)) { + MessageBox(hwnd, + plat_get_string(IDS_2095), + plat_get_string(IDS_2050), + MB_OK | MB_ICONERROR); + return(5); + } + } + + /* Initialize the rendering window, or fullscreen. */ + if (start_in_fullscreen) { + startblit(); + vid_apis[0][vid_api].close(); + video_fullscreen = 1; + vid_apis[1][vid_api].init(hwndRender); + leave_fullscreen_flag = 0; + endblit(); + device_force_redraw(); + } + if (vid_apis[video_fullscreen][vid_api].resize) { + startblit(); + vid_apis[video_fullscreen][vid_api].resize(winsizex, winsizey); + endblit(); + } + + /* All done, fire up the actual emulated machine. */ + if (! pc_init_modules()) { + /* Dang, no ROMs found at all! */ + MessageBox(hwnd, + plat_get_string(IDS_2056), + plat_get_string(IDS_2050), + MB_OK | MB_ICONERROR); + return(6); + } + + /* Fire up the machine. */ + pc_reset_hard(); + + /* Set the PAUSE mode depending on the renderer. */ + plat_pause(0); + + /* + * Everything has been configured, and all seems to work, + * so now it is time to start the main thread to do some + * real work, and we will hang in here, dealing with the + * UI until we're done. + */ + timeBeginPeriod(1); + + atexit(releasemouse); + + thMain = (HANDLE)_beginthread(MainThread, 0, NULL); + SetThreadPriority(thMain, THREAD_PRIORITY_HIGHEST); + + QueryPerformanceFrequency(&qpc_freq); + timer_freq = qpc_freq.QuadPart; + + /* Run the message loop. It will run until GetMessage() returns 0 */ + while (! quited) { + bRet = GetMessage(&messages, NULL, 0, 0); + if ((bRet == 0) || quited) break; + + if (bRet == -1) { + fatal("bRet is -1\n"); + } + + if (messages.message == WM_QUIT) { + quited = 1; + break; + } + + if (! TranslateAccelerator(hwnd, haccel, &messages)) { + TranslateMessage(&messages); + DispatchMessage(&messages); + } + + if (recv_key[0x58] && recv_key[0x42] && mousecapture) { + ClipCursor(&oldclip); + ShowCursor(TRUE); + mousecapture = 0; + } + + if ((recv_key[0x1D] || recv_key[0x9D]) && + (recv_key[0x38] || recv_key[0xB8]) && + (recv_key[0x51] || recv_key[0xD1]) && video_fullscreen) { + leave_fullscreen(); + } + } + + /* Why start??? --FvK */ + startblit(); + + Sleep(200); + TerminateThread(thMain, 0); + + nvr_save(); + + config_save(); + + pc_close(); + + vid_apis[video_fullscreen][vid_api].close(); + + timeEndPeriod(1); + + if (mousecapture) { + ClipCursor(&oldclip); + ShowCursor(TRUE); + } + + UnregisterClass(SUB_CLASS_NAME, hInst); + UnregisterClass(CLASS_NAME, hInst); + + return(messages.wParam); +} + + +FILE * +plat_fopen(wchar_t *path, wchar_t *mode) +{ + return(_wfopen(path, mode)); +} + + +void +plat_remove(wchar_t *path) +{ + _wremove(path); +} + + +int +plat_getcwd(wchar_t *bufp, int max) +{ + (void)_wgetcwd(bufp, max); + + return(0); +} + + +int +plat_chdir(wchar_t *path) +{ + return(_wchdir(path)); +} + + +void +get_executable_name(wchar_t *s, int size) +{ + GetModuleFileName(hinstance, s, size); +} + + +wchar_t * +set_window_title(wchar_t *s) +{ + if (! video_fullscreen) { + if (s != NULL) + wcscpy(wTitle, s); + else + s = wTitle; + + SetWindowText(hwndMain, s); + } + + return(s); +} + + +int +dir_check_exist(wchar_t *path) +{ + DWORD dwAttrib = GetFileAttributes(path); + + return(((dwAttrib != INVALID_FILE_ATTRIBUTES && + (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))) ? 1 : 0); +} + + +int +dir_create(wchar_t *path) +{ + return((int)CreateDirectory(path, NULL)); +} + + +uint64_t +timer_read(void) +{ + LARGE_INTEGER li; + + QueryPerformanceCounter(&li); + + return(li.QuadPart); +} + + +uint32_t +get_ticks(void) +{ + return(GetTickCount()); +} + + +void +delay_ms(uint32_t count) +{ + Sleep(count); +} + + +/* We should have the language ID as a parameter. */ +void +win_set_language(void) +{ + SetThreadLocale(dwLanguage); +} + + +/* Update the global language used. This needs a parameter.. */ +void +win_language_update(void) +{ + win_set_language(); +#if 0 + MenuUpdate(); +#endif + LoadCommonStrings(); +} + + +void +win_language_check(void) +{ + LCID dwLanguageNew = MAKELCID(dwLangID, dwSubLangID); + + if (dwLanguageNew != dwLanguage) { + dwLanguage = dwLanguageNew; + + win_language_update(); + } +} + + +void +plat_pause(int p) +{ + static wchar_t oldtitle[512]; + + /* If un-pausing, as the renderer if that's OK. */ + if (p == 0) + p = vid_apis[video_fullscreen][vid_api].pause(); + + /* If already so, done. */ + if (pause == p) return; + + if (p) { + wcscpy(oldtitle, wTitle); + wcscat(wTitle, L" - PAUSED -"); + set_window_title(NULL); + } else { + set_window_title(oldtitle); + } + + pause = p; + + /* Update the actual menu. */ + CheckMenuItem(menuMain, IDM_ACTION_PAUSE, (pause)?MF_CHECKED:MF_UNCHECKED); +} + + +wchar_t * +plat_get_string(int i) +{ + LPTSTR str; + + if ((i >= 2048) && (i <= 3071)) { + str = lpRCstr2048[i-2048].str; + } else if ((i >= 3072) && (i <= 4095)) { + str = lpRCstr3072[i-3072].str; + } else if ((i >= 4096) && (i <= 4351)) { + str = lpRCstr4096[i-4096].str; + } else if ((i >= 4352) && (i <= 4607)) { + str = lpRCstr4352[i-4352].str; + } else if ((i >= 4608) && (i <= 5119)) { + str = lpRCstr4608[i-4608].str; + } else if ((i >= 5120) && (i <= 5375)) { + str = lpRCstr5120[i-5120].str; + } else if ((i >= 5376) && (i <= 5631)) { + str = lpRCstr5376[i-5376].str; + } else if ((i >= 5632) && (i <= 6143)) { + str = lpRCstr5632[i-5632].str; + } else { + str = lpRCstr6144[i-6144].str; + } + + return((wchar_t *)str); +} + + +wchar_t * +plat_get_string_from_string(char *str) +{ + return(plat_get_string(atoi(str))); +} + + +void +take_screenshot(void) +{ + wchar_t path[1024], fn[128]; + struct tm *info; + time_t now; + + pclog("Screenshot: video API is: %i\n", vid_api); + if ((vid_api < 0) || (vid_api > 1)) return; + + memset(fn, 0, sizeof(fn)); + memset(path, 0, sizeof(path)); + + (void)time(&now); + info = localtime(&now); + + append_filename_w(path, cfg_path, SCREENSHOT_PATH, sizeof(path)-2); + + if (! dir_check_exist(path)) + dir_create(path); + +#ifdef WIN32 + wcscat(path, L"\\"); +#else + wcscat(path, L"/"); +#endif + + switch(vid_api) { + case 0: /* ddraw */ + wcsftime(path, 128, L"%Y%m%d_%H%M%S.bmp", info); + append_filename_w(path, cfg_path, fn, 1024); + if (video_fullscreen) + ddraw_fs_take_screenshot(path); + else + ddraw_take_screenshot(path); + pclog("Screenshot: fn='%ls'\n", path); + break; + + case 1: /* d3d9 */ + wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info); + append_filename_w(path, cfg_path, fn, 1024); + if (video_fullscreen) + d3d_fs_take_screenshot(path); + else + d3d_take_screenshot(path); + pclog("Screenshot: fn='%ls'\n", path); + break; + +#ifdef USE_VNC + case 2: /* vnc */ + wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info); + append_filename_w(path, cfg_path, fn, 1024); + vnc_take_screenshot(path); + pclog("Screenshot: fn='%ls'\n", path); + break; +#endif + } +} + + +void +startblit(void) +{ + WaitForSingleObject(ghMutex, INFINITE); +} + + +void +endblit(void) +{ + ReleaseMutex(ghMutex); +} + + +void +updatewindowsize(int x, int y) +{ + int owsx = winsizex; + int owsy = winsizey; + int temp_overscan_x = overscan_x; + int temp_overscan_y = overscan_y; + double dx, dy, dtx, dty; + + if (vid_resize) return; + + if (x < 160) x = 160; + if (y < 100) y = 100; + if (x > 2048) x = 2048; + if (y > 2048) y = 2048; + + if (suppress_overscan) + temp_overscan_x = temp_overscan_y = 0; + + unscaled_size_x=x; efwinsizey=y; + + if (force_43) { + dx = (double) x; + dtx = (double) temp_overscan_x; + + dy = (double) y; + dty = (double) temp_overscan_y; + + /* Account for possible overscan. */ + if (temp_overscan_y == 16) { + /* CGA */ + dy = (((dx - dtx) / 4.0) * 3.0) + dty; + } else if (temp_overscan_y < 16) { + /* MDA/Hercules */ + dy = (x / 4.0) * 3.0; + } else { + if (enable_overscan) { + /* EGA/(S)VGA with overscan */ + dy = (((dx - dtx) / 4.0) * 3.0) + dty; + } else { + /* EGA/(S)VGA without overscan */ + dy = (x / 4.0) * 3.0; + } + } + unscaled_size_y = (int) dy; + } else { + unscaled_size_y = efwinsizey; + } + + switch(scale) { + case 0: + winsizex = unscaled_size_x >> 1; + winsizey = unscaled_size_y >> 1; + break; + + case 1: + winsizex = unscaled_size_x; + winsizey = unscaled_size_y; + break; + + case 2: + winsizex = (unscaled_size_x * 3) >> 1; + winsizey = (unscaled_size_y * 3) >> 1; + break; + + case 3: + winsizex = unscaled_size_x << 1; + winsizey = unscaled_size_y << 1; + break; + } + + if ((owsx != winsizex) || (owsy != winsizey)) + win_doresize = 1; + else + win_doresize = 0; +} + + +void +uws_natural(void) +{ + updatewindowsize(unscaled_size_x, efwinsizey); +} + + +void +leave_fullscreen(void) +{ + leave_fullscreen_flag = 1; } diff --git a/src/win/win.h b/src/win/win.h index 3b89e2efc..916087de9 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -6,24 +6,20 @@ * * This file is part of the 86Box distribution. * - * The Emulator's Windows core. + * This file should contain things only used by the platform + * support modules for Windows. Generic definitions for UI and + * platform go into ../plat*.h. * - * Version: @(#)win.h 1.0.0 2017/05/30 + * Version: @(#)win.h 1.0.5 2017/10/13 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, + * Fred N. van Kempen, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. */ - -/* - * This should be named 'plat.h' and then include any - * Windows-specific header files needed, to keep them - * out of the main code. - */ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #ifndef BOX_WIN_H # define BOX_WIN_H @@ -31,70 +27,62 @@ # define UNICODE # endif # define BITMAP WINDOWS_BITMAP -/* # ifdef _WIN32_WINNT - # undef _WIN32_WINNT - # define _WIN32_WINNT 0x0501 - # endif */ +# if 0 +# ifdef _WIN32_WINNT +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0501 +# endif +# endif # include # include "resource.h" # undef BITMAP -#define szClassName L"86BoxMainWnd" -#define szSubClassName L"86BoxSubWnd" -#define szStatusBarClassName L"86BoxStatusBar" +/* Class names and such. */ +#define CLASS_NAME L"86BoxMainWnd" +#define MENU_NAME L"MainMenu" +#define ACCEL_NAME L"MainAccel" +#define SUB_CLASS_NAME L"86BoxSubWnd" +#define SB_CLASS_NAME L"86BoxStatusBar" +#define SB_MENU_NAME L"StatusBarMenu" + +/* Application-specific window messages. */ +#define WM_RESETD3D WM_USER +#define WM_LEAVEFULLSCREEN WM_USER+1 +#define WM_SAVESETTINGS 0x8888 -#define WM_RESETD3D WM_USER -#define WM_LEAVEFULLSCREEN WM_USER + 1 - -#define WM_SAVESETTINGS 0x8888 /* 86Box-specific message, used to tell the child dialog to save the currently specified settings. */ - -#define SB_ICON_WIDTH 24 - - -extern HINSTANCE hinstance; -extern HWND ghwnd; -extern HWND status_hwnd; -extern HWND hwndStatus; extern int status_is_open; extern int mousecapture; +extern LCID dwLanguage; + +extern HINSTANCE hinstance; +extern HWND hwndMain; +extern HICON hIcon[512]; extern char openfilestring[260]; extern WCHAR wopenfilestring[260]; -extern int pause; - -extern HMENU smenu; -extern HMENU *sb_menu_handles; - #ifdef __cplusplus extern "C" { #endif -extern void leave_fullscreen(void); +extern HICON LoadIconEx(PCTSTR pszIconName); -extern void status_open(HWND hwnd); +extern void win_language_set(void); +extern void win_language_update(void); +extern void win_language_check(void); -extern void deviceconfig_open(HWND hwnd, struct device_t *device); +#ifdef EMU_DEVICE_H +extern void deviceconfig_open(HWND hwnd, device_t *device); +#endif extern void joystickconfig_open(HWND hwnd, int joy_nr, int type); extern int getfile(HWND hwnd, char *f, char *fn); extern int getsfile(HWND hwnd, char *f, char *fn); -extern void get_executable_name(wchar_t *s, int size); -extern void set_window_title(wchar_t *s); - -extern void startblit(void); -extern void endblit(void); - extern void win_settings_open(HWND hwnd); -extern void win_menu_update(); - -extern void update_status_bar_panes(HWND hwnds); - -extern int fdd_type_to_icon(int type); extern void hard_disk_add_open(HWND hwnd, int is_existing); extern int hard_disk_was_added(void); @@ -102,12 +90,32 @@ extern int hard_disk_was_added(void); extern void get_registry_key_map(void); extern void process_raw_input(LPARAM lParam, int infocus); -extern int find_status_bar_part(int tag); +extern int fdd_type_to_icon(int type); -extern void cdrom_close(uint8_t id); -extern void update_tip(int meaning); -extern BOOL DirectoryExists(LPCTSTR szPath); +/* Functions in win_about.c: */ +extern void AboutDialogCreate(HWND hwnd); + + +/* Functions in win_status.c: */ +extern HWND hwndStatus; +extern void StatusWindowCreate(HWND hwnd); + + +/* Functions in win_stbar.c: */ +extern HWND hwndSBAR; +extern void StatusBarCreate(HWND hwndParent, int idStatus, HINSTANCE hInst); + + +/* Functions in win_dialog.c: */ +extern int file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, int save); +extern int file_dlg(HWND hwnd, WCHAR *f, char *fn, int save); +extern int file_dlg_mb(HWND hwnd, char *f, char *fn, int save); +extern int file_dlg_w_st(HWND hwnd, int i, WCHAR *fn, int save); +extern int file_dlg_st(HWND hwnd, int i, char *fn, int save); + +extern wchar_t *BrowseFolder(wchar_t *saved_path, wchar_t *title); + #ifdef __cplusplus } diff --git a/src/win/win_about.c b/src/win/win_about.c new file mode 100644 index 000000000..c8b46d86a --- /dev/null +++ b/src/win/win_about.c @@ -0,0 +1,70 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Handle the About dialog. + * + * Version: @(#)win_about.c 1.0.3 2017/10/13 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#undef BITMAP +#include +#include +#include +#include +#include +#include "../86box.h" +#include "../plat.h" +#include "win.h" + + +static BOOL CALLBACK +AboutDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND h; + + switch (message) { + case WM_INITDIALOG: + plat_pause(1); + h = GetDlgItem(hdlg, IDC_ABOUT_ICON); + SendMessage(h, STM_SETIMAGE, (WPARAM)IMAGE_ICON, + (LPARAM)LoadImage(hinstance,(PCTSTR)100,IMAGE_ICON,64,64,0)); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + EndDialog(hdlg, 0); + plat_pause(0); + return TRUE; + + default: + break; + } + break; + } + + return(FALSE); +} + + +void +AboutDialogCreate(HWND hwnd) +{ + DialogBox(hinstance, (LPCTSTR)DLG_ABOUT, hwnd, AboutDialogProcedure); +} diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c new file mode 100644 index 000000000..19e0f454e --- /dev/null +++ b/src/win/win_cdrom.c @@ -0,0 +1,204 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Handle the platform-side of CDROM drives. + * + * Version: @(#)win_cdrom.c 1.0.3 2017/10/09 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#undef BITMAP +#include +#include +#include +#include +#include +#include "../config.h" +#include "../cdrom/cdrom.h" +#include "../cdrom/cdrom_image.h" +#include "../cdrom/cdrom_null.h" +#include "../disk/hdd.h" +#include "../scsi/scsi.h" +#include "../scsi/scsi_disk.h" +#include "../plat.h" +#include "../ui.h" +#include "win.h" + + +uint8_t host_cdrom_drive_available[26]; +uint8_t host_cdrom_drive_available_num = 0; + + +void +cdrom_init_host_drives(void) +{ + WCHAR s[64]; + int i = 0; + + host_cdrom_drive_available_num = 0; + for (i='A'; i<='Z'; i++) { + _swprintf(s, L"%c:\\", i); + + if (GetDriveType(s)==DRIVE_CDROM) { + host_cdrom_drive_available[i - 'A'] = 1; + + host_cdrom_drive_available_num++; + } else { + host_cdrom_drive_available[i - 'A'] = 0; + } + } +} + + +void +cdrom_eject(uint8_t id) +{ + if (cdrom_drives[id].host_drive == 0) { + /* Switch from empty to empty. Do nothing. */ + return; + } + + if ((cdrom_drives[id].host_drive >= 'A') && + (cdrom_drives[id].host_drive <= 'Z')) { + ui_sb_check_menu_item(SB_CDROM|id, + IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); + } + + if (cdrom_drives[id].host_drive == 200) { + wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path); + } + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + cdrom_drives[id].handler->exit(id); + cdrom_close(id); + cdrom_null_open(id, 0); + if (cdrom_drives[id].bus_type) { + /* Signal disc change to the emulated machine. */ + cdrom_insert(id); + } + + ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, MF_UNCHECKED); + cdrom_drives[id].host_drive=0; + ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_CHECKED); + ui_sb_update_icon_state(SB_CDROM|id, 1); + ui_sb_enable_menu_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); + ui_sb_update_tip(SB_CDROM|id); + + config_save(); +} + + +void +cdrom_reload(uint8_t id) +{ + int new_cdrom_drive; + + if ((cdrom_drives[id].host_drive == cdrom_drives[id].prev_host_drive) || (cdrom_drives[id].prev_host_drive == 0) || (cdrom_drives[id].host_drive != 0)) { + /* Switch from empty to empty. Do nothing. */ + return; + } + + cdrom_close(id); + + if (cdrom_drives[id].prev_host_drive == 200) { + wcscpy(cdrom_image[id].image_path, cdrom_image[id].prev_image_path); + image_open(id, cdrom_image[id].image_path); + if (cdrom_drives[id].bus_type) { + /* Signal disc change to the emulated machine. */ + cdrom_insert(id); + } + if (wcslen(cdrom_image[id].image_path) == 0) { + ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_CHECKED); + cdrom_drives[id].host_drive = 0; + ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, MF_UNCHECKED); + ui_sb_update_icon_state(SB_CDROM|id, 1); + } else { + ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_UNCHECKED); + cdrom_drives[id].host_drive = 200; + ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, MF_CHECKED); + ui_sb_update_icon_state(SB_CDROM|id, 0); + } + } else { + new_cdrom_drive = cdrom_drives[id].prev_host_drive; + ioctl_open(id, new_cdrom_drive); + if (cdrom_drives[id].bus_type) { + /* Signal disc change to the emulated machine. */ + cdrom_insert(id); + } + ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_UNCHECKED); + cdrom_drives[id].host_drive = new_cdrom_drive; + ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); + ui_sb_update_icon_state(SB_CDROM|id, 0); + } + + ui_sb_enable_menu_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_update_tip(SB_CDROM|id); + + config_save(); +} + + +void +removable_disk_unload(uint8_t id) +{ + if (wcslen(hdd[id].fn) == 0) { + /* Switch from empty to empty. Do nothing. */ + return; + } + + scsi_unloadhd(hdd[id].scsi_id, hdd[id].scsi_lun, id); + scsi_disk_insert(id); +} + + +void +removable_disk_eject(uint8_t id) +{ + removable_disk_unload(id); + ui_sb_update_icon_state(SB_RDISK|id, 1); + ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); + ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_GRAYED); + + ui_sb_update_tip(SB_RDISK|id); + + config_save(); +} + + +void +removable_disk_reload(uint8_t id) +{ + if (wcslen(hdd[id].fn) != 0) { + /* Attempting to reload while an image is already loaded. Do nothing. */ + return; + } + + scsi_reloadhd(id); +#if 0 + scsi_disk_insert(id); +#endif + + ui_sb_update_icon_state(SB_RDISK|id, wcslen(hdd[id].fn) ? 0 : 1); + + ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_EJECT | id, MF_BYCOMMAND | (wcslen(hdd[id].fn) ? MF_ENABLED : MF_GRAYED)); + ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | (wcslen(hdd[id].fn) ? MF_ENABLED : MF_GRAYED)); + + ui_sb_update_tip(SB_RDISK|id); + + config_save(); +} diff --git a/src/cdrom/cdrom_ioctl.c b/src/win/win_cdrom_ioctl.c similarity index 99% rename from src/cdrom/cdrom_ioctl.c rename to src/win/win_cdrom_ioctl.c index 2829f524c..e99b372d1 100644 --- a/src/cdrom/cdrom_ioctl.c +++ b/src/win/win_cdrom_ioctl.c @@ -9,22 +9,28 @@ * Implementation of the CD-ROM host drive IOCTL interface for * Windows using SCSI Passthrough Direct. * - * Version: @(#)cdrom_ioctl.c 1.0.3 2017/09/03 + * Version: @(#)cdrom_ioctl.c 1.0.6 2017/10/09 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2016 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ #define WINVER 0x0600 #include #include -#include "ntddcdrm.h" -#include "ntddscsi.h" +#include +#include +#include +#include +#include +#include #include "../ibm.h" +#include "../device.h" #include "../scsi/scsi.h" -#include "cdrom.h" -#include "cdrom_ioctl.h" +#include "../cdrom/cdrom.h" +#include "../plat.h" #define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) diff --git a/src/win/win_cgapal.h b/src/win/win_cgapal.h deleted file mode 100644 index 0388cde27..000000000 --- a/src/win/win_cgapal.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * The Windows CGA palette handler header. - * - * Version: @(#)win_cgapal.h 1.0.0 2017/05/30 - * - * Author: Miran Grca, - * Copyright 2016-2017 Miran Grca. - */ - -extern PALETTE cgapal; -extern PALETTE cgapal_mono[6]; - -extern uint32_t pal_lookup[256]; - -#ifdef __cplusplus -extern "C" { -#endif -void cgapal_rebuild(); -void destroy_bitmap(BITMAP *b); -#ifdef __cplusplus -} -#endif diff --git a/src/win/win_d3d.cc b/src/win/win_d3d.cc index 3b7740d56..91f6897cb 100644 --- a/src/win/win_d3d.cc +++ b/src/win/win_d3d.cc @@ -8,10 +8,11 @@ * * Direct3D 9 rendererer and screenshots taking. * - * Version: @(#)win_d3d.cc 1.0.1 2017/08/23 + * Version: @(#)win_d3d.cc 1.0.4 2017/10/13 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ @@ -19,20 +20,20 @@ #include "../video/video.h" #include "win.h" #include "win_d3d.h" -#include "win_cgapal.h" extern "C" void fatal(const char *format, ...); extern "C" void pclog(const char *format, ...); extern "C" void device_force_redraw(void); -extern "C" void video_blit_complete(void); +extern "C" void d3d_take_screenshot(wchar_t *fn); void d3d_init_objects(void); void d3d_close_objects(void); -void d3d_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); -void d3d_blit_memtoscreen_8(int x, int y, int w, int h); + +static void blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +static void blit_memtoscreen_8(int x, int y, int w, int h); static LPDIRECT3D9 d3d = NULL; static LPDIRECT3DDEVICE9 d3ddev = NULL; @@ -99,9 +100,8 @@ int d3d_init(HWND h) fatal("CreateDevice failed\n"); d3d_init_objects(); - - video_blit_memtoscreen_func = d3d_blit_memtoscreen; - video_blit_memtoscreen_8_func = d3d_blit_memtoscreen_8; + + video_setblit(blit_memtoscreen_8, blit_memtoscreen); return 1; } @@ -228,7 +228,12 @@ void d3d_close() } } -void d3d_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +int d3d_pause(void) +{ + return(0); +} + +static void blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) { HRESULT hr = D3D_OK; VOID* pVoid; @@ -322,7 +327,7 @@ void d3d_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) PostMessage(d3d_hwnd, WM_RESETD3D, 0, 0); } -void d3d_blit_memtoscreen_8(int x, int y, int w, int h) +static void blit_memtoscreen_8(int x, int y, int w, int h) { VOID* pVoid; D3DLOCKED_RECT dr; diff --git a/src/win/win_d3d.h b/src/win/win_d3d.h index 11128d486..2757d6902 100644 --- a/src/win/win_d3d.h +++ b/src/win/win_d3d.h @@ -8,14 +8,14 @@ * * Direct3D 9 rendererer and screenshots taking. * - * Version: @(#)win_d3d.h 1.0.0 2017/05/30 + * Version: @(#)win_d3d.h 1.0.2 2017/10/13 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - #ifndef WIN_D3D_H # define WIN_D3D_H # define UNICODE @@ -32,12 +32,16 @@ extern "C" { extern int d3d_init(HWND h); extern void d3d_close(void); extern void d3d_reset(void); +extern int d3d_pause(void); extern void d3d_resize(int x, int y); +extern void d3d_take_screenshot(wchar_t *fn); extern int d3d_fs_init(HWND h); extern void d3d_fs_close(void); extern void d3d_fs_reset(void); +extern int d3d_fs_pause(void); extern void d3d_fs_resize(int x, int y); +extern void d3d_fs_take_screenshot(wchar_t *fn); #ifdef __cplusplus } diff --git a/src/win/win_d3d_fs.cc b/src/win/win_d3d_fs.cc index 575d18d80..7e10b4fc5 100644 --- a/src/win/win_d3d_fs.cc +++ b/src/win/win_d3d_fs.cc @@ -6,12 +6,13 @@ * * This file is part of the 86Box distribution. * - * Direct3D 9 full screen rendererer and screenshots taking. + * Direct3D 9 full-screen rendererer. * - * Version: @(#)win_d3d_fs.cc 1.0.2 2017/08/23 + * Version: @(#)win_d3d_fs.cc 1.0.6 2017/10/13 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ @@ -21,7 +22,6 @@ #include "../video/video.h" #include "win.h" #include "win_d3d.h" -#include "win_cgapal.h" extern "C" void fatal(const char *format, ...); @@ -29,12 +29,14 @@ extern "C" void pclog(const char *format, ...); extern "C" void device_force_redraw(void); +extern "C" void video_blit_complete(void); + +extern "C" void d3d_fs_take_screenshot(wchar_t *fn); + static void d3d_fs_init_objects(void); static void d3d_fs_close_objects(void); -static void d3d_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); -static void d3d_fs_blit_memtoscreen_8(int x, int y, int w, int h); - -extern "C" void video_blit_complete(void); +static void blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +static void blit_memtoscreen_8(int x, int y, int w, int h); static LPDIRECT3D9 d3d = NULL; @@ -45,9 +47,9 @@ static D3DPRESENT_PARAMETERS d3dpp; static HWND d3d_hwnd; static HWND d3d_device_window; - static int d3d_fs_w, d3d_fs_h; + struct CUSTOMVERTEX { FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag @@ -55,58 +57,6 @@ struct CUSTOMVERTEX FLOAT tu, tv; }; -PALETTE cgapal = -{ - {0,0,0},{0,42,0},{42,0,0},{42,21,0}, - {0,0,0},{0,42,42},{42,0,42},{42,42,42}, - {0,0,0},{21,63,21},{63,21,21},{63,63,21}, - {0,0,0},{21,63,63},{63,21,63},{63,63,63}, - - {0,0,0},{0,0,42},{0,42,0},{0,42,42}, - {42,0,0},{42,0,42},{42,21,00},{42,42,42}, - {21,21,21},{21,21,63},{21,63,21},{21,63,63}, - {63,21,21},{63,21,63},{63,63,21},{63,63,63}, - - {0,0,0},{0,21,0},{0,0,42},{0,42,42}, - {42,0,21},{21,10,21},{42,0,42},{42,0,63}, - {21,21,21},{21,63,21},{42,21,42},{21,63,63}, - {63,0,0},{42,42,0},{63,21,42},{41,41,41}, - - {0,0,0},{0,42,42},{42,0,0},{42,42,42}, - {0,0,0},{0,42,42},{42,0,0},{42,42,42}, - {0,0,0},{0,63,63},{63,0,0},{63,63,63}, - {0,0,0},{0,63,63},{63,0,0},{63,63,63}, -}; - -PALETTE cgapal_mono[6] = -{ - { // 0 - green, 4-color-optimized contrast - {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x17,0x05},{0x01,0x1a,0x06},{0x02,0x28,0x09},{0x02,0x2c,0x0a},{0x03,0x39,0x0d},{0x03,0x3c,0x0e}, - {0x00,0x07,0x01},{0x01,0x13,0x04},{0x01,0x1f,0x07},{0x01,0x23,0x08},{0x02,0x31,0x0b},{0x02,0x35,0x0c},{0x05,0x3f,0x11},{0x0d,0x3f,0x17}, - }, - { // 1 - green, 16-color-optimized contrast - {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x15,0x05},{0x01,0x17,0x05},{0x01,0x21,0x08},{0x01,0x24,0x08},{0x02,0x2e,0x0b},{0x02,0x31,0x0b}, - {0x01,0x22,0x08},{0x02,0x28,0x09},{0x02,0x30,0x0b},{0x02,0x32,0x0c},{0x03,0x39,0x0d},{0x03,0x3b,0x0e},{0x09,0x3f,0x14},{0x0d,0x3f,0x17}, - }, - { // 2 - amber, 4-color-optimized contrast - {0x00,0x00,0x00},{0x15,0x05,0x00},{0x20,0x0b,0x00},{0x24,0x0d,0x00},{0x33,0x18,0x00},{0x37,0x1b,0x00},{0x3f,0x26,0x01},{0x3f,0x2b,0x06}, - {0x0b,0x02,0x00},{0x1b,0x08,0x00},{0x29,0x11,0x00},{0x2e,0x14,0x00},{0x3b,0x1e,0x00},{0x3e,0x21,0x00},{0x3f,0x32,0x0a},{0x3f,0x38,0x0d}, - }, - { // 3 - amber, 16-color-optimized contrast - {0x00,0x00,0x00},{0x15,0x05,0x00},{0x1e,0x09,0x00},{0x21,0x0b,0x00},{0x2b,0x12,0x00},{0x2f,0x15,0x00},{0x38,0x1c,0x00},{0x3b,0x1e,0x00}, - {0x2c,0x13,0x00},{0x32,0x17,0x00},{0x3a,0x1e,0x00},{0x3c,0x1f,0x00},{0x3f,0x27,0x01},{0x3f,0x2a,0x04},{0x3f,0x36,0x0c},{0x3f,0x38,0x0d}, - }, - { // 4 - grey, 4-color-optimized contrast - {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x15,0x17,0x18},{0x18,0x1a,0x1b},{0x24,0x25,0x25},{0x27,0x28,0x28},{0x33,0x34,0x32},{0x37,0x38,0x35}, - {0x09,0x0a,0x0b},{0x11,0x12,0x13},{0x1c,0x1e,0x1e},{0x20,0x22,0x22},{0x2c,0x2d,0x2c},{0x2f,0x30,0x2f},{0x3c,0x3c,0x38},{0x3f,0x3f,0x3b}, - }, - { // 5 - grey, 16-color-optimized contrast - {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x13,0x14,0x15},{0x15,0x17,0x18},{0x1e,0x20,0x20},{0x20,0x22,0x22},{0x29,0x2a,0x2a},{0x2c,0x2d,0x2c}, - {0x1f,0x21,0x21},{0x23,0x25,0x25},{0x2b,0x2c,0x2b},{0x2d,0x2e,0x2d},{0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a},{0x3f,0x3f,0x3b}, - } -}; - -uint32_t pal_lookup[256]; static CUSTOMVERTEX d3d_verts[] = { @@ -128,43 +78,6 @@ static CUSTOMVERTEX d3d_verts[] = }; -void cgapal_rebuild(void) -{ - int c; - for (c = 0; c < 256; c++) - { - pal_lookup[c] = makecol(video_6to8[cgapal[c].r], video_6to8[cgapal[c].g], video_6to8[cgapal[c].b]); - } - if ((cga_palette > 1) && (cga_palette < 8)) - { - if (vid_cga_contrast != 0) - { - for (c = 0; c < 16; c++) - { - pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], video_6to8[cgapal_mono[cga_palette - 2][c].g], video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c + 16] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], video_6to8[cgapal_mono[cga_palette - 2][c].g], video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c + 32] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], video_6to8[cgapal_mono[cga_palette - 2][c].g], video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c + 48] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], video_6to8[cgapal_mono[cga_palette - 2][c].g], video_6to8[cgapal_mono[cga_palette - 2][c].b]); - } - } - else - { - for (c = 0; c < 16; c++) - { - pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], video_6to8[cgapal_mono[cga_palette - 1][c].g], video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c + 16] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], video_6to8[cgapal_mono[cga_palette - 1][c].g], video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c + 32] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], video_6to8[cgapal_mono[cga_palette - 1][c].g], video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c + 48] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], video_6to8[cgapal_mono[cga_palette - 1][c].g], video_6to8[cgapal_mono[cga_palette - 1][c].b]); - } - } - } - - if (cga_palette == 8) - { - pal_lookup[0x16] = makecol(video_6to8[42], video_6to8[42], video_6to8[0]); - } -} - int d3d_fs_init(HWND h) { int c; @@ -173,16 +86,15 @@ int d3d_fs_init(HWND h) d3d_fs_w = GetSystemMetrics(SM_CXSCREEN); d3d_fs_h = GetSystemMetrics(SM_CYSCREEN); + d3d_hwnd = h; for (c = 0; c < 256; c++) pal_lookup[c] = makecol(cgapal[c].r << 2, cgapal[c].g << 2, cgapal[c].b << 2); - d3d_hwnd = h; - /*FIXME: should be done once, in win.c */ _swprintf(emulator_title, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); d3d_device_window = CreateWindowEx ( 0, - szSubClassName, + SUB_CLASS_NAME, emulator_title, WS_POPUP, CW_USEDEFAULT, @@ -217,9 +129,8 @@ int d3d_fs_init(HWND h) fatal("CreateDevice failed\n"); d3d_fs_init_objects(); - - video_blit_memtoscreen_func = d3d_fs_blit_memtoscreen; - video_blit_memtoscreen_8_func = d3d_fs_blit_memtoscreen_8; + + video_setblit(blit_memtoscreen_8, blit_memtoscreen); return 1; } @@ -338,6 +249,11 @@ void d3d_fs_close() DestroyWindow(d3d_device_window); } +int d3d_fs_pause(void) +{ + return(0); +} + static void d3d_fs_size(RECT window_rect, double *l, double *t, double *r, double *b, int w, int h) { int ratio_w, ratio_h; @@ -388,7 +304,7 @@ static void d3d_fs_size(RECT window_rect, double *l, double *t, double *r, doubl } } -static void d3d_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +static void blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) { HRESULT hr = D3D_OK; VOID* pVoid; @@ -497,10 +413,10 @@ static void d3d_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) hr = d3ddev->Present(NULL, NULL, d3d_device_window, NULL); if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL) - PostMessage(ghwnd, WM_RESETD3D, 0, 0); + PostMessage(hwndMain, WM_RESETD3D, 0, 0); } -static void d3d_fs_blit_memtoscreen_8(int x, int y, int w, int h) +static void blit_memtoscreen_8(int x, int y, int w, int h) { HRESULT hr = D3D_OK; VOID* pVoid; @@ -615,7 +531,7 @@ static void d3d_fs_blit_memtoscreen_8(int x, int y, int w, int h) hr = d3ddev->Present(NULL, NULL, d3d_device_window, NULL); if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL) - PostMessage(ghwnd, WM_RESETD3D, 0, 0); + PostMessage(hwndMain, WM_RESETD3D, 0, 0); } diff --git a/src/win/win_ddraw.cc b/src/win/win_ddraw.cc index e87265f87..ce02b4fa4 100644 --- a/src/win/win_ddraw.cc +++ b/src/win/win_ddraw.cc @@ -3,9 +3,15 @@ */ #include #include +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#undef BITMAP #include "../video/video.h" +#include "../plat.h" +#include "../ui.h" #include "win_ddraw.h" -#include "win_cgapal.h" +#include "win.h" extern "C" void fatal(const char *format, ...); @@ -14,12 +20,10 @@ extern "C" void pclog(const char *format, ...); extern "C" void device_force_redraw(void); extern "C" int ddraw_init(HWND h); +extern "C" int ddraw_pause(void); extern "C" void ddraw_close(void); +extern "C" void ddraw_take_screenshot(wchar_t *fn); -extern "C" void video_blit_complete(void); - -static void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); -static void ddraw_blit_memtoscreen_8(int x, int y, int w, int h); static LPDIRECTDRAW lpdd = NULL; static LPDIRECTDRAW7 lpdd7 = NULL; @@ -28,259 +32,376 @@ static LPDIRECTDRAWSURFACE7 lpdds_back = NULL; static LPDIRECTDRAWSURFACE7 lpdds_back2 = NULL; static LPDIRECTDRAWCLIPPER lpdd_clipper = NULL; static DDSURFACEDESC2 ddsd; - static HWND ddraw_hwnd; +static HBITMAP hbitmap; +static int xs, ys, ys2; -int ddraw_init(HWND h) -{ - cgapal_rebuild(); - if (FAILED(DirectDrawCreate(NULL, &lpdd, NULL))) - return 0; - - if (FAILED(lpdd->QueryInterface(IID_IDirectDraw7, (LPVOID *)&lpdd7))) - return 0; +static void +CopySurface(IDirectDrawSurface7 *pDDSurface) +{ + HDC hdc, hmemdc; + HBITMAP hprevbitmap; + DDSURFACEDESC2 ddsd2; - lpdd->Release(); - lpdd = NULL; - - atexit(ddraw_close); - - if (FAILED(lpdd7->SetCooperativeLevel(h, DDSCL_NORMAL))) - return 0; - - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_pri, NULL))) - return 0; - - // memset(&ddsd, 0, sizeof(ddsd)); - // ddsd.dwSize = sizeof(ddsd); - - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.dwWidth = 2048; - ddsd.dwHeight = 2048; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; - if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_back, NULL))) - { - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.dwWidth = 2048; - ddsd.dwHeight = 2048; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_back, NULL))) - fatal("CreateSurface back failed\n"); - } - - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.dwWidth = 2048; - ddsd.dwHeight = 2048; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; - if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_back2, NULL))) - { - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.dwWidth = 2048; - ddsd.dwHeight = 2048; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_back2, NULL))) - fatal("CreateSurface back failed\n"); - } - - if (FAILED(lpdd7->CreateClipper(0, &lpdd_clipper, NULL))) - return 0; - if (FAILED(lpdd_clipper->SetHWnd(0, h))) - return 0; - if (FAILED(lpdds_pri->SetClipper(lpdd_clipper))) - return 0; - - pclog("DDRAW_INIT complete\n"); - ddraw_hwnd = h; - video_blit_memtoscreen_func = ddraw_blit_memtoscreen; - video_blit_memtoscreen_8_func = ddraw_blit_memtoscreen_8; - - return 1; + pDDSurface->GetDC(&hdc); + hmemdc = CreateCompatibleDC(hdc); + ZeroMemory(&ddsd2 ,sizeof( ddsd2 )); // better to clear before using + ddsd2.dwSize = sizeof( ddsd2 ); //initialize with size + pDDSurface->GetSurfaceDesc(&ddsd2); + hbitmap = CreateCompatibleBitmap( hdc ,xs ,ys); + hprevbitmap = (HBITMAP) SelectObject( hmemdc, hbitmap ); + BitBlt(hmemdc,0 ,0 ,xs ,ys ,hdc ,0 ,0,SRCCOPY); + SelectObject(hmemdc,hprevbitmap); // restore the old bitmap + DeleteDC(hmemdc); + pDDSurface->ReleaseDC(hdc); } -void ddraw_close(void) + +static void +DoubleLines(uint8_t *dst, uint8_t *src) { - if (lpdds_back2) - { - lpdds_back2->Release(); - lpdds_back2 = NULL; - } - if (lpdds_back) - { - lpdds_back->Release(); - lpdds_back = NULL; - } - if (lpdds_pri) - { - lpdds_pri->Release(); - lpdds_pri = NULL; - } - if (lpdd_clipper) - { - lpdd_clipper->Release(); - lpdd_clipper = NULL; - } - if (lpdd7) - { - lpdd7->Release(); - lpdd7 = NULL; - } + int i = 0; + + for (i = 0; i < ys; i++) { + memcpy(dst + (i * xs * 8), src + (i * xs * 4), xs * 4); + memcpy(dst + ((i * xs * 8) + (xs * 4)), src + (i * xs * 4), xs * 4); + } } -static void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) + +static void +SaveBitmap(wchar_t *szFilename, HBITMAP hBitmap) { - RECT r_src; - RECT r_dest; - int yy; - POINT po; - HRESULT hr; -// pclog("Blit memtoscreen %i,%i %i %i %i,%i\n", x, y, y1, y2, w, h); + static WCHAR szMessage[512]; + BITMAPFILEHEADER bmpFileHeader; + BITMAPINFO bmpInfo; + HDC hdc; + FILE *fp = NULL; + LPVOID pBuf = NULL; + LPVOID pBuf2 = NULL; - if (lpdds_back == NULL) - { - video_blit_complete(); - return; /*Nothing to do*/ - } + do { + hdc = GetDC(NULL); - if (h <= 0) - { - video_blit_complete(); - return; + ZeroMemory(&bmpInfo, sizeof(BITMAPINFO)); + bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + + GetDIBits(hdc, hBitmap, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS); + + if (bmpInfo.bmiHeader.biSizeImage <= 0) + bmpInfo.bmiHeader.biSizeImage = + bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8; + + if ((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) { +// pclog("ERROR: Unable to Allocate Bitmap Memory"); + break; } - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); + if (ys2 <= 250) + pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage * 2); - hr = lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); - if (hr == DDERR_SURFACELOST) - { - lpdds_back->Restore(); - lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); - device_force_redraw(); - } - if (!ddsd.lpSurface) - { - video_blit_complete(); - return; - } - for (yy = y1; yy < y2; yy++) - { - if ((y + yy) >= 0 && (y + yy) < buffer->h) - memcpy((uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); - } - video_blit_complete(); - lpdds_back->Unlock(NULL); + bmpInfo.bmiHeader.biCompression = BI_RGB; - po.x = po.y = 0; - - ClientToScreen(ddraw_hwnd, &po); - GetClientRect(ddraw_hwnd, &r_dest); - OffsetRect(&r_dest, po.x, po.y); - - r_src.left = 0; - r_src.top = 0; - r_src.right = w; - r_src.bottom = h; + GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight, pBuf, &bmpInfo, DIB_RGB_COLORS); - hr = lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL); - if (hr == DDERR_SURFACELOST) - { - lpdds_back2->Restore(); - lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL); - } + if ((fp = _wfopen(szFilename, L"wb")) == NULL) { + _swprintf(szMessage, + plat_get_string(IDS_2088), szFilename); + ui_msgbox(MBX_ERROR, szMessage); + break; + } - lpdds_back2->Unlock(NULL); - -// pclog("Blit from %i,%i %i,%i to %i,%i %i,%i\n", r_src.left, r_src.top, r_src.right, r_src.bottom, r_dest.left, r_dest.top, r_dest.right, r_dest.bottom); - hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL); - if (hr == DDERR_SURFACELOST) - { - lpdds_pri->Restore(); - lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL); - } + bmpFileHeader.bfReserved1 = 0; + bmpFileHeader.bfReserved2 = 0; + if (pBuf2) { + bmpInfo.bmiHeader.biSizeImage <<= 1; + bmpInfo.bmiHeader.biHeight <<= 1; + } + bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage; + bmpFileHeader.bfType=0x4D42; + bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); + + (void)fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp); + (void)fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp); + if (pBuf2) { + DoubleLines((uint8_t *) pBuf2, (uint8_t *) pBuf); + (void)fwrite(pBuf2,bmpInfo.bmiHeader.biSizeImage,1,fp); + } else { + (void)fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp); + } + } while(false); + + if (hdc) ReleaseDC(NULL,hdc); + + if (pBuf2) free(pBuf2); + + if (pBuf) free(pBuf); + + if (fp) fclose(fp); } -static void ddraw_blit_memtoscreen_8(int x, int y, int w, int h) -{ - RECT r_src; - RECT r_dest; - int xx, yy; - POINT po; - uint32_t *p; - HRESULT hr; - if (lpdds_back == NULL) +void +ddraw_common_take_screenshot(wchar_t *fn, IDirectDrawSurface7 *pDDSurface) +{ + xs = xsize; + ys = ys2 = ysize; + /* For EGA/(S)VGA, the size is NOT adjusted for overscan. */ + if ((overscan_y > 16) && enable_overscan) { - video_blit_complete(); - return; /*Nothing to do*/ - } - - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - - hr = lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); - - if (hr == DDERR_SURFACELOST) - { - lpdds_back->Restore(); - lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); - device_force_redraw(); - } - if (!ddsd.lpSurface) - { - video_blit_complete(); - return; - } - for (yy = 0; yy < h; yy++) - { - if ((y + yy) >= 0 && (y + yy) < buffer->h) - { - p = (uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]); - for (xx = 0; xx < w; xx++) - { - p[xx] = pal_lookup[buffer->line[y + yy][x + xx]]; - } - } - } - p = &(((uint32_t *) ddsd.lpSurface)[4 * ddsd.lPitch]); - lpdds_back->Unlock(NULL); - video_blit_complete(); - - po.x = po.y = 0; - - ClientToScreen(ddraw_hwnd, &po); - GetClientRect(ddraw_hwnd, &r_dest); - OffsetRect(&r_dest, po.x, po.y); - - r_src.left = 0; - r_src.top = 0; - r_src.right = w; - r_src.bottom = h; - - hr = lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL); - if (hr == DDERR_SURFACELOST) - { - lpdds_back2->Restore(); - lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL); - } - - hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL); - if (hr == DDERR_SURFACELOST) - { - lpdds_pri->Restore(); - hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL); - } + xs += overscan_x; + ys += overscan_y; + } + /* For CGA, the width is adjusted for overscan, but the height is not. */ + if (overscan_y == 16) + { + if (ys2 <= 250) + ys += (overscan_y >> 1); + else + ys += overscan_y; + } + CopySurface(pDDSurface); + SaveBitmap(fn, hbitmap); } -void ddraw_take_screenshot(wchar_t *fn) + +static void +blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) { - ddraw_common_take_screenshot(fn, lpdds_back2); + RECT r_src; + RECT r_dest; + int yy; + POINT po; + HRESULT hr; + +// pclog("Blit memtoscreen %i,%i %i %i %i,%i\n", x, y, y1, y2, w, h); + + if (lpdds_back == NULL) { + video_blit_complete(); + return; /*Nothing to do*/ + } + + if (h <= 0) { + video_blit_complete(); + return; + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + hr = lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + lpdds_back->Restore(); + lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + device_force_redraw(); + } + if (!ddsd.lpSurface) { + video_blit_complete(); + return; + } + + for (yy = y1; yy < y2; yy++) { + if ((y + yy) >= 0 && (y + yy) < buffer->h) + memcpy((uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + } + video_blit_complete(); + lpdds_back->Unlock(NULL); + + po.x = po.y = 0; + + ClientToScreen(ddraw_hwnd, &po); + GetClientRect(ddraw_hwnd, &r_dest); + OffsetRect(&r_dest, po.x, po.y); + + r_src.left = 0; + r_src.top = 0; + r_src.right = w; + r_src.bottom = h; + + hr = lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + lpdds_back2->Restore(); + lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL); + } + + lpdds_back2->Unlock(NULL); + +// pclog("Blit from %i,%i %i,%i to %i,%i %i,%i\n", r_src.left, r_src.top, r_src.right, r_src.bottom, r_dest.left, r_dest.top, r_dest.right, r_dest.bottom); + hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + lpdds_pri->Restore(); + lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL); + } +} + + +static void +blit_memtoscreen_8(int x, int y, int w, int h) +{ + RECT r_src; + RECT r_dest; + int xx, yy; + POINT po; + uint32_t *p; + HRESULT hr; + + if (lpdds_back == NULL) { + video_blit_complete(); + return; /*Nothing to do*/ + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + hr = lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + lpdds_back->Restore(); + lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + device_force_redraw(); + } + if (!ddsd.lpSurface) { + video_blit_complete(); + return; + } + + for (yy = 0; yy < h; yy++) { + if ((y + yy) >= 0 && (y + yy) < buffer->h) { + p = (uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]); + for (xx = 0; xx < w; xx++) + p[xx] = pal_lookup[buffer->line[y + yy][x + xx]]; + } + } + p = &(((uint32_t *) ddsd.lpSurface)[4 * ddsd.lPitch]); + lpdds_back->Unlock(NULL); + video_blit_complete(); + + po.x = po.y = 0; + ClientToScreen(ddraw_hwnd, &po); + GetClientRect(ddraw_hwnd, &r_dest); + OffsetRect(&r_dest, po.x, po.y); + + r_src.left = 0; + r_src.top = 0; + r_src.right = w; + r_src.bottom = h; + + hr = lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + lpdds_back2->Restore(); + lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL); + } + + hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + lpdds_pri->Restore(); + hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL); + } +} + + +int +ddraw_init(HWND h) +{ + if (FAILED(DirectDrawCreate(NULL, &lpdd, NULL))) return(0); + + if (FAILED(lpdd->QueryInterface(IID_IDirectDraw7, (LPVOID *)&lpdd7))) + return(0); + + lpdd->Release(); + lpdd = NULL; + + atexit(ddraw_close); + + if (FAILED(lpdd7->SetCooperativeLevel(h, DDSCL_NORMAL))) return(0); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_pri, NULL))) return(0); + + // memset(&ddsd, 0, sizeof(ddsd)); + // ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = 2048; + ddsd.dwHeight = 2048; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_back, NULL))) { + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = 2048; + ddsd.dwHeight = 2048; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_back, NULL))) + fatal("CreateSurface back failed\n"); + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = 2048; + ddsd.dwHeight = 2048; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_back2, NULL))) { + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = 2048; + ddsd.dwHeight = 2048; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + if (FAILED(lpdd7->CreateSurface(&ddsd, &lpdds_back2, NULL))) + fatal("CreateSurface back failed\n"); + } + + if (FAILED(lpdd7->CreateClipper(0, &lpdd_clipper, NULL))) return(0); + + if (FAILED(lpdd_clipper->SetHWnd(0, h))) return(0); + + if (FAILED(lpdds_pri->SetClipper(lpdd_clipper))) return(0); + + ddraw_hwnd = h; + + video_setblit(blit_memtoscreen_8, blit_memtoscreen); + + return(1); +} + + +void +ddraw_close(void) +{ + if (lpdds_back2) { + lpdds_back2->Release(); + lpdds_back2 = NULL; + } + if (lpdds_back) { + lpdds_back->Release(); + lpdds_back = NULL; + } + if (lpdds_pri) { + lpdds_pri->Release(); + lpdds_pri = NULL; + } + if (lpdd_clipper) { + lpdd_clipper->Release(); + lpdd_clipper = NULL; + } + if (lpdd7) { + lpdd7->Release(); + lpdd7 = NULL; + } +} + + +int +ddraw_pause(void) +{ + return(0); +} + + +void +ddraw_take_screenshot(wchar_t *fn) +{ + ddraw_common_take_screenshot(fn, lpdds_back2); } diff --git a/src/win/win_ddraw.h b/src/win/win_ddraw.h index 5090aa0cc..fa47da60f 100644 --- a/src/win/win_ddraw.h +++ b/src/win/win_ddraw.h @@ -15,12 +15,13 @@ extern "C" { extern int ddraw_init(HWND h); extern void ddraw_close(void); +extern int ddraw_pause(void); +extern void ddraw_take_screenshot(wchar_t *fn); extern int ddraw_fs_init(HWND h); extern void ddraw_fs_close(void); - -extern void ddraw_common_take_screenshot(wchar_t *fn, - IDirectDrawSurface7 *pDDSurface); +extern int ddraw_fs_pause(void); +extern void ddraw_fs_take_screenshot(wchar_t *fn); #ifdef __cplusplus } diff --git a/src/win/win_ddraw_fs.cc b/src/win/win_ddraw_fs.cc index abb390093..5604def7b 100644 --- a/src/win/win_ddraw_fs.cc +++ b/src/win/win_ddraw_fs.cc @@ -4,7 +4,6 @@ #include #include "../video/video.h" #include "win_ddraw.h" -#include "win_cgapal.h" static LPDIRECTDRAW lpdd = NULL; @@ -25,11 +24,14 @@ extern "C" void device_force_redraw(void); extern "C" int ddraw_fs_init(HWND h); extern "C" void ddraw_fs_close(void); +extern "C" int ddraw_fs_pause(void); +extern "C" void ddraw_fs_take_screenshot(wchar_t *fn); -extern "C" void video_blit_complete(void); +extern void ddraw_common_take_screenshot(wchar_t *fn, IDirectDrawSurface7 *pDDSurface); -static void ddraw_fs_blit_memtoscreen(int, int, int, int, int, int); -static void ddraw_fs_blit_memtoscreen_8(int, int, int, int); + +static void blit_memtoscreen(int, int, int, int, int, int); +static void blit_memtoscreen_8(int, int, int, int); int ddraw_fs_init(HWND h) @@ -89,8 +91,8 @@ int ddraw_fs_init(HWND h) pclog("DDRAW_INIT complete\n"); ddraw_hwnd = h; - video_blit_memtoscreen_func = ddraw_fs_blit_memtoscreen; - video_blit_memtoscreen_8_func = ddraw_fs_blit_memtoscreen_8; + + video_setblit(blit_memtoscreen_8, blit_memtoscreen); return 1; } @@ -174,7 +176,7 @@ static void ddraw_fs_size(RECT window_rect, RECT *r_dest, int w, int h) } } -static void ddraw_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +static void blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) { RECT r_src; RECT r_dest; @@ -242,7 +244,7 @@ static void ddraw_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h } } -static void ddraw_fs_blit_memtoscreen_8(int x, int y, int w, int h) +static void blit_memtoscreen_8(int x, int y, int w, int h) { RECT r_src; RECT r_dest; @@ -313,6 +315,14 @@ static void ddraw_fs_blit_memtoscreen_8(int x, int y, int w, int h) lpdds_pri->Flip(NULL, DDFLIP_NOVSYNC); } + +int +ddraw_fs_pause(void) +{ + return(0); +} + + void ddraw_fs_take_screenshot(wchar_t *fn) { ddraw_common_take_screenshot(fn, lpdds_back2); diff --git a/src/win/win_ddraw_screenshot.cc b/src/win/win_ddraw_screenshot.cc deleted file mode 100644 index 27bb5b0b1..000000000 --- a/src/win/win_ddraw_screenshot.cc +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * DirectDraw screenshot taking code. - * - * Version: @(#)win_ddraw_screenshot.cc 1.0.1 2017/08/23 - * - * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. - */ - -#include -#include -#define UNICODE -#define BITMAP WINDOWS_BITMAP -#include -#undef BITMAP -#include "../video/video.h" -#include "win.h" -#include "win_ddraw.h" -#include "win_language.h" - - -HBITMAP hbitmap; -int xs, ys, ys2; - - -extern "C" void pclog(const char *format, ...); - - -void CopySurface(IDirectDrawSurface7 *pDDSurface) -{ - HDC hdc, hmemdc; - - HBITMAP hprevbitmap; - - DDSURFACEDESC2 ddsd2; - - pDDSurface->GetDC(&hdc); - - hmemdc = CreateCompatibleDC(hdc); - - ZeroMemory(&ddsd2 ,sizeof( ddsd2 )); // better to clear before using - - ddsd2.dwSize = sizeof( ddsd2 ); //initialize with size - - pDDSurface->GetSurfaceDesc(&ddsd2); - - hbitmap = CreateCompatibleBitmap( hdc ,xs ,ys); - - hprevbitmap = (HBITMAP) SelectObject( hmemdc, hbitmap ); - - BitBlt(hmemdc,0 ,0 ,xs ,ys ,hdc ,0 ,0,SRCCOPY); - - SelectObject(hmemdc,hprevbitmap); // restore the old bitmap - - DeleteDC(hmemdc); - - pDDSurface->ReleaseDC(hdc); - - return ; -} - - -void DoubleLines(uint8_t *dst, uint8_t *src) -{ - int i = 0; - for (i = 0; i < ys; i++) - { - memcpy(dst + (i * xs * 8), src + (i * xs * 4), xs * 4); - memcpy(dst + ((i * xs * 8) + (xs * 4)), src + (i * xs * 4), xs * 4); - } -} - -static WCHAR szMessage[2048]; - -void SaveBitmap(wchar_t *szFilename,HBITMAP hBitmap) -{ - HDC hdc=NULL; - FILE* fp=NULL; - LPVOID pBuf=NULL; - LPVOID pBuf2=NULL; - BITMAPINFO bmpInfo; - BITMAPFILEHEADER bmpFileHeader; - - do{ - - hdc=GetDC(NULL); - - ZeroMemory(&bmpInfo,sizeof(BITMAPINFO)); - - bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); - - GetDIBits(hdc,hBitmap,0,0,NULL,&bmpInfo,DIB_RGB_COLORS); - - if(bmpInfo.bmiHeader.biSizeImage<=0) - bmpInfo.bmiHeader.biSizeImage=bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8; - - if((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage))==NULL) - { - // pclog("ERROR: Unable to Allocate Bitmap Memory"); - break; - } - - if (ys2 <= 250) - { - pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage * 2); - } - - bmpInfo.bmiHeader.biCompression=BI_RGB; - - GetDIBits(hdc,hBitmap,0,bmpInfo.bmiHeader.biHeight,pBuf, &bmpInfo, DIB_RGB_COLORS); - - if((fp = _wfopen(szFilename,L"wb"))==NULL) - { - _swprintf(szMessage, win_language_get_string_from_id(IDS_2088), szFilename); - msgbox_error_wstr(ghwnd, szMessage); - break; - } - - bmpFileHeader.bfReserved1=0; - - bmpFileHeader.bfReserved2=0; - - if (pBuf2) - { - bmpInfo.bmiHeader.biSizeImage <<= 1; - bmpInfo.bmiHeader.biHeight <<= 1; - } - - bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage; - - bmpFileHeader.bfType=0x4D42; - - bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); - - fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp); - - fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp); - - if (pBuf2) - { - DoubleLines((uint8_t *) pBuf2, (uint8_t *) pBuf); - fwrite(pBuf2,bmpInfo.bmiHeader.biSizeImage,1,fp); - } - else - { - fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp); - } - - }while(false); - - if(hdc) ReleaseDC(NULL,hdc); - - if(pBuf2) free(pBuf2); - - if(pBuf) free(pBuf); - - if(fp) fclose(fp); -} - -void ddraw_common_take_screenshot(wchar_t *fn, IDirectDrawSurface7 *pDDSurface) -{ - xs = xsize; - ys = ys2 = ysize; - /* For EGA/(S)VGA, the size is NOT adjusted for overscan. */ - if ((overscan_y > 16) && enable_overscan) - { - xs += overscan_x; - ys += overscan_y; - } - /* For CGA, the width is adjusted for overscan, but the height is not. */ - if (overscan_y == 16) - { - if (ys2 <= 250) - ys += (overscan_y >> 1); - else - ys += overscan_y; - } - CopySurface(pDDSurface); - SaveBitmap(fn, hbitmap); -} diff --git a/src/win/win_deviceconfig.c b/src/win/win_deviceconfig.c index 21517727d..531a2867d 100644 --- a/src/win/win_deviceconfig.c +++ b/src/win/win_deviceconfig.c @@ -8,27 +8,33 @@ * * Windows device configuration dialog implementation. * - * Version: @(#)win_deviceconfig.c 1.0.1 2017/06/19 + * Version: @(#)win_deviceconfig.c 1.0.7 2017/10/10 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ +#include +#include +#include +#include #include "../ibm.h" #include "../config.h" #include "../device.h" -#include "plat_midi.h" -#define NO_UNICODE /*FIXME: not Unicode? */ +#include "../plat.h" +#include "../plat_midi.h" +#include "../ui.h" #include "win.h" -#include "win_language.h" #include static device_t *config_device; -static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +static BOOL CALLBACK +deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND h; @@ -42,6 +48,7 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam device_config_t *config; char s[80]; wchar_t ws[512]; + LPTSTR lptsTemp; switch (message) { @@ -50,6 +57,8 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam id = IDC_CONFIG_BASE; config = config_device->config; + lptsTemp = (LPTSTR) malloc(512); + while (config->type != -1) { device_config_selection_t *selection = config->selection; @@ -71,7 +80,8 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam c = 0; while (selection->description[0]) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)selection->description); + mbstowcs(lptsTemp, selection->description, strlen(selection->description) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); if (val_int == selection->value) SendMessage(h, CB_SETCURSEL, c, 0); selection++; @@ -88,7 +98,8 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam for (c = 0; c < num; c++) { plat_midi_get_dev_name(c, s); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); if (val_int == c) SendMessage(h, CB_SETCURSEL, c, 0); } @@ -99,15 +110,15 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam case CONFIG_SPINNER: val_int = config_get_int(config_device->name, config->name, config->default_int); - sprintf(s, "%i", val_int); - SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + _swprintf(ws, L"%i", val_int); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)ws); id += 2; break; case CONFIG_FILE: { - char* str = config_get_string(config_device->name, config->name, 0); + wchar_t* str = config_get_wstring(config_device->name, config->name, 0); if (str) SendMessage(h, WM_SETTEXT, 0, (LPARAM)str); id += 3; @@ -120,7 +131,8 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam c = 0; while (selection->description[0]) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)selection->description); + mbstowcs(lptsTemp, selection->description, strlen(selection->description) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); if (val_int == selection->value) SendMessage(h, CB_SETCURSEL, c, 0); selection++; @@ -136,7 +148,8 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam c = 0; while (selection->description[0]) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)selection->description); + mbstowcs(lptsTemp, selection->description, strlen(selection->description) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); if (val_int == selection->value) SendMessage(h, CB_SETCURSEL, c, 0); selection++; @@ -148,6 +161,8 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam } config++; } + + free(lptsTemp); } return TRUE; @@ -220,7 +235,8 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam else if (val_int < config->spinner.min) val_int = config->spinner.min; - SendMessage(h, WM_GETTEXT, 79, (LPARAM)s); + SendMessage(h, WM_GETTEXT, 79, (LPARAM)ws); + wcstombs(s, ws, 79); sscanf(s, "%i", &c); if (val_int != c) @@ -266,13 +282,13 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam return TRUE; } - ret = msgbox_reset(ghwnd); + ret = ui_msgbox(MBX_QUESTION, (wchar_t *)IDS_2051); switch(ret) { - case IDNO: + case 1: EndDialog(hdlg, 0); return TRUE; - case IDCANCEL: + case -1: return FALSE; default: break; @@ -311,9 +327,8 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam break; case CONFIG_FILE: - SendMessage(h, WM_GETTEXT, 511, (LPARAM)s); - - config_set_string(config_device->name, config->name, s); + SendMessage(h, WM_GETTEXT, 511, (LPARAM)ws); + config_set_wstring(config_device->name, config->name, ws); id += 3; break; @@ -352,9 +367,9 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam config++; } - saveconfig(); + config_save(); - resetpchard(); + pc_reset_hard(); EndDialog(hdlg, 0); return TRUE; @@ -433,7 +448,7 @@ static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam ws[c] = 0; if (!file_dlg(hdlg, ws, s, 0)) - SendMessage(h, WM_SETTEXT, 0, (LPARAM)openfilestring); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)wopenfilestring); } } break; diff --git a/src/win/win_dialog.c b/src/win/win_dialog.c new file mode 100644 index 000000000..a92bf8c02 --- /dev/null +++ b/src/win/win_dialog.c @@ -0,0 +1,250 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Several dialogs for the application. + * + * Version: @(#)win_dialog.c 1.0.3 2017/10/10 + * + * Author: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#include +#undef BITMAP +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../device.h" +#include "../plat.h" +#include "../ui.h" +#include "win.h" + + +WCHAR path[MAX_PATH]; + + +static int CALLBACK +BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) +{ + if (uMsg == BFFM_INITIALIZED) + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData); + + return(0); +} + + +wchar_t * +BrowseFolder(wchar_t *saved_path, wchar_t *title) +{ + BROWSEINFO bi = { 0 }; + LPITEMIDLIST pidl; + IMalloc *imalloc; + + bi.lpszTitle = title; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; + bi.lpfn = BrowseCallbackProc; + bi.lParam = (LPARAM) saved_path; + + pidl = SHBrowseForFolder(&bi); + if (pidl != 0) { + /* Get the name of the folder and put it in path. */ + SHGetPathFromIDList(pidl, path); + + /* Free memory used. */ + imalloc = 0; + if (SUCCEEDED(SHGetMalloc(&imalloc))) { + imalloc->lpVtbl->Free(imalloc, pidl); + imalloc->lpVtbl->Release(imalloc); + } + + return(path); + } + + return(L""); +} + + +int +ui_msgbox(int flags, void *arg) +{ + WCHAR temp[512]; + DWORD fl = 0; + WCHAR *str = NULL; + WCHAR *cap = NULL; + + switch(flags & 0x1f) { + case MBX_INFO: /* just an informational message */ + fl = (MB_OK | MB_ICONINFORMATION); + cap = plat_get_string(IDS_STRINGS); /* "86Box" */ + break; + + case MBX_ERROR: /* error message */ + if (flags & MBX_FATAL) { + fl = (MB_OK | MB_ICONERROR); + cap = plat_get_string(IDS_2050); /* "Fatal Error"*/ + } else { + fl = (MB_OK | MB_ICONWARNING); + cap = plat_get_string(IDS_2049); /* "Error" */ + } + break; + + case MBX_QUESTION: /* question */ + fl = (MB_YESNOCANCEL | MB_ICONQUESTION); + cap = plat_get_string(IDS_STRINGS); /* "86Box" */ + break; + } + + /* If ANSI string, convert it. */ + str = (WCHAR *)arg; + if (flags & MBX_ANSI) { + mbstowcs(temp, (char *)arg, strlen((char *)arg)+1); + str = temp; + } else { + /* + * It's a Unicode string. + * + * Well, no, maybe not. It could also be one of the + * strings stored in the Resources. Those are wide, + * but referenced by a numeric ID. + * + * The good news is, that strings are usually stored + * in the executable near the end of the code/rodata + * segment. This means, that *real* string pointers + * usually have a pretty high (numeric) value, much + * higher than the numeric ID's. So, we guesswork + * that if the value of 'arg' is low, its an ID.. + */ +#if defined(__gcc__) && defined(__x86_64__) + /* GCC, 64-bit mode. */ + if (((int64_t)arg) < ((int64_t)65636)) +#else + /* Assume 32-bit mode. */ + if (((uint32_t)arg) < ((uint32_t)65636)) +#endif + str = plat_get_string((int)arg); + } + + /* At any rate, we do have a valid (wide) string now. */ + fl = MessageBox(hwndMain, /* our main window */ + str, /* error message etc */ + cap, /* window caption */ + fl); + + /* Convert return values to generic ones. */ + if (fl == IDNO) fl = 1; + else if (fl == IDCANCEL) fl = -1; + else fl = 0; + + return(fl); +} + + +#if 0 +int +msgbox_reset_yn(HWND hwnd) +{ + return(MessageBox(hwnd, plat_get_string(IDS_2051), +#endif + + +int +file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, int save) +{ + OPENFILENAME ofn; + BOOL r; + DWORD err; + + /* Initialize OPENFILENAME */ + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.lpstrFile = wopenfilestring; + + /* + * Set lpstrFile[0] to '\0' so that GetOpenFileName does + * not use the contents of szFile to initialize itself. + */ + memcpy(ofn.lpstrFile, fn, (wcslen(fn) << 1) + 2); + ofn.nMaxFile = 259; + ofn.lpstrFilter = f; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST; + if (! save) + ofn.Flags |= OFN_FILEMUSTEXIST; + + /* Display the Open dialog box. */ + if (save) { +// pclog("GetSaveFileName - lpstrFile = %s\n", ofn.lpstrFile); + r = GetSaveFileName(&ofn); + } else { +// pclog("GetOpenFileName - lpstrFile = %s\n", ofn.lpstrFile); + r = GetOpenFileName(&ofn); + } + + if (r) { + wcstombs(openfilestring, wopenfilestring, sizeof(openfilestring)); +// pclog("File dialog return true\n"); + + return(0); + } + + pclog("File dialog return false\n"); + err = CommDlgExtendedError(); + pclog("CommDlgExtendedError return %04X\n", err); + + return(1); +} + + +int +file_dlg(HWND hwnd, WCHAR *f, char *fn, int save) +{ + WCHAR ufn[512]; + + mbstowcs(ufn, fn, strlen(fn) + 1); + + return(file_dlg_w(hwnd, f, ufn, save)); +} + + +int +file_dlg_mb(HWND hwnd, char *f, char *fn, int save) +{ + WCHAR uf[512], ufn[512]; + + mbstowcs(uf, f, strlen(fn) + 1); + mbstowcs(ufn, fn, strlen(fn) + 1); + + return(file_dlg_w(hwnd, uf, ufn, save)); +} + + +int +file_dlg_w_st(HWND hwnd, int id, WCHAR *fn, int save) +{ + return(file_dlg_w(hwnd, plat_get_string(id), fn, save)); +} + + +int +file_dlg_st(HWND hwnd, int id, char *fn, int save) +{ + return(file_dlg(hwnd, plat_get_string(id), fn, save)); +} diff --git a/src/win/win_dynld.c b/src/win/win_dynld.c index 42b245fc5..1065867e8 100644 --- a/src/win/win_dynld.c +++ b/src/win/win_dynld.c @@ -8,19 +8,20 @@ * * Try to load a support DLL. * - * Version: @(#)win_dynld.c 1.0.2 2017/05/24 + * Version: @(#)win_dynld.c 1.0.5 2017/10/11 * * Author: Fred N. van Kempen, + * * Copyright 2017 Fred N. van Kempen */ -#include -#include #include -#include +#include #include -#include -#include "plat_dynld.h" +#include +#include +#include #include "../ibm.h" +#include "../plat_dynld.h" void * @@ -29,7 +30,6 @@ dynld_module(const char *name, dllimp_t *table) HMODULE h; dllimp_t *imp; void *func; - /* char **foo; */ /* See if we can load the desired module. */ if ((h = LoadLibrary(name)) == NULL) { diff --git a/src/win/win_iodev.c b/src/win/win_iodev.c deleted file mode 100644 index 30ecbe5b2..000000000 --- a/src/win/win_iodev.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Windows IO device menu handler. - * - * Version: @(#)win_iodev.c 1.0.1 2017/09/03 - * - * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. - */ -#define UNICODE -#define _WIN32_WINNT 0x0501 -#define BITMAP WINDOWS_BITMAP -#include -#include -#undef BITMAP - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../ibm.h" -#include "../device.h" -#include "../cdrom/cdrom.h" -#include "../cdrom/cdrom_image.h" -#include "../cdrom/cdrom_ioctl.h" -#include "../cdrom/cdrom_null.h" -#include "../scsi/scsi_disk.h" -#include "plat_iodev.h" -#include "win.h" - - -void cdrom_eject(uint8_t id) -{ - int part; - - part = find_status_bar_part(SB_CDROM | id); - - if ((part == -1) || (sb_menu_handles == NULL)) - { - return; - } - - if (cdrom_drives[id].host_drive == 0) - { - /* Switch from empty to empty. Do nothing. */ - return; - } - if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) - { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); - } - if (cdrom_drives[id].host_drive == 200) - { - wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path); - } - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - cdrom_drives[id].handler->exit(id); - cdrom_close(id); - cdrom_null_open(id, 0); - if (cdrom_drives[id].bus_type) - { - /* Signal disc change to the emulated machine. */ - cdrom_insert(id); - } - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_UNCHECKED); - cdrom_drives[id].host_drive=0; - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_CHECKED); - update_status_bar_icon_state(SB_CDROM | id, 1); - EnableMenuItem(sb_menu_handles[part], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); - update_tip(SB_CDROM | id); - saveconfig(); -} - -void cdrom_reload(uint8_t id) -{ - int part; - int new_cdrom_drive; - - part = find_status_bar_part(SB_CDROM | id); - - if ((part == -1) || (sb_menu_handles == NULL)) - { - return; - } - - if ((cdrom_drives[id].host_drive == cdrom_drives[id].prev_host_drive) || (cdrom_drives[id].prev_host_drive == 0) || (cdrom_drives[id].host_drive != 0)) - { - /* Switch from empty to empty. Do nothing. */ - return; - } - cdrom_close(id); - if (cdrom_drives[id].prev_host_drive == 200) - { - wcscpy(cdrom_image[id].image_path, cdrom_image[id].prev_image_path); - image_open(id, cdrom_image[id].image_path); - if (cdrom_drives[id].bus_type) - { - /* Signal disc change to the emulated machine. */ - cdrom_insert(id); - } - if (wcslen(cdrom_image[id].image_path) == 0) - { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_CHECKED); - cdrom_drives[id].host_drive = 0; - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_UNCHECKED); - update_status_bar_icon_state(SB_CDROM | id, 1); - } - else - { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); - cdrom_drives[id].host_drive = 200; - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_CHECKED); - update_status_bar_icon_state(SB_CDROM | id, 0); - } - } - else - { - new_cdrom_drive = cdrom_drives[id].prev_host_drive; - ioctl_open(id, new_cdrom_drive); - if (cdrom_drives[id].bus_type) - { - /* Signal disc change to the emulated machine. */ - cdrom_insert(id); - } - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); - cdrom_drives[id].host_drive = new_cdrom_drive; - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); - update_status_bar_icon_state(SB_CDROM | id, 0); - } - EnableMenuItem(sb_menu_handles[part], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - update_tip(SB_CDROM | id); - saveconfig(); -} - -void removable_disk_unload(uint8_t id) -{ - if (wcslen(hdc[id].fn) == 0) - { - /* Switch from empty to empty. Do nothing. */ - return; - } - scsi_unloadhd(hdc[id].scsi_id, hdc[id].scsi_lun, id); - scsi_disk_insert(id); -} - -void removable_disk_eject(uint8_t id) -{ - int part = 0; - - part = find_status_bar_part(SB_CDROM | id); - - if ((part == -1) || (sb_menu_handles == NULL)) - { - return; - } - - removable_disk_unload(id); - update_status_bar_icon_state(SB_RDISK | id, 1); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_GRAYED); - update_tip(SB_RDISK | id); - saveconfig(); -} - -void removable_disk_reload(uint8_t id) -{ - int part = 0; - - part = find_status_bar_part(SB_CDROM | id); - - if ((part == -1) || (sb_menu_handles == NULL)) - { - return; - } - - if (wcslen(hdc[id].fn) != 0) - { - /* Attempting to reload while an image is already loaded. Do nothing. */ - return; - } - scsi_reloadhd(id); - /* scsi_disk_insert(id); */ - update_status_bar_icon_state(SB_RDISK | id, wcslen(hdc[id].fn) ? 0 : 1); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | (wcslen(hdc[id].fn) ? MF_ENABLED : MF_GRAYED)); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | (wcslen(hdc[id].fn) ? MF_ENABLED : MF_GRAYED)); - update_tip(SB_RDISK | id); - saveconfig(); -} - diff --git a/src/win/win_joystick.cc b/src/win/win_joystick.cc index 91c2138b0..695638ee8 100644 --- a/src/win/win_joystick.cc +++ b/src/win/win_joystick.cc @@ -8,23 +8,25 @@ * * Joystick interface to host device. * - * Version: @(#)win_joystick.cc 1.0.0 2017/05/30 + * Version: @(#)win_joystick.cc 1.0.4 2017/10/12 * - * Author: Sarah Walker, + * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ - #define DIRECTINPUT_VERSION 0x0800 #include #include +#include #include extern "C" { #include "../device.h" -#include "../gameport.h" +#include "../game/gameport.h" } -#include "plat_joystick.h" +#include "../plat.h" +#include "../plat_joystick.h" #include "win.h" extern "C" int video_fullscreen; @@ -152,7 +154,7 @@ void joystick_init() lpdi_joystick[c]->EnumObjects(DIEnumDeviceObjectsCallback, &plat_joystick_state[c], DIDFT_ALL); - if (FAILED(lpdi_joystick[c]->SetCooperativeLevel(ghwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) + if (FAILED(lpdi_joystick[c]->SetCooperativeLevel(hwndMain, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) fatal("joystick_init : SetCooperativeLevel failed\n"); if (FAILED(lpdi_joystick[c]->SetDataFormat(&c_dfDIJoystick))) fatal("joystick_init : SetDataFormat failed\n"); diff --git a/src/win/win_joystickconfig.c b/src/win/win_joystickconfig.c index 3cd5a0c68..28c300629 100644 --- a/src/win/win_joystickconfig.c +++ b/src/win/win_joystickconfig.c @@ -5,12 +5,16 @@ #include #include #undef BITMAP - +#include +#include +#include +#include #include "../ibm.h" #include "../config.h" #include "../device.h" -#include "../gameport.h" -#include "plat_joystick.h" +#include "../game/gameport.h" +#include "../plat.h" +#include "../plat_joystick.h" #include "win.h" diff --git a/src/win/win_keyboard.c b/src/win/win_keyboard.c index e7b847f7d..75bc80e6a 100644 --- a/src/win/win_keyboard.c +++ b/src/win/win_keyboard.c @@ -8,33 +8,30 @@ * * Windows raw keyboard input handler. * - * Version: @(#)win_d3d.cc 1.0.0 2017/05/30 + * Version: @(#)win_keyboard.c 1.0.2 2017/10/10 * * Author: Miran Grca, + * * Copyright 2016-2017 Miran Grca. */ - #define UNICODE #define _WIN32_WINNT 0x0501 #define BITMAP WINDOWS_BITMAP #include #include #undef BITMAP - -#include -#include -#include -#include -#include -#include -#include +//#include +//#include #include - +#include +#include +#include #include "../device.h" -#include "plat_keyboard.h" - +#include "../plat.h" +#include "../plat_keyboard.h" #include "win.h" + #ifndef MAPVK_VK_TO_VSC #define MAPVK_VK_TO_VSC 0 #endif @@ -208,4 +205,4 @@ void process_raw_input(LPARAM lParam, int infocus) } free(raw); -} \ No newline at end of file +} diff --git a/src/win/win_language.c b/src/win/win_language.c deleted file mode 100644 index 4c0d761b3..000000000 --- a/src/win/win_language.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Windows localization core. - * - * Version: @(#)win_language.c 1.0.1 2017/08/24 - * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#include -#define UNICODE -#define BITMAP WINDOWS_BITMAP -#include -#include -#include -#undef BITMAP - -#include - -#include "../ibm.h" -#include "../device.h" -#include "plat_ui.h" -#include "win.h" -#include "win_language.h" - - -LCID dwLanguage; - -uint32_t dwLangID, dwSubLangID; - -typedef struct -{ - WCHAR lpString[512]; -} resource_string_t; - -resource_string_t *lpResourceString2048; -resource_string_t *lpResourceString3072; -resource_string_t *lpResourceString4096; -resource_string_t *lpResourceString4352; -resource_string_t *lpResourceString4608; -resource_string_t *lpResourceString5120; -resource_string_t *lpResourceString5376; -resource_string_t *lpResourceString5632; -resource_string_t *lpResourceString6144; - -char openfilestring[260]; -WCHAR wopenfilestring[260]; - -void win_language_set() -{ - SetThreadLocale(dwLanguage); -} - -void win_language_load_common_strings() -{ - int i = 0; - - lpResourceString2048 = (resource_string_t *) malloc(STRINGS_NUM_2048 * sizeof(resource_string_t)); - lpResourceString3072 = (resource_string_t *) malloc(STRINGS_NUM_3072 * sizeof(resource_string_t)); - lpResourceString4096 = (resource_string_t *) malloc(STRINGS_NUM_4096 * sizeof(resource_string_t)); - lpResourceString4352 = (resource_string_t *) malloc(STRINGS_NUM_4352 * sizeof(resource_string_t)); - lpResourceString4608 = (resource_string_t *) malloc(STRINGS_NUM_4608 * sizeof(resource_string_t)); - lpResourceString5120 = (resource_string_t *) malloc(STRINGS_NUM_5120 * sizeof(resource_string_t)); - lpResourceString5376 = (resource_string_t *) malloc(STRINGS_NUM_5376 * sizeof(resource_string_t)); - lpResourceString5632 = (resource_string_t *) malloc(STRINGS_NUM_5632 * sizeof(resource_string_t)); - lpResourceString6144 = (resource_string_t *) malloc(STRINGS_NUM_6144 * sizeof(resource_string_t)); - - for (i = 0; i < STRINGS_NUM_2048; i++) - { - LoadString(hinstance, 2048 + i, lpResourceString2048[i].lpString, 512); - } - - for (i = 0; i < STRINGS_NUM_3072; i++) - { - LoadString(hinstance, 3072 + i, lpResourceString3072[i].lpString, 512); - } - - for (i = 0; i < STRINGS_NUM_4096; i++) - { - LoadString(hinstance, 4096 + i, lpResourceString4096[i].lpString, 512); - } - - for (i = 0; i < STRINGS_NUM_4352; i++) - { - LoadString(hinstance, 4352 + i, lpResourceString4352[i].lpString, 512); - } - - for (i = 0; i < STRINGS_NUM_4608; i++) - { - LoadString(hinstance, 4608 + i, lpResourceString4608[i].lpString, 512); - } - - for (i = 0; i < STRINGS_NUM_5120; i++) - { - LoadString(hinstance, 5120 + i, lpResourceString5120[i].lpString, 512); - } - - for (i = 0; i < STRINGS_NUM_5376; i++) - { - LoadString(hinstance, 5376 + i, lpResourceString5376[i].lpString, 512); - } - - for (i = 0; i < STRINGS_NUM_5632; i++) - { - LoadString(hinstance, 5632 + i, lpResourceString5632[i].lpString, 512); - } - - for (i = 0; i < STRINGS_NUM_6144; i++) - { - LoadString(hinstance, 6144 + i, lpResourceString6144[i].lpString, 512); - } -} - -LPTSTR win_language_get_settings_category(int i) -{ - return lpResourceString2048[17 + i].lpString; -} - -void win_language_update() -{ - win_language_set(); - win_menu_update(); - win_language_load_common_strings(); -} - -void win_language_check() -{ - LCID dwLanguageNew = MAKELCID(dwLangID, dwSubLangID); - if (dwLanguageNew != dwLanguage) - { - dwLanguage = dwLanguageNew; - win_language_update(); - } -} - -LPTSTR win_language_get_string_from_id(int i) -{ - if ((i >= 2048) && (i <= 3071)) - { - return lpResourceString2048[i - 2048].lpString; - } - else if ((i >= 3072) && (i <= 4095)) - { - return lpResourceString3072[i - 3072].lpString; - } - else if ((i >= 4096) && (i <= 4351)) - { - return lpResourceString4096[i - 4096].lpString; - } - else if ((i >= 4352) && (i <= 4607)) - { - return lpResourceString4352[i - 4352].lpString; - } - else if ((i >= 4608) && (i <= 5119)) - { - return lpResourceString4608[i - 4608].lpString; - } - else if ((i >= 5120) && (i <= 5375)) - { - return lpResourceString5120[i - 5120].lpString; - } - else if ((i >= 5376) && (i <= 5631)) - { - return lpResourceString5376[i - 5376].lpString; - } - else if ((i >= 5632) && (i <= 6143)) - { - return lpResourceString5632[i - 5632].lpString; - } - else - { - return lpResourceString6144[i - 6144].lpString; - } -} - -wchar_t *plat_get_string_from_id(int i) -{ - return (wchar_t *) win_language_get_string_from_id(i); -} - -LPTSTR win_language_get_string_from_string(char *str) -{ - return win_language_get_string_from_id(atoi(str)); -} - -int msgbox_reset(HWND hwndParent) -{ - return MessageBox(hwndParent, lpResourceString2048[3].lpString, lpResourceString2048[0].lpString, MB_YESNOCANCEL | MB_ICONQUESTION); -} - -int msgbox_reset_yn(HWND hwndParent) -{ - return MessageBox(hwndParent, lpResourceString2048[3].lpString, lpResourceString2048[0].lpString, MB_YESNO | MB_ICONQUESTION); -} - -int msgbox_question(HWND hwndParent, int i) -{ - return MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString2048[0].lpString, MB_YESNO | MB_ICONQUESTION); -} - -void msgbox_info(HWND hwndParent, int i) -{ - MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString2048[0].lpString, MB_OK | MB_ICONINFORMATION); -} - -void msgbox_info_wstr(HWND hwndParent, WCHAR *wstr) -{ - MessageBox(hwndParent, wstr, lpResourceString2048[0].lpString, MB_OK | MB_ICONINFORMATION); -} - -void msgbox_error(HWND hwndParent, int i) -{ - MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString2048[1].lpString, MB_OK | MB_ICONWARNING); -} - -void plat_msgbox_error(int i) -{ - msgbox_error(ghwnd, i); -} - -void msgbox_error_wstr(HWND hwndParent, WCHAR *wstr) -{ - MessageBox(hwndParent, wstr, lpResourceString2048[1].lpString, MB_OK | MB_ICONWARNING); -} - -void msgbox_critical(HWND hwndParent, int i) -{ - MessageBox(hwndParent, win_language_get_string_from_id(i), lpResourceString2048[2].lpString, MB_OK | MB_ICONERROR); -} - -void msgbox_fatal(HWND hwndParent, char *string) -{ - LPTSTR lptsTemp; - lptsTemp = (LPTSTR) malloc(512); - - mbstowcs(lptsTemp, string, strlen(string) + 1); - - MessageBox(hwndParent, lptsTemp, lpResourceString2048[2].lpString, MB_OK | MB_ICONERROR); - - free(lptsTemp); -} - -void plat_msgbox_fatal(char *string) -{ - msgbox_fatal(ghwnd, string); -} - -int file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, int save) -{ - OPENFILENAME ofn; /* common dialog box structure */ - BOOL r; - DWORD err; - - /* Initialize OPENFILENAME */ - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwnd; - ofn.lpstrFile = wopenfilestring; - /* - Set lpstrFile[0] to '\0' so that GetOpenFileName does not - use the contents of szFile to initialize itself. - */ - memcpy(ofn.lpstrFile, fn, (wcslen(fn) << 1) + 2); - ofn.nMaxFile = 259; - ofn.lpstrFilter = f; - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; - ofn.Flags = OFN_PATHMUSTEXIST; - if (!save) - { - ofn.Flags |= OFN_FILEMUSTEXIST; - } - - /* Display the Open dialog box. */ - - if (save) - { - pclog("GetSaveFileName - lpstrFile = %s\n", ofn.lpstrFile); - r = GetSaveFileName(&ofn); - } - else - { - pclog("GetOpenFileName - lpstrFile = %s\n", ofn.lpstrFile); - r = GetOpenFileName(&ofn); - } - if (r) - { - wcstombs(openfilestring, wopenfilestring, sizeof(openfilestring)); - pclog("File dialog return true\n"); - return 0; - } - pclog("File dialog return false\n"); - err = CommDlgExtendedError(); - pclog("CommDlgExtendedError return %04X\n", err); - return 1; -} - -int file_dlg(HWND hwnd, WCHAR *f, char *fn, int save) -{ - WCHAR ufn[512]; - mbstowcs(ufn, fn, strlen(fn) + 1); - return file_dlg_w(hwnd, f, ufn, save); -} - -int file_dlg_mb(HWND hwnd, char *f, char *fn, int save) -{ - WCHAR uf[512]; - WCHAR ufn[512]; - mbstowcs(uf, f, strlen(fn) + 1); - mbstowcs(ufn, fn, strlen(fn) + 1); - return file_dlg_w(hwnd, uf, ufn, save); -} - -int file_dlg_w_st(HWND hwnd, int i, WCHAR *fn, int save) -{ - return file_dlg_w(hwnd, win_language_get_string_from_id(i), fn, save); -} - -int file_dlg_st(HWND hwnd, int i, char *fn, int save) -{ - return file_dlg(hwnd, win_language_get_string_from_id(i), fn, save); -} - -static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg, LPARAM lParam, LPARAM lpData) -{ - if(uMsg == BFFM_INITIALIZED) - { - SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData); - } - - return 0; -} - -WCHAR path[MAX_PATH]; - -wchar_t *BrowseFolder(wchar_t *saved_path, wchar_t *title) -{ - BROWSEINFO bi = { 0 }; - bi.lpszTitle = title; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; - bi.lpfn = BrowseCallbackProc; - bi.lParam = (LPARAM) saved_path; - - LPITEMIDLIST pidl = SHBrowseForFolder(&bi); - - if (pidl != 0) - { - /* Get the name of the folder and put it in path. */ - SHGetPathFromIDList(pidl, path); - - /* Free memory used. */ - IMalloc *imalloc = 0; - if (SUCCEEDED(SHGetMalloc(&imalloc))) - { - imalloc->lpVtbl->Free(imalloc, pidl); - imalloc->lpVtbl->Release(imalloc); - } - - return path; - } - - return L""; -} diff --git a/src/win/win_language.h b/src/win/win_language.h deleted file mode 100644 index 053eabf0d..000000000 --- a/src/win/win_language.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Windows localization core. - * - * Version: @(#)win_language.h 1.0.0 2017/05/30 - * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -LCID dwLanguage; - -int msgbox_reset(HWND hwndParent); -int msgbox_reset_yn(HWND hwndParent); -int msgbox_question(HWND hwndParent, int i); -void msgbox_info(HWND hwndParent, int i); -void msgbox_info_wstr(HWND hwndParent, WCHAR *wstr); -void msgbox_error(HWND hwndParent, int i); -void msgbox_error_wstr(HWND hwndParent, WCHAR *wstr); -void msgbox_fatal(HWND hwndParent, char *string); -void msgbox_critical(HWND hwndParent, int i); - -int file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, int save); -int file_dlg(HWND hwnd, WCHAR *f, char *fn, int save); -int file_dlg_mb(HWND hwnd, char *f, char *fn, int save); -int file_dlg_w_st(HWND hwnd, int i, WCHAR *fn, int save); -int file_dlg_st(HWND hwnd, int i, char *fn, int save); - -void win_language_load_common_strings(); -LPTSTR win_language_get_settings_category(int i); - -void win_language_update(); -void win_language_check(); - -LPTSTR win_language_get_string_from_id(int i); -LPTSTR win_language_get_string_from_string(char *str); - -wchar_t *BrowseFolder(wchar_t *saved_path, wchar_t *title); - -#ifdef __cplusplus -} -#endif diff --git a/src/win/win_midi.c b/src/win/win_midi.c index 2c3e3eded..0d49bf81e 100644 --- a/src/win/win_midi.c +++ b/src/win/win_midi.c @@ -1,15 +1,20 @@ #include #include +#include +#include +#include +#include #include "../ibm.h" #include "../config.h" #include "../sound/midi.h" -#include "plat_midi.h" +#include "../plat.h" +#include "../plat_midi.h" + int midi_id = 0; -static HMIDIOUT midi_out_device = NULL; - HANDLE m_event; +static HMIDIOUT midi_out_device = NULL; static uint8_t midi_rt_buf[1024]; static uint8_t midi_cmd_buf[1024]; static int midi_cmd_pos = 0; diff --git a/src/win/win_mouse.cc b/src/win/win_mouse.cc index 0cb82df2f..fc5bc8b7e 100644 --- a/src/win/win_mouse.cc +++ b/src/win/win_mouse.cc @@ -8,17 +8,20 @@ * * Mouse interface to host device. * - * Version: @(#)win_mouse.cc 1.0.1 2017/06/21 + * Version: @(#)win_mouse.cc 1.0.4 2017/10/12 * * Authors: Sarah Walker, * Miran Grca, + * * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2016,2017 Miran Grca. */ #define DIRECTINPUT_VERSION 0x0800 #include +#include #include -#include "plat_mouse.h" +#include "../plat.h" +#include "../plat_mouse.h" #include "win.h" @@ -48,7 +51,7 @@ void mouse_init(void) fatal("mouse_init : DirectInputCreate failed\n"); if (FAILED(lpdi->CreateDevice(GUID_SysMouse, &lpdi_mouse, NULL))) fatal("mouse_init : CreateDevice failed\n"); - if (FAILED(lpdi_mouse->SetCooperativeLevel(ghwnd, DISCL_FOREGROUND | (video_fullscreen ? DISCL_EXCLUSIVE : DISCL_NONEXCLUSIVE)))) + if (FAILED(lpdi_mouse->SetCooperativeLevel(hwndMain, DISCL_FOREGROUND | (video_fullscreen ? DISCL_EXCLUSIVE : DISCL_NONEXCLUSIVE)))) fatal("mouse_init : SetCooperativeLevel failed\n"); if (FAILED(lpdi_mouse->SetDataFormat(&c_dfDIMouse))) fatal("mouse_init : SetDataFormat failed\n"); diff --git a/src/win/win_opendir.c b/src/win/win_opendir.c index 00347a365..ba8430a86 100644 --- a/src/win/win_opendir.c +++ b/src/win/win_opendir.c @@ -10,21 +10,24 @@ * * Based on old original code @(#)dir_win32.c 1.2.0 2007/04/19 * - * Version: @(#)win_opendir.c 1.0.1 2017/05/17 + * Version: @(#)win_opendir.c 1.0.3 2017/10/10 * * Author: Fred N. van Kempen, + * * Copyright 1998-2007 MicroWalt Corporation * Copyright 2017 Fred N. van Kempen */ #define UNICODE #include #include -#include #include -#include +#include #include +#include +#include #include "../ibm.h" -#include "plat_dir.h" +#include "../plat.h" +#include "../plat_dir.h" #ifdef UNICODE diff --git a/src/win/win_serial.c b/src/win/win_serial.c index a5ab56f66..df5823171 100644 --- a/src/win/win_serial.c +++ b/src/win/win_serial.c @@ -12,21 +12,20 @@ * Windows and UNIX systems, with support for FTDI and Prolific * USB ports. Support for these has been removed. * - * Version: @(#)win_serial.c 1.0.4 2017/09/12 + * Version: @(#)win_serial.c 1.0.6 2017/10/10 * * Author: Fred N. van Kempen, + * * Copyright 2017 Fred N. van Kempen. */ #include #include #include #include -#include "plat_thread.h" -#define BHTTY_C -#include "plat_serial.h" - - -extern void pclog(char *__fmt, ...); +#define PLAT_SERIAL_C +#include "../ibm.h" +#include "../plat.h" +#include "../plat_serial.h" /* Handle the receiving of data from the host port. */ @@ -324,10 +323,10 @@ int bhtty_flush(BHTTY *pp) { DWORD dwErrs; - COMSTAT cs; + COMSTAT cst; /* First, clear any errors. */ - (void)ClearCommError(pp->handle, &dwErrs, &cs); + (void)ClearCommError(pp->handle, &dwErrs, &cst); /* Now flush all buffers. */ if (PurgeComm(pp->handle, @@ -338,7 +337,7 @@ bhtty_flush(BHTTY *pp) } /* Re-clear any errors. */ - if (ClearCommError(pp->handle, &dwErrs, &cs) == FALSE) { + if (ClearCommError(pp->handle, &dwErrs, &cst) == FALSE) { pclog("%s: clear errors: %d\n", pp->name, GetLastError()); return(-1); } diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 32ca41369..15b774d5e 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,9 +8,10 @@ * * Windows 86Box Settings dialog handler. * - * Version: @(#)win_settings.c 1.0.10 2017/09/03 + * Version: @(#)win_settings.c 1.0.21 2017/10/13 * * Author: Miran Grca, + * * Copyright 2016,2017 Miran Grca. */ #define UNICODE @@ -18,41 +19,48 @@ #include #include #undef BITMAP - #include #include +#include +#include +#include +#include #include "../ibm.h" +#include "../config.h" #include "../cpu/cpu.h" #include "../mem.h" +#include "../rom.h" #include "../device.h" #include "../nvr.h" #include "../machine/machine.h" -#include "../gameport.h" +#include "../game/gameport.h" #include "../lpt.h" #include "../mouse.h" #include "../cdrom/cdrom.h" +#include "../disk/hdd.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" #include "../floppy/floppy.h" #include "../floppy/fdd.h" -#include "../hdd/hdd.h" -#include "../hdd/hdd_ide_at.h" #include "../scsi/scsi.h" -#ifdef USE_NETWORK #include "../network/network.h" -#endif #include "../sound/sound.h" #include "../sound/midi.h" #include "../sound/snd_dbopl.h" #include "../sound/snd_mpu401.h" #include "../video/video.h" #include "../video/vid_voodoo.h" -#include "plat_midi.h" +#include "../plat.h" +#include "../plat_midi.h" +#include "../ui.h" #include "win.h" -#include "win_language.h" /* Machine category */ -static int temp_machine, temp_cpu_m, temp_cpu, temp_wait_states, temp_mem_size, temp_dynarec, temp_fpu, temp_sync; -static wchar_t temp_nvr_path[520]; +static int temp_machine, temp_cpu_m, temp_cpu, temp_wait_states, temp_mem_size, temp_fpu, temp_sync; +#ifdef USE_DYNAREC +static int temp_dynarec; +#endif /* Video category */ static int temp_gfxcard, temp_video_speed, temp_voodoo; @@ -64,24 +72,22 @@ static int temp_mouse, temp_joystick; static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS, temp_opl3_type; static int temp_float; -#ifdef USE_NETWORK /* Network category */ static int temp_net_type, temp_net_card; static char temp_pcap_dev[520]; -#endif /* Ports category */ static char temp_lpt1_device_name[16]; static int temp_serial[2], temp_lpt; /* Peripherals category */ -static int temp_scsi_card, hdc_ignore, temp_ide_ter, temp_ide_ter_irq, temp_ide_qua, temp_ide_qua_irq; +static int temp_scsi_card, temp_ide_ter, temp_ide_ter_irq, temp_ide_qua, temp_ide_qua_irq; +static char temp_hdc_name[16]; +static char *hdc_names[16]; static int temp_bugger; -static char temp_hdc_name[16]; - /* Hard disks category */ -static hard_disk_t temp_hdc[HDC_NUM]; +static hard_disk_t temp_hdd[HDD_NUM]; /* Removable devices category */ static int temp_fdd_types[FDD_NUM]; @@ -91,8 +97,6 @@ static cdrom_drive_t temp_cdrom_drives[CDROM_NUM]; static HWND hwndParentDialog, hwndChildDialog; -int hdd_controller_current; - static int displayed_category = 0; extern int is486; @@ -101,10 +105,26 @@ static int settings_sound_to_list[20], settings_list_to_sound[20]; static int settings_midi_to_list[20], settings_list_to_midi[20]; static int settings_mouse_to_list[20], settings_list_to_mouse[20]; static int settings_scsi_to_list[20], settings_list_to_scsi[20]; -#ifdef USE_NETWORK static int settings_network_to_list[20], settings_list_to_network[20]; -#endif -static char *hdd_names[16]; + + + +/* Show a MessageBox dialog. This is nasty, I know. --FvK */ +static int +settings_msgbox(int type, void *arg) +{ + HWND h; + int i; + + h = hwndMain; + hwndMain = hwndParentDialog; + + i = ui_msgbox(type, arg); + + hwndMain = h; + + return(i); +} /* This does the initial read of global variables into the temporary ones. */ @@ -118,9 +138,9 @@ static void win_settings_init(void) temp_wait_states = cpu_waitstates; temp_cpu = cpu; temp_mem_size = mem_size; - memset(temp_nvr_path, 0, sizeof(temp_nvr_path)); - wcscpy(temp_nvr_path, nvr_path); +#ifdef USE_DYNAREC temp_dynarec = cpu_use_dynarec; +#endif temp_fpu = enable_external_fpu; temp_sync = enable_sync; @@ -143,13 +163,11 @@ static void win_settings_init(void) temp_opl3_type = opl3_type; temp_float = sound_is_float; -#ifdef USE_NETWORK /* Network category */ temp_net_type = network_type; memset(temp_pcap_dev, 0, sizeof(temp_pcap_dev)); strcpy(temp_pcap_dev, network_pcap); temp_net_card = network_card; -#endif /* Ports category */ strncpy(temp_lpt1_device_name, lpt1_device_name, sizeof(temp_lpt1_device_name) - 1); @@ -159,7 +177,7 @@ static void win_settings_init(void) /* Peripherals category */ temp_scsi_card = scsi_card_current; - strncpy(temp_hdc_name, hdd_controller_name, sizeof(temp_hdc_name) - 1); + strncpy(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1); temp_ide_ter = ide_enable[2]; temp_ide_ter_irq = ide_irq[2]; temp_ide_qua = ide_enable[3]; @@ -167,7 +185,7 @@ static void win_settings_init(void) temp_bugger = bugger_enabled; /* Hard disks category */ - memcpy(temp_hdc, hdc, HDC_NUM * sizeof(hard_disk_t)); + memcpy(temp_hdd, hdd, HDD_NUM * sizeof(hard_disk_t)); /* Removable devices category */ for (i = 0; i < FDD_NUM; i++) @@ -192,8 +210,9 @@ static int win_settings_changed(void) i = i || (cpu_waitstates != temp_wait_states); i = i || (cpu != temp_cpu); i = i || (mem_size != temp_mem_size); - i = i || wcscmp(temp_nvr_path, nvr_path); +#ifdef USE_DYNAREC i = i || (temp_dynarec != cpu_use_dynarec); +#endif i = i || (temp_fpu != enable_external_fpu); i = i || (temp_sync != enable_sync); @@ -216,12 +235,10 @@ static int win_settings_changed(void) i = i || (opl3_type != temp_opl3_type); i = i || (sound_is_float != temp_float); -#ifdef USE_NETWORK /* Network category */ i = i || (network_type != temp_net_type); i = i || strcmp(temp_pcap_dev, network_pcap); i = i || (network_card != temp_net_card); -#endif /* Ports category */ i = i || strncmp(temp_lpt1_device_name, lpt1_device_name, sizeof(temp_lpt1_device_name) - 1); @@ -231,7 +248,7 @@ static int win_settings_changed(void) /* Peripherals category */ i = i || (scsi_card_current != temp_scsi_card); - i = i || strncmp(temp_hdc_name, hdd_controller_name, sizeof(temp_hdc_name) - 1); + i = i || strncmp(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1); i = i || (temp_ide_ter != ide_enable[2]); i = i || (temp_ide_ter_irq != ide_irq[2]); i = i || (temp_ide_qua != ide_enable[3]); @@ -239,7 +256,7 @@ static int win_settings_changed(void) i = i || (temp_bugger != bugger_enabled); /* Hard disks category */ - i = i || memcmp(hdc, temp_hdc, HDC_NUM * sizeof(hard_disk_t)); + i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); /* Removable devices category */ for (j = 0; j < FDD_NUM; j++) @@ -263,24 +280,15 @@ static int settings_msgbox_reset(void) if (changed) { - i = msgbox_reset(hwndParentDialog); + i = settings_msgbox(MBX_QUESTION, (wchar_t *)IDS_2051); - if (i == IDNO) - { - return 1; - } - else if (i == IDCANCEL) - { - return 0; - } - else - { - return 2; - } - } - else -{ - return 1; + if (i == 1) return(1); /* no */ + + if (i < 0) return(0); /* cancel */ + + return(2); /* yes */ + } else { + return(1); } } @@ -290,7 +298,7 @@ static void win_settings_save(void) { int i = 0; - resetpchard_close(); + pc_reset_hard_close(); /* Machine category */ machine = temp_machine; @@ -299,9 +307,9 @@ static void win_settings_save(void) cpu_waitstates = temp_wait_states; cpu = temp_cpu; mem_size = temp_mem_size; - memset(nvr_path, 0, sizeof(nvr_path)); - wcscpy(nvr_path, temp_nvr_path); +#ifdef USE_DYNAREC cpu_use_dynarec = temp_dynarec; +#endif enable_external_fpu = temp_fpu; enable_sync = temp_sync; @@ -324,13 +332,11 @@ static void win_settings_save(void) opl3_type = temp_opl3_type; sound_is_float = temp_float; -#ifdef USE_NETWORK /* Network category */ network_type = temp_net_type; memset(network_pcap, '\0', sizeof(network_pcap)); strcpy(network_pcap, temp_pcap_dev); network_card = temp_net_card; -#endif /* Ports category */ strncpy(lpt1_device_name, temp_lpt1_device_name, sizeof(temp_lpt1_device_name) - 1); @@ -340,7 +346,8 @@ static void win_settings_save(void) /* Peripherals category */ scsi_card_current = temp_scsi_card; - strncpy(hdd_controller_name, temp_hdc_name, sizeof(temp_hdc_name) - 1); + strncpy(hdc_name, temp_hdc_name, sizeof(temp_hdc_name) - 1); + hdc_init(hdc_name); ide_enable[2] = temp_ide_ter; ide_irq[2] = temp_ide_ter_irq; ide_enable[3] = temp_ide_qua; @@ -348,7 +355,7 @@ static void win_settings_save(void) bugger_enabled = temp_bugger; /* Hard disks category */ - memcpy(hdc, temp_hdc, HDC_NUM * sizeof(hard_disk_t)); + memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); /* Removable devices category */ for (i = 0; i < FDD_NUM; i++) @@ -360,21 +367,21 @@ static void win_settings_save(void) memcpy(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); mem_resize(); - loadbios(); + rom_load_bios(romset); - update_status_bar_panes(hwndStatus); + ui_sb_update_panes(); sound_realloc_buffers(); - resetpchard_init(); + pc_reset_hard_init(); cpu_set(); cpu_update_waitstates(); - saveconfig(); + config_save(); - speedchanged(); + pc_speed_changed(); if (joystick_type != 7) gameport_update_joystick_type(); } @@ -384,7 +391,9 @@ static void win_settings_machine_recalc_cpu(HWND hdlg) { HWND h; int temp_romset = 0; +#ifdef USE_DYNAREC int cpu_flags; +#endif int cpu_type; temp_romset = machine_getromset_ex(temp_machine); @@ -400,6 +409,7 @@ static void win_settings_machine_recalc_cpu(HWND hdlg) EnableWindow(h, FALSE); } +#ifdef USE_DYNAREC h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); cpu_flags = machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_flags; if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) && (cpu_flags & CPU_REQUIRES_DYNAREC)) @@ -423,6 +433,7 @@ static void win_settings_machine_recalc_cpu(HWND hdlg) { EnableWindow(h, TRUE); } +#endif h = GetDlgItem(hdlg, IDC_CHECK_FPU); cpu_type = machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; @@ -536,13 +547,13 @@ static void win_settings_machine_recalc_machine(HWND hdlg) { SendMessage(h, UDM_SETPOS, 0, temp_mem_size); h = GetDlgItem(hdlg, IDC_TEXT_MB); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) win_language_get_string_from_id(IDS_2094)); + SendMessage(h, WM_SETTEXT, 0, (LPARAM) plat_get_string(IDS_2094)); } else { SendMessage(h, UDM_SETPOS, 0, temp_mem_size / 1024); h = GetDlgItem(hdlg, IDC_TEXT_MB); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) win_language_get_string_from_id(IDS_2087)); + SendMessage(h, WM_SETTEXT, 0, (LPARAM) plat_get_string(IDS_2087)); } free(lptsTemp); @@ -556,7 +567,6 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w int d = 0; LPTSTR lptsTemp; char *stransi; - wchar_t *p; switch (message) { @@ -587,18 +597,20 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w SendMessage(h, CB_SETCURSEL, machinetolist[temp_machine], 0); h = GetDlgItem(hdlg, IDC_COMBO_WS); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2131)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_2131)); for (c = 0; c < 8; c++) { - wsprintf(lptsTemp, win_language_get_string_from_id(2132), c); + wsprintf(lptsTemp, plat_get_string(2132), c); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } SendMessage(h, CB_SETCURSEL, temp_wait_states, 0); +#ifdef USE_DYNAREC h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); SendMessage(h, BM_SETCHECK, temp_dynarec, 0); +#endif h = GetDlgItem(hdlg, IDC_MEMSPIN); SendMessage(h, UDM_SETBUDDY, (WPARAM)GetDlgItem(hdlg, IDC_MEMTEXT), 0); @@ -608,9 +620,6 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w win_settings_machine_recalc_machine(hdlg); - h = GetDlgItem(hdlg, IDC_EDIT_NVR_PATH); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) temp_nvr_path); - free(lptsTemp); return TRUE; @@ -652,24 +661,6 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w deviceconfig_open(hdlg, (void *)machine_getdevice(temp_machine)); break; - case IDC_BUTTON_NVR_PATH: - p = BrowseFolder(temp_nvr_path, win_language_get_string_from_id(IDS_2056)); - if (wcscmp(p, L"")) - { - memset(temp_nvr_path, 0, sizeof(temp_nvr_path)); - wcscpy(temp_nvr_path, p); - if (temp_nvr_path[wcslen(temp_nvr_path) - 1] == L'/') - { - temp_nvr_path[wcslen(temp_nvr_path) - 1] = L'\\'; - } - else if (temp_nvr_path[wcslen(temp_nvr_path) - 1] != L'\\') - { - temp_nvr_path[wcslen(temp_nvr_path)] = L'\\'; - } - h = GetDlgItem(hdlg, IDC_EDIT_NVR_PATH); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) temp_nvr_path); - } - break; } return FALSE; @@ -678,8 +669,10 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w lptsTemp = (LPTSTR) malloc(512); stransi = (char *) malloc(512); +#ifdef USE_DYNAREC h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); temp_dynarec = SendMessage(h, BM_GETCHECK, 0, 0); +#endif h=GetDlgItem(hdlg, IDC_CHECK_SYNC); temp_sync = SendMessage(h, BM_GETCHECK, 0, 0); @@ -737,7 +730,7 @@ static void recalc_vid_list(HWND hdlg) break; if (video_card_available(c) && gfx_present[video_new_to_old(c)] && - ((machines[temp_machine].flags & MACHINE_PCI) || !(video_card_getdevice(c)->flags & DEVICE_PCI))) + device_is_valid(video_card_getdevice(c), machines[temp_machine].flags)) { mbstowcs(szText, s, strlen(s) + 1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); @@ -781,12 +774,12 @@ static BOOL CALLBACK win_settings_video_proc(HWND hdlg, UINT message, WPARAM wPa recalc_vid_list(hdlg); h = GetDlgItem(hdlg, IDC_COMBO_VIDEO_SPEED); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2133)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2134)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2135)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2136)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2137)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2138)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2133)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2134)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2135)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2136)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2137)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2138)); SendMessage(h, CB_SETCURSEL, temp_video_speed, 0); h=GetDlgItem(hdlg, IDC_CHECK_VOODOO); @@ -931,7 +924,7 @@ static BOOL CALLBACK win_settings_input_proc(HWND hdlg, UINT message, WPARAM wPa { str_id = IDS_3072 + c; - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(str_id)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(str_id)); settings_list_to_mouse[d] = c; d++; @@ -944,7 +937,7 @@ static BOOL CALLBACK win_settings_input_proc(HWND hdlg, UINT message, WPARAM wPa c = 0; while (joystick_get_name(c)) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2144 + c)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(2144 + c)); c++; } EnableWindow(h, TRUE); @@ -1068,7 +1061,7 @@ static BOOL CALLBACK win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wPa int c = 0; int d = 0; LPTSTR lptsTemp; - device_t *sound_dev, *midi_dev; + device_t *sound_dev/*, *midi_dev*/; char *s; switch (message) @@ -1093,11 +1086,11 @@ static BOOL CALLBACK win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wPa { sound_dev = sound_card_getdevice(c); - if (!sound_dev || (sound_dev->flags & DEVICE_MCA) == (machines[temp_machine].flags & MACHINE_MCA)) + if (device_is_valid(sound_dev, machines[temp_machine].flags)) { if (c == 0) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2152)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_2152)); } else { @@ -1113,6 +1106,8 @@ static BOOL CALLBACK win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wPa } SendMessage(h, CB_SETCURSEL, settings_sound_to_list[temp_sound_card], 0); + EnableWindow(h, d ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_CONFIGURE_SND); if (sound_card_has_config(temp_sound_card)) { @@ -1138,22 +1133,19 @@ static BOOL CALLBACK win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wPa if (midi_device_available(c)) { - midi_dev = midi_device_getdevice(c); + /* midi_dev = midi_device_getdevice(c); */ - if (!midi_dev || (midi_dev->flags & DEVICE_MCA) == (machines[temp_machine].flags & MACHINE_MCA)) + if (c == 0) { - if (c == 0) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2152)); - } - else - { - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - settings_list_to_midi[d] = c; - d++; + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2152)); } + else + { + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + settings_list_to_midi[d] = c; + d++; } c++; @@ -1329,7 +1321,7 @@ static BOOL CALLBACK win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wPa if (c == 0) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2152)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_2152)); } else { @@ -1380,7 +1372,7 @@ static BOOL CALLBACK win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wPa } -static void recalc_hdd_list(HWND hdlg, int machine, int use_selected_hdd) +static void recalc_hdc_list(HWND hdlg, int machine, int use_selected_hdc) { HWND h; @@ -1395,94 +1387,65 @@ static void recalc_hdd_list(HWND hdlg, int machine, int use_selected_hdd) h = GetDlgItem(hdlg, IDC_COMBO_HDC); - if (machines[temp_machine].flags & MACHINE_HAS_IDE) + valid = 0; + + if (use_selected_hdc) { - hdc_ignore = 1; + c = SendMessage(h, CB_GETCURSEL, 0, 0); - SendMessage(h, CB_RESETCONTENT, 0, 0); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2154)); - EnableWindow(h, FALSE); - SendMessage(h, CB_SETCURSEL, 0, 0); - } - else - { - hdc_ignore = 0; - - valid = 0; - - if (use_selected_hdd) + if (c != -1 && hdc_names[c]) { - c = SendMessage(h, CB_GETCURSEL, 0, 0); - - if (c != -1 && hdd_names[c]) - { - strncpy(old_name, hdd_names[c], sizeof(old_name) - 1); - } - else - { - strcpy(old_name, "none"); - } + strncpy(old_name, hdc_names[c], sizeof(old_name) - 1); } else { - strncpy(old_name, temp_hdc_name, sizeof(old_name) - 1); + strcpy(old_name, "none"); } - - SendMessage(h, CB_RESETCONTENT, 0, 0); - c = d = 0; - while (1) - { - s = hdd_controller_get_name(c); - if (s[0] == 0) - { - break; - } - if ((hdd_controller_get_flags(c) & DEVICE_AT) && !(machines[machine].flags & MACHINE_AT)) - { - c++; - continue; - } - if ((hdd_controller_get_flags(c) & DEVICE_PS2) && !(machines[machine].flags & MACHINE_PS2_HDD)) - { - c++; - continue; - } - if ((hdd_controller_get_flags(c) & DEVICE_MCA) && !(machines[machine].flags & MACHINE_MCA)) - { - c++; - continue; - } - if (!hdd_controller_available(c)) - { - c++; - continue; - } - if (c < 2) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2152 + c)); - } - else - { - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - hdd_names[d] = hdd_controller_get_internal_name(c); - if (!strcmp(old_name, hdd_names[d])) - { - SendMessage(h, CB_SETCURSEL, d, 0); - valid = 1; - } - c++; - d++; - } - - if (!valid) - { - SendMessage(h, CB_SETCURSEL, 0, 0); - } - - EnableWindow(h, TRUE); } + else + { + strncpy(old_name, temp_hdc_name, sizeof(old_name) - 1); + } + + SendMessage(h, CB_RESETCONTENT, 0, 0); + c = d = 0; + while (1) + { + s = hdc_get_name(c); + if (s[0] == 0) + { + break; + } + if (c==1 && !(machines[temp_machine].flags&MACHINE_HAS_HDC)) + { + /* Skip "Internal" if machine doesn't have one. */ + c++; + continue; + } + if (!hdc_available(c) || !device_is_valid(hdc_get_device(c), machines[temp_machine].flags)) + { + c++; + continue; + } + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + + hdc_names[d] = hdc_get_internal_name(c); + if (!strcmp(old_name, hdc_names[d])) + { + SendMessage(h, CB_SETCURSEL, d, 0); + valid = 1; + } + c++; + d++; + } + + if (!valid) + { + SendMessage(h, CB_SETCURSEL, 0, 0); + } + + EnableWindow(h, d ? TRUE : FALSE); free(lptsTemp); } @@ -1537,12 +1500,13 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR if (scsi_card_available(c)) { scsi_dev = scsi_card_getdevice(c); - - if (!scsi_dev || (scsi_dev->flags & DEVICE_MCA) == (machines[temp_machine].flags & MACHINE_MCA)) + + + if (device_is_valid(scsi_dev, machines[temp_machine].flags)) { if (c == 0) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_2152)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_2152)); } else { @@ -1558,6 +1522,8 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR } SendMessage(h, CB_SETCURSEL, settings_scsi_to_list[temp_scsi_card], 0); + EnableWindow(h, d ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_CONFIGURE_SCSI); if (scsi_card_has_config(temp_scsi_card)) { @@ -1568,14 +1534,14 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR EnableWindow(h, FALSE); } - recalc_hdd_list(hdlg, temp_machine, 0); + recalc_hdc_list(hdlg, temp_machine, 0); h=GetDlgItem(hdlg, IDC_COMBO_IDE_TER); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_5376)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_5376)); for (c = 0; c < 11; c++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_2155), valid_ide_irqs[c]); + wsprintf(lptsTemp, plat_get_string(IDS_2155), valid_ide_irqs[c]); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } @@ -1589,11 +1555,11 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR } h=GetDlgItem(hdlg, IDC_COMBO_IDE_QUA); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_5376)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_5376)); for (c = 0; c < 11; c++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_2155), valid_ide_irqs[c]); + wsprintf(lptsTemp, plat_get_string(IDS_2155), valid_ide_irqs[c]); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } @@ -1641,18 +1607,11 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR return FALSE; case WM_SAVESETTINGS: - if (hdc_ignore == 0) + h = GetDlgItem(hdlg, IDC_COMBO_HDC); + c = SendMessage(h, CB_GETCURSEL, 0, 0); + if (hdc_names[c]) { - h = GetDlgItem(hdlg, IDC_COMBO_HDC); - c = SendMessage(h, CB_GETCURSEL, 0, 0); - if (hdd_names[c]) - { - strncpy(temp_hdc_name, hdd_names[c], sizeof(temp_hdc_name) - 1); - } - else - { - strcpy(temp_hdc_name, "none"); - } + strncpy(temp_hdc_name, hdc_names[c], sizeof(temp_hdc_name) - 1); } else { @@ -1688,7 +1647,6 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR } -#ifdef USE_NETWORK int net_ignore_message = 0; static void network_recalc_combos(HWND hdlg) @@ -1792,11 +1750,11 @@ static BOOL CALLBACK win_settings_network_proc(HWND hdlg, UINT message, WPARAM w settings_network_to_list[c] = d; - if (network_card_available(c)) + if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machines[temp_machine].flags)) { if (c == 0) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(2152)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(2152)); } else { @@ -1811,6 +1769,8 @@ static BOOL CALLBACK win_settings_network_proc(HWND hdlg, UINT message, WPARAM w } SendMessage(h, CB_SETCURSEL, settings_network_to_list[temp_net_card], 0); + EnableWindow(h, d ? TRUE : FALSE); + network_recalc_combos(hdlg); free(lptsTemp); @@ -1888,7 +1848,6 @@ static BOOL CALLBACK win_settings_network_proc(HWND hdlg, UINT message, WPARAM w return FALSE; } -#endif static BOOL win_settings_hard_disks_image_list_init(HWND hwndList) { @@ -1916,28 +1875,28 @@ int next_free_id = 0; static void normalize_hd_list() { - hard_disk_t ihdc[HDC_NUM]; + hard_disk_t ihdd[HDD_NUM]; int i, j; j = 0; - memset(ihdc, 0, HDC_NUM * sizeof(hard_disk_t)); + memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t)); - for (i = 0; i < HDC_NUM; i++) + for (i = 0; i < HDD_NUM; i++) { - if (temp_hdc[i].bus != HDD_BUS_DISABLED) + if (temp_hdd[i].bus != HDD_BUS_DISABLED) { - memcpy(&(ihdc[j]), &(temp_hdc[i]), sizeof(hard_disk_t)); + memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t)); j++; } } - memcpy(temp_hdc, ihdc, HDC_NUM * sizeof(hard_disk_t)); + memcpy(temp_hdd, ihdd, HDD_NUM * sizeof(hard_disk_t)); } -int hdc_id_to_listview_index[HDC_NUM]; +int hdc_id_to_listview_index[HDD_NUM]; int hd_listview_items; -hard_disk_t new_hdc; +hard_disk_t new_hdd; int hdlv_current_sel; static int get_selected_hard_disk(HWND hdlg) @@ -1975,34 +1934,34 @@ static void add_locations(HWND hdlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); for (i = 0; i < 7; i++) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_4352 + i)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_4352 + i)); } h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4097), i >> 1, i & 1); + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); for (i = 0; i < 16; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4098), i); + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4098), i); + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4097), i >> 1, i & 1); + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } @@ -2055,7 +2014,7 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.mfm_channel : temp_hdc[hdlv_current_sel].mfm_channel, 0); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.mfm_channel : temp_hdd[hdlv_current_sel].mfm_channel, 0); break; case HDD_BUS_XTIDE: /* XT IDE */ h = GetDlgItem(hdlg, IDT_1722); @@ -2065,7 +2024,7 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.xtide_channel : temp_hdc[hdlv_current_sel].xtide_channel, 0); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.xtide_channel : temp_hdd[hdlv_current_sel].xtide_channel, 0); break; case HDD_BUS_ESDI: /* ESDI */ h = GetDlgItem(hdlg, IDT_1722); @@ -2075,7 +2034,7 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.esdi_channel : temp_hdc[hdlv_current_sel].esdi_channel, 0); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.esdi_channel : temp_hdd[hdlv_current_sel].esdi_channel, 0); break; case HDD_BUS_IDE_PIO_ONLY: /* IDE (PIO-only) */ case HDD_BUS_IDE_PIO_AND_DMA: /* IDE (PIO and DMA) */ @@ -2086,7 +2045,7 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.ide_channel : temp_hdc[hdlv_current_sel].ide_channel, 0); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.ide_channel : temp_hdd[hdlv_current_sel].ide_channel, 0); break; case HDD_BUS_SCSI: /* SCSI */ case HDD_BUS_SCSI_REMOVABLE: /* SCSI (removable) */ @@ -2100,12 +2059,12 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.scsi_id : temp_hdc[hdlv_current_sel].scsi_id, 0); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.scsi_id : temp_hdd[hdlv_current_sel].scsi_id, 0); h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.scsi_lun : temp_hdc[hdlv_current_sel].scsi_lun, 0); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.scsi_lun : temp_hdd[hdlv_current_sel].scsi_lun, 0); break; } } @@ -2146,41 +2105,41 @@ static void recalc_next_free_id(HWND hdlg) next_free_id = -1; - for (i = 0; i < HDC_NUM; i++) + for (i = 0; i < HDD_NUM; i++) { - if (temp_hdc[i].bus == HDD_BUS_MFM) + if (temp_hdd[i].bus == HDD_BUS_MFM) { c_mfm++; } - else if (temp_hdc[i].bus == HDD_BUS_ESDI) + else if (temp_hdd[i].bus == HDD_BUS_ESDI) { c_esdi++; } - else if (temp_hdc[i].bus == HDD_BUS_XTIDE) + else if (temp_hdd[i].bus == HDD_BUS_XTIDE) { c_xtide++; } - else if (temp_hdc[i].bus == HDD_BUS_IDE_PIO_ONLY) + else if (temp_hdd[i].bus == HDD_BUS_IDE_PIO_ONLY) { c_ide_pio++; } - else if (temp_hdc[i].bus == HDD_BUS_IDE_PIO_AND_DMA) + else if (temp_hdd[i].bus == HDD_BUS_IDE_PIO_AND_DMA) { c_ide_dma++; } - else if (temp_hdc[i].bus == HDD_BUS_SCSI) + else if (temp_hdd[i].bus == HDD_BUS_SCSI) { c_scsi++; } - else if (temp_hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) + else if (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) { c_scsi++; } } - for (i = 0; i < HDC_NUM; i++) + for (i = 0; i < HDD_NUM; i++) { - if (temp_hdc[i].bus == HDD_BUS_DISABLED) + if (temp_hdd[i].bus == HDD_BUS_DISABLED) { next_free_id = i; break; @@ -2241,59 +2200,59 @@ static void win_settings_hard_disks_update_item(HWND hwndList, int i, int column if (column == 0) { - switch(temp_hdc[i].bus) + switch(temp_hdd[i].bus) { case HDD_BUS_MFM: - wsprintf(szText, win_language_get_string_from_id(IDS_4608), temp_hdc[i].mfm_channel >> 1, temp_hdc[i].mfm_channel & 1); + wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); break; case HDD_BUS_XTIDE: - wsprintf(szText, win_language_get_string_from_id(IDS_4609), temp_hdc[i].xtide_channel >> 1, temp_hdc[i].xtide_channel & 1); + wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xtide_channel >> 1, temp_hdd[i].xtide_channel & 1); break; case HDD_BUS_ESDI: - wsprintf(szText, win_language_get_string_from_id(IDS_4610), temp_hdc[i].esdi_channel >> 1, temp_hdc[i].esdi_channel & 1); + wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); break; case HDD_BUS_IDE_PIO_ONLY: - wsprintf(szText, win_language_get_string_from_id(IDS_4611), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); + wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); break; case HDD_BUS_IDE_PIO_AND_DMA: - wsprintf(szText, win_language_get_string_from_id(IDS_4612), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); + wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); break; case HDD_BUS_SCSI: - wsprintf(szText, win_language_get_string_from_id(IDS_4613), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); + wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun); break; case HDD_BUS_SCSI_REMOVABLE: - wsprintf(szText, win_language_get_string_from_id(IDS_4614), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); + wsprintf(szText, plat_get_string(IDS_4614), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun); break; } lvI.pszText = szText; - lvI.iImage = (temp_hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; + lvI.iImage = (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; } else if (column == 1) { - lvI.pszText = temp_hdc[i].fn; + lvI.pszText = temp_hdd[i].fn; lvI.iImage = 0; } else if (column == 2) { - wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].tracks); + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); lvI.pszText = szText; lvI.iImage = 0; } else if (column == 3) { - wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].hpc); + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); lvI.pszText = szText; lvI.iImage = 0; } else if (column == 4) { - wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].spt); + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); lvI.pszText = szText; lvI.iImage = 0; } else if (column == 5) { - wsprintf(szText, win_language_get_string_from_id(IDS_4098), (temp_hdc[i].tracks * temp_hdc[i].hpc * temp_hdc[i].spt) >> 11); + wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); lvI.pszText = szText; lvI.iImage = 0; } @@ -2319,39 +2278,39 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < HDC_NUM; i++) + for (i = 0; i < HDD_NUM; i++) { - if (temp_hdc[i].bus > 0) + if (temp_hdd[i].bus > 0) { hdc_id_to_listview_index[i] = j; lvI.iSubItem = 0; - switch(temp_hdc[i].bus) + switch(temp_hdd[i].bus) { case HDD_BUS_MFM: - wsprintf(szText, win_language_get_string_from_id(IDS_4608), temp_hdc[i].mfm_channel >> 1, temp_hdc[i].mfm_channel & 1); + wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); break; case HDD_BUS_XTIDE: - wsprintf(szText, win_language_get_string_from_id(IDS_4609), temp_hdc[i].xtide_channel >> 1, temp_hdc[i].xtide_channel & 1); + wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xtide_channel >> 1, temp_hdd[i].xtide_channel & 1); break; case HDD_BUS_ESDI: - wsprintf(szText, win_language_get_string_from_id(IDS_4610), temp_hdc[i].esdi_channel >> 1, temp_hdc[i].esdi_channel & 1); + wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); break; case HDD_BUS_IDE_PIO_ONLY: - wsprintf(szText, win_language_get_string_from_id(IDS_4611), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); + wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); break; case HDD_BUS_IDE_PIO_AND_DMA: - wsprintf(szText, win_language_get_string_from_id(IDS_4612), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1); + wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); break; case HDD_BUS_SCSI: - wsprintf(szText, win_language_get_string_from_id(IDS_4613), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); + wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun); break; case HDD_BUS_SCSI_REMOVABLE: - wsprintf(szText, win_language_get_string_from_id(IDS_4614), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun); + wsprintf(szText, plat_get_string(IDS_4614), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun); break; } lvI.pszText = szText; lvI.iItem = j; - lvI.iImage = (temp_hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; + lvI.iImage = (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; if (ListView_InsertItem(hwndList, &lvI) == -1) { @@ -2359,7 +2318,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 1; - lvI.pszText = temp_hdc[i].fn; + lvI.pszText = temp_hdd[i].fn; lvI.iItem = j; lvI.iImage = 0; @@ -2369,7 +2328,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 2; - wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].tracks); + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); lvI.pszText = szText; lvI.iItem = j; lvI.iImage = 0; @@ -2380,7 +2339,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 3; - wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].hpc); + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); lvI.pszText = szText; lvI.iItem = j; lvI.iImage = 0; @@ -2391,7 +2350,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 4; - wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].spt); + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); lvI.pszText = szText; lvI.iItem = j; lvI.iImage = 0; @@ -2402,7 +2361,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) } lvI.iSubItem = 5; - wsprintf(szText, win_language_get_string_from_id(IDS_4098), (temp_hdc[i].tracks * temp_hdc[i].hpc * temp_hdc[i].spt) >> 11); + wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); lvI.pszText = szText; lvI.iItem = j; lvI.iImage = 0; @@ -2438,7 +2397,7 @@ static BOOL win_settings_hard_disks_init_columns(HWND hwndList) for (iCol = 0; iCol < C_COLUMNS_HARD_DISKS; iCol++) { lvc.iSubItem = iCol; - lvc.pszText = win_language_get_string_from_id(2082 + iCol); + lvc.pszText = plat_get_string(2082 + iCol); switch(iCol) { @@ -2501,7 +2460,7 @@ static void set_edit_box_contents(HWND hdlg, int id, uint64_t val) WCHAR szText[256]; h = GetDlgItem(hdlg, id); - wsprintf(szText, win_language_get_string_from_id(IDS_2156), val); + wsprintf(szText, plat_get_string(IDS_2156), val); SendMessage(h, WM_SETTEXT, (WPARAM) wcslen(szText), (LPARAM) szText); } @@ -2518,7 +2477,7 @@ uint64_t selection = 127; uint64_t spt, hpc, tracks, size; wchar_t hd_file_name[512]; -static hard_disk_t *hdc_ptr; +static hard_disk_t *hdd_ptr; static int hdconf_initialize_hdt_combo(HWND hdlg) { @@ -2533,17 +2492,17 @@ static int hdconf_initialize_hdt_combo(HWND hdlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); for (i = 0; i < 127; i++) { - temp_size = hdt[i][0] * hdt[i][1] * hdt[i][2]; + temp_size = hdd_table[i][0] * hdd_table[i][1] * hdd_table[i][2]; size_mb = temp_size >> 11; - wsprintf(szText, win_language_get_string_from_id(IDS_2157), size_mb, hdt[i][0], hdt[i][1], hdt[i][2]); + wsprintf(szText, plat_get_string(IDS_2157), size_mb, hdd_table[i][0], hdd_table[i][1], hdd_table[i][2]); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); - if ((tracks == hdt[i][0]) && (hpc == hdt[i][1]) && (spt == hdt[i][2])) + if ((tracks == hdd_table[i][0]) && (hpc == hdd_table[i][1]) && (spt == hdd_table[i][2])) { selection = i; } } - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_4100)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_4101)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_4100)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_4101)); SendMessage(h, CB_SETCURSEL, selection, 0); return selection; } @@ -2557,7 +2516,7 @@ static void recalc_selection(HWND hdlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); for (i = 0; i < 127; i++) { - if ((tracks == hdt[i][0]) && (hpc == hdt[i][1]) && (spt == hdt[i][2])) + if ((tracks == hdd_table[i][0]) && (hpc == hdd_table[i][1]) && (spt == hdd_table[i][2])) { selection = i; } @@ -2594,14 +2553,14 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W if (existing & 2) { next_free_id = (existing >> 3) & 0x1f; - hdc_ptr = &(hdc[next_free_id]); + hdd_ptr = &(hdd[next_free_id]); } else { - hdc_ptr = &(temp_hdc[next_free_id]); + hdd_ptr = &(temp_hdd[next_free_id]); } - SetWindowText(hdlg, win_language_get_string_from_id((existing & 1) ? IDS_4103 : IDS_4102)); + SetWindowText(hdlg, plat_get_string((existing & 1) ? IDS_4103 : IDS_4102)); no_update = 1; spt = (existing & 1) ? 0 : 17; @@ -2635,17 +2594,17 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); if (existing & 2) { - hdc_ptr->bus = HDD_BUS_SCSI_REMOVABLE; + hdd_ptr->bus = HDD_BUS_SCSI_REMOVABLE; max_spt = 99; max_hpc = 255; } else { - hdc_ptr->bus = HDD_BUS_IDE_PIO_ONLY; + hdd_ptr->bus = HDD_BUS_IDE_PIO_ONLY; max_spt = 63; max_hpc = 16; } - SendMessage(h, CB_SETCURSEL, hdc_ptr->bus, 0); + SendMessage(h, CB_SETCURSEL, hdd_ptr->bus, 0); max_tracks = 266305; recalc_location_controls(hdlg, 1); if (existing & 2) @@ -2670,7 +2629,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W /* Set the file name edit box contents to our existing parameters. */ h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) hdc[next_free_id].fn); + SendMessage(h, WM_SETTEXT, 0, (LPARAM) hdd[next_free_id].fn); } else { @@ -2695,73 +2654,73 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W if (!(existing & 2)) { h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - hdc_ptr->bus = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; + hdd_ptr->bus = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; } /* Make sure no file name is allowed with removable SCSI hard disks. */ - if ((wcslen(hd_file_name) == 0) && (hdc_ptr->bus != HDD_BUS_SCSI_REMOVABLE)) + if ((wcslen(hd_file_name) == 0) && (hdd_ptr->bus != HDD_BUS_SCSI_REMOVABLE)) { - hdc_ptr->bus = HDD_BUS_DISABLED; - msgbox_error(hwndParentDialog, IDS_4112); + hdd_ptr->bus = HDD_BUS_DISABLED; + settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4112); return TRUE; } - else if ((wcslen(hd_file_name) == 0) && (hdc_ptr->bus == HDD_BUS_SCSI_REMOVABLE)) + else if ((wcslen(hd_file_name) == 0) && (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE)) { /* Mark hard disk added but return empty - it will signify the disk was ejected. */ - hdc_ptr->spt = hdc_ptr->hpc = hdc_ptr->tracks = 0; - memset(hdc_ptr->fn, 0, sizeof(hdc_ptr->fn)); + hdd_ptr->spt = hdd_ptr->hpc = hdd_ptr->tracks = 0; + memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); goto hd_add_ok_common; } - get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &(hdc_ptr->spt)); - get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &(hdc_ptr->hpc)); - get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &(hdc_ptr->tracks)); - spt = hdc_ptr->spt; - hpc = hdc_ptr->hpc; - tracks = hdc_ptr->tracks; + get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &(hdd_ptr->spt)); + get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &(hdd_ptr->hpc)); + get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &(hdd_ptr->tracks)); + spt = hdd_ptr->spt; + hpc = hdd_ptr->hpc; + tracks = hdd_ptr->tracks; if (existing & 2) { - if (hdc_ptr->bus == HDD_BUS_SCSI_REMOVABLE) + if (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE) { - memset(hdc_ptr->prev_fn, 0, sizeof(hdc_ptr->prev_fn)); - wcscpy(hdc_ptr->prev_fn, hdc_ptr->fn); + memset(hdd_ptr->prev_fn, 0, sizeof(hdd_ptr->prev_fn)); + wcscpy(hdd_ptr->prev_fn, hdd_ptr->fn); } } else { - switch(hdc_ptr->bus) + switch(hdd_ptr->bus) { case HDD_BUS_MFM: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hdc_ptr->mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + hdd_ptr->mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0); break; case HDD_BUS_ESDI: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hdc_ptr->esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + hdd_ptr->esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0); break; case HDD_BUS_XTIDE: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hdc_ptr->xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + hdd_ptr->xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); break; case HDD_BUS_IDE_PIO_ONLY: case HDD_BUS_IDE_PIO_AND_DMA: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - hdc_ptr->ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + hdd_ptr->ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); break; case HDD_BUS_SCSI: case HDD_BUS_SCSI_REMOVABLE: h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - hdc_ptr->scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0); + hdd_ptr->scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0); h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - hdc_ptr->scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0); + hdd_ptr->scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0); break; } } - memset(hdc_ptr->fn, 0, sizeof(hdc_ptr->fn)); - wcscpy(hdc_ptr->fn, hd_file_name); + memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); + wcscpy(hdd_ptr->fn, hd_file_name); sector_size = 512; @@ -2774,7 +2733,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W if (size >= 0x100000000ll) { fclose(f); - msgbox_error(hwndParentDialog, IDS_4104); + settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4104); return TRUE; } @@ -2797,7 +2756,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W if (size > 0xffffffffffffffffll) { fclose(f); - msgbox_error(hwndParentDialog, IDS_4105); + settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4105); return TRUE; } @@ -2837,7 +2796,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W } fclose(f); - msgbox_info(hwndParentDialog, IDS_4113); + settings_msgbox(MBX_INFO, (wchar_t *)IDS_4113); } hd_add_ok_common: @@ -2849,13 +2808,13 @@ hd_add_ok_common: hard_disk_added = 0; if (!(existing & 2)) { - hdc_ptr->bus = HDD_BUS_DISABLED; + hdd_ptr->bus = HDD_BUS_DISABLED; } EndDialog(hdlg, 0); return TRUE; case IDC_CFILE: - if (!file_dlg_w(hdlg, win_language_get_string_from_id(IDS_4106), L"", !(existing & 1))) + if (!file_dlg_w(hdlg, plat_get_string(IDS_4106), L"", !(existing & 1))) { if (!(existing & 1)) { @@ -2863,7 +2822,7 @@ hd_add_ok_common: if (f != NULL) { fclose(f); - if (msgbox_question(ghwnd, IDS_4111) != IDYES) + if (settings_msgbox(MBX_QUESTION, (wchar_t *)IDS_4111) != 0) /* yes */ { return FALSE; } @@ -2874,7 +2833,7 @@ hd_add_ok_common: if (f == NULL) { hdd_add_file_open_error: - msgbox_error(hwndParentDialog, (existing & 1) ? IDS_4107 : IDS_4108); + settings_msgbox(MBX_ERROR, (existing & 1) ? (wchar_t *)IDS_4107 : (wchar_t *)IDS_4108); return TRUE; } if (existing & 1) @@ -2885,7 +2844,7 @@ hdd_add_file_open_error: fread(§or_size, 1, 4, f); if (sector_size != 512) { - msgbox_error(hwndParentDialog, IDS_4109); + settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4109); fclose(f); return TRUE; } @@ -3098,9 +3057,9 @@ hdd_add_file_open_error: if ((temp != selection) && (temp != 127) && (temp != 128)) { selection = temp; - tracks = hdt[selection][0]; - hpc = hdt[selection][1]; - spt = hdt[selection][2]; + tracks = hdd_table[selection][0]; + hpc = hdd_table[selection][1]; + spt = hdd_table[selection][2]; size = (tracks * hpc * spt) << 9; set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); @@ -3162,14 +3121,14 @@ hdd_add_file_open_error: recalc_location_controls(hdlg, 1); h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); b = SendMessage(h,CB_GETCURSEL,0,0) + 1; - if (b == hdc_ptr->bus) + if (b == hdd_ptr->bus) { goto hd_add_bus_skip; } - hdc_ptr->bus = b; + hdd_ptr->bus = b; - switch(hdc_ptr->bus) + switch(hdd_ptr->bus) { case HDD_BUS_DISABLED: default: @@ -3221,7 +3180,7 @@ hdd_add_file_open_error: break; } - if ((hdc_ptr->bus == HDD_BUS_SCSI_REMOVABLE) && !chs_enabled) + if ((hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE) && !chs_enabled) { h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); EnableWindow(h, TRUE); @@ -3234,7 +3193,7 @@ hdd_add_file_open_error: h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); EnableWindow(h, TRUE); } - else if ((hdc_ptr->bus != HDD_BUS_SCSI_REMOVABLE) && !chs_enabled) + else if ((hdd_ptr->bus != HDD_BUS_SCSI_REMOVABLE) && !chs_enabled) { h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); EnableWindow(h, FALSE); @@ -3325,7 +3284,7 @@ static BOOL CALLBACK win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARA ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); hdlv_current_sel = 0; h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - SendMessage(h, CB_SETCURSEL, temp_hdc[0].bus - 1, 0); + SendMessage(h, CB_SETCURSEL, temp_hdd[0].bus - 1, 0); } else { @@ -3360,7 +3319,7 @@ static BOOL CALLBACK win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARA } ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - SendMessage(h, CB_SETCURSEL, temp_hdc[hdlv_current_sel].bus - 1, 0); + SendMessage(h, CB_SETCURSEL, temp_hdd[hdlv_current_sel].bus - 1, 0); recalc_location_controls(hdlg, 0); ignore_change = 0; } @@ -3378,11 +3337,11 @@ static BOOL CALLBACK win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARA ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); b = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; - if (b == temp_hdc[hdlv_current_sel].bus) + if (b == temp_hdd[hdlv_current_sel].bus) { goto hd_bus_skip; } - temp_hdc[hdlv_current_sel].bus = b; + temp_hdd[hdlv_current_sel].bus = b; recalc_location_controls(hdlg, 0); h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); @@ -3398,17 +3357,17 @@ hd_bus_skip: ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - if (temp_hdc[hdlv_current_sel].bus == HDD_BUS_MFM) + if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_MFM) { - temp_hdc[hdlv_current_sel].mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_hdd[hdlv_current_sel].mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0); } - else if (temp_hdc[hdlv_current_sel].bus == HDD_BUS_ESDI) + else if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_ESDI) { - temp_hdc[hdlv_current_sel].esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_hdd[hdlv_current_sel].esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0); } - else if (temp_hdc[hdlv_current_sel].bus == HDD_BUS_XTIDE) + else if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_XTIDE) { - temp_hdc[hdlv_current_sel].xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_hdd[hdlv_current_sel].xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); } h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); @@ -3423,7 +3382,7 @@ hd_bus_skip: ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - temp_hdc[hdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_hdd[hdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); ignore_change = 0; @@ -3437,7 +3396,7 @@ hd_bus_skip: ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - temp_hdc[hdlv_current_sel].scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_hdd[hdlv_current_sel].scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0); h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); ignore_change = 0; @@ -3451,7 +3410,7 @@ hd_bus_skip: ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - temp_hdc[hdlv_current_sel].scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_hdd[hdlv_current_sel].scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0); h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); ignore_change = 0; @@ -3482,8 +3441,8 @@ hd_bus_skip: return FALSE; case IDC_BUTTON_HDD_REMOVE: - memcpy(temp_hdc[hdlv_current_sel].fn, L"", 4); - temp_hdc[hdlv_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */ + memcpy(temp_hdd[hdlv_current_sel].fn, L"", 4); + temp_hdd[hdlv_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */ normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. */ ignore_change = 1; h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); @@ -3494,7 +3453,7 @@ hd_bus_skip: ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); hdlv_current_sel = 0; h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - SendMessage(h, CB_SETCURSEL, temp_hdc[0].bus - 1, 0); + SendMessage(h, CB_SETCURSEL, temp_hdd[0].bus - 1, 0); } else { @@ -3591,7 +3550,7 @@ static BOOL win_settings_floppy_drives_recalc_list(HWND hwndList) } else { - lvI.pszText = win_language_get_string_from_id(IDS_5376); + lvI.pszText = plat_get_string(IDS_5376); } lvI.iItem = i; lvI.iImage = temp_fdd_types[i]; @@ -3600,7 +3559,7 @@ static BOOL win_settings_floppy_drives_recalc_list(HWND hwndList) return FALSE; lvI.iSubItem = 1; - lvI.pszText = win_language_get_string_from_id(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); + lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); lvI.iItem = i; lvI.iImage = 0; @@ -3610,7 +3569,7 @@ static BOOL win_settings_floppy_drives_recalc_list(HWND hwndList) } lvI.iSubItem = 2; - lvI.pszText = win_language_get_string_from_id(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); + lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); lvI.iItem = i; lvI.iImage = 0; @@ -3641,21 +3600,21 @@ static BOOL win_settings_cdrom_drives_recalc_list(HWND hwndList) { case CDROM_BUS_DISABLED: default: - lvI.pszText = win_language_get_string_from_id(fsid); + lvI.pszText = plat_get_string(fsid); lvI.iImage = 0; break; case CDROM_BUS_ATAPI_PIO_ONLY: - wsprintf(szText, win_language_get_string_from_id(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); lvI.pszText = szText; lvI.iImage = 1; break; case CDROM_BUS_ATAPI_PIO_AND_DMA: - wsprintf(szText, win_language_get_string_from_id(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); lvI.pszText = szText; lvI.iImage = 1; break; case CDROM_BUS_SCSI: - wsprintf(szText, win_language_get_string_from_id(fsid), temp_cdrom_drives[i].scsi_device_id, temp_cdrom_drives[i].scsi_device_lun); + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].scsi_device_id, temp_cdrom_drives[i].scsi_device_lun); lvI.pszText = szText; lvI.iImage = 1; break; @@ -3677,7 +3636,7 @@ static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.iSubItem = 0; - lvc.pszText = win_language_get_string_from_id(IDS_2143); + lvc.pszText = plat_get_string(IDS_2143); lvc.cx = 292; lvc.fmt = LVCFMT_LEFT; @@ -3688,7 +3647,7 @@ static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) } lvc.iSubItem = 1; - lvc.pszText = win_language_get_string_from_id(IDS_2059); + lvc.pszText = plat_get_string(IDS_2059); lvc.cx = 50; lvc.fmt = LVCFMT_LEFT; @@ -3699,7 +3658,7 @@ static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) } lvc.iSubItem = 2; - lvc.pszText = win_language_get_string_from_id(IDS_2170); + lvc.pszText = plat_get_string(IDS_2170); lvc.cx = 75; lvc.fmt = LVCFMT_LEFT; @@ -3718,7 +3677,7 @@ static BOOL win_settings_cdrom_drives_init_columns(HWND hwndList) lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.iSubItem = 0; - lvc.pszText = win_language_get_string_from_id(2082); + lvc.pszText = plat_get_string(IDS_2082); lvc.cx = 392; lvc.fmt = LVCFMT_LEFT; @@ -3789,7 +3748,7 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) } else { - lvI.pszText = win_language_get_string_from_id(IDS_5376); + lvI.pszText = plat_get_string(IDS_5376); } lvI.iImage = temp_fdd_types[i]; @@ -3799,7 +3758,7 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) } lvI.iSubItem = 1; - lvI.pszText = win_language_get_string_from_id(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); + lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); lvI.iItem = i; lvI.iImage = 0; @@ -3809,7 +3768,7 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) } lvI.iSubItem = 2; - lvI.pszText = win_language_get_string_from_id(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); + lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); lvI.iItem = i; lvI.iImage = 0; @@ -3837,21 +3796,21 @@ static void win_settings_cdrom_drives_update_item(HWND hwndList, int i) { case CDROM_BUS_DISABLED: default: - lvI.pszText = win_language_get_string_from_id(fsid); + lvI.pszText = plat_get_string(fsid); lvI.iImage = 0; break; case CDROM_BUS_ATAPI_PIO_ONLY: - wsprintf(szText, win_language_get_string_from_id(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); lvI.pszText = szText; lvI.iImage = 1; break; case CDROM_BUS_ATAPI_PIO_AND_DMA: - wsprintf(szText, win_language_get_string_from_id(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); lvI.pszText = szText; lvI.iImage = 1; break; case CDROM_BUS_SCSI: - wsprintf(szText, win_language_get_string_from_id(fsid), temp_cdrom_drives[i].scsi_device_id, temp_cdrom_drives[i].scsi_device_lun); + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].scsi_device_id, temp_cdrom_drives[i].scsi_device_lun); lvI.pszText = szText; lvI.iImage = 1; break; @@ -3876,28 +3835,28 @@ static void cdrom_add_locations(HWND hdlg) { if ((i == CDROM_BUS_DISABLED) || (i >= CDROM_BUS_ATAPI_PIO_ONLY)) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(combo_id_to_string_id(i))); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(combo_id_to_string_id(i))); } } h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); for (i = 0; i < 16; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4098), i); + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4098), i); + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, win_language_get_string_from_id(IDS_4097), i >> 1, i & 1); + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } @@ -3991,7 +3950,7 @@ static BOOL CALLBACK win_settings_removable_devices_proc(HWND hdlg, UINT message { if (i == 0) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) win_language_get_string_from_id(IDS_5376)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_5376)); } else { @@ -4251,18 +4210,11 @@ cdrom_bus_skip: #define SETTINGS_PAGE_VIDEO 1 #define SETTINGS_PAGE_INPUT 2 #define SETTINGS_PAGE_SOUND 3 -#ifdef USE_NETWORK #define SETTINGS_PAGE_NETWORK 4 #define SETTINGS_PAGE_PORTS 5 #define SETTINGS_PAGE_PERIPHERALS 6 #define SETTINGS_PAGE_HARD_DISKS 7 #define SETTINGS_PAGE_REMOVABLE_DEVICES 8 -#else -#define SETTINGS_PAGE_PORTS 4 -#define SETTINGS_PAGE_PERIPHERALS 5 -#define SETTINGS_PAGE_HARD_DISKS 6 -#define SETTINGS_PAGE_REMOVABLE_DEVICES 7 -#endif void win_settings_show_child(HWND hwndParent, DWORD child_id) { @@ -4293,11 +4245,9 @@ void win_settings_show_child(HWND hwndParent, DWORD child_id) case SETTINGS_PAGE_SOUND: hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_SOUND, hwndParent, win_settings_sound_proc); break; -#ifdef USE_NETWORK case SETTINGS_PAGE_NETWORK: hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_NETWORK, hwndParent, win_settings_network_proc); break; -#endif case SETTINGS_PAGE_PORTS: hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_PORTS, hwndParent, win_settings_ports_proc); break; @@ -4329,11 +4279,7 @@ static BOOL win_settings_main_image_list_init(HWND hwndList) GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, 1, 1); -#ifdef USE_NETWORK for (i = 0; i < 9; i++) -#else - for (i = 0; i < 8; i++) -#endif { hiconItem = LoadIcon(hinstance, (LPCWSTR) (256 + i)); ImageList_AddIcon(hSmall, hiconItem); @@ -4353,13 +4299,9 @@ static BOOL win_settings_main_insert_categories(HWND hwndList) lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; -#ifdef USE_NETWORK for (i = 0; i < 9; i++) -#else - for (i = 0; i < 8; i++) -#endif { - lvI.pszText = win_language_get_settings_category(i); + lvI.pszText = plat_get_string(IDS_2065+i); lvI.iItem = i; lvI.iImage = i; @@ -4382,7 +4324,7 @@ static BOOL CALLBACK win_settings_main_proc(HWND hdlg, UINT message, WPARAM wPar switch (message) { case WM_INITDIALOG: - pause = 1; + plat_pause(1); win_settings_init(); displayed_category = -1; h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); @@ -4403,11 +4345,7 @@ static BOOL CALLBACK win_settings_main_proc(HWND hdlg, UINT message, WPARAM wPar if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_SETTINGSCATLIST)) { category = -1; -#ifdef USE_NETWORK for (i = 0; i < 9; i++) -#else - for (i = 0; i < 8; i++) -#endif { h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); j = ListView_GetItemState(h, i, LVIS_SELECTED); @@ -4441,7 +4379,7 @@ static BOOL CALLBACK win_settings_main_proc(HWND hdlg, UINT message, WPARAM wPar /* pclog("Destroying window...\n"); */ DestroyWindow(hwndChildDialog); EndDialog(hdlg, 0); - pause = 0; + plat_pause(0); return TRUE; } else @@ -4451,7 +4389,7 @@ static BOOL CALLBACK win_settings_main_proc(HWND hdlg, UINT message, WPARAM wPar case IDCANCEL: DestroyWindow(hwndChildDialog); EndDialog(hdlg, 0); - pause=0; + plat_pause(0); return TRUE; } break; diff --git a/src/win/win_status.c b/src/win/win_status.c index 0a0fc659c..86565f865 100644 --- a/src/win/win_status.c +++ b/src/win/win_status.c @@ -5,90 +5,105 @@ #include #include #undef BITMAP - +#include +#include +#include +#include #include "../ibm.h" #include "../mem.h" #include "../cpu/x86_ops.h" +#ifdef USE_DYNAREC #include "../cpu/codegen.h" +#endif #include "../device.h" #include "win.h" -HWND status_hwnd; -int status_is_open = 0; + +HWND hwndStatus = NULL; extern int sreadlnum, swritelnum, segareads, segawrites, scycles_lost; - extern uint64_t main_time; static uint64_t status_time; -static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +static BOOL CALLBACK +StatusWindowProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - char device_s[4096]; - switch (message) - { - case WM_INITDIALOG: - status_is_open = 1; - case WM_USER: - { - uint64_t new_time = timer_read(); - uint64_t status_diff = new_time - status_time; - status_time = new_time; - sprintf(device_s, - "CPU speed : %f MIPS\n" - "FPU speed : %f MFLOPS\n\n" + char temp[4096]; + uint64_t new_time; + uint64_t status_diff; - "Video throughput (read) : %i bytes/sec\n" - "Video throughput (write) : %i bytes/sec\n\n" - "Effective clockspeed : %iHz\n\n" - "Timer 0 frequency : %fHz\n\n" - "CPU time : %f%% (%f%%)\n" + switch (message) { + case WM_INITDIALOG: + hwndStatus = hdlg; + /*FALLTHROUGH*/ - "New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n" - "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS" - ,mips, - flops, - segareads, - segawrites, - clockrate - scycles_lost, - pit_timer0_freq(), - ((double)main_time * 100.0) / status_diff, + case WM_USER: + new_time = timer_read(); + status_diff = new_time - status_time; + status_time = new_time; + sprintf(temp, + "CPU speed : %f MIPS\n" + "FPU speed : %f MFLOPS\n\n" + + "Video throughput (read) : %i bytes/sec\n" + "Video throughput (write) : %i bytes/sec\n\n" + "Effective clockspeed : %iHz\n\n" + "Timer 0 frequency : %fHz\n\n" + "CPU time : %f%% (%f%%)\n" + +#ifdef USE_DYNAREC + "New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n" + "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i" +#endif + ,mips, + flops, + segareads, + segawrites, + clockrate - scycles_lost, + pit_timer0_freq(), + ((double)main_time * 100.0) / status_diff, ((double)main_time * 100.0) / timer_freq - , cpu_new_blocks_latched, cpu_recomp_blocks_latched, (double)cpu_recomp_ins_latched / 1000000.0, (double)cpu_recomp_ins_latched/cpu_recomp_blocks_latched, - cpu_recomp_flushes_latched, cpu_recomp_evicted_latched, - cpu_recomp_reuse_latched, cpu_recomp_removed_latched, - - ((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq) - ); - main_time = 0; - SendDlgItemMessage(hdlg, IDT_SDEVICE, WM_SETTEXT, (WPARAM)NULL, (LPARAM)device_s); +#ifdef USE_DYNAREC + , cpu_new_blocks_latched, cpu_recomp_blocks_latched, (double)cpu_recomp_ins_latched / 1000000.0, (double)cpu_recomp_ins_latched/cpu_recomp_blocks_latched, + cpu_recomp_flushes_latched, cpu_recomp_evicted_latched, + cpu_recomp_reuse_latched, cpu_recomp_removed_latched +#endif + ); + main_time = 0; + SendDlgItemMessage(hdlg, IDT_SDEVICE, WM_SETTEXT, + (WPARAM)NULL, (LPARAM)temp); - device_s[0] = 0; - device_add_status_info(device_s, 4096); - SendDlgItemMessage(hdlg, IDT_STEXT, WM_SETTEXT, (WPARAM)NULL, (LPARAM)device_s); - } - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - case IDCANCEL: - status_is_open = 0; - EndDialog(hdlg, 0); - return TRUE; - } - break; - } + temp[0] = 0; + device_add_status_info(temp, 4096); + SendDlgItemMessage(hdlg, IDT_STEXT, WM_SETTEXT, + (WPARAM)NULL, (LPARAM)temp); + return(TRUE); + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + hwndStatus = NULL; + EndDialog(hdlg, 0); + return(TRUE); + } + break; + } - return FALSE; + return(FALSE); } -void status_open(HWND hwnd) + +void +StatusWindowCreate(HWND hwndParent) { - status_hwnd = CreateDialog(hinstance, (LPCSTR)DLG_STATUS, hwnd, status_dlgproc); - ShowWindow(status_hwnd, SW_SHOW); + HWND hwnd; + + hwnd = CreateDialog(hinstance, (LPCSTR)DLG_STATUS, + hwndParent, StatusWindowProcedure); + ShowWindow(hwnd, SW_SHOW); } diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c new file mode 100644 index 000000000..3651eabeb --- /dev/null +++ b/src/win/win_stbar.c @@ -0,0 +1,1141 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implement the application's Status Bar. + * + * Version: @(#)win_stbar.c 1.0.3 2017/10/09 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016,2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. + */ +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#include +#include +#undef BITMAP +#include +#include +#include +#include +#include +#include "../config.h" +#include "../ibm.h" +#include "../cpu/cpu.h" +#include "../device.h" +#include "../machine/machine.h" +#include "../cdrom/cdrom.h" +#include "../cdrom/cdrom_image.h" +#include "../cdrom/cdrom_null.h" +#include "../disk/hdd.h" +#include "../disk/hdc.h" +#include "../floppy/floppy.h" +#include "../floppy/fdd.h" +#include "../scsi/scsi.h" +#include "../scsi/scsi_disk.h" +#include "../network/network.h" +#include "../video/video.h" +#include "../sound/sound.h" +#include "../plat.h" +#include "../ui.h" +#include "win.h" + + +HWND hwndSBAR; + + +static LONG_PTR OriginalProcedure; +static HMENU *sb_menu_handles; +static HMENU menuSBAR; +static WCHAR **sbTips; +static int *iStatusWidths; +static int *sb_icon_flags; +static int *sb_part_meanings; +static int *sb_part_icons; +static int sb_parts = 0; +static int sb_ready = 0; + + +/* Also used by win_settings.c */ +int +fdd_type_to_icon(int type) +{ + int ret = 512; + + switch(type) { + case 0: + break; + + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + ret = 128; + break; + + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + ret = 144; + break; + + default: + break; + } + + return(ret); +} + + +/* FIXME: should be hdd_count() in hdd.c */ +static int +hdd_count(int bus) +{ + int c = 0; + int i; + + for (i=0; i= 'A') && + (cdrom_drives[id].host_drive <= 'Z')) { + cdrom_drives[id].host_drive = 0; + } + + goto check_menu_items; + } else { + if ((cdrom_drives[id].host_drive >= 'A') && + (cdrom_drives[id].host_drive <= 'Z')) { + if (!host_cdrom_drive_available[cdrom_drives[id].host_drive - 'A']) { + cdrom_drives[id].host_drive = 0; + } + } + } + + AppendMenu(m, MF_SEPARATOR, 0, 0); + + for (i=0; i<26; i++) { + _swprintf(s, L"Host CD/DVD Drive (%c:)", i+'A'); + if (host_cdrom_drive_available[i]) + AppendMenu(m, MF_STRING, IDM_CDROM_HOST_DRIVE | (i<<3)|id, s); + } + +check_menu_items: + if (! cdrom_drives[id].sound_on) + CheckMenuItem(m, IDM_CDROM_MUTE | id, MF_CHECKED); + + if (cdrom_drives[id].host_drive == 200) + CheckMenuItem(m, IDM_CDROM_IMAGE | id, MF_CHECKED); + else + if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) { + CheckMenuItem(m, IDM_CDROM_HOST_DRIVE | id | + ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); + } else { + cdrom_drives[id].host_drive = 0; + CheckMenuItem(m, IDM_CDROM_EMPTY | id, MF_CHECKED); + } +} + + +static void +StatusBarCreateRemovableDiskSubmenu(HMENU m, int id) +{ + AppendMenu(m, MF_STRING, IDM_RDISK_EJECT | id, + plat_get_string(IDS_2166)); + AppendMenu(m, MF_STRING, IDM_RDISK_RELOAD | id, + plat_get_string(IDS_2167)); + AppendMenu(m, MF_SEPARATOR, 0, 0); + AppendMenu(m, MF_STRING, IDM_RDISK_SEND_CHANGE | id, + plat_get_string(IDS_2142)); + AppendMenu(m, MF_SEPARATOR, 0, 0); + AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE | id, + plat_get_string(IDS_2168)); + AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE_WP | id, + plat_get_string(IDS_2169)); +} + + +/* API */ +int +ui_sb_find_part(int tag) +{ + int found = -1; + int i; + + if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) { + return -1; + } + + for (i=0; i= SB_TEXT) || !sb_ready || (sb_parts == 0) || (sb_icon_flags == NULL) || (sb_part_icons == NULL)) { + return; + } + + temp_flags |= active; + + found = ui_sb_find_part(tag); + if (found != -1) { + if (temp_flags != (sb_icon_flags[found] & 1)) { + sb_icon_flags[found] &= ~1; + sb_icon_flags[found] |= active; + + sb_part_icons[found] &= ~257; + sb_part_icons[found] |= sb_icon_flags[found]; + + SendMessage(hwndSBAR, SB_SETICON, found, + (LPARAM)hIcon[sb_part_icons[found]]); + } + } +} + + +/* API: This is for the drive state indicator. */ +void +ui_sb_update_icon_state(int tag, int state) +{ + int found = -1; + + if (((tag & 0xf0) >= SB_HDD) || !sb_ready || (sb_parts == 0) || (sb_icon_flags == NULL) || (sb_part_icons == NULL)) { + return; + } + + found = ui_sb_find_part(tag); + if (found != -1) { + sb_icon_flags[found] &= ~256; + sb_icon_flags[found] |= state ? 256 : 0; + + sb_part_icons[found] &= ~257; + sb_part_icons[found] |= sb_icon_flags[found]; + + SendMessage(hwndSBAR, SB_SETICON, found, + (LPARAM)hIcon[sb_part_icons[found]]); + } +} + + +static void +StatusBarCreateFloppyTip(int part) +{ + WCHAR wtext[512]; + WCHAR tempTip[512]; + + int drive = sb_part_meanings[part] & 0xf; + + mbstowcs(wtext, fdd_getname(fdd_get_type(drive)), + strlen(fdd_getname(fdd_get_type(drive))) + 1); + if (wcslen(floppyfns[drive]) == 0) { + _swprintf(tempTip, plat_get_string(IDS_2158), + drive+1, wtext, plat_get_string(IDS_2057)); + } else { + _swprintf(tempTip, plat_get_string(IDS_2158), + drive+1, wtext, floppyfns[drive]); + } + + if (sbTips[part] != NULL) { + free(sbTips[part]); + sbTips[part] = NULL; + } + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + +static void +StatusBarCreateCdromTip(int part) +{ + WCHAR wtext[512]; + WCHAR tempTip[512]; + WCHAR *szText; + int id; + int drive = sb_part_meanings[part] & 0xf; + int bus = cdrom_drives[drive].bus_type; + + id = IDS_4352 + (bus - 1); + szText = plat_get_string(id); + + if (cdrom_drives[drive].host_drive == 200) { + if (wcslen(cdrom_image[drive].image_path) == 0) { + _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, plat_get_string(IDS_2057)); + } else { + _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, cdrom_image[drive].image_path); + } + } else if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) { + _swprintf(wtext, plat_get_string(IDS_2058), cdrom_drives[drive].host_drive & ~0x20); + _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, wtext); + } else { + _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, plat_get_string(IDS_2057)); + } + + if (sbTips[part] != NULL) { + free(sbTips[part]); + sbTips[part] = NULL; + } + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + +static void +StatusBarCreateRemovableDiskTip(int part) +{ + WCHAR tempTip[512]; + int drive = sb_part_meanings[part] & 0x1f; + + if (wcslen(hdd[drive].fn) == 0) { + _swprintf(tempTip, plat_get_string(IDS_4115), drive, plat_get_string(IDS_2057)); + } else { + _swprintf(tempTip, plat_get_string(IDS_4115), drive, hdd[drive].fn); + } + + if (sbTips[part] != NULL) { + free(sbTips[part]); + sbTips[part] = NULL; + } + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + +static void +StatusBarCreateDiskTip(int part) +{ + WCHAR tempTip[512]; + WCHAR *szText; + int id; + int bus = sb_part_meanings[part] & 0xf; + + id = IDS_4352 + (bus - 1); + szText = plat_get_string(id); + + _swprintf(tempTip, plat_get_string(IDS_4096), szText); + if (sbTips[part] != NULL) + free(sbTips[part]); + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + +static void +StatusBarCreateNetworkTip(int part) +{ + WCHAR tempTip[512]; + + _swprintf(tempTip, plat_get_string(IDS_2069)); + + if (sbTips[part] != NULL) + free(sbTips[part]); + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + +/* API */ +void +ui_sb_update_tip(int meaning) +{ + int part = -1; + int i; + + if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) return; + + for (i=0; i 0) { + for (i = 0; i < sb_parts; i++) + SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM)NULL); + SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM)0, (LPARAM)NULL); + + if (iStatusWidths) { + free(iStatusWidths); + iStatusWidths = NULL; + } + if (sb_part_meanings) { + free(sb_part_meanings); + sb_part_meanings = NULL; + } + if (sb_part_icons) { + free(sb_part_icons); + sb_part_icons = NULL; + } + if (sb_icon_flags) { + free(sb_icon_flags); + sb_icon_flags = NULL; + } + StatusBarDestroyMenus(); + StatusBarDestroyTips(); + } + + sb_parts = 0; + for (i=0; i= 'A') && (cdrom_drives[id].host_drive <= 'Z')) { + sb_icon_flags[i] = 0; + } else { + sb_icon_flags[i] = 256; + } + sb_part_icons[i] = 160 | sb_icon_flags[i]; + sb_menu_handles[i] = StatusBarCreatePopupMenu(i); + StatusBarCreateCdromSubmenu(sb_menu_handles[i], sb_part_meanings[i] & 0xf); + EnableMenuItem(sb_menu_handles[i], IDM_CDROM_RELOAD | (sb_part_meanings[i] & 0xf), MF_BYCOMMAND | MF_GRAYED); + StatusBarCreateCdromTip(i); + break; + + case SB_RDISK: /* Removable hard disk */ + sb_icon_flags[i] = (wcslen(hdd[sb_part_meanings[i] & 0x1f].fn) == 0) ? 256 : 0; + sb_part_icons[i] = 176 + sb_icon_flags[i]; + sb_menu_handles[i] = StatusBarCreatePopupMenu(i); + StatusBarCreateRemovableDiskSubmenu(sb_menu_handles[i], sb_part_meanings[i] & 0x1f); + EnableMenuItem(sb_menu_handles[i], IDM_RDISK_EJECT | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | ((sb_icon_flags[i] & 256) ? MF_GRAYED : MF_ENABLED)); + EnableMenuItem(sb_menu_handles[i], IDM_RDISK_RELOAD | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(sb_menu_handles[i], IDM_RDISK_SEND_CHANGE | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | ((sb_icon_flags[i] & 256) ? MF_GRAYED : MF_ENABLED)); + StatusBarCreateRemovableDiskTip(i); + break; + + case SB_HDD: /* Hard disk */ + sb_part_icons[i] = 192; + StatusBarCreateDiskTip(i); + break; + + case SB_NETWORK: /* Network */ + sb_part_icons[i] = 208; + StatusBarCreateNetworkTip(i); + break; + + case SB_TEXT: /* Status text */ + SendMessage(hwndSBAR, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM)L""); + sb_part_icons[i] = -1; + break; + } + + if (sb_part_icons[i] != -1) { + SendMessage(hwndSBAR, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM)L""); + SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM)hIcon[sb_part_icons[i]]); + SendMessage(hwndSBAR, SB_SETTIPTEXT, i, (LPARAM)sbTips[i]); + } else { + SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM)NULL); + } + } + + sb_ready = 1; +} + + +static VOID APIENTRY +StatusBarPopupMenu(HWND hwnd, POINT pt, int id) +{ + if (id >= (sb_parts - 1)) return; + + pt.x = id * SB_ICON_WIDTH; /* Justify to the left. */ + pt.y = 0; /* Justify to the top. */ + ClientToScreen(hwnd, (LPPOINT) &pt); + TrackPopupMenu(sb_menu_handles[id], + TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_LEFTBUTTON, + pt.x, pt.y, 0, hwndSBAR, NULL); +} + + +/* Handle messages for the Status Bar window. */ +static LRESULT CALLBACK +StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WCHAR temp_path[1024]; + RECT rc; + POINT pt; + int new_cdrom_drive; + int ret = 0; + int item_id = 0; + int item_params = 0; + int id = 0; + int part = 0; + int letter = 0; + + switch (message) { + case WM_COMMAND: + item_id = LOWORD(wParam) & 0xff00; /* low 8 bits */ + item_params = LOWORD(wParam) & 0x00ff; /* high 8 bits */ + + switch (item_id) { + case IDM_FLOPPY_IMAGE_EXISTING: + case IDM_FLOPPY_IMAGE_EXISTING_WP: + id = item_params & 0x0003; + part = ui_sb_find_part(SB_FLOPPY | id); + if ((part == -1) || (sb_menu_handles == NULL)) + break; + + ret = file_dlg_w_st(hwnd, IDS_2159, floppyfns[id], 0); + if (! ret) { + floppy_close(id); + ui_writeprot[id] = (item_id == IDM_FLOPPY_IMAGE_EXISTING_WP) ? 1 : 0; + floppy_load(id, wopenfilestring); + ui_sb_update_icon_state(SB_FLOPPY | id, wcslen(floppyfns[id]) ? 0 : 1); + EnableMenuItem(sb_menu_handles[part], IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | (wcslen(floppyfns[id]) ? MF_ENABLED : MF_GRAYED)); + ui_sb_update_tip(SB_FLOPPY | id); + config_save(); + } + break; + + case IDM_FLOPPY_EJECT: + id = item_params & 0x0003; + part = ui_sb_find_part(SB_FLOPPY | id); + if ((part == -1) || (sb_menu_handles == NULL)) + break; + + floppy_close(id); + ui_sb_update_icon_state(SB_FLOPPY | id, 1); + EnableMenuItem(sb_menu_handles[part], IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_update_tip(SB_FLOPPY | id); + config_save(); + break; + + case IDM_CDROM_MUTE: + id = item_params & 0x0007; + part = ui_sb_find_part(SB_CDROM | id); + if ((part == -1) || (sb_menu_handles == NULL)) + break; + + cdrom_drives[id].sound_on ^= 1; + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_MUTE | id, cdrom_drives[id].sound_on ? MF_UNCHECKED : MF_CHECKED); + config_save(); + sound_cd_thread_reset(); + break; + + case IDM_CDROM_EMPTY: + id = item_params & 0x0007; + cdrom_eject(id); + break; + + case IDM_CDROM_RELOAD: + id = item_params & 0x0007; + cdrom_reload(id); + break; + + case IDM_CDROM_IMAGE: + id = item_params & 0x0007; + part = ui_sb_find_part(SB_CDROM | id); + if ((part == -1) || (sb_menu_handles == NULL)) + break; + + if (!file_dlg_w_st(hwnd, IDS_2075, cdrom_image[id].image_path, 0)) { + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + wcscpy(temp_path, wopenfilestring); + if ((wcscmp(cdrom_image[id].image_path, temp_path) == 0) && (cdrom_drives[id].host_drive == 200)) { + /* Switching from image to the same image. Do nothing. */ + break; + } + wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path); + cdrom_drives[id].handler->exit(id); + cdrom_close(id); + image_open(id, temp_path); + /* Signal media change to the emulated machine. */ + cdrom_insert(id); + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); + if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) { + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); + } + cdrom_drives[id].host_drive = (wcslen(cdrom_image[id].image_path) == 0) ? 0 : 200; + if (cdrom_drives[id].host_drive == 200) { + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_CHECKED); + ui_sb_update_icon_state(SB_CDROM | id, 0); + } else { + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_UNCHECKED); + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); + ui_sb_update_icon_state(SB_CDROM | id, 1); + } + EnableMenuItem(sb_menu_handles[part], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_update_tip(SB_CDROM | id); + config_save(); + } + break; + + case IDM_CDROM_HOST_DRIVE: + id = item_params & 0x0007; + letter = ((item_params >> 3) & 0x001f) + 'A'; + part = ui_sb_find_part(SB_CDROM | id); + if ((part == -1) || (sb_menu_handles == NULL)) + { + break; + } + + new_cdrom_drive = letter; + if (cdrom_drives[id].host_drive == new_cdrom_drive) + { + /* Switching to the same drive. Do nothing. */ + break; + } + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + cdrom_drives[id].handler->exit(id); + cdrom_close(id); + ioctl_open(id, new_cdrom_drive); + /* Signal media change to the emulated machine. */ + cdrom_insert(id); + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); + if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) + { + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); + } + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_UNCHECKED); + cdrom_drives[id].host_drive = new_cdrom_drive; + CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); + EnableMenuItem(sb_menu_handles[part], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + ui_sb_update_icon_state(SB_CDROM | id, 0); + ui_sb_update_tip(SB_CDROM | id); + config_save(); + break; + + case IDM_RDISK_EJECT: + id = item_params & 0x001f; + removable_disk_eject(id); + break; + + case IDM_RDISK_RELOAD: + id = item_params & 0x001f; + removable_disk_reload(id); + break; + + case IDM_RDISK_SEND_CHANGE: + id = item_params & 0x001f; + scsi_disk_insert(id); + break; + + case IDM_RDISK_IMAGE: + case IDM_RDISK_IMAGE_WP: + id = item_params & 0x001f; + ret = file_dlg_w_st(hwnd, IDS_4106, hdd[id].fn, id); + if (!ret) { + removable_disk_unload(id); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + wcscpy(hdd[id].fn, wopenfilestring); + hdd[id].wp = (item_id == IDM_RDISK_IMAGE_WP) ? 1 : 0; + scsi_loadhd(hdd[id].scsi_id, hdd[id].scsi_lun, id); + scsi_disk_insert(id); + if (wcslen(hdd[id].fn) > 0) { + ui_sb_update_icon_state(SB_RDISK | id, 0); + EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_ENABLED); + } + else { + ui_sb_update_icon_state(SB_RDISK | id, 1); + EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_GRAYED); + } + ui_sb_update_tip(SB_RDISK | id); + config_save(); + } + break; + + default: + break; + } + return(0); + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + GetClientRect(hwnd, (LPRECT)& rc); + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + if (PtInRect((LPRECT) &rc, pt)) + StatusBarPopupMenu(hwnd, pt, (pt.x / SB_ICON_WIDTH)); + break; + + default: + return(CallWindowProc((WNDPROC)OriginalProcedure, + hwnd, message, wParam, lParam)); + } + + return(0); +} + + +/* API: Create and set up the Status Bar window. */ +void +StatusBarCreate(HWND hwndParent, int idStatus, HINSTANCE hInst) +{ + RECT rectDialog; + int dw, dh, i; + + /* Load our icons into the cache for faster access. */ + for (i = 128; i < 130; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 144; i < 146; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 160; i < 162; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 176; i < 178; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 192; i < 194; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 208; i < 210; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 384; i < 386; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 400; i < 402; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 416; i < 418; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 432; i < 434; i++) + hIcon[i] = LoadIconEx((PCTSTR) i); + + GetWindowRect(hwndParent, &rectDialog); + dw = rectDialog.right - rectDialog.left; + dh = rectDialog.bottom - rectDialog.top; + + /* Load the Common Controls DLL if needed. */ + InitCommonControls(); + + /* Create the window, and make sure it's using the STATUS class. */ + hwndSBAR = CreateWindowEx(0, + STATUSCLASSNAME, + (LPCTSTR)NULL, + SBARS_SIZEGRIP|WS_CHILD|WS_VISIBLE|SBT_TOOLTIPS, + 0, dh-17, dw, 17, + hwndParent, + (HMENU)idStatus, hInst, NULL); + + /* Replace the original procedure with ours. */ + OriginalProcedure = GetWindowLongPtr(hwndSBAR, GWLP_WNDPROC); + SetWindowLongPtr(hwndSBAR, GWL_WNDPROC, (LONG_PTR)&StatusBarProcedure); + + SendMessage(hwndSBAR, SB_SETMINHEIGHT, (WPARAM)17, (LPARAM)0); + + /* Align the window with the parent (main) window. */ + GetWindowRect(hwndSBAR, &rectDialog); + SetWindowPos(hwndSBAR, + HWND_TOPMOST, + rectDialog.left, rectDialog.top, + rectDialog.right-rectDialog.left, + rectDialog.bottom-rectDialog.top, + SWP_SHOWWINDOW); + + /* Load the dummu menu for this window. */ + menuSBAR = LoadMenu(hInst, SB_MENU_NAME); + + /* Initialize the status bar and populate the icons and menus. */ + sb_parts = 0; + ui_sb_update_panes(); +} + + +/* API (Settings) */ +void +ui_sb_check_menu_item(int tag, int id, int chk) +{ + int part; + + part = ui_sb_find_part(tag); + if ((part == -1) || (sb_menu_handles == NULL)) + return; + + CheckMenuItem(sb_menu_handles[part], id, chk); +} + + +/* API (Settings) */ +void +ui_sb_enable_menu_item(int tag, int id, int flg) +{ + int part; + + part = ui_sb_find_part(tag); + if ((part == -1) || (sb_menu_handles == NULL)) + return; + + EnableMenuItem(sb_menu_handles[part], id, flg); +} + + +/* API */ +void +ui_sb_set_text_w(wchar_t *wstr) +{ + int part = -1; + int i; + + if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) return; + + for (i=0; i + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2017 Fred N. van Kempen. + */ +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#include +#undef BITMAP +#include +#include +#include +#include +#include +#include "../ibm.h" +#include "../plat.h" + + +typedef struct { + HANDLE handle; +} win_event_t; + + +void * +thread_create(void (*thread_rout)(void *param), void *param) +{ + return((void *)_beginthread(thread_rout, 0, param)); +} + + +void +thread_kill(void *handle) +{ + if (handle == NULL) return; + + TerminateThread(handle, 0); +} + + +void +thread_sleep(int t) +{ + Sleep(t); +} + + +event_t * +thread_create_event(void) +{ + win_event_t *ev = malloc(sizeof(win_event_t)); + + ev->handle = CreateEvent(NULL, FALSE, FALSE, NULL); + + return((event_t *)ev); +} + + +void +thread_set_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *)arg; + + if (arg == NULL) return; + + SetEvent(ev->handle); +} + + +void +thread_reset_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *)arg; + + if (arg == NULL) return; + + ResetEvent(ev->handle); +} + + +int +thread_wait_event(event_t *arg, int timeout) +{ + win_event_t *ev = (win_event_t *)arg; + + if (arg == NULL) return(0); + + if (timeout == -1) + timeout = INFINITE; + + if (WaitForSingleObject(ev->handle, timeout)) return(1); + + return(0); +} + + +void +thread_destroy_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *)arg; + + if (arg == NULL) return; + + CloseHandle(ev->handle); + + free(ev); +} + + +mutex_t * +thread_create_mutex(wchar_t *name) +{ + return((mutex_t*)CreateMutex(NULL, FALSE, name)); +} + + +void +thread_close_mutex(mutex_t *mutex) +{ + if (mutex == NULL) return; + + CloseHandle((HANDLE)mutex); +} + + +int +thread_wait_mutex(mutex_t *mutex) +{ + if (mutex == NULL) return(0); + + DWORD dwres = WaitForSingleObject((HANDLE)mutex, INFINITE); + + if (dwres == WAIT_OBJECT_0) return(1); + + return(0); +} + + +int +thread_release_mutex(mutex_t *mutex) +{ + if (mutex == NULL) return(0); + + return(!!ReleaseMutex((HANDLE)mutex)); +} diff --git a/src/win/win_video.c b/src/win/win_video.c deleted file mode 100644 index 3a50f7b9f..000000000 --- a/src/win/win_video.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include -#include -#include -#include "../video/video.h" -#include "win_cgapal.h" - - -BITMAP *screen; - - -void hline(BITMAP *b, int x1, int y, int x2, uint32_t col) -{ - if (y < 0 || y >= buffer->h) - return; - - if (b == buffer) - memset(&b->line[y][x1], col, x2 - x1); - else - memset(&((uint32_t *)b->line[y])[x1], col, (x2 - x1) * 4); -} - -void blit(BITMAP *src, BITMAP *dst, int x1, int y1, int x2, int y2, int xs, int ys) -{ -} - -void stretch_blit(BITMAP *src, BITMAP *dst, int x1, int y1, int xs1, int ys1, int x2, int y2, int xs2, int ys2) -{ -} - -void rectfill(BITMAP *b, int x1, int y1, int x2, int y2, uint32_t col) -{ -} - -void set_palette(PALETTE p) -{ -} - -void destroy_bitmap(BITMAP *b) -{ -} - -BITMAP *create_bitmap(int x, int y) -{ - BITMAP *b = malloc(sizeof(BITMAP) + (y * sizeof(uint8_t *))); - int c; - b->dat = malloc(x * y * 4); - for (c = 0; c < y; c++) - { - b->line[c] = b->dat + (c * x * 4); - } - b->w = x; - b->h = y; - return b; -} diff --git a/src/win/win_vnc.c b/src/win/win_vnc.c new file mode 100644 index 000000000..3ef79e3ce --- /dev/null +++ b/src/win/win_vnc.c @@ -0,0 +1,327 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implement the VNC renderer with LibVNCServer. + * + * Version: @(#)win_vnc.c 1.0.2 2017/10/14 + * + * Authors: Fred N. van Kempen, + * Based on raw code by RichardG, + * + * Copyright 2017 Fred N. van Kempen. + */ +#include +#include +#include "../ibm.h" +#include "../device.h" +#include "../video/video.h" +#include "../plat.h" +#include "../plat_keyboard.h" +#include "../ui.h" +#define BITMAP MY_BITMAP +#include +#undef BITMAP +#include "win.h" +#include "win_vnc.h" + + +static rfbScreenInfoPtr rfb = NULL; +static int clients; +static int updatingSize; +static int allowedX, + allowedY; + +static int keysyms_00[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00-07 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 08-0f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 10-17 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 18-1f + 0x0039, 0x2a02, 0x2a28, 0x2a04, 0x2a05, 0x2a06, 0x2a08, 0x0028, // 20-27 + 0x2a0a, 0x2a0b, 0x2a09, 0x2a0d, 0x0033, 0x000c, 0x0034, 0x0035, // 28-2f + 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, // 30-37 + 0x0009, 0x000a, 0x2a27, 0x0027, 0x2a33, 0x000d, 0x2a34, 0x2a35, // 38-3f + 0x2a03, 0x2a1e, 0x2a30, 0x2a2e, 0x2a20, 0x2a12, 0x2a21, 0x2a22, // 40-47 + 0x2a23, 0x2a17, 0x2a24, 0x2a25, 0x2a26, 0x2a32, 0x2a31, 0x2a18, // 48-4f + 0x2a19, 0x2a10, 0x2a13, 0x2a1f, 0x2a14, 0x2a16, 0x2a2f, 0x2a11, // 50-57 + 0x2a2d, 0x2a15, 0x2a2c, 0x001a, 0x0000, 0x001b, 0x2a07, 0x2a0c, // 58-5f + 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022, // 60-67 + 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018, // 68-6f + 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011, // 70-77 + 0x002d, 0x0015, 0x002c, 0x2a1a, 0x0000, 0x2a1b, 0x2a29, 0x0000, // 78-7f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 80-87 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 88-8f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 90-97 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 98-9f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // a0-a7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // a8-af + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // b0-b7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // b8-bf + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // c0-c7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // c8-cf + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // d0-d7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // d8-df + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // e0-e7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // e8-ef + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // f0-f7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 // f8-ff +}; + +static int keysyms_ff[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00-07 + 0x000e, 0x000f, 0x0000, 0x004c, 0x0000, 0x001c, 0x0000, 0x0000, // 08-0f + 0x0000, 0x0000, 0x0000, 0xff45, 0x0000, 0x0000, 0x0000, 0x0000, // 10-17 + 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, // 18-1f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 20-27 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 28-2f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 30-37 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 38-3f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 40-47 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 48-4f + 0x0047, 0x00cb, 0xaac8, 0x00cd, 0x00d0, 0x0049, 0x0051, 0x004f, // 50-57 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 58-5f + 0x0000, 0x0000, 0x0000, 0x0052, 0x0000, 0x0000, 0x0000, 0x00dd, // 60-67 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 68-6f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 70-77 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 78-7f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 80-87 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x009c, 0x0000, 0x0000, // 88-8f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 90-97 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 98-9f + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // a0-a7 + 0x0000, 0x0000, 0x0037, 0x004e, 0x0000, 0x004a, 0x0000, 0x00b5, // a8-af + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // b0-b7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x003b, 0x003c, // b8-bf + 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, // c0-c7 + 0x0057, 0x0058, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // c8-cf + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // d0-d7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // d8-df + 0x0000, 0x0036, 0x0000, 0x001d, 0x009d, 0x0000, 0x0000, 0x0000, // e0-e7 + 0x0000, 0x0038, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // e8-ef + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // f0-f7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0053 // f8-ff +}; + + +static void +vnc_clientgone(rfbClientPtr cl) +{ + pclog("VNC: client disconnected: %s\n", cl->host); + + if (clients > 0) + clients--; + if (clients == 0) { + /* No more clients, pause the emulator. */ + pclog("VNC: no clients, pausing..\n"); + plat_pause(1); + } +} + + +static enum rfbNewClientAction +vnc_newclient(rfbClientPtr cl) +{ + /* Hook the ClientGone function so we know when they're gone. */ + cl->clientGoneHook = vnc_clientgone; + + pclog("VNC: new client: %s\n", cl->host); + if (++clients == 1) { + /* We now have clients, un-pause the emulator. */ + pclog("VNC: unpausing..\n"); + plat_pause(0); + } + + return(RFB_CLIENT_ACCEPT); +} + + +static void +vnc_display(rfbClientPtr cl) +{ + /* Avoid race condition between resize and update. */ + if (!updatingSize && cl->newFBSizePending) { + updatingSize = 1; + } else if (updatingSize && !cl->newFBSizePending) { + updatingSize = 0; + + allowedX = rfb->width; + allowedY = rfb->height; + } +} + + +static void +vnc_kbdevent(rfbBool down, rfbKeySym k, rfbClientPtr cl) +{ + int will_press = 0; + int key; + +#if 0 + pclog("VNC: kbdevent %d %x\n", down, k); +#endif + + if ((k >> 8) == 0x00) { + will_press = keysyms_00[k & 0xff]; + } else if ((k >> 8) == 0xff) { + will_press = keysyms_ff[k & 0xff]; + } + + if (will_press <= 0) return; + +#if 0 + pclog("VNC: translated to %x %x\n", + (will_press >> 8) & 0xff, will_press & 0xff); +#endif + + // first key + key = (will_press >> 8) & 0xff; + if (key > 0) + recv_key[key] = down; + + // second key + key = will_press & 0xff; + if (key > 0) + recv_key[key] = down; +} + + +static void +vnc_blit(int x, int y, int y1, int y2, int w, int h) +{ + uint32_t *p; + int yy; + + for (yy=y1; yyframeBuffer)[yy*2048]); + + if ((y+yy) >= 0 && (y+yy) < 2048) + memcpy(p, &(((uint32_t *)buffer32->line[y+yy])[x]), w*4); + } + + video_blit_complete(); + + if (! updatingSize) + rfbMarkRectAsModified(rfb, 0,0, allowedX,allowedY); +} + + +static void +vnc_blit8(int x, int y, int w, int h) +{ + uint32_t *p; + int xx, yy; + + for (yy = 0; yy < h; yy++) { + p = (uint32_t *)&(((uint32_t *)rfb->frameBuffer)[yy*2048]); + + if ((y+yy) >= 0 && (y+yy) < buffer->h) { + for (xx=0; xxline[y+yy][x+xx]]; + } + } + + video_blit_complete(); + + if (! updatingSize) + rfbMarkRectAsModified(rfb, 0,0, x+w,y+h); +} + + +int +vnc_init(HWND h) +{ + static char title[128]; + rfbPixelFormat rpf = { + /* + * Screen format: + * 32bpp; 32 depth; + * little endian; + * true color; + * max 255 R/G/B; + * red shift 16; green shift 8; blue shift 0; + * padding + */ + 32, 32, 0, 1, 255,255,255, 16, 8, 0, 0, 0 + }; + + if (rfb == NULL) { + wcstombs(title, set_window_title(NULL), sizeof(title)); + updatingSize = 0; + allowedX = allowedY = 2048; + + rfb = rfbGetScreen(0, NULL, 2048, 2048, 8, 3, 4); + rfb->desktopName = title; + rfb->frameBuffer = (char *)malloc(2048 * 2048 * 4); + + rfb->serverFormat = rpf; + rfb->alwaysShared = TRUE; + rfb->displayHook = vnc_display; + rfb->kbdAddEvent = vnc_kbdevent; + rfb->newClientHook = vnc_newclient; + + rfbInitServer(rfb); + + rfbRunEventLoop(rfb, -1, TRUE); + } + + /* Set up our BLIT handlers. */ + video_setblit(vnc_blit8, vnc_blit); + + pclog("VNC: init complete.\n"); + + clients = 0; + + return(1); +} + + +void +vnc_close(void) +{ + pclog("VNC: closed.\n"); +} + + +void +vnc_resize(int x, int y) +{ + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + if (rfb == NULL) return; + + if ((x != rfb->width || y != rfb->height) && x > 160 && y > 0) { + pclog("VNC: updating resolution: %dx%d\n", x, y); + + allowedX = (rfb->width < x) ? rfb->width : x; + allowedY = (rfb->width < y) ? rfb->width : y; + + rfb->width = x; + rfb->height = y; + + iterator = rfbGetClientIterator(rfb); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) { + LOCK(cl->updateMutex); + cl->newFBSizePending = 1; + UNLOCK(cl->updateMutex); + } + } +} + + +int +vnc_pause(void) +{ + return((clients > 0) ? 0 : 1); +} + + +void +vnc_take_screenshot(wchar_t *fn) +{ + pclog("VNC: take_screenshot\n"); +} diff --git a/src/win/win_vnc.h b/src/win/win_vnc.h new file mode 100644 index 000000000..ba3d793e9 --- /dev/null +++ b/src/win/win_vnc.h @@ -0,0 +1,30 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for the VNC renderer. + * + * Version: @(#)win_vnc.h 1.0.1 2017/10/13 + * + * Authors: RichardG, + * Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen. + */ +#ifndef WIN_VNC_H +# define WIN_VNC_H + + +extern int vnc_init(HWND h); +extern void vnc_close(void); +extern void vnc_resize(int x, int y); +extern int vnc_pause(void); + +extern void vnc_take_screenshot(wchar_t *fn); + + +#endif /*WIN_VNC_H*/