From 30b903c744e5aae4d7a186b050b620fc35f24949 Mon Sep 17 00:00:00 2001 From: waltje Date: Sun, 21 Apr 2019 16:09:12 -0500 Subject: [PATCH] Many small fixes here and there. Devices now have a 'path' member, which usually points to a ROM file, or loader script. No more 'available' functions unless one is needed for special cases. Machines now can be 'configured' for mainboard settings etc. Machines are now devices as well (root devices). Regular devices now get a pointer to a 'parent' device. The machines table has been reduced to just a lookup table, machine info is now inside the machine file. Machine-specific CPU lists are now inside the machine file. Chipset implementations are now devices, and were moved to devices/chipsets/ Much work on individual machines done. All COMPAQ machines moved to dev-branch. Zenith SupersPORT moved to dev-branch. The i686-based machines (Tyan) released from dev-branch and cleaned up. Several new MFM and RLL disk controllers for XT, in dev-branch for now. --- src/config.c | 39 +- src/cpu/386.c | 4 +- src/cpu/386_dynarec.c | 6 +- src/cpu/386_ops.h | 14 +- src/cpu/808x.c | 363 ++- src/cpu/codegen.h | 5 +- src/cpu/codegen_ops.c | 5 +- src/cpu/codegen_x86.c | 6 +- src/cpu/cpu.c | 494 ++-- src/cpu/cpu.h | 171 +- src/cpu/cpu_table.c | 701 ++--- src/cpu/x86_ops.h | 10 +- src/cpu/x86seg.c | 13 +- src/cpu/x87_ops.h | 6 +- src/device.c | 87 +- src/device.h | 48 +- src/devices/cdrom/cdrom_dosbox.cpp | 18 +- .../chipsets/ali1429.c} | 114 +- src/devices/chipsets/ali1429.h | 56 + .../chipsets/headland.c} | 153 +- src/devices/chipsets/headland.h | 57 + src/devices/chipsets/intel4x0.c | 418 +++ src/devices/chipsets/intel4x0.h | 62 + .../m_at_neat.c => devices/chipsets/neat.c} | 72 +- src/devices/chipsets/neat.h | 56 + .../chipsets/opti495.c} | 123 +- src/devices/chipsets/opti495.h | 56 + src/devices/chipsets/scat.c | 1641 +++++++++++ src/devices/chipsets/scat.h | 58 + .../chipsets/sis471.c} | 51 +- src/devices/chipsets/sis471.h | 56 + .../chipsets/sis496.c} | 95 +- src/devices/chipsets/sis496.h | 56 + .../chipsets/sis50x.c} | 7 +- .../chipsets/wd76c10.c} | 73 +- src/devices/chipsets/wd76c10.h | 56 + src/devices/disk/hdc.c | 8 +- src/devices/disk/hdc_esdi_at.c | 22 +- src/devices/disk/hdc_esdi_mca.c | 10 +- src/devices/disk/hdc_ide_ata.c | 71 +- src/devices/disk/hdc_ide_xta.c | 104 +- src/devices/disk/hdc_st506_at.c | 8 +- src/devices/disk/hdc_st506_xt.c | 321 ++- src/devices/disk/hdc_xtide.c | 55 +- src/devices/floppy/fdc.c | 24 +- src/devices/floppy/fdd_86f.c | 84 +- src/devices/floppy/fdd_mfm.c | 223 +- src/devices/floppy/new/fdd_mfm.c | 521 ++++ src/devices/floppy/new/fdd_mfm.h | 26 + src/devices/input/keyboard.c | 5 +- src/devices/input/keyboard.h | 12 +- src/devices/input/keyboard_at.c | 101 +- src/devices/input/keyboard_xt.c | 227 +- src/devices/input/mouse.c | 9 +- src/devices/input/mouse.h | 6 +- src/devices/input/mouse_bus.c | 44 +- src/devices/input/mouse_ps2.c | 12 +- src/devices/input/mouse_serial.c | 23 +- src/devices/misc/bugger.c | 7 +- src/devices/misc/isamem.c | 489 ++-- src/devices/misc/isartc.c | 136 +- src/devices/network/net_3c503.c | 69 +- src/devices/network/net_ne2000.c | 296 +- src/devices/network/net_wd80x3.c | 295 +- src/devices/ports/game.c | 57 +- src/devices/ports/game.h | 6 +- src/devices/ports/parallel.c | 101 +- src/devices/ports/parallel.h | 7 +- src/devices/ports/serial.c | 123 +- src/devices/ports/serial.h | 14 +- src/devices/printer/prt_escp.c | 4 +- src/devices/scsi/scsi_aha154x.c | 71 +- src/devices/scsi/scsi_buslogic.c | 42 +- src/devices/scsi/scsi_ncr5380.c | 69 +- src/devices/scsi/scsi_ncr53c810.c | 13 +- src/devices/scsi/scsi_x54x.h | 6 +- src/devices/sio/sio_detect.c | 8 +- src/devices/sio/sio_fdc37c669.c | 14 +- src/devices/sio/sio_fdc37c66x.c | 10 +- src/devices/sio/sio_fdc37c93x.c | 14 +- src/devices/sio/sio_pc87306.c | 12 +- src/devices/sio/sio_um8669f.c | 12 +- src/devices/sio/sio_w83877f.c | 11 +- src/devices/sound/midi_fluidsynth.c | 22 +- src/devices/sound/midi_mt32.c | 14 +- src/devices/sound/midi_system.c | 8 +- src/devices/sound/resid-fp/sid.cpp | 6 +- src/devices/sound/snd_adlib.c | 152 +- src/devices/sound/snd_adlibgold.c | 10 +- src/devices/sound/snd_audiopci.c | 9 +- src/devices/sound/snd_cms.c | 8 +- src/devices/sound/snd_cs423x.c | 4 +- src/devices/sound/snd_gus.c | 7 +- src/devices/sound/snd_lpt_dac.c | 5 +- src/devices/sound/snd_lpt_dss.c | 5 +- src/devices/sound/snd_mpu401.c | 32 +- src/devices/sound/snd_pas16.c | 6 +- src/devices/sound/snd_sb.c | 1005 +++---- src/devices/sound/snd_sn76489.c | 41 +- src/devices/sound/snd_ssi2001.c | 23 +- src/devices/sound/snd_wss.c | 9 +- src/devices/system/dma.c | 3 +- src/devices/system/intel.c | 12 +- src/devices/system/intel_flash.c | 85 +- src/devices/system/intel_piix.c | 10 +- src/devices/system/intel_sio.c | 8 +- src/devices/system/mca.c | 85 +- src/devices/system/mcr.c | 5 +- src/devices/system/nvr_at.c | 14 +- src/devices/system/nvr_ps2.c | 10 +- src/devices/system/pci.c | 36 +- src/devices/system/pci.h | 10 +- src/devices/system/pic.c | 3 +- src/devices/system/pit.c | 13 +- src/devices/video/vid_ati18800.c | 51 +- src/devices/video/vid_ati28800.c | 39 +- src/devices/video/vid_ati68860_ramdac.c | 10 +- src/devices/video/vid_ati_mach64.c | 80 +- src/devices/video/vid_att20c49x_ramdac.c | 7 +- src/devices/video/vid_av9194.c | 10 +- src/devices/video/vid_bt48x_ramdac.c | 34 +- src/devices/video/vid_cga.c | 110 +- src/devices/video/vid_cga_compaq.c | 18 +- src/devices/video/vid_cl54xx.c | 243 +- src/devices/video/vid_colorplus.c | 17 +- src/devices/video/vid_ega.c | 76 +- src/devices/video/vid_et4000.c | 90 +- src/devices/video/vid_et4000w32.c | 103 +- src/devices/video/vid_genius.c | 24 +- src/devices/video/vid_hercules.c | 15 +- src/devices/video/vid_herculesplus.c | 15 +- src/devices/video/vid_icd2061.c | 13 +- src/devices/video/vid_ics2595.c | 10 +- src/devices/video/vid_im1024.c | 29 +- src/devices/video/vid_incolor.c | 13 +- src/devices/video/vid_mda.c | 35 +- src/devices/video/vid_oak_oti.c | 152 +- src/devices/video/vid_paradise.c | 613 ++-- src/devices/video/vid_pgc.c | 18 +- src/devices/video/vid_s3.c | 194 +- src/devices/video/vid_s3_virge.c | 110 +- src/devices/video/vid_sc1502x_ramdac.c | 10 +- src/devices/video/vid_sdac_ramdac.c | 10 +- src/devices/video/vid_sigma.c | 18 +- src/devices/video/vid_stg_ramdac.c | 10 +- src/devices/video/vid_svga.c | 3 +- src/devices/video/vid_tgui9440.c | 72 +- src/devices/video/vid_ti_cf62011.c | 35 +- src/devices/video/vid_tkd8001_ramdac.c | 10 +- src/devices/video/vid_tvga.c | 71 +- src/devices/video/vid_vga.c | 40 +- src/devices/video/vid_voodoo.c | 77 +- src/devices/video/vid_wy700.c | 26 +- src/devices/video/video.c | 123 +- src/devices/video/video.h | 16 +- src/devices/video/video_dev.c | 45 +- src/emu.h | 15 +- src/io.c | 6 +- src/io.h | 6 +- src/machines/m_acer.c | 247 ++ src/machines/m_ali.c | 116 + src/machines/m_amstrad.c | 2566 +++++++---------- src/machines/m_amstrad.h | 79 + src/machines/m_amstrad_vid.c | 1747 +++++++++++ src/machines/m_aopen.c | 119 + src/machines/m_asus.c | 195 ++ src/machines/m_at.c | 102 +- src/machines/m_at_4x0.c | 1004 ------- src/machines/m_at_compaq.c | 188 -- src/machines/m_at_scat.c | 1438 --------- .../{m_at_commodore.c => m_commodore.c} | 59 +- src/machines/m_compaq.c | 371 +++ src/machines/{m_xt_xi8088.h => m_compaq.h} | 33 +- src/machines/m_compaq_vid.c | 796 +++++ src/machines/m_europc.c | 207 +- src/machines/m_headland.c | 181 ++ src/machines/m_intel4x0.c | 298 ++ src/machines/m_laserxt.c | 281 ++ src/machines/m_misc.c | 315 ++ src/machines/m_neat.c | 123 + src/machines/m_olim24.c | 770 +++++ src/machines/m_olim24.h | 54 + .../{m_olivetti_m24.c => m_olim24_vid.c} | 416 +-- src/machines/m_opti495.c | 254 ++ src/machines/m_pbell.c | 116 + src/machines/m_pcjr.c | 703 ++--- src/machines/m_ps1.c | 248 +- src/machines/m_ps1.h | 64 + src/machines/m_ps1_hdc.c | 80 +- src/machines/m_ps2_isa.c | 153 +- src/machines/m_ps2_mca.c | 2107 +++++++------- src/machines/m_scat.c | 209 ++ src/machines/{m_xt_compaq.c => m_sis471.c} | 74 +- src/machines/m_sis496.c | 150 + src/machines/m_tandy.c | 2021 ------------- src/machines/m_tandy1000.c | 1055 +++++++ src/machines/m_tandy1000.h | 62 + src/machines/m_tandy1000_vid.c | 1103 +++++++ src/machines/{m_xt_t1000.c => m_tosh1x00.c} | 2271 ++++++++------- src/machines/{m_xt_t1000.h => m_tosh1x00.h} | 25 +- src/machines/m_tosh1x00_vid.c | 757 +++++ src/machines/{m_at_t3100e.c => m_tosh3100e.c} | 325 ++- src/machines/{m_at_t3100e.h => m_tosh3100e.h} | 22 +- .../{m_at_t3100e_vid.c => m_tosh3100e_vid.c} | 271 +- src/machines/m_tyan.c | 193 ++ src/machines/m_wd76c10.c | 110 + src/machines/{m_xt_xi8088.c => m_xi8088.c} | 198 +- src/machines/m_xt.c | 331 ++- src/machines/m_xt_laserxt.c | 222 -- src/machines/m_xt_t1000_vid.c | 791 ----- src/machines/m_zenith.c | 395 ++- src/machines/m_zenith.h | 49 + src/machines/m_zenith_vid.c | 687 +++++ src/machines/machine.c | 133 +- src/machines/machine.h | 365 ++- src/machines/machine_table.c | 283 +- src/mem.c | 178 +- src/mem.h | 21 +- src/pc.c | 172 +- src/random.c | 46 +- src/rom.c | 201 +- src/rom.h | 29 +- src/rom_load.c | 215 +- src/ui/lang/VARCem-KZ.str | Bin 18722 -> 30088 bytes src/ui/ui_stbar.c | 10 +- src/win/mingw/Makefile.MinGW | 242 +- src/win/msvc/Makefile.VC | 161 +- src/win/win.c | 2 + src/win/win.h | 6 +- src/win/win_d2d.cpp | 25 +- src/win/win_d3d.cpp | 7 +- src/win/win_devconf.c | 28 +- src/win/win_mouse.cpp | 20 +- src/win/win_settings.c | 22 +- src/win/win_settings_disk.h | 36 +- src/win/win_settings_floppy.h | 6 +- src/win/win_settings_input.h | 24 +- src/win/win_settings_machine.h | 72 +- src/win/win_settings_network.h | 12 +- src/win/win_settings_periph.h | 25 +- src/win/win_settings_remov.h | 6 +- src/win/win_settings_sound.h | 18 +- src/win/win_settings_video.h | 20 +- 243 files changed, 25591 insertions(+), 16979 deletions(-) rename src/{machines/m_at_ali1429.c => devices/chipsets/ali1429.c} (63%) create mode 100644 src/devices/chipsets/ali1429.h rename src/{machines/m_at_headland.c => devices/chipsets/headland.c} (89%) create mode 100644 src/devices/chipsets/headland.h create mode 100644 src/devices/chipsets/intel4x0.c create mode 100644 src/devices/chipsets/intel4x0.h rename src/{machines/m_at_neat.c => devices/chipsets/neat.c} (97%) create mode 100644 src/devices/chipsets/neat.h rename src/{machines/m_at_opti495.c => devices/chipsets/opti495.c} (87%) create mode 100644 src/devices/chipsets/opti495.h create mode 100644 src/devices/chipsets/scat.c create mode 100644 src/devices/chipsets/scat.h rename src/{machines/m_at_sis471.c => devices/chipsets/sis471.c} (86%) create mode 100644 src/devices/chipsets/sis471.h rename src/{machines/m_at_sis496.c => devices/chipsets/sis496.c} (76%) create mode 100644 src/devices/chipsets/sis496.h rename src/{machines/m_at_sis50x.c => devices/chipsets/sis50x.c} (98%) rename src/{machines/m_at_wd76c10.c => devices/chipsets/wd76c10.c} (83%) create mode 100644 src/devices/chipsets/wd76c10.h create mode 100644 src/devices/floppy/new/fdd_mfm.c create mode 100644 src/devices/floppy/new/fdd_mfm.h create mode 100644 src/machines/m_acer.c create mode 100644 src/machines/m_ali.c create mode 100644 src/machines/m_amstrad.h create mode 100644 src/machines/m_amstrad_vid.c create mode 100644 src/machines/m_aopen.c create mode 100644 src/machines/m_asus.c delete mode 100644 src/machines/m_at_4x0.c delete mode 100644 src/machines/m_at_compaq.c delete mode 100644 src/machines/m_at_scat.c rename src/machines/{m_at_commodore.c => m_commodore.c} (68%) create mode 100644 src/machines/m_compaq.c rename src/machines/{m_xt_xi8088.h => m_compaq.h} (63%) create mode 100644 src/machines/m_compaq_vid.c create mode 100644 src/machines/m_headland.c create mode 100644 src/machines/m_intel4x0.c create mode 100644 src/machines/m_laserxt.c create mode 100644 src/machines/m_misc.c create mode 100644 src/machines/m_neat.c create mode 100644 src/machines/m_olim24.c create mode 100644 src/machines/m_olim24.h rename src/machines/{m_olivetti_m24.c => m_olim24_vid.c} (60%) create mode 100644 src/machines/m_opti495.c create mode 100644 src/machines/m_pbell.c create mode 100644 src/machines/m_ps1.h create mode 100644 src/machines/m_scat.c rename src/machines/{m_xt_compaq.c => m_sis471.c} (54%) create mode 100644 src/machines/m_sis496.c delete mode 100644 src/machines/m_tandy.c create mode 100644 src/machines/m_tandy1000.c create mode 100644 src/machines/m_tandy1000.h create mode 100644 src/machines/m_tandy1000_vid.c rename src/machines/{m_xt_t1000.c => m_tosh1x00.c} (57%) rename src/machines/{m_xt_t1000.h => m_tosh1x00.h} (73%) create mode 100644 src/machines/m_tosh1x00_vid.c rename src/machines/{m_at_t3100e.c => m_tosh3100e.c} (72%) rename src/machines/{m_at_t3100e.h => m_tosh3100e.h} (77%) rename src/machines/{m_at_t3100e_vid.c => m_tosh3100e_vid.c} (73%) create mode 100644 src/machines/m_tyan.c create mode 100644 src/machines/m_wd76c10.c rename src/machines/{m_xt_xi8088.c => m_xi8088.c} (57%) delete mode 100644 src/machines/m_xt_laserxt.c delete mode 100644 src/machines/m_xt_t1000_vid.c create mode 100644 src/machines/m_zenith.h create mode 100644 src/machines/m_zenith_vid.c diff --git a/src/config.c b/src/config.c index ab179ca..eb21901 100644 --- a/src/config.c +++ b/src/config.c @@ -12,7 +12,7 @@ * it on Windows XP, and possibly also Vista. Use the * -DANSI_CFG for use on these systems. * - * Version: @(#)config.c 1.0.43 2019/02/23 + * Version: @(#)config.c 1.0.45 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -49,9 +49,9 @@ #include "emu.h" #include "config.h" #include "cpu/cpu.h" -#include "machines/machine.h" #include "nvr.h" #include "device.h" +#include "machines/machine.h" #include "devices/misc/isamem.h" #include "devices/misc/isartc.h" #include "devices/ports/game_dev.h" @@ -394,20 +394,17 @@ load_machine(const char *cat) p = config_get_string(cat, "machine", NULL); if (p != NULL) - machine = machine_get_from_internal_name(p); + machine_type = machine_get_from_internal_name(p); else - machine = -1; + machine_type = -1; + (void)machine_load(); cpu_manufacturer = config_get_int(cat, "cpu_manufacturer", 0); - cpu = config_get_int(cat, "cpu", 0); + cpu_type = 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 ((uint32_t)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 = machine_get_memsize(mem_size); cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0); @@ -415,7 +412,7 @@ load_machine(const char *cat) time_sync = config_get_int(cat, "enable_sync", -1); if (time_sync != -1) { - /* FIXME: remove this after 12/01/2018 --FvK */ + /* FIXME: remove this after 12/31/2019 --FvK */ config_delete_var(cat, "enable_sync"); } else time_sync = config_get_int(cat, "time_sync", TIME_SYNC_DISABLED); @@ -433,10 +430,10 @@ save_machine(const char *cat) else config_set_int(cat, "cpu_manufacturer", cpu_manufacturer); - if (cpu == 0) + if (cpu_type == 0) config_delete_var(cat, "cpu"); else - config_set_int(cat, "cpu", cpu); + config_set_int(cat, "cpu", cpu_type); if (cpu_waitstates == 0) config_delete_var(cat, "cpu_waitstates"); @@ -467,13 +464,13 @@ load_video(const char *cat) { char *p; - if (machines[machine].fixed_vidcard) { + if (machine->flags_fixed & MACHINE_VIDEO) { config_delete_var(cat, "video_card"); video_card = VID_INTERNAL; } else { p = config_get_string(cat, "video_card", NULL); if (p == NULL) { - if (machines[machine].flags & MACHINE_VIDEO) + if (machine->flags & MACHINE_VIDEO) p = "internal"; else p = "none"; @@ -481,9 +478,6 @@ load_video(const char *cat) video_card = video_get_video_from_internal_name(p); } - /*FXME: remove by 12/01/2018 --FvK */ - config_delete_var(cat, "video_speed"); - voodoo_enabled = !!config_get_int(cat, "voodoo", 0); } @@ -806,7 +800,7 @@ load_other(const char *cat) p = config_get_string(cat, "hdc", NULL); if (p == NULL) { - if (machines[machine].flags & MACHINE_HDC) + if (machine->flags & MACHINE_HDC) p = "internal"; else p = "none"; @@ -1466,7 +1460,8 @@ config_default(void) { int i; - cpu = 0; + cpu_manufacturer = 0; + cpu_type = 0; scale = 1; video_card = VID_CGA; vid_api = vidapi_from_internal_name("default");; @@ -1670,7 +1665,7 @@ config_load(void) config_default(); /* Flag this as an invalid configuration. */ - machine = -1; + machine_type = -1; } return(i); @@ -1701,7 +1696,7 @@ config_dump(void) while (sec != NULL) { entry_t *ent; - if (sec->name && sec->name[0]) + if (sec->name[0]) INFO("[%s]\n", sec->name); ent = (entry_t *)sec->entry_head.next; diff --git a/src/cpu/386.c b/src/cpu/386.c index fa0a552..6e6b2b0 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -8,7 +8,7 @@ * * Implementation of 80286+ CPU interpreter. * - * Version: @(#)386.c 1.0.7 2019/02/28 + * Version: @(#)386.c 1.0.8 2019/04/20 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -216,7 +216,7 @@ exec386(int cycs) pmodeint(8, 0); if (cpu_state.abrt) { cpu_state.abrt = 0; - softresetx86(); + cpu_reset(0); cpu_set_edx(); INFO("CPU: triple fault - reset\n"); } diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index bb616a1..563a820 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -8,7 +8,7 @@ * * Implementation of the CPU's dynamic recompiler. * - * Version: @(#)386_dynarec.c 1.0.7 2019/02/28 + * Version: @(#)386_dynarec.c 1.0.8 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -238,7 +238,7 @@ void x86_int(uint32_t num) if (idt.limit < 35) { cpu_state.abrt = 0; - softresetx86(); + cpu_reset(0); cpu_set_edx(); INFO("CPU: triple fault in real mode - reset\n"); } @@ -870,7 +870,7 @@ inrecomp=0; if (cpu_state.abrt) { cpu_state.abrt = 0; - softresetx86(); + cpu_reset(0); cpu_set_edx(); ERRLOG("CPU: triple fault - reset\n"); } diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 2912206..0b8fa8c 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -8,14 +8,14 @@ * * 286/386+ instruction handlers list. * - * Version: @(#)386_ops.h 1.0.3 2018/10/05 + * Version: @(#)386_ops.h 1.0.4 2019/04/11 * * Authors: Fred N. van Kempen, * Sarah Walker, * leilei, * Miran Grca, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 leilei. * Copyright 2016-2018 Miran Grca. @@ -185,9 +185,7 @@ static int ILLEGAL(uint32_t fetchdat) #include "x86_ops_jump.h" #include "x86_ops_misc.h" #include "x87_ops.h" -#if defined(DEV_BRANCH) && defined(USE_I686) -# include "x86_ops_i686.h" -#endif +#include "x86_ops_i686.h" #include "x86_ops_mmx.h" #include "x86_ops_mmx_arith.h" #include "x86_ops_mmx_cmp.h" @@ -984,8 +982,6 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; -#ifdef DEV_BRANCH -#ifdef USE_I686 const OpFn OP_TABLE(pentiumpro_0f)[1024] = { /*16-bit data, 16-bit addr*/ @@ -1077,7 +1073,6 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, }; -#if 0 const OpFn OP_TABLE(pentium2_0f)[1024] = { /*16-bit data, 16-bit addr*/ @@ -1168,7 +1163,6 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; -#endif const OpFn OP_TABLE(pentium2d_0f)[1024] = { @@ -1260,8 +1254,6 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; -#endif -#endif const OpFn OP_TABLE(286)[1024] = { diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 35d80a9..9cb4bcd 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -8,7 +8,7 @@ * * 808x CPU emulation. * - * Version: @(#)808x.c 1.0.15 2019/03/05 + * Version: @(#)808x.c 1.0.17 2019/04/20 * * Authors: Miran Grca, * Andrew Jenner (reenigne), @@ -46,7 +46,6 @@ #include "cpu.h" #include "x86.h" #include "../io.h" -#include "../machines/machine.h" #include "../devices/system/pic.h" #include "../devices/system/nmi.h" #include "../mem.h" @@ -126,12 +125,10 @@ static uint16_t cpu_data = 0; static uint32_t *ovr_seg = NULL; -int indump = 0; - - void -dumpregs(int force) +cpu_dumpregs(int force) { + static int indump = 0; char *seg_names[4] = { "ES", "CS", "SS", "DS" }; int c; @@ -179,6 +176,117 @@ dumpregs(int force) } +/* Preparation of the various arrays needed to speed up the MOD and R/M work. */ +static void +makemod1table(void) +{ + mod1add[0][0] = &BX; + mod1add[0][1] = &BX; + mod1add[0][2] = &BP; + mod1add[0][3] = &BP; + mod1add[0][4] = &SI; + mod1add[0][5] = &DI; + mod1add[0][6] = &BP; + mod1add[0][7] = &BX; + mod1add[1][0] = &SI; + mod1add[1][1] = &DI; + mod1add[1][2] = &SI; + mod1add[1][3] = &DI; + mod1add[1][4] = &zero; + mod1add[1][5] = &zero; + mod1add[1][6] = &zero; + mod1add[1][7] = &zero; + mod1seg[0] = &ds; + mod1seg[1] = &ds; + mod1seg[2] = &ss; + mod1seg[3] = &ss; + mod1seg[4] = &ds; + mod1seg[5] = &ds; + mod1seg[6] = &ss; + mod1seg[7] = &ds; + opseg[0] = &es; + opseg[1] = &cs; + opseg[2] = &ss; + opseg[3] = &ds; + _opseg[0] = &_es; + _opseg[1] = &_cs; + _opseg[2] = &_ss; + _opseg[3] = &_ds; +} + + +/* Prepare the ZNP table needed to speed up the setting of the Z, N, and P flags. */ +static void +makeznptable(void) +{ + int c, d; + for (c = 0; c < 256; c++) { + d = 0; + if (c & 1) + d++; + if (c & 2) + d++; + if (c & 4) + d++; + if (c & 8) + d++; + if (c & 16) + d++; + if (c & 32) + d++; + if (c & 64) + d++; + if (c & 128) + d++; + if (d & 1) + znptable8[c] = 0; + else + znptable8[c] = P_FLAG; + if (c == 0xb1) + DEBUG("znp8 b1 = %i %02X\n", d, znptable8[c]); + if (c == 0x65b1) + DEBUG("znp16 65b1 = %i %02X\n", d, znptable16[c]); + if (!c) + znptable8[c] |= Z_FLAG; + if (c & 0x80) + znptable8[c] |= N_FLAG; + } + + for (c = 0; c < 65536; c++) { + d = 0; + if (c & 1) + d++; + if (c & 2) + d++; + if (c & 4) + d++; + if (c & 8) + d++; + if (c & 16) + d++; + if (c & 32) + d++; + if (c & 64) + d++; + if (c & 128) + d++; + if (d & 1) + znptable16[c] = 0; + else + znptable16[c] = P_FLAG; + if (c == 0xb1) + DEBUG("znp16 b1 = %i %02X\n", d, znptable16[c]); + if (c == 0x65b1) + DEBUG("znp16 65b1 = %i %02X\n", d, znptable16[c]); + if (!c) + znptable16[c] |= Z_FLAG; + if (c & 0x8000) + znptable16[c] |= N_FLAG; + } +} + + +/* Fetches the effective address from the prefetch queue according to MOD and R/M. */ static void pfq_add(int c); static void set_pzs(int bits); @@ -348,9 +456,9 @@ pfq_write(void) read more than one byte even on the 8086. */ if (is8086 && !(pfq_ip & 1) && !(pfq_pos & 1)) { tempw = readmemwf(pfq_ip); - *(uint16_t *) &(pfq[pfq_pos]) = tempw; + pfq[pfq_pos++] = (tempw & 0xff); + pfq[pfq_pos++] = (tempw >> 8); pfq_ip += 2; - pfq_pos += 2; } else { pfq[pfq_pos] = readmembf(pfq_ip); pfq_ip++; @@ -442,46 +550,6 @@ pfq_clear(void) } -/* Preparation of the various arrays needed to speed up the MOD and R/M work. */ -static void -makemod1table(void) -{ - mod1add[0][0] = &BX; - mod1add[0][1] = &BX; - mod1add[0][2] = &BP; - mod1add[0][3] = &BP; - mod1add[0][4] = &SI; - mod1add[0][5] = &DI; - mod1add[0][6] = &BP; - mod1add[0][7] = &BX; - mod1add[1][0] = &SI; - mod1add[1][1] = &DI; - mod1add[1][2] = &SI; - mod1add[1][3] = &DI; - mod1add[1][4] = &zero; - mod1add[1][5] = &zero; - mod1add[1][6] = &zero; - mod1add[1][7] = &zero; - mod1seg[0] = &ds; - mod1seg[1] = &ds; - mod1seg[2] = &ss; - mod1seg[3] = &ss; - mod1seg[4] = &ds; - mod1seg[5] = &ds; - mod1seg[6] = &ss; - mod1seg[7] = &ds; - opseg[0] = &es; - opseg[1] = &cs; - opseg[2] = &ss; - opseg[3] = &ds; - _opseg[0] = &_es; - _opseg[1] = &_cs; - _opseg[2] = &_ss; - _opseg[3] = &_ds; -} - - -/* Fetches the effective address from the prefetch queue according to MOD and R/M. */ static void do_mod_rm(void) { @@ -619,138 +687,6 @@ seteaw(uint16_t val) } -/* Prepare the ZNP table needed to speed up the setting of the Z, N, and P flags. */ -static void -makeznptable(void) -{ - int c, d; - for (c = 0; c < 256; c++) { - d = 0; - if (c & 1) - d++; - if (c & 2) - d++; - if (c & 4) - d++; - if (c & 8) - d++; - if (c & 16) - d++; - if (c & 32) - d++; - if (c & 64) - d++; - if (c & 128) - d++; - if (d & 1) - znptable8[c] = 0; - else - znptable8[c] = P_FLAG; - if (c == 0xb1) - DEBUG("znp8 b1 = %i %02X\n", d, znptable8[c]); - if (c == 0x65b1) - DEBUG("znp16 65b1 = %i %02X\n", d, znptable16[c]); - if (!c) - znptable8[c] |= Z_FLAG; - if (c & 0x80) - znptable8[c] |= N_FLAG; - } - - for (c = 0; c < 65536; c++) { - d = 0; - if (c & 1) - d++; - if (c & 2) - d++; - if (c & 4) - d++; - if (c & 8) - d++; - if (c & 16) - d++; - if (c & 32) - d++; - if (c & 64) - d++; - if (c & 128) - d++; - if (d & 1) - znptable16[c] = 0; - else - znptable16[c] = P_FLAG; - if (c == 0xb1) - DEBUG("znp16 b1 = %i %02X\n", d, znptable16[c]); - if (c == 0x65b1) - DEBUG("znp16 65b1 = %i %02X\n", d, znptable16[c]); - if (!c) - znptable16[c] |= Z_FLAG; - if (c & 0x8000) - znptable16[c] |= N_FLAG; - } -} - - -/* Common reset function. */ -static void -reset_common(int hard) -{ - if (hard) { - INFO("x86 reset\n"); - ins = 0; - } - use32 = 0; - cpu_cur_status = 0; - stack32 = 0; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - msw = 0; - if (is486) - cr0 = 1 << 30; - else - cr0 = 0; - cpu_cache_int_enabled = 0; - cpu_update_waitstates(); - cr4 = 0; - eflags = 0; - cgate32 = 0; - if (AT) { - loadcs(0xF000); - cpu_state.pc = 0xFFF0; - rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; - } else { - loadcs(0xFFFF); - cpu_state.pc=0; - rammask = 0xfffff; - } - idt.base = 0; - idt.limit = is386 ? 0x03FF : 0xFFFF; - flags = 2; - trap = 0; - ovr_seg = NULL; - in_lock = halt = 0; - - if (hard) { - makeznptable(); - resetreadlookup(); - makemod1table(); - resetmcr(); - pfq_clear(); - cpu_set_edx(); - EAX = 0; - ESP = 0; - mmu_perm = 4; - pfq_size = (is8086) ? 6 : 4; - } - - x86seg_reset(); -#ifdef USE_DYNAREC - if (hard) - codegen_reset(); -#endif - x86_was_reset = 1; - port_92_clear_reset(); -} - - /* Pushes a word to the stack. */ static void do_push_ex(uint16_t val) @@ -2846,7 +2782,7 @@ on_halt: void refreshread(void) { - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed > 4772728) + if (cpu_get_speed() > 4772728) cpu_wait(8, 1); /* insert extra wait states */ /* @@ -2872,17 +2808,64 @@ refreshread(void) } -/* Hard reset. */ +/* Reset the CPU. */ void -resetx86(void) +cpu_reset(int hard) { - reset_common(1); -} + if (hard) { + INFO("CPU: reset\n"); + ins = 0; + } + use32 = 0; + cpu_cur_status = 0; + stack32 = 0; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + msw = 0; + if (is486) + cr0 = 1 << 30; + else + cr0 = 0; + cpu_cache_int_enabled = 0; + cpu_update_waitstates(); + cr4 = 0; + eflags = 0; + cgate32 = 0; + if (AT) { + loadcs(0xF000); + cpu_state.pc = 0xFFF0; + rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; + } else { + loadcs(0xFFFF); + cpu_state.pc=0; + rammask = 0xfffff; + } -/* Soft reset. */ -void -softresetx86(void) -{ - reset_common(0); + idt.base = 0; + idt.limit = is386 ? 0x03FF : 0xFFFF; + flags = 2; + trap = 0; + ovr_seg = NULL; + in_lock = halt = 0; + + if (hard) { + makeznptable(); + resetreadlookup(); + makemod1table(); + resetmcr(); + pfq_clear(); + cpu_set_edx(); + EAX = 0; + ESP = 0; + mmu_perm = 4; + pfq_size = (is8086) ? 6 : 4; + } + + x86seg_reset(); +#ifdef USE_DYNAREC + if (hard) + codegen_reset(); +#endif + x86_was_reset = 1; + port_92_clear_reset(); } diff --git a/src/cpu/codegen.h b/src/cpu/codegen.h index 6a53c7a..e1ffd5d 100644 --- a/src/cpu/codegen.h +++ b/src/cpu/codegen.h @@ -8,7 +8,7 @@ * * Definitions for the code generator. * - * Version: @(#)codegen.h 1.0.4 2018/11/13 + * Version: @(#)codegen.h 1.0.5 2019/03/21 * * Authors: Sarah Walker, * Miran Grca, @@ -41,9 +41,10 @@ #ifdef EMU_MEM_H # include "x86_ops.h" +//FIXME: this is wrong. use _M_xx indentifiers. #ifdef __amd64__ # include "codegen_x86-64.h" -#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _WIN32 +#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_) || defined(_M_IX86) || defined(_M_X64) # include "codegen_x86.h" # else # error Dynamic recompiler not implemented on your platform diff --git a/src/cpu/codegen_ops.c b/src/cpu/codegen_ops.c index 0786a42..498eff1 100644 --- a/src/cpu/codegen_ops.c +++ b/src/cpu/codegen_ops.c @@ -8,7 +8,7 @@ * * Instruction parsing and generation. * - * Version: @(#)codegen_ops.c 1.0.2 2018/10/24 + * Version: @(#)codegen_ops.c 1.0.3 2019/03/21 * * Authors: Sarah Walker, * Miran Grca, @@ -59,9 +59,10 @@ #endif #ifdef __GNUC__ +//FIXME: this is wrong. use the _M_xxx identifiers. # ifdef __amd64__ # include "codegen_ops_x86-64.h" /* 64-bit */ -# elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _WIN32 +#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_) || defined(_M_IX86) || defined(_M_X64) # include "codegen_ops_x86.h" /* 32-bit */ # endif #endif diff --git a/src/cpu/codegen_x86.c b/src/cpu/codegen_x86.c index 31f2aea..3a012f0 100644 --- a/src/cpu/codegen_x86.c +++ b/src/cpu/codegen_x86.c @@ -8,13 +8,13 @@ * * Dynamic Recompiler for Intel 32-bit systems. * - * Version: @(#)codegen_x86.c 1.0.4 2018/09/22 + * Version: @(#)codegen_x86.c 1.0.5 2019/03/21 * * Authors: Fred N. van Kempen, * Sarah Walker, * Miran Grca, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. * @@ -36,7 +36,7 @@ * Boston, MA 02111-1307 * USA. */ -#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _WIN32 +#if defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_) || defined(_M_IX86) || defined(_M_X64) #include #include diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 6e0ee17..61f3da6 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -8,7 +8,7 @@ * * CPU type handler. * - * Version: @(#)cpu.c 1.0.10 2019/02/17 + * Version: @(#)cpu.c 1.0.11 2019/04/11 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -16,9 +16,9 @@ * Miran Grca, * * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 leilei. - * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,7 +45,6 @@ #include "../emu.h" #include "cpu.h" #include "../device.h" -#include "../machines/machine.h" #include "../io.h" #include "x86.h" #include "x86_ops.h" @@ -71,6 +70,26 @@ enum { }; +const OpFn *x86_opcodes; +const OpFn *x86_opcodes_0f; +const OpFn *x86_opcodes_d8_a16; +const OpFn *x86_opcodes_d8_a32; +const OpFn *x86_opcodes_d9_a16; +const OpFn *x86_opcodes_d9_a32; +const OpFn *x86_opcodes_da_a16; +const OpFn *x86_opcodes_da_a32; +const OpFn *x86_opcodes_db_a16; +const OpFn *x86_opcodes_db_a32; +const OpFn *x86_opcodes_dc_a16; +const OpFn *x86_opcodes_dc_a32; +const OpFn *x86_opcodes_dd_a16; +const OpFn *x86_opcodes_dd_a32; +const OpFn *x86_opcodes_de_a16; +const OpFn *x86_opcodes_de_a32; +const OpFn *x86_opcodes_df_a16; +const OpFn *x86_opcodes_df_a32; +const OpFn *x86_opcodes_REPE; +const OpFn *x86_opcodes_REPNE; #ifdef USE_DYNAREC const OpFn *x86_dynarec_opcodes; const OpFn *x86_dynarec_opcodes_0f; @@ -94,34 +113,10 @@ const OpFn *x86_dynarec_opcodes_REPE; const OpFn *x86_dynarec_opcodes_REPNE; #endif -const OpFn *x86_opcodes; -const OpFn *x86_opcodes_0f; -const OpFn *x86_opcodes_d8_a16; -const OpFn *x86_opcodes_d8_a32; -const OpFn *x86_opcodes_d9_a16; -const OpFn *x86_opcodes_d9_a32; -const OpFn *x86_opcodes_da_a16; -const OpFn *x86_opcodes_da_a32; -const OpFn *x86_opcodes_db_a16; -const OpFn *x86_opcodes_db_a32; -const OpFn *x86_opcodes_dc_a16; -const OpFn *x86_opcodes_dc_a32; -const OpFn *x86_opcodes_dd_a16; -const OpFn *x86_opcodes_dd_a32; -const OpFn *x86_opcodes_de_a16; -const OpFn *x86_opcodes_de_a32; -const OpFn *x86_opcodes_df_a16; -const OpFn *x86_opcodes_df_a32; -const OpFn *x86_opcodes_REPE; -const OpFn *x86_opcodes_REPNE; -CPU *cpu_s; -int cpu_effective; -int cpu_multi; -int cpu_16bitbus; int cpu_busspeed; +int cpu_16bitbus; int cpu_cyrix_alignment; -int cpuspeed; int CPUID; uint64_t cpu_CR4_mask; int isa_cycles; @@ -142,14 +137,12 @@ int is186, /* 80186 */ is_rapidcad, /* RapidCAD */ is_pentium; /* Pentium+ */ -int hasfpu, - cpu_hasrdtsc, +int cpu_hasrdtsc, cpu_hasMMX, cpu_hasMSR, cpu_hasCR4, cpu_hasVME; - uint64_t tsc = 0; msr_t msr; cr0_t CR0; @@ -157,7 +150,7 @@ uint64_t pmc[2] = {0, 0}; uint16_t temp_seg_data[4] = {0, 0, 0, 0}; -#if defined(DEV_BRANCH) && defined(USE_I686) +/* Variables for the 686+ processors. */ uint16_t cs_msr = 0; uint32_t esp_msr = 0; uint32_t eip_msr = 0; @@ -182,9 +175,9 @@ uint64_t ecx186_msr = 0; uint64_t ecx187_msr = 0; uint64_t ecx1e0_msr = 0; uint64_t ecx570_msr = 0; -#endif #if defined(DEV_BRANCH) && defined(USE_AMD_K) +/* Variables for the AMD "K" processors. */ uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */ uint64_t star = 0; /* These are K6-only. */ uint64_t sfmask = 0; @@ -206,96 +199,83 @@ int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; int timing_misaligned; +static const CPU *cpu_list, + *cpu = NULL; +static int cpu_turbo = -1, + cpu_effective = -1; + static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6; +static int cyrix_addr; -void -cpu_dynamic_switch(int new_cpu) +/* + * Actually do the 'setup' work. + * + * Given the currently-selected CPU from the list the machine + * has provided us with, perform all actions needed to make it + * the active CPU. + */ +static void +cpu_activate(void) { - int c = cpu; + int hasfpu; - if (cpu_effective == new_cpu) - return; + /* Select the desired CPU and/or speed. */ + cpu = &cpu_list[cpu_effective]; + INFO("CPU: %s [%i] speed=%lu\n", cpu->name, cpu_effective, cpu->rspeed); - cpu = new_cpu; - cpu_set(); - pc_speed_changed(); - cpu = c; -} - - -void -cpu_set_edx(void) -{ - EDX = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].edx_reset; -} - - -void -cpu_set(void) -{ - if (! machines[machine].cpu[cpu_manufacturer].cpus) { - /*CPU is invalid, set to default*/ - cpu_manufacturer = 0; - cpu = 0; - } - - cpu_effective = cpu; - cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective]; - - CPUID = cpu_s->cpuid_model; - cpuspeed = cpu_s->speed; - is8086 = (cpu_s->cpu_type > CPU_8088); - is_nec = (cpu_s->cpu_type == CPU_NEC); - is186 = (cpu_s->cpu_type == CPU_186); - is286 = (cpu_s->cpu_type >= CPU_286); - is386 = (cpu_s->cpu_type >= CPU_386SX); - is_rapidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); - is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD); - is_cyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1); - is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP); - hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); - DEBUG("CPU: manuf=%d model=%d, cpuid=%08lx speed=%lu\n", - cpu_manufacturer, cpu_effective, CPUID, cpuspeed); - DEBUG(" 8086=%d nec=%d 186=%d 286=%d 386=%d rcad=%d cyrix=%d 486=%d pent=%d\n", + CPUID = cpu->cpuid_model; + is8086 = (cpu->type > CPU_8088); + is_nec = (cpu->type == CPU_NEC); + is186 = (cpu->type == CPU_186); + is286 = (cpu->type >= CPU_286); + is386 = (cpu->type >= CPU_386SX); + is_rapidcad = (cpu->type == CPU_RAPIDCAD); + is486 = ((cpu->type >= CPU_i486SX) || (cpu->type == CPU_486SLC) || \ + (cpu->type == CPU_486DLC) || (cpu->type == CPU_RAPIDCAD)); + is_cyrix = ((cpu->type == CPU_486SLC) || (cpu->type == CPU_486DLC) || \ + (cpu->type == CPU_Cx486S) || (cpu->type == CPU_Cx486DX) || \ + (cpu->type == CPU_Cx5x86) || (cpu->type == CPU_Cx6x86) || \ + (cpu->type == CPU_Cx6x86MX) || (cpu->type == CPU_Cx6x86L) || \ + (cpu->type == CPU_CxGX1)); + is_pentium = (cpu->type >= CPU_WINCHIP); + hasfpu = (cpu->type >= CPU_i486DX) || (cpu->type == CPU_RAPIDCAD); + DEBUG("CPU: manuf=%i model=%i cpuid=%08lx\n", + cpu_manufacturer, cpu_effective, CPUID); + DEBUG(" 8086=%i nec=%i 186=%i 286=%i 386=%i rcad=%i cyrix=%i 486=%i pent=%i\n", is8086,is_nec,is186,is286,is386,is_rapidcad,is_cyrix,is486,is_pentium); - DEBUG(" hasfpu=%d\n", hasfpu); + DEBUG(" hasfpu=%i\n", hasfpu); + + cpu_16bitbus = ((cpu->type == CPU_286) || \ + (cpu->type == CPU_386SX) || \ + (cpu->type == CPU_486SLC)); + if (cpu->multi) + cpu_busspeed = cpu->rspeed / cpu->multi; - cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC); - if (cpu_s->multi) - cpu_busspeed = cpu_s->rspeed / cpu_s->multi; - cpu_multi = cpu_s->multi; cpu_hasrdtsc = 0; cpu_hasMMX = 0; cpu_hasMSR = 0; cpu_hasCR4 = 0; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; - if ((cpu_s->cpu_type == CPU_286) || - (cpu_s->cpu_type == CPU_386SX) || - (cpu_s->cpu_type == CPU_386DX) || - (cpu_s->cpu_type == CPU_i486SX)) { + if ((cpu->type == CPU_286) || (cpu->type == CPU_386SX) || + (cpu->type == CPU_386DX) || (cpu->type == CPU_i486SX)) { if (enable_external_fpu) hasfpu = 1; } cpu_update_waitstates(); - isa_cycles = cpu_s->atclk_div; + isa_cycles = cpu->atclk_div; //FIXME: will have to use new cpu_speed variable! --FvK - if (cpu_s->rspeed <= 8000000) + if (cpu->rspeed <= 8000000) cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; else - cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000; + cpu_rom_prefetch_cycles = cpu->rspeed / 1000000; - if (cpu_s->pci_speed) { - pci_nonburst_time = 4*cpu_s->rspeed / cpu_s->pci_speed; - pci_burst_time = cpu_s->rspeed / cpu_s->pci_speed; - } else { - pci_nonburst_time = 4; - pci_burst_time = 1; - } + /* Set the PCI bus speed(s). */ + pci_set_speed(cpu->fsb_speed); if (is_cyrix) io_sethandler(0x0022, 2, @@ -396,7 +376,7 @@ cpu_set(void) timing_misaligned = 0; cpu_cyrix_alignment = 0; - switch (cpu_s->cpu_type) { + switch (cpu->type) { case CPU_8088: case CPU_8086: case CPU_NEC: @@ -892,7 +872,7 @@ cpu_set(void) #endif break; - case CPU_PENTIUMMMX: + case CPU_PENTIUM_MMX: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); #else @@ -1174,9 +1154,8 @@ cpu_set(void) break; #endif -#if defined(DEV_BRANCH) && defined(USE_I686) - case CPU_PENTIUMPRO: -# ifdef USE_DYNAREC + case CPU_PENTIUM_PRO: +#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; @@ -1184,9 +1163,9 @@ cpu_set(void) 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 +#else x86_setopcodes(ops_386, ops_pentiumpro_0f); -# endif +#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; @@ -1211,14 +1190,14 @@ cpu_set(void) 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 +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); -# endif +#endif break; -#if 0 - case CPU_PENTIUM2: -# ifdef USE_DYNAREC +#if 1 + case CPU_PENTIUM_2: +#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; @@ -1226,9 +1205,9 @@ cpu_set(void) 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 +#else x86_setopcodes(ops_386, ops_pentium2_0f); -# endif +#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; @@ -1253,14 +1232,14 @@ cpu_set(void) 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 +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); -# endif +#endif break; #endif - case CPU_PENTIUM2D: -# ifdef USE_DYNAREC + case CPU_PENTIUM_2D: +#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; @@ -1268,9 +1247,9 @@ cpu_set(void) 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 +#else x86_setopcodes(ops_386, ops_pentium2d_0f); -# endif +#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; @@ -1295,18 +1274,162 @@ cpu_set(void) 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 +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); -# endif - break; #endif + break; default: - fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type); + fatal("CPU setup: unknown CPU type %i\n", cpu->type); + /*NOTREACHED*/ } } +/* + * Select the CPU to use. + * + * We get a pointer to the list of CPUs supported by the machine, + * and an index to the currently-selected one. Although one usually + * does not change a CPU on the fly (please, don't try this at home) + * it is implemented this way because it currently is the only way + * to change the operating speed of the selected CPU. + * + * We assume that the 'default' CPU we get called with, is the one + * that runs at highest possible speed, and that index 0 will be + * the lowest possible speed. + * + * In the future, this will be changed. + */ +void +cpu_set_type(const CPU *list, int type) +{ + if (list == NULL) { + fatal("CPU: invalid CPU list, aborting!\n"); + /*NOTREACHED*/ + } + cpu_list = list; + + /* The 'turbo' speed is the one we got called with. */ + cpu_turbo = type; + + /* For now, the selected CPU/speed is the effective one. */ + cpu_effective = cpu_turbo; + + /* Activate the selected CPU. */ + cpu_activate(); +} + + +/* Return the type of the currently-selected CPU. */ +int +cpu_get_type(void) +{ + return(cpu->type); +} + + +/* Return the name of the currently-selected CPU. */ +const char * +cpu_get_name(void) +{ + return(cpu->name); +} + + +/* Return the flags for the currently-selected CPU. */ +int +cpu_get_flags(void) +{ + return(cpu->flags); +} + + +/* + * Select a new operating speed for the currently-selected CPU. + * + * As described above, for now this means actually selecting a + * different CPU from the list, as the CPUs are listed by speed. + * + * This will change in the near future. + */ +int +cpu_set_speed(int new_speed) +{ + int old_speed = cpu_effective; + + if (cpu_effective == new_speed) + return(old_speed); + + /* Update the effective CPU type. */ + cpu_effective = new_speed; + + /* Activate the selected CPU. */ + cpu_activate(); + + return(old_speed); +} + + +/* Return the operating speed of the currently-selected CPU. */ +uint32_t +cpu_get_speed(void) +{ + return(cpu->rspeed); +} + + +void +cpu_update_waitstates(void) +{ + if (is486) + cpu_prefetch_width = 16; + else + cpu_prefetch_width = cpu_16bitbus ? 2 : 4; + + if (cpu_cache_int_enabled) { + /* Disable prefetch emulation */ + cpu_prefetch_cycles = 0; + } else if (cpu_waitstates && (cpu->type >= CPU_286 && cpu->type <= CPU_386DX)) { + /* Waitstates override */ + cpu_prefetch_cycles = cpu_waitstates+1; + cpu_cycles_read = cpu_waitstates+1; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); + cpu_cycles_write = cpu_waitstates+1; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); + } else if (cpu_cache_ext_enabled) { + /* Use cache timings */ + cpu_prefetch_cycles = cpu->cache_read_cycles; + cpu_cycles_read = cpu->cache_read_cycles; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu->cache_read_cycles; + cpu_cycles_write = cpu->cache_write_cycles; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu->cache_write_cycles; + } else { + /* Use memory timings */ + cpu_prefetch_cycles = cpu->mem_read_cycles; + cpu_cycles_read = cpu->mem_read_cycles; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu->mem_read_cycles; + cpu_cycles_write = cpu->mem_write_cycles; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu->mem_write_cycles; + } + + if (is486) + cpu_prefetch_cycles = (cpu_prefetch_cycles * 11) / 16; + + cpu_mem_prefetch_cycles = cpu_prefetch_cycles; + + if (cpu->rspeed <= 8000000) + cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; +} + + +void +cpu_set_edx(void) +{ + EDX = cpu->edx_reset; +} + + char * cpu_current_pc(char *bufp) { @@ -1324,7 +1447,7 @@ cpu_current_pc(char *bufp) void cpu_CPUID(void) { - switch (machine_type()) { + switch (cpu->type) { case CPU_i486DX: if (! EAX) { EAX = 0x00000001; @@ -1514,7 +1637,7 @@ cpu_CPUID(void) break; #endif - case CPU_PENTIUMMMX: + case CPU_PENTIUM_MMX: if (! EAX) { EAX = 0x00000001; EBX = 0x756e6547; @@ -1584,8 +1707,7 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; -#if defined(DEV_BRANCH) && defined(USE_I686) - case CPU_PENTIUMPRO: + case CPU_PENTIUM_PRO: if (! EAX) { EAX = 0x00000002; EBX = 0x756e6547; @@ -1601,8 +1723,8 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; -# if 0 - case CPU_PENTIUM2: +#if 1 + case CPU_PENTIUM_2: if (! EAX) { EAX = 0x00000002; EBX = 0x756e6547; @@ -1620,9 +1742,9 @@ cpu_CPUID(void) else EAX = EBX = ECX = EDX = 0; break; -# endif +#endif - case CPU_PENTIUM2D: + case CPU_PENTIUM_2D: if (! EAX) { EAX = 0x00000002; EBX = 0x756e6547; @@ -1639,7 +1761,6 @@ cpu_CPUID(void) } else EAX = EBX = ECX = EDX = 0; break; -#endif } } @@ -1647,7 +1768,7 @@ cpu_CPUID(void) void cpu_RDMSR(void) { - switch (machine_type()) { + switch (cpu->type) { case CPU_WINCHIP: EAX = EDX = 0; switch (ECX) { @@ -1678,7 +1799,7 @@ cpu_RDMSR(void) break; case 0x10a: - EAX = cpu_multi & 3; + EAX = cpu->multi & 3; break; } break; @@ -1721,7 +1842,7 @@ cpu_RDMSR(void) #endif case CPU_PENTIUM: - case CPU_PENTIUMMMX: + case CPU_PENTIUM_MMX: EAX = EDX = 0; switch (ECX) { case 0x10: @@ -1743,9 +1864,9 @@ cpu_RDMSR(void) } break; -#if defined(DEV_BRANCH) && defined(USE_I686) - case CPU_PENTIUMPRO: - case CPU_PENTIUM2D: + case CPU_PENTIUM_PRO: + case CPU_PENTIUM_2: + case CPU_PENTIUM_2D: EAX = EDX = 0; switch (ECX) { case 0x10: @@ -1754,7 +1875,7 @@ cpu_RDMSR(void) break; case 0x17: - if (machine_type() != CPU_PENTIUM2D) + if (cpu->type != CPU_PENTIUM_2D) goto i686_invalid_rdmsr; EAX = ecx17_msr & 0xffffffff; EDX = ecx17_msr >> 32; @@ -1806,20 +1927,20 @@ cpu_RDMSR(void) break; case 0x174: - if (machine_type() == CPU_PENTIUMPRO) + if (cpu->type == CPU_PENTIUM_PRO) goto i686_invalid_rdmsr; EAX &= 0xFFFF0000; EAX |= cs_msr; break; case 0x175: - if (machine_type() == CPU_PENTIUMPRO) + if (cpu->type == CPU_PENTIUM_PRO) goto i686_invalid_rdmsr; EAX = esp_msr; break; case 0x176: - if (machine_type() == CPU_PENTIUMPRO) + if (cpu->type == CPU_PENTIUM_PRO) goto i686_invalid_rdmsr; EAX = eip_msr; break; @@ -1891,14 +2012,14 @@ i686_invalid_rdmsr: break; } break; -#endif } } -void cpu_WRMSR(void) +void +cpu_WRMSR(void) { - switch (machine_type()) { + switch (cpu->type) { case CPU_WINCHIP: switch (ECX) { case 0x02: @@ -1923,7 +2044,7 @@ void cpu_WRMSR(void) if (EAX & (1 << 29)) CPUID = 0; else - CPUID = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpuid_model; + CPUID = cpu->cpuid_model; break; case 0x108: @@ -1965,7 +2086,7 @@ void cpu_WRMSR(void) #endif case CPU_PENTIUM: - case CPU_PENTIUMMMX: + case CPU_PENTIUM_MMX: switch (ECX) { case 0x10: tsc = EAX | ((uint64_t)EDX << 32); @@ -1984,16 +2105,16 @@ void cpu_WRMSR(void) } break; -#if defined(DEV_BRANCH) && defined(USE_I686) - case CPU_PENTIUMPRO: - case CPU_PENTIUM2D: + case CPU_PENTIUM_PRO: + case CPU_PENTIUM_2: + case CPU_PENTIUM_2D: switch (ECX) { case 0x10: tsc = EAX | ((uint64_t)EDX << 32); break; case 0x17: - if (machine_type() != CPU_PENTIUM2D) + if (cpu->type != CPU_PENTIUM_2D) goto i686_invalid_wrmsr; ecx17_msr = EAX | ((uint64_t)EDX << 32); break; @@ -2031,19 +2152,19 @@ void cpu_WRMSR(void) break; case 0x174: - if (machine_type() == CPU_PENTIUMPRO) + if (cpu->type == CPU_PENTIUM_PRO) goto i686_invalid_wrmsr; cs_msr = EAX & 0xFFFF; break; case 0x175: - if (machine_type() == CPU_PENTIUMPRO) + if (cpu->type == CPU_PENTIUM_PRO) goto i686_invalid_wrmsr; esp_msr = EAX; break; case 0x176: - if (machine_type() == CPU_PENTIUMPRO) + if (cpu->type == CPU_PENTIUM_PRO) goto i686_invalid_wrmsr; eip_msr = EAX; break; @@ -2102,18 +2223,14 @@ i686_invalid_wrmsr: break; } break; -#endif } } -static int cyrix_addr; void cyrix_write(uint16_t addr, uint8_t val, void *priv) { - if (! (addr & 1)) - cyrix_addr = val; - else switch (cyrix_addr) { + if (addr & 1) switch (cyrix_addr) { case 0xc0: /*CCR0*/ ccr0 = val; break; @@ -2133,9 +2250,9 @@ cyrix_write(uint16_t addr, uint8_t val, void *priv) case 0xe8: /*CCR4*/ if ((ccr3 & 0xf0) == 0x10) { ccr4 = val; - if (machine_type() >= CPU_Cx6x86) { + if (cpu->type >= CPU_Cx6x86) { if (val & 0x80) - CPUID = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpuid_model; + CPUID = cpu->cpuid_model; else CPUID = 0; } @@ -2151,7 +2268,8 @@ cyrix_write(uint16_t addr, uint8_t val, void *priv) if ((ccr3 & 0xf0) == 0x10) ccr6 = val; break; - } + } else + cyrix_addr = val; } @@ -2167,13 +2285,15 @@ cyrix_read(uint16_t addr, void *priv) case 0xe8: return ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff; case 0xe9: return ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff; case 0xea: return ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff; - case 0xfe: return machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cyrix_id & 0xff; - case 0xff: return machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cyrix_id >> 8; + case 0xfe: return cpu->cyrix_id & 0xff; + case 0xff: return cpu->cyrix_id >> 8; } if ((cyrix_addr & 0xf0) == 0xc0) return 0xff; - if (cyrix_addr == 0x20 && machine_type() == CPU_Cx5x86) return 0xff; + + if (cyrix_addr == 0x20 && cpu->type == CPU_Cx5x86) + return 0xff; } return 0xff; @@ -2197,49 +2317,3 @@ x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f) x86_opcodes_0f = opcodes_0f; } #endif - - -void -cpu_update_waitstates(void) -{ - cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective]; - - if (is486) - cpu_prefetch_width = 16; - else - cpu_prefetch_width = cpu_16bitbus ? 2 : 4; - - if (cpu_cache_int_enabled) { - /* Disable prefetch emulation */ - cpu_prefetch_cycles = 0; - } else if (cpu_waitstates && (cpu_s->cpu_type >= CPU_286 && cpu_s->cpu_type <= CPU_386DX)) { - /* Waitstates override */ - cpu_prefetch_cycles = cpu_waitstates+1; - cpu_cycles_read = cpu_waitstates+1; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); - cpu_cycles_write = cpu_waitstates+1; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); - } else if (cpu_cache_ext_enabled) { - /* Use cache timings */ - cpu_prefetch_cycles = cpu_s->cache_read_cycles; - cpu_cycles_read = cpu_s->cache_read_cycles; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_read_cycles; - cpu_cycles_write = cpu_s->cache_write_cycles; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_write_cycles; - } else { - /* Use memory timings */ - cpu_prefetch_cycles = cpu_s->mem_read_cycles; - cpu_cycles_read = cpu_s->mem_read_cycles; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_read_cycles; - cpu_cycles_write = cpu_s->mem_write_cycles; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_write_cycles; - } - - if (is486) - cpu_prefetch_cycles = (cpu_prefetch_cycles * 11) / 16; - - cpu_mem_prefetch_cycles = cpu_prefetch_cycles; - - if (cpu_s->rspeed <= 8000000) - cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; -} diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 7ee5707..0198369 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -6,14 +6,16 @@ * * This file is part of the VARCem Project. * - * CPU type handler. + * Definitions for the CPU module. * - * Version: @(#)cpu.h 1.0.9 2019/02/17 + * Version: @(#)cpu.h 1.0.10 2019/04/20 * - * Authors: Sarah Walker, - * leilei, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, + * leilei, * + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 leilei. @@ -40,6 +42,17 @@ # define EMU_CPU_H +/* Supported CPU manufacturers. */ +#define MANU_INTEL 0 +#define MANU_AMD 1 +#define MANU_CYRIX 2 +#define MANU_IDT 3 +#define MANU_NEC 4 + +/* + * Supported CPU types. + * FIXME: We should encode the CPU class in the ID's. + */ #define CPU_8088 0 /* 808x class CPUs */ #define CPU_8086 1 #define CPU_NEC 2 /* NEC V20 or V30 */ @@ -60,31 +73,17 @@ #define CPU_Cx5x86 17 #define CPU_WINCHIP 18 /* 586 class CPUs */ #define CPU_PENTIUM 19 -#define CPU_PENTIUMMMX 20 +#define CPU_PENTIUM_MMX 20 #define CPU_Cx6x86 21 #define CPU_Cx6x86MX 22 #define CPU_Cx6x86L 23 #define CPU_CxGX1 24 -#if defined(DEV_BRANCH) && defined(USE_AMD_K) #define CPU_K5 25 #define CPU_5K86 26 #define CPU_K6 27 -#endif -#if defined(DEV_BRANCH) && defined(USE_I686) -#define CPU_PENTIUMPRO 28 /* 686 class CPUs */ -#if 0 -# define CPU_PENTIUM2 29 -# define CPU_PENTIUM2D 30 -#else -# define CPU_PENTIUM2D 29 -#endif -#endif - -#define MANU_INTEL 0 -#define MANU_AMD 1 -#define MANU_CYRIX 2 -#define MANU_IDT 3 -#define MANU_NEC 4 +#define CPU_PENTIUM_PRO 28 /* 686 class CPUs */ +#define CPU_PENTIUM_2 29 +#define CPU_PENTIUM_2D 30 #define CPU_SUPPORTS_DYNAREC 1 #define CPU_REQUIRES_DYNAREC 2 @@ -93,49 +92,59 @@ typedef struct { const char *name; - int cpu_type; - int speed; + int type; + uint32_t rspeed; int multi; - int pci_speed; + int fsb_speed; + uint32_t edx_reset; uint32_t cpuid_model; uint16_t cyrix_id; - int cpu_flags; - int mem_read_cycles, mem_write_cycles; - int cache_read_cycles, cache_write_cycles; + + int flags; + + int mem_read_cycles, + mem_write_cycles; + int cache_read_cycles, + cache_write_cycles; + int atclk_div; } CPU; -extern CPU cpus_8088[]; -extern CPU cpus_8086[]; -extern CPU cpus_nec[]; -extern CPU cpus_186[]; -extern CPU cpus_286[]; -extern CPU cpus_i386SX[]; -extern CPU cpus_i386DX[]; -extern CPU cpus_Am386SX[]; -extern CPU cpus_Am386DX[]; -extern CPU cpus_486SLC[]; -extern CPU cpus_486DLC[]; -extern CPU cpus_i486[]; -extern CPU cpus_Am486[]; -extern CPU cpus_Cx486[]; -extern CPU cpus_WinChip[]; -extern CPU cpus_Pentium5V[]; -extern CPU cpus_Pentium5V50[]; -extern CPU cpus_PentiumS5[]; + +extern const CPU cpus_8088[]; +extern const CPU cpus_8086[]; +extern const CPU cpus_nec[]; +extern const CPU cpus_186[]; +extern const CPU cpus_286[]; +extern const CPU cpus_i386SX[]; +extern const CPU cpus_i386DX[]; +extern const CPU cpus_Am386SX[]; +extern const CPU cpus_Am386DX[]; +extern const CPU cpus_486SLC[]; +extern const CPU cpus_486DLC[]; +extern const CPU cpus_i486[]; +extern const CPU cpus_Am486[]; +extern const CPU cpus_Cx486[]; +extern const CPU cpus_WinChip[]; +extern const CPU cpus_Pentium5V[]; +extern const CPU cpus_Pentium5V50[]; +extern const CPU cpus_PentiumS5[]; #if defined(DEV_BRANCH) && defined(USE_AMD_K) -extern CPU cpus_K5[]; -extern CPU cpus_K56[]; -#endif -extern CPU cpus_Pentium[]; -extern CPU cpus_6x86[]; -#if defined(DEV_BRANCH) && defined(USE_I686) -extern CPU cpus_PentiumPro[]; -extern CPU cpus_Pentium2[]; -extern CPU cpus_Pentium2D[]; +extern const CPU cpus_K5[]; +extern const CPU cpus_K56[]; +# define CPU_AMD_K5 {"AMD",cpus_K5} +# define CPU_AMD_K56 {"AMD",cpus_K56} +#else +# define CPU_AMD_K5 {"",NULL} +# define CPU_AMD_K56 {"",NULL} #endif +extern const CPU cpus_Pentium[]; +extern const CPU cpus_6x86[]; +extern const CPU cpus_PentiumPro[]; +extern const CPU cpus_Pentium2[]; +extern const CPU cpus_Pentium2D[]; #define C_FLAG 0x0001 @@ -158,9 +167,9 @@ extern CPU cpus_Pentium2D[]; #define CR4_PVI (1 << 1) #define CR4_PSE (1 << 4) -#define CPL ((_cs.access>>5)&3) -#define IOPL ((flags>>12)&3) -#define IOPLp ((!(msw&1)) || (CPL<=IOPL)) +#define CPL ((_cs.access>>5)&3) +#define IOPL ((flags>>12)&3) +#define IOPLp ((!(msw&1)) || (CPL<=IOPL)) typedef union { @@ -321,15 +330,14 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128) /* Global variables. */ -extern int xt_cpu_multi; -extern int cpu_16bitbus; extern int cpu_busspeed; +extern int cpu_16bitbus; +extern int xt_cpu_multi; extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ extern int is8086, is186, is286, is386, is486; extern int is_nec, is_rapidcad, is_cyrix, is_pentium; -extern int hasfpu; extern int cpu_hasrdtsc; extern int cpu_hasMSR; extern int cpu_hasMMX; @@ -340,7 +348,6 @@ extern uint32_t cpu_cur_status; extern uint64_t cpu_CR4_mask; extern uint64_t tsc; extern msr_t msr; -extern int cpuspeed; extern int cycles_lost; extern uint8_t opcode; extern int fpucount; @@ -349,11 +356,10 @@ extern int cgate16; extern int cpl_override; extern int CPUID; extern int isa_cycles; -extern int cpu_effective; extern uint16_t flags,eflags; extern uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; -extern int ins,output; +extern int ins; // FIXME: get rid of this! extern int cycdiff; extern uint32_t pccache; extern uint8_t *pccache2; @@ -424,29 +430,27 @@ extern int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; extern int timing_misaligned; -extern CPU cpus_pcjr[]; // FIXME: should be in machine file! -extern CPU cpus_europc[]; // FIXME: should be in machine file! -extern CPU cpus_pc1512[]; // FIXME: should be in machine file! -extern CPU cpus_ibmat[]; // FIXME: should be in machine file! -extern CPU cpus_ibmxt286[]; // FIXME: should be in machine file! -extern CPU cpus_ps1_m2011[]; // FIXME: should be in machine file! -extern CPU cpus_ps2_m30_286[]; // FIXME: should be in machine file! -#if 0 -extern CPU cpus_acer[]; // FIXME: should be in machine file! -#endif - - /* Functions. */ extern void cyrix_write(uint16_t addr, uint8_t val, void *priv); extern uint8_t cyrix_read(uint16_t addr, void *priv); extern void loadseg(uint16_t seg, x86seg *s); extern void loadcs(uint16_t seg); -extern char *cpu_current_pc(char *bufp); -extern void cpu_dynamic_switch(int new_cpu); - +extern void cpu_set_type(const CPU *list, int type); +extern int cpu_get_type(void); +extern const char *cpu_get_name(void); +extern int cpu_set_speed(int new_speed); +extern uint32_t cpu_get_speed(void); +extern int cpu_get_flags(void); extern void cpu_update_waitstates(void); -extern void cpu_set(void); +extern char *cpu_current_pc(char *bufp); +extern void cpu_set_edx(void); +extern void cpu_reset(int hard); +extern void cpu_dumpregs(int __force); + +extern void execx86(int cycs); +extern void exec386(int cycs); +extern void exec386_dynarec(int cycs); extern void cpu_CPUID(void); extern void cpu_RDMSR(void); @@ -455,12 +459,7 @@ extern void cpu_WRMSR(void); extern int checkio(uint32_t port); extern void codegen_block_end(void); extern void codegen_reset(void); -extern void cpu_set_edx(void); extern int divl(uint32_t val); -extern void dumpregs(int __force); -extern void execx86(int cycs); -extern void exec386(int cycs); -extern void exec386_dynarec(int cycs); extern int idivl(int32_t val); extern void loadcscall(uint16_t seg); extern void loadcsjmp(uint16_t seg, uint32_t oxpc); @@ -468,10 +467,8 @@ extern void pmodeint(int num, int soft); extern void pmoderetf(int is32, uint16_t off); extern void pmodeiret(int is32); extern void resetmcr(void); -extern void resetx86(void); extern void refreshread(void); extern void resetreadlookup(void); -extern void softresetx86(void); extern void x86_int_sw(uint32_t num); extern int x86_int_sw_rm(int num); extern void x86gpf(char *s, uint16_t error); diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 80fb164..9200d72 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -8,7 +8,7 @@ * * Define all known processor types. * - * Version: @(#)cpu_table.c 1.0.7 2019/02/11 + * Version: @(#)cpu_table.c 1.0.8 2019/04/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,440 +42,369 @@ #include #include "../emu.h" #include "cpu.h" -#include "../machines/machine.h" -CPU cpus_8088[] = { - /*8088 standard*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/10", CPU_8088, 1, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/12", CPU_8088, 1, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/16", CPU_8088, 1, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, +const CPU cpus_8088[] = { + /* 8088 */ + { "8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8088/8", CPU_8088, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8088/9.54", CPU_8088, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8088/10", CPU_8088, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8088/12", CPU_8088, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8088/16", CPU_8088, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, #ifdef _DEBUG - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, + { "286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1 }, #endif - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} + { NULL } }; -CPU cpus_pcjr[] = { - /*8088 PCjr*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_8086[] = { + /* 8086 */ + { "8086/7.16", CPU_8086, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1 }, + { "8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8086/9.54", CPU_8086, 9545456, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1 }, + { "8086/10", CPU_8086, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8086/12", CPU_8086, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "8086/16", CPU_8086, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2 }, + { NULL } }; -CPU cpus_europc[] = { - /*8088 EuroPC*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8088/7.16", CPU_8088, 1, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_nec[] = { + /* NEC V20/30 */ + { "V20/8", CPU_NEC, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "V20/10", CPU_NEC, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "V20/12", CPU_NEC, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "V20/16", CPU_NEC, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2 }, + { NULL } }; -CPU cpus_8086[] = { - /*8086 standard*/ - {"8086/7.16", CPU_8086, 1, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/9.54", CPU_8086, 1, 9545456, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8086/10", CPU_8086, 1, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/12", CPU_8086, 1, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/16", CPU_8086, 1, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_186[] = { + /* 80186 */ + { "80186/7.16", CPU_186, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "80186/8", CPU_186, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "80186/9.54", CPU_186, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "80186/10", CPU_186, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "80186/12", CPU_186, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { "80186/16", CPU_186, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2 }, + { "80186/20", CPU_186, 20000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3 }, + { "80186/25", CPU_186, 25000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3 }, + { NULL } }; -CPU cpus_nec[] = { - /*NEC V20/30 standard*/ - {"V20/8", CPU_NEC, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"V20/10", CPU_NEC, 1, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"V20/12", CPU_NEC, 1, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"V20/16", CPU_NEC, 1, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_286[] = { + /* 80286 */ + { "286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1 }, + { "286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1 }, + { "286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1 }, + { "286/12", CPU_286, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2 }, + { "286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2 }, + { "286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3 }, + { "286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3 }, + { NULL } }; -CPU cpus_186[] = { - /*80186 standard*/ - {"80186/7.16", CPU_186, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"80186/8", CPU_186, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"80186/9.54", CPU_186, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"80186/10", CPU_186, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"80186/12", CPU_186, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"80186/16", CPU_186, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, - {"80186/20", CPU_186, 5, 20000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3}, - {"80186/25", CPU_186, 6, 25000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_i386SX[] = { + /* i386SX */ + { "i386SX/16", CPU_386SX, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2 }, + { "i386SX/20", CPU_386SX, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3 }, + { "i386SX/25", CPU_386SX, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3 }, + { "i386SX/33", CPU_386SX, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4 }, + { "i386SX/40", CPU_386SX, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5 }, + { NULL } }; -CPU cpus_pc1512[] = { - /*8086 Amstrad*/ - {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_i386DX[] = { + /* i386DX */ + { "i386DX/16", CPU_386DX, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2 }, + { "i386DX/20", CPU_386DX, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3 }, + { "i386DX/25", CPU_386DX, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3 }, + { "i386DX/33", CPU_386DX, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4 }, + { "i386DX/40", CPU_386DX, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5 }, + { "RapidCAD/25", CPU_RAPIDCAD, 25000000, 1, 0, 0x0430, 0, 0, 0, 4,4,3,3, 3 }, + { "RapidCAD/33", CPU_RAPIDCAD, 33333333, 1, 0, 0x0430, 0, 0, 0, 6,6,3,3, 4 }, + { "RapidCAD/40", CPU_RAPIDCAD, 40000000, 1, 0, 0x0430, 0, 0, 0, 7,7,3,3, 5 }, + { NULL } }; -CPU cpus_286[] = { - /*286*/ - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/8", CPU_286, 1, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, - {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, - {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, - {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_Am386SX[] = { + /* Am386 */ + { "Am386SX/16", CPU_386SX, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2 }, + { "Am386SX/20", CPU_386SX, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3 }, + { "Am386SX/25", CPU_386SX, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3 }, + { "Am386SX/33", CPU_386SX, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4 }, + { "Am386SX/40", CPU_386SX, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5 }, + { NULL } }; -CPU cpus_ibmat[] = { - /*286*/ - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1}, - {"286/8", CPU_286, 0, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_Am386DX[] = { + /* Am386 */ + { "Am386DX/25", CPU_386DX, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3 }, + { "Am386DX/33", CPU_386DX, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4 }, + { "Am386DX/40", CPU_386DX, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5 }, + { NULL } }; -CPU cpus_ibmxt286[] = { - /*286*/ - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_486SLC[] = { + /* Cx486SLC */ + { "Cx486SLC/20", CPU_486SLC, 20000000, 1, 0, 0x0400, 0, 0x0000, 0, 4,4,3,3, 3 }, + { "Cx486SLC/25", CPU_486SLC, 25000000, 1, 0, 0x0400, 0, 0x0000, 0, 4,4,3,3, 3 }, + { "Cx486SLC/33", CPU_486SLC, 33333333, 1, 0, 0x0400, 0, 0x0000, 0, 6,6,3,3, 4 }, + { "Cx486SRx2/32", CPU_486SLC, 32000000, 2, 0, 0x0406, 0, 0x0006, 0, 6,6,6,6, 4 }, + { "Cx486SRx2/40", CPU_486SLC, 40000000, 2, 0, 0x0406, 0, 0x0006, 0, 8,8,6,6, 6 }, + { "Cx486SRx2/50", CPU_486SLC, 50000000, 2, 0, 0x0406, 0, 0x0006, 0, 8,8,6,6, 6 }, + { NULL } }; -CPU cpus_ps1_m2011[] = { - /*286*/ - {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_486DLC[] = { + /* Cx486DLC */ + { "Cx486DLC/25", CPU_486DLC, 25000000, 1, 0, 0x0401, 0, 0x0001, 0, 4,4,3,3, 3 }, + { "Cx486DLC/33", CPU_486DLC, 33333333, 1, 0, 0x0401, 0, 0x0001, 0, 6,6,3,3, 4 }, + { "Cx486DLC/40", CPU_486DLC, 40000000, 1, 0, 0x0401, 0, 0x0001, 0, 7,7,3,3, 5 }, + { "Cx486DRx2/32", CPU_486DLC, 32000000, 2, 0, 0x0407, 0, 0x0007, 0, 6,6,6,6, 4 }, + { "Cx486DRx2/40", CPU_486DLC, 40000000, 2, 0, 0x0407, 0, 0x0007, 0, 8,8,6,6, 6 }, + { "Cx486DRx2/50", CPU_486DLC, 50000000, 2, 0, 0x0407, 0, 0x0007, 0, 8,8,6,6, 6 }, + { "Cx486DRx2/66", CPU_486DLC, 66666666, 2, 0, 0x0407, 0, 0x0007, 0, 12,12,6,6, 8 }, + { NULL } }; -CPU cpus_ps2_m30_286[] = { - /*286*/ - {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, - {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, - {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, - {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_i486[] = { + /* i486 */ + { "i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x042a, 0, 0, CPU_SUPPORTS_DYNAREC, 3,3,3,3, 2 }, + { "i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x042a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3 }, + { "i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x042a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3 }, + { "i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x042a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4 }, + { "i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x045b, 0x045b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6 }, + { "i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x045b, 0x045b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 8 }, + { "i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x0404, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3 }, + { "i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x0404, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4 }, + { "i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x0404, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 6 }, + { "i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x0430, 0x0430, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6 }, + { "i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x0430, 0x0430, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6 }, + { "i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x0430, 0x0430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8 }, + { "i486DX4/75", CPU_iDX4, 75000000, 3, 25000000, 0x0481, 0x0481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9 }, /*CPUID available on DX4, >= 75 MHz*/ + { "i486DX4/100", CPU_iDX4, 100000000, 3, 33333333, 0x0481, 0x0481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12 }, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ + { "Pentium OverDrive/63", CPU_PENTIUM, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2 }, + { "Pentium OverDrive/83", CPU_PENTIUM, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10 }, + { NULL } }; -CPU cpus_i386SX[] = { - /*i386SX*/ - {"i386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2}, - {"i386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"i386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"i386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_Am486[] = { + /* Am486/5x86 */ + { "Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x042a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4 }, + { "Am486SX/40", CPU_Am486SX, 40000000, 1, 20000000, 0x042a, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5 }, + { "Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x045b, 0x045b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6 }, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ + { "Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x045b, 0x045b, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8 }, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/ + { "Am486DX/33", CPU_Am486DX, 33333333, 1, 33333333, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4 }, + { "Am486DX/40", CPU_Am486DX, 40000000, 1, 20000000, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5 }, + { "Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x0470, 0x0470, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6 }, + { "Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x0470, 0x0470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8 }, + { "Am486DX2/80", CPU_Am486DX, 80000000, 2, 20000000, 0x0470, 0x0470, 0, CPU_SUPPORTS_DYNAREC, 14,14,6,6, 10 }, + { "Am486DX4/75", CPU_Am486DX, 75000000, 3, 25000000, 0x0482, 0x0482, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9 }, + { "Am486DX4/90", CPU_Am486DX, 90000000, 3, 30000000, 0x0482, 0x0482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 12 }, + { "Am486DX4/100", CPU_Am486DX, 100000000, 3, 33333333, 0x0482, 0x0482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 12 }, + { "Am486DX4/120", CPU_Am486DX, 120000000, 3, 20000000, 0x0482, 0x0482, 0, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 15 }, + { "Am5x86/P75", CPU_Am486DX, 133333333, 4, 33333333, 0x04e0, 0x04e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16 }, + { "Am5x86/P75+", CPU_Am486DX, 160000000, 4, 20000000, 0x04e0, 0x04e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20 }, + { NULL } }; -CPU cpus_i386DX[] = { - /*i386DX*/ - {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2}, - {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4}, - {"i386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5}, - {"RapidCAD/25", CPU_RAPIDCAD, 2, 25000000, 1, 0, 0x430, 0, 0, 0, 4,4,3,3, 3}, - {"RapidCAD/33", CPU_RAPIDCAD, 3, 33333333, 1, 0, 0x430, 0, 0, 0, 6,6,3,3, 4}, - {"RapidCAD/40", CPU_RAPIDCAD, 4, 40000000, 1, 0, 0x430, 0, 0, 0, 7,7,3,3, 5}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_Cx486[] = { + /* Cx486/5x86 */ + { "Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x0420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3 }, + { "Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x0420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4 }, + { "Cx486S/40", CPU_Cx486S, 40000000, 1, 20000000, 0x0420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5 }, + { "Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x0430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4 }, + { "Cx486DX/40", CPU_Cx486DX, 40000000, 1, 20000000, 0x0430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5 }, + { "Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x0430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6 }, + { "Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x0430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8 }, + { "Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 20000000, 0x0430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 10 }, + { "Cx486DX4/75", CPU_Cx486DX, 75000000, 3, 25000000, 0x0480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9 }, + { "Cx486DX4/100", CPU_Cx486DX, 100000000, 3, 33333333, 0x0480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 12 }, + { "Cx5x86/100", CPU_Cx5x86, 100000000, 3, 33333333, 0x0480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 12 }, + { "Cx5x86/120", CPU_Cx5x86, 120000000, 3, 20000000, 0x0480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 15 }, + { "Cx5x86/133", CPU_Cx5x86, 133333333, 4, 33333333, 0x0480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16 }, + { NULL } }; -#if 0 -CPU cpus_acer[] = { - /*i386SX*/ - {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,4,4, 3}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} -}; -#endif +const CPU cpus_6x86[] = { + /* Cyrix 6x86 */ + { "6x86-P90", CPU_Cx6x86, 80000000, 3, 40000000, 0x0520, 0x0520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 10 }, + { "6x86-PR120+", CPU_Cx6x86, 100000000, 3, 25000000, 0x0520, 0x0520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12 }, + { "6x86-PR133+", CPU_Cx6x86, 110000000, 3, 27500000, 0x0520, 0x0520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 14 }, + { "6x86-PR150+", CPU_Cx6x86, 120000000, 3, 30000000, 0x0520, 0x0520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "6x86-PR166+", CPU_Cx6x86, 133333333, 3, 33333333, 0x0520, 0x0520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { "6x86-PR200+", CPU_Cx6x86, 150000000, 3, 37500000, 0x0520, 0x0520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 18 }, -CPU cpus_Am386SX[] = { - /*Am386*/ - {"Am386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2}, - {"Am386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"Am386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"Am386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"Am386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} + /* Cyrix 6x86L */ + { "6x86L-PR133+", CPU_Cx6x86L, 110000000, 3, 27500000, 0x0540, 0x0540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 14 }, + { "6x86L-PR150+", CPU_Cx6x86L, 120000000, 3, 30000000, 0x0540, 0x0540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "6x86L-PR166+", CPU_Cx6x86L, 133333333, 3, 33333333, 0x0540, 0x0540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { "6x86L-PR200+", CPU_Cx6x86L, 150000000, 3, 37500000, 0x0540, 0x0540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 18 }, + + /* Cyrix 6x86MX */ + { "6x86MX-PR166", CPU_Cx6x86MX, 133333333, 3, 33333333, 0x0600, 0x0600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { "6x86MX-PR200", CPU_Cx6x86MX, 166666666, 3, 33333333, 0x0600, 0x0600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "6x86MX-PR233", CPU_Cx6x86MX, 188888888, 3, 37500000, 0x0600, 0x0600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 45/2 }, + { "6x86MX-PR266", CPU_Cx6x86MX, 207500000, 3, 41666667, 0x0600, 0x0600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, 25 }, + { "6x86MX-PR300", CPU_Cx6x86MX, 233333333, 3, 33333333, 0x0600, 0x0600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7, 28 }, + { "6x86MX-PR333", CPU_Cx6x86MX, 250000000, 3, 41666667, 0x0600, 0x0600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9, 30 }, + { "6x86MX-PR366", CPU_Cx6x86MX, 250000000, 3, 33333333, 0x0600, 0x0600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 30 }, + { "6x86MX-PR400", CPU_Cx6x86MX, 285000000, 3, 41666667, 0x0600, 0x0600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 33 }, + { NULL } }; -CPU cpus_Am386DX[] = { - /*Am386*/ - {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4}, - {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_WinChip[] = { + /* IDT WinChip */ + { "WinChip 75", CPU_WINCHIP, 75000000, 2, 25000000, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 9 }, + { "WinChip 90", CPU_WINCHIP, 90000000, 2, 30000000, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, 21/2 }, + { "WinChip 100", CPU_WINCHIP, 100000000, 2, 33333333, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, 12 }, + { "WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 14 }, + { "WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 16 }, + { "WinChip 150", CPU_WINCHIP, 150000000, 3, 30000000, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, 35/2 }, + { "WinChip 166", CPU_WINCHIP, 166666666, 3, 33333333, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, 40 }, + { "WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 21 }, + { "WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 24 }, + { "WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 27 }, + { "WinChip 240", CPU_WINCHIP, 240000000, 6, 30000000, 0x0540, 0x0540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 28 }, + { NULL } }; -CPU cpus_486SLC[] = { - /*Cx486SLC*/ - {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, - {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, - {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3, 4}, - {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6, 4}, - {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 6}, - {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 6}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_Pentium5V[] = { + /* Intel Pentium (5V, socket 4) */ + { "Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7 }, + { "Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8 }, + { "Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x051a, 0x051a, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x051a, 0x051a, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { NULL } }; -CPU cpus_486DLC[] = { - /*Cx486DLC*/ - {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3, 3}, - {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3, 4}, - {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3, 5}, - {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6, 4}, - {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 6}, - {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 6}, - {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 8}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_Pentium5V50[] = { + /* Intel Pentium (5V, socket 4, including 50 MHz FSB) */ + { "Pentium 50 (Q0399)", CPU_PENTIUM, 50000000, 1, 25000000, 0x0513, 0x0513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3, 6 }, + { "Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7 }, + { "Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8 }, + { "Pentium OverDrive 100", CPU_PENTIUM, 100000000, 2, 25000000, 0x051a, 0x051a, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 12 }, + { "Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x051a, 0x051a, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x051a, 0x051a, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { NULL } }; -CPU cpus_i486[] = { - /*i486*/ - {"i486SX/16", CPU_i486SX, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3,3,3,3, 2}, - {"i486SX/20", CPU_i486SX, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"i486SX/25", CPU_i486SX, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"i486SX/33", CPU_i486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, -#if 0 - {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"i486SX2/66 (Q0569)", CPU_i486SX, 6, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 8}, -#else - {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"i486SX2/66 (Q0569)", CPU_i486SX, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 8}, -#endif - {"i486DX/25", CPU_i486DX, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"i486DX/33", CPU_i486DX, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"i486DX/50", CPU_i486DX, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 6}, -#if 0 - {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, -#else - {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, -#endif - {"iDX4/75", CPU_iDX4, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*CPUID available on DX4, >= 75 MHz*/ - {"iDX4/100", CPU_iDX4, 10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ - {"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, - {"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_PentiumS5[] = { + /* Intel Pentium (Socket 5) */ + { "Pentium 75", CPU_PENTIUM, 75000000, 2, 25000000, 0x0522, 0x0522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + { "Pentium OverDrive MMX 75", CPU_PENTIUM_MMX, 75000000, 2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + { "Pentium 90", CPU_PENTIUM, 90000000, 2, 30000000, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2 }, + { "Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12 }, + { "Pentium 100/66", CPU_PENTIUM, 100000000, 2, 33333333, 0x0526, 0x0526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12 }, + { "Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x0526, 0x0526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16 }, + { "Pentium OverDrive 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + { "Pentium OverDrive 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40 }, + { "Pentium OverDrive MMX 125", CPU_PENTIUM_MMX, 125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15 }, + { "Pentium OverDrive MMX 150/60", CPU_PENTIUM_MMX, 150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + { "Pentium OverDrive MMX 166", CPU_PENTIUM_MMX, 166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "Pentium OverDrive MMX 180", CPU_PENTIUM_MMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21 }, + { "Pentium OverDrive MMX 200", CPU_PENTIUM_MMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { NULL } }; -CPU cpus_Am486[] = { - /*Am486/5x86*/ - {"Am486SX/33", CPU_Am486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"Am486SX/40", CPU_Am486SX, 4, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"Am486SX2/50", CPU_Am486SX, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ - {"Am486SX2/66", CPU_Am486SX, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/ - {"Am486DX/33", CPU_Am486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"Am486DX/40", CPU_Am486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"Am486DX2/50", CPU_Am486DX, 5, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"Am486DX2/66", CPU_Am486DX, 6, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"Am486DX2/80", CPU_Am486DX, 8, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14,6,6, 10}, - {"Am486DX4/75", CPU_Am486DX, 7, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, - {"Am486DX4/90", CPU_Am486DX, 9, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 12}, - {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 12}, - {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 15}, - {"Am5x86/P75", CPU_Am486DX, 12, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"Am5x86/P75+", CPU_Am486DX, 13, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} -}; - -CPU cpus_Cx486[] = { - /*Cx486/5x86*/ - {"Cx486S/25", CPU_Cx486S, 2, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"Cx486S/33", CPU_Cx486S, 3, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"Cx486S/40", CPU_Cx486S, 4, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"Cx486DX/33", CPU_Cx486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"Cx486DX/40", CPU_Cx486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"Cx486DX2/50", CPU_Cx486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"Cx486DX2/66", CPU_Cx486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"Cx486DX2/80", CPU_Cx486DX, 8, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 10}, - {"Cx486DX4/75", CPU_Cx486DX, 7, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, - {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 12}, - {"Cx5x86/100", CPU_Cx5x86, 10, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 12}, - {"Cx5x86/120", CPU_Cx5x86, 11, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 15}, - {"Cx5x86/133", CPU_Cx5x86, 12, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} -}; - -CPU cpus_6x86[] = { - /*Cyrix 6x86*/ - {"6x86-P90", CPU_Cx6x86, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 10}, - {"6x86-PR120+", CPU_Cx6x86, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, - {"6x86-PR133+", CPU_Cx6x86, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 14}, - {"6x86-PR150+", CPU_Cx6x86, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"6x86-PR166+", CPU_Cx6x86, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"6x86-PR200+", CPU_Cx6x86, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 18}, - - /*Cyrix 6x86L*/ - {"6x86L-PR133+", CPU_Cx6x86L, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 14}, - {"6x86L-PR150+", CPU_Cx6x86L, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"6x86L-PR166+", CPU_Cx6x86L, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"6x86L-PR200+", CPU_Cx6x86L, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 18}, - - /*Cyrix 6x86MX*/ - {"6x86MX-PR166", CPU_Cx6x86MX, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"6x86MX-PR200", CPU_Cx6x86MX, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"6x86MX-PR233", CPU_Cx6x86MX, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 45/2}, - {"6x86MX-PR266", CPU_Cx6x86MX, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, 25}, - {"6x86MX-PR300", CPU_Cx6x86MX, 18, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7, 28}, - {"6x86MX-PR333", CPU_Cx6x86MX, 18, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9, 30}, - {"6x86MX-PR366", CPU_Cx6x86MX, 18, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 30}, - {"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 33}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} - }; - -CPU cpus_WinChip[] = { - /*IDT WinChip*/ - {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 9}, - {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, 21/2}, - {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, 12}, - {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 14}, - {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 16}, - {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, 35/2}, - {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, 40}, - {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 21}, - {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 24}, - {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 27}, - {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 28}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} -}; - -CPU cpus_Pentium5V[] = { - /*Intel Pentium (5V, socket 4)*/ - {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7}, - {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8}, - {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} -}; - -CPU cpus_Pentium5V50[] = { - /*Intel Pentium (5V, socket 4, including 50 MHz FSB)*/ - {"Pentium 50 (Q0399)",CPU_PENTIUM, 5, 50000000, 1, 25000000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3, 6}, - {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7}, - {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8}, - {"Pentium OverDrive 100",CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 12}, - {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} -}; - -CPU cpus_PentiumS5[] = { - /*Intel Pentium (Socket 5)*/ - {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2}, - {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, - {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12}, - {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16}, - {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} -}; - -CPU cpus_Pentium[] = { - /*Intel Pentium*/ - {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2}, - {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, - {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12}, - {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"Pentium 150", CPU_PENTIUM, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium 166", CPU_PENTIUM, 19, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Pentium 200", CPU_PENTIUM, 21, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 14, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 16, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 17, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 26, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 28, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15}, - {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_Pentium[] = { + /* Intel Pentium */ + { "Pentium 75", CPU_PENTIUM, 75000000, 2, 25000000, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + { "Pentium OverDrive MMX 75", CPU_PENTIUM_MMX, 75000000, 2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + { "Pentium 90", CPU_PENTIUM, 90000000, 2, 30000000, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2 }, + { "Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12 }, + { "Pentium 100/66", CPU_PENTIUM, 100000000, 2, 33333333, 0x0526, 0x0526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12 }, + { "Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x0526, 0x0526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { "Pentium 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + { "Pentium 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { "Pentium MMX 166", CPU_PENTIUM_MMX, 166666666, 3, 33333333, 0x0543, 0x0543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "Pentium MMX 200", CPU_PENTIUM_MMX, 200000000, 3, 33333333, 0x0543, 0x0543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { "Pentium MMX 233", CPU_PENTIUM_MMX, 233333333, 4, 33333333, 0x0543, 0x0543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28 }, + { "Mobile Pentium MMX 120", CPU_PENTIUM_MMX, 120000000, 2, 30000000, 0x0543, 0x0543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "Mobile Pentium MMX 133", CPU_PENTIUM_MMX, 133333333, 2, 33333333, 0x0543, 0x0543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { "Mobile Pentium MMX 150", CPU_PENTIUM_MMX, 150000000, 3, 30000000, 0x0544, 0x0544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + { "Mobile Pentium MMX 166", CPU_PENTIUM_MMX, 166666666, 3, 33333333, 0x0544, 0x0544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "Mobile Pentium MMX 200", CPU_PENTIUM_MMX, 200000000, 3, 33333333, 0x0581, 0x0581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { "Mobile Pentium MMX 233", CPU_PENTIUM_MMX, 233333333, 4, 33333333, 0x0581, 0x0581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28 }, + { "Mobile Pentium MMX 266", CPU_PENTIUM_MMX, 266666666, 4, 33333333, 0x0582, 0x0582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32 }, + { "Mobile Pentium MMX 300", CPU_PENTIUM_MMX, 300000000, 5, 33333333, 0x0582, 0x0582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36 }, + { "Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15 }, + { "Pentium OverDrive 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + { "Pentium OverDrive 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x052c, 0x052c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "Pentium OverDrive MMX 125", CPU_PENTIUM_MMX, 125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15 }, + { "Pentium OverDrive MMX 150/60", CPU_PENTIUM_MMX, 150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + { "Pentium OverDrive MMX 166", CPU_PENTIUM_MMX, 166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "Pentium OverDrive MMX 180", CPU_PENTIUM_MMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21 }, + { "Pentium OverDrive MMX 200", CPU_PENTIUM_MMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { NULL } }; #if defined(DEV_BRANCH) && defined(USE_AMD_K) -CPU cpus_K5[] = { - /*AMD K5 (Socket 5)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 9, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 9, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"K5 (5k86) 90 (P90)", CPU_K5, 12, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 12, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2}, - {"K5 (5k86) 100 (P100)", CPU_K5, 13, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12}, - {"K5 (SSA/5) 100 (PR100)",CPU_K5, 13, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 14, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 16, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 17, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"K5 (5k86) 116.5 (PR166)",CPU_5K86, 19, 166666666, 3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 21, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_K5[] = { + /* AMD K5 (Socket 5) */ + { "K5 (5k86) 75 (P75)", CPU_K5, 75000000, 2, 25000000, 0x0500, 0x0500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + { "K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 2, 25000000, 0x0501, 0x0501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + { "K5 (5k86) 90 (P90)", CPU_K5, 90000000, 2, 30000000, 0x0500, 0x0500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2 }, + { "K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 2, 30000000, 0x0501, 0x0501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2 }, + { "K5 (5k86) 100 (P100)", CPU_K5, 100000000, 2, 33333333, 0x0500, 0x0500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12 }, + { "K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 2, 33333333, 0x0501, 0x0501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12 }, + { "K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x0511, 0x0511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x0514, 0x0514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { "K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 3, 30000000, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + { "K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 3, 33333333, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x0534, 0x0534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { NULL } }; -CPU cpus_K56[] = { - /*AMD K5 and K6 (Socket 7)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 9, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 9, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"K5 (5k86) 90 (P90)", CPU_K5, 12, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 12, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2}, - {"K5 (5k86) 100 (P100)", CPU_K5, 13, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12}, - {"K5 (SSA/5) 100 (PR100)",CPU_K5, 13, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 14, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 16, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 17, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"K5 (5k86) 116.5 (PR166)",CPU_5K86, 19, 166666666, 3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 21, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"K6 (Model 6) 166", CPU_K6, 19, 166666666, 3, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"K6 (Model 6) 200", CPU_K6, 21, 200000000, 3, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"K6 (Model 6) 233", CPU_K6, 24, 233333333, 4, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6 (Model 7) 200", CPU_K6, 21, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"K6 (Model 7) 233", CPU_K6, 24, 233333333, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6 (Model 7) 266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6 (Model 7) 300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_K56[] = { + /* AMD K5 and K6 (Socket 7) */ + { "K5 (5k86) 75 (P75)", CPU_K5, 75000000, 2, 25000000, 0x0500, 0x0500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + { "K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 2, 25000000, 0x0501, 0x0501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + { "K5 (5k86) 90 (P90)", CPU_K5, 90000000, 2, 30000000, 0x0500, 0x0500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2 }, + { "K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 2, 30000000, 0x0501, 0x0501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 21/2 }, + { "K5 (5k86) 100 (P100)", CPU_K5, 100000000, 2, 33333333, 0x0500, 0x0500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12 }, + { "K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 2, 33333333, 0x0501, 0x0501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, 12 }, + { "K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x0511, 0x0511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14 }, + { "K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x0514, 0x0514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16 }, + { "K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 3, 30000000, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + { "K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 3, 33333333, 0x0524, 0x0524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x0534, 0x0534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { "K6 (Model 6) 166", CPU_K6, 166666666, 3, 33333333, 0x0562, 0x0562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + { "K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x0562, 0x0562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { "K6 (Model 6) 233", CPU_K6, 233333333, 4, 33333333, 0x0562, 0x0562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28 }, + { "K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x0570, 0x0570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + { "K6 (Model 7) 233", CPU_K6, 233333333, 4, 33333333, 0x0570, 0x0570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28 }, + { "K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x0570, 0x0570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32 }, + { "K6 (Model 7) 300", CPU_K6, 300000000, 5, 33333333, 0x0570, 0x0570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36 }, + { NULL } }; #endif -#if defined(DEV_BRANCH) && defined(USE_I686) -CPU cpus_PentiumPro[] = { - /*Intel Pentium Pro and II Overdrive*/ - {"Pentium Pro 50", CPU_PENTIUMPRO, 5, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3, 6}, - {"Pentium Pro 60" , CPU_PENTIUMPRO, 6, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7}, - {"Pentium Pro 66" , CPU_PENTIUMPRO, 6, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8}, - {"Pentium Pro 75", CPU_PENTIUMPRO, 9, 75000000, 2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"Pentium Pro 150", CPU_PENTIUMPRO, 17, 150000000, 3, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium Pro 166", CPU_PENTIUMPRO, 19, 166666666, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Pentium Pro 180", CPU_PENTIUMPRO, 20, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21}, - {"Pentium Pro 200", CPU_PENTIUMPRO, 21, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"Pentium II Overdrive 50", CPU_PENTIUM2D, 5, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3, 6}, - {"Pentium II Overdrive 60", CPU_PENTIUM2D, 6, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7}, - {"Pentium II Overdrive 66", CPU_PENTIUM2D, 6, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8}, - {"Pentium II Overdrive 75", CPU_PENTIUM2D, 9, 75000000, 2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9}, - {"Pentium II Overdrive 210", CPU_PENTIUM2D, 22, 210000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, 25}, - {"Pentium II Overdrive 233", CPU_PENTIUM2D, 24, 233333333, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,1, 28}, - {"Pentium II Overdrive 240", CPU_PENTIUM2D, 25, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29}, - {"Pentium II Overdrive 266", CPU_PENTIUM2D, 26, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"Pentium II Overdrive 270", CPU_PENTIUM2D, 27, 270000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33}, - {"Pentium II Overdrive 300/66",CPU_PENTIUM2D, 28, 300000000, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, - {"Pentium II Overdrive 300/60",CPU_PENTIUM2D, 28, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"Pentium II Overdrive 333", CPU_PENTIUM2D, 29, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +const CPU cpus_PentiumPro[] = { + /* Intel Pentium Pro and II Overdrive */ + {"Pentium Pro 50", CPU_PENTIUM_PRO, 50000000, 1, 25000000, 0x0612, 0x0612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3, 6 }, + {"Pentium Pro 60", CPU_PENTIUM_PRO, 60000000, 1, 30000000, 0x0612, 0x0612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7 }, + {"Pentium Pro 66", CPU_PENTIUM_PRO, 66666666, 1, 33333333, 0x0612, 0x0612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8 }, + {"Pentium Pro 75", CPU_PENTIUM_PRO, 75000000, 2, 25000000, 0x0612, 0x0612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + {"Pentium Pro 150", CPU_PENTIUM_PRO, 150000000, 3, 30000000, 0x0612, 0x0612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2 }, + {"Pentium Pro 166", CPU_PENTIUM_PRO, 166666666, 3, 33333333, 0x0617, 0x0617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20 }, + {"Pentium Pro 180", CPU_PENTIUM_PRO, 180000000, 3, 30000000, 0x0617, 0x0617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21 }, + {"Pentium Pro 200", CPU_PENTIUM_PRO, 200000000, 3, 33333333, 0x0617, 0x0617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24 }, + {"Pentium II Overdrive 50", CPU_PENTIUM_2D, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3, 6 }, + {"Pentium II Overdrive 60", CPU_PENTIUM_2D, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7 }, + {"Pentium II Overdrive 66", CPU_PENTIUM_2D, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8 }, + {"Pentium II Overdrive 75", CPU_PENTIUM_2D, 75000000, 2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, 9 }, + {"Pentium II Overdrive 210", CPU_PENTIUM_2D, 210000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, 25 }, + {"Pentium II Overdrive 233", CPU_PENTIUM_2D, 233333333, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,1, 28 }, + {"Pentium II Overdrive 240", CPU_PENTIUM_2D, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29 }, + {"Pentium II Overdrive 266", CPU_PENTIUM_2D, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32 }, + {"Pentium II Overdrive 270", CPU_PENTIUM_2D, 270000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33 }, + {"Pentium II Overdrive 300/66", CPU_PENTIUM_2D, 300000000, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36 }, + {"Pentium II Overdrive 300/60", CPU_PENTIUM_2D, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36 }, + {"Pentium II Overdrive 333", CPU_PENTIUM_2D, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40 }, + { NULL } }; -#endif diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 5b30c07..27f86b7 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -8,13 +8,13 @@ * * Miscellaneous x86 CPU Instructions. * - * Version: @(#)x86_ops.h 1.0.2 2018/05/05 + * Version: @(#)x86_ops.h 1.0.3 2019/04/11 * * Authors: Fred N. van Kempen, * Sarah Walker, * Miran Grca, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. * @@ -89,10 +89,9 @@ extern const OpFn dynarec_ops_c6x86mx_0f[1024]; extern const OpFn dynarec_ops_k6_0f[1024]; #endif -#if defined(DEV_BRANCH) && defined(USE_I686) extern const OpFn dynarec_ops_pentiumpro_0f[1024]; +extern const OpFn dynarec_ops_pentium2_0f[1024]; extern const OpFn dynarec_ops_pentium2d_0f[1024]; -#endif extern const OpFn dynarec_ops_fpu_287_d9_a16[256]; extern const OpFn dynarec_ops_fpu_287_d9_a32[256]; @@ -181,10 +180,9 @@ extern const OpFn ops_c6x86mx_0f[1024]; extern const OpFn ops_k6_0f[1024]; #endif -#if defined(DEV_BRANCH) && defined(USE_I686) extern const OpFn ops_pentiumpro_0f[1024]; +extern const OpFn ops_pentium2_0f[1024]; extern const OpFn ops_pentium2d_0f[1024]; -#endif extern const OpFn ops_fpu_287_d9_a16[256]; extern const OpFn ops_fpu_287_d9_a32[256]; diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index fb0d049..ff6b31a 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -8,13 +8,15 @@ * * x86 CPU segment emulation. * - * Version: @(#)x86seg.c 1.0.5 2018/10/05 + * Version: @(#)x86seg.c 1.0.6 2019/04/20 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2018 Sarah Walker. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -43,7 +45,6 @@ #define HAVE_STDARG_H #include "../emu.h" #include "cpu.h" -#include "../machines/machine.h" #include "../mem.h" #include "../nvr.h" #include "x86.h" @@ -88,7 +89,7 @@ x86abort(const char *fmt, ...) pclog(-1, NULL); nvr_save(); - dumpregs(1); + cpu_dumpregs(1); exit(-1); } @@ -1612,7 +1613,7 @@ void pmodeint(int num, int soft) if (num==8) { /*Triple fault - reset!*/ - softresetx86(); + cpu_reset(0); cpu_set_edx(); } else if (num==0xD) diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 49c837a..88148cb 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -8,14 +8,14 @@ * * x87 FPU instructions core. * - * Version: @(#)x87_ops.h 1.0.7 2018/10/24 + * Version: @(#)x87_ops.h 1.0.8 2019/03/21 * * Authors: Fred N. van Kempen, * Sarah Walker, * leilei, * Miran Grca, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 leilei. * Copyright 2016-2018 Miran Grca. @@ -332,7 +332,7 @@ static INLINE uint16_t x87_compare(double a, double b) return result & (C0|C2|C3); #endif -#if defined(__GNUC__) +#if defined(__GNUC__) && (defined(__i386) || defined(__i386__) || defined(_X86_) || defined(_M_IX86) || defined(_M_X64)) if (!is386) { if (((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) diff --git a/src/device.c b/src/device.c index b75d5ab..fdf0469 100644 --- a/src/device.c +++ b/src/device.c @@ -9,7 +9,9 @@ * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.c 1.0.19 2019/03/05 + * **TODO** Merge the various 'add' variants, its getting too messy. + * + * Version: @(#)device.c 1.0.21 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,6 +46,8 @@ #include #include "emu.h" #include "config.h" +#include "mem.h" +#include "rom.h" #include "device.h" #include "machines/machine.h" #include "devices/sound/sound.h" @@ -69,7 +73,7 @@ static clonedev_t *clones = NULL; /* Initialize the module for use. */ void -device_init(void) +device_reset(void) { clonedev_t *ptr; @@ -86,6 +90,23 @@ device_init(void) } +#ifdef _DEBUG +void +device_dump(void) +{ + int c; + + for (c = 0; c < DEVICE_MAX; c++) { + if (devices[c] == NULL) continue; + + INFO("DEVICE [%3i] = '%s' flags=%08lx local=%08lx priv=%08lx\n", + c, devices[c]->name, + devices[c]->flags, devices[c]->local, device_priv[c]); + } +} +#endif + + /* Clone a master device for multi-instance devices. */ const device_t * device_clone(const device_t *master) @@ -130,8 +151,9 @@ device_clone(const device_t *master) } +/* Add a new device to the system. */ void * -device_add(const device_t *d) +device_add_parent(const device_t *d, void *parent) { wchar_t temp[1024]; void *priv = NULL; @@ -165,23 +187,31 @@ device_add(const device_t *d) INFO("DEVICE: device '%s' is unstable, user agreed!\n", d->name); } - old = device_current; - device_current = (device_t *)d; - /* - * Do this so that a chained device_add will not identify the - * same ID its master device is already trying to assign. + * Allocate device 'c' to the device being initialized. + * + * We have to do this BEFORE calling the init function, or + * else this go bad if that function in turn adds devices + * as well (chain loading) - which would then use this same + * slot as it was not allocated yet. */ devices[c] = (device_t *)d; + /* Keep track of our current device, which is used for configuration. */ + old = device_current; + device_current = (device_t *)d; + + /* We do not initialize 'root' (machine) devices. */ if (d->init != NULL) { - priv = d->init(d); + /* Pass the provided 'parent' argument. */ + priv = d->init(d, parent); if (priv == NULL) { if (d->name) ERRLOG("DEVICE: device '%s' init failed\n", d->name); else ERRLOG("DEVICE: device init failed\n"); + /* Free up this slot. */ devices[c] = NULL; return(NULL); @@ -195,6 +225,13 @@ device_add(const device_t *d) } +void * +device_add(const device_t *d) +{ + return(device_add_parent(d, device_priv[0])); +} + + /* For devices that do not have an init function (internal video etc.) */ void device_add_ex(const device_t *d, void *priv) @@ -328,11 +365,17 @@ device_available(const device_t *d) if (d->flags & DEVICE_UNSTABLE) return(0); #endif + /* If the 'available' function member is set, use that. */ if (d->dev_available != NULL) { func = d->dev_available; return(func()); } + /* Otherwise, just do a 'present' check on the ROM path. */ + if (d->path != NULL) + return(rom_present(d->path)); + + /* Neither... always available. */ return(1); } @@ -372,10 +415,9 @@ device_get_config_string(const char *s) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) return(config_get_string(device_current->name, s, c->default_string)); - c++; } @@ -388,10 +430,9 @@ device_get_config_int(const char *s) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) return(config_get_int(device_current->name, s, c->default_int)); - c++; } @@ -404,10 +445,9 @@ device_get_config_int_ex(const char *s, int def) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) return(config_get_int(device_current->name, s, def)); - c++; } @@ -420,10 +460,9 @@ device_get_config_hex16(const char *s) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) return(config_get_hex16(device_current->name, s, c->default_int)); - c++; } @@ -436,10 +475,9 @@ device_get_config_hex20(const char *s) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) return(config_get_hex20(device_current->name, s, c->default_int)); - c++; } @@ -452,10 +490,9 @@ device_get_config_mac(const char *s, int def) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) return(config_get_mac(device_current->name, s, def)); - c++; } @@ -468,7 +505,7 @@ device_set_config_int(const char *s, int val) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) { config_set_int(device_current->name, s, val); break; @@ -484,7 +521,7 @@ device_set_config_hex16(const char *s, int val) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) { config_set_hex16(device_current->name, s, val); break; @@ -500,7 +537,7 @@ device_set_config_hex20(const char *s, int val) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) { config_set_hex20(device_current->name, s, val); break; @@ -516,7 +553,7 @@ device_set_config_mac(const char *s, int val) { const device_config_t *c = device_current->config; - while (c && c->type != -1) { + while (c && c->name) { if (! strcmp(s, c->name)) { config_set_mac(device_current->name, s, val); break; diff --git a/src/device.h b/src/device.h index f10ef19..0fb22ea 100644 --- a/src/device.h +++ b/src/device.h @@ -8,7 +8,7 @@ * * Definitions for the device handler. * - * Version: @(#)device.h 1.0.9 2019/02/10 + * Version: @(#)device.h 1.0.12 2019/04/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,22 +53,27 @@ enum { - DEVICE_ALL = 0x0000, /* any/all device */ - DEVICE_UNSTABLE = 0x0001, /* unstable device, be cautious */ - DEVICE_PCJR = 0x0002, /* requires an IBM PCjr */ - DEVICE_AT = 0x0004, /* requires an AT-compatible system */ - DEVICE_PS2 = 0x0008, /* requires a PS/1 or PS/2 system */ - DEVICE_ISA = 0x0100, /* requires the ISA bus */ - DEVICE_EISA = 0x0200, /* requires the EISA bus */ - DEVICE_VLB = 0x0400, /* requires the VLB bus */ - DEVICE_PCI = 0x0800, /* requires the PCI bus */ - DEVICE_AGP = 0x1000, /* requires the AGP bus */ - DEVICE_MCA = 0x2000, /* requires the MCA bus */ - DEVICE_CBUS = 0x4000 /* requires the C-BUS bus (PC98) */ + DEVICE_ALL = 0x00000000, /* any/all device */ + DEVICE_UNSTABLE = 0x00000001, /* unstable device, be cautious */ + DEVICE_PCJR = 0x00000002, /* requires an IBM PCjr */ + DEVICE_AT = 0x00000004, /* requires an AT-compatible system */ + DEVICE_PS2 = 0x00000008, /* requires a PS/1 or PS/2 system */ + DEVICE_ISA = 0x00000100, /* requires the ISA bus */ + DEVICE_EISA = 0x00000200, /* requires the EISA bus */ + DEVICE_VLB = 0x00000400, /* requires the VLB bus */ + DEVICE_PCI = 0x00000800, /* requires the PCI bus */ + DEVICE_AGP = 0x00001000, /* requires the AGP bus */ + DEVICE_MCA = 0x00002000, /* requires the MCA bus */ + DEVICE_CBUS = 0x00004000, /* requires the C-BUS bus (PC98) */ + DEVICE_VIDTYPE = 0xc0000000, /* video type bits in device flags */ + DEVICE_ROOT = 0xffffffff /* machine root device */ }; #define DEVICE_SYS_MASK 0x0006 #define DEVICE_BUS_MASK 0xff00 +#define DEVICE_VIDEO(x) (((x) & 0x03) << 30) +#define DEVICE_VIDEO_GET(x) (((x) >> 30) & 0x03) + typedef struct { const char *description; @@ -99,10 +104,12 @@ typedef struct { typedef struct _device_ { const char *name; - uint32_t flags; /* system flags */ - uint32_t local; /* flags local to device */ + uint32_t flags; /* system flags */ + uint32_t local; /* flags local to device */ - void *(*init)(const struct _device_ *); + const wchar_t *path; /* path to BIOS/ROM file(s) */ + + void *(*init)(const struct _device_ *, void *arg); void (*close)(void *priv); void (*reset)(void *priv); void *u1_reuse; @@ -113,6 +120,7 @@ typedef struct _device_ { const void *u2_reuse; #define vid_timing u2_reuse #define mca_reslist u2_reuse +#define mach_info u2_reuse const device_config_t *config; } device_t; @@ -121,10 +129,14 @@ typedef struct _device_ { extern "C" { #endif -extern void device_init(void); +extern void device_reset(void); +#ifdef _DEBUG +extern void device_dump(void); +#endif extern const device_t *device_clone(const device_t *master); extern void *device_add(const device_t *); -extern void device_add_ex(const device_t *d, void *priv); +extern void *device_add_parent(const device_t *, void *parent); +extern void device_add_ex(const device_t *, void *priv); extern void device_close_all(void); extern void device_reset_all(int flags); extern void *device_get_priv(const device_t *); diff --git a/src/devices/cdrom/cdrom_dosbox.cpp b/src/devices/cdrom/cdrom_dosbox.cpp index f8358dd..7b7f2fa 100644 --- a/src/devices/cdrom/cdrom_dosbox.cpp +++ b/src/devices/cdrom/cdrom_dosbox.cpp @@ -15,7 +15,7 @@ * **NOTE** This code will very soon be replaced with a C variant, so * no more changes will be done. * - * Version: @(#)cdrom_dosbox.cpp 1.0.13 2019/03/11 + * Version: @(#)cdrom_dosbox.cpp 1.0.14 2019/04/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -72,9 +72,11 @@ using namespace std; CDROM_Interface_Image::BinaryFile::BinaryFile(const wchar_t *filename, bool &error) { + const wstring cwstr(L"rb"); + memset(fn, 0x00, sizeof(fn)); wcscpy(fn, filename); - file = plat_fopen64(fn, L"rb"); + file = plat_fopen64(fn, (const wchar_t *)cwstr.c_str()); DEBUG("CDROM: binary_open(%ls) = %08lx\n", fn, file); if (file == NULL) @@ -533,7 +535,7 @@ CDROM_Interface_Image::CueGetFrame(uint64_t &arg, char **line) success = CueGetBuffer(temp, line, false); if (success) - success = (sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3); + success = (sscanf(temp, "%i:%i:%i", &min, &sec, &fr) == 3); if (success) arg = MSF_TO_FRAMES(min, sec, fr); @@ -551,6 +553,7 @@ CDROM_Interface_Image::CueLoadSheet(const wchar_t *cuefile) wchar_t temp[MAX_FILENAME_LENGTH]; char ansi[MAX_FILENAME_LENGTH]; char buf[MAX_LINE_LENGTH], *line; + const wstring cwstr(L"r"); uint64_t shift = 0; uint64_t currPregap = 0; uint64_t totalPregap = 0; @@ -568,7 +571,7 @@ CDROM_Interface_Image::CueLoadSheet(const wchar_t *cuefile) plat_get_dirname(pathname, cuefile); /* Open the file. */ - fp = plat_fopen(cuefile, L"r"); + fp = plat_fopen(cuefile, (wchar_t *)cwstr.c_str()); if (fp == NULL) return false; @@ -698,13 +701,20 @@ CDROM_Interface_Image::CueLoadSheet(const wchar_t *cuefile) memset(filename, 0x00, sizeof(filename)); plat_append_filename(filename, pathname, temp); track.file = new BinaryFile(filename, error); + } else { + ERRLOG("CUE: unsupported track format '%s' in cue sheet!\n", + type.c_str()); + success = false; + break; } + if (error) { ERRLOG("CUE: cannot open fille '%ls' in cue sheet!\n", filename); delete track.file; track.file = NULL; success = false; + break; } } else if (command == "PREGAP") success = CueGetFrame(currPregap, &line); diff --git a/src/machines/m_at_ali1429.c b/src/devices/chipsets/ali1429.c similarity index 63% rename from src/machines/m_at_ali1429.c rename to src/devices/chipsets/ali1429.c index d39b251..e94e5e5 100644 --- a/src/machines/m_at_ali1429.c +++ b/src/devices/chipsets/ali1429.c @@ -6,9 +6,9 @@ * * This file is part of the VARCem Project. * - * Implementation the ALI M1429 mainboard. + * Implementation of the ALi M-1429/1431 chipset. * - * Version: @(#)m_at_ali1429.c 1.0.7 2019/02/16 + * Version: @(#)ali1429.c 1.0.8 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,27 +38,29 @@ */ #include #include +#include #include #include -#include "../emu.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../device.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/disk/hdc.h" -#include "../devices/disk/hdc_ide.h" -#include "machine.h" +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../device.h" +#include "../../plat.h" +#include "ali1429.h" -static int ali1429_index; -static uint8_t ali1429_regs[256]; +typedef struct { + int type; + + int indx; + uint8_t regs[256]; +} ali_t; static void -ali1429_recalc(void) +ali1429_recalc(ali_t *dev) { uint32_t base; int c; @@ -66,8 +68,8 @@ ali1429_recalc(void) for (c = 0; c < 8; c++) { base = 0xc0000 + (c << 15); - if (ali1429_regs[0x13] & (1 << c)) { - switch (ali1429_regs[0x14] & 3) { + if (dev->regs[0x13] & (1 << c)) { + switch (dev->regs[0x14] & 3) { case 0: mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); @@ -101,64 +103,82 @@ ali1429_recalc(void) static void ali1429_write(uint16_t port, uint8_t val, void *priv) { - if (! (port & 1)) - ali1429_index = val; - else { - ali1429_regs[ali1429_index] = val; + ali_t *dev = (ali_t *)priv; - switch (ali1429_index) { + if (port & 1) { + dev->regs[dev->indx] = val; + + switch (dev->indx) { case 0x13: - ali1429_recalc(); + ali1429_recalc(dev); break; case 0x14: shadowbios = val & 1; shadowbios_write = val & 2; - ali1429_recalc(); + ali1429_recalc(dev); break; } - } + } else + dev->indx = val; } static uint8_t ali1429_read(uint16_t port, void *priv) { - if (! (port & 1)) - return(ali1429_index); + ali_t *dev = (ali_t *)priv; - if ((ali1429_index >= 0xc0 || ali1429_index == 0x20) && is_cyrix) + if (! (port & 1)) + return(dev->indx); + + if ((dev->indx >= 0xc0 || dev->indx == 0x20) && is_cyrix) return(0xff); /*Don't conflict with Cyrix config registers*/ - return(ali1429_regs[ali1429_index]); + return(dev->regs[dev->indx]); } static void -ali1429_reset(void) +ali1429_reset(ali_t *dev) { - memset(ali1429_regs, 0xff, 256); + memset(dev->regs, 0xff, sizeof(dev->regs)); } static void -ali1429_init(void) +ali_close(void *priv) { + ali_t *dev = (ali_t *)priv; + + free(dev); +} + + +static void * +ali_init(const device_t *info, UNUSED(void *parent)) +{ + ali_t *dev; + + dev = (ali_t *)mem_alloc(sizeof(ali_t)); + memset(dev, 0x00, sizeof(ali_t)); + dev->type = info->local; + + ali1429_reset(dev); + io_sethandler(0x0022, 2, - ali1429_read,NULL,NULL, ali1429_write,NULL,NULL, NULL); + ali1429_read,NULL,NULL, ali1429_write,NULL,NULL, dev); + + return(dev); } -void -m_at_ali1429_init(const machine_t *model, void *arg) -{ - ali1429_reset(); - - m_at_common_ide_init(model, arg); - - device_add(&keyboard_at_ami_device); - - device_add(&fdc_at_device); - - ali1429_init(); -} +const device_t ali1429_device = { + "ALi-M1429", + 0, + 0, + NULL, + ali_init, ali_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/chipsets/ali1429.h b/src/devices/chipsets/ali1429.h new file mode 100644 index 0000000..d1cf715 --- /dev/null +++ b/src/devices/chipsets/ali1429.h @@ -0,0 +1,56 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the ALi M-1429 chipset. + * + * Version: @(#)ali1429.h 1.0.1 2019/04/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ALI1429_H +# define ALI1429_H + + +#ifdef EMU_DEVICE_H +extern const device_t ali1429_device; +#endif + + +#endif /*ALI1429_H*/ diff --git a/src/machines/m_at_headland.c b/src/devices/chipsets/headland.c similarity index 89% rename from src/machines/m_at_headland.c rename to src/devices/chipsets/headland.c index a966c10..3399a64 100644 --- a/src/machines/m_at_headland.c +++ b/src/devices/chipsets/headland.c @@ -8,9 +8,7 @@ * * Implementation of the HEADLAND AT286 chipset. * - * FIXME: fix the mem_map_t stuff in mem_read_b() et al! - * - * Version: @(#)m_at_headland.c 1.0.10 2019/02/16 + * Version: @(#)headland.c 1.0.12 2019/04/20 * * Authors: Fred N. van Kempen, * Original by GreatPsycho for PCem. @@ -43,30 +41,33 @@ #include #include #include -#include "../emu.h" -#include "../cpu/cpu.h" -#include "../cpu/x86.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/disk/hdc.h" -#include "../devices/video/video.h" -#include "machine.h" +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../cpu/x86.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../device.h" +#include "../../plat.h" +#include "../input/keyboard.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" +#include "../disk/hdc.h" +#include "../video/video.h" +#include "headland.h" typedef struct { + uint8_t type; + + uint8_t cri; + uint8_t cr[8]; + uint8_t port_92; uint8_t indx; uint8_t regs[256]; - uint8_t cri; - uint8_t cr[8]; - uint8_t ems_mar; uint16_t ems_mr[64]; @@ -233,7 +234,7 @@ hl_write(uint16_t addr, uint8_t val, void *priv) mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); } else if (dev->indx == 0x87) { if ((val & 1) && !(old_val & 1)) - softresetx86(); + cpu_reset(0); } break; @@ -243,7 +244,7 @@ hl_write(uint16_t addr, uint8_t val, void *priv) mem_a20_recalc(); } if ((~dev->port_92 & val) & 1) { - softresetx86(); + cpu_reset(0); cpu_set_edx(); } dev->port_92 = val | 0xfc; @@ -551,9 +552,25 @@ mem_write_l(uint32_t addr, uint32_t val, void *priv) static void -headland_init(headland_t *dev, int ht386) +headland_close(void *priv) { - int i; + headland_t *dev = (headland_t *)priv; + + free(dev); +} + + +static void * +headland_init(const device_t *info, UNUSED(void *parent)) +{ + headland_t *dev; + int i, ht386; + + dev = (headland_t *)mem_alloc(sizeof(headland_t)); + memset(dev, 0x00, sizeof(headland_t)); + dev->type = info->local; + + ht386 = (dev->type == 32) ? 1 : 0; dev->port_92 = 0xfc; @@ -568,10 +585,10 @@ headland_init(headland_t *dev, int ht386) } else dev->cr[4] = 0x00; - io_sethandler(0x01EC, 1, + io_sethandler(0x01ec, 1, hl_read,hl_readw,NULL, hl_write,hl_writew,NULL, dev); - io_sethandler(0x01ED, 3, hl_read,NULL,NULL, hl_write,NULL,NULL, dev); + io_sethandler(0x01ed, 3, hl_read,NULL,NULL, hl_write,NULL,NULL, dev); for (i = 0; i < 64; i++) dev->ems_mr[i] = 0x00; @@ -588,10 +605,10 @@ headland_init(headland_t *dev, int ht386) mem_map_set_dev(&dev->low_mapping, dev); if (mem_size > 640) { - mem_map_add(&dev->mid_mapping, 0xA0000, 0x60000, + mem_map_add(&dev->mid_mapping, 0xa0000, 0x60000, mem_read_b,mem_read_w,mem_read_l, mem_write_b,mem_write_w,mem_write_l, - ram + 0xA0000, MEM_MAPPING_INTERNAL, &dev->mid_mapping); + ram + 0xa0000, MEM_MAPPING_INTERNAL, &dev->mid_mapping); mem_map_enable(&dev->mid_mapping); mem_map_set_dev(&dev->mid_mapping, dev); } @@ -626,75 +643,31 @@ headland_init(headland_t *dev, int ht386) 0, &dev->ems_mapping[i]); mem_map_disable(&dev->ems_mapping[i]); mem_map_set_dev(&dev->ems_mapping[i], dev); - - /* HACK - we need 'mr' in the r/w routines!! */ - dev->ems_mapping[i].p2 = &dev->ems_mr[i]; + mem_map_set_p2(&dev->ems_mapping[i], &dev->ems_mr[i]); } memmap_state_update(dev); -} - - -static headland_t * -headland_common_init(int ht386) -{ - headland_t *dev; - - dev = (headland_t *)mem_alloc(sizeof(headland_t)); - memset(dev, 0x00, sizeof(headland_t)); - - device_add(&keyboard_at_ami_device); - - device_add(&fdc_at_device); - - headland_init(dev, ht386); return(dev); } -void -m_at_tg286m_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); +const device_t headland_device = { + "Headland 286", + 0, + 0, + NULL, + headland_init, headland_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; - device_add(&ide_isa_device); - - headland_common_init(0); -} - - -/* Generic Headland 386SX machine. */ -void -m_at_headland_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&ide_isa_device); - - headland_common_init(1); -} - - -/* Arche Technologies AMA-932J-25 (Headland HT18 386SX-25.) */ -void -m_at_ama932j_init(const machine_t *model, void *arg) -{ - romdef_t *roms = (romdef_t *)arg; - headland_t *dev; - - m_at_common_init(model, arg); - - device_add(&ide_isa_device); - - dev = headland_common_init(1); - - if (video_card == VID_INTERNAL) { - /* Load the BIOS. */ - rom_init(&dev->vid_bios, roms->vidfn, - 0xc0000, roms->vidsz, roms->vidsz - 1, 0, 0); - - /* Initialize the on-board controller. */ - device_add(&oti067_onboard_device); - } -} +const device_t headland_386_device = { + "Headland 386", + 0, + 32, + NULL, + headland_init, headland_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/chipsets/headland.h b/src/devices/chipsets/headland.h new file mode 100644 index 0000000..bd28e5e --- /dev/null +++ b/src/devices/chipsets/headland.h @@ -0,0 +1,57 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Headland HTxxx chipsets. + * + * Version: @(#)headland.h 1.0.1 2019/04/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef HEADLAND_H +# define HEADLAND_H + + +#ifdef EMU_DEVICE_H +extern const device_t headland_device; +extern const device_t headland_386_device; +#endif + + +#endif /*HEADLAND_H*/ diff --git a/src/devices/chipsets/intel4x0.c b/src/devices/chipsets/intel4x0.c new file mode 100644 index 0000000..ce1b799 --- /dev/null +++ b/src/devices/chipsets/intel4x0.c @@ -0,0 +1,418 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Intel 430/440 PCISet chipsets. + * + * Version: @(#)intel4x0.c 1.0.6 2019/04/11 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../device.h" +#include "../../plat.h" +#include "../system/pci.h" +#include "intel4x0.h" + + +enum { + INTEL_430LX, + INTEL_430NX, + INTEL_430FX, + INTEL_430FX_PB640, + INTEL_430HX, + INTEL_430VX, + INTEL_440FX +}; + + +typedef struct { + int chip; + + uint8_t regs[256]; +} i4x0_t; + + +static void +i4x0_map(uint32_t addr, uint32_t size, int state) +{ + switch (state & 3) { + case 0: + mem_set_mem_state(addr, size, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + + case 1: + mem_set_mem_state(addr, size, + MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + + case 2: + mem_set_mem_state(addr, size, + MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + + case 3: + mem_set_mem_state(addr, size, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + + flushmmucache_nopc(); +} + + +static void +i4x0_write(int func, int addr, uint8_t val, void *priv) +{ + i4x0_t *dev = (i4x0_t *)priv; + + if (func) + return; + + if ((addr >= 0x10) && (addr < 0x4f)) + return; + + switch (addr) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0e: + return; + + case 0x04: /*Command register*/ + if (dev->chip >= INTEL_430FX) { + if (dev->chip == INTEL_430FX_PB640) + val &= 0x06; + else + val &= 0x02; + } else + val &= 0x42; + val |= 0x04; + break; + + case 0x05: + if (dev->chip >= INTEL_430FX) + val = 0; + else + val &= 0x01; + break; + + case 0x06: /*Status*/ + val = 0; + break; + + case 0x07: + if (dev->chip >= INTEL_430HX) { + val &= 0x80; + val |= 0x02; + } else { + val = 0x02; + if (dev->chip == INTEL_430FX_PB640) + val |= 0x20; + } + break; + + case 0x59: /*PAM0*/ + if ((dev->regs[0x59] ^ val) & 0xf0) { + i4x0_map(0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + break; + + case 0x5a: /*PAM1*/ + if ((dev->regs[0x5a] ^ val) & 0x0f) + i4x0_map(0xc0000, 0x04000, val & 0xf); + if ((dev->regs[0x5a] ^ val) & 0xf0) + i4x0_map(0xc4000, 0x04000, val >> 4); + break; + + case 0x5b: /*PAM2*/ + if ((dev->regs[0x5b] ^ val) & 0x0f) + i4x0_map(0xc8000, 0x04000, val & 0xf); + if ((dev->regs[0x5b] ^ val) & 0xf0) + i4x0_map(0xcc000, 0x04000, val >> 4); + break; + + case 0x5c: /*PAM3*/ + if ((dev->regs[0x5c] ^ val) & 0x0f) + i4x0_map(0xd0000, 0x04000, val & 0xf); + if ((dev->regs[0x5c] ^ val) & 0xf0) + i4x0_map(0xd4000, 0x04000, val >> 4); + break; + + case 0x5d: /*PAM4*/ + if ((dev->regs[0x5d] ^ val) & 0x0f) + i4x0_map(0xd8000, 0x04000, val & 0xf); + if ((dev->regs[0x5d] ^ val) & 0xf0) + i4x0_map(0xdc000, 0x04000, val >> 4); + break; + + case 0x5e: /*PAM5*/ + if ((dev->regs[0x5e] ^ val) & 0x0f) + i4x0_map(0xe0000, 0x04000, val & 0xf); + if ((dev->regs[0x5e] ^ val) & 0xf0) + i4x0_map(0xe4000, 0x04000, val >> 4); + break; + + case 0x5f: /*PAM6*/ + if ((dev->regs[0x5f] ^ val) & 0x0f) + i4x0_map(0xe8000, 0x04000, val & 0xf); + if ((dev->regs[0x5f] ^ val) & 0xf0) + i4x0_map(0xec000, 0x04000, val >> 4); + break; + + case 0x72: /*SMRAM*/ + if ((dev->chip >= INTEL_430FX) && + ((dev->regs[0x72] ^ val) & 0x48)) + i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); + break; + } + + dev->regs[addr] = val; +} + + +static uint8_t +i4x0_read(int func, int addr, void *priv) +{ + i4x0_t *dev = (i4x0_t *)priv; + + if (func) + return 0xff; + + return dev->regs[addr]; +} + + +static void +i4x0_reset(void *priv) +{ + i4x0_t *dev = (i4x0_t *)priv; + + i4x0_write(0, 0x59, 0x00, priv); + if (dev->chip >= INTEL_430FX) + i4x0_write(0, 0x72, 0x02, priv); +} + + +static void +i4x0_close(void *priv) +{ + i4x0_t *dev = (i4x0_t *)priv; + + free(dev); +} + + +static void * +i4x0_init(const device_t *info, UNUSED(void *parent)) +{ + i4x0_t *dev; + + dev = (i4x0_t *)mem_alloc(sizeof(i4x0_t)); + memset(dev, 0x00, sizeof(i4x0_t)); + dev->chip = info->local; + + dev->regs[0x00] = 0x86; /*Intel*/ + dev->regs[0x01] = 0x80; + + switch(dev->chip) { + case INTEL_430LX: + dev->regs[0x02] = 0xa3; dev->regs[0x03] = 0x04; /*82434LX/NX*/ + dev->regs[0x08] = 0x03; /*A3 stepping*/ + dev->regs[0x50] = 0x80; + dev->regs[0x52] = 0x40; /*256kb PLB cache*/ + break; + + case INTEL_430NX: + dev->regs[0x02] = 0xa3; dev->regs[0x03] = 0x04; /*82434LX/NX*/ + dev->regs[0x08] = 0x10; /*A0 stepping*/ + dev->regs[0x50] = 0xA0; + dev->regs[0x52] = 0x44; /*256kb PLB cache*/ + dev->regs[0x66] = dev->regs[0x67] = 0x02; + break; + + case INTEL_430FX: + case INTEL_430FX_PB640: + dev->regs[0x02] = 0x2d; dev->regs[0x03] = 0x12; /*SB82437FX-66*/ + if (dev->chip == INTEL_430FX_PB640) + dev->regs[0x08] = 0x02; /*???? stepping*/ + else + dev->regs[0x08] = 0x00; /*A0 stepping*/ + dev->regs[0x52] = 0x40; /*256kb PLB cache*/ + break; + + case INTEL_430HX: + dev->regs[0x02] = 0x50; dev->regs[0x03] = 0x12; /*82439HX*/ + dev->regs[0x08] = 0x00; /*A0 stepping*/ + dev->regs[0x51] = 0x20; + dev->regs[0x52] = 0xB5; /*512kb cache*/ + dev->regs[0x56] = 0x52; /*DRAM control*/ + dev->regs[0x59] = 0x40; + dev->regs[0x5A] = dev->regs[0x5B] = \ + dev->regs[0x5C] = dev->regs[0x5D] = 0x44; + dev->regs[0x5E] = dev->regs[0x5F] = 0x44; + dev->regs[0x65] = dev->regs[0x66] = dev->regs[0x67] = 0x02; + dev->regs[0x68] = 0x11; + break; + + case INTEL_430VX: + dev->regs[0x02] = 0x30; dev->regs[0x03] = 0x70; /*82437VX*/ + dev->regs[0x08] = 0x00; /*A0 stepping*/ + dev->regs[0x52] = 0x42; /*256kb PLB cache*/ + dev->regs[0x53] = 0x14; + dev->regs[0x56] = 0x52; /*DRAM control*/ + dev->regs[0x67] = 0x11; + dev->regs[0x69] = 0x03; + dev->regs[0x70] = 0x20; + dev->regs[0x74] = 0x0e; + dev->regs[0x78] = 0x23; + break; + + case INTEL_440FX: + dev->regs[0x02] = 0x37; dev->regs[0x03] = 0x12; /*82441FX*/ + dev->regs[0x08] = 0x02; /*A0 stepping*/ + dev->regs[0x2c] = 0xf4; + dev->regs[0x2d] = 0x1a; + dev->regs[0x2f] = 0x11; + dev->regs[0x51] = 0x01; + dev->regs[0x53] = 0x80; + dev->regs[0x58] = 0x10; + dev->regs[0x5a] = dev->regs[0x5b] = \ + dev->regs[0x5c] = dev->regs[0x5d] = 0x11; + dev->regs[0x5e] = 0x11; + dev->regs[0x5f] = 0x31; + break; + } + + dev->regs[0x04] = 0x06; dev->regs[0x05] = 0x00; + if (dev->chip == INTEL_440FX) + dev->regs[0x06] = 0x80; + + if (dev->chip == INTEL_430FX) + dev->regs[0x07] = 0x82; + else if (dev->chip != INTEL_440FX) + dev->regs[0x07] = 0x02; + dev->regs[0x0b] = 0x06; + if (dev->chip >= INTEL_430FX) + dev->regs[0x57] = 0x01; + else + dev->regs[0x57] = 0x31; + dev->regs[0x60] = dev->regs[0x61] = dev->regs[0x62] = \ + dev->regs[0x63] = 0x02; + dev->regs[0x64] = 0x02; + if (dev->chip >= INTEL_430FX) + dev->regs[0x72] = 0x02; + + pci_add_card(0, i4x0_read, i4x0_write, dev); + + return dev; +} + + +const device_t i430lx_device = { + "Intel 82434LX", + DEVICE_PCI, + INTEL_430LX, + NULL, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t i430nx_device = { + "Intel 82434NX", + DEVICE_PCI, + INTEL_430NX, + NULL, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t i430fx_device = { + "Intel SB82437FX-66", + DEVICE_PCI, + INTEL_430FX, + NULL, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t i430fx_pb640_device = { + "Intel SB82437FX-66 (PB640)", + DEVICE_PCI, + INTEL_430FX_PB640, + NULL, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t i430hx_device = { + "Intel 82439HX", + DEVICE_PCI, + INTEL_430HX, + NULL, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t i430vx_device = { + "Intel 82437VX", + DEVICE_PCI, + INTEL_430VX, + NULL, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t i440fx_device = { + "Intel 82441FX", + DEVICE_PCI, + INTEL_440FX, + NULL, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/chipsets/intel4x0.h b/src/devices/chipsets/intel4x0.h new file mode 100644 index 0000000..bffef10 --- /dev/null +++ b/src/devices/chipsets/intel4x0.h @@ -0,0 +1,62 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Intel 430/440 chipsets. + * + * Version: @(#)intel4x0.h 1.0.1 2019/04/11 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef INTEL4X0_H +# define INTEL4X0_H + + +#ifdef EMU_DEVICE_H +extern const device_t i430lx_device; +extern const device_t i430nx_device; +extern const device_t i430fx_device; +extern const device_t i430fx_pb640_device; +extern const device_t i430hx_device; +extern const device_t i430vx_device; +extern const device_t i440fx_device; +#endif + + +#endif /*INTEL4X0_H*/ diff --git a/src/machines/m_at_neat.c b/src/devices/chipsets/neat.c similarity index 97% rename from src/machines/m_at_neat.c rename to src/devices/chipsets/neat.c index a94c18a..3681e06 100644 --- a/src/machines/m_at_neat.c +++ b/src/devices/chipsets/neat.c @@ -6,14 +6,14 @@ * * This file is part of the VARCem Project. * - * Emulation of C&T CS8121 ("NEAT") 82C206/211/212/215 chipset. + * Emulation of C&T CS8221 ("NEAT") 82C206/211/212/215 chipset. * * Note: The datasheet mentions that the chipset supports up to 8MB * of DRAM. This is intepreted as 'being able to refresh up to * 8MB of DRAM chips', because it works fine with bus-based * memory expansion. * - * Version: @(#)m_at_neat.c 1.0.3 2019/02/16 + * Version: @(#)neat.c 1.0.5 2019/04/08 * * Author: Fred N. van Kempen, * @@ -54,14 +54,13 @@ #include #include #include -#include "../emu.h" -#include "../io.h" -#include "../mem.h" -#include "../device.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "machine.h" +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../device.h" +#include "../../plat.h" +#include "neat.h" #define EMS_MAXPAGE 4 @@ -242,10 +241,10 @@ typedef struct { } emspage_t; typedef struct { - uint8_t regs[128]; /* all the CS8221 registers */ - uint8_t indx; /* programmed index into registers */ + uint8_t type; - char pad; + uint8_t indx; /* programmed index into registers */ + uint8_t regs[128]; /* all the CS8221 registers */ uint16_t ems_base, /* configured base address */ ems_oldbase; @@ -432,7 +431,7 @@ ems_init(neat_t *dev, int en) /* Get configured frame address. */ i = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; - dev->ems_frame = 0xC0000 + (EMS_PGSIZE * i); + dev->ems_frame = 0xc0000 + (EMS_PGSIZE * i); /* * For each supported page (we can have a maximum of 4), @@ -655,7 +654,16 @@ neat_read(uint16_t port, void *priv) static void -neat_init(void) +neat_close(void *priv) +{ + neat_t *dev = (neat_t *)priv; + + free(dev); +} + + +static void * +neat_init(const device_t *info, UNUSED(void *parent)) { neat_t *dev; int i; @@ -663,6 +671,7 @@ neat_init(void) /* Create an instance. */ dev = (neat_t *)mem_alloc(sizeof(neat_t)); memset(dev, 0x00, sizeof(neat_t)); + dev->type = info->local; /* Initialize some of the registers to specific defaults. */ for (i = REG_RA0; i <= REG_RB11; i++) { @@ -807,28 +816,17 @@ neat_init(void) /* Set up an I/O handler for the chipset. */ io_sethandler(0x0022, 2, neat_read,NULL,NULL, neat_write,NULL,NULL, dev); + + return(dev); } -void -m_at_neat_init(const machine_t *model, void *arg) -{ - m_at_init(model, arg); - - neat_init(); - - device_add(&fdc_at_device); -} - - -void -m_at_neat_ami_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - neat_init(); - - device_add(&keyboard_at_ami_device); - - device_add(&fdc_at_device); -} +const device_t neat_device = { + "C&T CS8221 (\"NEAT\")", + 0, + 0, + NULL, + neat_init, neat_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/chipsets/neat.h b/src/devices/chipsets/neat.h new file mode 100644 index 0000000..c5a1615 --- /dev/null +++ b/src/devices/chipsets/neat.h @@ -0,0 +1,56 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the C&T "NEAT" chipset. + * + * Version: @(#)neat.h 1.0.1 2019/04/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NEAT_H +# define NEAT_H + + +#ifdef EMU_DEVICE_H +extern const device_t neat_device; +#endif + + +#endif /*NEAT_H*/ diff --git a/src/machines/m_at_opti495.c b/src/devices/chipsets/opti495.c similarity index 87% rename from src/machines/m_at_opti495.c rename to src/devices/chipsets/opti495.c index 0d6d23e..96e1110 100644 --- a/src/machines/m_at_opti495.c +++ b/src/devices/chipsets/opti495.c @@ -8,8 +8,6 @@ * * Implementation of the Opti 82C495 chipset. * - * This is the chipset used in the AMI386 model - * * Details for the chipset from Ralph Brown's interrupt list * This describes the OPTi 82C493, the 82C495 seems similar * except there is one more register (2C) @@ -260,7 +258,7 @@ 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 * - * Version: @(#)m_at_opti495.c 1.0.9 2019/02/16 + * Version: @(#)opti495.c 1.0.11 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -291,38 +289,44 @@ SeeAlso: #P0178,#P0187 #include #include #include +#include #include -#include "../emu.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../device.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "machine.h" +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../device.h" +#include "../../plat.h" +#include "opti495.h" -static uint8_t optiregs[0x10]; -static int optireg; +typedef struct { + int type; + + int indx; + uint8_t regs[0x10]; +} opti_t; static void -opti495_write(uint16_t addr, uint8_t val, void *p) +opti495_write(uint16_t addr, uint8_t val, void *priv) { + opti_t *dev = (opti_t *)priv; + switch (addr) { case 0x22: - optireg = val; + dev->indx = val; break; case 0x24: - if (optireg >= 0x20 && optireg <= 0x2C) { - optiregs[optireg - 0x20] = val; - if (optireg == 0x21) { + if (dev->indx >= 0x20 && dev->indx <= 0x2C) { + dev->regs[dev->indx - 0x20] = val; + if (dev->indx == 0x21) { cpu_cache_ext_enabled = val & 0x10; cpu_update_waitstates(); } - if (optireg == 0x22) { + if (dev->indx == 0x22) { shadowbios = !(val & 0x80); shadowbios_write = val & 0x80; if (shadowbios) @@ -337,62 +341,57 @@ opti495_write(uint16_t addr, uint8_t val, void *p) static uint8_t -opti495_read(uint16_t addr, void *p) +opti495_read(uint16_t addr, void *priv) { + opti_t *dev = (opti_t *)priv; + uint8_t ret = 0xff; + switch (addr) { case 0x24: - if (optireg >= 0x20 && optireg <= 0x2c) - return(optiregs[optireg - 0x20]); + if (dev->indx >= 0x20 && dev->indx <= 0x2c) + ret = dev->regs[dev->indx - 0x20]; break; } - return(0xff); + return(ret); } static void -opti495_init(void) +opti_close(void *priv) { + opti_t *dev = (opti_t *)priv; + + free(dev); +} + + +static void * +opti_init(const device_t *info, UNUSED(void *parent)) +{ + opti_t *dev; + + dev = (opti_t *)mem_alloc(sizeof(opti_t)); + memset(dev, 0x00, sizeof(opti_t)); + dev->type = info->local; + + dev->regs[0x22 - 0x20] = 0x80; + io_sethandler(0x0022, 1, - opti495_read,NULL,NULL, opti495_write,NULL,NULL, NULL); + opti495_read,NULL,NULL, opti495_write,NULL,NULL, dev); io_sethandler(0x0024, 1, - opti495_read,NULL,NULL, opti495_write,NULL,NULL, NULL); + opti495_read,NULL,NULL, opti495_write,NULL,NULL, dev); - optiregs[0x22 - 0x20] = 0x80; + return(dev); } -void -m_at_opti495_ami_init(const machine_t *model, void *arg) -{ - m_at_common_ide_init(model, arg); - - device_add(&keyboard_at_ami_device); - device_add(&fdc_at_device); - - opti495_init(); -} - - -void -m_at_opti495_award_init(const machine_t *model, void *arg) -{ - m_at_common_ide_init(model, arg); - - device_add(&keyboard_at_device); - device_add(&fdc_at_device); - - opti495_init(); -} - - -void -m_at_opti495_mr_init(const machine_t *model, void *arg) -{ - m_at_common_ide_init(model, arg); - - device_add(&keyboard_at_ami_device); - device_add(&fdc_at_device); - - opti495_init(); -} +const device_t opti495_device = { + "Opti 82C495", + 0, + 0, + NULL, + opti_init, opti_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/chipsets/opti495.h b/src/devices/chipsets/opti495.h new file mode 100644 index 0000000..c01ecf9 --- /dev/null +++ b/src/devices/chipsets/opti495.h @@ -0,0 +1,56 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Opti 82C495 chipset. + * + * Version: @(#)opti495.h 1.0.1 2019/04/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef OPTI495_H +# define OPTI495_H + + +#ifdef EMU_DEVICE_H +extern const device_t opti495_device; +#endif + + +#endif /*OPTI495_H*/ diff --git a/src/devices/chipsets/scat.c b/src/devices/chipsets/scat.c new file mode 100644 index 0000000..455e686 --- /dev/null +++ b/src/devices/chipsets/scat.c @@ -0,0 +1,1641 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the C&T 82C235 ("SCAT") chipset. + * + * Version: @(#)scat.c 1.0.16 2019/04/20 + * + * Authors: Fred N. van Kempen, + * Original by GreatPsycho for PCem. + * Miran Grca, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../cpu/x86.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../device.h" +#include "../../plat.h" +#include "../system/nmi.h" +#include "scat.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 SCATSX_LAPTOP_FEATURES 0x60 +#define SCATSX_FAST_VIDEO_CONTROL 0x61 +#define SCATSX_FAST_VIDEORAM_ENABLE 0x62 +#define SCATSX_HIGH_PERFORMANCE_REFRESH 0x63 +#define SCATSX_CAS_TIMING_FOR_DMA 0x64 + + +typedef struct { + uint8_t regs_2x8; + uint8_t regs_2x9; +} ems_page_t; + +typedef struct { + int type; + + int indx; + uint8_t regs[256]; + uint8_t reg_2xA; + uint8_t port_92; + + uint32_t xms_bound; + + int external_is_RAS; + + ems_page_t page[32]; + + mem_map_t low_mapping[32]; + mem_map_t high_mapping[16]; + mem_map_t remap_mapping[6]; + mem_map_t efff_mapping[44]; + mem_map_t romcs_mapping[8]; + mem_map_t ems_mapping[32]; +} scat_t; + + +static const uint8_t max_map[32] = { + 0, 1, 1, 1, 2, 3, 4, 8, + 4, 8, 12, 16, 20, 24, 28, 32, + 0, 5, 9, 13, 6, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static const uint8_t max_map_sx[32] = { + 0, 1, 2, 1, 3, 4, 6, 10, + 5, 9, 13, 4, 8, 12, 16, 14, + 18, 22, 26, 20, 24, 28, 32, 18, + 20, 32, 0, 0, 0, 0, 0, 0 +}; +static const uint8_t scatsx_external_is_RAS[33] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0 +}; + + +static uint8_t scat_read(uint16_t port, void *priv); +static void scat_write(uint16_t port, uint8_t val, void *priv); + + +static void +romcs_state_update(scat_t *dev, uint8_t val) +{ + int i; + + for (i = 0; i < 4; i++) { + if (val & 1) { + mem_map_enable(&dev->romcs_mapping[i << 1]); + mem_map_enable(&dev->romcs_mapping[(i << 1) + 1]); + } else { + mem_map_disable(&dev->romcs_mapping[i << 1]); + mem_map_disable(&dev->romcs_mapping[(i << 1) + 1]); + } + val >>= 1; + } + + for (i = 0; i < 4; i++) { + if (val & 1) { + mem_map_enable(&bios_mapping[i << 1]); + mem_map_enable(&bios_mapping[(i << 1) + 1]); + } else { + mem_map_disable(&bios_mapping[i << 1]); + mem_map_disable(&bios_mapping[(i << 1) + 1]); + } + val >>= 1; + } +} + + +static void +shadow_state_update(scat_t *dev) +{ + int i, val; + + for (i = 0; i < 24; i++) { + val = ((dev->regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL | MEM_WRITE_INTERNAL : MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; + mem_set_mem_state((i + 40) << 14, 0x4000, val); + } + + flushmmucache(); +} + + +static void +set_xms_bound(scat_t *dev, uint8_t val) +{ + uint32_t xms_max = ((dev->regs[SCAT_VERSION] & 0xf0) != 0 && ((val & 0x10) != 0)) || (dev->regs[SCAT_VERSION] >= 4) ? 0xfe0000 : 0xfc0000; + int i; + + switch (val & 0x0f) { + case 1: + dev->xms_bound = 0x100000; + break; + + case 2: + dev->xms_bound = 0x140000; + break; + + case 3: + dev->xms_bound = 0x180000; + break; + + case 4: + dev->xms_bound = 0x200000; + break; + + case 5: + dev->xms_bound = 0x300000; + break; + + case 6: + dev->xms_bound = 0x400000; + break; + + case 7: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x600000 : 0x500000; + break; + + case 8: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x800000 : 0x700000; + break; + + case 9: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xa00000 : 0x800000; + break; + + case 10: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xc00000 : 0x900000; + break; + + case 11: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xe00000 : 0xa00000; + break; + + case 12: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xb00000; + break; + + case 13: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xc00000; + break; + + case 14: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xd00000; + break; + + case 15: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xf00000; + break; + + default: + dev->xms_bound = xms_max; + break; + } + + if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && (val & 0x40) == 0 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3) || + (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3)) { + if ((val & 0x0f) == 0 || dev->xms_bound > 0x160000) + dev->xms_bound = 0x160000; + + if (dev->xms_bound > 0x100000) + mem_set_mem_state(0x100000, dev->xms_bound - 0x100000, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + + if (dev->xms_bound < 0x160000) + mem_set_mem_state(dev->xms_bound, 0x160000 - dev->xms_bound, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } else { + if (dev->xms_bound > xms_max) + dev->xms_bound = xms_max; + + if (dev->xms_bound > 0x100000) + mem_set_mem_state(0x100000, dev->xms_bound - 0x100000, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + + if (dev->xms_bound < ((uint32_t)mem_size << 10)) + mem_set_mem_state(dev->xms_bound, (mem_size << 10) - dev->xms_bound, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + + mem_map_set_addr(&dev->low_mapping[31], 0xf80000, + ((dev->regs[SCAT_VERSION] & 0xf0) != 0 && ((val & 0x10) != 0)) || + (dev->regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000); + if (dev->regs[SCAT_VERSION] & 0xf0) { + for (i = 0; i < 8; i++) { + if (val & 0x10) + mem_map_disable(&dev->high_mapping[i]); + else + mem_map_enable(&dev->high_mapping[i]); + } + } +} + + +static uint32_t +get_addr(scat_t *dev, uint32_t addr, ems_page_t *p) +{ + int nbanks_2048k, nbanks_512k; + uint32_t addr2; + int nbank; + + if (p && (dev->regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80)) + addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; + + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { + switch((dev->regs[SCAT_EXTENDED_BOUNDARY] & ((dev->regs[SCAT_VERSION] & 0x0f) > 3 ? 0x40 : 0)) | (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f)) { + case 0x41: + nbank = addr >> 19; + if (nbank < 4) + nbank = 1; + else if (nbank == 4) + nbank = 0; + else + nbank -= 3; + break; + + case 0x42: + nbank = addr >> 19; + if (nbank < 8) + nbank = 1 + (nbank >> 2); + else if (nbank == 8) + nbank = 0; + else + nbank -= 6; + break; + + case 0x43: + nbank = addr >> 19; + if (nbank < 12) + nbank = 1 + (nbank >> 2); + else if (nbank == 12) + nbank = 0; + else + nbank -= 9; + break; + + case 0x44: + nbank = addr >> 19; + if (nbank < 4) + nbank = 2; + else if (nbank < 6) + nbank -= 4; + else + nbank -= 3; + break; + + case 0x45: + nbank = addr >> 19; + if (nbank < 8) + nbank = 2 + (nbank >> 2); + else if (nbank < 10) + nbank -= 8; + else + nbank -= 6; + break; + + default: + nbank = addr >> (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) < 8 && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21); + break; + } + + nbank &= (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; + + if ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && + (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3 && + nbank == 2 && (addr & 0x7ffff) < 0x60000 && mem_size > 640) { + nbank = 1; + addr ^= 0x70000; + } + + if (dev->external_is_RAS && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { + if (nbank == 3) + nbank = 7; + else + return 0xffffffff; + } else if (!dev->external_is_RAS && dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { + switch(nbank) { + case 7: + nbank = 3; + break; + + /* Note - In the following cases, the chipset accesses multiple memory banks + at the same time, so it's impossible to predict which memory bank + is actually accessed. */ + case 5: + case 1: + nbank = 1; + break; + + case 3: + nbank = 2; + break; + + default: + nbank = 0; + break; + } + } + + if ((dev->regs[SCAT_VERSION] & 0x0f) > 3 && (mem_size > 2048) && (mem_size & 1536)) { + if ((mem_size & 1536) == 512) { + if (nbank == 0) + addr &= 0x7ffff; + else + addr = 0x80000 + ((addr & 0x1fffff) | ((nbank - 1) << 21)); + } else { + if (nbank < 2) + addr = (addr & 0x7ffff) | (nbank << 19); + else + addr = 0x100000 + ((addr & 0x1fffff) | ((nbank - 2) << 21)); + } + } else { + if (mem_size <= ((dev->regs[SCAT_VERSION] & 0x0f) > 3 ? 2048 : 4096) && (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) < 8) || dev->external_is_RAS)) { + nbanks_2048k = 0; + nbanks_512k = mem_size >> 9; + } else { + nbanks_2048k = mem_size >> 11; + nbanks_512k = (mem_size & 1536) >> 9; + } + + if (nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))) { + addr &= 0x1fffff; + addr |= (nbank << 21); + } else if (nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)) { + addr &= 0x7ffff; + addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19); + } else { + addr &= 0x1ffff; + addr |= (nbanks_2048k << 21) | (nbanks_512k << 19) | ((nbank - nbanks_2048k - nbanks_512k) << 17); + } + } + } else { + switch(dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) { + case 0x02: + case 0x04: + nbank = addr >> 19; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else + addr2 = addr >> 10; + break; + + case 0x03: + nbank = addr >> 19; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7ffff) < 0x60000) { + addr ^= 0x1f0000; + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else + addr2 = addr >> 10; + break; + + case 0x05: + nbank = addr >> 19; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { + nbank = (addr >> 10) & 3; + addr2 = addr >> 12; + } else + addr2 = addr >> 10; + break; + + case 0x06: + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else { + nbank = 2 + ((addr - 0x100000) >> 21); + addr2 = (addr - 0x100000) >> 11; + } + break; + + case 0x07: + case 0x0f: + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if (nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else { + nbank = 4 + ((addr - 0x500000) >> 21); + addr2 = (addr - 0x500000) >> 11; + } + break; + + case 0x08: + nbank = addr >> 19; + if (nbank < 4) { + nbank = 1; + addr2 = addr >> 11; + } else if (nbank == 4) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 3; + addr2 = addr >> 10; + } + break; + + case 0x09: + nbank = addr >> 19; + if (nbank < 8) { + nbank = 1 + ((addr >> 11) & 1); + addr2 = addr >> 12; + } else if (nbank == 8) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 6; + addr2 = addr >> 10; + } + break; + + case 0x0a: + nbank = addr >> 19; + if (nbank < 8) { + nbank = 1 + ((addr >> 11) & 1); + addr2 = addr >> 12; + } else if (nbank < 12) { + nbank = 3; + addr2 = addr >> 11; + } else if (nbank == 12) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 9; + addr2 = addr >> 10; + } + break; + + case 0x0b: + nbank = addr >> 21; + addr2 = addr >> 11; + break; + + case 0x0c: + case 0x0d: + nbank = addr >> 21; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 11) & 1; + addr2 = addr >> 12; + } else + addr2 = addr >> 11; + break; + + case 0x0e: + case 0x13: + nbank = addr >> 21; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { + nbank = (addr >> 11) & 3; + addr2 = addr >> 13; + } else + addr2 = addr >> 11; + break; + + case 0x10: + case 0x11: + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if (nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else if (nbank < 18) { + nbank = 4 + (((addr - 0x500000) >> 11) & 1); + addr2 = (addr - 0x500000) >> 12; + } else { + nbank = 6 + ((addr - 0x900000) >> 21); + addr2 = (addr - 0x900000) >> 11; + } + break; + + case 0x12: + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if (nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else { + nbank = 4 + (((addr - 0x500000) >> 11) & 3); + addr2 = (addr - 0x500000) >> 13; + } + break; + + case 0x14: + case 0x15: + nbank = addr >> 21; + if ((nbank & 7) < 4) { + nbank = (addr >> 11) & 3; + addr2 = addr >> 13; + } else if ((nbank & 7) < 6) { + nbank = 4 + (((addr - 0x800000) >> 11) & 1); + addr2 = (addr - 0x800000) >> 12; + } else { + nbank = 6 + (((addr - 0xc00000) >> 11) & 3); + addr2 = (addr - 0xc00000) >> 13; + } + break; + + case 0x16: + nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3); + addr2 = addr >> 13; + break; + + case 0x17: + if (dev->external_is_RAS && (addr & 0x800) == 0) + return 0xffffffff; + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else { + nbank = 2 + ((addr - 0x100000) >> 23); + addr2 = (addr - 0x100000) >> 12; + } + break; + + case 0x18: + if (dev->external_is_RAS && (addr & 0x800) == 0) + return 0xffffffff; + nbank = addr >> 21; + if (nbank < 4) { + nbank = 1; + addr2 = addr >> 12; + } else if (nbank == 4) { + nbank = 0; + addr2 = addr >> 11; + } else { + nbank -= 3; + addr2 = addr >> 11; + } + break; + + case 0x19: + if (dev->external_is_RAS && (addr & 0x800) == 0) + return 0xffffffff; + nbank = addr >> 23; + if ((nbank & 3) < 2) { + nbank = (addr >> 12) & 1; + addr2 = addr >> 13; + } else + addr2 = addr >> 12; + break; + + default: + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 6) { + nbank = addr >> 19; + addr2 = (addr >> 10) & 0x1ff; + } else if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 0x17) { + nbank = addr >> 21; + addr2 = (addr >> 11) & 0x3ff; + } else { + nbank = addr >> 23; + addr2 = (addr >> 12) & 0x7ff; + } + break; + } + + nbank &= (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; + + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) > 0x16 && nbank == 3) + return 0xffffffff; + + if (dev->external_is_RAS && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { + if (nbank == 3) + nbank = 7; + else + return 0xffffffff; + } else if (!dev->external_is_RAS && dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { + switch(nbank) { + case 7: + nbank = 3; + break; + + /* Note - In the following cases, the chipset accesses multiple memory banks + at the same time, so it's impossible to predict which memory bank + is actually accessed. */ + case 5: + case 1: + nbank = 1; + break; + + case 3: + nbank = 2; + break; + + default: + nbank = 0; + break; + } + } + + switch(mem_size & ~511) { + case 1024: + case 1536: + addr &= 0x3ff; + if (nbank < 2) + addr |= (nbank << 10) | ((addr2 & 0x1ff) << 11); + else + addr |= ((addr2 & 0x1ff) << 10) | (nbank << 19); + break; + + case 2048: + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 5) { + addr &= 0x3ff; + if (nbank < 4) + addr |= (nbank << 10) | ((addr2 & 0x1ff) << 12); + else + addr |= ((addr2 & 0x1ff) << 10) | (nbank << 19); + } else { + addr &= 0x7ff; + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + } + break; + + case 2560: + if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); + } + break; + + case 3072: + if (nbank < 2) + addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); + else + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); + break; + + case 4096: + case 6144: + addr &= 0x7ff; + if (nbank < 2) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 12); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + break; + + case 4608: + if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) >= 8 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) <= 0x0a) || ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 0x18)) { + if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else if (nbank < 3) + addr = 0x80000 + ((addr & 0x7ff) | ((nbank - 1) << 11) | ((addr2 & 0x3ff) << 12)); + else + addr = 0x480000 + ((addr & 0x3ff) | ((addr2 & 0x1ff) << 10) | ((nbank - 3) << 19)); + } else if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); + } + break; + + case 5120: + case 7168: + if (nbank < 2) + addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); + else if (nbank < 4) + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); + break; + + case 6656: + if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) >= 8 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) <= 0x0a) || ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 0x18)) { + if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else if (nbank < 3) + addr = 0x80000 + ((addr & 0x7ff) | ((nbank - 1) << 11) | ((addr2 & 0x3ff) << 12)); + else if (nbank == 3) + addr = 0x480000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11)); + else + addr = 0x680000 + ((addr & 0x3ff) | ((addr2 & 0x1ff) << 10) | ((nbank - 4) << 19)); + } else if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else if (nbank == 1) { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr = addr + 0x80000 + (addr2 << 11); + } else { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr = addr + 0x280000 + ((addr2 << 12) | ((nbank & 1) << 11) | (((nbank - 2) & 6) << 21)); + } + break; + + case 8192: + addr &= 0x7ff; + if (nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + break; + + case 9216: + if (nbank < 2) + addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); + else if (dev->external_is_RAS) { + if (nbank < 6) + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); + } else + addr = 0x100000 + ((addr & 0xfff) | ((addr2 & 0x7ff) << 12) | ((nbank - 2) << 23)); + break; + + case 10240: + if (dev->external_is_RAS) { + addr &= 0x7ff; + if (nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + } else if (nbank == 0) + addr = (addr & 0x7ff) | ((addr2 & 0x3ff) << 11); + else { + addr &= 0xfff; + addr2 &= 0x7ff; + addr = addr + 0x200000 + ((addr2 << 12) | ((nbank - 1) << 23)); + } + break; + + case 11264: + if (nbank < 2) + addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); + else if (nbank < 6) + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); + break; + + case 12288: + if (dev->external_is_RAS) { + addr &= 0x7ff; + if (nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); + else if (nbank < 6) + addr |= ((nbank & 1) << 11) | ((addr2 & 0x3ff) << 12) | ((nbank & 4) << 21); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + } else { + if (nbank < 2) + addr = (addr & 0x7ff) | (nbank << 11) | ((addr2 & 0x3ff) << 12); + else + addr = 0x400000 + ((addr & 0xfff) | ((addr2 & 0x7ff) << 12) | ((nbank - 2) << 23)); + } + break; + + case 13312: + if (nbank < 2) + addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); + else if (nbank < 4) + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); + else + addr = 0x500000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 13) | ((nbank & 3) << 11)); + break; + + case 14336: + addr &= 0x7ff; + if (nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); + else if (nbank < 6) + addr |= ((nbank & 1) << 11) | ((addr2 & 0x3ff) << 12) | ((nbank & 4) << 21); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + break; + + case 16384: + if (dev->external_is_RAS) { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr |= ((nbank & 3) << 11) | (addr2 << 13) | ((nbank & 4) << 21); + } else { + addr &= 0xfff; + addr2 &= 0x7ff; + if (nbank < 2) + addr |= (addr2 << 13) | (nbank << 12); + else + addr |= (addr2 << 12) | (nbank << 23); + } + break; + + default: + if (mem_size < 2048 || ((mem_size & 1536) == 512) || (mem_size == 2048 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 6)) { + addr &= 0x3ff; + addr2 &= 0x1ff; + addr |= (addr2 << 10) | (nbank << 19); + } else if (mem_size < 8192 || (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 0x17) { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr |= (addr2 << 11) | (nbank << 21); + } else { + addr &= 0xfff; + addr2 &= 0x7ff; + addr |= (addr2 << 12) | (nbank << 23); + } + break; + } + } + + return addr; +} + + +static void +set_global_EMS_state(scat_t *dev, int state) +{ + uint32_t base_addr, virt_addr; + int i, conf; + + for (i = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0 : 24; i < 32; i++) { + base_addr = (i + 16) << 14; + + if (i >= 24) + base_addr += 0x30000; + if (state && (dev->page[i].regs_2x9 & 0x80)) { + virt_addr = get_addr(dev, base_addr, &dev->page[i]); + if (i < 24) + mem_map_disable(&dev->efff_mapping[i]); + else + mem_map_disable(&dev->efff_mapping[i + 12]); + mem_map_enable(&dev->ems_mapping[i]); + + if (virt_addr < ((uint32_t)mem_size << 10)) + mem_map_set_exec(&dev->ems_mapping[i], ram + virt_addr); + else + mem_map_set_exec(&dev->ems_mapping[i], NULL); + } else { + mem_map_set_exec(&dev->ems_mapping[i], ram + base_addr); + mem_map_disable(&dev->ems_mapping[i]); + + conf = (dev->regs[SCAT_VERSION] & 0xf0) ? (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) + : (dev->regs[SCAT_DRAM_CONFIGURATION] & 0xf) | ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2); + if (i < 24) { + if (conf > 1 || (conf == 1 && i < 16)) + mem_map_enable(&dev->efff_mapping[i]); + else + mem_map_disable(&dev->efff_mapping[i]); + } else if (conf > 3 || ((dev->regs[SCAT_VERSION] & 0xf0) != 0 && conf == 2)) + mem_map_enable(&dev->efff_mapping[i + 12]); + else + mem_map_disable(&dev->efff_mapping[i + 12]); + } + } + + flushmmucache(); +} + + +static void +memmap_state_update(scat_t *dev) +{ + uint32_t addr; + int i; + + for (i = (((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0 : 16); i < 44; i++) { + addr = get_addr(dev, 0x40000 + (i << 14), NULL); + mem_map_set_exec(&dev->efff_mapping[i], + addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + } + + addr = get_addr(dev, 0, NULL); + mem_map_set_exec(&dev->low_mapping[0], + addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + + addr = get_addr(dev, 0xf0000, NULL); + mem_map_set_exec(&dev->low_mapping[1], + addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + + for (i = 2; i < 32; i++) { + addr = get_addr(dev, i << 19, NULL); + mem_map_set_exec(&dev->low_mapping[i], + addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + } + + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { + for (i = 0; i < max_map[(dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) | ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)]; i++) + mem_map_enable(&dev->low_mapping[i]); + + for (; i < 32; i++) + mem_map_disable(&dev->low_mapping[i]); + + for (i = 24; i < 36; i++) { + if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) | (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4) + mem_map_disable(&dev->efff_mapping[i]); + else + mem_map_enable(&dev->efff_mapping[i]); + } + } else { + for (i = 0; i < max_map_sx[dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f]; i++) + mem_map_enable(&dev->low_mapping[i]); + + for (; i < 32; i++) + mem_map_disable(&dev->low_mapping[i]); + + for(i = 24; i < 36; i++) { + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 2 || (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3) + mem_map_disable(&dev->efff_mapping[i]); + else + mem_map_enable(&dev->efff_mapping[i]); + } + } + + if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && + (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((dev->regs[SCAT_VERSION] & 0xf0) != 0)) { + if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && + (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3) || + (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3)) { + mem_map_disable(&dev->low_mapping[2]); + + for (i = 0; i < 6; i++) { + addr = get_addr(dev, 0x100000 + (i << 16), NULL); + mem_map_set_exec(&dev->remap_mapping[i], + addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + mem_map_enable(&dev->remap_mapping[i]); + } + } else { + for (i = 0; i < 6; i++) + mem_map_disable(&dev->remap_mapping[i]); + + if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && + (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) > 4) || (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) > 3)) + mem_map_enable(&dev->low_mapping[2]); + } + } else { + for (i = 0; i < 6; i++) + mem_map_disable(&dev->remap_mapping[i]); + + mem_map_enable(&dev->low_mapping[2]); + } + + set_global_EMS_state(dev, dev->regs[SCAT_EMS_CONTROL] & 0x80); +} + + +static void +scat_write(uint16_t port, uint8_t val, void *priv) +{ + scat_t *dev = (scat_t *)priv; + uint8_t reg_valid = 0, + shadow_update = 0, + map_update = 0, + indx; + uint32_t base_addr, virt_addr; + + switch (port) { + case 0x22: + dev->indx = val; + break; + + case 0x23: + switch (dev->indx) { + case SCAT_DMA_WAIT_STATE_CONTROL: + case SCAT_CLOCK_CONTROL: + case SCAT_PERIPHERAL_CONTROL: + reg_valid = 1; + break; + + case SCAT_EMS_CONTROL: + if (val & 0x40) { + if (val & 1) { + io_sethandler(0x0218, 3, scat_read,NULL,NULL, scat_write,NULL,NULL, dev); + io_removehandler(0x0208, 3, scat_read,NULL,NULL, scat_write,NULL,NULL, dev); + } else { + io_sethandler(0x0208, 3, scat_read,NULL,NULL, scat_write,NULL,NULL, dev); + io_removehandler(0x0218, 3, scat_read,NULL,NULL, scat_write,NULL,NULL, dev); + } + } else { + io_removehandler(0x0208, 0x0003, scat_read,NULL,NULL, scat_write,NULL,NULL, dev); + io_removehandler(0x0218, 0x0003, scat_read,NULL,NULL, scat_write,NULL,NULL, dev); + } + set_global_EMS_state(dev, val & 0x80); + reg_valid = 1; + break; + + case SCAT_POWER_MANAGEMENT: + /* TODO - Only use AUX parity disable bit for this version. + Other bits should be implemented later. */ + val &= (dev->regs[SCAT_VERSION] & 0xf0) == 0 ? 0x40 : 0x60; + reg_valid = 1; + break; + + case SCAT_DRAM_CONFIGURATION: + map_update = 1; + + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { + cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; + cpu_update_waitstates(); + } + + reg_valid = 1; + break; + + case SCAT_EXTENDED_BOUNDARY: + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { + if (dev->regs[SCAT_VERSION] < 4) { + val &= 0xbf; + set_xms_bound(dev, val & 0x0f); + } else { + val = (val & 0x7f) | 0x80; + set_xms_bound(dev, val & 0x4f); + } + } else + set_xms_bound(dev, val & 0x1f); + + mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if ((val ^ dev->regs[SCAT_EXTENDED_BOUNDARY]) & 0xc0) + map_update = 1; + reg_valid = 1; + break; + + case SCAT_ROM_ENABLE: + romcs_state_update(dev, val); + reg_valid = 1; + break; + + case SCAT_RAM_WRITE_PROTECT: + reg_valid = 1; + flushmmucache_cr3(); + break; + + case SCAT_SHADOW_RAM_ENABLE_1: + case SCAT_SHADOW_RAM_ENABLE_2: + case SCAT_SHADOW_RAM_ENABLE_3: + reg_valid = 1; + shadow_update = 1; + break; + + case SCATSX_LAPTOP_FEATURES: + if ((dev->regs[SCAT_VERSION] & 0xf0) != 0) { + val = (val & ~8) | (dev->regs[SCATSX_LAPTOP_FEATURES] & 8); + reg_valid = 1; + } + break; + + case SCATSX_FAST_VIDEO_CONTROL: + case SCATSX_FAST_VIDEORAM_ENABLE: + case SCATSX_HIGH_PERFORMANCE_REFRESH: + case SCATSX_CAS_TIMING_FOR_DMA: + if ((dev->regs[SCAT_VERSION] & 0xf0) != 0) + reg_valid = 1; + break; + + default: + break; + } + + if (reg_valid) + dev->regs[dev->indx] = val; + + if (shadow_update) + shadow_state_update(dev); + + if (map_update) + memmap_state_update(dev); + break; + + case 0x92: + if ((mem_a20_alt ^ val) & 2) { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~dev->port_92 & val) & 1) { + cpu_reset(0); + cpu_set_edx(); + } + dev->port_92 = val; + break; + + case 0x208: + case 0x218: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + indx = dev->reg_2xA & 0x1f; + else + indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; + dev->page[indx].regs_2x8 = val; + base_addr = (indx + 16) << 14; + if (indx >= 24) + base_addr += 0x30000; + + if ((dev->regs[SCAT_EMS_CONTROL] & 0x80) && (dev->page[indx].regs_2x9 & 0x80)) { + virt_addr = get_addr(dev, base_addr, &dev->page[indx]); + if (virt_addr < ((uint32_t)mem_size << 10)) + mem_map_set_exec(&dev->ems_mapping[indx], ram + virt_addr); + else + mem_map_set_exec(&dev->ems_mapping[indx], NULL); + flushmmucache(); + } + } + break; + + case 0x209: + case 0x219: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + indx = dev->reg_2xA & 0x1f; + else + indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; + dev->page[indx].regs_2x9 = val; + base_addr = (indx + 16) << 14; + if (indx >= 24) + base_addr += 0x30000; + + if (dev->regs[SCAT_EMS_CONTROL] & 0x80) { + if (val & 0x80) { + virt_addr = get_addr(dev, base_addr, &dev->page[indx]); + if (indx < 24) + mem_map_disable(&dev->efff_mapping[indx]); + else + mem_map_disable(&dev->efff_mapping[indx + 12]); + if (virt_addr < ((uint32_t)mem_size << 10)) + mem_map_set_exec(&dev->ems_mapping[indx], ram + virt_addr); + else + mem_map_set_exec(&dev->ems_mapping[indx], NULL); + mem_map_enable(&dev->ems_mapping[indx]); + } else { + mem_map_set_exec(&dev->ems_mapping[indx], ram + base_addr); + mem_map_disable(&dev->ems_mapping[indx]); + if (indx < 24) + mem_map_enable(&dev->efff_mapping[indx]); + else + mem_map_enable(&dev->efff_mapping[indx + 12]); + } + + flushmmucache(); + } + + if (dev->reg_2xA & 0x80) + dev->reg_2xA = (dev->reg_2xA & 0xe0) | ((dev->reg_2xA + 1) & (((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x1f : 3)); + } + break; + + case 0x20a: + case 0x21a: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + dev->reg_2xA = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? val : val & 0xc3; + break; + } +} + + +static uint8_t +scat_read(uint16_t port, void *priv) +{ + scat_t *dev = (scat_t *)priv; + uint8_t ret = 0xff, indx; + + switch (port) { + case 0x23: + switch (dev->indx) { + case SCAT_MISCELLANEOUS_STATUS: + ret = (dev->regs[dev->indx] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5); + break; + + case SCAT_DRAM_CONFIGURATION: + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + ret = (dev->regs[dev->indx] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); + else + ret = dev->regs[dev->indx]; + break; + + case SCAT_EXTENDED_BOUNDARY: + ret = dev->regs[dev->indx]; + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { + if ((dev->regs[SCAT_VERSION] & 0x0f) >= 4) + ret |= 0x80; + else + ret &= 0xaf; + } + break; + + default: + ret = dev->regs[dev->indx]; + break; + } + break; + + case 0x92: + ret = dev->port_92; + break; + + case 0x208: + case 0x218: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + indx = dev->reg_2xA & 0x1f; + else + indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; + ret = dev->page[indx].regs_2x8; + } + break; + + case 0x209: + case 0x219: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + indx = dev->reg_2xA & 0x1f; + else + indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; + ret = dev->page[indx].regs_2x9; + } + break; + + case 0x20a: + case 0x21a: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + ret = dev->reg_2xA; + break; + } + + return ret; +} + + +static uint8_t +mem_read_scatb(uint32_t addr, void *priv) +{ + mem_map_t *map = (mem_map_t *)priv; + scat_t *dev = (scat_t *)map->dev; + ems_page_t *page = (ems_page_t *)map->p2; + uint8_t val = 0xff; + + addr = get_addr(dev, addr, page); + if (addr < ((uint32_t)mem_size << 10)) + val = ram[addr]; + + return val; +} + + +static uint16_t +mem_read_scatw(uint32_t addr, void *priv) +{ + mem_map_t *map = (mem_map_t *)priv; + scat_t *dev = (scat_t *)map->dev; + ems_page_t *page = (ems_page_t *)map->p2; + uint16_t val = 0xffff; + + addr = get_addr(dev, addr, page); + if (addr < ((uint32_t)mem_size << 10)) + val = *(uint16_t *)&ram[addr]; + + return val; +} + + +static uint32_t +mem_read_scatl(uint32_t addr, void *priv) +{ + mem_map_t *map = (mem_map_t *)priv; + scat_t *dev = (scat_t *)map->dev; + ems_page_t *page = (ems_page_t *)map->p2; + uint32_t val = 0xffffffff; + + addr = get_addr(dev, addr, page); + if (addr < ((uint32_t)mem_size << 10)) + val = *(uint32_t *)&ram[addr]; + + return val; +} + + +static void +mem_write_scatb(uint32_t addr, uint8_t val, void *priv) +{ + mem_map_t *map = (mem_map_t *)priv; + scat_t *dev = (scat_t *)map->dev; + ems_page_t *page = (ems_page_t *)map->p2; + uint32_t oldaddr = addr, chkaddr; + + addr = get_addr(dev, addr, page); + chkaddr = page ? addr : oldaddr; + if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return; + } + + if (addr < ((uint32_t)mem_size << 10)) + ram[addr] = val; +} + + +static void +mem_write_scatw(uint32_t addr, uint16_t val, void *priv) +{ + mem_map_t *map = (mem_map_t *)priv; + scat_t *dev = (scat_t *)map->dev; + ems_page_t *page = (ems_page_t *)map->p2; + uint32_t oldaddr = addr, chkaddr; + + addr = get_addr(dev, addr, page); + chkaddr = page ? addr : oldaddr; + if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return; + } + + if (addr < ((uint32_t)mem_size << 10)) + *(uint16_t *)&ram[addr] = val; +} + + +static void +mem_write_scatl(uint32_t addr, uint32_t val, void *priv) +{ + mem_map_t *map = (mem_map_t *)priv; + scat_t *dev = (scat_t *)map->dev; + ems_page_t *page = (ems_page_t *)map->p2; + uint32_t oldaddr = addr, chkaddr; + + addr = get_addr(dev, addr, page); + chkaddr = page ? addr : oldaddr; + if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return; + } + if (addr < ((uint32_t)mem_size << 10)) + *(uint32_t *)&ram[addr] = val; +} + + +static void +scat_close(void *priv) +{ + scat_t *dev = (scat_t *)priv; + + free(dev); +} + + +static void * +scat_init(const device_t *info, UNUSED(void *parent)) +{ + scat_t *dev; + uint32_t k; + int i, sx; + + dev = (scat_t *)mem_alloc(sizeof(scat_t)); + memset(dev, 0x00, sizeof(scat_t)); + dev->type = info->local; + + sx = (dev->type == 32) ? 1 : 0; + + for (i = 0; i < sizeof(dev->regs); i++) + dev->regs[i] = 0xff; + + if (sx) { + dev->regs[SCAT_VERSION] = 0x13; + dev->regs[SCAT_CLOCK_CONTROL] = 6; + dev->regs[SCAT_PERIPHERAL_CONTROL] = 0; + dev->regs[SCAT_DRAM_CONFIGURATION] = 1; + dev->regs[SCATSX_LAPTOP_FEATURES] = 0; + dev->regs[SCATSX_FAST_VIDEO_CONTROL] = 0; + dev->regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0; + dev->regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8; + dev->regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; + } else { + switch(dev->type) { + case 4: + dev->regs[SCAT_VERSION] = 4; + break; + + default: + dev->regs[SCAT_VERSION] = 1; + break; + } + dev->regs[SCAT_CLOCK_CONTROL] = 2; + dev->regs[SCAT_PERIPHERAL_CONTROL] = 0x80; + dev->regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12; + } + dev->regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; + dev->regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; + dev->regs[SCAT_ROM_ENABLE] = 0xc0; + dev->regs[SCAT_RAM_WRITE_PROTECT] = 0; + dev->regs[SCAT_POWER_MANAGEMENT] = 0; + dev->regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; + dev->regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; + dev->regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; + dev->regs[SCAT_EXTENDED_BOUNDARY] = 0; + dev->regs[SCAT_EMS_CONTROL] = 0; + dev->port_92 = 0; + + /* Disable all system mappings, we will override them. */ + mem_map_disable(&ram_low_mapping); + if (! sx) + mem_map_disable(&ram_mid_mapping); + mem_map_disable(&ram_high_mapping); + for (i = 0; i < 4; i++) + mem_map_disable(&bios_mapping[i]); + + k = (sx) ? 0x80000 : 0x40000; + mem_map_add(&dev->low_mapping[0], 0, k, + mem_read_scatb, mem_read_scatw, mem_read_scatl, + mem_write_scatb, mem_write_scatw, mem_write_scatl, + ram, MEM_MAPPING_INTERNAL, &dev->low_mapping[0]); + mem_map_set_dev(&dev->low_mapping[0], dev); + + mem_map_add(&dev->low_mapping[1], 0xf0000, 0x10000, + mem_read_scatb,mem_read_scatw,mem_read_scatl, + mem_write_scatb,mem_write_scatw,mem_write_scatl, + ram + 0xf0000, MEM_MAPPING_INTERNAL, &dev->low_mapping[1]); + mem_map_set_dev(&dev->low_mapping[1], dev); + + for (i = 2; i < 32; i++) { + mem_map_add(&dev->low_mapping[i], (i << 19), 0x80000, + mem_read_scatb,mem_read_scatw,mem_read_scatl, + mem_write_scatb,mem_write_scatw,mem_write_scatl, + ram + (i<<19), MEM_MAPPING_INTERNAL, &dev->low_mapping[i]); + mem_map_set_dev(&dev->low_mapping[i], dev); + } + + if (sx) { + i = 16; + k = 0x40000; + } else { + i = 0; + k = (dev->regs[SCAT_VERSION] < 4) ? 0x40000 : 0x60000; + } + mem_map_set_addr(&dev->low_mapping[31], 0xf80000, k); + + for (; i < 44; i++) { + mem_map_add(&dev->efff_mapping[i], 0x40000 + (i << 14), 0x4000, + mem_read_scatb,mem_read_scatw,mem_read_scatl, + mem_write_scatb,mem_write_scatw,mem_write_scatl, + mem_size > (256 + (i << 4)) ? ram + 0x40000 + (i << 14) : NULL, + MEM_MAPPING_INTERNAL, &dev->efff_mapping[i]); + mem_map_set_dev(&dev->efff_mapping[i], dev); + + if (sx) + mem_map_enable(&dev->efff_mapping[i]); + } + + for (i = 0; i < 8; i++) { + mem_map_add(&dev->romcs_mapping[i], 0xc0000 + (i << 14), 0x4000, + rom_bios_read,rom_bios_readw,rom_bios_readl, + mem_write_null,mem_write_nullw,mem_write_nulll, + bios + ((i << 14) & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); + mem_map_disable(&dev->romcs_mapping[i]); + } + + if (sx) { + for (i = 24; i < 32; i++) { + dev->page[i].regs_2x8 = 0xff; + dev->page[i].regs_2x9 = 0x03; + mem_map_add(&dev->ems_mapping[i], (i + 28) << 14, 0x04000, + mem_read_scatb,mem_read_scatw,mem_read_scatl, + mem_write_scatb,mem_write_scatw,mem_write_scatl, + ram + ((i + 28) << 14), 0, &dev->ems_mapping[i]); + mem_map_set_dev(&dev->ems_mapping[i], dev); + mem_map_set_p2(&dev->ems_mapping[i], &dev->page[i]); + mem_map_disable(&dev->ems_mapping[i]); + } + + for (i = 0; i < 16; i++) { + mem_map_add(&dev->high_mapping[i], (i << 14) + 0xfc0000, 0x04000, + rom_bios_read,rom_bios_readw,rom_bios_readl, + mem_write_null,mem_write_nullw,mem_write_nulll, + bios + ((i << 14) & biosmask), 0, NULL); + mem_map_enable(&dev->high_mapping[i]); + } + } else { + for (i = 0; i < 32; i++) { + dev->page[i].regs_2x8 = 0xff; + dev->page[i].regs_2x9 = 0x03; + mem_map_add(&dev->ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, + mem_read_scatb,mem_read_scatw,mem_read_scatl, + mem_write_scatb,mem_write_scatw,mem_write_scatl, + ram + ((i + (i >= 24 ? 28 : 16)) << 14), + 0, &dev->ems_mapping[i]); + mem_map_set_dev(&dev->ems_mapping[i], dev); + mem_map_set_p2(&dev->ems_mapping[i], &dev->page[i]); + } + + for (i = (dev->regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++) { + mem_map_add(&dev->high_mapping[i], (i << 14) + 0xfc0000, 0x04000, + rom_bios_read,rom_bios_readw,rom_bios_readl, + mem_write_null,mem_write_nullw,mem_write_nulll, + bios + ((i << 14) & biosmask), 0, NULL); + mem_map_enable(&dev->high_mapping[i]); + } + } + + for (i = 0; i < 6; i++) { + mem_map_add(&dev->remap_mapping[i], 0x100000 + (i << 16), 0x10000, + mem_read_scatb,mem_read_scatw,mem_read_scatl, + mem_write_scatb,mem_write_scatw,mem_write_scatl, + mem_size >= 1024 ? ram + get_addr(dev, 0x100000 + (i << 16), NULL) : NULL, + MEM_MAPPING_INTERNAL, &dev->remap_mapping[i]); + mem_map_set_dev(&dev->remap_mapping[i], dev); + } + + if (sx) { + dev->external_is_RAS = scatsx_external_is_RAS[mem_size >> 9]; + } else { + dev->external_is_RAS = (dev->regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4; + } + + set_xms_bound(dev, 0); + memmap_state_update(dev); + shadow_state_update(dev); + + io_sethandler(0x0022, 2, + scat_read,NULL,NULL, scat_write,NULL,NULL, dev); + io_sethandler(0x0092, 1, + scat_read,NULL,NULL, scat_write,NULL,NULL, dev); + + return(dev); +} + + +const device_t scat_device = { + "C&T SCAT (v1)", + 0, + 0, + NULL, + scat_init, scat_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t scat_4_device = { + "C&T SCAT (v4)", + 0, + 4, + NULL, + scat_init, scat_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t scat_sx_device = { + "C&T SCATsx", + 0, + 32, + NULL, + scat_init, scat_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/chipsets/scat.h b/src/devices/chipsets/scat.h new file mode 100644 index 0000000..f156140 --- /dev/null +++ b/src/devices/chipsets/scat.h @@ -0,0 +1,58 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the C&T "SCAT" chipset. + * + * Version: @(#)scat.h 1.0.1 2019/04/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SCAT_H +# define SCAT_H + + +#ifdef EMU_DEVICE_H +extern const device_t scat_device; +extern const device_t scat_4_device; +extern const device_t scat_sx_device; +#endif + + +#endif /*SCAT_H*/ diff --git a/src/machines/m_at_sis471.c b/src/devices/chipsets/sis471.c similarity index 86% rename from src/machines/m_at_sis471.c rename to src/devices/chipsets/sis471.c index 9a134e9..d07015e 100644 --- a/src/machines/m_at_sis471.c +++ b/src/devices/chipsets/sis471.c @@ -6,9 +6,9 @@ * * This file is part of the VARCem Project. * - * Emulation of the SiS 85c471 Super I/O chip. + * Emulation of the SiS 85C471 System Controller chip. * - * Version: @(#)m_at_sis471.c 1.0.13 2019/02/16 + * Version: @(#)sis471.c 1.0.14 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,20 +39,21 @@ #include #include #include -#include "../emu.h" -#include "../io.h" -#include "../device.h" -#include "../devices/system/memregs.h" -#include "../devices/ports/serial.h" -#include "../devices/ports/parallel.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/disk/hdc.h" -#include "../devices/disk/hdc_ide.h" -#include "machine.h" +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../device.h" +#include "../../plat.h" +#include "../ports/serial.h" +#include "../ports/parallel.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" +#include "sis471.h" typedef struct { + int type; + uint8_t cur_reg, regs[39]; } sis471_t; @@ -138,12 +139,14 @@ sis_close(void *priv) static void * -sis_init(const device_t *info) +sis_init(const device_t *info, UNUSED(void *parent)) { int mem_size_mb, i; + sis471_t *dev; - sis471_t *dev = (sis471_t *)mem_alloc(sizeof(sis471_t)); + dev = (sis471_t *)mem_alloc(sizeof(sis471_t)); memset(dev, 0x00, sizeof(sis471_t)); + dev->type = info->local; // lpt2_remove(); @@ -271,28 +274,16 @@ sis_init(const device_t *info) io_sethandler(0x0022, 2, sis_read,NULL,NULL, sis_write,NULL,NULL, dev); - return dev; + return(dev); } const device_t sis_85c471_device = { - "SiS 85c471", + "SiS 85C471", 0, 0, + NULL, sis_init, sis_close, NULL, NULL, NULL, NULL, NULL, NULL }; - - -void -m_at_dtk486_init(const machine_t *model, void *arg) -{ - m_at_ide_init(model, arg); - - device_add(&fdc_at_device); - - memregs_init(); - - device_add(&sis_85c471_device); -} diff --git a/src/devices/chipsets/sis471.h b/src/devices/chipsets/sis471.h new file mode 100644 index 0000000..a4e1de6 --- /dev/null +++ b/src/devices/chipsets/sis471.h @@ -0,0 +1,56 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the SiS 85C471 system controller chip. + * + * Version: @(#)sis471.h 1.0.1 2019/04/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SIS471_H +# define SIS471_H + + +#ifdef EMU_DEVICE_H +extern const device_t sis_85c471_device; +#endif + + +#endif /*SIS471_H*/ diff --git a/src/machines/m_at_sis496.c b/src/devices/chipsets/sis496.c similarity index 76% rename from src/machines/m_at_sis496.c rename to src/devices/chipsets/sis496.c index 7cbe9fd..112c5f2 100644 --- a/src/machines/m_at_sis496.c +++ b/src/devices/chipsets/sis496.c @@ -8,7 +8,7 @@ * * Implementation of the SiS 85C496/497 chipset. * - * Version: @(#)m_at_sis49x.c 1.0.9 2019/02/16 + * Version: @(#)sis49x.c 1.0.11 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,18 +41,15 @@ #include #include #include -#include "../emu.h" -#include "../io.h" -#include "../device.h" -#include "../mem.h" -#include "../devices/system/pci.h" -#include "../devices/system/memregs.h" -#include "../devices/sio/sio.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/disk/hdc.h" -#include "../devices/input/keyboard.h" -#include "machine.h" +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../device.h" +#include "../../plat.h" +#include "../system/pci.h" +#include "sis496.h" typedef struct { @@ -358,7 +355,7 @@ sis496_reset(void *priv) static void -sis_close(void *priv) +sis496_close(void *priv) { sis49x_t *dev = (sis49x_t *)priv; @@ -367,7 +364,7 @@ sis_close(void *priv) static void * -sis_init(const device_t *info) +sis496_init(const device_t *info, UNUSED(void *parent)) { sis49x_t *dev = (sis49x_t *)mem_alloc(sizeof(sis49x_t)); memset(dev, 0x00, sizeof(sis49x_t)); @@ -399,73 +396,11 @@ sis_init(const device_t *info) const device_t sis_85c496_device = { - "SiS 85c496/85c497", + "SiS 85C496/85C497", DEVICE_PCI, 0, - sis_init, sis_close, sis496_reset, + NULL, + sis496_init, sis496_close, sis496_reset, NULL, NULL, NULL, NULL, NULL }; - - -static void -common_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - device_add(&ide_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); - 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); - - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - - device_add(&sis_85c496_device); -} - - -void -m_at_sis496_ami_init(const machine_t *model, void *arg) -{ - m_at_common_ide_init(model, arg); - - device_add(&keyboard_at_ami_device); - device_add(&fdc_at_device); - -////////// - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); - 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); - - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - - device_add(&sis_85c496_device); -///////// -} - - -void -m_at_r418_init(const machine_t *model, void *arg) -{ - common_init(model, arg); - - device_add(&fdc37c665_device); -} diff --git a/src/devices/chipsets/sis496.h b/src/devices/chipsets/sis496.h new file mode 100644 index 0000000..4701c17 --- /dev/null +++ b/src/devices/chipsets/sis496.h @@ -0,0 +1,56 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the SiS 85C496/497 chipset. + * + * Version: @(#)sis49x.h 1.0.1 2019/04/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SIS496_H +# define SIS496_H + + +#ifdef EMU_DEVICE_H +extern const device_t sis_85c496_device; +#endif + + +#endif /*SIS496_H*/ diff --git a/src/machines/m_at_sis50x.c b/src/devices/chipsets/sis50x.c similarity index 98% rename from src/machines/m_at_sis50x.c rename to src/devices/chipsets/sis50x.c index e07258b..eb0993e 100644 --- a/src/machines/m_at_sis50x.c +++ b/src/devices/chipsets/sis50x.c @@ -8,7 +8,7 @@ * * Emulation of the SiS 85C50x PCI chips. * - * Version: @(#)m_at_sis50x.c 1.0.5 2019/02/16 + * Version: @(#)sis50x.c 1.0.6 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,8 +42,9 @@ #include "../emu.h" #include "../io.h" #include "../mem.h" -#include "../devices/system/pci.h" -#include "machine.h" +#include "../system/pci.h" +#include "../plat.h" +#include "sis50x.h" typedef struct { diff --git a/src/machines/m_at_wd76c10.c b/src/devices/chipsets/wd76c10.c similarity index 83% rename from src/machines/m_at_wd76c10.c rename to src/devices/chipsets/wd76c10.c index 77ce0be..958b598 100644 --- a/src/machines/m_at_wd76c10.c +++ b/src/devices/chipsets/wd76c10.c @@ -6,9 +6,9 @@ * * This file is part of the VARCem Project. * - * Implementation of the WD76C10 system controller. + * Implementation of the WD76C10 System Controller chip. * - * Version: @(#)m_at_wd76c10.c 1.0.11 2019/02/16 + * Version: @(#)wd76c10.c 1.0.12 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,21 +38,24 @@ */ #include #include +#include #include #include -#include "../emu.h" -#include "../io.h" -#include "../mem.h" -#include "../device.h" -#include "../devices/ports/serial.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/video/video.h" -#include "machine.h" +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../device.h" +#include "../../plat.h" +#include "../ports/serial.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" +#include "wd76c10.h" typedef struct { + int type; + uint16_t reg_0092; uint16_t reg_2072; uint16_t reg_2872; @@ -195,11 +198,25 @@ wd76c10_writeb(uint16_t port, uint8_t val, void *priv) } -static wd76c10_t * -wd76c10_init(void) +static void +wd76c10_close(void *priv) { - wd76c10_t *dev = (wd76c10_t *)mem_alloc(sizeof(wd76c10_t)); + wd76c10_t *dev = (wd76c10_t *)priv; + + free(dev); +} + + +static void * +wd76c10_init(const device_t *info, UNUSED(void *parent)) +{ + wd76c10_t *dev; + + dev = (wd76c10_t *)mem_alloc(sizeof(wd76c10_t)); memset(dev, 0x00, sizeof(wd76c10_t)); + dev->type = info->local; + + dev->fdc = (fdc_t *)device_add(&fdc_at_device); io_sethandler(0x0092, 2, wd76c10_readb,wd76c10_read,NULL, @@ -213,21 +230,17 @@ wd76c10_init(void) io_sethandler(0x5872, 2, wd76c10_readb,wd76c10_read,NULL, wd76c10_writeb,wd76c10_write,NULL, dev); - return dev; + + return(dev); } -void -m_at_wd76c10_init(const machine_t *model, void *arg) -{ - wd76c10_t *dev; - - m_at_common_ide_init(model, arg); - - device_add(&keyboard_ps2_quadtel_device); - - dev = wd76c10_init(); - dev->fdc = (fdc_t *)device_add(&fdc_at_device); - - device_add(¶dise_wd90c11_megapc_device); -} +const device_t wd76c10_device = { + "WD 76C10", + 0, + 0, + NULL, + wd76c10_init, wd76c10_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/chipsets/wd76c10.h b/src/devices/chipsets/wd76c10.h new file mode 100644 index 0000000..49eb5c6 --- /dev/null +++ b/src/devices/chipsets/wd76c10.h @@ -0,0 +1,56 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the WD76C10 System Controller chip. + * + * Version: @(#)wd76c10.h 1.0.1 2019/04/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef WD76C10_H +# define WD76C10_H + + +#ifdef EMU_DEVICE_H +extern const device_t wd76c10_device; +#endif + + +#endif /*WD76C10_H*/ diff --git a/src/devices/disk/hdc.c b/src/devices/disk/hdc.c index f31a234..1c74a90 100644 --- a/src/devices/disk/hdc.c +++ b/src/devices/disk/hdc.c @@ -8,7 +8,7 @@ * * Common code to handle all sorts of disk controllers. * - * Version: @(#)hdc.c 1.0.17 2019/02/24 + * Version: @(#)hdc.c 1.0.18 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -63,10 +63,14 @@ static const struct { { "st506_xt", &st506_xt_xebec_device }, { "st506_dtc5150x", &st506_xt_dtc5150x_device }, +#ifdef USE_ST11 { "st506_st11_m", &st506_xt_st11_m_device }, { "st506_st11_r", &st506_xt_st11_r_device }, +#endif +#ifdef USE_WD1002 { "st506_wd1002a_wx1", &st506_xt_wd1002a_wx1_device }, { "st506_wd1002a_27x", &st506_xt_wd1002a_27x_device }, +#endif { "xta_wdxt150", &xta_wdxt150_device }, @@ -125,7 +129,7 @@ void hdc_reset(void) { INFO("HDC: reset(current=%d, internal=%d)\n", - hdc_type, !!(machines[machine].flags & MACHINE_HDC)); + hdc_type, !!(machine->flags & MACHINE_HDC)); /* If we have a valid controller, add its device. */ if (controllers[hdc_type].device != NULL) diff --git a/src/devices/disk/hdc_esdi_at.c b/src/devices/disk/hdc_esdi_at.c index c9cb306..691823c 100644 --- a/src/devices/disk/hdc_esdi_at.c +++ b/src/devices/disk/hdc_esdi_at.c @@ -8,13 +8,13 @@ * * Driver for the ESDI controller (WD1007-vse1) for PC/AT. * - * Version: @(#)hdc_esdi_at.c 1.0.13 2018/10/15 + * Version: @(#)hdc_esdi_at.c 1.0.15 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -47,7 +47,6 @@ #define dbglog hdc_log #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -787,7 +786,7 @@ loadhd(hdc_t *dev, int hdd_num, int d, const wchar_t *fn) static void * -wd1007vse1_init(const device_t *info) +wd1007vse1_init(const device_t *info, UNUSED(void *parent)) { hdc_t *dev; int c, d; @@ -809,8 +808,8 @@ wd1007vse1_init(const device_t *info) dev->status = STAT_READY|STAT_DSC; dev->error = 1; - rom_init(&dev->bios_rom, - ESDI_BIOS_FILE, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios_rom, info->path, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); io_sethandler(0x01f0, 1, hdc_read, hdc_readw, NULL, @@ -846,19 +845,12 @@ wd1007vse1_close(void *priv) } -static int -wd1007vse1_available(void) -{ - return(rom_present(ESDI_BIOS_FILE)); -} - - const device_t esdi_at_wd1007vse1_device = { "PC/AT ESDI Fixed Disk Adapter", DEVICE_ISA | DEVICE_AT, (HDD_BUS_ESDI << 8) | 0, + ESDI_BIOS_FILE, wd1007vse1_init, wd1007vse1_close, NULL, - wd1007vse1_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/devices/disk/hdc_esdi_mca.c b/src/devices/disk/hdc_esdi_mca.c index b99ce11..56e8916 100644 --- a/src/devices/disk/hdc_esdi_mca.c +++ b/src/devices/disk/hdc_esdi_mca.c @@ -52,12 +52,12 @@ * however, are auto-configured by the system software as * shown above. * - * Version: @(#)hdc_esdi_mca.c 1.0.14 2018/10/15 + * Version: @(#)hdc_esdi_mca.c 1.0.16 2019/04/09 * * Authors: Fred N. van Kempen, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -90,6 +90,7 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../../ui/ui.h" #include "../system/dma.h" #include "../system/pic.h" @@ -1074,7 +1075,7 @@ hdc_mca_write(int port, uint8_t val, void *priv) static void * -esdi_init(const device_t *info) +esdi_init(const device_t *info, UNUSED(void *parent)) { drive_t *drive; hdc_t *dev; @@ -1165,7 +1166,7 @@ esdi_close(void *priv) static int esdi_available(void) { - return(rom_present(BIOS_FILE_L) && rom_present(BIOS_FILE_H)); + return( rom_present(BIOS_FILE_L) && rom_present(BIOS_FILE_H) ); } @@ -1173,6 +1174,7 @@ const device_t esdi_ps2_device = { "IBM PS/2 ESDI Fixed Disk Adapter", DEVICE_MCA, (HDD_BUS_ESDI << 8) | 0, + NULL, esdi_init, esdi_close, NULL, esdi_available, NULL, NULL, NULL, diff --git a/src/devices/disk/hdc_ide_ata.c b/src/devices/disk/hdc_ide_ata.c index 0e376cc..4d4a57d 100644 --- a/src/devices/disk/hdc_ide_ata.c +++ b/src/devices/disk/hdc_ide_ata.c @@ -14,12 +14,12 @@ * Devices currently implemented are hard disk, CD-ROM and * ZIP IDE/ATAPI devices. * - * Version: @(#)hdc_ide_ata.c 1.0.29 2018/11/13 + * Version: @(#)hdc_ide_ata.c 1.0.31 2019/04/11 * * Authors: Miran Grca, * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -54,7 +54,6 @@ #include "../../emu.h" #include "../../version.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -807,10 +806,14 @@ ide_set_sector(ide_t *ide, int64_t sector_num) static void ide_zero(int d) { - ide_t *dev; - ide_drives[d] = (ide_t *)mem_alloc(sizeof(ide_t)); - memset(ide_drives[d], 0, sizeof(ide_t)); - dev = ide_drives[d]; + ide_t *dev = ide_drives[d]; + + if (dev == NULL) { + dev = (ide_t *)mem_alloc(sizeof(ide_t)); + memset(dev, 0x00, sizeof(ide_t)); + ide_drives[d] = dev; + } + dev->channel = d; dev->type = IDE_NONE; dev->hdd_num = -1; @@ -831,9 +834,12 @@ ide_board_close(int board) for (d = 0; d < 2; d++) { c = (board << 1) + d; dev = ide_drives[c]; + if (dev == NULL) continue; - if ((dev->type == IDE_HDD) && (dev->hdd_num != -1)) + if ((dev->type == IDE_HDD) && (dev->hdd_num != -1)) { hdd_image_close(dev->hdd_num); + dev->hdd_num = -1; + } if (board < 4) { if (ide_drive_is_atapi(dev)) { @@ -842,14 +848,19 @@ ide_board_close(int board) } } - if (dev->buffer) + if (dev->buffer) { free(dev->buffer); + dev->buffer = NULL; + } - if (dev->sector_buffer) + if (dev->sector_buffer) { free(dev->sector_buffer); + dev->sector_buffer = NULL; + } - if (dev) - free(dev); + ide_drives[c] = NULL; + + free(dev); } } @@ -857,11 +868,16 @@ ide_board_close(int board) void ide_allocate_buffer(ide_t *dev) { - if (dev->buffer) - return; + uint32_t sz = 65536 * sizeof(uint16_t); - dev->buffer = (uint16_t *)mem_alloc(65536 * sizeof(uint16_t)); - memset(dev->buffer, 0, 65536 * sizeof(uint16_t)); + if (dev->buffer) { +INFO("IDE: buffer already present @%08lx\n", dev->buffer); + return; + } + + dev->buffer = (uint16_t *)mem_alloc(sz); + memset(dev->buffer, 0x00, sz); +INFO("IDE: buffer allocated @%08lx\n", dev->buffer); } @@ -2296,7 +2312,7 @@ ide_set_side(int controller, uint16_t port) static void * -ide_ter_init(const device_t *info) +ide_ter_init(const device_t *info, UNUSED(void *parent)) { ide_boards[2] = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); memset(ide_boards[2], 0, sizeof(ide_board_t)); @@ -2328,7 +2344,7 @@ ide_ter_close(void *priv) static void * -ide_qua_init(const device_t *info) +ide_qua_init(const device_t *info, UNUSED(void *parent)) { ide_boards[3] = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); memset(ide_boards[3], 0, sizeof(ide_board_t)); @@ -2426,7 +2442,7 @@ secondary_ide_check(void) static void * -ide_init(const device_t *info) +ide_init(const device_t *info, UNUSED(void *parent)) { DEBUG("Initializing IDE...\n"); @@ -2569,6 +2585,7 @@ const device_t ide_isa_device = { "PC/AT IDE Controller", DEVICE_ISA | DEVICE_AT, (HDD_BUS_IDE << 8) | 0, + NULL, ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL @@ -2578,6 +2595,7 @@ const device_t ide_isa_2ch_device = { "PC/AT IDE Controller (Dual-Channel)", DEVICE_ISA | DEVICE_AT, (HDD_BUS_IDE << 8) | 2, + NULL, ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL @@ -2587,6 +2605,7 @@ const device_t ide_isa_2ch_opt_device = { "PC/AT IDE Controller (Single/Dual)", DEVICE_ISA | DEVICE_AT, (HDD_BUS_IDE << 8) | 3, + NULL, ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL @@ -2596,6 +2615,7 @@ const device_t ide_vlb_device = { "IDE Controller", DEVICE_VLB | DEVICE_AT, (HDD_BUS_IDE << 8) | 4, + NULL, ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL @@ -2605,6 +2625,7 @@ const device_t ide_vlb_2ch_device = { "IDE Controller (Dual-Channel)", DEVICE_VLB | DEVICE_AT, (HDD_BUS_IDE << 8) | 6, + NULL, ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL @@ -2614,6 +2635,7 @@ const device_t ide_pci_device = { "IDE Controller", DEVICE_PCI | DEVICE_AT, (HDD_BUS_IDE << 8) | 8, + NULL, ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL @@ -2623,6 +2645,7 @@ const device_t ide_pci_2ch_device = { "IDE Controller (Dual-Channel)", DEVICE_PCI | DEVICE_AT, (HDD_BUS_IDE << 8) | 10, + NULL, ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL @@ -2661,12 +2684,12 @@ static const device_config_t ide_ter_config[] = { "IRQ 12", 12 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -2674,6 +2697,7 @@ const device_t ide_ter_device = { "Tertiary IDE Controller", DEVICE_AT, (HDD_BUS_IDE << 8) | 0, + NULL, ide_ter_init, ide_ter_close, NULL, NULL, NULL, NULL, NULL, ide_ter_config @@ -2712,12 +2736,12 @@ static const device_config_t ide_qua_config[] = { "IRQ 12", 12 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -2725,6 +2749,7 @@ const device_t ide_qua_device = { "Quaternary IDE Controller", DEVICE_AT, (HDD_BUS_IDE << 8) | 0, + NULL, ide_qua_init, ide_qua_close, NULL, NULL, NULL, NULL, NULL, ide_qua_config diff --git a/src/devices/disk/hdc_ide_xta.c b/src/devices/disk/hdc_ide_xta.c index 15777e8..ce222e7 100644 --- a/src/devices/disk/hdc_ide_xta.c +++ b/src/devices/disk/hdc_ide_xta.c @@ -46,13 +46,13 @@ * * NOTE: The XTA interface is 0-based for sector numbers !! * - * Version: @(#)hdc_ide_xta.c 1.0.10 2018/10/15 + * Version: @(#)hdc_ide_xta.c 1.0.13 2019/04/11 * * Author: Fred N. van Kempen, * * Based on my earlier HD20 driver for the EuroPC. * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -384,7 +384,7 @@ do_format(hdc_t *dev, drive_t *drive, dcb_t *dcb) dev->head = dcb->head; dev->sector = 0; - DEBUG("%s: format_%s(%d) %d,%d\n", dev->name, + DEBUG("%s: format_%s(%i) %i,%i\n", dev->name, (dcb->cmd==CMD_FORMAT_DRIVE)?"drive":"track", drive->id, dev->track, dev->head); @@ -450,7 +450,7 @@ hdc_callback(void *priv) switch (dcb->cmd) { case CMD_TEST_READY: - DEBUG("%s: test_ready(%d) ready=%d\n", + DEBUG("%s: test_ready(%i) ready=%i\n", dev->name, dcb->drvsel, drive->present); if (! drive->present) { @@ -461,7 +461,7 @@ hdc_callback(void *priv) break; case CMD_RECALIBRATE: - DEBUG("%s: recalibrate(%d) ready=%d\n", + DEBUG("%s: recalibrate(%i) ready=%i\n", dev->name, dcb->drvsel, drive->present); if (! drive->present) { @@ -476,7 +476,7 @@ hdc_callback(void *priv) case CMD_READ_SENSE: switch(dev->state) { case STATE_IDLE: - DEBUG("%s: sense(%d)\n", + DEBUG("%s: sense(%i)\n", dev->name, dcb->drvsel); dev->buf_idx = 0; @@ -530,7 +530,7 @@ hdc_callback(void *priv) /* Activate the status icon. */ hdd_active(drive->hdd_num, 1); - DEBUG("%s: read_%s(%d: %d,%d,%d) cnt=%d\n", + DEBUG("%s: read_%s(%i: %i,%i,%i) cnt=%i\n", dev->name, (no_data)?"verify":"sector", drive->id, dev->track, dev->head, dev->sector, dev->count); @@ -578,7 +578,7 @@ do_send: val = dma_channel_write(dev->dma, *dev->buf_ptr); if (val == DMA_NODATA) { - ERRLOG("%s: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", + ERRLOG("%s: CMD_READ_SECTORS out of data (idx=%i, len=%i)!\n", dev->name, dev->buf_idx, dev->buf_len); dev->status |= (STAT_CD | STAT_IO| STAT_REQ); @@ -596,7 +596,7 @@ do_send: case STATE_SDONE: dev->buf_idx = 0; if (--dev->count == 0) { - DEBUG("%s: read_%s(%d) DONE\n", + DEBUG("%s: read_%s(%i) DONE\n", dev->name, (no_data)?"verify":"sector", drive->id); @@ -652,7 +652,7 @@ do_send: /* Activate the status icon. */ hdd_active(drive->hdd_num, 1); - DEBUG("%s: write_%s(%d: %d,%d,%d) cnt=%d\n", + DEBUG("%s: write_%s(%i: %i,%i,%i) cnt=%i\n", dev->name, (no_data)?"verify":"sector", dcb->drvsel, dev->track, dev->head, dev->sector, dev->count); @@ -683,11 +683,9 @@ do_recv: while (dev->buf_idx < dev->buf_len) { val = dma_channel_read(dev->dma); if (val == DMA_NODATA) { - ERRLOG("%s: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", + ERRLOG("%s: CMD_WRITE_SECTORS out of data (idx=%i, len=%i)!\n", dev->name, dev->buf_idx, dev->buf_len); - ERRLOG("%s: CMD_WRITE_SECTORS out of data!\n", - dev->name); dev->status |= (STAT_CD | STAT_IO | STAT_REQ); dev->callback = HDC_TIME; return; @@ -723,7 +721,7 @@ do_recv: dev->buf_idx = 0; if (--dev->count == 0) { - DEBUG("%s: write_%s(%d) DONE\n", + DEBUG("%s: write_%s(%i) DONE\n", dev->name, (no_data)?"verify":"sector", drive->id); @@ -759,7 +757,7 @@ do_recv: /* Seek to cylinder. */ val = (dcb->cyl_low | (dcb->cyl_high << 8)); - DEBUG("%s: seek(%d) %d/%d ready=%d\n", dev->name, + DEBUG("%s: seek(%i) %i/%i ready=%i\n", dev->name, dcb->drvsel, val, drive->cur_cyl, drive->present); if (drive->present) { @@ -791,8 +789,8 @@ do_recv: (params->cyl_high << 8) | params->cyl_low; drive->hpc = params->heads; drive->spt = dev->spt; /*hardcoded*/ - - INFO("%s: set_params(%d) cyl=%d,hd=%d,spt=%d\n", +//FIXME: not correct + INFO("%s: set_params(%i) cyl=%i,hd=%i,spt=%i\n", dev->name, dcb->drvsel, drive->tracks, drive->hpc, drive->spt); @@ -865,7 +863,7 @@ do_recv: case CMD_DRIVE_DIAGS: switch(dev->state) { case STATE_IDLE: - DEBUG("%s: drive_diags(%d) ready=%d\n", + DEBUG("%s: drive_diags(%i) ready=%i\n", dev->name, dcb->drvsel, drive->present); if (drive->present) { @@ -1016,10 +1014,9 @@ hdc_write(uint16_t port, uint8_t val, void *priv) static void * -xta_init(const device_t *info) +xta_init(const device_t *info, UNUSED(void *parent)) { drive_t *drive; - wchar_t *fn = NULL; hdc_t *dev; int c, i; int bus; @@ -1039,7 +1036,6 @@ xta_init(const device_t *info) dev->rom_addr = device_get_config_hex20("bios_addr"); dev->dma = 3; dev->spt = 17; /* MFM */ - fn = WD_BIOS_FILE; break; case 1: /* EuroPC */ @@ -1056,12 +1052,11 @@ xta_init(const device_t *info) dev->irq = 5; dev->dma = 3; dev->rom_addr = 0xc8000; - dev->spt = 17; - fn = WD_BIOS_FILE; + dev->spt = 34; break; } - INFO("%s: initializing (I/O=%04X, IRQ=%d, DMA=%d", + INFO("%s: initializing (I/O=%04X, IRQ=%i, DMA=%i", dev->name, dev->base, dev->irq, dev->dma); if (dev->rom_addr != 0x000000) INFO(", BIOS=%06X", dev->rom_addr); @@ -1082,18 +1077,18 @@ xta_init(const device_t *info) drive->present = 1; /* These are the "hardware" parameters (from the image.) */ - drive->cfg_spt = (uint8_t)(hdd[i].spt & 0xff); - drive->cfg_hpc = (uint8_t)(hdd[i].hpc & 0xff); - drive->cfg_tracks = (uint16_t)hdd[i].tracks; + drive->spt = (uint8_t)(hdd[i].spt & 0xff); + drive->hpc = (uint8_t)(hdd[i].hpc & 0xff); + drive->tracks = (uint16_t)hdd[i].tracks; /* Use them as "configured" parameters until overwritten. */ - drive->spt = drive->cfg_spt; - drive->hpc = drive->cfg_hpc; - drive->tracks = drive->cfg_tracks; + drive->cfg_spt = drive->spt; + drive->cfg_hpc = drive->hpc; + drive->cfg_tracks = drive->tracks; - INFO("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", - dev->name, hdd[i].bus_id.ide_channel, drive->tracks, - drive->hpc, drive->spt, i); + INFO("%s: drive%i (cyl=%i,hd=%i,spt=%i), disk %i\n", + dev->name, hdd[i].bus_id.ide_channel, + drive->tracks, drive->hpc, drive->spt, i); if (++c > XTA_NUM) break; } @@ -1105,7 +1100,7 @@ xta_init(const device_t *info) /* Load BIOS if it has one. */ if (dev->rom_addr != 0x000000) - rom_init(&dev->bios_rom, fn, + rom_init(&dev->bios_rom, info->path, dev->rom_addr, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); /* Create a timer for command delays. */ @@ -1143,46 +1138,46 @@ static const device_config_t wdxt150_config[] = { "base", "Address", CONFIG_HEX16, "", 0x0320, /*W2*/ { { - "320H", 0x0320 - }, + "320H", 0x0320 + }, { - "324H", 0x0324 - }, + "324H", 0x0324 + }, { - "" - } + NULL + } } }, { "irq", "IRQ", CONFIG_SELECTION, "", 5, /*W3*/ { { - "IRQ 5", 5 - }, + "IRQ 5", 5 + }, { - "IRQ 4", 4 - }, + "IRQ 4", 4 + }, { - "" - } + NULL + } } }, { "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xc8000, /*W1*/ { { - "C800H", 0xc8000 - }, + "C800H", 0xc8000 + }, { - "CA00H", 0xca000 - }, + "CA00H", 0xca000 + }, { - "" - } + NULL + } } }, { - "", "", -1 + NULL } }; @@ -1191,6 +1186,7 @@ const device_t xta_wdxt150_device = { "WDXT-150 XTA Fixed Disk Controller", DEVICE_ISA, (HDD_BUS_IDE << 8) | 0, + WD_BIOS_FILE, xta_init, xta_close, NULL, NULL, NULL, NULL, NULL, wdxt150_config @@ -1200,6 +1196,7 @@ const device_t xta_hd20_device = { "EuroPC HD20 Fixed Disk Controller", DEVICE_ISA, (HDD_BUS_IDE << 8) | 1, + NULL, xta_init, xta_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -1210,6 +1207,7 @@ const device_t xta_t1200_device = { "Toshiba T1200 Fixed Disk Controller", DEVICE_ISA, (HDD_BUS_IDE << 8) | 2, + NULL, xta_init, xta_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/disk/hdc_st506_at.c b/src/devices/disk/hdc_st506_at.c index e83baa4..e4697e4 100644 --- a/src/devices/disk/hdc_st506_at.c +++ b/src/devices/disk/hdc_st506_at.c @@ -12,12 +12,12 @@ * based design. Most cards were WD1003-WA2 or -WAH, where the * -WA2 cards had a floppy controller as well (to save space.) * - * Version: @(#)hdc_st506_at.c 1.0.12 2018/10/15 + * Version: @(#)hdc_st506_at.c 1.0.14 2019/04/11 * * Authors: Fred N. van Kempen, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -49,7 +49,6 @@ #define dbglog hdc_log #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../timer.h" #include "../../device.h" @@ -698,7 +697,7 @@ loadhd(hdc_t *dev, int c, int d, const wchar_t *fn) static void * -st506_init(const device_t *info) +st506_init(const device_t *info, UNUSED(void *parent)) { hdc_t *dev; int c, d; @@ -760,6 +759,7 @@ const device_t st506_at_wd1003_device = { "IBM PC/AT Fixed Disk Adapter", DEVICE_ISA | DEVICE_AT, (HDD_BUS_ST506 << 8) | 0, + NULL, st506_init, st506_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/disk/hdc_st506_xt.c b/src/devices/disk/hdc_st506_xt.c index a1684d8..884180e 100644 --- a/src/devices/disk/hdc_st506_xt.c +++ b/src/devices/disk/hdc_st506_xt.c @@ -41,7 +41,7 @@ * Since all controllers (including the ones made by DTC) use * (mostly) the same API, we keep them all in this module. * - * Version: @(#)hdc_st506_xt.c 1.0.16 2019/03/02 + * Version: @(#)hdc_st506_xt.c 1.0.18 2019/04/20 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -92,13 +92,14 @@ #define XEBEC_BIOS_FILE L"disk/st506/ibm_xebec_62x0822_1985.bin" #define DTC_BIOS_FILE L"disk/st506/dtc_cxd21a.bin" -#define ST11_BIOS_FILE L"disk/st506/st11_bios_vers_1.7.bin" +#define ST11_BIOS_FILE_OLD L"disk/st506/st11_bios_vers_1.7.bin" +#define ST11_BIOS_FILE_NEW L"disk/st506/st11_bios_vers_2.0.bin" #define WD1002A_WX1_BIOS_FILE L"disk/st506/wd1002a_wx1-62-000094-032.bin" #define WD1002A_27X_BIOS_FILE L"disk/st506/wd1002a_27x-62-000215-060.bin" -#define ST506_TIME (50LL * TIMER_USEC) -#define ST506_TIME_MS (20LL * ST506_TIME) +#define ST506_TIME (250LL * TIMER_USEC) +#define ST506_TIME_MS (1000LL * TIMER_USEC) /* MFM and RLL use different sectors/track. */ #define SECTOR_SIZE 512 @@ -188,9 +189,10 @@ #define CMD_READ_LONG 0xe5 #define CMD_WRITE_LONG 0xe6 -#define CMD_FORMAT_DRIVE_ST11 0xf6 /* ST-11 BIOS */ +#define CMD_FORMAT_ST11 0xf6 /* ST-11 BIOS */ #define CMD_GET_GEOMETRY_ST11 0xf8 /* ST-11 BIOS */ #define CMD_SET_GEOMETRY_ST11 0xfa /* ST-11 BIOS */ +#define CMD_WRITE_GEOMETRY_ST11 0xfc /* ST-11 BIOS 2.0 */ #define CMD_GET_DRIVE_PARAMS_DTC 0xfb /* DTC */ #define CMD_SET_STEP_RATE_DTC 0xfc /* DTC */ @@ -308,7 +310,7 @@ get_sector(hdc_t *dev, drive_t *drive, off64_t *addr) { if (! drive->present) { /* No need to log this. */ - dev->error = ERR_NOT_AVAILABLE; + dev->error = ERR_NOT_READY; // AVAILABLE return(0); } @@ -388,6 +390,7 @@ st506_callback(void *priv) hdc_t *dev = (hdc_t *)priv; drive_t *drive; off64_t addr; + uint32_t capac; int val; /* Cancel the timer for now. */ @@ -405,7 +408,7 @@ st506_callback(void *priv) DEBUG("ST506: TEST_READY(%i) = %i\n", dev->drive_sel, drive->present); if (! drive->present) - st506_error(dev, ERR_NOT_AVAILABLE); + st506_error(dev, ERR_NOT_READY); //AVAILABLE st506_complete(dev); break; @@ -415,14 +418,13 @@ st506_callback(void *priv) DEBUG("ST506: RECALIBRATE(%i) [%i]\n", dev->drive_sel, drive->present); if (! drive->present) { - st506_error(dev, ERR_NOT_AVAILABLE); - st506_complete(dev); + st506_error(dev, ERR_NOT_READY); + st506_complete(dev); //AVAILABLE break; } /* Wait 20msec. */ dev->callback = ST506_TIME_MS * 20; - dev->cylinder = dev->cyl_off; drive->cylinder = dev->cylinder; dev->state = STATE_DONE; @@ -462,12 +464,10 @@ st506_callback(void *priv) break; case CMD_FORMAT_DRIVE: - case CMD_FORMAT_DRIVE_ST11: switch (dev->state) { case STATE_START_COMMAND: (void)get_chs(dev, drive); - DEBUG("ST506: FORMAT_DRIVE%s(%i) interleave=%i\n", - (dev->command[0] == CMD_FORMAT_DRIVE_ST11) ? "_ST11" : "", + DEBUG("ST506: FORMAT_DRIVE(%i) interleave=%i\n", dev->drive_sel, dev->command[4]); hdd_active(drive->hdd_num, 1); dev->callback = ST506_TIME; @@ -482,12 +482,12 @@ st506_callback(void *priv) return; } - /* FIXME: should be drive->capac, not ->spt */ - hdd_image_zero(drive->hdd_num, - addr, drive->cfg_spt); + /* Capacity of this drive. */ + capac = (drive->tracks - 1) * drive->hpc * drive->spt; + hdd_image_zero(drive->hdd_num, addr, capac); - /* Wait 5msec per cylinder. */ - dev->callback = ST506_TIME_MS * 5 * drive->cfg_cyl; + /* Wait 20msec per cylinder. */ + dev->callback = ST506_TIME_MS * 20 * drive->cfg_cyl; dev->state = STATE_SENT_DATA; break; @@ -555,8 +555,8 @@ st506_callback(void *priv) hdd_image_zero(drive->hdd_num, addr, drive->cfg_spt); - /* Wait 5msec per cylinder. */ - dev->callback = ST506_TIME_MS * 5; + /* Wait 20msec per cylinder. */ + dev->callback = ST506_TIME_MS * 20; dev->state = STATE_SENT_DATA; break; @@ -664,7 +664,8 @@ st506_callback(void *priv) dev->head, dev->sector, dev->count); if (! get_sector(dev, drive, &addr)) { - st506_error(dev, dev->error); +// st506_error(dev, dev->error); + st506_error(dev, ERR_BAD_PARAMETER); st506_complete(dev); return; } @@ -741,7 +742,7 @@ st506_callback(void *priv) if (! val) st506_error(dev, ERR_SEEK_ERROR); } else - st506_error(dev, ERR_NOT_AVAILABLE); + st506_error(dev, ERR_NOT_READY); //AVAILABLE st506_complete(dev); break; @@ -888,22 +889,61 @@ st506_callback(void *priv) st506_complete(dev); break; + case CMD_FORMAT_ST11: + if (dev->type == 11 || dev->type == 12) switch (dev->state) { + /* Apparently, ONLY the reserved cylinder (-1) .. */ + case STATE_START_COMMAND: + (void)get_chs(dev, drive); + DEBUG("ST506: FORMAT_ST11(%i) parm=%i\n", + dev->drive_sel, dev->command[1]); + hdd_active(drive->hdd_num, 1); + dev->callback = ST506_TIME; + dev->state = STATE_SEND_DATA; + break; + + case STATE_SEND_DATA: /* wrong, but works */ + if (! get_sector(dev, drive, &addr)) { + hdd_active(drive->hdd_num, 0); + st506_error(dev, dev->error); + st506_complete(dev); + return; + } + + hdd_image_zero(drive->hdd_num, + addr, drive->cfg_spt); + + /* Wait 20msec per cylinder. */ + dev->callback = ST506_TIME_MS * 20; + + dev->state = STATE_SENT_DATA; + break; + + case STATE_SENT_DATA: + hdd_active(drive->hdd_num, 0); + st506_complete(dev); + break; + } else { + st506_error(dev, ERR_BAD_COMMAND); + st506_complete(dev); + } + break; + case CMD_GET_GEOMETRY_ST11: if (dev->type == 11 || dev->type == 12) switch (dev->state) { /* - * [0] = 0xda; // magic - * [1] = 0xbe; // magic - * [2] = cyl_hi - * [3] = cyl_lo - * [4] = heads - * [5] = sectors - * [6] = interleave - * [7] = 00 // ?? - * [8] = 01 // ?? - * [9] = 03 // ?? + * [0] = 0xda; // magic + * [1] = 0xbe; // magic + * [2] = cyl_hi + * [3] = cyl_lo + * [4] = heads + * [5] = sectors + * [6] = interleave + * [7] = 00 // ?? + * [8] = 01 // ?? + * [9] = 03 // ?? * [10] = landing_hi * [11] = landing_lo - * [12] = 'SEAGATESTxxxxxx' // magic + * [12] = 'SEAGATESTxxxxxx' // drive model * [29] .. = 00 * [41] = 02 // ?? * @@ -917,9 +957,24 @@ st506_callback(void *priv) * write it anywhere on that cylinder, but OK.. */ case STATE_START_COMMAND: + INFO("ST506: GET GEO (%i) parm=%i\n", + dev->drive_sel, dev->command[2]); + + /* Read data from image. */ + hdd_image_read(drive->hdd_num, 0, 1, + (uint8_t *)dev->buff); +#ifdef x_DEBUG +{ + char temp[20480]; + hexdump_p(temp, dev->buff, 512); + INFO("ST506: sector buffer:\n%s\n", temp); +} +#endif /* Send geometry data. */ dev->buff_pos = 0; dev->buff_cnt = SECTOR_SIZE; + +#if 0 memset(dev->buff, 0x00, dev->buff_cnt); dev->buff[0] = 0xda; dev->buff[1] = 0xbe; @@ -935,6 +990,7 @@ st506_callback(void *priv) dev->buff[11] = drive->tracks & 0xff; memcpy(&dev->buff[12], "SEAGATESTxxxxxx", 15); dev->buff[41] = 0x02; +#endif dev->state = STATE_SEND_DATA; dev->status = STAT_BSY | STAT_IO | STAT_REQ; break; @@ -971,8 +1027,8 @@ st506_callback(void *priv) * we do not with real drives, we could simply * write it anywhere on that cylinder, but OK.. */ - INFO("ST506: GEO data for drive %i:\n", - dev->drive_sel); + INFO("ST506: SET GEO (%i) parm=%i\n", + dev->drive_sel, dev->command[2]); INFO("ST506: [ %02x %02x %02x %02x %02x %02x %02x %02x ]\n", dev->buff[0], dev->buff[1], dev->buff[2], dev->buff[3], @@ -990,7 +1046,41 @@ st506_callback(void *priv) break; case CMD_SET_STEP_RATE_DTC: - st506_complete(dev); + if (dev->type == 1) { + /* For DTC, we are done. */ + st506_complete(dev); + } else if (dev->type == 11 || dev->type == 12) { + /* + * For Seagate ST-11, this is WriteGeometry. + * + * By the time this command is sent, it will have + * formatted the first track, so it should be good, + * and our sector buffer contains the magic data + * (see above) we need to write to it. + */ + INFO("ST506: WRITE GEO (%i) parm=%i\n", + dev->drive_sel, dev->command[2]); + INFO("ST506: [ %02x %02x %02x %02x %02x %02x %02x %02x ]\n", + dev->buff[0], dev->buff[1], dev->buff[2], + dev->buff[3], dev->buff[4], dev->buff[5], + dev->buff[6], dev->buff[7]); + + /* Write data to image. */ + hdd_image_write(drive->hdd_num, 0, 1, + (uint8_t *)dev->buff); +#ifdef x_DEBUG +{ + char temp[20480]; + hexdump_p(temp, dev->buff, 512); + INFO("ST506: sector buffer:\n%s\n", temp); +} +#endif + + st506_complete(dev); + } else { + st506_error(dev, ERR_BAD_COMMAND); + st506_complete(dev); + } break; case CMD_GET_DRIVE_PARAMS_DTC: @@ -1001,7 +1091,7 @@ st506_callback(void *priv) memset(dev->buff, 0x00, dev->buff_cnt); dev->buff[0] = drive->tracks & 0xff; dev->buff[1] = ((drive->tracks >> 2) & 0xc0) | - drive->spt; + dev->spt; dev->buff[2] = drive->hpc - 1; dev->status = STAT_BSY | STAT_IO | STAT_REQ; dev->state = STATE_SEND_DATA; @@ -1120,10 +1210,9 @@ st506_write(uint16_t port, uint8_t val, void *priv) case 0: /* write data */ switch (dev->state) { case STATE_RECEIVE_COMMAND: /* command data */ - dev->buff[dev->buff_pos++] = val; + dev->command[dev->buff_pos++] = val; if (dev->buff_pos == dev->buff_cnt) { /* We have a new command. */ - memcpy(dev->command, dev->buff, dev->buff_cnt); dev->buff_pos = 0; dev->buff_cnt = 0; dev->status = STAT_BSY; @@ -1184,7 +1273,7 @@ mem_write(uint32_t addr, uint8_t val, void *priv) ptr = (dev->bios_rom.mask & mask) - dev->bios_ram; if (mask && ((addr & mask) > ptr) && - ((addr & mask) < (ptr + dev->bios_ram))) { + ((addr & mask) <= (ptr + dev->bios_ram))) { dev->scratch[addr & (dev->bios_ram - 1)] = val; } } @@ -1221,7 +1310,7 @@ mem_read(uint32_t addr, void *priv) ptr = (dev->bios_rom.mask & mask) - dev->bios_ram; if (mask && ((addr & mask) > ptr) && - ((addr & mask) < (ptr + dev->bios_ram))) { + ((addr & mask) <= (ptr + dev->bios_ram))) { ret = dev->scratch[addr & (dev->bios_ram - 1)]; } else ret = dev->bios_rom.rom[addr]; @@ -1350,9 +1439,9 @@ set_switches(hdc_t *dev) static void * -st506_init(const device_t *info) +st506_init(const device_t *info, UNUSED(void *parent)) { - wchar_t *fn = NULL; + const wchar_t *fn; hdc_t *dev; int i, c; @@ -1367,24 +1456,35 @@ st506_init(const device_t *info) dev->dma = 3; dev->bios_addr = 0xc8000; + fn = info->path; switch(dev->type) { case 0: /* Xebec (MFM) */ - fn = XEBEC_BIOS_FILE; break; case 1: /* DTC5150 (MFM) */ - fn = DTC_BIOS_FILE; dev->switches = 0xff; break; +#ifdef USE_ST11 case 12: /* Seagate ST-11R (RLL) */ dev->spt = RLL_SECTORS; /*FALLTHROUGH*/ case 11: /* Seagate ST-11M (MFM) */ - fn = ST11_BIOS_FILE; dev->switches = 0x01; /* fixed */ dev->misc = device_get_config_int("revision"); + switch(dev->misc) { + case 1: /* v1.1 */ + break; + + case 5: /* v1.7 */ + fn = ST11_BIOS_FILE_OLD; + break; + + case 19: /* v2.0 */ + fn = ST11_BIOS_FILE_NEW; + break; + } dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); dev->bios_addr = device_get_config_hex20("bios_addr"); @@ -1401,9 +1501,10 @@ st506_init(const device_t *info) */ dev->cyl_off = 1; break; +#endif +#ifdef USE_WD1002 case 21: /* Western Digital WD1002A-WX1 (MFM) */ - fn = WD1002A_WX1_BIOS_FILE; dev->switches = 0x10; /* autobios */ dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); @@ -1411,17 +1512,25 @@ st506_init(const device_t *info) break; case 22: /* Western Digital WD1002A-27X (RLL) */ - fn = WD1002A_27X_BIOS_FILE; dev->switches = 0x10; /* autobios */ dev->spt = RLL_SECTORS; dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); dev->bios_addr = device_get_config_hex20("bios_addr"); break; +#endif + + case 101: /* Western Digital WD1002A-WX1 (MFM) */ + dev->switches = 0x10; /* autobios */ + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + dev->bios_addr = device_get_config_hex20("bios_addr"); + break; } /* Load the ROM BIOS. */ - loadrom(dev, fn); + if (fn != NULL) + loadrom(dev, fn); /* Set up the I/O region. */ io_sethandler(dev->base, 4, @@ -1483,44 +1592,6 @@ st506_close(void *priv) } -static int -xebec_available(void) -{ - return(rom_present(XEBEC_BIOS_FILE)); -} - - -static int -dtc5150x_available(void) -{ - return(rom_present(DTC_BIOS_FILE)); -} - -static int -st11_m_available(void) -{ - return(rom_present(ST11_BIOS_FILE)); -} - -static int -st11_r_available(void) -{ - return(rom_present(ST11_BIOS_FILE)); -} - -static int -wd1002a_wx1_available(void) -{ - return(rom_present(WD1002A_WX1_BIOS_FILE)); -} - -static int -wd1002a_27x_available(void) -{ - return(rom_present(WD1002A_27X_BIOS_FILE)); -} - - static const device_config_t dtc_config[] = { { "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, @@ -1541,15 +1612,16 @@ static const device_config_t dtc_config[] = { "F400H", 0xf4000 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; +#ifdef USE_ST11 static const device_config_t st11_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x0320, @@ -1567,7 +1639,7 @@ static const device_config_t st11_config[] = { "32CH", 0x032c }, { - "" + NULL } } }, @@ -1581,7 +1653,7 @@ static const device_config_t st11_config[] = { "IRQ 5", 5 }, { - "" + NULL } } }, @@ -1604,31 +1676,34 @@ static const device_config_t st11_config[] = { "E000H", 0xe0000 }, { - "" + NULL } } }, { - "revision", "Board Revision", CONFIG_SELECTION, "", 5, + "revision", "Board Revision", CONFIG_SELECTION, "", 19, { +#if 0 /*Not Tested Yet*/ { - "Rev. 00", 0 + "Rev. 01 (v1.1)", 1 + }, +#endif + { + "Rev. 05 (v1.7)", 5 }, { - "Rev. 01", 1 + "Rev. 19 (v2.0)", 19 }, { - "Rev. 05", 5 - }, - { - "" + NULL } } }, { - "", "", -1 + NULL } }; +#endif static const device_config_t wd_config[] = { { @@ -1641,7 +1716,7 @@ static const device_config_t wd_config[] = { "C800H", 0xc8000 }, { - "" + NULL } } }, @@ -1655,7 +1730,7 @@ static const device_config_t wd_config[] = { "324H", 0x0324 }, { - "" + NULL } } }, @@ -1669,12 +1744,12 @@ static const device_config_t wd_config[] = { "IRQ 5", 5 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -1683,9 +1758,9 @@ const device_t st506_xt_xebec_device = { "IBM PC Fixed Disk Adapter", DEVICE_ISA, (HDD_BUS_ST506 << 8) | 0, + XEBEC_BIOS_FILE, st506_init, st506_close, NULL, - xebec_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; @@ -1693,19 +1768,20 @@ const device_t st506_xt_dtc5150x_device = { "DTC 5150X Fixed Disk Adapter", DEVICE_ISA, (HDD_BUS_ST506 << 8) | 1, + DTC_BIOS_FILE, st506_init, st506_close, NULL, - dtc5150x_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, dtc_config }; +#ifdef USE_ST11 const device_t st506_xt_st11_m_device = { "ST-11M Fixed Disk Adapter", DEVICE_ISA, (HDD_BUS_ST506 << 8) | 11, + ST11_BIOS_FILE_NEW, st506_init, st506_close, NULL, - st11_m_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, st11_config }; @@ -1713,19 +1789,21 @@ const device_t st506_xt_st11_r_device = { "ST-11R RLL Fixed Disk Adapter", DEVICE_ISA, (HDD_BUS_ST506 << 8) | 12, + ST11_BIOS_FILE_NEW, st506_init, st506_close, NULL, - st11_r_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, st11_config }; +#endif +#ifdef USE_WD1002 const device_t st506_xt_wd1002a_wx1_device = { "WD1002A-WX1 Fixed Disk Adapter", DEVICE_ISA, (HDD_BUS_ST506 << 8) | 21, + WD1002A_WX1_BIOS_FILE, st506_init, st506_close, NULL, - wd1002a_wx1_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, wd_config }; @@ -1733,8 +1811,19 @@ const device_t st506_xt_wd1002a_27x_device = { "WD1002A-27X RLL Fixed Disk Adapter", DEVICE_ISA, (HDD_BUS_ST506 << 8) | 22, + WD1002A_27X_BIOS_FILE, st506_init, st506_close, NULL, - wd1002a_27x_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + wd_config +}; +#endif + +const device_t st506_xt_olim240_hdc_device = { + "WD1002A-WX1 Fixed Disk Adapter (no BIOS)", + DEVICE_ISA, + (HDD_BUS_ST506 << 8) | 101, + NULL, + st506_init, st506_close, NULL, + NULL, NULL, NULL, NULL, wd_config }; diff --git a/src/devices/disk/hdc_xtide.c b/src/devices/disk/hdc_xtide.c index d6a394d..1b8a9ed 100644 --- a/src/devices/disk/hdc_xtide.c +++ b/src/devices/disk/hdc_xtide.c @@ -24,12 +24,12 @@ * FIXME: Make sure this works with the new IDE stuff, the AT and PS/2 * controllers do not have dev->ide set to anything... * - * Version: @(#)hdc_xtide.c 1.0.9 2018/09/22 + * Version: @(#)hdc_xtide.c 1.0.11 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -61,6 +61,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "hdc.h" #include "hdc_ide.h" #include "hdd.h" @@ -150,9 +151,8 @@ hdc_read(uint16_t port, void *priv) static void * -xtide_init(const device_t *info) +xtide_init(const device_t *info, UNUSED(void *parent)) { - wchar_t *fn = NULL; int rom_sz = 0; int io = 0; hdc_t *dev; @@ -162,34 +162,30 @@ xtide_init(const device_t *info) switch(info->local) { case 0: - fn = ROM_PATH_XT; rom_sz = 0x4000; io = 0x300; dev->ide_board = ide_xtide_init(); break; case 1: - fn = ROM_PATH_AT; rom_sz = 0x4000; io = 0x300; device_add(&ide_isa_2ch_device); break; case 2: - fn = ROM_PATH_PS2; rom_sz = 0x8000; //FIXME: file is 8KB ? io = 0x360; dev->ide_board = ide_xtide_init(); break; case 3: - fn = ROM_PATH_PS2_AT; rom_sz = 0x4000; //FIXME: no I/O address? device_add(&ide_isa_2ch_device); break; } - rom_init(&dev->bios_rom, fn, + rom_init(&dev->bios_rom, info->path, 0xc8000, rom_sz, rom_sz-1, 0, MEM_MAPPING_EXTERNAL); if (io != 0) @@ -211,38 +207,13 @@ xtide_close(void *priv) } -static int -xtide_available(void) -{ - return(rom_present(ROM_PATH_XT)); -} - -static int -xtide_at_available(void) -{ - return(rom_present(ROM_PATH_AT)); -} - -static int -xtide_acculogic_available(void) -{ - return(rom_present(ROM_PATH_PS2)); -} - -static int -xtide_at_ps2_available(void) -{ - return(rom_present(ROM_PATH_PS2_AT)); -} - - const device_t xtide_device = { "PC/XT XTIDE", DEVICE_ISA, (HDD_BUS_IDE << 8) | 0, + ROM_PATH_XT, xtide_init, xtide_close, NULL, - xtide_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; @@ -250,9 +221,9 @@ const device_t xtide_at_device = { "PC/AT XTIDE", DEVICE_ISA | DEVICE_AT, (HDD_BUS_IDE << 8) | 1, + ROM_PATH_AT, xtide_init, xtide_close, NULL, - xtide_at_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; @@ -260,9 +231,9 @@ const device_t xtide_acculogic_device = { "PC/XT XTIDE (Acculogic)", DEVICE_ISA, (HDD_BUS_IDE << 8) | 2, + ROM_PATH_PS2, xtide_init, xtide_close, NULL, - xtide_acculogic_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; @@ -270,8 +241,8 @@ const device_t xtide_at_ps2_device = { "PS/2 AT XTIDE (1.1.5)", DEVICE_ISA | DEVICE_PS2, (HDD_BUS_IDE << 8) | 3, + ROM_PATH_PS2_AT, xtide_init, xtide_close, NULL, - xtide_at_ps2_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/devices/floppy/fdc.c b/src/devices/floppy/fdc.c index fe206e1..b9158d4 100644 --- a/src/devices/floppy/fdc.c +++ b/src/devices/floppy/fdc.c @@ -9,7 +9,7 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.c 1.0.18 2019/02/10 + * Version: @(#)fdc.c 1.0.20 2019/04/11 * * Authors: Miran Grca, * Sarah Walker, @@ -45,7 +45,6 @@ #define dbglog fdc_log #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -54,6 +53,7 @@ #include "../../ui/ui.h" #include "../system/dma.h" #include "../system/pic.h" +#include "../../plat.h" #include "fdd.h" #include "fdc.h" @@ -2279,13 +2279,14 @@ fdc_close(void *priv) static void * -fdc_init(const device_t *info) +fdc_init(const device_t *info, UNUSED(void *parent)) { - fdc_t *fdc = (fdc_t *)mem_alloc(sizeof(fdc_t)); + fdc_t *fdc; + fdc = (fdc_t *)mem_alloc(sizeof(fdc_t)); memset(fdc, 0x00, sizeof(fdc_t)); - fdc->flags = info->local; + fdc_reset(fdc); fdc->irq = 6; @@ -2324,6 +2325,7 @@ const device_t fdc_xt_device = { "PC/XT Floppy Drive Controller", 0, 0, + NULL, fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL @@ -2333,6 +2335,7 @@ const device_t fdc_pcjr_device = { "PCjr Floppy Drive Controller", 0, FDC_FLAG_PCJR, + NULL, fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL @@ -2342,6 +2345,7 @@ const device_t fdc_at_device = { "PC/AT Floppy Drive Controller", 0, FDC_FLAG_AT, + NULL, fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL @@ -2351,6 +2355,7 @@ const device_t fdc_at_actlow_device = { "PC/AT Floppy Drive Controller (Active low)", 0, FDC_FLAG_AT|FDC_FLAG_DISKCHG_ACTLOW, + NULL, fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL @@ -2360,6 +2365,7 @@ const device_t fdc_at_ps1_device = { "PC/AT Floppy Drive Controller (PS/1, PS/2 ISA)", 0, FDC_FLAG_AT|FDC_FLAG_PS1|FDC_FLAG_DISKCHG_ACTLOW, + NULL, fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL @@ -2369,6 +2375,7 @@ const device_t fdc_at_smc_device = { "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", 0, FDC_FLAG_AT|FDC_FLAG_SUPERIO, + NULL, fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL @@ -2378,9 +2385,8 @@ const device_t fdc_at_winbond_device = { "PC/AT Floppy Drive Controller (Winbond W83x77F)", 0, FDC_FLAG_AT|FDC_FLAG_SUPERIO|FDC_FLAG_START_RWC_1|FDC_FLAG_MORE_TRACKS, - fdc_init, - fdc_close, - fdc_reset, + NULL, + fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL }; @@ -2389,6 +2395,7 @@ const device_t fdc_at_nsc_device = { "PC/AT Floppy Drive Controller (NSC PC8730x)", 0, FDC_FLAG_AT|FDC_FLAG_MORE_TRACKS|FDC_FLAG_NSC, + NULL, fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL @@ -2398,6 +2405,7 @@ const device_t fdc_toshiba_device = { "Toshiba TC8565 Floppy Drive Controller", 0, FDC_FLAG_TOSHIBA, + NULL, fdc_init, fdc_close, fdc_reset, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/floppy/fdd_86f.c b/src/devices/floppy/fdd_86f.c index a843f85..b2ea763 100644 --- a/src/devices/floppy/fdd_86f.c +++ b/src/devices/floppy/fdd_86f.c @@ -10,7 +10,7 @@ * data in the form of FM/MFM-encoded transitions) which also * forms the core of the emulator's floppy disk emulation. * - * Version: @(#)fdd_86f.c 1.0.16 2019/02/10 + * Version: @(#)fdd_86f.c 1.0.18 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -536,6 +536,7 @@ common_get_raw_size(int drive, int side) double size = 100000.0; int mfm; int rm, ssd; + uint32_t extra_bc = 0; mfm = d86f_is_mfm(drive); rpm = ((d86f_track_flags(drive) & 0xE0) == 0x20) ? 360.0 : 300.0; @@ -543,6 +544,13 @@ common_get_raw_size(int drive, int side) rm = d86f_get_rpm_mode(drive); ssd = d86f_get_speed_shift_dir(drive); + /* 0% speed shift and shift direction 1: special case where extra bit cells are the entire track size. */ + if (!rm && ssd) + extra_bc = d86f_handler[drive].extra_bit_cells(drive, side); + + if (extra_bc) + return extra_bc; + switch (rm) { case 1: rpm_diff = 1.01; @@ -592,13 +600,9 @@ common_get_raw_size(int drive, int side) if (! mfm) rate /= 2.0; - if (!rm && ssd) - size = 0.0; - else { - size = (size / 250.0) * rate; - size = (size * 300.0) / rpm; - size *= rpm_diff; - } + size = (size / 250.0) * rate; + size = (size * 300.0) / rpm; + size *= rpm_diff; /* * Round down to a multiple of 16 and add the extra bit cells, @@ -660,7 +664,7 @@ d86f_register_86f(int drive) int -d86f_get_array_size(int drive, int side) +d86f_get_array_size(int drive, int side, int words) { int array_size; int hole, rm; @@ -738,10 +742,14 @@ d86f_get_array_size(int drive, int side) array_size <<= 4; array_size += d86f_handler[drive].extra_bit_cells(drive, side); - array_size >>= 4; - if (d86f_handler[drive].extra_bit_cells(drive, side) & 15) - array_size++; + if (array_size & 15) + array_size = (array_size >> 4) + 1; + else + array_size = (array_size >> 4); + + if (!words) + array_size <<= 1; return array_size; } @@ -1115,9 +1123,8 @@ d86f_get_bit(int drive, int side) /* * In some cases, misidentification occurs so we need * to make sure the surface data array is not not NULL. - */ - if (d86f_has_surface_desc(drive) && - dev->track_surface_data && dev->track_surface_data[side]) { + */ + if (d86f_has_surface_desc(drive) && dev->track_surface_data[side]) { if (d86f_reverse_bytes(drive)) { surface_data = dev->track_surface_data[side][track_word] & 0xFF; } else { @@ -1129,8 +1136,7 @@ d86f_get_bit(int drive, int side) current_bit = (encoded_data >> track_bit) & 1; dev->last_word[side] <<= 1; - if (d86f_has_surface_desc(drive) && - dev->track_surface_data && dev->track_surface_data[side]) { + if (d86f_has_surface_desc(drive) && dev->track_surface_data[side]) { surface_bit = (surface_data >> track_bit) & 1; if (! surface_bit) dev->last_word[side] |= current_bit; @@ -2629,7 +2635,11 @@ d86f_prepare_pretrack(int drive, int side, int iso) sync_len = mfm ? 12 : 6; real_gap1_len = mfm ? 50 : 26; gap_fill = mfm ? 0x4E : 0xFF; - raw_size = d86f_handler[drive].get_raw_size(drive, side) >> 4; + raw_size = d86f_handler[drive].get_raw_size(drive, side); + if (raw_size & 15) + raw_size = (raw_size >> 4) + 1; + else + raw_size = (raw_size >> 4); dev->index_hole_pos[side] = 0; @@ -2705,7 +2715,11 @@ d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t mfm = d86f_is_mfm(drive); gap_fill = mfm ? 0x4E : 0xFF; - raw_size = d86f_handler[drive].get_raw_size(drive, side) >> 4; + raw_size = d86f_handler[drive].get_raw_size(drive, side); + if (raw_size & 15) + raw_size = (raw_size >> 4) + 1; + else + raw_size = (raw_size >> 4); pos = prev_pos; @@ -2811,7 +2825,7 @@ d86f_construct_encoded_buffer(int drive, int side) uint16_t *src1_s = dev->thin_track_surface_data[0][side]; uint16_t *src2 = dev->thin_track_encoded_data[1][side]; uint16_t *src2_s = dev->thin_track_surface_data[1][side]; - len = d86f_get_array_size(drive, side); + len = d86f_get_array_size(drive, side, 1); for (i = 0; i < len; i++) { /* The two bits differ. */ @@ -2859,7 +2873,7 @@ d86f_decompose_encoded_buffer(int drive, int side) uint16_t *src2_s = dev->thin_track_surface_data[1][side]; dst = d86f_handler[drive].encoded_data(drive, side); - len = d86f_get_array_size(drive, side); + len = d86f_get_array_size(drive, side, 1); for (i = 0; i < len; i++) { if (d86f_has_surface_desc(drive)) { @@ -2921,7 +2935,7 @@ d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, ui fread(&(dev->index_hole_pos[side]), 4, 1, dev->f); } else fseek(dev->f, dev->track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET); - array_size = d86f_get_array_size(drive, side) << 1; + array_size = d86f_get_array_size(drive, side, 0); if (d86f_has_surface_desc(drive)) fread(sa, 1, array_size, dev->f); fread(da, 1, array_size, dev->f); @@ -3007,6 +3021,7 @@ d86f_seek(int drive, int track) void d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0) { + uint32_t array_size = d86f_get_array_size(drive, side, 0); uint16_t side_flags = d86f_handler[drive].side_flags(drive); uint32_t extra_bit_cells = d86f_handler[drive].extra_bit_cells(drive, side); uint32_t index_hole_pos = d86f_handler[drive].index_hole_pos(drive, side); @@ -3019,9 +3034,9 @@ d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0) fwrite(&index_hole_pos, 1, 4, *f); if (d86f_has_surface_desc(drive)) - fwrite(sa0, 1, d86f_get_array_size(drive, side) << 1, *f); + fwrite(sa0, 1, array_size, *f); - fwrite(da0, 1, d86f_get_array_size(drive, side) << 1, *f); + fwrite(da0, 1, array_size, *f); } @@ -3060,7 +3075,7 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table) if (track_table) tbl = track_table; - if (! fdd_doublestep_40(drive)) { + if (!fdd_doublestep_40(drive)) { d86f_decompose_encoded_buffer(drive, 0); if (sides == 2) d86f_decompose_encoded_buffer(drive, 1); @@ -3293,8 +3308,7 @@ d86f_add_track(int drive, int track, int side) uint32_t array_size; int logical_track; - array_size = d86f_get_array_size(drive, side); - array_size <<= 1; + array_size = d86f_get_array_size(drive, side, 0); if (d86f_get_sides(drive) == 2) { logical_track = (track << 1) + side; @@ -3350,7 +3364,7 @@ d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) return; } - array_size = d86f_get_array_size(drive, side); + array_size = d86f_get_array_size(drive, side, 0); if (d86f_has_surface_desc(drive)) { /* Preserve the physical holes but get rid of the fuzzy bytes. */ @@ -3363,7 +3377,7 @@ d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) } /* Zero the data buffer. */ - memset(dev->track_encoded_data[side], 0, array_size << 1); + memset(dev->track_encoded_data[side], 0, array_size); d86f_add_track(drive, dev->cur_track, side); if (! fdd_doublestep_40(drive)) @@ -3716,8 +3730,10 @@ d86f_load(int drive, const wchar_t *fn) fread(&(dev->side_flags[0]), 2, 1, dev->f); if (dev->disk_flags & 0x80) { fread(&(dev->extra_bit_cells[0]), 4, 1, dev->f); - if (dev->extra_bit_cells[0] < -32768) dev->extra_bit_cells[0] = -32768; - if (dev->extra_bit_cells[0] > 32768) dev->extra_bit_cells[0] = 32768; + if ((dev->disk_flags & 0x1060) != 0x1000) { + if (dev->extra_bit_cells[0] < -32768) dev->extra_bit_cells[0] = -32768; + if (dev->extra_bit_cells[0] > 32768) dev->extra_bit_cells[0] = 32768; + } } else { dev->extra_bit_cells[0] = 0; } @@ -3727,8 +3743,10 @@ d86f_load(int drive, const wchar_t *fn) fread(&(dev->side_flags[1]), 2, 1, dev->f); if (dev->disk_flags & 0x80) { fread(&(dev->extra_bit_cells[1]), 4, 1, dev->f); - if (dev->extra_bit_cells[1] < -32768) dev->extra_bit_cells[1] = -32768; - if (dev->extra_bit_cells[1] > 32768) dev->extra_bit_cells[1] = 32768; + if ((dev->disk_flags & 0x1060) != 0x1000) { + if (dev->extra_bit_cells[1] < -32768) dev->extra_bit_cells[1] = -32768; + if (dev->extra_bit_cells[1] > 32768) dev->extra_bit_cells[1] = 32768; + } } else { dev->extra_bit_cells[0] = 0; } diff --git a/src/devices/floppy/fdd_mfm.c b/src/devices/floppy/fdd_mfm.c index 20302f9..3b8a8a9 100644 --- a/src/devices/floppy/fdd_mfm.c +++ b/src/devices/floppy/fdd_mfm.c @@ -8,7 +8,7 @@ * * Implementation of the HxC MFM image format. * - * Version: @(#)fdd_mfm.c 1.0.1 2018/11/12 + * Version: @(#)fdd_mfm.c 1.0.3 2019/04/07 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -87,6 +87,9 @@ typedef struct { mfm_track_t *tracks; mfm_adv_track_t *adv_tracks; + uint16_t disk_flags; + uint16_t side_flags[2]; + int br_rounded, rpm_rounded, total_tracks, cur_track; @@ -98,15 +101,81 @@ static mfm_t *mfm[FDD_NUM]; static fdc_t *mfm_fdc; -static uint16_t -disk_flags(int drive) +static int +get_track_index(int drive, int side, int track) { + mfm_t *dev = mfm[drive]; + int i, ret = -1; + + for (i = 0; i < dev->total_tracks; i++) { + if ((dev->tracks[i].track_no == track) && + (dev->tracks[i].side_no == side)) { + ret = i; + break; + } + } + + return ret; +} + + +static int +get_adv_track_index(int drive, int side, int track) +{ + mfm_t *dev = mfm[drive]; + int i, ret = -1; + + for (i = 0; i < dev->total_tracks; i++) { + if ((dev->adv_tracks[i].track_no == track) && + (dev->adv_tracks[i].side_no == side)) { + ret = i; + break; + } + } + + return ret; +} + + +static void +get_adv_track_bitrate(int drive, int side, int track, int *br, int *rpm) +{ + mfm_t *dev = mfm[drive]; + int track_index; + double dbr; + + track_index = get_adv_track_index(drive, side, track); + + if (track_index == -1) { + *br = 250; + *rpm = 300; + } else { + dbr = round(((double) dev->adv_tracks[track_index].bit_rate) / 50.0) * 50.0; + *br = ((int) dbr); + dbr = round(((double) dev->adv_tracks[track_index].rpm) / 60.0) * 60.0; + *rpm = ((int) dbr); + } +} + + +static void +set_disk_flags(int drive) +{ + int br = 250, rpm = 300; mfm_t *dev = mfm[drive]; uint16_t temp_disk_flags = 0x1080; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0; Bit 12 = 1, bits 6, 5 = 0 - extra bit cells field specifies the entire amount of bit cells per track. */ - switch (dev->br_rounded) { + /* If this is the modified MFM format, get bit rate (and RPM) from track 0 instead. */ + if (dev->hdr.if_type & 0x80) + get_adv_track_bitrate(drive, 0, 0, &br, &rpm); + else { + br = dev->br_rounded; + rpm = dev->rpm_rounded; + } + + switch (br) { case 500: temp_disk_flags |= 2; break; @@ -125,84 +194,35 @@ disk_flags(int drive) if (dev->hdr.sides_no == 2) temp_disk_flags |= 8; - return(temp_disk_flags); -} - - -static int -get_track_index(int drive, int side) -{ - mfm_t *dev = mfm[drive]; - int i, ret = -1; - - for (i = 0; i < dev->total_tracks; i++) { - if ((dev->tracks[i].track_no == dev->cur_track) && - (dev->tracks[i].side_no == side)) { - ret = i; - break; - } - } - - return ret; -} - - -static int -get_adv_track_index(int drive, int side) -{ - mfm_t *dev = mfm[drive]; - int i, ret = -1; - - for (i = 0; i < dev->total_tracks; i++) { - if ((dev->adv_tracks[i].track_no == dev->cur_track) && - (dev->adv_tracks[i].side_no == side)) { - ret = i; - break; - } - } - - return ret; -} - - -static void -get_adv_track_bitrate(int drive, int side, int *br, int *rpm) -{ - mfm_t *dev = mfm[drive]; - int track_index; - double dbr; - - track_index = get_adv_track_index(drive, side); - - if (track_index == -1) { - *br = 250; - *rpm = 300; - } else { - dbr = round(((double) dev->adv_tracks[track_index].bit_rate) / 50.0) * 50.0; - *br = ((int) dbr); - dbr = round(((double) dev->adv_tracks[track_index].rpm) / 60.0) * 60.0; - *rpm = ((int) dbr); - } + dev->disk_flags = temp_disk_flags; } static uint16_t -side_flags(int drive) +disk_flags(int drive) +{ + mfm_t *dev = mfm[drive]; + + return dev->disk_flags; +} + + +static void +set_side_flags(int drive, int side) { mfm_t *dev = mfm[drive]; uint16_t temp_side_flags = 0; - int side, br = 250, rpm = 300; + int br = 250, rpm = 300; - if (dev->hdr.if_type & 0x80) { - side = fdd_get_head(drive); - get_adv_track_bitrate(drive, side, &br, &rpm); - } else { + if (dev->hdr.if_type & 0x80) + get_adv_track_bitrate(drive, side, dev->cur_track, &br, &rpm); + else { br = dev->br_rounded; rpm = dev->rpm_rounded; } /* 300 kbps @ 360 rpm = 250 kbps @ 200 rpm */ - if ((rpm >= 352) && (rpm <= 367) && (br == 300)) { + if ((br == 300) && (rpm == 360)) { br = 250; rpm = 300; } @@ -226,7 +246,7 @@ side_flags(int drive) break; } - if ((rpm >= 352) && (rpm <= 367)) + if (rpm == 360) temp_side_flags |= 0x20; /* @@ -235,7 +255,19 @@ side_flags(int drive) */ temp_side_flags |= 0x08; - return(temp_side_flags); + dev->side_flags[side] = temp_side_flags; +} + + +static uint16_t +side_flags(int drive) +{ + mfm_t *dev = mfm[drive]; + int side; + + side = fdd_get_head(drive); + + return dev->side_flags[side]; } @@ -244,17 +276,33 @@ get_raw_size(int drive, int side) { mfm_t *dev = mfm[drive]; int track_index, is_300_rpm; + int br = 250, rpm = 300; - if (dev->hdr.if_type & 0x80) - track_index = get_adv_track_index(drive, side); - else - track_index = get_track_index(drive, side); + if (dev->hdr.if_type & 0x80) { + track_index = get_adv_track_index(drive, side, dev->cur_track); + get_adv_track_bitrate(drive, 0, 0, &br, &rpm); + } else { + track_index = get_track_index(drive, side, dev->cur_track); + br = dev->br_rounded; + rpm = dev->rpm_rounded; + } - is_300_rpm = (dev->hdr.rpm < 352); + is_300_rpm = (rpm == 300); if (track_index == -1) { - ERRLOG("MFM: Unable to find track (%i, %i)\n", dev->cur_track, side); - return is_300_rpm ? 100000 : 83333; + DEBUG("MFM: unable to find track(%i, %i)\n", dev->cur_track, side); + + switch (br) { + case 250: + default: + return is_300_rpm ? 100000 : 83333; + case 300: + return is_300_rpm ? 120000 : 100000; + case 500: + return is_300_rpm ? 200000 : 166666; + case 1000: + return is_300_rpm ? 400000 : 333333; + } } /* Bit 7 on - my extension of the HxC MFM format to output exact bitcell counts @@ -282,7 +330,7 @@ encoded_data(int drive, int side) } -void +static void mfm_read_side(int drive, int side) { mfm_t *dev = mfm[drive]; @@ -290,9 +338,9 @@ mfm_read_side(int drive, int side) int track_bytes; if (dev->hdr.if_type & 0x80) - track_index = get_adv_track_index(drive, side); + track_index = get_adv_track_index(drive, side, dev->cur_track); else - track_index = get_track_index(drive, side); + track_index = get_track_index(drive, side, dev->cur_track); track_size = get_raw_size(drive, side); track_bytes = track_size >> 3; @@ -306,7 +354,7 @@ mfm_read_side(int drive, int side) fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET); else fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET); - fread(dev->track_data[side], 1, track_size, dev->f); + fread(dev->track_data[side], 1, track_bytes, dev->f); } DEBUG("drive = %i, side = %i, dev->cur_track = %i, track_index = %i, track_size = %i\n", @@ -337,6 +385,9 @@ mfm_seek(int drive, int track) mfm_read_side(drive, 0); mfm_read_side(drive, 1); + + set_side_flags(drive, 0); + set_side_flags(drive, 1); } @@ -363,7 +414,7 @@ mfm_load(int drive, const wchar_t *fn) dev->f = plat_fopen(fn, L"rb"); if (dev->f == NULL) { free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + memset(floppyfns[drive], 0x00, sizeof(floppyfns[drive])); return(0); } @@ -375,10 +426,10 @@ mfm_load(int drive, const wchar_t *fn) /* Calculate tracks * sides, allocate the tracks array, and read it. */ dev->total_tracks = dev->hdr.tracks_no * dev->hdr.sides_no; if (dev->hdr.if_type & 0x80) { - dev->adv_tracks = (mfm_adv_track_t *) malloc(dev->total_tracks * sizeof(mfm_adv_track_t)); + dev->adv_tracks = (mfm_adv_track_t *)mem_alloc(dev->total_tracks * sizeof(mfm_adv_track_t)); fread(dev->adv_tracks, 1, dev->total_tracks * sizeof(mfm_adv_track_t), dev->f); } else { - dev->tracks = (mfm_track_t *) malloc(dev->total_tracks * sizeof(mfm_track_t)); + dev->tracks = (mfm_track_t *)mem_alloc(dev->total_tracks * sizeof(mfm_track_t)); fread(dev->tracks, 1, dev->total_tracks * sizeof(mfm_track_t), dev->f); } @@ -417,6 +468,8 @@ mfm_load(int drive, const wchar_t *fn) /* Set up the drive unit. */ mfm[drive] = dev; + set_disk_flags(drive); + /* Attach this format to the D86F engine. */ d86f_handler[drive].disk_flags = disk_flags; d86f_handler[drive].side_flags = side_flags; diff --git a/src/devices/floppy/new/fdd_mfm.c b/src/devices/floppy/new/fdd_mfm.c new file mode 100644 index 0000000..5886530 --- /dev/null +++ b/src/devices/floppy/new/fdd_mfm.c @@ -0,0 +1,521 @@ +/* + * 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 HxC MFM image format. + * + * Version: @(#)fdd_mfm.c 1.0.1 2019/03/02 + * + * Authors: Miran Grca, + * + * Copyright 2018,2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "../86box.h" +#include "../plat.h" +#include "fdd.h" +#include "fdd_86f.h" +#include "fdd_img.h" +#include "fdd_mfm.h" +#include "fdc.h" + + +#pragma pack(push,1) +typedef struct { + uint8_t hdr_name[7]; + + uint16_t tracks_no; + uint8_t sides_no; + + uint16_t rpm; + uint16_t bit_rate; + uint8_t if_type; + + uint32_t track_list_offset; +} mfm_header_t; + +typedef struct { + uint16_t track_no; + uint8_t side_no; + uint32_t track_size; + uint32_t track_offset; +} mfm_track_t; + +typedef struct { + uint16_t track_no; + uint8_t side_no; + uint16_t rpm; + uint16_t bit_rate; + uint32_t track_size; + uint32_t track_offset; +} mfm_adv_track_t; +#pragma pack(pop) + +typedef struct { + FILE *f; + + mfm_header_t hdr; + mfm_track_t *tracks; + mfm_adv_track_t *adv_tracks; + + uint8_t disk_flags, pad; + uint8_t side_flags[2]; + + int br_rounded, rpm_rounded, + total_tracks, cur_track; + + uint8_t track_data[2][256*1024]; +} mfm_t; + + +static mfm_t *mfm[FDD_NUM]; +static fdc_t *mfm_fdc; + + +#ifdef ENABLE_MFM_LOG +int mfm_do_log = ENABLE_MFM_LOG; + + +static void +mfm_log(const char *fmt, ...) +{ + va_list ap; + + if (mfm_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define mfm_log(fmt, ...) +#endif + + +static int +get_track_index(int drive, int side, int track) +{ + mfm_t *dev = mfm[drive]; + int i, ret = -1; + + for (i = 0; i < dev->total_tracks; i++) { + if ((dev->tracks[i].track_no == track) && + (dev->tracks[i].side_no == side)) { + ret = i; + break; + } + } + + return ret; +} + + +static int +get_adv_track_index(int drive, int side, int track) +{ + mfm_t *dev = mfm[drive]; + int i, ret = -1; + + for (i = 0; i < dev->total_tracks; i++) { + if ((dev->adv_tracks[i].track_no == track) && + (dev->adv_tracks[i].side_no == side)) { + ret = i; + break; + } + } + + return ret; +} + + +static void +get_adv_track_bitrate(int drive, int side, int track, int *br, int *rpm) +{ + mfm_t *dev = mfm[drive]; + int track_index; + double dbr; + + track_index = get_adv_track_index(drive, side, track); + + if (track_index == -1) { + *br = 250; + *rpm = 300; + } else { + dbr = round(((double) dev->adv_tracks[track_index].bit_rate) / 50.0) * 50.0; + *br = ((int) dbr); + dbr = round(((double) dev->adv_tracks[track_index].rpm) / 60.0) * 60.0; + *rpm = ((int) dbr); + } +} + + +static void +set_disk_flags(int drive) +{ + int br = 250, rpm = 300; + mfm_t *dev = mfm[drive]; + uint16_t temp_disk_flags = 0x1080; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0; + Bit 12 = 1, bits 6, 5 = 0 - extra bit cells field specifies the entire + amount of bit cells per track. */ + + /* If this is the modified MFM format, get bit rate (and RPM) from track 0 instead. */ + if (dev->hdr.if_type & 0x80) + get_adv_track_bitrate(drive, 0, 0, &br, &rpm); + else { + br = dev->br_rounded; + rpm = dev->rpm_rounded; + } + + switch (br) { + case 500: + temp_disk_flags |= 2; + break; + + case 300: + case 250: + default: + temp_disk_flags |= 0; + break; + + case 1000: + temp_disk_flags |= 4; + break; + } + + if (dev->hdr.sides_no == 2) + temp_disk_flags |= 8; + + dev->disk_flags = temp_disk_flags; +} + + +static uint16_t +disk_flags(int drive) +{ + mfm_t *dev = mfm[drive]; + + return dev->disk_flags; +} + + +static void +set_side_flags(int drive, int side) +{ + mfm_t *dev = mfm[drive]; + uint16_t temp_side_flags = 0; + int br = 250, rpm = 300; + + if (dev->hdr.if_type & 0x80) + get_adv_track_bitrate(drive, side, dev->cur_track, &br, &rpm); + else { + br = dev->br_rounded; + rpm = dev->rpm_rounded; + } + + /* 300 kbps @ 360 rpm = 250 kbps @ 200 rpm */ + if ((br == 300) && (rpm == 360)) { + br = 250; + rpm = 300; + } + + switch (br) { + case 500: + temp_side_flags = 0; + break; + + case 300: + temp_side_flags = 1; + break; + + case 250: + default: + temp_side_flags = 2; + break; + + case 1000: + temp_side_flags = 3; + break; + } + + if (rpm == 360) + temp_side_flags |= 0x20; + + /* + * Set the encoding value to match that provided by the FDC. + * Then if it's wrong, it will sector not found anyway. + */ + temp_side_flags |= 0x08; + + dev->side_flags[side] = temp_side_flags; +} + + +static uint16_t +side_flags(int drive) +{ + mfm_t *dev = mfm[drive]; + int side; + + side = fdd_get_head(drive); + + return dev->side_flags[side]; +} + + +static uint32_t +get_raw_size(int drive, int side) +{ + mfm_t *dev = mfm[drive]; + int track_index, is_300_rpm; + int br = 250, rpm = 300; + + if (dev->hdr.if_type & 0x80) { + track_index = get_adv_track_index(drive, side, dev->cur_track); + get_adv_track_bitrate(drive, 0, 0, &br, &rpm); + } else { + track_index = get_track_index(drive, side, dev->cur_track); + br = dev->br_rounded; + rpm = dev->rpm_rounded; + } + + is_300_rpm = (rpm == 300); + + if (track_index == -1) { + mfm_log("MFM: Unable to find track (%i, %i)\n", dev->cur_track, side); + switch (br) { + case 250: + default: + return is_300_rpm ? 100000 : 83333; + case 300: + return is_300_rpm ? 120000 : 100000; + case 500: + return is_300_rpm ? 200000 : 166666; + case 1000: + return is_300_rpm ? 400000 : 333333; + } + } + + /* Bit 7 on - my extension of the HxC MFM format to output exact bitcell counts + for each track instead of rounded byte counts. */ + if (dev->hdr.if_type & 0x80) + return dev->adv_tracks[track_index].track_size; + else + return dev->tracks[track_index].track_size * 8; +} + + +static int32_t +extra_bit_cells(int drive, int side) +{ + return (int32_t) get_raw_size(drive, side); +} + + +static uint16_t * +encoded_data(int drive, int side) +{ + mfm_t *dev = mfm[drive]; + + return((uint16_t *)dev->track_data[side]); +} + + +void +mfm_read_side(int drive, int side) +{ + mfm_t *dev = mfm[drive]; + int track_index, track_size; + int track_bytes; + + if (dev->hdr.if_type & 0x80) + track_index = get_adv_track_index(drive, side, dev->cur_track); + else + track_index = get_track_index(drive, side, dev->cur_track); + + track_size = get_raw_size(drive, side); + track_bytes = track_size >> 3; + if (track_size & 0x07) + track_bytes++; + + if (track_index == -1) + memset(dev->track_data[side], 0x00, track_bytes); + else { + if (dev->hdr.if_type & 0x80) + fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET); + else + fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET); + fread(dev->track_data[side], 1, track_size, dev->f); + } + + mfm_log("drive = %i, side = %i, dev->cur_track = %i, track_index = %i, track_size = %i\n", + drive, side, dev->cur_track, track_index, track_size); +} + + +void +mfm_seek(int drive, int track) +{ + mfm_t *dev = mfm[drive]; + + mfm_log("mfm_seek(%i, %i)\n", drive, track); + + if (fdd_doublestep_40(drive)) { + if (dev->hdr.tracks_no <= 43) + track /= 2; + } + + dev->cur_track = track; + d86f_set_cur_track(drive, track); + + if (dev->f == NULL) + return; + + if (track < 0) + track = 0; + + mfm_read_side(drive, 0); + mfm_read_side(drive, 1); + + set_side_flags(drive, 0); + set_side_flags(drive, 1); +} + + +void +mfm_load(int drive, wchar_t *fn) +{ + mfm_t *dev; + double dbr; + int i; + + writeprot[drive] = fwriteprot[drive] = 1; + + /* Allocate a drive block. */ + dev = (mfm_t *)malloc(sizeof(mfm_t)); + memset(dev, 0x00, sizeof(mfm_t)); + + dev->f = plat_fopen(fn, L"rb"); + if (dev->f == NULL) { + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + + d86f_unregister(drive); + + /* Read the header. */ + fread(&dev->hdr, 1, sizeof(mfm_header_t), dev->f); + + /* Calculate tracks * sides, allocate the tracks array, and read it. */ + dev->total_tracks = dev->hdr.tracks_no * dev->hdr.sides_no; + if (dev->hdr.if_type & 0x80) { + dev->adv_tracks = (mfm_adv_track_t *) malloc(dev->total_tracks * sizeof(mfm_adv_track_t)); + fread(dev->adv_tracks, 1, dev->total_tracks * sizeof(mfm_adv_track_t), dev->f); + } else { + dev->tracks = (mfm_track_t *) malloc(dev->total_tracks * sizeof(mfm_track_t)); + fread(dev->tracks, 1, dev->total_tracks * sizeof(mfm_track_t), dev->f); + } + + /* The chances of finding a HxC MFM image of a single-sided thin track + disk are much smaller than the chances of finding a HxC MFM image + incorrectly converted from a SCP image, erroneously indicating 1 + side and 80+ tracks instead of 2 sides and <= 43 tracks, so if we + have detected such an image, convert the track numbers. */ + if ((dev->hdr.tracks_no > 43) && (dev->hdr.sides_no == 1)) { + dev->hdr.tracks_no >>= 1; + dev->hdr.sides_no <<= 1; + + for (i = 0; i < dev->total_tracks; i++) { + if (dev->hdr.if_type & 0x80) { + dev->adv_tracks[i].side_no <<= 1; + dev->adv_tracks[i].side_no |= (dev->adv_tracks[i].track_no & 1); + dev->adv_tracks[i].track_no >>= 1; + } else { + dev->tracks[i].side_no <<= 1; + dev->tracks[i].side_no |= (dev->tracks[i].track_no & 1); + dev->tracks[i].track_no >>= 1; + } + } + } + + if (!(dev->hdr.if_type & 0x80)) { + dbr = round(((double) dev->hdr.bit_rate) / 50.0) * 50.0; + dev->br_rounded = (int) dbr; + mfm_log("Rounded bit rate: %i kbps\n", dev->br_rounded); + + dbr = round(((double) dev->hdr.rpm) / 60.0) * 60.0; + dev->rpm_rounded = (int) dbr; + mfm_log("Rounded RPM: %i kbps\n", dev->rpm_rounded); + } + + /* Set up the drive unit. */ + mfm[drive] = dev; + + set_disk_flags(drive); + + /* Attach this format to the D86F engine. */ + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = null_writeback; + d86f_handler[drive].set_sector = null_set_sector; + d86f_handler[drive].write_data = null_write_data; + d86f_handler[drive].format_conditions = null_format_conditions; + d86f_handler[drive].extra_bit_cells = extra_bit_cells; + d86f_handler[drive].encoded_data = encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = get_raw_size; + d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, D86FVER); + + d86f_common_handlers(drive); + + drives[drive].seek = mfm_seek; + + mfm_log("Loaded as MFM\n"); +} + + +void +mfm_close(int drive) +{ + mfm_t *dev = mfm[drive]; + + if (dev == NULL) return; + + d86f_unregister(drive); + + drives[drive].seek = NULL; + + if (dev->tracks) + free(dev->tracks); + + if (dev->adv_tracks) + free(dev->adv_tracks); + + if (dev->f) + fclose(dev->f); + + /* Release the memory. */ + free(dev); + mfm[drive] = NULL; +} + + +void +mfm_set_fdc(void *fdc) +{ + mfm_fdc = (fdc_t *)fdc; +} diff --git a/src/devices/floppy/new/fdd_mfm.h b/src/devices/floppy/new/fdd_mfm.h new file mode 100644 index 0000000..2aba3fb --- /dev/null +++ b/src/devices/floppy/new/fdd_mfm.h @@ -0,0 +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. + * + * Implementation of the HxC MFM image format. + * + * Version: @(#)fdd_mfm.h 1.0.0 2018/11/12 + * + * Authors: Miran Grca, + * + * Copyright 2018 Miran Grca. + */ +#ifndef EMU_FLOPPY_MFM_H +# define EMU_FLOPPY_MFM_H + + +extern void mfm_seek(int drive, int track); +extern void mfm_load(int drive, wchar_t *fn); +extern void mfm_close(int drive); + + +#endif /*EMU_FLOPPY_MFM_H*/ diff --git a/src/devices/input/keyboard.c b/src/devices/input/keyboard.c index ae3e79e..dc59110 100644 --- a/src/devices/input/keyboard.c +++ b/src/devices/input/keyboard.c @@ -8,13 +8,13 @@ * * General keyboard driver interface. * - * Version: @(#)keyboard.c 1.0.11 2018/10/20 + * Version: @(#)keyboard.c 1.0.12 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,7 +44,6 @@ #define HAVE_STDARG_H #define dbglog kbd_log #include "../../emu.h" -#include "../../machines/machine.h" #include "../../plat.h" #include "../../ui/ui.h" #include "keyboard.h" diff --git a/src/devices/input/keyboard.h b/src/devices/input/keyboard.h index b222987..74615d7 100644 --- a/src/devices/input/keyboard.h +++ b/src/devices/input/keyboard.h @@ -8,7 +8,7 @@ * * Definitions for the keyboard interface. * - * Version: @(#)keyboard.h 1.0.8 2019/02/11 + * Version: @(#)keyboard.h 1.0.10 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -85,8 +85,9 @@ extern const device_t keyboard_pc_device; extern const device_t keyboard_pc82_device; extern const device_t keyboard_xt_device; extern const device_t keyboard_xt86_device; +extern const device_t keyboard_generic_device; extern const device_t keyboard_tandy_device; -extern const device_t keyboard_xt_lxt3_device; +extern const device_t keyboard_laserxt3_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; @@ -126,6 +127,13 @@ extern void keyboard_cab(void); extern int keyboard_isfsexit(void); extern int keyboard_ismsexit(void); +extern void keyboard_xt_set_funcs(void *arg, + uint8_t (*func)(void *), void *priv); +extern void keyboard_at_set_funcs(void *arg, + uint8_t (*rfunc)(void *), + void (*wfunc)(void *, uint8_t), + void *priv); + extern void keyboard_at_adddata_keyboard_raw(uint8_t val); extern void keyboard_at_adddata_mouse(uint8_t val); extern void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val,void *), void *); diff --git a/src/devices/input/keyboard_at.c b/src/devices/input/keyboard_at.c index f2467c7..e07794e 100644 --- a/src/devices/input/keyboard_at.c +++ b/src/devices/input/keyboard_at.c @@ -11,7 +11,7 @@ * NOTE: Several changes to disable Mode1 for now, as this breaks * the TSX32 operating system. More cleanups needed.. * - * Version: @(#)keyboard_at.c 1.0.17 2019/02/12 + * Version: @(#)keyboard_at.c 1.0.21 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,7 +47,6 @@ #define dbglog kbd_log #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../timer.h" @@ -60,10 +59,11 @@ #include "../sound/sound.h" #include "../sound/snd_speaker.h" #include "../video/video.h" +#include "../../plat.h" #include "keyboard.h" -#include "../../machines/m_at_t3100e.h" -#include "../../machines/m_xt_xi8088.h" +//FIXME: get rid of this! +#include "../../machines/m_tosh3100e.h" #define STAT_PARITY 0x80 @@ -143,6 +143,11 @@ typedef struct { uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); + + /* Custom machine-dependent keyboard stuff. */ + uint8_t (*read_func)(void *priv); + void (*write_func)(void *priv, uint8_t val); + void *func_priv; } atkbd_t; @@ -741,13 +746,14 @@ kbd_adddata_vals(uint8_t *val, uint8_t len) static void kbd_adddata_keyboard(uint16_t val) { - int xt_mode = (keyboard_mode & 0x20) && ((CurrentKbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1); + atkbd_t *kbd = CurrentKbd; + int xt_mode = (keyboard_mode & 0x20) && ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1); int translate = (keyboard_mode & 0x40); uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((CurrentKbd->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + translate = translate || ((kbd->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); num_lock = !!(keyboard_get_state() & KBD_FLAG_NUM); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; @@ -767,24 +773,24 @@ kbd_adddata_keyboard(uint16_t val) } /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((CurrentKbd != NULL) && - ((CurrentKbd->flags & KBC_VEN_MASK) == KBC_VEN_TOSHIBA) && + if ((kbd != NULL) && + ((kbd->flags & KBC_VEN_MASK) == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { - case 0x4f: t3100e_notify_set(0x01); break; /* End */ - case 0x50: t3100e_notify_set(0x02); break; /* Down */ - case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ - case 0x52: t3100e_notify_set(0x04); break; /* Ins */ - case 0x53: t3100e_notify_set(0x05); break; /* Del */ - case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ - case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ - case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ - case 0x47: t3100e_notify_set(0x09); break; /* Home */ - case 0x48: t3100e_notify_set(0x0A); break; /* Up */ - case 0x49: t3100e_notify_set(0x0B); break; /* PgUp */ - case 0x4A: t3100e_notify_set(0x0C); break; /* Keypad -*/ - case 0x4B: t3100e_notify_set(0x0D); break; /* Left */ - case 0x4C: t3100e_notify_set(0x0E); break; /* KP 5 */ - case 0x4D: t3100e_notify_set(0x0F); break; /* Right */ + case 0x4f: t3100e_notify_set(kbd->func_priv, 0x01); break; /* End */ + case 0x50: t3100e_notify_set(kbd->func_priv, 0x02); break; /* Down */ + case 0x51: t3100e_notify_set(kbd->func_priv, 0x03); break; /* PgDn */ + case 0x52: t3100e_notify_set(kbd->func_priv, 0x04); break; /* Ins */ + case 0x53: t3100e_notify_set(kbd->func_priv, 0x05); break; /* Del */ + case 0x54: t3100e_notify_set(kbd->func_priv, 0x06); break; /* SysRQ */ + case 0x45: t3100e_notify_set(kbd->func_priv, 0x07); break; /* NumLock */ + case 0x46: t3100e_notify_set(kbd->func_priv, 0x08); break; /* ScrLock */ + case 0x47: t3100e_notify_set(kbd->func_priv, 0x09); break; /* Home */ + case 0x48: t3100e_notify_set(kbd->func_priv, 0x0a); break; /* Up */ + case 0x49: t3100e_notify_set(kbd->func_priv, 0x0b); break; /* PgUp */ + case 0x4A: t3100e_notify_set(kbd->func_priv, 0x0c); break; /* Keypad -*/ + case 0x4B: t3100e_notify_set(kbd->func_priv, 0x0d); break; /* Left */ + case 0x4C: t3100e_notify_set(kbd->func_priv, 0x0e); break; /* KP 5 */ + case 0x4D: t3100e_notify_set(kbd->func_priv, 0x0f); break; /* Right */ } DEBUG("ATkbd: translate is %s, ", translate ? "on" : "off"); @@ -954,8 +960,7 @@ kbd_output_write(atkbd_t *kbd, uint8_t val) } if ((kbd->output_port ^ val) & 0x01) { /*Reset*/ if (! (val & 0x01)) { - /* Pin 0 selected. */ - softresetx86(); /*Pulse reset!*/ + cpu_reset(0); cpu_set_edx(); } } @@ -1427,7 +1432,7 @@ kbd_write60_toshiba(void *p, uint8_t val) switch(kbd->command) { case 0xb6: /* T3100e - set color/mono switch */ - t3100e_mono_set(val); + t3100e_mono_set(kbd->func_priv, val); return 0; } @@ -1446,11 +1451,11 @@ kbd_write64_toshiba(void *p, uint8_t val) return 1; case 0xb0: /* T3100e: Turbo on */ - t3100e_turbo_set(1); + t3100e_turbo_set(kbd->func_priv, 1); return 0; case 0xb1: /* T3100e: Turbo off */ - t3100e_turbo_set(0); + t3100e_turbo_set(kbd->func_priv, 0); return 0; case 0xb2: /* T3100e: Select external display */ @@ -1462,11 +1467,11 @@ kbd_write64_toshiba(void *p, uint8_t val) return 0; case 0xb4: /* T3100e: Get configuration / status */ - kbd_adddata(t3100e_config_get()); + kbd_adddata(t3100e_config_get(kbd->func_priv)); return 0; case 0xb5: /* T3100e: Get colour / mono byte */ - kbd_adddata(t3100e_mono_get()); + kbd_adddata(t3100e_mono_get(kbd->func_priv)); return 0; case 0xb6: /* T3100e: Set colour / mono byte */ @@ -1488,7 +1493,7 @@ kbd_write64_toshiba(void *p, uint8_t val) return 0; case 0xbc: /* T3100e: Reset Fn+Key notification */ - t3100e_notify_set(0x00); + t3100e_notify_set(kbd->func_priv, 0x00); return 0; case 0xc0: /*Read input port*/ @@ -1496,7 +1501,7 @@ kbd_write64_toshiba(void *p, uint8_t val) /* The T3100e returns all bits set except bit 6 which * is set by t3100e_mono_set() */ - kbd->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + kbd->input_port = (t3100e_mono_get(kbd->func_priv) & 1) ? 0xff : 0xbf; kbd_adddata(kbd->input_port); return 0; @@ -1772,10 +1777,7 @@ do_command: pit_set_gate(&pit, 2, val & 1); if ((kbd->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) { - if (val & 0x04) - xi8088_turbo_set(1); - else - xi8088_turbo_set(0); + kbd->write_func(kbd->func_priv, !!(val & 0x04)); } break; @@ -1946,7 +1948,7 @@ kbd_read(uint16_t port, void *priv) ret &= ~0x10; } if ((kbd->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) { - if (xi8088_turbo_get()) + if (kbd->read_func(kbd->func_priv)) ret |= 0x04; else ret &= ~0x04; @@ -2013,7 +2015,7 @@ kbd_reset(void *priv) static void * -kbd_init(const device_t *info) +kbd_init(const device_t *info, UNUSED(void *parent)) { atkbd_t *kbd; @@ -2110,6 +2112,7 @@ const device_t keyboard_at_device = { "PC/AT Keyboard", 0, KBC_TYPE_ISA | KBC_VEN_GENERIC, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2119,6 +2122,7 @@ const device_t keyboard_at_ami_device = { "PC/AT Keyboard (AMI)", 0, KBC_TYPE_ISA | KBC_VEN_AMI, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2128,6 +2132,7 @@ const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, KBC_TYPE_ISA | KBC_VEN_TOSHIBA, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2137,6 +2142,7 @@ const device_t keyboard_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2146,6 +2152,7 @@ const device_t keyboard_ps2_xi8088_device = { "PS/2 Keyboard (Xi8088)", 0, KBC_TYPE_PS2_1 | KBC_VEN_XI8088, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2155,6 +2162,7 @@ const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, KBC_TYPE_PS2_1 | KBC_VEN_AMI, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2164,6 +2172,7 @@ const device_t keyboard_ps2_mca_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2173,6 +2182,7 @@ const device_t keyboard_ps2_mca_2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2182,6 +2192,7 @@ const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2191,6 +2202,7 @@ const device_t keyboard_ps2_pci_device = { "PS/2 Keyboard", DEVICE_PCI, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2200,6 +2212,7 @@ const device_t keyboard_ps2_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, KBC_TYPE_PS2_1 | KBC_VEN_AMI, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -2230,6 +2243,18 @@ keyboard_at_adddata_mouse(uint8_t val) } +/* Set custom machine-dependent keyboard stuff. */ +void +keyboard_at_set_funcs(void *arg, uint8_t (*readfunc)(void *), void (*writefunc)(void *, uint8_t), void *priv) +{ + atkbd_t *kbd = (atkbd_t *)arg; + + kbd->read_func = readfunc; + kbd->write_func = writefunc; + kbd->func_priv = priv; +} + + void keyboard_at_set_mouse_scan(uint8_t val) { diff --git a/src/devices/input/keyboard_xt.c b/src/devices/input/keyboard_xt.c index 5174d5f..6094827 100644 --- a/src/devices/input/keyboard_xt.c +++ b/src/devices/input/keyboard_xt.c @@ -8,7 +8,7 @@ * * Implementation of the XT-style keyboard. * - * Version: @(#)keyboard_xt.c 1.0.14 2019/02/14 + * Version: @(#)keyboard_xt.c 1.0.16 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,7 +43,6 @@ #include #define dbglog kbd_log #include "../../emu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../timer.h" #include "../../device.h" @@ -54,6 +53,7 @@ #include "../sound/sound.h" #include "../sound/snd_speaker.h" #include "../video/video.h" +#include "../../plat.h" #ifdef USE_CASSETTE # include #endif @@ -75,6 +75,7 @@ enum { KBC_PC82, /* IBM PC, 1982 */ KBC_XT, /* IBM PC/XT, 1982 */ KBC_XT86, /* IBM PC/XT, 1986, and most clones */ + KBC_GENERIC, /* Generic XT (no FDD count or memory size) */ KBC_TANDY, /* Tandy XT */ KBC_LASER /* VTech LaserXT */ }; @@ -82,7 +83,6 @@ enum { typedef struct { uint8_t type; - int8_t tandy; uint8_t pa, pb, @@ -91,6 +91,9 @@ typedef struct { int8_t want_irq; int8_t blocked; uint8_t key_waiting; + + uint8_t (*read_func)(void *); + void *func_priv; } xtkbd_t; @@ -363,26 +366,24 @@ static int key_queue_start, static void kbd_poll(void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *dev = (xtkbd_t *)priv; keyboard_delay += (1000LL * TIMER_USEC); - if (!(kbd->pb & 0x40) && (! kbd->tandy)) + if (!(dev->pb & 0x40) && (dev->type != KBC_TANDY)) return; - if (kbd->want_irq) { - kbd->want_irq = 0; - kbd->pa = kbd->key_waiting; - kbd->blocked = 1; + if (dev->want_irq) { + dev->want_irq = 0; + dev->pa = dev->key_waiting; + dev->blocked = 1; picint(2); } - if (key_queue_start != key_queue_end && !kbd->blocked) { - kbd->key_waiting = key_queue[key_queue_start]; - DBGLOG(1, "XTkbd: reading %02X from the key queue at %i\n", - kbd->pa, key_queue_start); + if (key_queue_start != key_queue_end && !dev->blocked) { + dev->key_waiting = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0x0f; - kbd->want_irq = 1; + dev->want_irq = 1; } } @@ -391,9 +392,6 @@ static void kbd_adddata(uint16_t val) { key_queue[key_queue_end] = val & 0xff; - - DBGLOG(1, "XTkbd: %02X added to key queue at %i\n", - val, key_queue_end); key_queue_end = (key_queue_end + 1) & 0x0f; } @@ -411,7 +409,7 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) switch(val) { case FAKE_LSHIFT_ON: if (num_lock) { - if (!shift_states) { + if (! shift_states) { /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ adddata(0x2a); } @@ -429,7 +427,7 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) case FAKE_LSHIFT_OFF: if (num_lock) { - if (!shift_states) { + if (! shift_states) { /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ adddata(0xaa); } @@ -462,17 +460,17 @@ kbd_adddata_ex(uint16_t val) static void kbd_write(uint16_t port, uint8_t val, void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *dev = (xtkbd_t *)priv; switch (port) { case 0x61: - if (!(kbd->pb & 0x40) && (val & 0x40)) { + if (!(dev->pb & 0x40) && (val & 0x40)) { key_queue_start = key_queue_end = 0; - kbd->want_irq = 0; - kbd->blocked = 0; + dev->want_irq = 0; + dev->blocked = 0; kbd_adddata(0xaa); } - kbd->pb = val; + dev->pb = val; ppi.pb = val; timer_process(); @@ -484,23 +482,39 @@ kbd_write(uint16_t port, uint8_t val, void *priv) speaker_gated = val & 1; speaker_enable = val & 2; - if (kbd->type <= KBC_PC82) { #ifdef USE_CASSETTE + if (dev->type <= KBC_PC82) { if (cassette_enabled) cassette_motor(! (val & 0x08)); -#endif } +#endif if (speaker_enable) speaker_was_enable = 1; pit_set_gate(&pit, 2, val & 1); if (val & 0x80) { - kbd->pa = 0; - kbd->blocked = 0; + dev->pa = 0; + dev->blocked = 0; picintc(2); } break; + + case 0x63: + /* + * The value written to port 63H is normally 99H, + * being the correct 'setup byte' for the original + * Intel 8255 PPI device. + * + * We ignore it here. + */ + if (val == 0x99) + break; + /*FALLTHROUGH*/ + + default: + ERRLOG("XTkbd: write(%04x, %02x) invalid\n", port, val); + break; } } @@ -508,65 +522,69 @@ kbd_write(uint16_t port, uint8_t val, void *priv) static uint8_t kbd_read(uint16_t port, void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *dev = (xtkbd_t *)priv; uint8_t ret = 0xff; switch (port) { case 0x60: - if ((kbd->type <= KBC_PC82) && (kbd->pb & 0x80)) - ret = kbd->pd; - else if (((kbd->type == KBC_XT) || (kbd->type == KBC_XT86)) && - (kbd->pb & 0x80)) - ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */ + if ((dev->type <= KBC_PC82) && (dev->pb & 0x80)) + ret = dev->pd; + else if (((dev->type == KBC_XT) || (dev->type == KBC_XT86)) && + (dev->pb & 0x80)) + ret = 0xff; /* According to Ruud on the PCem forum, + * this is supposed to return 0xff on + * the XT. FIXME: check! + */ else - ret = kbd->pa; + ret = dev->pa; break; case 0x61: - ret = kbd->pb; + ret = dev->pb; break; case 0x62: - if (kbd->type == KBC_PC) + if (dev->type == KBC_PC) ret = 0x00; - else if (kbd->type == KBC_PC82) { - if (kbd->pb & 0x04) + else if (dev->type == KBC_PC82) { + if (dev->pb & 0x04) ret = ((mem_size - 64) / 32) & 0x0f; else ret = ((mem_size - 64) / 32) >> 4; } else { - if (kbd->pb & 0x08) - ret = kbd->pd >> 4; + if (dev->pb & 0x08) + ret = dev->pd >> 4; else { - if (kbd->type == KBC_LASER) + if (dev->type == KBC_LASER) /* LaserXT = Always 512k RAM; * LaserXT/3 = Bit 0: 1=512K, 0=256K */ ret = (mem_size == 512) ? 0x0d : 0x0c; else - ret = kbd->pd & 0x0f; + ret = dev->pd & 0x0f; } - if (kbd->type == KBC_TANDY) - ret |= (tandy1k_eeprom_read() ? 0x10 : 0); + /* Tandy uses bit4 for the Serial EEPROM. */ + if (dev->type == KBC_TANDY) + ret |= dev->read_func(dev->func_priv) ? 0x10 : 0x00; } /* Indicate the PC SPEAKER state. */ ret |= (ppispeakon ? 0x20 : 0); /* Make the IBM PC BIOS happy (Cassette Interface.) */ - if (kbd->type <= KBC_PC82) + if (dev->type <= KBC_PC82) ret |= (ppispeakon ? 0x10 : 0); break; case 0x63: - if ((kbd->type == KBC_XT) || (kbd->type == KBC_XT86)) - ret = kbd->pd; + if ((dev->type == KBC_XT) || (dev->type == KBC_XT86) || (dev->type == KBC_GENERIC)) + ret = dev->pd; break; default: - ERRLOG("XTkbd: bad read %04X\n", port); + ERRLOG("XTkbd: read(%04x) invalid\n", port); break; } @@ -577,29 +595,29 @@ kbd_read(uint16_t port, void *priv) static void kbd_reset(void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *dev = (xtkbd_t *)priv; - kbd->want_irq = 0; - kbd->blocked = 0; - kbd->pa = 0x00; - kbd->pb = 0x00; + dev->want_irq = 0; + dev->blocked = 0; + dev->pa = 0x00; + dev->pb = 0x00; keyboard_scan = 1; - key_queue_start = 0, + key_queue_start = 0; key_queue_end = 0; } static void * -kbd_init(const device_t *info) +kbd_init(const device_t *info, UNUSED(void *parent)) { int i, fdd_count = 0; - xtkbd_t *kbd; + xtkbd_t *dev; - kbd = (xtkbd_t *)mem_alloc(sizeof(xtkbd_t)); - memset(kbd, 0x00, sizeof(xtkbd_t)); - kbd->type = info->local; + dev = (xtkbd_t *)mem_alloc(sizeof(xtkbd_t)); + memset(dev, 0x00, sizeof(xtkbd_t)); + dev->type = info->local; /* See how many diskette drives we have. */ for (i = 0; i < FDD_NUM; i++) { @@ -607,90 +625,89 @@ kbd_init(const device_t *info) fdd_count++; } - if (kbd->type <= KBC_XT86) { - + if (dev->type <= KBC_XT86) { /* * DIP switch readout: bit set = OFF, clear = ON. * * Switches 7, 8 - floppy drives. */ if (fdd_count == 0) - kbd->pd = 0x00; + dev->pd = 0x00; else - kbd->pd = ((fdd_count - 1) << 6); + dev->pd = ((fdd_count - 1) << 6); /* Switches 5, 6 - video. */ i = video_type(); if (i == VID_TYPE_MDA) - kbd->pd |= 0x30; /* MDA/Herc */ + dev->pd |= 0x30; /* MDA/Herc */ #if 0 else if (i == VID_TYPE_CGA40) - kbd->pd |= 0x10; /* CGA, 40 columns */ + dev->pd |= 0x10; /* CGA, 40 columns */ #endif else if (i == VID_TYPE_CGA) - kbd->pd |= 0x20; /* CGA, 80 colums */ + dev->pd |= 0x20; /* CGA, 80 colums */ else if (i == VID_TYPE_SPEC) - kbd->pd |= 0x00; /* EGA/VGA */ + dev->pd |= 0x00; /* EGA/VGA */ /* Switches 3, 4 - memory size. */ - if (kbd->type == KBC_XT86) { + if (dev->type == KBC_XT86) { /* PC/XT (1986) and up. */ switch (mem_size) { case 256: - kbd->pd |= 0x00; + dev->pd |= 0x00; break; case 512: - kbd->pd |= 0x04; + dev->pd |= 0x04; break; case 576: - kbd->pd |= 0x08; + dev->pd |= 0x08; break; case 640: default: - kbd->pd |= 0x0c; + dev->pd |= 0x0c; break; } - } else if (kbd->type >= KBC_PC82) { + } else if (dev->type >= KBC_PC82) { /* PC (1982) and PC/XT (1982.) */ switch (mem_size) { case 64: - kbd->pd |= 0x00; + dev->pd |= 0x00; break; case 128: - kbd->pd |= 0x04; + dev->pd |= 0x04; break; case 192: - kbd->pd |= 0x08; + dev->pd |= 0x08; break; case 256: default: - kbd->pd |= 0x0c; + dev->pd |= 0x0c; break; } - } else { + } else if (dev->type >= KBC_PC) { /* PC (1981.) */ switch (mem_size) { case 16: - kbd->pd |= 0x00; + dev->pd |= 0x00; break; case 32: - kbd->pd |= 0x04; + dev->pd |= 0x04; break; case 48: - kbd->pd |= 0x08; + dev->pd |= 0x08; break; case 64: default: - kbd->pd |= 0x0c; + dev->pd |= 0x0c; break; } } @@ -699,27 +716,27 @@ kbd_init(const device_t *info) /* Switch 1 - diskette drives available? */ if (fdd_count > 0) - kbd->pd |= 0x01; + dev->pd |= 0x01; } keyboard_send = kbd_adddata_ex; - kbd_reset(kbd); + kbd_reset(dev); io_sethandler(0x0060, 4, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); - timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, kbd); + timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, dev); keyboard_set_table(scancode_xt); - return(kbd); + return(dev); } static void kbd_close(void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *dev = (xtkbd_t *)priv; /* Stop the timer. */ keyboard_delay = 0; @@ -730,9 +747,9 @@ kbd_close(void *priv) keyboard_send = NULL; io_removehandler(0x0060, 4, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); - free(kbd); + free(dev); } @@ -740,6 +757,7 @@ const device_t keyboard_pc_device = { "IBM PC (1981) Keyboard", 0, KBC_PC, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -749,6 +767,7 @@ const device_t keyboard_pc82_device = { "IBM PC (1982) Keyboard", 0, KBC_PC82, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -758,6 +777,7 @@ const device_t keyboard_xt_device = { "IBM PC/XT (1982) Keyboard", 0, KBC_XT, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -767,6 +787,17 @@ const device_t keyboard_xt86_device = { "IBM PC/XT (1986) Keyboard", 0, KBC_XT86, + NULL, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t keyboard_generic_device = { + "Generic XT Keyboard", + 0, + KBC_GENERIC, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -776,16 +807,28 @@ const device_t keyboard_tandy_device = { "Tandy 1000 Keyboard", 0, KBC_TANDY, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL }; -const device_t keyboard_xt_lxt3_device = { +const device_t keyboard_laserxt3_device = { "VTech Laser XT3 Keyboard", 0, KBC_LASER, + NULL, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL }; + + +void +keyboard_xt_set_funcs(void *arg, uint8_t (*func)(void *), void *priv) +{ + xtkbd_t *dev = (xtkbd_t *)arg; + + dev->read_func = func; + dev->func_priv = priv; +} diff --git a/src/devices/input/mouse.c b/src/devices/input/mouse.c index 5aba015..2d05245 100644 --- a/src/devices/input/mouse.c +++ b/src/devices/input/mouse.c @@ -10,12 +10,12 @@ * * TODO: Add the Genius bus- and serial mouse. * - * Version: @(#)mouse.c 1.0.16 2018/11/20 + * Version: @(#)mouse.c 1.0.18 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * Redistribution and use in source and binary forms, with @@ -57,6 +57,7 @@ #define dbglog mouse_log #include "../../emu.h" #include "../../device.h" +#include "../../plat.h" #include "mouse.h" @@ -71,14 +72,14 @@ int mouse_x, static const device_t mouse_none_device = { "Disabled", - 0, MOUSE_NONE, + 0, MOUSE_NONE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const device_t mouse_internal_device = { "Internal", - 0, MOUSE_INTERNAL, + 0, MOUSE_INTERNAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/input/mouse.h b/src/devices/input/mouse.h index 0cb8182..0eacb7b 100644 --- a/src/devices/input/mouse.h +++ b/src/devices/input/mouse.h @@ -8,12 +8,12 @@ * * Definitions for the mouse driver. * - * Version: @(#)mouse.h 1.0.9 2018/11/10 + * Version: @(#)mouse.h 1.0.10 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * Redistribution and use in source and binary forms, with @@ -77,7 +77,7 @@ extern int mouse_buttons; #ifdef EMU_DEVICE_H extern const device_t *mouse_get_device(int mouse); -extern void *mouse_ps2_init(const device_t *); +extern void *mouse_ps2_init(const device_t *, void *parent); extern const device_t mouse_logibus_device; extern const device_t mouse_logibus_internal_device; diff --git a/src/devices/input/mouse_bus.c b/src/devices/input/mouse_bus.c index 282d781..35e9303 100644 --- a/src/devices/input/mouse_bus.c +++ b/src/devices/input/mouse_bus.c @@ -53,12 +53,12 @@ * Microsoft Windows NT 3.1 * Microsoft Windows 98 SE * - * Version: @(#)mouse_bus.c 1.1.3 2018/11/20 + * Version: @(#)mouse_bus.c 1.1.5 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2017,2018 Miran Grca. * Copyright 200?-2018 Bochs. * @@ -104,6 +104,7 @@ #include "../../device.h" #include "../../random.h" #include "../system/pic.h" +#include "../../plat.h" #include "mouse.h" @@ -656,7 +657,7 @@ bm_close(void *priv) /* Initialize the device for use by the user. */ static void * -bm_init(const device_t *info) +bm_init(const device_t *info, UNUSED(void *parent)) { mouse_t *dev; @@ -738,19 +739,19 @@ static const device_config_t lt_config[] = { "base", "Address", CONFIG_HEX16, "", 0x23c, { { - "0x230", 0x230 + "230H", 0x230 }, { - "0x234", 0x234 + "234H", 0x234 }, { - "0x238", 0x238 + "238H", 0x238 }, { - "0x23C", 0x23c + "23CH", 0x23c }, { - "" + NULL } } }, @@ -769,7 +770,7 @@ static const device_config_t lt_config[] = { "IRQ 5", 5 }, { - "" + NULL } } }, @@ -785,7 +786,7 @@ static const device_config_t lt_config[] = { "60 Hz (JMP 2 = 2)", 60 }, { - "" + NULL } } }, @@ -798,12 +799,12 @@ static const device_config_t lt_config[] = { "Three", 3 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -813,19 +814,19 @@ static const device_config_t ms_config[] = { "base", "Address", CONFIG_HEX16, "", 0x23c, { { - "0x230", 0x230 + "230H", 0x230 }, { - "0x234", 0x234 + "234H", 0x234 }, { - "0x238", 0x238 + "238H", 0x238 }, { - "0x23C", 0x23c + "23CH", 0x23c }, { - "" + NULL } } }, @@ -844,7 +845,7 @@ static const device_config_t ms_config[] = { "IRQ 5", 5 }, { - "" + NULL } } }, @@ -857,12 +858,12 @@ static const device_config_t ms_config[] = { "Three", 3 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -871,6 +872,7 @@ const device_t mouse_logibus_device = { "Logitech Bus Mouse", DEVICE_ISA, 0, + NULL, bm_init, bm_close, NULL, bm_poll, NULL, NULL, NULL, @@ -881,6 +883,7 @@ const device_t mouse_logibus_internal_device = { "Logitech Bus Mouse (Internal)", 0, 1, + NULL, bm_init, bm_close, NULL, bm_poll, NULL, NULL, NULL, @@ -891,6 +894,7 @@ const device_t mouse_msinport_device = { "Microsoft Bus Mouse (InPort)", DEVICE_ISA, 10, + NULL, bm_init, bm_close, NULL, bm_poll, NULL, NULL, NULL, diff --git a/src/devices/input/mouse_ps2.c b/src/devices/input/mouse_ps2.c index dbb68a1..a8299c7 100644 --- a/src/devices/input/mouse_ps2.c +++ b/src/devices/input/mouse_ps2.c @@ -8,13 +8,13 @@ * * Implementation of PS/2 series Mouse devices. * - * Version: @(#)mouse_ps2.c 1.0.8 2018/10/05 + * Version: @(#)mouse_ps2.c 1.0.10 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,6 +44,7 @@ #define dbglog mouse_log #include "../../emu.h" #include "../../device.h" +#include "../../plat.h" #include "keyboard.h" #include "mouse.h" @@ -246,7 +247,7 @@ ps2_poll(int x, int y, int z, int b, void *priv) * We also get called from the various machines. */ void * -mouse_ps2_init(const device_t *info) +mouse_ps2_init(const device_t *info, UNUSED(void *parent)) { mouse_t *dev; int i; @@ -300,12 +301,12 @@ static const device_config_t ps2_config[] = { "Wheel", 4 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -314,6 +315,7 @@ const device_t mouse_ps2_device = { "Standard PS/2 Mouse", 0, MOUSE_PS2, + NULL, mouse_ps2_init, ps2_close, NULL, ps2_poll, NULL, NULL, NULL, ps2_config diff --git a/src/devices/input/mouse_serial.c b/src/devices/input/mouse_serial.c index 6831870..19f5b94 100644 --- a/src/devices/input/mouse_serial.c +++ b/src/devices/input/mouse_serial.c @@ -10,12 +10,12 @@ * * TODO: Add the Genius Serial Mouse. * - * Version: @(#)mouse_serial.c 1.0.12 2018/11/13 + * Version: @(#)mouse_serial.c 1.0.14 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2018 Miran Grca. * * Redistribution and use in source and binary forms, with @@ -58,6 +58,7 @@ #include "../../device.h" #include "../../timer.h" #include "../ports/serial.h" +#include "../../plat.h" #include "mouse.h" @@ -596,7 +597,7 @@ ser_close(void *priv) /* Initialize the device for use by the user. */ static void * -ser_init(const device_t *info) +ser_init(const device_t *info, UNUSED(void *parent)) { static serial_ops_t ops = { ser_callback, /* mcr */ @@ -680,7 +681,7 @@ static const device_config_t ser_config[] = { "COM2", 1 }, { - "" + NULL } } }, @@ -696,12 +697,12 @@ static const device_config_t ser_config[] = { "Wheel", 4 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -715,7 +716,7 @@ static const device_config_t ltser_config[] = { "COM2", 1 }, { - "" + NULL } } }, @@ -728,12 +729,12 @@ static const device_config_t ltser_config[] = { "Three", 3 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -742,6 +743,7 @@ const device_t mouse_mssystems_device = { "Mouse Systems Serial Mouse", 0, MOUSE_MSYSTEMS, + NULL, ser_init, ser_close, NULL, ser_poll, NULL, NULL, NULL, ser_config @@ -751,6 +753,7 @@ const device_t mouse_msserial_device = { "Microsoft Serial Mouse", 0, MOUSE_MICROSOFT, + NULL, ser_init, ser_close, NULL, ser_poll, NULL, NULL, NULL, ser_config @@ -760,6 +763,7 @@ const device_t mouse_ltserial_device = { "Logitech Serial Mouse", 0, MOUSE_LOGITECH, + NULL, ser_init, ser_close, NULL, ser_poll, NULL, NULL, NULL, ltser_config @@ -770,6 +774,7 @@ const device_t mouse_mswhserial_device = { "Microsoft Serial Wheel Mouse", 0, MOUSE_MSWHEEL, + NULL, ser_init, ser_close, NULL, ser_poll, NULL, NULL, NULL, ser_config diff --git a/src/devices/misc/bugger.c b/src/devices/misc/bugger.c index 2dd4bd5..b6f0623 100644 --- a/src/devices/misc/bugger.c +++ b/src/devices/misc/bugger.c @@ -44,11 +44,11 @@ * configuration register (CTRL_SPCFG bit set) but have to * remember that stuff first... * - * Version: @(#)bugger.c 1.0.8 2018/09/29 + * Version: @(#)bugger.c 1.0.10 2019/04/08 * * Author: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -351,7 +351,7 @@ bug_read(uint16_t port, UNUSED(void *priv)) /* Initialize the ISA BusBugger emulator. */ static void * -bug_init(const device_t *info) +bug_init(const device_t *info, UNUSED(void *parent)) { bugger_t *dev; @@ -389,6 +389,7 @@ const device_t bugger_device = { "ISA/PCI Bus Bugger", DEVICE_ISA, 0, + NULL, bug_init, bug_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/misc/isamem.c b/src/devices/misc/isamem.c index bf87520..21608d3 100644 --- a/src/devices/misc/isamem.c +++ b/src/devices/misc/isamem.c @@ -32,11 +32,11 @@ * TODO: The EV159 is supposed to support 16b EMS transfers, but the * EMM.sys driver for it doesn't seem to want to do that.. * - * Version: @(#)isamem.c 1.0.6 2018/10/24 + * Version: @(#)isamem.c 1.0.8 2019/04/11 * * Author: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -75,7 +75,6 @@ #include #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../device.h" @@ -366,7 +365,7 @@ DEBUG("EMS: write(%02x) to register 1 !\n"); /* Initialize the device for use. */ static void * -isamem_init(const device_t *info) +isamem_init(const device_t *info, UNUSED(void *parent)) { memdev_t *dev; uint32_t k, t; @@ -648,239 +647,239 @@ isamem_close(void *priv) } -static const device_config_t ibmxt_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - { { 0 } }, - { { 0 } }, - { 0, 512, 16 } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 256, - { { 0 } }, - { { 0 } }, - { 0, 640-64, 64 } - }, - { - "", "", -1 - } +static const device_config_t ibmxt_config[] = { + { + "size", "Memory Size", CONFIG_SPINNER, "", 128, + { { 0 } }, + { { 0 } }, + { 0, 512, 16 } + }, + { + "start", "Start Address", CONFIG_SPINNER, "", 256, + { { 0 } }, + { { 0 } }, + { 0, 640-64, 64 } + }, + { + NULL + } }; static const device_t ibmxt_device = { "IBM PC/XT Memory Expansion", DEVICE_ISA, 0, + NULL, isamem_init, isamem_close, NULL, NULL, NULL, NULL, NULL, ibmxt_config }; -static const device_config_t ibmat_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 512, - { { 0 } }, - { { 0 } }, - { 0, 4096, 512 } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 512, - { { 0 } }, - { { 0 } }, - { 0, 16128, 128 } - }, - { - "", "", -1 - } +static const device_config_t ibmat_config[] = { + { + "size", "Memory Size", CONFIG_SPINNER, "", 512, + { { 0 } }, + { { 0 } }, + { 0, 4096, 512 } + }, + { + "start", "Start Address", CONFIG_SPINNER, "", 512, + { { 0 } }, + { { 0 } }, + { 0, 16128, 128 } + }, + { + NULL + } }; static const device_t ibmat_device = { "IBM PC/AT Memory Expansion", DEVICE_ISA, 1, + NULL, isamem_init, isamem_close, NULL, NULL, NULL, NULL, NULL, ibmat_config }; -static const device_config_t p5pak_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - { { 0 } }, - { { 0 } }, - { 0, 384, 64 } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 512, - { { 0 } }, - { { 0 } }, - { 64, 576, 64 } - }, - { - "", "", -1 - } +static const device_config_t p5pak_config[] = { + { + "size", "Memory Size", CONFIG_SPINNER, "", 128, + { { 0 } }, + { { 0 } }, + { 0, 384, 64 } + }, + { + "start", "Start Address", CONFIG_SPINNER, "", 512, + { { 0 } }, + { { 0 } }, + { 64, 576, 64 } + }, + { + NULL + } }; static const device_t p5pak_device = { "Paradise Systems 5-PAK", DEVICE_ISA, 2, + NULL, isamem_init, isamem_close, NULL, NULL, NULL, NULL, NULL, p5pak_config }; -static const device_config_t ems5150_config[] = -{ +static const device_config_t ems5150_config[] = { + { + "size", "Memory Size", CONFIG_SPINNER, "", 256, + { { 0 } }, + { { 0 } }, + { 0, 2048, 64 } + }, + { + "base", "Address", CONFIG_HEX16, "", 0, { - "size", "Memory Size", CONFIG_SPINNER, "", 256, - { { 0 } }, - { { 0 } }, - { 0, 2048, 64 } - }, - { - "base", "Address", CONFIG_HEX16, "", 0, { - { - "Disabled", 0 - }, - { - "Board 1", 0x0208 - }, - { - "Board 2", 0x020a - }, - { - "Board 3", 0x020c - }, - { - "Board 4", 0x020e - }, - { - "" - } + "Disabled", 0 }, + { + "Board 1", 0x0208 + }, + { + "Board 2", 0x020a + }, + { + "Board 3", 0x020c + }, + { + "Board 4", 0x020e + }, + { + NULL + } }, - { - "", "", -1 - } + }, + { + NULL + } }; static const device_t ems5150_device = { "Micro Mainframe EMS-5150(T)", DEVICE_ISA, 3, + NULL, isamem_init, isamem_close, NULL, NULL, NULL, NULL, NULL, ems5150_config }; -static const device_config_t ev159_config[] = -{ +static const device_config_t ev159_config[] = { + { + "size", "Memory Size", CONFIG_SPINNER, "", 512, + { { 0 } }, + { { 0 } }, + { 0, 3072, 512 } + }, + { + "start", "Start Address", CONFIG_SPINNER, "", 0, + { { 0 } }, + { { 0 } }, + { 0, 16128, 128 } + }, + { + "length", "Contiguous Size", CONFIG_SPINNER, "", 0, + { { 0 } }, + { { 0 } }, + { 0, 16384, 128 } + }, + { + "width", "I/O Width", CONFIG_SELECTION, "", 0, { - "size", "Memory Size", CONFIG_SPINNER, "", 512, - { { 0 } }, - { { 0 } }, - { 0, 3072, 512 } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 0, - { { 0 } }, - { { 0 } }, - { 0, 16128, 128 } - }, - { - "length", "Contiguous Size", CONFIG_SPINNER, "", 0, - { { 0 } }, - { { 0 } }, - { 0, 16384, 128 } - }, - { - "width", "I/O Width", CONFIG_SELECTION, "", 0, { - { - "8-bit", 0 - }, - { - "16-bit", 1 - }, - { - "" - } + "8-bit", 0 }, - }, - { - "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, { - { - "Standard (150ns)", 0 - }, - { - "High-Speed (120ns)", 1 - }, - { - "" - } + "16-bit", 1 + }, + { + NULL } }, + }, + { + "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, { - "ems", "EMS mode", CONFIG_SELECTION, "", 0, { - { - "Disabled", 0 - }, - { - "Enabled", 1 - }, - { - "" - } + "Standard (150ns)", 0 }, - }, - { - "base", "Address", CONFIG_HEX16, "", 0x0258, { - { - "208H", 0x0208 - }, - { - "218H", 0x0218 - }, - { - "258H", 0x0258 - }, - { - "268H", 0x0268 - }, - { - "2A8H", 0x02A8 - }, - { - "2B8H", 0x02B8 - }, - { - "2E8H", 0x02E8 - }, - { - "" - } + "High-Speed (120ns)", 1 }, - }, - { - "", "", -1 + { + NULL + } } + }, + { + "ems", "EMS mode", CONFIG_SELECTION, "", 0, + { + { + "Disabled", 0 + }, + { + "Enabled", 1 + }, + { + NULL + } + }, + }, + { + "base", "Address", CONFIG_HEX16, "", 0x0258, + { + { + "208H", 0x0208 + }, + { + "218H", 0x0218 + }, + { + "258H", 0x0258 + }, + { + "268H", 0x0268 + }, + { + "2A8H", 0x02A8 + }, + { + "2B8H", 0x02B8 + }, + { + "2E8H", 0x02E8 + }, + { + NULL + } + }, + }, + { + NULL + } }; static const device_t ev159_device = { "Everex EV-159 RAM 3000 Deluxe", DEVICE_ISA, 10, + NULL, isamem_init, isamem_close, NULL, NULL, NULL, NULL, NULL, ev159_config @@ -888,100 +887,100 @@ static const device_t ev159_device = { #ifdef USE_ISAMEM_RAMPAGE -static const device_config_t rampage_config[] = -{ +static const device_config_t rampage_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x0258, { - "base", "Address", CONFIG_HEX16, "", 0x0258, { - { - "208H", 0x0208 - }, - { - "218H", 0x0218 - }, - { - "258H", 0x0258 - }, - { - "268H", 0x0268 - }, - { - "2A8H", 0x02A8 - }, - { - "2B8H", 0x02B8 - }, - { - "2E8H", 0x02E8 - }, - { - "" - } + "208H", 0x0208 }, - }, - { - "frame", "Frame Address", CONFIG_HEX20, "", 0, { - { - "Disabled", 0x00000 - }, - { - "C000H", 0xC0000 - }, - { - "D000H", 0xD0000 - }, - { - "E000H", 0xE0000 - }, - { - "" - } + "218H", 0x0218 }, - }, - { - "width", "I/O Width", CONFIG_SELECTION, "", 8, { - { - "8-bit", 8 - }, - { - "16-bit", 16 - }, - { - "" - } + "258H", 0x0258 }, - }, - { - "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, { - { - "Standard", 0 - }, - { - "High-Speed", 1 - }, - { - "" - } + "268H", 0x0268 + }, + { + "2A8H", 0x02A8 + }, + { + "2B8H", 0x02B8 + }, + { + "2E8H", 0x02E8 + }, + { + NULL } - }, - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - { { 0 } }, - { { 0 } }, - { 0, 8192, 128 } - }, - { - "", "", -1 } + }, + { + "frame", "Frame Address", CONFIG_HEX20, "", 0, + { + { + "Disabled", 0x00000 + }, + { + "C000H", 0xC0000 + }, + { + "D000H", 0xD0000 + }, + { + "E000H", 0xE0000 + }, + { + NULL + } + } + }, + { + "width", "I/O Width", CONFIG_SELECTION, "", 8, + { + { + "8-bit", 8 + }, + { + "16-bit", 16 + }, + { + NULL + } + } + }, + { + "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, + { + { + "Standard", 0 + }, + { + "High-Speed", 1 + }, + { + NULL + } + } + }, + { + "size", "Memory Size", CONFIG_SPINNER, "", 128, + { { 0 } }, + { { 0 } }, + { 0, 8192, 128 } + }, + { + NULL + } }; static const device_t isamem_rampage_device = { "AST RAMpage/XT", DEVICE_ISA, 11, + NULL, isamem_init, isamem_close, NULL, NULL, NULL, NULL, NULL, rampage_config diff --git a/src/devices/misc/isartc.c b/src/devices/misc/isartc.c index a7f0cec..f9e5410 100644 --- a/src/devices/misc/isartc.c +++ b/src/devices/misc/isartc.c @@ -28,11 +28,11 @@ * NOTE: The IRQ functionalities have been implemented, but not yet * tested, as I need to write test software for them first :) * - * Version: @(#)isartc.c 1.0.5 2018/09/22 + * Version: @(#)isartc.c 1.0.7 2019/04/11 * * Author: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -72,7 +72,6 @@ #include #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../device.h" #include "../../nvr.h" @@ -459,7 +458,7 @@ DEBUG("RTC: write test=%02x\n", val); /* Initialize the device for use. */ static void * -isartc_init(const device_t *info) +isartc_init(const device_t *info, UNUSED(void *parent)) { rtcdev_t *dev; @@ -554,49 +553,50 @@ isartc_close(void *priv) static const device_config_t ev170_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x02C0, { - "base", "Address", CONFIG_HEX16, "", 0x02C0, { - { - "240H", 0x0240 - }, - { - "2C0H", 0x02c0 - }, - { - "" - } + "240H", 0x0240 }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", -1, { - { - "Disabled", -1 - }, - { - "IRQ2", 2 - }, - { - "IRQ5", 5 - }, - { - "IRQ7", 7 - }, - { - "" - } + "2C0H", 0x02c0 }, - }, - { - "", "", -1 + { + NULL + } } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", -1, + { + { + "Disabled", -1 + }, + { + "IRQ2", 2 + }, + { + "IRQ5", 5 + }, + { + "IRQ7", 7 + }, + { + NULL + } + } + }, + { + NULL + } }; static const device_t ev170_device = { "Everex EV-170 Magic I/O", DEVICE_ISA, 0, + NULL, isartc_init, isartc_close, NULL, NULL, NULL, NULL, NULL, ev170_config @@ -604,29 +604,30 @@ static const device_t ev170_device = { static const device_config_t pii147_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x0240, { - "base", "Address", CONFIG_HEX16, "", 0x0240, { - { - "Clock 1", 0x0240 - }, - { - "Clock 2", 0x0340 - }, - { - "" - } + "Clock 1", 0x0240 }, - }, - { - "", "", -1 + { + "Clock 2", 0x0340 + }, + { + NULL + } } + }, + { + NULL + } }; static const device_t pii147_device = { "DTK PII-147 Hexa I/O Plus", DEVICE_ISA, 1, + NULL, isartc_init, isartc_close, NULL, NULL, NULL, NULL, NULL, pii147_config @@ -634,35 +635,36 @@ static const device_t pii147_device = { static const device_config_t p5pak_config[] = { + { + "irq", "IRQ", CONFIG_SELECTION, "", -1, { - "irq", "IRQ", CONFIG_SELECTION, "", -1, { - { - "Disabled", -1 - }, - { - "IRQ2", 2 - }, - { - "IRQ3", 3 - }, - { - "IRQ5", 5 - }, - { - "" - } + "Disabled", -1 }, - }, - { - "", "", -1 + { + "IRQ2", 2 + }, + { + "IRQ3", 3 + }, + { + "IRQ5", 5 + }, + { + NULL + } } + }, + { + NULL + } }; static const device_t p5pak_device = { "Paradise Systems 5-PAK", DEVICE_ISA, 2, + NULL, isartc_init, isartc_close, NULL, NULL, NULL, NULL, NULL, p5pak_config diff --git a/src/devices/network/net_3c503.c b/src/devices/network/net_3c503.c index f621dae..4efa34a 100644 --- a/src/devices/network/net_3c503.c +++ b/src/devices/network/net_3c503.c @@ -8,7 +8,7 @@ * Implementation of the following network controllers: * - 3Com Etherlink II 3c503 (ISA 8-bit). * - * Version: @(#)net_3c503.c 1.0.4 2018/10/24 + * Version: @(#)net_3c503.c 1.0.6 2019/04/11 * * Based on @(#)3c503.cpp Carl (MAME) * @@ -17,7 +17,6 @@ * Fred N. van Kempen, * Carl, * - * Copyright 2018 TheCollector1995. * Copyright 2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. * Portions Copyright (C) 2018 MAME Project @@ -1448,7 +1447,7 @@ tc503_rx(void *priv, uint8_t *buf, int io_len) static void * -tc503_init(const device_t *info) +tc503_init(const device_t *info, UNUSED(void *parent)) { uint32_t mac; tc503_t *dev; @@ -1534,35 +1533,33 @@ static const device_config_t tc503_config[] = { "base", "Address", CONFIG_HEX16, "", 0x300, { { - "0x250", 0x250 + "250H", 0x250 }, { - "0x280", 0x280 + "280H", 0x280 }, { - "0x2a0", 0x2a0 + "2A0H", 0x2a0 }, { - "0x2e0", 0x2e0 + "2E0H", 0x2e0 }, { - "0x300", 0x300 + "300H", 0x300 }, { - "0x310", 0x310 + "310H", 0x310 }, { - "0x330", 0x330 + "330H", 0x330 }, { - "0x350", 0x350 + "350H", 0x350 }, { - "", 0 + NULL } - }, - { { NULL, { NULL } } }, - { 0, 0, 0 } + } }, { "irq", "IRQ", CONFIG_SELECTION, "", 3, @@ -1580,11 +1577,9 @@ static const device_config_t tc503_config[] = { "IRQ 5", 5 }, { - "", 0 + NULL } - }, - { { NULL, { NULL } } }, - { 0, 0, 0 } + } }, { "dma", "DMA", CONFIG_SELECTION, "", 3, @@ -1599,53 +1594,40 @@ static const device_config_t tc503_config[] = { "DMA 3", 3 }, { - "", 0 + NULL } - }, - { { NULL, { NULL } } }, - { 0, 0, 0 } + } }, { "mac", "MAC Address", CONFIG_MAC, "", -1, { { - "", 0 + NULL } - }, - { { NULL, { NULL } } }, - { 0, 0, 0 } + } }, { "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xCC000, { { - "DC00", 0xDC000 + "DC00H", 0xDC000 }, { - "D800", 0xD8000 + "D800H", 0xD8000 }, { - "C800", 0xC8000 + "C800H", 0xC8000 }, { - "CC00", 0xCC000 + "CC00H", 0xCC000 }, { - "", 0 + NULL } - }, - { { NULL, { NULL } } }, - { 0, 0, 0 } + } }, { - "", "", -1, "", -1, - { - { - "", 0 - } - }, - { { NULL, { NULL } } }, - { 0, 0, 0 } + NULL, } }; @@ -1654,6 +1636,7 @@ const device_t tc503_device = { "3Com EtherLink II", DEVICE_ISA, 0, + NULL, tc503_init, tc503_close, NULL, NULL, NULL, NULL, NULL, tc503_config diff --git a/src/devices/network/net_ne2000.c b/src/devices/network/net_ne2000.c index 0696aa8..929fcf2 100644 --- a/src/devices/network/net_ne2000.c +++ b/src/devices/network/net_ne2000.c @@ -16,7 +16,7 @@ * * FIXME: move statbar calls to upper layer * - * Version: @(#)net_ne2000.c 1.0.14 2018/10/24 + * Version: @(#)net_ne2000.c 1.0.16 2019/04/11 * * Based on @(#)ne2k.cc v1.56.2.1 2004/02/02 22:37:22 cbothamy * @@ -2379,7 +2379,7 @@ nic_mca_write(int port, uint8_t val, void *priv) static void * -nic_init(const device_t *info) +nic_init(const device_t *info, UNUSED(void *parent)) { char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD"; uint32_t mac; @@ -2678,154 +2678,154 @@ nic_close(void *priv) static const device_config_t ne1000_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x300, { - "base", "Address", CONFIG_HEX16, "", 0x300, { - { - "0x280", 0x280 - }, - { - "0x300", 0x300 - }, - { - "0x320", 0x320 - }, - { - "0x340", 0x340 - }, - { - "0x360", 0x360 - }, - { - "0x380", 0x380 - }, - { - "" - } + "280H", 0x280 }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } + "300H", 0x300 }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 + { + "320H", 0x320 + }, + { + "340H", 0x340 + }, + { + "360H", 0x360 + }, + { + "380H", 0x380 + }, + { + NULL + } } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 3, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + NULL + } + } + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + NULL + } }; static const device_config_t ne2000_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x300, { - "base", "Address", CONFIG_HEX16, "", 0x300, { - { - "0x280", 0x280 - }, - { - "0x300", 0x300 - }, - { - "0x320", 0x320 - }, - { - "0x340", 0x340 - }, - { - "0x360", 0x360 - }, - { - "0x380", 0x380 - }, - { - "" - } + "280H", 0x280 }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 10, { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "" - } + "300H", 0x300 }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "bios_addr", "BIOS address", CONFIG_HEX20, "", 0, { - { - "Disabled", 0x00000 - }, - { - "D000", 0xD0000 - }, - { - "D800", 0xD8000 - }, - { - "C800", 0xC8000 - }, - { - "" - } + "320H", 0x320 }, - }, - { - "", "", -1 + { + "340H", 0x340 + }, + { + "360H", 0x360 + }, + { + "380H", 0x380 + }, + { + NULL + } } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 10, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + NULL + } + } + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + "bios_addr", "BIOS address", CONFIG_HEX20, "", 0, + { + { + "Disabled", 0x00000 + }, + { + "D000H", 0xD0000 + }, + { + "D800H", 0xD8000 + }, + { + "C800H", 0xC8000 + }, + { + NULL + } + } + }, + { + NULL + } }; static const device_config_t ne2_mca_config[] = { - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + NULL + } }; static const rsl_t ne2_mca_rsl = { { 0x1000, 0x2020, 0x8020, 0xa0a0, 0xb0b0, @@ -2839,24 +2839,24 @@ static const rsl_t ne2_enext_mca_rsl = { }; static const device_config_t rtl8019as_config[] = { - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + NULL + } }; static const device_config_t rtl8029as_config[] = { - { - "bios", "Enable BIOS", CONFIG_BINARY, "", 0 - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } + { + "bios", "Enable BIOS", CONFIG_BINARY, "", 0 + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + NULL + } }; @@ -2864,6 +2864,7 @@ const device_t ne1000_device = { "Novell NE1000", DEVICE_ISA, NE2K_NE1000, + NULL, nic_init, nic_close, NULL, NULL, NULL, NULL, NULL, ne1000_config @@ -2873,6 +2874,7 @@ const device_t ne2000_device = { "Novell NE2000", DEVICE_ISA | DEVICE_AT, NE2K_NE2000, + NULL, nic_init, nic_close, NULL, NULL, NULL, NULL, NULL, ne2000_config @@ -2882,6 +2884,7 @@ const device_t ne2_mca_device = { "Novell NE/2", DEVICE_MCA, NE2K_NE2_MCA, + NULL, nic_init, nic_close, NULL, NULL, NULL, NULL, (void *)&ne2_mca_rsl, @@ -2892,6 +2895,7 @@ const device_t ne2_enext_mca_device = { "NetWorth Ethernet/MC", DEVICE_MCA, NE2K_NE2_ENEXT_MCA, + NULL, nic_init, nic_close, NULL, NULL, NULL, NULL, (void *)&ne2_enext_mca_rsl, @@ -2902,6 +2906,7 @@ const device_t rtl8019as_device = { "Realtek RTL8019AS", DEVICE_ISA | DEVICE_AT, NE2K_RTL8019AS, + NULL, nic_init, nic_close, NULL, NULL, NULL, NULL, NULL, rtl8019as_config @@ -2911,6 +2916,7 @@ const device_t rtl8029as_device = { "Realtek RTL8029AS", DEVICE_PCI, NE2K_RTL8029AS, + NULL, nic_init, nic_close, NULL, NULL, NULL, NULL, NULL, rtl8029as_config diff --git a/src/devices/network/net_wd80x3.c b/src/devices/network/net_wd80x3.c index d40cded..49a73e0 100644 --- a/src/devices/network/net_wd80x3.c +++ b/src/devices/network/net_wd80x3.c @@ -11,13 +11,13 @@ * - SMC/WD 8013EBT (ISA 16-bit); * - SMC/WD 8013EP/A (MCA). * - * Version: @(#)net_wd80x3.c 1.0.4 2018/10/24 + * Version: @(#)net_wd80x3.c 1.0.6 2019/04/11 * * Authors: Fred N. van Kempen, * TheCollector1995, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -1367,7 +1367,7 @@ wd_mca_write(int port, uint8_t val, void *priv) static void * -wd_init(const device_t *info) +wd_init(const device_t *info, UNUSED(void *parent)) { uint32_t mac; nic_t *dev; @@ -1483,171 +1483,171 @@ wd_close(void *priv) static const device_config_t wd8003_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x300, { - "base", "Address", CONFIG_HEX16, "", 0x300, { - { - "0x240", 0x240 - }, - { - "0x280", 0x280 - }, - { - "0x300", 0x300 - }, - { - "0x380", 0x380 - }, - { - "" - } + "240H", 0x240 }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } + "280H", 0x280 }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, { - { - "C800", 0xC8000 - }, - { - "CC00", 0xCC000 - }, - { - "D000", 0xD0000 - }, - { - "D400", 0xD4000 - }, - { - "D800", 0xD8000 - }, - { - "DC00", 0xDC000 - }, - { - "" - } + "300H", 0x300 }, - }, - { - "", "", -1 + { + "380H", 0x380 + }, + { + NULL + } } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 3, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + NULL + } + } + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, + { + { + "C800H", 0xc8000 + }, + { + "CC00H", 0xcc000 + }, + { + "D000H", 0xd0000 + }, + { + "D400H", 0xd4000 + }, + { + "D800H", 0xd8000 + }, + { + "DC00H", 0xdc000 + }, + { + NULL + } + } + }, + { + NULL + } }; static const device_config_t wd8013_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x300, { - "base", "Address", CONFIG_HEX16, "", 0x300, { - { - "0x240", 0x240 - }, - { - "0x280", 0x280 - }, - { - "0x300", 0x300 - }, - { - "0x380", 0x380 - }, - { - "" - } + "240H", 0x240 }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 15", 15 - }, - { - "" - } + "280H", 0x280 }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, { - { - "C800", 0xC8000 - }, - { - "CC00", 0xCC000 - }, - { - "D000", 0xD0000 - }, - { - "D400", 0xD4000 - }, - { - "D800", 0xD8000 - }, - { - "DC00", 0xDC000 - }, - { - "" - } + "300H", 0x300 }, - }, - { - "", "", -1 + { + "380H", 0x380 + }, + { + NULL + } } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 3, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 15", 15 + }, + { + NULL + } + } + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, + { + { + "C800H", 0xc8000 + }, + { + "CC00H", 0xcc000 + }, + { + "D000H", 0xd0000 + }, + { + "D400H", 0xd4000 + }, + { + "D800H", 0xd8000 + }, + { + "DC00H", 0xdc000 + }, + { + NULL + } + } + }, + { + NULL + } }; static const device_config_t mca_config[] = { - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + NULL + } }; @@ -1655,6 +1655,7 @@ const device_t wd8003e_device = { "Western Digital WD8003E", DEVICE_ISA, WD8003E, + NULL, wd_init, wd_close, NULL, NULL, NULL, NULL, NULL, wd8003_config @@ -1664,6 +1665,7 @@ const device_t wd8013ebt_device = { "Western Digital WD8013EBT", DEVICE_ISA, WD8013EBT, + NULL, wd_init, wd_close, NULL, NULL, NULL, NULL, NULL, wd8013_config @@ -1673,6 +1675,7 @@ const device_t wd8013epa_device = { "Western Digital WD8013EP/A", DEVICE_MCA, WD8013EPA, + NULL, wd_init, wd_close, NULL, NULL, NULL, NULL, NULL, mca_config diff --git a/src/devices/ports/game.c b/src/devices/ports/game.c index a29137d..b347dee 100644 --- a/src/devices/ports/game.c +++ b/src/devices/ports/game.c @@ -8,12 +8,12 @@ * * Implementation of a generic Game Port. * - * Version: @(#)game.c 1.0.18 2018/10/20 + * Version: @(#)game.c 1.0.20 2019/04/19 * * Authors: Fred N. van Kempen, * Sarah Walker, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -43,11 +43,12 @@ #define HAVE_STDARG_H #define dbglog game_log #include "../../emu.h" -#include "../../machines/machine.h" #include "../../cpu/cpu.h" #include "../../io.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" +#include "../input/game/joystick.h" #include "game.h" #include "game_dev.h" @@ -167,8 +168,24 @@ game_over(void *priv) } +static void +game_close(void *priv) +{ + game_t *dev = (game_t *)priv; + + if (dev == NULL) return; + + if (dev->joystick != NULL) + dev->joystick->close(dev->joystick_priv); + + game_global = NULL; + + free(dev); +} + + static void * -game_init(const device_t *info) +game_init(const device_t *info, UNUSED(void *parent)) { game_t *dev; int i; @@ -209,26 +226,9 @@ game_init(const device_t *info) } -static void -game_close(void *priv) -{ - game_t *dev = (game_t *)priv; - - if (dev == NULL) return; - - if (dev->joystick != NULL) - dev->joystick->close(dev->joystick_priv); - - game_global = NULL; - - free(dev); -} - - const device_t game_device = { "Standard Game Port", - 0, - 0, + 0, 0, NULL, game_init, game_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -236,8 +236,7 @@ const device_t game_device = { const device_t game_201_device = { "Custom Game Port (201H)", - 0, - 1, + 0, 1, NULL, game_init, game_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -245,12 +244,18 @@ const device_t game_201_device = { void -game_update_joystick_type(void) +game_reset(void) { game_t *dev = game_global; - if (dev != NULL) { + if (dev == NULL) return; + + if (dev->joystick != NULL) { dev->joystick->close(dev->joystick_priv); + dev->joystick = NULL; + } + + if (joystick_type != JOYSTICK_NONE) { dev->joystick = gamedev_get_device(joystick_type); dev->joystick_priv = dev->joystick->init(); } diff --git a/src/devices/ports/game.h b/src/devices/ports/game.h index fcbc216..a27e8d5 100644 --- a/src/devices/ports/game.h +++ b/src/devices/ports/game.h @@ -8,12 +8,12 @@ * * Definitions for the generic game port handlers. * - * Version: @(#)game.h 1.0.7 2018/09/19 + * Version: @(#)game.h 1.0.8 2019/04/19 * * Authors: Fred N. van Kempen, * Sarah Walker, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2008-2017 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -48,7 +48,7 @@ extern const device_t game_201_device; #endif extern void game_log(int level, const char *fmt, ...); -extern void game_update_joystick_type(void); +extern void game_reset(void); #ifdef __cplusplus } diff --git a/src/devices/ports/parallel.c b/src/devices/ports/parallel.c index 4edbe0f..99d5a00 100644 --- a/src/devices/ports/parallel.c +++ b/src/devices/ports/parallel.c @@ -8,7 +8,7 @@ * * Implementation of the "LPT" style parallel ports. * - * Version: @(#)parallel.c 1.0.15 2019/01/03 + * Version: @(#)parallel.c 1.0.17 2019/04/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,6 +46,7 @@ #include "../../emu.h" #include "../../io.h" #include "../../device.h" +#include "../../plat.h" #include "parallel.h" #include "parallel_dev.h" @@ -57,6 +58,10 @@ typedef struct { uint8_t dat, /* port data register */ ctrl; /* port control register */ + /* Port overloading stuff. */ + void *func_priv; + uint8_t (*func_read)(uint16_t, void *); + /* Device stuff. */ int dev_id; /* attached device */ const lpt_device_t *dev_ts; @@ -141,6 +146,9 @@ parallel_read(uint16_t port, void *priv) ret = dev->dev_ts->read_status(dev->dev_ps); else ret = 0x00; + + if (dev->func_read != NULL) + ret |= dev->func_read(port, dev->func_priv); break; case 2: /* control */ @@ -148,6 +156,9 @@ parallel_read(uint16_t port, void *priv) ret = dev->dev_ts->read_ctrl(dev->dev_ps); else ret = dev->ctrl; + + if (dev->func_read != NULL) + ret |= dev->func_read(port, dev->func_priv); break; } @@ -157,37 +168,6 @@ parallel_read(uint16_t port, void *priv) } -static void * -parallel_init(const device_t *info) -{ - parallel_t *dev; - - /* Get the correct device. */ - dev = &ports[info->local]; - - /* Clear port. */ - dev->dat = 0x00; - dev->ctrl = 0x04; - - /* Enable the I/O handler for this port. */ - io_sethandler(dev->base, 3, - parallel_read,NULL,NULL, - parallel_write,NULL,NULL, dev); - - /* If the user configured a device for this port, attach it. */ - if (parallel_device[info->local] != 0) { - dev->dev_ts = parallel_device_get_device(parallel_device[info->local]); - if (dev->dev_ts != NULL) - dev->dev_ps = dev->dev_ts->init(dev->dev_ts); - } - - INFO("PARALLEL: LPT%i (I/O=%04X, device=%i)\n", - info->local+1, dev->base, parallel_device[info->local]); - - return(dev); -} - - static void parallel_close(void *priv) { @@ -200,6 +180,10 @@ parallel_close(void *priv) dev->dev_ps = NULL; } + /* Remove overloads. */ + dev->func_priv = NULL; + dev->func_read = NULL; + /* Remove the I/O handler. */ io_removehandler(dev->base, 3, parallel_read,NULL,NULL, @@ -211,30 +195,57 @@ parallel_close(void *priv) } +static void * +parallel_init(const device_t *info, UNUSED(void *parent)) +{ + parallel_t *dev; + int port = info->local; + + /* Get the correct device. */ + dev = &ports[port]; + + /* Clear port. */ + dev->dat = 0x00; + dev->ctrl = 0x04; + + /* Enable the I/O handler for this port. */ + io_sethandler(dev->base, 4, + parallel_read,NULL,NULL, + parallel_write,NULL,NULL, dev); + + /* If the user configured a device for this port, attach it. */ + if (parallel_device[port] != 0) { + dev->dev_ts = parallel_device_get_device(parallel_device[port]); + if (dev->dev_ts != NULL) + dev->dev_ps = dev->dev_ts->init(dev->dev_ts); + } + + INFO("PARALLEL: %s (I/O=%04X, device=%i)\n", + info->name, dev->base, parallel_device[port]); + + return(dev); +} + + const device_t parallel_1_device = { "LPT1", - 0, - 0, + 0, 0, NULL, parallel_init, parallel_close, NULL, NULL, NULL, NULL, NULL, NULL }; - const device_t parallel_2_device = { "LPT2", - 0, - 1, + 0, 1, NULL, parallel_init, parallel_close, NULL, NULL, NULL, NULL, NULL, NULL }; - const device_t parallel_3_device = { "LPT3", - 0, - 2, + 0, 2, NULL, parallel_init, parallel_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -273,3 +284,13 @@ parallel_setup(int id, uint16_t port) dev->base = port; } + + +void +parallel_set_func(void *arg, uint8_t (*rfunc)(uint16_t, void *), void *priv) +{ + parallel_t *dev = (parallel_t *)arg; + + dev->func_priv = priv; + dev->func_read = rfunc; +} diff --git a/src/devices/ports/parallel.h b/src/devices/ports/parallel.h index 74e46cd..45c21a1 100644 --- a/src/devices/ports/parallel.h +++ b/src/devices/ports/parallel.h @@ -8,13 +8,13 @@ * * Definitions for the "LPT" parallel port handlerss. * - * Version: @(#)parallel.h 1.0.5 2018/09/19 + * Version: @(#)parallel.h 1.0.6 2019/04/14 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -58,5 +58,8 @@ extern void parallel_log(int level, const char *fmt, ...); extern void parallel_reset(void); extern void parallel_setup(int id, uint16_t port); +extern void parallel_set_func(void *arg, + uint8_t (*rfunc)(uint16_t, void *), void *priv); + #endif /*EMU_PARALLEL_H*/ diff --git a/src/devices/ports/serial.c b/src/devices/ports/serial.c index af9d2fe..d77fc35 100644 --- a/src/devices/ports/serial.c +++ b/src/devices/ports/serial.c @@ -32,11 +32,11 @@ * The lower half of the driver can interface to the host system * serial ports, or other channels, for real-world access. * - * Version: @(#)serial.c 1.0.12 2018/11/16 + * Version: @(#)serial.c 1.0.14 2019/04/14 * * Author: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -82,7 +82,8 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" -#include "../../devices/system/pic.h" +#include "../system/pic.h" +#include "../../plat.h" #include "serial.h" @@ -260,7 +261,10 @@ update_ints(serial_t *dev) DEBUG("Serial%d: intr, IIR=%02X, type=%d, mcr=%02X\n", dev->port, dev->iir, dev->type, dev->mcr); - if (stat && ((dev->mcr & MCR_OUT2) || dev->is_pcjr)) { + /* Are hardware interrupts enabled? */ + if (!(dev->mcr & MCR_OUT2) && !dev->is_pcjr) return; + + if (stat) { /* Raise an interrupt. */ if (dev->type < UART_TYPE_16450) { /* Edge-triggered. */ @@ -363,7 +367,6 @@ reset_port(serial_t *dev) } -/* Fake interrupt generator, needed for Serial Mouse. */ static void read_timer(void *priv) { @@ -380,7 +383,7 @@ read_timer(void *priv) #ifdef USE_HOST_SERIAL -/* BHTTY READ COMPLETE handler. */ +/* Platform module has data, so read it! */ static void read_done(void *arg, int num) { @@ -389,14 +392,14 @@ read_done(void *arg, int num) /* We can do at least 'num' bytes.. */ while (num-- > 0) { /* Get a byte from them. */ - if (bhtty_read(dev->bh, &dev->hold, 1) < 0) break; + if (plat_serial_read(dev->bh, &dev->hold, 1) < 0) break; /* Stuff it into the FIFO and set intr. */ write_fifo(dev, &dev->hold, 1); } /* We have data waiting for us.. delay a little, and then read it. */ - timer_add(ser_timer, &dev->delay, &dev->delay, dev); +// timer_add(ser_timer, &dev->delay, &dev->delay, dev); } #endif @@ -405,13 +408,18 @@ static void ser_write(uint16_t addr, uint8_t val, void *priv) { serial_t *dev = (serial_t *)priv; - uint8_t wl, sb, pa, msr; - uint32_t baud, speed; +#if defined(_LOGGING) || defined(USE_HOST_SERIAL) + uint32_t speed; + uint8_t wl, sb, pa; +#endif + uint32_t baud; + uint8_t msr; + DEBUG("Serial%i: write(%i, %02x)\n", dev->port, (addr & 0x0007), val); switch (addr & 0x0007) { - case 0: /* DLAB, DATA */ + case 0: /* DATA,DLAB1 */ if (dev->lcr & LCR_DLAB) { /* DLAB set, set DLAB low byte. */ dev->dlab1 = val; @@ -424,8 +432,8 @@ ser_write(uint16_t addr, uint8_t val, void *priv) #ifdef USE_HOST_SERIAL if (dev->bh != NULL) { /* We are linked, so send to BH layer. */ - bhtty_write((BHTTY *)dev->bh, dev->thr); - } + plat_serial_write(dev->bh, dev->thr); + } else #endif if (dev->ops && dev->ops->write) @@ -445,7 +453,7 @@ ser_write(uint16_t addr, uint8_t val, void *priv) } break; - case 1: /* DLAB, IER */ + case 1: /* IER,DLAB2 */ if (dev->lcr & LCR_DLAB) { /* DLAB set, set DLAB high byte. */ dev->dlab2 = val; @@ -458,14 +466,10 @@ ser_write(uint16_t addr, uint8_t val, void *priv) break; case 2: /* FCR */ -#if 0 if (dev->type >= UART_TYPE_16550) { -DEBUG("Serial%i: tried to enable FIFO (%02x), type %d!\n", dev->port, val, dev->type); +pclog(0,"Serial%i: tried to enable FIFO (%02x), type %d!\n", dev->port, val, dev->type); dev->fcr = val; } -#else - dev->fcr = val; -#endif break; case 3: /* LCR */ @@ -473,12 +477,14 @@ DEBUG("Serial%i: tried to enable FIFO (%02x), type %d!\n", dev->port, val, dev-> /* We dropped DLAB, so handle baudrate. */ baud = ((dev->dlab2 << 8) | dev->dlab1); if (baud > 0) { +#if defined(_LOGGING) || defined(USE_HOST_SERIAL) speed = 115200UL / baud; +#endif DEBUG("Serial%i: divisor %u, baudrate %i\n", dev->port, baud, speed); #ifdef USE_HOST_SERIAL if (dev->bh != NULL) - bhtty_speed((BHTTY *)dev->bh, speed); + plat_serial_speed(dev->bh, speed); #endif } else { DEBUG("Serial%i: divisor %u invalid!\n", @@ -486,25 +492,25 @@ DEBUG("Serial%i: tried to enable FIFO (%02x), type %d!\n", dev->port, val, dev-> } } +#if defined(_LOGGING) || defined(USE_HOST_SERIAL) wl = (val & LCR_WLS) + 5; /* databits */ sb = (val & LCR_SBS) ? 2 : 1; /* stopbits */ pa = (val & (LCR_PE|LCR_EP|LCR_PS)) >> 3; +#endif DEBUG("Serial%i: WL=%i SB=%i PA=%i\n", dev->port, wl, sb, pa); #ifdef USE_HOST_SERIAL if (dev->bh != NULL) - bhtty_params((BHTTY *)dev->bh, wl, pa, sb); + plat_serial_params(dev->bh, wl, pa, sb); #endif dev->lcr = val; break; - case 4: /*MCR*/ -#ifdef USE_HOST_SERIAL + case 4: /* MCR */ if (dev->bh == NULL) { /* Not linked, force LOOPBACK mode. */ val |= MCR_LMS; } -#endif if ((val & MCR_RTS) && !(dev->mcr & MCR_RTS)) { /* @@ -523,7 +529,7 @@ DEBUG("Serial%i: tried to enable FIFO (%02x), type %d!\n", dev->port, val, dev-> #ifdef USE_HOST_SERIAL if (dev->bh != NULL) { /* Linked, start host port. */ - (void)bhtty_active(dev->bh, 1); + (void)plat_serial_active(dev->bh, 1); } else { #endif /* Not linked, start RX timer. */ @@ -561,7 +567,7 @@ DEBUG("Serial%i: tried to enable FIFO (%02x), type %d!\n", dev->port, val, dev-> } break; - case 5: /*LSR*/ + case 5: /* LSR */ if (val & LSR_MASK) dev->int_status |= SER_INT_LSR; if (val & LSR_DR) @@ -572,14 +578,14 @@ DEBUG("Serial%i: tried to enable FIFO (%02x), type %d!\n", dev->port, val, dev-> update_ints(dev); break; - case 6: /*MSR*/ + case 6: /* MSR */ dev->msr = val; if (dev->msr & MSR_MASK) dev->int_status |= SER_INT_MSR; update_ints(dev); break; - case 7: /*SCRATCH*/ + case 7: /* SCRATCH */ if (dev->type > UART_TYPE_8250) { dev->scratch = val; } @@ -686,7 +692,7 @@ ser_read(uint16_t addr, void *priv) static void * -ser_init(const device_t *info) +ser_init(const device_t *info, UNUSED(void *parent)) { serial_t *dev; @@ -733,27 +739,26 @@ ser_close(void *priv) const device_t serial_1_device = { - "COM1:", - 0, - 1, + "COM1", + 0, 1, NULL, ser_init, ser_close, NULL, NULL, NULL, NULL, NULL, NULL }; const device_t serial_2_device = { - "COM2:", - 0, - 2, + "COM2", + 0, 2, NULL, ser_init, ser_close, NULL, NULL, NULL, NULL, NULL, NULL, }; const device_t serial_1_pcjr_device = { - "COM1:", + "COM1 (PCjr)", 0, 1+128, + NULL, ser_init, ser_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -845,6 +850,52 @@ serial_attach(int port, serial_ops_t *ops, void *arg) } +#ifdef USE_HOST_SERIAL +/* Link a serial port to a host (serial) port. */ +int +serial_link(int port, const char *arg) +{ + serial_t *dev; + + /* No can do if port not enabled. */ + if (! serial_enabled[port]) return(-1); + + /* Grab the desired port block. */ + dev = &ports[port]; + + if (arg != NULL) { + /* Make sure we're not already linked. */ + if (dev->bh != NULL) { + ERRLOG("Serial%i already linked !\n", port); + return(-1); + } + + /* Request a port from the host system. */ + dev->bh = plat_serial_open(arg, 0); + if (dev->bh == NULL) { + ERRLOG("Serial%i unable to link to '%s' !\n", port, arg); + return(-1); + } + + /* Set up bottom-half I/O callback info. */ +#if 0 + bh->rd_done = read_done; + bh->rd_arg = dev; +#endif + } else { + /* If we are linked, unlink it. */ + if (dev->bh != NULL) { + plat_serial_close(dev->bh); + dev->bh = NULL; + } + + } + + return(0); +} +#endif + + /* API: clear the FIFO buffers of a serial port. */ void serial_clear(void *arg) diff --git a/src/devices/ports/serial.h b/src/devices/ports/serial.h index e6fc280..e1f4ccc 100644 --- a/src/devices/ports/serial.h +++ b/src/devices/ports/serial.h @@ -8,7 +8,7 @@ * * Definitions for the SERIAL card. * - * Version: @(#)serial.h 1.0.8 2018/11/15 + * Version: @(#)serial.h 1.0.9 2018/11/23 * * Author: Fred N. van Kempen, * @@ -60,7 +60,7 @@ /* Supported UART types. */ #define UART_TYPE_8250 0 /* standard NS8250 */ #define UART_TYPE_8250A 1 /* updated NS8250(A) */ -#define UART_TYPE_16450 2 /* 16450 */ +#define UART_TYPE_16450 2 /* 8250B / 16450 */ #define UART_TYPE_16550 3 /* 16550 (broken fifo) */ #define UART_TYPE_16550A 4 /* 16550A (working fifo) */ #define UART_TYPE_16670 5 /* 16670 (64b fifo) */ @@ -92,5 +92,15 @@ extern int serial_link(int port, const char *name); extern void serial_clear(void *arg); extern void serial_write(void *arg, uint8_t *ptr, uint8_t len); +/* Platform serial driver support. */ +extern void *plat_serial_open(const char *port, int tmo); +extern void plat_serial_close(void *); +extern int plat_serial_active(void *, int flg); +extern int plat_serial_params(void *, char dbit, char par, char sbit); +extern int plat_serial_flush(void *); +extern int plat_serial_speed(void *, long speed); +extern int plat_serial_write(void *, uint8_t val); +extern int plat_serial_read(void *, uint8_t *bufp, int max); + #endif /*EMU_SERIAL_H*/ diff --git a/src/devices/printer/prt_escp.c b/src/devices/printer/prt_escp.c index 186100a..f26871d 100644 --- a/src/devices/printer/prt_escp.c +++ b/src/devices/printer/prt_escp.c @@ -8,7 +8,7 @@ * * Implementation of the Generic ESC/P Dot-Matrix printer. * - * Version: @(#)prt_escp.c 1.0.7 2019/02/10 + * Version: @(#)prt_escp.c 1.0.8 2019/04/11 * * Authors: Michael Drüing, * Fred N. van Kempen, @@ -57,8 +57,6 @@ #include #include FT_FREETYPE_H #include "../../emu.h" -#include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../timer.h" #include "../../mem.h" #include "../../rom.h" diff --git a/src/devices/scsi/scsi_aha154x.c b/src/devices/scsi/scsi_aha154x.c index e1e52fb..9347f93 100644 --- a/src/devices/scsi/scsi_aha154x.c +++ b/src/devices/scsi/scsi_aha154x.c @@ -10,7 +10,7 @@ * made by Adaptec, Inc. These controllers were designed for * the ISA bus. * - * Version: @(#)scsi_aha154x.c 1.0.11 2018/10/16 + * Version: @(#)scsi_aha154x.c 1.0.13 2019/04/11 * * Based on original code from TheCollector1995 and Miran Grca. * @@ -18,7 +18,7 @@ * Miran Grca, * TheCollector1995, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -731,12 +731,13 @@ set_nvr(x54x_t *dev) /* General initialization routine for all boards. */ static void * -aha_init(const device_t *info) +aha_init(const device_t *info, UNUSED(void *parent)) { x54x_t *dev; /* Call common initializer. */ dev = (x54x_t *)x54x_init(info); + dev->bios_path = info->path; /* * Set up the (initial) I/O address, IRQ and DMA info. @@ -788,7 +789,6 @@ aha_init(const device_t *info) case AHA_154xC: strcpy(dev->name, "AHA-154xC"); - dev->bios_path = AHA1540C_BIOS_PATH; dev->nvr_path = L"aha1542c.nvr"; dev->fw_rev = "D001"; dev->rom_shram = 0x3f80; /* shadow RAM address base */ @@ -803,7 +803,6 @@ aha_init(const device_t *info) case AHA_154xCF: strcpy(dev->name, "AHA-154xCF"); - dev->bios_path = AHA1540CF_BIOS_PATH; dev->nvr_path = L"aha1542cf.nvr"; dev->fw_rev = "E001"; dev->rom_shram = 0x3f80; /* shadow RAM address base */ @@ -819,7 +818,6 @@ aha_init(const device_t *info) case AHA_154xCP: strcpy(dev->name, "AHA-154xCP"); - dev->bios_path = AHA1540CP_BIOS_PATH; dev->nvr_path = L"aha1540cp.nvr"; dev->fw_rev = "F001"; dev->rom_shram = 0x3f80; /* shadow RAM address base */ @@ -834,7 +832,6 @@ aha_init(const device_t *info) case AHA_1640: strcpy(dev->name, "AHA-1640"); - dev->bios_path = AHA1640_BIOS_PATH; dev->fw_rev = "BB01"; dev->lba_bios = 1; @@ -881,25 +878,25 @@ static const device_config_t aha_154xb_config[] = { "None", 0 }, { - "0x330", 0x330 + "330H", 0x330 }, { - "0x334", 0x334 + "334H", 0x334 }, { - "0x230", 0x230 + "230H", 0x230 }, { - "0x234", 0x234 + "234H", 0x234 }, { - "0x130", 0x130 + "130H", 0x130 }, { - "0x134", 0x134 + "134H", 0x134 }, { - "" + NULL } } }, @@ -925,7 +922,7 @@ static const device_config_t aha_154xb_config[] = { "IRQ 15", 15 }, { - "" + NULL } } }, @@ -942,7 +939,7 @@ static const device_config_t aha_154xb_config[] = { "DMA 7", 7 }, { - "" + NULL } } }, @@ -974,7 +971,7 @@ static const device_config_t aha_154xb_config[] = { "7", 7 }, { - "" + NULL } } }, @@ -994,12 +991,12 @@ static const device_config_t aha_154xb_config[] = { "D800H", 0xd8000 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -1012,25 +1009,25 @@ static const device_config_t aha_154x_config[] = { "None", 0 }, { - "0x330", 0x330 + "330H", 0x330 }, { - "0x334", 0x334 + "334H", 0x334 }, { - "0x230", 0x230 + "230H", 0x230 }, { - "0x234", 0x234 + "234H", 0x234 }, { - "0x130", 0x130 + "130H", 0x130 }, { - "0x134", 0x134 + "134H", 0x134 }, { - "" + NULL } } }, @@ -1056,7 +1053,7 @@ static const device_config_t aha_154x_config[] = { "IRQ 15", 15 }, { - "" + NULL } } }, @@ -1073,7 +1070,7 @@ static const device_config_t aha_154x_config[] = { "DMA 7", 7 }, { - "" + NULL } } }, @@ -1093,12 +1090,12 @@ static const device_config_t aha_154x_config[] = { "D800H", 0xd8000 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -1107,6 +1104,7 @@ const device_t aha1540b_device = { "Adaptec AHA-1540B", DEVICE_ISA | DEVICE_AT, AHA_154xB, + NULL, aha_init, x54x_close, NULL, NULL, NULL, NULL, NULL, aha_154xb_config @@ -1116,6 +1114,7 @@ const device_t aha1542c_device = { "Adaptec AHA-1542C", DEVICE_ISA | DEVICE_AT, AHA_154xC, + AHA1540C_BIOS_PATH, aha_init, x54x_close, NULL, NULL, NULL, NULL, NULL, aha_154x_config @@ -1125,6 +1124,17 @@ const device_t aha1542cf_device = { "Adaptec AHA-1542CF", DEVICE_ISA | DEVICE_AT, AHA_154xCF, + AHA1540CF_BIOS_PATH, + aha_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + aha_154x_config +}; + +const device_t aha1542cp_device = { + "Adaptec AHA-1542CP", + DEVICE_ISA | DEVICE_AT, + AHA_154xCP, + AHA1540CP_BIOS_PATH, aha_init, x54x_close, NULL, NULL, NULL, NULL, NULL, aha_154x_config @@ -1134,6 +1144,7 @@ const device_t aha1640_device = { "Adaptec AHA-1640", DEVICE_MCA, AHA_1640, + AHA1640_BIOS_PATH, aha_init, x54x_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/scsi/scsi_buslogic.c b/src/devices/scsi/scsi_buslogic.c index c792d26..3786f26 100644 --- a/src/devices/scsi/scsi_buslogic.c +++ b/src/devices/scsi/scsi_buslogic.c @@ -13,7 +13,7 @@ * 1 - BT-545S ISA; * 2 - BT-958D PCI * - * Version: @(#)scsi_buslogic.c 1.0.14 2019/02/10 + * Version: @(#)scsi_buslogic.c 1.0.16 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1611,10 +1611,10 @@ BuslogicDeviceReset(void *priv) static void * -buslogic_init(const device_t *info) +buslogic_init(const device_t *info, UNUSED(void *parent)) { x54x_t *dev; - wchar_t *bios_rom_name; + const wchar_t *bios_rom_name; uint16_t bios_rom_size; uint16_t bios_rom_mask; uint8_t has_autoscsi_rom; @@ -1629,10 +1629,10 @@ buslogic_init(const device_t *info) /* Call common initializer. */ dev = (x54x_t *)x54x_init(info); + bios_rom_name = info->path; dev->ven_data = mem_alloc(sizeof(buslogic_data_t)); memset(dev->ven_data, 0x00, sizeof(buslogic_data_t)); - bl = (buslogic_data_t *)dev->ven_data; dev->bus = info->flags; @@ -1684,7 +1684,6 @@ buslogic_init(const device_t *info) switch(bl->chip) { case CHIP_BUSLOGIC_ISA_542: strcpy(dev->name, "BT-542BH"); - bios_rom_name = BT542_BIOS_PATH; bios_rom_size = 0x4000; bios_rom_mask = 0x3fff; has_autoscsi_rom = 0; @@ -1697,7 +1696,6 @@ buslogic_init(const device_t *info) case CHIP_BUSLOGIC_ISA: default: strcpy(dev->name, "BT-545S"); - bios_rom_name = BT545_BIOS_PATH; bios_rom_size = 0x4000; bios_rom_mask = 0x3fff; has_autoscsi_rom = 1; @@ -1711,7 +1709,6 @@ buslogic_init(const device_t *info) case CHIP_BUSLOGIC_MCA: strcpy(dev->name, "BT-640A"); - bios_rom_name = BT640A_BIOS_PATH; bios_rom_size = 0x4000; bios_rom_mask = 0x3fff; has_autoscsi_rom = 0; @@ -1727,7 +1724,6 @@ buslogic_init(const device_t *info) case CHIP_BUSLOGIC_VLB: strcpy(dev->name, "BT-445S"); - bios_rom_name = BT445S_BIOS_PATH; bios_rom_size = 0x4000; bios_rom_mask = 0x3fff; has_autoscsi_rom = 1; @@ -1744,7 +1740,6 @@ buslogic_init(const device_t *info) case CHIP_BUSLOGIC_PCI: strcpy(dev->name, "BT-958D"); - bios_rom_name = BT958D_BIOS_PATH; bios_rom_size = 0x4000; bios_rom_mask = 0x3fff; has_autoscsi_rom = 1; @@ -1834,25 +1829,25 @@ static const device_config_t BT_ISA_Config[] = { "base", "Address", CONFIG_HEX16, "", 0x334, { { - "0x330", 0x330 + "330H", 0x330 }, { - "0x334", 0x334 + "334H", 0x334 }, { - "0x230", 0x230 + "230H", 0x230 }, { - "0x234", 0x234 + "234H", 0x234 }, { - "0x130", 0x130 + "130H", 0x130 }, { - "0x134", 0x134 + "134H", 0x134 }, { - "", 0 + NULL } } }, @@ -1878,7 +1873,7 @@ static const device_config_t BT_ISA_Config[] = { "IRQ 15", 15 }, { - "", 0 + NULL } } }, @@ -1895,7 +1890,7 @@ static const device_config_t BT_ISA_Config[] = { "DMA 7", 7 }, { - "", 0 + NULL } } }, @@ -1915,12 +1910,12 @@ static const device_config_t BT_ISA_Config[] = { "D800H", 0xd8000 }, { - "", 0 + NULL } } }, { - "", "", -1 + NULL } }; @@ -1930,7 +1925,7 @@ static const device_config_t BT958D_Config[] = { "bios", "Enable BIOS", CONFIG_BINARY, "", 0 }, { - "", "", -1 + NULL } }; @@ -1939,6 +1934,7 @@ const device_t buslogic_device = { "Buslogic BT-542BH ISA", DEVICE_ISA | DEVICE_AT, CHIP_BUSLOGIC_ISA_542, + BT542_BIOS_PATH, buslogic_init, x54x_close, NULL, NULL, NULL, NULL, NULL, BT_ISA_Config @@ -1948,6 +1944,7 @@ const device_t buslogic_545s_device = { "Buslogic BT-545S ISA", DEVICE_ISA | DEVICE_AT, CHIP_BUSLOGIC_ISA, + BT545_BIOS_PATH, buslogic_init, x54x_close, NULL, NULL, NULL, NULL, NULL, BT_ISA_Config @@ -1957,6 +1954,7 @@ const device_t buslogic_640a_device = { "Buslogic BT-640A MCA", DEVICE_MCA, CHIP_BUSLOGIC_MCA, + BT640A_BIOS_PATH, buslogic_init, x54x_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -1966,6 +1964,7 @@ const device_t buslogic_445s_device = { "Buslogic BT-445S ISA", DEVICE_VLB, CHIP_BUSLOGIC_VLB, + BT445S_BIOS_PATH, buslogic_init, x54x_close, NULL, NULL, NULL, NULL, NULL, BT_ISA_Config @@ -1975,6 +1974,7 @@ const device_t buslogic_pci_device = { "Buslogic BT-958D PCI", DEVICE_PCI, CHIP_BUSLOGIC_PCI, + BT958D_BIOS_PATH, buslogic_init, x54x_close, NULL, NULL, NULL, NULL, NULL, BT958D_Config diff --git a/src/devices/scsi/scsi_ncr5380.c b/src/devices/scsi/scsi_ncr5380.c index e8c6241..7e833ca 100644 --- a/src/devices/scsi/scsi_ncr5380.c +++ b/src/devices/scsi/scsi_ncr5380.c @@ -11,14 +11,14 @@ * * NOTE: This code now only supports targets at LUN=0 !! * - * Version: @(#)scsi_ncr5380.c 1.0.13 2018/10/20 + * Version: @(#)scsi_ncr5380.c 1.0.15 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * TheCollector1995, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -1283,7 +1283,7 @@ scsiat_out(uint16_t port, uint8_t val, void *priv) static void * -ncr_init(const device_t *info) +ncr_init(const device_t *info, UNUSED(void *parent)) { char temp[128]; ncr5380_t *ncr_dev; @@ -1296,7 +1296,7 @@ ncr_init(const device_t *info) switch(ncr_dev->type) { case 0: /* Longshine LCS6821N */ ncr_dev->rom_addr = 0xDC000; - rom_init(&ncr_dev->bios_rom, LCS6821N_ROM, + rom_init(&ncr_dev->bios_rom, info->path, ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -1310,7 +1310,7 @@ ncr_init(const device_t *info) case 1: /* Rancho RT1000B */ ncr_dev->rom_addr = 0xDC000; - rom_init(&ncr_dev->bios_rom, RT1000B_ROM, + rom_init(&ncr_dev->bios_rom, info->path, ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -1326,7 +1326,7 @@ ncr_init(const device_t *info) ncr_dev->rom_addr = 0xDC000; ncr_dev->base = device_get_config_hex16("base"); ncr_dev->irq = device_get_config_int("irq"); - rom_init(&ncr_dev->bios_rom, T130B_ROM, + rom_init(&ncr_dev->bios_rom, info->path, ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -1343,7 +1343,7 @@ ncr_init(const device_t *info) ncr_dev->base = device_get_config_hex16("base"); ncr_dev->irq = device_get_config_int("irq"); ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); - rom_init(&ncr_dev->bios_rom, SCSIAT_ROM, + rom_init(&ncr_dev->bios_rom, info->path, ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -1394,31 +1394,6 @@ ncr_close(void *priv) } -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)); -} - -static int -scsiat_available(void) -{ - return(rom_present(SCSIAT_ROM)); -} - - static const device_config_t t130b_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x0350, @@ -1436,7 +1411,7 @@ static const device_config_t t130b_config[] = { "350H", 0x0350 }, { - "" + NULL } } }, @@ -1453,12 +1428,12 @@ static const device_config_t t130b_config[] = { "IRQ 7", 7 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -1494,7 +1469,7 @@ static const device_config_t scsiat_config[] = { "370H", 0x0370 }, { - "" + NULL } } }, @@ -1526,7 +1501,7 @@ static const device_config_t scsiat_config[] = { "IRQ 15", 15 }, { - "" + NULL } } }, @@ -1549,12 +1524,12 @@ static const device_config_t scsiat_config[] = { "DC00H", 0xdc000 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -1563,9 +1538,9 @@ const device_t scsi_lcs6821n_device = { "Longshine LCS-6821N", DEVICE_ISA, 0, + LCS6821N_ROM, ncr_init, ncr_close, NULL, - lcs6821n_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; @@ -1573,9 +1548,9 @@ const device_t scsi_rt1000b_device = { "Ranco RT1000B", DEVICE_ISA, 1, + RT1000B_ROM, ncr_init, ncr_close, NULL, - rt1000b_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; @@ -1583,9 +1558,9 @@ const device_t scsi_t130b_device = { "Trantor T130B", DEVICE_ISA, 2, + T130B_ROM, ncr_init, ncr_close, NULL, - t130b_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, t130b_config }; @@ -1593,8 +1568,8 @@ const device_t scsi_scsiat_device = { "Sumo SCSI-AT", DEVICE_ISA, 3, + SCSIAT_ROM, ncr_init, ncr_close, NULL, - scsiat_available, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, scsiat_config }; diff --git a/src/devices/scsi/scsi_ncr53c810.c b/src/devices/scsi/scsi_ncr53c810.c index 4bb6a9b..f3ff84a 100644 --- a/src/devices/scsi/scsi_ncr53c810.c +++ b/src/devices/scsi/scsi_ncr53c810.c @@ -10,7 +10,7 @@ * NCR and later Symbios and LSI. This controller was designed * for the PCI bus. * - * Version: @(#)scsi_ncr53c810.c 1.0.12 2018/10/16 + * Version: @(#)scsi_ncr53c810.c 1.0.14 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -18,7 +18,7 @@ * Artyom Tarasenko (QEMU) * Paul Brook (QEMU) * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2009-2018 Artyom Tarasenko. * Copyright 2006-2018 Paul Brook. @@ -2251,7 +2251,7 @@ ncr53c810_pci_write(int func, int addr, uint8_t val, void *p) static void * -ncr53c810_init(const device_t *info) +ncr53c810_init(const device_t *info, UNUSED(void *parent)) { ncr53c810_t *dev; @@ -2279,14 +2279,14 @@ ncr53c810_init(const device_t *info) #if USE_PCI_BAR if (dev->has_bios) { dev->bios_mask = 0xffffc000; - rom_init(&dev->bios, NCR53C810_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios, info->path, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); ncr53c810_pci_bar[2].addr = 0xFFFFC000; mem_map_disable(&dev->bios.mapping); } else ncr53c810_pci_bar[2].addr = 0; #else if (dev->has_bios) - rom_init(&dev->bios, NCR53C810_ROM, + rom_init(&dev->bios, info->path, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); #endif @@ -2311,7 +2311,7 @@ static const device_config_t ncr53c810_pci_config[] = { "bios", "Enable BIOS", CONFIG_BINARY, "", 0 }, { - "", "", -1 + NULL } }; @@ -2319,6 +2319,7 @@ const device_t ncr53c810_pci_device = { "NCR 53c810 (SCSI)", DEVICE_PCI, 0, + NCR53C810_ROM, ncr53c810_init, ncr53c810_close, NULL, NULL, NULL, NULL, NULL, ncr53c810_pci_config diff --git a/src/devices/scsi/scsi_x54x.h b/src/devices/scsi/scsi_x54x.h index 0e3a6dc..a3030ce 100644 --- a/src/devices/scsi/scsi_x54x.h +++ b/src/devices/scsi/scsi_x54x.h @@ -8,13 +8,13 @@ * * Definitions for the common AHA/BL code. * - * Version: @(#)scsi_x54x.h 1.0.6 2018/10/21 + * Version: @(#)scsi_x54x.h 1.0.7 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * TheCollector1995, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -395,7 +395,7 @@ typedef struct { uint32_t Base; uint8_t pos_regs[8]; /* MCA */ - wchar_t *bios_path; /* path to BIOS image file */ + const 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 */ diff --git a/src/devices/sio/sio_detect.c b/src/devices/sio/sio_detect.c index c243a65..e9765aa 100644 --- a/src/devices/sio/sio_detect.c +++ b/src/devices/sio/sio_detect.c @@ -8,7 +8,7 @@ * * Super I/O chip detection code. * - * Version: @(#)sio_detect.c 1.0.4 2018/11/10 + * Version: @(#)sio_detect.c 1.0.6 2019/04/09 * * Author: Miran Grca, * @@ -42,6 +42,7 @@ #include "../../io.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" +#include "../../plat.h" #include "sio.h" @@ -85,7 +86,7 @@ detect_close(void *priv) static void * -detect_init(void) +detect_init(const device_t *info, UNUSED(void *parent)) { sio_detect_t *dev = (sio_detect_t *)mem_alloc(sizeof(sio_detect_t)); memset(dev, 0x00, sizeof(sio_detect_t)); @@ -115,8 +116,7 @@ detect_init(void) const device_t sio_detect_device = { "Super I/O Detection Helper", - 0, - 0, + 0, 0, NULL, detect_init, detect_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sio/sio_fdc37c669.c b/src/devices/sio/sio_fdc37c669.c index 341b38e..23fea30 100644 --- a/src/devices/sio/sio_fdc37c669.c +++ b/src/devices/sio/sio_fdc37c669.c @@ -8,10 +8,12 @@ * * Implementation of the SMC FDC37C669 Super I/O Chip. * - * Version: @(#)sio_fdc37c669.c 1.0.9 2018/11/11 + * Version: @(#)sio_fdc37c669.c 1.0.11 2019/04/09 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -47,6 +49,7 @@ #include "../floppy/fdc.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" +#include "../../plat.h" #include "sio.h" @@ -306,10 +309,10 @@ fdc37c669_close(void *priv) static void * -fdc37c669_init(const device_t *info) +fdc37c669_init(const device_t *info, UNUSED(void *parent)) { fdc37c669_t *dev = (fdc37c669_t *)mem_alloc(sizeof(fdc37c669_t)); - memset(dev, 0, sizeof(fdc37c669_t)); + memset(dev, 0x00, sizeof(fdc37c669_t)); dev->fdc = device_add(&fdc_at_smc_device); @@ -324,8 +327,7 @@ fdc37c669_init(const device_t *info) const device_t fdc37c669_device = { "SMC FDC37C669 Super I/O", - 0, - 0, + 0, 0, NULL, fdc37c669_init, fdc37c669_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sio/sio_fdc37c66x.c b/src/devices/sio/sio_fdc37c66x.c index aba18d1..7d80683 100644 --- a/src/devices/sio/sio_fdc37c66x.c +++ b/src/devices/sio/sio_fdc37c66x.c @@ -9,13 +9,13 @@ * Implementation of the SMC FDC37C663 and FDC37C665 Super * I/O Chips. * - * Version: @(#)sio_fdc37c66x.c 1.0.9 2018/11/11 + * Version: @(#)sio_fdc37c66x.c 1.0.11 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -52,6 +52,7 @@ #include "../floppy/fdc.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" +#include "../../plat.h" #include "sio.h" @@ -276,7 +277,7 @@ fdc37c66x_close(void *priv) static void * -fdc37c66x_init(const device_t *info) +fdc37c66x_init(const device_t *info, UNUSED(void *parent)) { fdc37c66x_t *dev = (fdc37c66x_t *)mem_alloc(sizeof(fdc37c66x_t)); memset(dev, 0x00, sizeof(fdc37c66x_t)); @@ -298,6 +299,7 @@ const device_t fdc37c663_device = { "SMC FDC37C663 Super I/O", 0, 0x63, + NULL, fdc37c66x_init, fdc37c66x_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -307,6 +309,7 @@ const device_t fdc37c665_device = { "SMC FDC37C665 Super I/O", 0, 0x65, + NULL, fdc37c66x_init, fdc37c66x_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -316,6 +319,7 @@ const device_t fdc37c666_device = { "SMC FDC37C666 Super I/O", 0, 0x66, + NULL, fdc37c66x_init, fdc37c66x_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sio/sio_fdc37c93x.c b/src/devices/sio/sio_fdc37c93x.c index e4b16c2..8091b96 100644 --- a/src/devices/sio/sio_fdc37c93x.c +++ b/src/devices/sio/sio_fdc37c93x.c @@ -9,10 +9,12 @@ * Implementation of the SMC FDC37C932FR and FDC37C935 Super * I/O Chips. * - * Version: @(#)sio_fdc37c93x.c 1.0.11 2018/11/11 + * Version: @(#)sio_fdc37c93x.c 1.0.13 2019/04/09 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -48,6 +50,7 @@ #include "../floppy/fdc.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" +#include "../../plat.h" #include "sio.h" @@ -662,7 +665,7 @@ access_bus_close(void *priv) static void * -access_bus_init(const device_t *info) +access_bus_init(const device_t *info, UNUSED(void *parent)) { access_bus_t *dev = (access_bus_t *)mem_alloc(sizeof(access_bus_t)); memset(dev, 0x00, sizeof(access_bus_t)); @@ -675,6 +678,7 @@ static const device_t access_bus_device = { "SMC FDC37C932FR ACCESS.bus", 0, 0x03, + NULL, access_bus_init, access_bus_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -691,7 +695,7 @@ fdc37c93x_close(void *priv) static void * -fdc37c93x_init(const device_t *info) +fdc37c93x_init(const device_t *info, UNUSED(void *parent)) { fdc37c93x_t *dev = (fdc37c93x_t *)mem_alloc(sizeof(fdc37c93x_t)); memset(dev, 0x00, sizeof(fdc37c93x_t)); @@ -718,6 +722,7 @@ const device_t fdc37c932fr_device = { "SMC FDC37C932FR Super I/O", 0, 0x03, + NULL, fdc37c93x_init, fdc37c93x_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -727,6 +732,7 @@ const device_t fdc37c935_device = { "SMC FDC37C935 Super I/O", 0, 0x02, + NULL, fdc37c93x_init, fdc37c93x_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sio/sio_pc87306.c b/src/devices/sio/sio_pc87306.c index 52d7202..09c37e5 100644 --- a/src/devices/sio/sio_pc87306.c +++ b/src/devices/sio/sio_pc87306.c @@ -8,10 +8,12 @@ * * Emulation of the NatSemi PC87306 Super I/O chip. * - * Version: @(#)sio_pc87306.c 1.0.9 2018/11/11 + * Version: @(#)sio_pc87306.c 1.0.11 2019/04/09 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -47,6 +49,7 @@ #include "../floppy/fdc.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" +#include "../../plat.h" #include "sio.h" @@ -440,7 +443,7 @@ pc87306_close(void *priv) static void * -pc87306_init(const device_t *info) +pc87306_init(const device_t *info, UNUSED(void *parent)) { pc87306_t *dev = (pc87306_t *)mem_alloc(sizeof(pc87306_t)); memset(dev, 0x00, sizeof(pc87306_t)); @@ -458,8 +461,7 @@ pc87306_init(const device_t *info) const device_t pc87306_device = { "National Semiconductor PC87306 Super I/O", - 0, - 0, + 0, 0, NULL, pc87306_init, pc87306_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sio/sio_um8669f.c b/src/devices/sio/sio_um8669f.c index 5a732df..ffacf42 100644 --- a/src/devices/sio/sio_um8669f.c +++ b/src/devices/sio/sio_um8669f.c @@ -29,11 +29,13 @@ * 70 - IRQ * 74 - DMA * - * Version: @(#)sio_um8669f.c 1.0.9 2018/11/11 + * Version: @(#)sio_um8669f.c 1.0.11 2019/04/09 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * Sarah Walker, * + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -68,6 +70,7 @@ #include "../ports/serial.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" +#include "../../plat.h" #include "sio.h" @@ -344,7 +347,7 @@ um8669f_close(void *priv) static void * -um8669f_init(const device_t *info) +um8669f_init(const device_t *info, UNUSED(void *parent)) { um8669f_t *dev = (um8669f_t *)mem_alloc(sizeof(um8669f_t)); memset(dev, 0x00, sizeof(um8669f_t)); @@ -362,8 +365,7 @@ um8669f_init(const device_t *info) const device_t um8669f_device = { "UMC UM8669F Super I/O", - 0, - 0, + 0, 0, NULL, um8669f_init, um8669f_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sio/sio_w83877f.c b/src/devices/sio/sio_w83877f.c index e1ae1fb..db46095 100644 --- a/src/devices/sio/sio_w83877f.c +++ b/src/devices/sio/sio_w83877f.c @@ -10,10 +10,12 @@ * * Winbond W83877F Super I/O Chip * - * Version: @(#)sio_w83877f.c 1.0.9 2018/11/11 + * Version: @(#)sio_w83877f.c 1.0.11 2019/04/09 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -49,6 +51,7 @@ #include "../ports/serial.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" +#include "../../plat.h" #include "sio.h" @@ -454,7 +457,7 @@ w83877f_close(void *priv) static void * -w83877f_init(const device_t *info) +w83877f_init(const device_t *info, UNUSED(void *parent)) { w83877f_t *dev = (w83877f_t *)mem_alloc(sizeof(w83877f_t)); memset(dev, 0x00, sizeof(w83877f_t)); @@ -472,6 +475,7 @@ const device_t w83877f_device = { "Winbond W83877F Super I/O", 0, 5, + NULL, w83877f_init, w83877f_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -482,6 +486,7 @@ const device_t w83877f_president_device = { "Winbond W83877F Super I/O (President)", 0, 4, + NULL, w83877f_init, w83877f_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sound/midi_fluidsynth.c b/src/devices/sound/midi_fluidsynth.c index 88b6c49..4ec5f53 100644 --- a/src/devices/sound/midi_fluidsynth.c +++ b/src/devices/sound/midi_fluidsynth.c @@ -17,7 +17,7 @@ * website (for 32bit and 64bit Windows) are working, and * need no additional support files other than sound fonts. * - * Version: @(#)midi_fluidsynth.c 1.0.14 2018/10/25 + * Version: @(#)midi_fluidsynth.c 1.0.16 2019/04/11 * * Code borrowed from scummvm. * @@ -25,7 +25,7 @@ * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -260,7 +260,7 @@ fluidsynth_sysex(uint8_t *data, unsigned int len) static void * -fluidsynth_init(const device_t *info) +fluidsynth_init(const device_t *info, UNUSED(void *parent)) { fluidsynth_t *data = &fsdev; midi_device_t* dev; @@ -429,6 +429,9 @@ static const device_config_t fluidsynth_config[] = { { { "SF2 Sound Fonts","sf2" + }, + { + NULL } } }, @@ -486,6 +489,9 @@ static const device_config_t fluidsynth_config[] = { }, { "Triangle",1 + }, + { + NULL } } }, @@ -542,22 +548,20 @@ static const device_config_t fluidsynth_config[] = { "7th Order",3 }, { - "" + NULL } } }, { - "","",-1 + NULL } }; const device_t fluidsynth_device = { "FluidSynth", - 0, 0, - fluidsynth_init, - fluidsynth_close, - NULL, + 0, 0, NULL, + fluidsynth_init, fluidsynth_close, NULL, fluidsynth_available, NULL, NULL, diff --git a/src/devices/sound/midi_mt32.c b/src/devices/sound/midi_mt32.c index 0bbb817..ecbad72 100644 --- a/src/devices/sound/midi_mt32.c +++ b/src/devices/sound/midi_mt32.c @@ -8,13 +8,13 @@ * * Interface to the MuNT32 MIDI synthesizer. * - * Version: @(#)midi_mt32.c 1.0.7 2018/10/25 + * Version: @(#)midi_mt32.c 1.0.9 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -293,14 +293,14 @@ mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) static void * -mt32_init(const device_t *info) +mt32_init(const device_t *info, UNUSED(void *parent)) { return mt32emu_init(MT32_CTRL_ROM_PATH, MT32_PCM_ROM_PATH); } static void * -cm32l_init(const device_t *info) +cm32l_init(const device_t *info, UNUSED(void *parent)) { return mt32emu_init(CM32_CTRL_ROM_PATH, CM32_PCM_ROM_PATH); } @@ -365,14 +365,14 @@ static const device_config_t mt32_config[] = "nice_ramp","Nice ramp",CONFIG_BINARY,"",1 }, { - "","",-1 + NULL } }; const device_t mt32_device = { "Roland MT-32 Emulation", - 0, 0, + 0, 0, NULL, mt32_init, mt32_close, NULL, mt32_available, NULL, NULL, NULL, @@ -381,7 +381,7 @@ const device_t mt32_device = { const device_t cm32l_device = { "Roland CM-32L Emulation", - 0, 0, + 0, 0, NULL, cm32l_init, mt32_close, NULL, cm32l_available, NULL, NULL, NULL, diff --git a/src/devices/sound/midi_system.c b/src/devices/sound/midi_system.c index 31efc22..fa311e4 100644 --- a/src/devices/sound/midi_system.c +++ b/src/devices/sound/midi_system.c @@ -8,13 +8,13 @@ * * Interface to system MIDI driver. * - * Version: @(#)midi_system.c 1.0.5 2018/09/22 + * Version: @(#)midi_system.c 1.0.7 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -50,7 +50,7 @@ void * -system_midi_init(const device_t *info) +system_midi_init(const device_t *info, UNUSED(void *parent)) { midi_device_t *dev; @@ -98,7 +98,7 @@ static const device_config_t system_midi_config[] = { const device_t system_midi_device = { SYSTEM_MIDI_NAME, - 0, 0, + 0, 0, NULL, system_midi_init, system_midi_close, NULL, system_midi_available, NULL, NULL, NULL, diff --git a/src/devices/sound/resid-fp/sid.cpp b/src/devices/sound/resid-fp/sid.cpp index 801f9e0..430c896 100644 --- a/src/devices/sound/resid-fp/sid.cpp +++ b/src/devices/sound/resid-fp/sid.cpp @@ -106,7 +106,7 @@ static int host_cpu_features(void) static int features = 0; static int features_detected = 0; /* 32-bit only */ -#if defined(__i386__) || (defined(_MSC_VER) && defined(_WIN32)) +#if defined(__i386__) || (defined(_MSC_VER) && defined(_M_IX86)) unsigned long temp1, temp2; #endif @@ -114,7 +114,7 @@ static int host_cpu_features(void) return features; features_detected = 1; -#if defined(_MSC_VER) && defined(_WIN32) /* MSVC compatible assembly appropriate for 32-bit Windows */ +#if defined(_MSC_VER) && defined(_M_IX86) /* MSVC compatible assembly appropriate for 32-bit Windows */ /* see if we are dealing with a cpu that has the cpuid instruction */ __asm { pushf @@ -137,7 +137,7 @@ static int host_cpu_features(void) : : "eax"); #endif -#if defined(__i386__) || (defined(_MSC_VER) && defined(_WIN32)) +#if defined(__i386__) || (defined(_MSC_VER) && defined(_M_IX86)) temp1 &= 0x200000; temp2 &= 0x200000; if (temp1 == temp2) { diff --git a/src/devices/sound/snd_adlib.c b/src/devices/sound/snd_adlib.c index c17b00d..39a80d3 100644 --- a/src/devices/sound/snd_adlib.c +++ b/src/devices/sound/snd_adlib.c @@ -8,13 +8,13 @@ * * Implementation of the ADLIB sound device. * - * Version: @(#)snd_adlib.c 1.0.7 2018/10/16 + * Version: @(#)snd_adlib.c 1.0.9 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -45,101 +45,116 @@ #include "../../emu.h" #include "../../io.h" #include "../../device.h" +#include "../../plat.h" #include "../system/mca.h" #include "sound.h" #include "snd_opl.h" -typedef struct adlib_t -{ - opl_t opl; - - uint8_t pos_regs[8]; +typedef struct { + opl_t opl; + + uint8_t pos_regs[8]; } adlib_t; -static void adlib_get_buffer(int32_t *buffer, int len, void *p) +static void +get_buffer(int32_t *buffer, int len, void *priv) { - adlib_t *adlib = (adlib_t *)p; - int c; + adlib_t *dev = (adlib_t *)priv; + int c; - opl2_update2(&adlib->opl); - - for (c = 0; c < len * 2; c++) - buffer[c] += (int32_t)adlib->opl.buffer[c]; + opl2_update2(&dev->opl); - adlib->opl.pos = 0; -} + for (c = 0; c < len * 2; c++) + buffer[c] += (int32_t)dev->opl.buffer[c]; -uint8_t adlib_mca_read(int port, void *p) -{ - adlib_t *adlib = (adlib_t *)p; - - DBGLOG(1, "adlib_mca_read: port=%04x\n", port); - - return adlib->pos_regs[port & 7]; -} - -void adlib_mca_write(int port, uint8_t val, void *p) -{ - adlib_t *adlib = (adlib_t *)p; - - if (port < 0x102) - return; - - DBGLOG(1, "adlib_mca_write: port=%04x val=%02x\n", port, val); - - switch (port) - { - case 0x102: - if ((adlib->pos_regs[2] & 1) && !(val & 1)) - io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - if (!(adlib->pos_regs[2] & 1) && (val & 1)) - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - break; - } - adlib->pos_regs[port & 7] = val; + dev->opl.pos = 0; } -void * -adlib_init(const device_t *info) +static uint8_t +adlib_mca_read(int port, void *priv) { - adlib_t *adlib = (adlib_t *)mem_alloc(sizeof(adlib_t)); - memset(adlib, 0, sizeof(adlib_t)); - - DEBUG("adlib_init\n"); - opl2_init(&adlib->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - sound_add_handler(adlib_get_buffer, adlib); - return adlib; + adlib_t *dev = (adlib_t *)priv; + + DBGLOG(1, "adlib_mca_read: port=%04x\n", port); + + return dev->pos_regs[port & 7]; } -void * -adlib_mca_init(const device_t *info) +static void +adlib_mca_write(int port, uint8_t val, void *priv) { - adlib_t *adlib = (adlib_t *)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); - adlib->pos_regs[0] = 0xd7; - adlib->pos_regs[1] = 0x70; + adlib_t *dev = (adlib_t *)priv; - return adlib; + if (port < 0x102) + return; + + DBGLOG(1, "adlib_mca_write: port=%04x val=%02x\n", port, val); + + switch (port) { + case 0x102: + if ((dev->pos_regs[2] & 1) && !(val & 1)) + io_removehandler(0x0388, 0x0002, + opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &dev->opl); + if (! (dev->pos_regs[2] & 1) && (val & 1)) + io_sethandler(0x0388, 0x0002, + opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &dev->opl); + break; + } + + dev->pos_regs[port & 7] = val; } -void adlib_close(void *p) -{ - adlib_t *adlib = (adlib_t *)p; - free(adlib); +static void * +adlib_init(const device_t *info, UNUSED(void *parent)) +{ + adlib_t *dev; + + dev = (adlib_t *)mem_alloc(sizeof(adlib_t)); + memset(dev, 0x00, sizeof(adlib_t)); + + switch(info->local) { + case 0: /* ISA */ + io_sethandler(0x0388, 2, + opl2_read,NULL,NULL, + opl2_write,NULL,NULL, &dev->opl); + break; + + case 1: /* MCA */ + dev->pos_regs[0] = 0xd7; + dev->pos_regs[1] = 0x70; + mca_add(adlib_mca_read, adlib_mca_write, dev); + break; + } + + opl2_init(&dev->opl); + + sound_add_handler(get_buffer, dev); + + return(dev); } + +static void +adlib_close(void *priv) +{ + adlib_t *dev = (adlib_t *)priv; + + free(dev); +} + + const device_t adlib_device = { "AdLib", DEVICE_ISA, 0, + NULL, adlib_init, adlib_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -148,7 +163,8 @@ const device_t adlib_device = { const device_t adlib_mca_device = { "AdLib", DEVICE_MCA, - 0, + 1, + NULL, adlib_init, adlib_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sound/snd_adlibgold.c b/src/devices/sound/snd_adlibgold.c index 9a52000..01c175a 100644 --- a/src/devices/sound/snd_adlibgold.c +++ b/src/devices/sound/snd_adlibgold.c @@ -10,13 +10,13 @@ * * TODO: Stack allocation of big buffers (line 688 et al.) * - * Version: @(#)snd_adlibgold.c 1.0.10 2018/10/16 + * Version: @(#)snd_adlibgold.c 1.0.12 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -812,7 +812,7 @@ static void adgold_get_buffer(int32_t *buffer, int len, void *p) } -void *adgold_init(const device_t *info) +void *adgold_init(const device_t *info, UNUSED(void *parent)) { FILE *f; int c; @@ -891,14 +891,16 @@ static const device_config_t adgold_config[] = { "surround", "Surround module", CONFIG_BINARY, "", 1 }, { - "", "", -1 + NULL } }; + const device_t adgold_device = { "AdLib Gold", DEVICE_ISA, 0, + NULL, adgold_init, adgold_close, NULL, NULL, NULL, NULL, NULL, adgold_config diff --git a/src/devices/sound/snd_audiopci.c b/src/devices/sound/snd_audiopci.c index 60f5eb3..0a4b87b 100644 --- a/src/devices/sound/snd_audiopci.c +++ b/src/devices/sound/snd_audiopci.c @@ -8,13 +8,13 @@ * * Implementation of the AudioPCI sound device. * - * Version: @(#)snd_audiopci.c 1.0.14 2018/10/16 + * Version: @(#)snd_audiopci.c 1.0.16 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -48,6 +48,7 @@ #include "../../mem.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/nmi.h" #include "../system/pci.h" #include "sound.h" @@ -1330,7 +1331,7 @@ es1371_pci_write(int func, int addr, uint8_t val, void *p) static void * -es1371_init(const device_t *info) +es1371_init(const device_t *info, UNUSED(void *parent)) { es1371_t *dev = (es1371_t *)mem_alloc(sizeof(es1371_t)); memset(dev, 0, sizeof(es1371_t)); @@ -1370,6 +1371,7 @@ const device_t es1371_device = { "Ensoniq AudioPCI (ES1371)", DEVICE_PCI, 0, + NULL, es1371_init, es1371_close, NULL, NULL, es1371_speed_changed, @@ -1383,6 +1385,7 @@ const device_t sbpci128_device = { "Sound Blaster 128", DEVICE_PCI, 1, + NULL, es1371_init, es1371_close, NULL, NULL, es1371_speed_changed, diff --git a/src/devices/sound/snd_cms.c b/src/devices/sound/snd_cms.c index 212df79..91bd9e4 100644 --- a/src/devices/sound/snd_cms.c +++ b/src/devices/sound/snd_cms.c @@ -8,13 +8,13 @@ * * Implementation of the Creative CMS/GameBlaster sound device. * - * Version: @(#)snd_cms.c 1.0.7 2018/10/16 + * Version: @(#)snd_cms.c 1.0.9 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -45,6 +45,7 @@ #include "../../emu.h" #include "../../io.h" #include "../../device.h" +#include "../../plat.h" #include "sound.h" @@ -240,7 +241,7 @@ cms_read(uint16_t addr, void *priv) static void * -cms_init(const device_t *info) +cms_init(const device_t *info, UNUSED(void *parent)) { cms_t *dev; @@ -269,6 +270,7 @@ const device_t cms_device = { "Creative Music System (Game Blaster)", DEVICE_ISA, 0, + NULL, cms_init, cms_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sound/snd_cs423x.c b/src/devices/sound/snd_cs423x.c index fa305e1..38a2c3c 100644 --- a/src/devices/sound/snd_cs423x.c +++ b/src/devices/sound/snd_cs423x.c @@ -8,13 +8,13 @@ * * Implementation of Cirrus Logic Crystal 423x sound devices. * - * Version: @(#)snd_cs423x.c 1.0.1 2019/01/13 + * Version: @(#)snd_cs423x.c 1.0.2 2019/03/15 * * Authors: Altheos, * Fred N. van Kempen, * - * Copyright 2018,2019 Altheos. * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2018,2019 Altheos. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the diff --git a/src/devices/sound/snd_gus.c b/src/devices/sound/snd_gus.c index cc99f78..7d36260 100644 --- a/src/devices/sound/snd_gus.c +++ b/src/devices/sound/snd_gus.c @@ -8,7 +8,7 @@ * * Implementation of the Gravis UltraSound sound device. * - * Version: @(#)snd_gus.c 1.0.10 2019/01/13 + * Version: @(#)snd_gus.c 1.0.12 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,6 +46,7 @@ #include "../../io.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/dma.h" #include "../system/nmi.h" #include "../system/pic.h" @@ -1155,7 +1156,7 @@ get_buffer(int32_t *buffer, int len, void *priv) static void * -gus_init(const device_t *info) +gus_init(const device_t *info, UNUSED(void *parent)) { gus_t *dev; double out = 1.0; @@ -1263,6 +1264,7 @@ const device_t gus_device = { "Gravis UltraSound", DEVICE_ISA, 0, + NULL, gus_init, gus_close, NULL, NULL, speed_changed, NULL, NULL, @@ -1274,6 +1276,7 @@ const device_t gusmax_device = { "Gravis UltraSound MAX", DEVICE_ISA, 1, + NULL, gus_init, gus_close, NULL, NULL, speed_changed, NULL, NULL, diff --git a/src/devices/sound/snd_lpt_dac.c b/src/devices/sound/snd_lpt_dac.c index 18b8dc1..6a57a70 100644 --- a/src/devices/sound/snd_lpt_dac.c +++ b/src/devices/sound/snd_lpt_dac.c @@ -8,13 +8,13 @@ * * Implemantation of LPT-based sound devices. * - * Version: @(#)snd_lpt_dac.c 1.0.9 2018/10/16 + * Version: @(#)snd_lpt_dac.c 1.0.10 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,7 +44,6 @@ #define dbglog sound_card_log #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../timer.h" #include "../ports/parallel_dev.h" #include "sound.h" diff --git a/src/devices/sound/snd_lpt_dss.c b/src/devices/sound/snd_lpt_dss.c index d901ee0..d7e947b 100644 --- a/src/devices/sound/snd_lpt_dss.c +++ b/src/devices/sound/snd_lpt_dss.c @@ -8,13 +8,13 @@ * * Implementation of the LPT-based DSS sound device. * - * Version: @(#)snd_lpt_dss.c 1.0.9 2018/10/16 + * Version: @(#)snd_lpt_dss.c 1.0.10 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,7 +44,6 @@ #define dbglog sound_card_log #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../timer.h" #include "../ports/parallel_dev.h" #include "sound.h" diff --git a/src/devices/sound/snd_mpu401.c b/src/devices/sound/snd_mpu401.c index a9414e2..67b595c 100644 --- a/src/devices/sound/snd_mpu401.c +++ b/src/devices/sound/snd_mpu401.c @@ -8,7 +8,7 @@ * * Roland MPU-401 emulation. * - * Version: @(#)snd_mpu401.c 1.0.10 2018/09/22 + * Version: @(#)snd_mpu401.c 1.0.13 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -16,7 +16,7 @@ * Sarah Walker, * DOSBox Team, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * Copyright 2008-2017 DOSBox Team. @@ -48,9 +48,9 @@ #define dbglog sound_midi_log #include "../../emu.h" #include "../../io.h" -#include "../../machines/machine.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pic.h" #include "../system/mca.h" #include "sound.h" @@ -927,7 +927,7 @@ void mpu401_device_add(void) { - if (machines[machine].flags & MACHINE_MCA) + if (MCA) device_add(&mpu401_mca_device); else device_add(&mpu401_device); @@ -968,7 +968,7 @@ mpu401_mca_write(int port, uint8_t val, void *priv) static void * -mpu401_standalone_init(const device_t *info) +mpu401_standalone_init(const device_t *info, UNUSED(void *parent)) { mpu_t *dev; uint16_t base; @@ -1009,13 +1009,13 @@ static const device_config_t mpu401_standalone_config[] = { "base", "MPU-401 Address", CONFIG_HEX16, "", 0x330, { { - "0x300", 0x300 + "300H", 0x300 }, { - "0x330", 0x330 + "330H", 0x330 }, { - "" + NULL } } }, @@ -1041,12 +1041,12 @@ static const device_config_t mpu401_standalone_config[] = { "IRQ 10", 10 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -1054,11 +1054,9 @@ const device_t mpu401_device = { "Roland MPU-IPC-T", DEVICE_ISA, 0, + NULL, mpu401_standalone_init, mpu401_standalone_close, NULL, - NULL, - NULL, - NULL, - NULL, + NULL, NULL, NULL, NULL, mpu401_standalone_config }; @@ -1066,10 +1064,8 @@ const device_t mpu401_mca_device = { "MPU-401 MCA (Standalone)", DEVICE_MCA, 0, + NULL, mpu401_standalone_init, mpu401_standalone_close, NULL, - NULL, - NULL, - NULL, - NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/devices/sound/snd_pas16.c b/src/devices/sound/snd_pas16.c index e6e5a77..416d30f 100644 --- a/src/devices/sound/snd_pas16.c +++ b/src/devices/sound/snd_pas16.c @@ -79,7 +79,7 @@ * FF88 - board model * 3 = PAS16 * - * Version: @(#)snd_pas16.c 1.0.9 2019/02/08 + * Version: @(#)snd_pas16.c 1.0.12 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -118,6 +118,7 @@ #include "../../io.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/dma.h" #include "../system/pic.h" #include "../system/pit.h" @@ -770,7 +771,7 @@ void pas16_get_buffer(int32_t *buffer, int len, void *p) } -static void *pas16_init(const device_t *info) +static void *pas16_init(const device_t *info, UNUSED(void *parent)) { pas16_t *pas16 = (pas16_t *)mem_alloc(sizeof(pas16_t)); memset(pas16, 0, sizeof(pas16_t)); @@ -799,6 +800,7 @@ const device_t pas16_device = { "Pro Audio Spectrum 16", DEVICE_ISA | DEVICE_UNSTABLE, 0, + NULL, pas16_init, pas16_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sound/snd_sb.c b/src/devices/sound/snd_sb.c index 79300db..7b336fa 100644 --- a/src/devices/sound/snd_sb.c +++ b/src/devices/sound/snd_sb.c @@ -8,14 +8,14 @@ * * Sound Blaster emulation. * - * Version: @(#)snd_sb.c 1.0.9 2018/10/25 + * Version: @(#)snd_sb.c 1.0.11 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * TheCollector1995, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -48,6 +48,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "../system/mca.h" #include "sound.h" #include "filters.h" @@ -1019,7 +1020,7 @@ void sb_pro_mcv_write(int port, uint8_t val, void *p) sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); } -void *sb_1_init(const device_t *info) +void *sb_1_init(const device_t *info, UNUSED(void *parent)) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x0 to 2x3 -> CMS chip @@ -1045,7 +1046,7 @@ void *sb_1_init(const device_t *info) sound_add_handler(sb_get_buffer_sb2, sb); return sb; } -void *sb_15_init(const device_t *info) +void *sb_15_init(const device_t *info, UNUSED(void *parent)) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x0 to 2x3 -> CMS chip @@ -1072,7 +1073,7 @@ void *sb_15_init(const device_t *info) return sb; } -void *sb_mcv_init(const device_t *info) +void *sb_mcv_init(const device_t *info, UNUSED(void *parent)) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x6, 2xA, 2xC, 2xE -> DSP chip @@ -1094,7 +1095,7 @@ void *sb_mcv_init(const device_t *info) sb->pos_regs[1] = 0x50; return sb; } -void *sb_2_init(const device_t *info) +void *sb_2_init(const device_t *info, UNUSED(void *parent)) { /*sb2 port mappings. 220h or 240h. 2x0 to 2x3 -> CMS chip @@ -1144,7 +1145,7 @@ void *sb_2_init(const device_t *info) return sb; } -void *sb_pro_v1_init(const device_t *info) +void *sb_pro_v1_init(const device_t *info, UNUSED(void *parent)) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip, Left and Right (9*2 voices) @@ -1177,7 +1178,7 @@ void *sb_pro_v1_init(const device_t *info) return sb; } -void *sb_pro_v2_init(const device_t *info) +void *sb_pro_v2_init(const device_t *info, UNUSED(void *parent)) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip (18 voices) @@ -1209,7 +1210,7 @@ void *sb_pro_v2_init(const device_t *info) return sb; } -void *sb_pro_mcv_init(const device_t *info) +void *sb_pro_mcv_init(const device_t *info, UNUSED(void *parent)) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip, Left and Right (18 voices) @@ -1234,7 +1235,7 @@ void *sb_pro_mcv_init(const device_t *info) return sb; } -void *sb_16_init(const device_t *info) +void *sb_16_init(const device_t *info, UNUSED(void *parent)) { sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); @@ -1268,12 +1269,7 @@ void *sb_16_init(const device_t *info) return sb; } -int sb_awe32_available(void) -{ - return rom_present(ROM_PATH_AWE32); -} - -void *sb_awe32_init(const device_t *info) +void *sb_awe32_init(const device_t *info, UNUSED(void *parent)) { sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); @@ -1348,513 +1344,518 @@ void sb_speed_changed(void *p) sb_dsp_speed_changed(&sb->dsp); } -static const device_config_t sb_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 7, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - } - }, - { - "dma", "DMA", CONFIG_SELECTION, "", 1, - { - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, + +static const device_config_t sb_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x220, { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + { + "220H", 0x220 + }, + { + "240H", 0x240 + }, + { + NULL + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 7, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + NULL + } + } + }, + { + "dma", "DMA", CONFIG_SELECTION, "", 1, + { + { + "DMA 1", 1 + }, + { + "DMA 3", 3 + }, + { + NULL + } + } + }, + { + "opl", "Enable OPL", CONFIG_BINARY, "", 1 + }, + { + NULL + } }; -static const device_config_t sb_mcv_config[] = -{ - { - "irq", "IRQ", CONFIG_SELECTION, "", 7, - { - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - } - }, - { - "dma", "DMA", CONFIG_SELECTION, "", 1, - { - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, +static const device_config_t sb_mcv_config[] = { + { + "irq", "IRQ", CONFIG_SELECTION, "", 7, { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + { + "IRQ 3", 3 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + NULL + } + } + }, + { + "dma", "DMA", CONFIG_SELECTION, "", 1, + { + { + "DMA 1", 1 + }, + { + "DMA 3", 3 + }, + { + NULL + } + } + }, + { + "opl", "Enable OPL", CONFIG_BINARY, "", 1 + }, + { + NULL + } }; -static const device_config_t sb_pro_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 7, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, - { - "dma", "DMA", CONFIG_SELECTION, "", 1, - { - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, +static const device_config_t sb_pro_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x220, { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + { + "220H", 0x220 + }, + { + "240H", 0x240 + }, + { + NULL + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 7, + { + { + "IRQ 2", 2 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 10", 10 + }, + { + NULL + } + } + }, + { + "dma", "DMA", CONFIG_SELECTION, "", 1, + { + { + "DMA 1", 1 + }, + { + "DMA 3", 3 + }, + { + NULL + } + } + }, + { + "opl", "Enable OPL", CONFIG_BINARY, "", 1 + }, + { + NULL + } }; -static const device_config_t sb_16_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "0x260", 0x260 - }, - { - "0x280", 0x280 - }, - { - "" - } - } - }, - { - "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, - { - { - "Disabled", 0 - }, - { - "0x300", 0x300 - }, - { - "0x330", 0x330 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, - { - "dma", "Low DMA channel", CONFIG_SELECTION, "", 1, - { - { - "DMA 0", 0 - }, - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "dma16", "High DMA channel", CONFIG_SELECTION, "", 5, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - } - }, +static const device_config_t sb_16_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x220, { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + { + "220H", 0x220 + }, + { + "240H", 0x240 + }, + { + "260H", 0x260 + }, + { + "280H", 0x280 + }, + { + NULL + } + } + }, + { + "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, + { + { + "Disabled", 0 + }, + { + "300H", 0x300 + }, + { + "330H", 0x330 + }, + { + NULL + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, + { + { + "IRQ 2", 2 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 10", 10 + }, + { + NULL + } + } + }, + { + "dma", "Low DMA channel", CONFIG_SELECTION, "", 1, + { + { + "DMA 0", 0 + }, + { + "DMA 1", 1 + }, + { + "DMA 3", 3 + }, + { + NULL + } + } + }, + { + "dma16", "High DMA channel", CONFIG_SELECTION, "", 5, + { + { + "DMA 5", 5 + }, + { + "DMA 6", 6 + }, + { + "DMA 7", 7 + }, + { + NULL + } + } + }, + { + "opl", "Enable OPL", CONFIG_BINARY, "", 1 + }, + { + NULL + } }; -static const device_config_t sb_awe32_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "0x260", 0x260 - }, - { - "0x280", 0x280 - }, - { - "" - } - } - }, - { - "emu_base", "EMU8000 Address", CONFIG_HEX16, "", 0x620, - { - { - "0x620", 0x620 - }, - { - "0x640", 0x640 - }, - { - "0x660", 0x660 - }, - { - "0x680", 0x680 - }, - { - .description = "" - } - } - }, - { - "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, - { - { - "Disabled", 0 - }, - { - "0x300", 0x300 - }, - { - "0x330", 0x330 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, - { - "dma", "Low DMA channel", CONFIG_SELECTION, "", 1, - { - { - "DMA 0", 0 - }, - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "dma16", "High DMA channel", CONFIG_SELECTION, "", 5, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - } - }, - { - "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512, - { - { - "None", 0 - }, - { - "512 KB", 512 - }, - { - "2 MB", 2048 - }, - { - "8 MB", 8192 - }, - { - "28 MB", 28*1024 - }, - { - "" - } - } - }, +static const device_config_t sb_awe32_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x220, { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + { + "220H", 0x220 + }, + { + "240H", 0x240 + }, + { + "260H", 0x260 + }, + { + "280H", 0x280 + }, + { + NULL + } + } + }, + { + "emu_base", "EMU8000 Address", CONFIG_HEX16, "", 0x620, + { + { + "620H", 0x620 + }, + { + "640H", 0x640 + }, + { + "660H", 0x660 + }, + { + "680H", 0x680 + }, + { + NULL + } + } + }, + { + "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, + { + { + "Disabled", 0 + }, + { + "300H", 0x300 + }, + { + "330H", 0x330 + }, + { + NULL + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, + { + { + "IRQ 2", 2 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 10", 10 + }, + { + NULL + } + } + }, + { + "dma", "Low DMA channel", CONFIG_SELECTION, "", 1, + { + { + "DMA 0", 0 + }, + { + "DMA 1", 1 + }, + { + "DMA 3", 3 + }, + { + NULL + } + } + }, + { + "dma16", "High DMA channel", CONFIG_SELECTION, "", 5, + { + { + "DMA 5", 5 + }, + { + "DMA 6", 6 + }, + { + "DMA 7", 7 + }, + { + NULL + } + } + }, + { + "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512, + { + { + "None", 0 + }, + { + "512 KB", 512 + }, + { + "2 MB", 2048 + }, + { + "8 MB", 8192 + }, + { + "28 MB", 28*1024 + }, + { + NULL + } + } + }, + { + "opl", "Enable OPL", CONFIG_BINARY, "", 1 + }, + { + NULL + } }; -const device_t sb_1_device = -{ - "Sound Blaster v1.0", - DEVICE_ISA, - 0, - sb_1_init, sb_close, NULL, - NULL, - sb_speed_changed, - NULL, - NULL, - sb_config + +const device_t sb_1_device = { + "Sound Blaster v1.0", + DEVICE_ISA, + 0, + NULL, + sb_1_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + sb_config }; -const device_t sb_15_device = -{ - "Sound Blaster v1.5", - DEVICE_ISA, - 0, - sb_15_init, sb_close, NULL, - NULL, - sb_speed_changed, - NULL, - NULL, - sb_config + +const device_t sb_15_device = { + "Sound Blaster v1.5", + DEVICE_ISA, + 0, + NULL, + sb_15_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + sb_config }; -const device_t sb_mcv_device = -{ - "Sound Blaster MCV", - DEVICE_MCA, - 0, - sb_mcv_init, sb_close, NULL, - NULL, - sb_speed_changed, - NULL, - NULL, - sb_mcv_config + +const device_t sb_mcv_device = { + "Sound Blaster MCV", + DEVICE_MCA, + 0, + NULL, + sb_mcv_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + sb_mcv_config }; -const device_t sb_2_device = -{ - "Sound Blaster v2.0", - DEVICE_ISA, - 0, - sb_2_init, sb_close, NULL, - NULL, - sb_speed_changed, - NULL, - NULL, - sb_config + +const device_t sb_2_device = { + "Sound Blaster v2.0", + DEVICE_ISA, + 0, + NULL, + sb_2_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + sb_config }; -const device_t sb_pro_v1_device = -{ - "Sound Blaster Pro", - DEVICE_ISA, - 0, - sb_pro_v1_init, sb_close, NULL, - NULL, - sb_speed_changed, - NULL, - NULL, - sb_pro_config + +const device_t sb_pro_v1_device = { + "Sound Blaster Pro", + DEVICE_ISA, + 0, + NULL, + sb_pro_v1_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + sb_pro_config }; -const device_t sb_pro_v2_device = -{ - "Sound Blaster Pro v2", - DEVICE_ISA, - 0, - sb_pro_v2_init, sb_close, NULL, - NULL, - sb_speed_changed, - NULL, - NULL, - sb_pro_config + +const device_t sb_pro_v2_device = { + "Sound Blaster Pro v2", + DEVICE_ISA, + 0, + NULL, + sb_pro_v2_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + sb_pro_config }; -const device_t sb_pro_mcv_device = -{ - "Sound Blaster Pro MCV", - DEVICE_MCA, - 0, - sb_pro_mcv_init, sb_close, NULL, - NULL, - sb_speed_changed, - NULL, - NULL, - NULL + +const device_t sb_pro_mcv_device = { + "Sound Blaster Pro MCV", + DEVICE_MCA, + 0, + NULL, + sb_pro_mcv_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + NULL }; -const device_t sb_16_device = -{ - "Sound Blaster 16", - DEVICE_ISA, - 0, - sb_16_init, sb_close, NULL, - NULL, - sb_speed_changed, - NULL, - NULL, - sb_16_config + +const device_t sb_16_device = { + "Sound Blaster 16", + DEVICE_ISA, + 0, + NULL, + sb_16_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + sb_16_config }; -const device_t sb_awe32_device = -{ - "Sound Blaster AWE32", - DEVICE_ISA, - 0, - sb_awe32_init, sb_close, NULL, - sb_awe32_available, - sb_speed_changed, - NULL, - NULL, - sb_awe32_config + +const device_t sb_awe32_device = { + "Sound Blaster AWE32", + DEVICE_ISA, + 0, + ROM_PATH_AWE32, + sb_awe32_init, sb_close, NULL, + NULL, + sb_speed_changed, + NULL, + NULL, + sb_awe32_config }; diff --git a/src/devices/sound/snd_sn76489.c b/src/devices/sound/snd_sn76489.c index da00c77..e31264c 100644 --- a/src/devices/sound/snd_sn76489.c +++ b/src/devices/sound/snd_sn76489.c @@ -8,13 +8,13 @@ * * Implementation of the TI SN74689 PSG sound devices. * - * Version: @(#)snd_sn76489.c 1.0.6 2018/10/16 + * Version: @(#)snd_sn76489.c 1.0.8 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -46,6 +46,7 @@ #include "../../emu.h" #include "../../io.h" #include "../../device.h" +#include "../../plat.h" #include "sound.h" #include "snd_sn76489.h" @@ -244,7 +245,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(const device_t *info) +void *sn76489_device_init(const device_t *info, UNUSED(void *parent)) { sn76489_t *sn76489 = (sn76489_t *)mem_alloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); @@ -253,7 +254,7 @@ void *sn76489_device_init(const device_t *info) return sn76489; } -void *ncr8496_device_init(const device_t *info) +void *ncr8496_device_init(const device_t *info, UNUSED(void *parent)) { sn76489_t *sn76489 = (sn76489_t *)mem_alloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); @@ -270,23 +271,19 @@ void sn76489_device_close(void *p) free(sn76489); } -const device_t sn76489_device = -{ - "TI SN74689 PSG", - 0, - 0, - sn76489_device_init, - sn76489_device_close, - NULL, NULL, NULL, NULL, - NULL + +const device_t sn76489_device = { + "TI SN74689 PSG", + 0, 0, NULL, + sn76489_device_init, sn76489_device_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; -const device_t ncr8496_device = -{ - "NCR8496 PSG", - 0, - 0, - ncr8496_device_init, - sn76489_device_close, - NULL, NULL, NULL, NULL, - NULL + +const device_t ncr8496_device = { + "NCR8496 PSG", + 0, 0, NULL, + ncr8496_device_init, sn76489_device_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; diff --git a/src/devices/sound/snd_ssi2001.c b/src/devices/sound/snd_ssi2001.c index 125c0c3..f6c2f82 100644 --- a/src/devices/sound/snd_ssi2001.c +++ b/src/devices/sound/snd_ssi2001.c @@ -8,13 +8,13 @@ * * Implementation of the SSI2001 sound device. * - * Version: @(#)snd_ssi2001.c 1.0.7 2018/10/16 + * Version: @(#)snd_ssi2001.c 1.0.9 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -45,6 +45,7 @@ #include "../../emu.h" #include "../../io.h" #include "../../device.h" +#include "../../plat.h" #include "sound.h" #include "snd_resid.h" @@ -109,7 +110,7 @@ ssi_write(uint16_t addr, uint8_t val, void *priv) static void * -ssi_init(const device_t *info) +ssi_init(const device_t *info, UNUSED(void *parent)) { ssi2001_t *dev; @@ -155,19 +156,19 @@ static const device_config_t ssi2001_config[] = { "base", "Address", CONFIG_HEX16, "", 0x280, { { - "0x280", 0x280 + "280H", 0x280 }, { - "0x2A0", 0x2a0 + "2A0H", 0x2a0 }, { - "0x2C0", 0x2c0 + "2C0H", 0x2c0 }, { - "0x2E0", 0x2e0 + "2E0H", 0x2e0 }, { - "" + NULL } } }, @@ -181,19 +182,21 @@ static const device_config_t ssi2001_config[] = { "Enabled", 1 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; + const device_t ssi2001_device = { "Innovation SSI-2001", DEVICE_ISA, 0, + NULL, ssi_init, ssi_close, NULL, NULL, NULL, NULL, NULL, ssi2001_config diff --git a/src/devices/sound/snd_wss.c b/src/devices/sound/snd_wss.c index 3b910fc..9f2ffa0 100644 --- a/src/devices/sound/snd_wss.c +++ b/src/devices/sound/snd_wss.c @@ -8,14 +8,14 @@ * * Implementation of the Windows Sound System sound device. * - * Version: @(#)snd_wss.c 1.0.6 2018/10/16 + * Version: @(#)snd_wss.c 1.0.8 2019/04/09 * * Authors: Fred N. van Kempen, * TheCollector1995, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2018 TheCollector1995. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. @@ -48,6 +48,7 @@ #include "../../emu.h" #include "../../io.h" #include "../../device.h" +#include "../../plat.h" #include "../system/mca.h" #include "../system/dma.h" #include "../system/pic.h" @@ -165,7 +166,7 @@ ncr_audio_mca_write(int port, uint8_t val, void *priv) static void * -wss_init(const device_t *info) +wss_init(const device_t *info, UNUSED(void *parent)) { wss_t *dev; @@ -226,6 +227,7 @@ const device_t wss_device = { "Windows Sound System", DEVICE_ISA, 0, + NULL, wss_init, wss_close, NULL, NULL, wss_speed_changed, @@ -237,6 +239,7 @@ const device_t ncr_business_audio_device = { "NCR Business Audio", DEVICE_MCA, 1, + NULL, wss_init, wss_close, NULL, NULL, wss_speed_changed, diff --git a/src/devices/system/dma.c b/src/devices/system/dma.c index 6bdc3e6..29eefec 100644 --- a/src/devices/system/dma.c +++ b/src/devices/system/dma.c @@ -8,7 +8,7 @@ * * Implementation of the Intel DMA controllers. * - * Version: @(#)dma.c 1.0.9 2019/02/28 + * Version: @(#)dma.c 1.0.10 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,7 +43,6 @@ #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../cpu/x86.h" -#include "../../machines/machine.h" #include "../../mem.h" #include "../../io.h" #include "../../plat.h" diff --git a/src/devices/system/intel.c b/src/devices/system/intel.c index 681968c..7d3f375 100644 --- a/src/devices/system/intel.c +++ b/src/devices/system/intel.c @@ -8,13 +8,13 @@ * * Implementation of Intel mainboards. * - * Version: @(#)intel.c 1.0.7 2018/11/11 + * Version: @(#)intel.c 1.0.9 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -43,7 +43,6 @@ #include #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../timer.h" @@ -136,7 +135,7 @@ batman_close(void *priv) static void * -batman_init(const device_t *info) +batman_init(const device_t *info, UNUSED(void *parent)) { batman_t *dev = (batman_t *)mem_alloc(sizeof(batman_t)); memset(dev, 0x00, sizeof(batman_t)); @@ -151,14 +150,13 @@ batman_init(const device_t *info) timer_add(timer_over, &dev->timer, &dev->timer, dev); - return dev; + return(dev); } const device_t intel_batman_device = { "Intel Batman board chip", - 0, - 0, + 0, 0, NULL, batman_init, batman_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/system/intel_flash.c b/src/devices/system/intel_flash.c index 36a7a18..bf33497 100644 --- a/src/devices/system/intel_flash.c +++ b/src/devices/system/intel_flash.c @@ -8,13 +8,13 @@ * * Implementation of the Intel 2 Mbit 8-bit flash devices. * - * Version: @(#)intel_flash.c 1.0.8 2018/10/24 + * Version: @(#)intel_flash.c 1.0.12 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -42,11 +42,12 @@ #include #include #include "../../emu.h" -#include "../../machines/machine.h" #include "../../device.h" #include "../../mem.h" +#include "../../rom.h" #include "../../nvr.h" #include "../../plat.h" +#include "../../machines/machine.h" #define FLASH_IS_BXB 2 @@ -195,9 +196,9 @@ void *intel_flash_init(uint8_t type) flash = (flash_t *)mem_alloc(sizeof(flash_t)); memset(flash, 0, sizeof(flash_t)); - l = (int)strlen(machine_get_internal_name_ex(machine))+1; + l = (int)strlen(machine_get_internal_name())+1; machine_name = (wchar_t *)mem_alloc(l * sizeof(wchar_t)); - mbstowcs(machine_name, machine_get_internal_name_ex(machine), l); + mbstowcs(machine_name, machine_get_internal_name(), l); l = (int)wcslen(machine_name)+5; flash_name = (wchar_t *)mem_alloc(l*sizeof(wchar_t)); swprintf(flash_name, l, L"%ls.bin", machine_name); @@ -239,11 +240,11 @@ void *intel_flash_init(uint8_t type) } if (flash->invert_high_pin) { - memcpy(flash->array, rom + 65536, 65536); - memcpy(flash->array + 65536, rom, 65536); + memcpy(flash->array, bios + 65536, 65536); + memcpy(flash->array + 65536, bios, 65536); } else - memcpy(flash->array, rom, 131072); + memcpy(flash->array, bios, 131072); if (flash->invert_high_pin) intel_flash_add_mappings_inverted(flash); @@ -267,25 +268,25 @@ void *intel_flash_init(uint8_t type) return flash; } -void *intel_flash_bxb_ami_init(const device_t *info) +void *intel_flash_bxb_ami_init(const device_t *info, UNUSED(void *parent)) { return intel_flash_init(info->local); } /* For AMI BIOS'es - Intel 28F001BXT with high address pin inverted. */ -void *intel_flash_bxt_ami_init(const device_t *info) +void *intel_flash_bxt_ami_init(const device_t *info, UNUSED(void *parent)) { return intel_flash_init(info->local); } /* For Award BIOS'es - Intel 28F001BXT with high address pin not inverted. */ -void *intel_flash_bxt_init(const device_t *info) +void *intel_flash_bxt_init(const device_t *info, UNUSED(void *parent)) { return intel_flash_init(info->local); } /* For Acer BIOS'es - Intel 28F001BXB. */ -void *intel_flash_bxb_init(const device_t *info) +void *intel_flash_bxb_init(const device_t *info, UNUSED(void *parent)) { return intel_flash_init(info->local); } @@ -305,42 +306,38 @@ void intel_flash_close(void *p) } -const device_t intel_flash_bxt_ami_device = -{ - "Intel 28F001BXT Flash BIOS", - 0, FLASH_INVERT, - intel_flash_bxt_ami_init, - intel_flash_close, - NULL, - NULL, NULL, NULL, NULL, NULL +const device_t intel_flash_bxt_ami_device = { + "Intel 28F001BXT Flash BIOS", + 0, FLASH_INVERT, + NULL, + intel_flash_bxt_ami_init, intel_flash_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; -const device_t intel_flash_bxb_ami_device = -{ - "Intel 28F001BXB Flash BIOS", - 0, FLASH_IS_BXB | FLASH_INVERT, - intel_flash_bxb_ami_init, - intel_flash_close, - NULL, - NULL, NULL, NULL, NULL, NULL +const device_t intel_flash_bxb_ami_device = { + "Intel 28F001BXB Flash BIOS", + 0, FLASH_IS_BXB | FLASH_INVERT, + NULL, + intel_flash_bxb_ami_init, intel_flash_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; -const device_t intel_flash_bxt_device = -{ - "Intel 28F001BXT Flash BIOS", - 0, 0, - intel_flash_bxt_init, - intel_flash_close, - NULL, - NULL, NULL, NULL, NULL, NULL +const device_t intel_flash_bxt_device = { + "Intel 28F001BXT Flash BIOS", + 0, 0, + NULL, + intel_flash_bxt_init, intel_flash_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; -const device_t intel_flash_bxb_device = -{ - "Intel 28F001BXB Flash BIOS", - 0, FLASH_IS_BXB, - intel_flash_bxb_init, - intel_flash_close, - NULL, - NULL, NULL, NULL, NULL, NULL +const device_t intel_flash_bxb_device = { + "Intel 28F001BXB Flash BIOS", + 0, FLASH_IS_BXB, + NULL, + intel_flash_bxb_init, intel_flash_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; diff --git a/src/devices/system/intel_piix.c b/src/devices/system/intel_piix.c index 0ee1c0f..b6cee54 100644 --- a/src/devices/system/intel_piix.c +++ b/src/devices/system/intel_piix.c @@ -12,13 +12,13 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)intel_piix.c 1.0.8 2018/10/14 + * Version: @(#)intel_piix.c 1.0.10 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -49,6 +49,7 @@ #include "../../io.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "../input/keyboard.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" @@ -839,7 +840,7 @@ piix_close(void *p) static void * -piix_init(const device_t *info) +piix_init(const device_t *info, UNUSED(void *parent)) { piix_t *piix = (piix_t *)mem_alloc(sizeof(piix_t)); memset(piix, 0, sizeof(piix_t)); @@ -872,6 +873,7 @@ const device_t piix_device = { "Intel 82371FB (PIIX)", DEVICE_PCI, 1, + NULL, piix_init, piix_close, piix_reset, NULL, NULL, NULL, NULL, NULL @@ -881,6 +883,7 @@ const device_t piix_pb640_device = { "Intel 82371FB (PIIX) (PB640)", DEVICE_PCI, 0x101, + NULL, piix_init, piix_close, piix_reset, NULL, NULL, NULL, NULL, NULL @@ -890,6 +893,7 @@ const device_t piix3_device = { "Intel 82371SB (PIIX3)", DEVICE_PCI, 3, + NULL, piix_init, piix_close, piix_reset, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/system/intel_sio.c b/src/devices/system/intel_sio.c index b3cca47..7e1f226 100644 --- a/src/devices/system/intel_sio.c +++ b/src/devices/system/intel_sio.c @@ -8,13 +8,13 @@ * * Emulation of Intel System I/O PCI chip. * - * Version: @(#)intel_sio.c 1.0.4 2018/10/05 + * Version: @(#)intel_sio.c 1.0.6 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -45,6 +45,7 @@ #include "../../io.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "dma.h" #include "pci.h" #include "intel_sio.h" @@ -194,7 +195,7 @@ sio_close(void *p) static void * -sio_init(const device_t *info) +sio_init(const device_t *info, UNUSED(void *parent)) { sio_t *sio = (sio_t *)mem_alloc(sizeof(sio_t)); memset(sio, 0, sizeof(sio_t)); @@ -217,6 +218,7 @@ const device_t sio_device = { "Intel 82378IB (SIO)", DEVICE_PCI, 0, + NULL, sio_init, sio_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/system/mca.c b/src/devices/system/mca.c index 1d59f76..e95d560 100644 --- a/src/devices/system/mca.c +++ b/src/devices/system/mca.c @@ -52,55 +52,64 @@ static int mca_index; static int mca_nr_cards; -void mca_init(int nr_cards) +void +mca_init(int nr_cards) { - int c; - - for (c = 0; c < 8; c++) - { - mca_card_read[c] = NULL; - mca_card_write[c] = NULL; - mca_priv[c] = NULL; - } - - mca_index = 0; - mca_nr_cards = nr_cards; + int c; + + for (c = 0; c < 8; c++) { + mca_card_read[c] = NULL; + mca_card_write[c] = NULL; + mca_priv[c] = NULL; + } + + mca_index = 0; + mca_nr_cards = nr_cards; } -void mca_set_index(int index) + +void +mca_set_index(int index) { - mca_index = index; + mca_index = index; } -uint8_t mca_read(uint16_t port) + +uint8_t +mca_read(uint16_t port) { - if (mca_index >= mca_nr_cards) - return 0xff; - if (!mca_card_read[mca_index]) - return 0xff; - return mca_card_read[mca_index](port, mca_priv[mca_index]); + if (mca_index >= mca_nr_cards) + return 0xff; + + if (! mca_card_read[mca_index]) + return 0xff; + + return mca_card_read[mca_index](port, mca_priv[mca_index]); } -void mca_write(uint16_t port, uint8_t val) + +void +mca_write(uint16_t port, uint8_t val) { - if (mca_index >= mca_nr_cards) - return; - if (mca_card_write[mca_index]) - mca_card_write[mca_index](port, val, mca_priv[mca_index]); + if (mca_index >= mca_nr_cards) + return; + + if (mca_card_write[mca_index]) + mca_card_write[mca_index](port, val, mca_priv[mca_index]); } -void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv) + +void +mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv) { - int c; - - for (c = 0; c < mca_nr_cards; c++) - { - if (!mca_card_read[c] && !mca_card_write[c]) - { - mca_card_read[c] = read; - mca_card_write[c] = write; - mca_priv[c] = priv; - return; - } - } + int c; + + for (c = 0; c < mca_nr_cards; c++) { + if (! mca_card_read[c] && !mca_card_write[c]) { + mca_card_read[c] = read; + mca_card_write[c] = write; + mca_priv[c] = priv; + return; + } + } } diff --git a/src/devices/system/mcr.c b/src/devices/system/mcr.c index 979fd1f..8dcb89a 100644 --- a/src/devices/system/mcr.c +++ b/src/devices/system/mcr.c @@ -10,13 +10,13 @@ * This chip was used as part of many 386 chipsets. * It controls memory addressing and shadowing. * - * Version: @(#)mcr.c 1.0.3 2018/10/05 + * Version: @(#)mcr.c 1.0.4 2019/03/20 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,6 +44,7 @@ #include #include "../../emu.h" #include "../../mem.h" +#include "../../rom.h" int nextreg6; diff --git a/src/devices/system/nvr_at.c b/src/devices/system/nvr_at.c index eec3afd..30dd5e5 100644 --- a/src/devices/system/nvr_at.c +++ b/src/devices/system/nvr_at.c @@ -189,7 +189,7 @@ * including the later update (DS12887A) which implemented a * "century" register to be compatible with Y2K. * - * Version: @(#)nvr_at.c 1.0.12 2019/03/06 + * Version: @(#)nvr_at.c 1.0.14 2019/04/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -232,6 +232,7 @@ #include "../../timer.h" #include "../../device.h" #include "../../nvr.h" +#include "../../plat.h" #include "nmi.h" #include "pic.h" #include "pit.h" @@ -561,8 +562,7 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) } } else { local->addr = (val & (nvr->size - 1)); - if (!(machines[machine].flags & MACHINE_MCA) && - !(machines[machine].flags & MACHINE_NONMI)) + if (!(machine->flags&MACHINE_MCA) && !(machine->flags&MACHINE_NONMI)) nmi_mask = (~val & 0x80); } } @@ -652,7 +652,7 @@ nvr_recalc(nvr_t *nvr) static void * -nvr_at_init(const device_t *info) +nvr_at_init(const device_t *info, UNUSED(void *parent)) { local_t *local; nvr_t *nvr; @@ -665,7 +665,7 @@ nvr_at_init(const device_t *info) nvr->data = local; /* This is machine specific. */ - nvr->size = machines[machine].nvrsz; + nvr->size = machine->nvrsz; switch(info->local) { case 0: /* standard AT (no century register) */ nvr->irq = 8; @@ -728,6 +728,7 @@ const device_t at_nvr_old_device = { "PC/AT NVRAM (No Century)", DEVICE_ISA | DEVICE_AT, 0, + NULL, nvr_at_init, nvr_at_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -737,6 +738,7 @@ const device_t at_nvr_device = { "PC/AT NVRAM", DEVICE_ISA | DEVICE_AT, 1, + NULL, nvr_at_init, nvr_at_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -746,6 +748,7 @@ const device_t ps_nvr_device = { "PS/1 or PS/2 NVRAM", DEVICE_PS2, 2, + NULL, nvr_at_init, nvr_at_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -755,6 +758,7 @@ const device_t amstrad_nvr_device = { "Amstrad NVRAM", DEVICE_ISA | DEVICE_AT, 3, + NULL, nvr_at_init, nvr_at_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/system/nvr_ps2.c b/src/devices/system/nvr_ps2.c index 1d8efca..a095266 100644 --- a/src/devices/system/nvr_ps2.c +++ b/src/devices/system/nvr_ps2.c @@ -8,12 +8,12 @@ * * Handling of the PS/2 series CMOS devices. * - * Version: @(#)nvr_ps2.c 1.0.9 2018/10/24 + * Version: @(#)nvr_ps2.c 1.0.12 2019/04/09 * * Authors: Fred N. van Kempen, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -104,7 +104,7 @@ ps2_nvr_write(uint16_t port, uint8_t val, void *priv) static void * -ps2_nvr_init(const device_t *info) +ps2_nvr_init(const device_t *info, UNUSED(void *parent)) { char temp[128]; ps2_nvr_t *nvr; @@ -147,14 +147,14 @@ ps2_nvr_close(void *priv) } free(nvr->fn); - free(nvr->ram); + free(nvr); } const device_t ps2_nvr_device = { "PS/2 Secondary NVRAM", - 0, 0, + 0, 0, NULL, ps2_nvr_init, ps2_nvr_close, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/system/pci.c b/src/devices/system/pci.c index bcb90f0..fa7980d 100644 --- a/src/devices/system/pci.c +++ b/src/devices/system/pci.c @@ -8,13 +8,13 @@ * * Implement the PCI bus. * - * Version: @(#)pci.c 1.0.10 2018/11/10 + * Version: @(#)pci.c 1.0.11 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,7 +44,6 @@ #define HAVE_STDARG_H #define dbglog pcilog #include "../../emu.h" -#include "../../machines/machine.h" #include "../../cpu/cpu.h" #include "../../io.h" #include "../../mem.h" @@ -74,13 +73,13 @@ typedef struct { #ifdef ENABLE_BUS_LOG int pci_do_log = ENABLE_BUS_LOG; #endif -int pci_burst_time, - pci_nonburst_time; static pci_card_t pci_cards[32]; static uint8_t last_pci_card = 0; static uint8_t pci_card_to_slot_mapping[32]; static uint8_t elcr[2] = { 0, 0 }; +static int pci_burst_time, + pci_nonburst_time; static uint8_t pci_irqs[4]; static uint64_t pci_irq_hold[16]; static pci_mirq_t pci_mirqs[2]; @@ -623,7 +622,7 @@ trc_reset(uint8_t val) pci_reset(); } - resetx86(); + cpu_reset(1); } @@ -687,6 +686,31 @@ pci_init(int type) } +void +pci_set_speed(uint32_t fsb_speed) +{ + uint32_t cpu_speed = cpu_get_speed(); + + if (fsb_speed) { + pci_nonburst_time = (4 * cpu_speed) / fsb_speed; + pci_burst_time = cpu_speed / fsb_speed; + } else { + pci_nonburst_time = 4; + pci_burst_time = 1; + } +} + + +uint32_t +pci_get_speed(int burst) +{ + if (burst) + return(pci_burst_time); + + return(pci_nonburst_time); +} + + void pci_register_slot(int card, int type, int inta, int intb, int intc, int intd) { diff --git a/src/devices/system/pci.h b/src/devices/system/pci.h index ea2e4be..07db1ce 100644 --- a/src/devices/system/pci.h +++ b/src/devices/system/pci.h @@ -8,13 +8,13 @@ * * Definitions for the PCI handler module. * - * Version: @(#)pci.h 1.0.2 2018/09/04 + * Version: @(#)pci.h 1.0.3 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -74,10 +74,6 @@ typedef union { } bar_t; -extern int pci_burst_time, - pci_nonburst_time; - - extern void pci_set_irq_routing(int pci_int, int irq); extern void pci_enable_mirq(int mirq); @@ -94,6 +90,8 @@ extern void pci_clear_irq(uint8_t card, uint8_t pci_int); extern void pci_reset(void); extern void pci_init(int type); +extern void pci_set_speed(uint32_t speed); +extern uint32_t pci_get_speed(int burst); extern void pci_register_slot(int card, int type, int inta, int intb, int intc, int intd); extern void pci_close(void); diff --git a/src/devices/system/pic.c b/src/devices/system/pic.c index 0167030..4d2ac15 100644 --- a/src/devices/system/pic.c +++ b/src/devices/system/pic.c @@ -8,7 +8,7 @@ * * Implementation of Intel 8259 interrupt controller. * - * Version: @(#)pic.c 1.0.6 2019/03/04 + * Version: @(#)pic.c 1.0.7 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,7 +41,6 @@ #include #include #include "../../emu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "pci.h" #include "pic.h" diff --git a/src/devices/system/pit.c b/src/devices/system/pit.c index 2abe24d..9bff6dc 100644 --- a/src/devices/system/pit.c +++ b/src/devices/system/pit.c @@ -6,14 +6,14 @@ * * This file is part of the VARCem Project. * - * Implement the PIT (Programmable Interval Timer.) + * Implement the Intel 8254 PIT (Programmable Interval Timer.) * * 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! * - * Version: @(#)pit.c 1.0.12 2019/02/17 + * Version: @(#)pit.c 1.0.13 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,7 +48,6 @@ #include #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../device.h" #include "../../timer.h" @@ -661,7 +660,7 @@ pit_setclock(uint32_t freq) { uint32_t speed; - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) { + if (cpu_get_type() >= CPU_286) { /* For 286 and up, this is easy. */ cpuclock = (float)freq; PITCONST = cpuclock / 1193182.0; @@ -675,11 +674,11 @@ pit_setclock(uint32_t freq) xt_cpu_multi = 3; /* Get selected CPU's (max) clock rate. */ - speed = machine_speed(1); //FIXME: + speed = cpu_get_speed(); switch (speed) { case 7159092: /* 7.16 MHz */ - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_flags & CPU_ALTERNATE_XTAL) { + if (cpu_get_flags() & CPU_ALTERNATE_XTAL) { cpuclock = 28636368.0; xt_cpu_multi = 4; } else @@ -695,7 +694,7 @@ pit_setclock(uint32_t freq) break; default: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_flags & CPU_ALTERNATE_XTAL) { + if (cpu_get_flags() & CPU_ALTERNATE_XTAL) { cpuclock = 28636368.0; xt_cpu_multi = 6; } diff --git a/src/devices/video/vid_ati18800.c b/src/devices/video/vid_ati18800.c index 790916b..edec8d3 100644 --- a/src/devices/video/vid_ati18800.c +++ b/src/devices/video/vid_ati18800.c @@ -8,7 +8,7 @@ * * ATI 18800 emulation (VGA Edge-16) * - * Version: @(#)vid_ati18800.c 1.0.11 2019/03/03 + * Version: @(#)vid_ati18800.c 1.0.13 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,6 +46,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -204,10 +205,9 @@ static void ati18800_recalctimings(svga_t *svga) static void * -ati18800_init(const device_t *info) +ati18800_init(const device_t *info, UNUSED(void *parent)) { ati18800_t *dev; - const wchar_t *fn = NULL; dev = (ati18800_t *)mem_alloc(sizeof(ati18800_t)); memset(dev, 0x00, sizeof(ati18800_t)); @@ -215,24 +215,21 @@ ati18800_init(const device_t *info) switch (info->local) { #if defined(DEV_BRANCH) && defined(USE_WONDER) case ATI18800_WONDER: - fn = BIOS_ROM_PATH_WONDER; break; #endif case ATI18800_VGA88: - fn = BIOS_ROM_PATH_VGA88; break; case ATI18800_EDGE16: - fn = BIOS_ROM_PATH_EDGE16; break; default: break; }; - if (fn != NULL) { - rom_init(&dev->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, + if (info->path != NULL) { + rom_init(&dev->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); } @@ -248,7 +245,7 @@ ati18800_init(const device_t *info) ati_eeprom_load(&dev->eeprom, L"ati18800.nvr", 0); - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); return dev; @@ -282,36 +279,16 @@ force_redraw(void *priv) } -#if defined(DEV_BRANCH) && defined(USE_WONDER) -static int -ati18800_wonder_available(void) -{ - return rom_present(BIOS_ROM_PATH_WONDER); -} -#endif - -static int -ati18800_vga88_available(void) -{ - return rom_present(BIOS_ROM_PATH_VGA88); -} - -static int -ati18800_available(void) -{ - return rom_present(BIOS_ROM_PATH_EDGE16); -} - - static const video_timings_t ati18800_timing = {VID_ISA,8,16,32,8,16,32}; #if defined(DEV_BRANCH) && defined(USE_WONDER) const device_t ati18800_wonder_device = { "ATI-18800", - DEVICE_ISA | DEVICE_UNSTABLE, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA | DEVICE_UNSTABLE, ATI18800_WONDER, + BIOS_ROM_PATH_WONDER, ati18800_init, ati18800_close, NULL, - ati18800_wonder_available, + NULL, speed_changed, force_redraw, &ati18800_timing, @@ -321,10 +298,11 @@ const device_t ati18800_wonder_device = { const device_t ati18800_vga88_device = { "ATI-18800-1", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, ATI18800_VGA88, + BIOS_ROM_PATH_VGA88, ati18800_init, ati18800_close, NULL, - ati18800_vga88_available, + NULL, speed_changed, force_redraw, &ati18800_timing, @@ -333,10 +311,11 @@ const device_t ati18800_vga88_device = { const device_t ati18800_device = { "ATI-18800-5", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, ATI18800_EDGE16, + BIOS_ROM_PATH_EDGE16, ati18800_init, ati18800_close, NULL, - ati18800_available, + NULL, speed_changed, force_redraw, &ati18800_timing, diff --git a/src/devices/video/vid_ati28800.c b/src/devices/video/vid_ati28800.c index e62bcbf..12e32c7 100644 --- a/src/devices/video/vid_ati28800.c +++ b/src/devices/video/vid_ati28800.c @@ -8,7 +8,7 @@ * * ATI 28800 emulation (VGA Charger and Korean VGA) * - * Version: @(#)vid_ati28800.c 1.0.18 2019/03/03 + * Version: @(#)vid_ati28800.c 1.0.20 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -483,7 +483,7 @@ ati28800k_load_font(svga_t *svga, const wchar_t *fn) static void * -ati28800_init(const device_t *info) +ati28800_init(const device_t *info, UNUSED(void *parent)) { ati28800_t *dev; @@ -495,8 +495,7 @@ ati28800_init(const device_t *info) switch(info->local) { case 0: dev->id = 5; - rom_init(&dev->bios_rom, - BIOS_ROM_PATH, + rom_init(&dev->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); ati_eeprom_load(&dev->eeprom, L"ati28800.nvr", 0); @@ -533,7 +532,7 @@ ati28800_init(const device_t *info) dev->in_get_korean_font_kind_set = 0; dev->ksc5601_mode_enabled = 0; - rom_init(&dev->bios_rom, BIOS_ATIKOR_PATH, + rom_init(&dev->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); ati_eeprom_load(&dev->eeprom, L"atikorvga.nvr", 0); break; @@ -578,7 +577,7 @@ ati28800_init(const device_t *info) } } - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); return(dev); @@ -596,12 +595,6 @@ ati28800_close(void *priv) } -static int -ati28800_available(void) -{ - return(rom_present(BIOS_ROM_PATH)); -} - static int ati28800k_available(void) { @@ -658,12 +651,12 @@ static const device_config_t ati28800_config[] = { "1 MB", 1024 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -682,12 +675,12 @@ static const device_config_t ati28800_wonderxl_config[] = { "1 MB", 1024 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; #endif @@ -696,10 +689,11 @@ static const device_config_t ati28800_wonderxl_config[] = { static const video_timings_t ati28800_timing = {VID_ISA,3,3,6,5,5,10}; const device_t ati28800_device = { "ATI-28800", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 0, + BIOS_ROM_PATH, ati28800_init, ati28800_close, NULL, - ati28800_available, + NULL, speed_changed, force_redraw, &ati28800_timing, @@ -709,8 +703,9 @@ const device_t ati28800_device = { static const video_timings_t ati28800k_timing = {VID_ISA,3,3,6,5,5,10}; const device_t ati28800k_device = { "ATI Korean VGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, VID_ATIKOREANVGA, + BIOS_ATIKOR_PATH, ati28800_init, ati28800_close, NULL, ati28800k_available, speed_changed, @@ -722,8 +717,9 @@ const device_t ati28800k_device = { static const video_timings_t ati28800_compaq_timing = {VID_ISA,3,3,6,5,5,10}; const device_t ati28800_compaq_device = { "Compaq ATI-28800", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, VID_VGAWONDERXL, + NULL, ati28800_init, ati28800_close, NULL, ati28800_compaq_available, speed_changed, @@ -736,8 +732,9 @@ const device_t ati28800_compaq_device = { static const video_timings_t ati28800w_timing = {VID_ISA,3,3,6,5,5,10}; const device_t ati28800_wonderxl24_device = { "ATI-28800 (VGA Wonder XL24)", - DEVICE_ISA | DEVICE_UNSTABLE, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA | DEVICE_UNSTABLE, VID_VGAWONDERXL24, + NULL, ati28800_init, ati28800_close, NULL, ati28800_wonderxl24_available, speed_changed, diff --git a/src/devices/video/vid_ati68860_ramdac.c b/src/devices/video/vid_ati68860_ramdac.c index 1833da2..60d6cd9 100644 --- a/src/devices/video/vid_ati68860_ramdac.c +++ b/src/devices/video/vid_ati68860_ramdac.c @@ -28,13 +28,13 @@ * 7 If set can remove "snow" in some cases * (A860_Delay_L ?) ?? * - * Version: @(#)vid_ati68860.c 1.0.4 2018/10/05 + * Version: @(#)vid_ati68860.c 1.0.6 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -64,6 +64,7 @@ #include "../../emu.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -244,7 +245,7 @@ ati68860_set_ramdac_type(ati68860_ramdac_t *dev, int type) static void * -ati68860_init(const device_t *info) +ati68860_init(const device_t *info, UNUSED(void *parent)) { ati68860_ramdac_t *dev; @@ -269,8 +270,7 @@ ati68860_close(void *priv) const device_t ati68860_ramdac_device = { "ATi-68860 RAMDAC", - 0, - 0, + 0, 0, NULL, ati68860_init, ati68860_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_ati_mach64.c b/src/devices/video/vid_ati_mach64.c index ef89211..b9e3b49 100644 --- a/src/devices/video/vid_ati_mach64.c +++ b/src/devices/video/vid_ati_mach64.c @@ -8,7 +8,7 @@ * * ATi Mach64 graphics card emulation. * - * Version: @(#)vid_ati_mach64.c 1.0.16 2019/03/07 + * Version: @(#)vid_ati_mach64.c 1.0.18 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -3305,7 +3305,9 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p) } } -static void *mach64_common_init(const device_t *info) + +static void * +mach64_common_init(const device_t *info) { mach64_t *mach64 = (mach64_t *)mem_alloc(sizeof(mach64_t)); memset(mach64, 0, sizeof(mach64_t)); @@ -3349,13 +3351,15 @@ static void *mach64_common_init(const device_t *info) mach64->fifo_not_full_event = thread_create_event(); mach64->fifo_thread = thread_create(fifo_thread, mach64); - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); return mach64; } -static void *mach64gx_init(const device_t *info) + +static void * +mach64gx_init(const device_t *info, UNUSED(void *parent)) { mach64_t *mach64 = (mach64_t *)mach64_common_init(info); @@ -3373,15 +3377,18 @@ static void *mach64gx_init(const device_t *info) ati_eeprom_load(&mach64->eeprom, L"mach64.nvr", 1); if (info->flags & DEVICE_PCI) - rom_init(&mach64->bios_rom, BIOS_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&mach64->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); else if (info->flags & DEVICE_VLB) - rom_init(&mach64->bios_rom, BIOS_VLB_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&mach64->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); else if (info->flags & DEVICE_ISA) - rom_init(&mach64->bios_rom, BIOS_ISA_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&mach64->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); return mach64; } -static void *mach64vt2_init(const device_t *info) + + +static void * +mach64vt2_init(const device_t *info, UNUSED(void *parent)) { mach64_t *mach64 = (mach64_t *)mach64_common_init(info); svga_t *svga = &mach64->svga; @@ -3396,31 +3403,16 @@ static void *mach64vt2_init(const device_t *info) ati_eeprom_load(&mach64->eeprom, L"mach64vt.nvr", 1); - rom_init(&mach64->bios_rom, BIOS_ROMVT2_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&mach64->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); svga->vblank_start = mach64_vblank_start; return mach64; } -int mach64gx_available(void) -{ - return rom_present(BIOS_ROM_PATH); -} -int mach64gx_isa_available(void) -{ - return rom_present(BIOS_ISA_ROM_PATH); -} -int mach64gx_vlb_available(void) -{ - return rom_present(BIOS_VLB_ROM_PATH); -} -int mach64vt2_available(void) -{ - return rom_present(BIOS_ROMVT2_PATH); -} -void mach64_close(void *p) +static void +mach64_close(void *p) { mach64_t *mach64 = (mach64_t *)p; @@ -3433,14 +3425,18 @@ void mach64_close(void *p) free(mach64); } -void mach64_speed_changed(void *p) + +static void +mach64_speed_changed(void *p) { mach64_t *mach64 = (mach64_t *)p; svga_recalctimings(&mach64->svga); } -void mach64_force_redraw(void *p) + +static void +mach64_force_redraw(void *p) { mach64_t *mach64 = (mach64_t *)p; @@ -3463,12 +3459,12 @@ static const device_config_t mach64gx_config[] = "4 MB", 4 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -3484,12 +3480,12 @@ static const device_config_t mach64vt2_config[] = "4 MB", 4 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -3497,10 +3493,11 @@ static const device_config_t mach64vt2_config[] = static const video_timings_t mach64gx_isa_timing = {VID_ISA,3,3,6,5,5,10}; const device_t mach64gx_isa_device = { "ATI Mach64GX", - DEVICE_AT | DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_AT | DEVICE_ISA, 0, + BIOS_ISA_ROM_PATH, mach64gx_init, mach64_close, NULL, - mach64gx_isa_available, + NULL, mach64_speed_changed, mach64_force_redraw, &mach64gx_isa_timing, @@ -3510,10 +3507,11 @@ const device_t mach64gx_isa_device = { static const video_timings_t mach64gx_vlb_timing = {VID_BUS,2,2,1,20,20,21}; const device_t mach64gx_vlb_device = { "ATI Mach64GX", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, 0, + BIOS_VLB_ROM_PATH, mach64gx_init, mach64_close, NULL, - mach64gx_vlb_available, + NULL, mach64_speed_changed, mach64_force_redraw, &mach64gx_vlb_timing, @@ -3523,10 +3521,11 @@ const device_t mach64gx_vlb_device = { static const video_timings_t mach64gx_pci_timing = {VID_BUS,2,2,1,20,20,21}; const device_t mach64gx_pci_device = { "ATI Mach64GX", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, 0, + BIOS_ROM_PATH, mach64gx_init, mach64_close, NULL, - mach64gx_available, + NULL, mach64_speed_changed, mach64_force_redraw, &mach64gx_pci_timing, @@ -3536,10 +3535,11 @@ const device_t mach64gx_pci_device = { static const video_timings_t mach64vt2_timing = {VID_BUS,2,2,1,20,20,21}; const device_t mach64vt2_device = { "ATI Mach64VT2", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, 0, + BIOS_ROMVT2_PATH, mach64vt2_init, mach64_close, NULL, - mach64vt2_available, + NULL, mach64_speed_changed, mach64_force_redraw, &mach64vt2_timing, diff --git a/src/devices/video/vid_att20c49x_ramdac.c b/src/devices/video/vid_att20c49x_ramdac.c index b89084d..1af8c38 100644 --- a/src/devices/video/vid_att20c49x_ramdac.c +++ b/src/devices/video/vid_att20c49x_ramdac.c @@ -8,7 +8,7 @@ * * Emulation of a AT&T 20c490/491 and 492/493 RAMDAC. * - * Version: @(#)vid_att20c49x_ramdac.c 1.0.1 2019/01/12 + * Version: @(#)vid_att20c49x_ramdac.c 1.0.3 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include "../../emu.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_att20c49x_ramdac.h" @@ -139,7 +140,7 @@ att49x_ramdac_in(uint16_t addr, att49x_ramdac_t *ramdac, svga_t *svga) static void * -att49x_ramdac_init(const device_t *info) +att49x_ramdac_init(const device_t *info, UNUSED(void *parent)) { att49x_ramdac_t *dev; @@ -166,6 +167,7 @@ const device_t att490_ramdac_device = { "AT&T 20c490/20c491 RAMDAC", 0, ATT_490_1, + NULL, att49x_ramdac_init, att49x_ramdac_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -175,6 +177,7 @@ const device_t att492_ramdac_device = { "AT&T 20c492/20c493 RAMDAC", 0, ATT_492_3, + NULL, att49x_ramdac_init, att49x_ramdac_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_av9194.c b/src/devices/video/vid_av9194.c index a7a1c4f..fb6d837 100644 --- a/src/devices/video/vid_av9194.c +++ b/src/devices/video/vid_av9194.c @@ -8,7 +8,7 @@ * * AV9194 clock generator emulation.. * - * Version: @(#)vid_av9194.c 1.0.1 2019/01/12 + * Version: @(#)vid_av9194.c 1.0.3 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include "../../emu.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_av9194.h" @@ -116,17 +117,16 @@ av9194_getclock(int clock, void *priv) static void * -av9194_init(const device_t *info) +av9194_init(const device_t *info, UNUSED(void *parent)) { /* Return something non-NULL. */ - return (void *)&av9194_device; + return (void *)info; } const device_t av9194_device = { "AV9194 Clock Generator", - 0, - 0, + 0, 0, NULL, av9194_init, NULL, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_bt48x_ramdac.c b/src/devices/video/vid_bt48x_ramdac.c index 76cf451..3ce319d 100644 --- a/src/devices/video/vid_bt48x_ramdac.c +++ b/src/devices/video/vid_bt48x_ramdac.c @@ -8,7 +8,7 @@ * * Brooktree Bt48x series true color RAMDAC emulation. * - * Version: @(#)vid_bt48x_ramdac.c 1.0.11 2019/03/07 + * Version: @(#)vid_bt48x_ramdac.c 1.0.14 2019/04/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include "../../emu.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_bt48x_ramdac.h" @@ -207,7 +208,7 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *d break; case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ - indx = svga->dac_addr & 0x03ff; + indx = svga->dac_addr & da_mask; if ((dev->type >= BT485) && (svga->hwcursor.xsize == 64)) cd = (uint8_t *) dev->cursor64_data; else { @@ -215,7 +216,6 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *d cd = (uint8_t *) dev->cursor32_data; } cd[indx] = val; - svga->dac_addr++; svga->dac_addr = (svga->dac_addr + 1) & da_mask; break; @@ -239,8 +239,6 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *d svga->hwcursor.y = dev->hwc_y - svga->hwcursor.ysize; break; } - - return; } @@ -429,22 +427,22 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) y_pos = displine + y_add; x_pos = offset + 32 + x_add; - p = &screen->line[y_pos][0]; + p = &screen->line[y_pos][x_pos]; if (offset >= svga->hwcursor_latch.x) { switch (mode) { case 1: /* Three Color */ switch (comb) { case 1: - p[x_pos].val = clr1; + p->val = clr1; break; case 2: - p[x_pos].val = clr2; + p->val = clr2; break; case 3: - p[x_pos].val = clr3; + p->val = clr3; break; } break; @@ -452,15 +450,15 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) case 2: /* PM/Windows */ switch (comb) { case 0: - p[x_pos].val = clr1; + p->val = clr1; break; case 1: - p[x_pos].val = clr2; + p->val = clr2; break; case 3: - p[x_pos].val ^= 0xffffff; + p->val ^= 0xffffff; break; } break; @@ -468,11 +466,11 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) case 3: /* X-Windows */ switch (comb) { case 2: - p[x_pos].val = clr1; + p->val = clr1; break; case 3: - p[x_pos].val = clr2; + p->val = clr2; break; } break; @@ -490,9 +488,8 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) } - static void * -bt48x_init(const device_t *info) +bt48x_init(const device_t *info, UNUSED(void *parent)) { bt48x_ramdac_t *dev; @@ -547,6 +544,7 @@ const device_t bt484_ramdac_device = { "Brooktree Bt484 RAMDAC", 0, BT484, + NULL, bt48x_init, bt48x_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -556,6 +554,7 @@ const device_t att20c504_ramdac_device = { "AT&T 20c504 RAMDAC", 0, ATT20C504, + NULL, bt48x_init, bt48x_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -565,6 +564,7 @@ const device_t bt485_ramdac_device = { "Brooktree Bt485 RAMDAC", 0, BT485, + NULL, bt48x_init, bt48x_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -574,6 +574,7 @@ const device_t att20c505_ramdac_device = { "AT&T 20c505 RAMDAC", 0, ATT20C505, + NULL, bt48x_init, bt48x_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -583,6 +584,7 @@ const device_t bt485a_ramdac_device = { "Brooktree Bt485A RAMDAC", 0, BT485A, + NULL, bt48x_init, bt48x_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_cga.c b/src/devices/video/vid_cga.c index 572ec11..3289787 100644 --- a/src/devices/video/vid_cga.c +++ b/src/devices/video/vid_cga.c @@ -8,7 +8,7 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.c 1.0.14 2019/03/08 + * Version: @(#)vid_cga.c 1.0.16 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -49,6 +49,7 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pit.h" #include "video.h" #include "vid_cga.h" @@ -170,7 +171,7 @@ cga_out(uint16_t port, uint8_t val, void *priv) old = dev->cgamode; dev->cgamode = val; if (old ^ val) { - if ((old ^ val) & 0x05) + if (((old ^ val) & 0x05) && dev->cpriv) cga_comp_update(dev->cpriv, val); cga_recalctimings(dev); } @@ -607,6 +608,7 @@ void cga_init(cga_t *dev) { dev->composite = 0; + if (dev->cpriv != NULL) { cga_comp_close(dev->cpriv); dev->cpriv = NULL; @@ -614,49 +616,6 @@ cga_init(cga_t *dev) } -void * -cga_standalone_init(const device_t *info) -{ - int display_type; - cga_t *dev; - - dev = (cga_t *)mem_alloc(sizeof(cga_t)); - memset(dev, 0x00, sizeof(cga_t)); - - display_type = device_get_config_int("display_type"); - dev->composite = (display_type != CGA_RGB); - dev->revision = device_get_config_int("composite_type"); - dev->snow_enabled = device_get_config_int("snow_enabled"); - dev->font_type = device_get_config_int("font_type"); - dev->rgb_type = device_get_config_int("rgb_type"); - - dev->vram = (uint8_t *)mem_alloc(0x4000); - - dev->cpriv = cga_comp_init(dev->revision); - - timer_add(cga_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); - - mem_map_add(&dev->mapping, 0xb8000, 0x08000, - cga_read,NULL,NULL, cga_write,NULL,NULL, - dev->vram, MEM_MAPPING_EXTERNAL, dev); - - io_sethandler(0x03d0, 16, - cga_in,NULL,NULL, cga_out,NULL,NULL, dev); - - overscan_x = overscan_y = 16; - - cga_palette = (dev->rgb_type << 1); - video_palette_rebuild(); - - video_load_font(CGA_FONT_ROM_PATH, - (dev->font_type) ? FONT_CGA_THICK : FONT_CGA_THIN); - - video_inform(VID_TYPE_CGA, info->vid_timing); - - return dev; -} - - void cga_close(void *priv) { @@ -680,6 +639,53 @@ cga_speed_changed(void *priv) } +static void * +cga_standalone_init(const device_t *info, UNUSED(void *parent)) +{ + int display_type; + cga_t *dev; + + dev = (cga_t *)mem_alloc(sizeof(cga_t)); + memset(dev, 0x00, sizeof(cga_t)); + + cga_init(dev); + + display_type = device_get_config_int("display_type"); + dev->composite = (display_type != CGA_RGB); + dev->revision = device_get_config_int("composite_type"); + dev->snow_enabled = device_get_config_int("snow_enabled"); + dev->font_type = device_get_config_int("font_type"); + dev->rgb_type = device_get_config_int("rgb_type"); + + dev->vram = (uint8_t *)mem_alloc(0x4000); + + if (dev->composite) + dev->cpriv = cga_comp_init(dev->revision); + + timer_add(cga_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + mem_map_add(&dev->mapping, 0xb8000, 0x08000, + cga_read,NULL,NULL, cga_write,NULL,NULL, + dev->vram, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03d0, 16, + cga_in,NULL,NULL, cga_out,NULL,NULL, dev); + + overscan_x = overscan_y = 16; + + cga_palette = (dev->rgb_type << 1); + video_palette_rebuild(); + + video_load_font(CGA_FONT_ROM_PATH, + (dev->font_type) ? FONT_CGA_THICK : FONT_CGA_THIN); + + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); + + return(dev); +} + + const device_config_t cga_config[] = { { "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, @@ -691,7 +697,7 @@ const device_config_t cga_config[] = { "Composite", CGA_COMPOSITE }, { - "" + NULL } } }, @@ -705,7 +711,7 @@ const device_config_t cga_config[] = { "New", COMPOSITE_NEW }, { - "" + NULL } } }, @@ -728,7 +734,7 @@ const device_config_t cga_config[] = { "Color (no brown)", 4 }, { - "" + NULL } } }, @@ -742,7 +748,7 @@ const device_config_t cga_config[] = { "Thick", 1 }, { - "" + NULL } } }, @@ -750,14 +756,16 @@ const device_config_t cga_config[] = { "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 }, { - "", "", -1 + NULL } }; const device_t cga_device = { "CGA", - DEVICE_ISA, 0, + DEVICE_VIDEO(VID_TYPE_CGA) | DEVICE_ISA, + 0, + NULL, cga_standalone_init, cga_close, NULL, NULL, cga_speed_changed, diff --git a/src/devices/video/vid_cga_compaq.c b/src/devices/video/vid_cga_compaq.c index a23600b..2bb9728 100644 --- a/src/devices/video/vid_cga_compaq.c +++ b/src/devices/video/vid_cga_compaq.c @@ -8,7 +8,7 @@ * * Implementation of CGA used by Compaq PC's. * - * Version: @(#)vid_cga_compaq.c 1.0.7 2019/03/07 + * Version: @(#)vid_cga_compaq.c 1.0.9 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,6 +48,7 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pit.h" #include "video.h" #include "vid_cga.h" @@ -360,7 +361,7 @@ compaq_poll(void *priv) static void * -compaq_cga_init(const device_t *info) +compaq_cga_init(const device_t *info, UNUSED(void *parent)) { compaq_cga_t *dev; int c, display_type; @@ -416,9 +417,10 @@ compaq_cga_init(const device_t *info) cga_palette = (dev->cga.rgb_type << 1); video_palette_rebuild(); - video_inform(VID_TYPE_CGA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); - return dev; + return(dev); } @@ -453,7 +455,9 @@ static const video_timings_t cga_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t cga_compaq_device = { "Compaq CGA", - DEVICE_ISA, 0, + DEVICE_VIDEO(VID_TYPE_CGA) | DEVICE_ISA, + 0, + NULL, compaq_cga_init, compaq_cga_close, NULL, NULL, speed_changed, @@ -464,7 +468,9 @@ const device_t cga_compaq_device = { const device_t cga_compaq2_device = { "Compaq CGA 2", - DEVICE_ISA, 1, + DEVICE_VIDEO(VID_TYPE_CGA) | DEVICE_ISA, + 1, + NULL, compaq_cga_init, compaq_cga_close, NULL, NULL, speed_changed, diff --git a/src/devices/video/vid_cl54xx.c b/src/devices/video/vid_cl54xx.c index 3daebb3..78355d4 100644 --- a/src/devices/video/vid_cl54xx.c +++ b/src/devices/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, 5430, 5434 and 5436 are supported). * - * Version: @(#)vid_cl54xx.c 1.0.26 2019/03/07 + * Version: @(#)vid_cl54xx.c 1.0.28 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -52,6 +52,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pci.h" #include "video.h" #include "vid_svga.h" @@ -1059,20 +1060,24 @@ hwcursor_draw(svga_t *svga, int displine) b0 = (dat[0] >> (7 - xx)) & 1; b1 = (dat[1] >> (7 - xx)) & 1; comb = (b1 | (b0 << 1)); + if (offset >= svga->hwcursor_latch.x) { switch(comb) { case 0: /* The original screen pixel is shown (invisible cursor) */ break; + case 1: /* The pixel is shown in the cursor background color */ screen->line[displine + y_add][offset + 32 + x_add].val = bgcol; break; + case 2: /* The pixel is shown as the inverse of the original screen pixel (XOR cursor) */ screen->line[displine + y_add][offset + 32 + x_add].val ^= 0xffffff; break; + case 3: /* The pixel is shown in the cursor foreground color */ screen->line[displine + y_add][offset + 32 + x_add].val = fgcol; @@ -1082,6 +1087,7 @@ hwcursor_draw(svga_t *svga, int displine) offset++; } + svga->hwcursor_latch.addr++; } @@ -2481,12 +2487,12 @@ cl_pci_write(int func, int addr, uint8_t val, void *priv) static void * -gd54xx_init(const device_t *info) +gd54xx_init(const device_t *info, UNUSED(void *parent)) { gd54xx_t *dev = (gd54xx_t *)mem_alloc(sizeof(gd54xx_t)); svga_t *svga = &dev->svga; int id = info->local & 0xff; - wchar_t *romfn = NULL; + const wchar_t *romfn = info->path; int vram; memset(dev, 0x00, sizeof(gd54xx_t)); @@ -2498,16 +2504,13 @@ gd54xx_init(const device_t *info) switch (id) { case CIRRUS_ID_CLGD5402: case CIRRUS_ID_CLGD5420: - romfn = BIOS_GD5420_PATH; break; case CIRRUS_ID_CLGD5422: case CIRRUS_ID_CLGD5424: - romfn = BIOS_GD5422_PATH; break; case CIRRUS_ID_CLGD5426: - romfn = BIOS_GD5426_PATH; break; case CIRRUS_ID_CLGD5428: @@ -2518,15 +2521,12 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5429: - romfn = BIOS_GD5429_PATH; break; case CIRRUS_ID_CLGD5434: - romfn = BIOS_GD5434_PATH; break; case CIRRUS_ID_CLGD5436: - romfn = BIOS_GD5436_PATH; break; case CIRRUS_ID_CLGD5430: @@ -2555,7 +2555,6 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5480: - romfn = BIOS_GD5480_PATH; break; } @@ -2633,9 +2632,10 @@ gd54xx_init(const device_t *info) svga->crtc[0x27] = id; - video_inform(VID_TYPE_SPEC, (const video_timings_t *)info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); - return dev; + return(dev); } @@ -2668,91 +2668,6 @@ gd54xx_force_redraw(void *priv) } -static int -gd5420_available(void) -{ - return rom_present(BIOS_GD5420_PATH); -} - -static int -gd5422_available(void) -{ - return rom_present(BIOS_GD5422_PATH); -} - -static int -gd5426_available(void) -{ - return rom_present(BIOS_GD5426_PATH); -} - -static int -gd5428_available(void) -{ - return rom_present(BIOS_GD5428_VLB_PATH); -} - -static int -gd5428_isa_available(void) -{ - return rom_present(BIOS_GD5428_ISA_PATH); -} - -static int -gd5429_available(void) -{ - return rom_present(BIOS_GD5429_PATH); -} - -static int -gd5430_vlb_available(void) -{ - return rom_present(BIOS_GD5430_VLB_PATH); -} - -static int -gd5430_pci_available(void) -{ - return rom_present(BIOS_GD5430_PCI_PATH); -} - -static int -gd5434_available(void) -{ - return rom_present(BIOS_GD5434_PATH); -} - -static int -gd5436_available(void) -{ - return rom_present(BIOS_GD5436_PATH); -} - -static int -gd5440_available(void) -{ - return rom_present(BIOS_GD5440_PATH); -} - -static int -gd5446_available(void) -{ - return rom_present(BIOS_GD5446_PATH); -} - -static int -gd5446_stb_available(void) -{ - return rom_present(BIOS_GD5446_STB_PATH); -} - -static int -gd5480_available(void) -{ - return rom_present(BIOS_GD5480_PATH); -} - - static const device_config_t gd5422_config[] = { { @@ -2765,12 +2680,12 @@ static const device_config_t gd5422_config[] = "1 MB",1 }, { - "" + NULL } }, }, { - "","",-1 + NULL } }; @@ -2786,12 +2701,12 @@ static const device_config_t gd5428_config[] = "2 MB",2 }, { - "" + NULL } }, }, { - "","",-1 + NULL } }; @@ -2807,12 +2722,12 @@ static const device_config_t gd5440_onboard_config[] = "2 MB",2 }, { - "" + NULL } }, }, { - "","",-1 + NULL } }; @@ -2828,12 +2743,12 @@ static const device_config_t gd5434_config[] = "4 MB",4 }, { - "" + NULL } }, }, { - "","",-1 + NULL } }; @@ -2843,10 +2758,11 @@ static const video_timings_t cl_gd_pci_timing = {VID_BUS,4,4,8,10,10,20}; const device_t gd5402_isa_device = { "Cirrus Logic GD-5402 (ACUMOS AVGA2)", - DEVICE_AT | DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5402, + BIOS_GD5420_PATH, /* Common BIOS between 5402 and 5420 */ gd54xx_init, gd54xx_close, NULL, - gd5420_available, /* Common BIOS between 5402 and 5420 */ + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_isa_timing, @@ -2855,10 +2771,11 @@ const device_t gd5402_isa_device = { const device_t gd5420_isa_device = { "Cirrus Logic GD-5420", - DEVICE_AT | DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5420, + BIOS_GD5420_PATH, /* Common BIOS between 5402 and 5420 */ gd54xx_init, gd54xx_close, NULL, - gd5420_available, /* Common BIOS between 5402 and 5420 */ + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_isa_timing, @@ -2867,10 +2784,11 @@ const device_t gd5420_isa_device = { const device_t gd5422_isa_device = { "Cirrus Logic GD-5422", - DEVICE_AT | DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5422, + BIOS_GD5422_PATH, /* Common BIOS between 5422 and 5424 */ gd54xx_init, gd54xx_close, NULL, - gd5422_available, /* Common BIOS between 5422 and 5424 */ + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_isa_timing, @@ -2879,10 +2797,11 @@ const device_t gd5422_isa_device = { const device_t gd5424_vlb_device = { "Cirrus Logic GD-5424", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, CIRRUS_ID_CLGD5424, + BIOS_GD5422_PATH, /* Common BIOS between 5422 and 5424 */ gd54xx_init, gd54xx_close, NULL, - gd5422_available, /* Common BIOS between 5422 and 5424 */ + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_vlb_timing, @@ -2891,10 +2810,11 @@ const device_t gd5424_vlb_device = { const device_t gd5426_vlb_device = { "Cirrus Logic GD-5426", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, CIRRUS_ID_CLGD5426, + BIOS_GD5426_PATH, gd54xx_init, gd54xx_close, NULL, - gd5426_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_vlb_timing, @@ -2903,10 +2823,11 @@ const device_t gd5426_vlb_device = { const device_t gd5428_isa_device = { "Cirrus Logic GD-5428", - DEVICE_AT | DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5428, + BIOS_GD5428_ISA_PATH, gd54xx_init, gd54xx_close, NULL, - gd5428_isa_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_isa_timing, @@ -2915,10 +2836,11 @@ const device_t gd5428_isa_device = { const device_t gd5428_vlb_device = { "Cirrus Logic GD-5428", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, CIRRUS_ID_CLGD5428, + BIOS_GD5428_VLB_PATH, gd54xx_init, gd54xx_close, NULL, - gd5428_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_vlb_timing, @@ -2927,10 +2849,11 @@ const device_t gd5428_vlb_device = { const device_t gd5429_isa_device = { "Cirrus Logic GD-5429", - DEVICE_AT | DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5429, + BIOS_GD5429_PATH, gd54xx_init, gd54xx_close, NULL, - gd5429_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_isa_timing, @@ -2939,10 +2862,11 @@ const device_t gd5429_isa_device = { const device_t gd5429_vlb_device = { "Cirrus Logic GD-5429", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, CIRRUS_ID_CLGD5429, + BIOS_GD5429_PATH, gd54xx_init, gd54xx_close, NULL, - gd5429_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_vlb_timing, @@ -2951,10 +2875,11 @@ const device_t gd5429_vlb_device = { const device_t gd5430_vlb_device = { "Cirrus Logic GD-5430", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, CIRRUS_ID_CLGD5430, + BIOS_GD5430_VLB_PATH, gd54xx_init, gd54xx_close, NULL, - gd5430_vlb_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_vlb_timing, @@ -2963,10 +2888,11 @@ const device_t gd5430_vlb_device = { const device_t gd5430_pci_device = { "Cirrus Logic GD-5430", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, CIRRUS_ID_CLGD5430, + BIOS_GD5430_PCI_PATH, gd54xx_init, gd54xx_close, NULL, - gd5430_pci_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_pci_timing, @@ -2975,10 +2901,11 @@ const device_t gd5430_pci_device = { const device_t gd5434_isa_device = { "Cirrus Logic GD-5434", - DEVICE_AT | DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5434, + BIOS_GD5434_PATH, gd54xx_init, gd54xx_close, NULL, - gd5434_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_isa_timing, @@ -2987,10 +2914,11 @@ const device_t gd5434_isa_device = { const device_t gd5434_vlb_device = { "Cirrus Logic GD-5434", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, CIRRUS_ID_CLGD5434, + BIOS_GD5434_PATH, gd54xx_init, gd54xx_close, NULL, - gd5434_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_vlb_timing, @@ -2999,10 +2927,11 @@ const device_t gd5434_vlb_device = { const device_t gd5434_pci_device = { "Cirrus Logic GD-5434", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, CIRRUS_ID_CLGD5434, + BIOS_GD5434_PATH, gd54xx_init, gd54xx_close, NULL, - gd5434_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_pci_timing, @@ -3011,20 +2940,35 @@ const device_t gd5434_pci_device = { const device_t gd5436_pci_device = { "Cirrus Logic GD-5436", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, CIRRUS_ID_CLGD5436, + BIOS_GD5436_PATH, gd54xx_init, gd54xx_close, NULL, - gd5436_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_pci_timing, gd5434_config }; +const device_t gd5440_pci_device = { + "Cirrus Logic GD-5440", + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, + CIRRUS_ID_CLGD5440 | 0x400, + BIOS_GD5440_PATH, + gd54xx_init, gd54xx_close, NULL, + NULL, + gd54xx_speed_changed, + gd54xx_force_redraw, + &cl_gd_pci_timing, + gd5428_config +}; + const device_t gd5440_onboard_pci_device = { "Onboard Cirrus Logic GD-5440", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, CIRRUS_ID_CLGD5440 | 0x600, + NULL, gd54xx_init, gd54xx_close, NULL, NULL, gd54xx_speed_changed, @@ -3033,24 +2977,13 @@ const device_t gd5440_onboard_pci_device = { gd5440_onboard_config }; -const device_t gd5440_pci_device = { - "Cirrus Logic GD-5440", - DEVICE_PCI, - CIRRUS_ID_CLGD5440 | 0x400, - gd54xx_init, gd54xx_close, NULL, - gd5440_available, - gd54xx_speed_changed, - gd54xx_force_redraw, - &cl_gd_pci_timing, - gd5428_config -}; - const device_t gd5446_pci_device = { "Cirrus Logic GD-5446", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, CIRRUS_ID_CLGD5446, + BIOS_GD5446_PATH, gd54xx_init, gd54xx_close, NULL, - gd5446_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_pci_timing, @@ -3059,10 +2992,11 @@ const device_t gd5446_pci_device = { const device_t gd5446_stb_pci_device = { "STB Nitro 64V", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, CIRRUS_ID_CLGD5446 | 0x100, + BIOS_GD5446_STB_PATH, gd54xx_init, gd54xx_close, NULL, - gd5446_stb_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_pci_timing, @@ -3071,10 +3005,11 @@ const device_t gd5446_stb_pci_device = { const device_t gd5480_pci_device = { "Cirrus Logic GD-5480", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, CIRRUS_ID_CLGD5480, + BIOS_GD5480_PATH, gd54xx_init, gd54xx_close, NULL, - gd5480_available, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, &cl_gd_pci_timing, diff --git a/src/devices/video/vid_colorplus.c b/src/devices/video/vid_colorplus.c index 7f205f6..e979bd4 100644 --- a/src/devices/video/vid_colorplus.c +++ b/src/devices/video/vid_colorplus.c @@ -8,7 +8,7 @@ * * Plantronics ColorPlus emulation. * - * Version: @(#)vid_colorplus.c 1.0.11 2019/03/07 + * Version: @(#)vid_colorplus.c 1.0.13 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,6 +48,7 @@ #include "../../mem.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pit.h" #include "../ports/parallel.h" #include "video.h" @@ -373,7 +374,7 @@ colorplus_poll(void *priv) static void * -colorplus_init(const device_t *info) +colorplus_init(const device_t *info, UNUSED(void *parent)) { colorplus_t *dev; int display_type; @@ -399,7 +400,8 @@ colorplus_init(const device_t *info) io_sethandler(0x03d0, 16, colorplus_in,NULL,NULL, colorplus_out,NULL,NULL, dev); - video_inform(VID_TYPE_CGA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); /* Force the LPT3 port to be enabled. */ parallel_enabled[2] = 1; @@ -443,7 +445,7 @@ static const device_config_t colorplus_config[] = { "Composite", CGA_COMPOSITE }, { - "" + NULL } } }, @@ -457,7 +459,7 @@ static const device_config_t colorplus_config[] = { "New", COMPOSITE_NEW }, { - "" + NULL } } }, @@ -465,7 +467,7 @@ static const device_config_t colorplus_config[] = { "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 }, { - "", "", -1 + NULL } }; @@ -473,8 +475,9 @@ static const video_timings_t colorplus_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t colorplus_device = { "Plantronics ColorPlus", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_CGA) | DEVICE_ISA, 0, + NULL, colorplus_init, colorplus_close, NULL, NULL, speed_changed, diff --git a/src/devices/video/vid_ega.c b/src/devices/video/vid_ega.c index 6557b8b..f93ff2d 100644 --- a/src/devices/video/vid_ega.c +++ b/src/devices/video/vid_ega.c @@ -9,7 +9,7 @@ * Emulation of the EGA, Chips & Technologies SuperEGA, and * AX JEGA graphics cards. * - * Version: @(#)vid_ega.c 1.0.11 2019/03/07 + * Version: @(#)vid_ega.c 1.0.13 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -49,6 +49,7 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pit.h" #include "video.h" #include "vid_ega.h" @@ -1040,10 +1041,9 @@ speed_changed(void *priv) static void * -ega_standalone_init(const device_t *info) +ega_standalone_init(const device_t *info, UNUSED(void *parent)) { ega_t *dev; - const wchar_t *fn = NULL; uint8_t temp; int c; @@ -1053,25 +1053,8 @@ ega_standalone_init(const device_t *info) overscan_x = 16; overscan_y = 28; - switch(info->local) { - case EGA_IBM: - fn = BIOS_IBM_PATH; - break; - - case EGA_COMPAQ: - fn = BIOS_CPQ_PATH; - break; - - case EGA_SUPEREGA: - fn = BIOS_SEGA_PATH; - break; - - default: - break; - } - - if (fn != NULL) { - rom_init(&dev->bios_rom, fn, + if (info->path != NULL) { + rom_init(&dev->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (dev->bios_rom.rom[0x3ffe] == 0xaa && @@ -1099,7 +1082,7 @@ ega_standalone_init(const device_t *info) io_sethandler(0x03a0, 0x0040, ega_in,NULL,NULL, ega_out,NULL,NULL, dev); - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); return dev; @@ -1204,7 +1187,7 @@ LoadFontxFile(wchar_t *fname) static void * -jega_standalone_init(const device_t *info) +jega_standalone_init(const device_t *info, UNUSED(void *parent)) { ega_t *dev = (ega_t *)ega_standalone_init(info); @@ -1218,25 +1201,6 @@ jega_standalone_init(const device_t *info) #endif -static int -ega_standalone_available(void) -{ - return rom_present(BIOS_IBM_PATH); -} - -static int -cpqega_standalone_available(void) -{ - return rom_present(BIOS_CPQ_PATH); -} - -static int -sega_standalone_available(void) -{ - return rom_present(BIOS_SEGA_PATH); -} - - /* * SW1 SW2 SW3 SW4 * OFF OFF ON OFF Monochrome (5151) 1011 0x0b @@ -1262,7 +1226,7 @@ static const device_config_t ega_config[] = { "256 KB", 256 }, { - "" + NULL } } }, @@ -1294,12 +1258,12 @@ static const device_config_t ega_config[] = { "Enhanced Color - Enhanced Mode (5154/ECD)", 0x09 }, { - "" + NULL } } }, { - "","",-1 + NULL } }; @@ -1307,10 +1271,11 @@ static const device_config_t ega_config[] = { static const video_timings_t ega_timing = {VID_ISA,8,16,32,8,16,32}; const device_t ega_device = { "EGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, EGA_IBM, + BIOS_CPQ_PATH, ega_standalone_init, ega_close, NULL, - ega_standalone_available, + NULL, speed_changed, NULL, &ega_timing, @@ -1320,10 +1285,11 @@ const device_t ega_device = { static const video_timings_t ega_compaq_timing = {VID_ISA,8,16,32,8,16,32}; const device_t ega_compaq_device = { "Compaq EGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, EGA_COMPAQ, + BIOS_CPQ_PATH, ega_standalone_init, ega_close, NULL, - cpqega_standalone_available, + NULL, speed_changed, NULL, &ega_compaq_timing, @@ -1333,10 +1299,11 @@ const device_t ega_compaq_device = { static const video_timings_t sega_timing = {VID_ISA,8,16,32,8,16,32}; const device_t sega_device = { "SuperEGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, EGA_SUPEREGA, + BIOS_SEGA_PATH, ega_standalone_init, ega_close, NULL, - sega_standalone_available, + NULL, speed_changed, NULL, &sega_timing, @@ -1346,10 +1313,11 @@ const device_t sega_device = { #ifdef JEGA const device_t jega_device = { "AX JEGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, EGA_SUPEREGA, + NULL, ega_standalone_init, ega_close, NULL, - sega_standalone_available, //FIXME: check JEGA roms/fonts?? --FvK + jega_standalone_available, //FIXME: check JEGA roms/fonts?? --FvK speed_changed, NULL, &sega_timing, //FIXME: check these?? --FvK diff --git a/src/devices/video/vid_et4000.c b/src/devices/video/vid_et4000.c index ad80a61..8abc1f3 100644 --- a/src/devices/video/vid_et4000.c +++ b/src/devices/video/vid_et4000.c @@ -8,7 +8,7 @@ * * Emulation of the Tseng Labs ET4000. * - * Version: @(#)vid_et4000.c 1.0.14 2019/03/03 + * Version: @(#)vid_et4000.c 1.0.16 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,6 +47,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "../system/mca.h" #include "video.h" #include "vid_svga.h" @@ -474,16 +475,14 @@ et4000_mca_write(int port, uint8_t val, void *priv) static void * -et4000_init(const device_t *info) +et4000_init(const device_t *info, UNUSED(void *parent)) { - const wchar_t *fn; et4000_t *dev; dev = (et4000_t *)mem_alloc(sizeof(et4000_t)); memset(dev, 0x00, sizeof(et4000_t)); dev->name = info->name; dev->type = info->local; - fn = BIOS_ROM_PATH; switch(dev->type) { case 0: /* ISA ET4000AX */ @@ -538,7 +537,6 @@ et4000_init(const device_t *info) et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); io_sethandler(0x32cb, 1, et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); - fn = KOREAN_BIOS_ROM_PATH; break; } @@ -546,12 +544,12 @@ et4000_init(const device_t *info) dev->vram_mask = dev->vram_size - 1; - rom_init(&dev->bios_rom, fn, + rom_init(&dev->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); DEBUG("VIDEO: %s (vram=%iKB)\n", dev->name, dev->vram_size>>10); - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); return(dev); @@ -570,7 +568,7 @@ et4000_close(void *priv) static void -et4000_speed_changed(void *priv) +speed_changed(void *priv) { et4000_t *dev = (et4000_t *)priv; @@ -579,7 +577,7 @@ et4000_speed_changed(void *priv) static void -et4000_force_redraw(void *priv) +force_redraw(void *priv) { et4000_t *dev = (et4000_t *)priv; @@ -587,13 +585,6 @@ et4000_force_redraw(void *priv) } -static int -et4000_available(void) -{ - return rom_present(BIOS_ROM_PATH); -} - - static int et4000k_available(void) { @@ -602,28 +593,27 @@ et4000k_available(void) } -static const device_config_t et4000_config[] = -{ +static const device_config_t et4000_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 1024, { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, { - { - "256 KB", 256 - }, - { - "512 KB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + "1 MB", 1024 + }, + { + NULL } - }, - { - "", "", -1 } + }, + { + NULL + } }; static const video_timings_t et4000ax_isa_timing = {VID_ISA,3,3,6,5,5,10}; @@ -632,48 +622,52 @@ static const video_timings_t et4000ax_mca_timing = {VID_MCA,4,5,10,5,5,10}; const device_t et4000_isa_device = { "Tseng Labs ET4000AX", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 0, + BIOS_ROM_PATH, et4000_init, et4000_close, NULL, - et4000_available, - et4000_speed_changed, - et4000_force_redraw, + NULL, + speed_changed, + force_redraw, &et4000ax_isa_timing, et4000_config }; const device_t et4000_mca_device = { "Tseng Labs ET4000AX", - DEVICE_MCA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_MCA, 1, + BIOS_ROM_PATH, et4000_init, et4000_close, NULL, - et4000_available, - et4000_speed_changed, - et4000_force_redraw, + NULL, + speed_changed, + force_redraw, &et4000ax_mca_timing, et4000_config }; const device_t et4000k_isa_device = { "Tseng Labs ET4000AX (Korean)", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 2, + KOREAN_BIOS_ROM_PATH, et4000_init, et4000_close, NULL, et4000k_available, - et4000_speed_changed, - et4000_force_redraw, + speed_changed, + force_redraw, &et4000ax_isa_timing, et4000_config }; const device_t et4000k_tg286_isa_device = { "Trigem Korean VGA (Trigem 286M)", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 3, + KOREAN_BIOS_ROM_PATH, et4000_init, et4000_close, NULL, et4000k_available, - et4000_speed_changed, - et4000_force_redraw, + speed_changed, + force_redraw, &et4000ax_isa_timing, et4000_config }; diff --git a/src/devices/video/vid_et4000w32.c b/src/devices/video/vid_et4000w32.c index 04b642e..62a974f 100644 --- a/src/devices/video/vid_et4000w32.c +++ b/src/devices/video/vid_et4000w32.c @@ -12,7 +12,7 @@ * * FIXME: Note the madness on line 1163, fix that somehow? --FvK * - * Version: @(#)vid_et4000w32.c 1.0.17 2010/03/07 + * Version: @(#)vid_et4000w32.c 1.0.19 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1234,7 +1234,7 @@ static void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) static void * -et4000w32p_init(const device_t *info) +et4000w32p_init(const device_t *info, UNUSED(void *parent)) { int vram_size; et4000w32p_t *et4000 = (et4000w32p_t *)mem_alloc(sizeof(et4000w32p_t)); @@ -1258,20 +1258,19 @@ et4000w32p_init(const device_t *info) switch(et4000->type) { case ET4000W32_CARDEX: - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; break; case ET4000W32_DIAMOND: - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_DIAMOND, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); et4000->svga.clock_gen = device_add(&icd2061_device); et4000->svga.getclock = icd2061_getclock; break; } + rom_init(&et4000->bios_rom, info->path, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (info->flags & DEVICE_PCI) mem_map_disable(&et4000->bios_rom.mapping); @@ -1309,7 +1308,7 @@ et4000w32p_init(const device_t *info) et4000->fifo_not_full_event = thread_create_event(); et4000->fifo_thread = thread_create(fifo_thread, et4000); - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); return et4000; @@ -1332,7 +1331,7 @@ et4000w32p_close(void *p) static void -et4000w32p_speed_changed(void *p) +speed_changed(void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -1341,7 +1340,7 @@ et4000w32p_speed_changed(void *p) static void -et4000w32p_force_redraw(void *p) +force_redraw(void *p) { et4000w32p_t *et4000w32p = (et4000w32p_t *)p; @@ -1349,38 +1348,24 @@ et4000w32p_force_redraw(void *p) } -static int -et4000w32p_available(void) -{ - return rom_present(BIOS_ROM_PATH_DIAMOND); -} - -static int -et4000w32p_cardex_available(void) -{ - return rom_present(BIOS_ROM_PATH_CARDEX); -} - - -static const device_config_t et4000w32p_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t et4000w32p_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 2, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + NULL + } + } + }, + { + NULL + } }; static const video_timings_t et4000w32p_pci_timing = {VID_BUS,4,4,4,10,10,10}; @@ -1389,48 +1374,52 @@ static const video_timings_t et4000w32p_vlb_timing = {VID_BUS,4,4,4,10,10,10}; const device_t et4000w32p_cardex_vlb_device = { "Tseng Labs ET4000/w32p (Cardex)", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, ET4000W32_CARDEX, + BIOS_ROM_PATH_CARDEX, et4000w32p_init, et4000w32p_close, NULL, - et4000w32p_cardex_available, - et4000w32p_speed_changed, - et4000w32p_force_redraw, + NULL, + speed_changed, + force_redraw, &et4000w32p_vlb_timing, et4000w32p_config }; const device_t et4000w32p_cardex_pci_device = { "Tseng Labs ET4000/w32p (Cardex)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, ET4000W32_CARDEX, + BIOS_ROM_PATH_CARDEX, et4000w32p_init, et4000w32p_close, NULL, - et4000w32p_cardex_available, - et4000w32p_speed_changed, - et4000w32p_force_redraw, + NULL, + speed_changed, + force_redraw, &et4000w32p_pci_timing, et4000w32p_config }; const device_t et4000w32p_vlb_device = { "Tseng Labs ET4000/w32p (Diamond)", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, ET4000W32_DIAMOND, + BIOS_ROM_PATH_DIAMOND, et4000w32p_init, et4000w32p_close, NULL, - et4000w32p_available, - et4000w32p_speed_changed, - et4000w32p_force_redraw, + NULL, + speed_changed, + force_redraw, &et4000w32p_vlb_timing, et4000w32p_config }; const device_t et4000w32p_pci_device = { "Tseng Labs ET4000/w32p (Diamond)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, ET4000W32_DIAMOND, + BIOS_ROM_PATH_DIAMOND, et4000w32p_init, et4000w32p_close, NULL, - et4000w32p_available, - et4000w32p_speed_changed, - et4000w32p_force_redraw, + NULL, + speed_changed, + force_redraw, &et4000w32p_pci_timing, et4000w32p_config }; diff --git a/src/devices/video/vid_genius.c b/src/devices/video/vid_genius.c index 24108b3..4e93ec7 100644 --- a/src/devices/video/vid_genius.c +++ b/src/devices/video/vid_genius.c @@ -63,7 +63,7 @@ * reducing the height of characters so they fit in an 8x12 cell * if necessary. * - * Version: @(#)vid_genius.c 1.0.10 2019/03/07 + * Version: @(#)vid_genius.c 1.0.12 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -585,7 +585,7 @@ load_font(genius_t *dev, const wchar_t *s) static void * -genius_init(const device_t *info) +genius_init(const device_t *info, UNUSED(void *parent)) { genius_t *dev; int c; @@ -599,7 +599,7 @@ genius_init(const device_t *info) return(NULL); } - /* 160k video RAM */ + /* 160K video RAM */ dev->vram = (uint8_t *)mem_alloc(0x28000); timer_add(genius_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); @@ -655,9 +655,10 @@ genius_init(const device_t *info) dev->enabled = 1; dev->genius_charh = 0x90; /* Native character height register */ - video_inform(VID_TYPE_MDA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); - return dev; + return(dev); } @@ -671,13 +672,6 @@ genius_close(void *priv) } -static int -genius_available(void) -{ - return rom_present(FONT_ROM_PATH); -} - - static void speed_changed(void *priv) { @@ -691,9 +685,11 @@ static const video_timings_t genius_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t genius_device = { "Genius VHR", - DEVICE_ISA, 0, + DEVICE_VIDEO(VID_TYPE_MDA) | DEVICE_ISA, + 0, + FONT_ROM_PATH, genius_init, genius_close, NULL, - genius_available, + NULL, speed_changed, NULL, &genius_timings, diff --git a/src/devices/video/vid_hercules.c b/src/devices/video/vid_hercules.c index 4c07590..a7ea823 100644 --- a/src/devices/video/vid_hercules.c +++ b/src/devices/video/vid_hercules.c @@ -8,7 +8,7 @@ * * Hercules emulation. * - * Version: @(#)vid_hercules.c 1.0.15 2019/03/07 + * Version: @(#)vid_hercules.c 1.0.17 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,6 +48,7 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pit.h" #include "../ports/parallel.h" #include "video.h" @@ -426,7 +427,7 @@ hercules_poll(void *priv) static void * -hercules_init(const device_t *info) +hercules_init(const device_t *info, UNUSED(void *parent)) { hercules_t *dev; int c; @@ -483,7 +484,8 @@ hercules_init(const device_t *info) cga_palette = 0; video_palette_rebuild(); - video_inform(VID_TYPE_MDA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); /* Force the LPT3 port to be enabled. */ parallel_enabled[2] = 1; @@ -534,7 +536,7 @@ static const device_config_t hercules_config[] = { "Gray", 3 }, { - "" + NULL } } }, @@ -542,7 +544,7 @@ static const device_config_t hercules_config[] = { "blend", "Blend", CONFIG_BINARY, "", 1 }, { - "", "", -1 + NULL } }; @@ -550,8 +552,9 @@ static const video_timings_t hercules_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t hercules_device = { "Hercules", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_MDA) | DEVICE_ISA, 0, + NULL, hercules_init, hercules_close, NULL, NULL, speed_changed, diff --git a/src/devices/video/vid_herculesplus.c b/src/devices/video/vid_herculesplus.c index 09df897..84b4ac7 100644 --- a/src/devices/video/vid_herculesplus.c +++ b/src/devices/video/vid_herculesplus.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_hercules_plus.c 1.0.16 2019/03/07 + * Version: @(#)vid_hercules_plus.c 1.0.18 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,6 +47,7 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pit.h" #include "../ports/parallel.h" #include "video.h" @@ -636,7 +637,7 @@ herculesplus_poll(void *priv) static void * -herculesplus_init(const device_t *info) +herculesplus_init(const device_t *info, UNUSED(void *parent)) { herculesplus_t *dev; int c; @@ -687,7 +688,8 @@ herculesplus_init(const device_t *info) dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = 16; - video_inform(VID_TYPE_MDA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); /* Force the LPT3 port to be enabled. */ parallel_enabled[2] = 1; @@ -739,7 +741,7 @@ static const device_config_t herculesplus_config[] = { "Gray", 3 }, { - "" + NULL } } }, @@ -747,7 +749,7 @@ static const device_config_t herculesplus_config[] = { "blend", "Blend", CONFIG_BINARY, "", 1 }, { - "", "", -1 + NULL } }; @@ -756,8 +758,9 @@ static const video_timings_t herculesplus_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t herculesplus_device = { "Hercules Plus", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_MDA) | DEVICE_ISA, 0, + NULL, herculesplus_init, herculesplus_close, NULL, NULL, speed_changed, diff --git a/src/devices/video/vid_icd2061.c b/src/devices/video/vid_icd2061.c index bed113b..b09b3ff 100644 --- a/src/devices/video/vid_icd2061.c +++ b/src/devices/video/vid_icd2061.c @@ -12,12 +12,12 @@ * but without the need for tuning (which is irrelevant in * emulation anyway). * - * Version: @(#)vid_icd2061.c 1.0.4 2018/10/05 + * Version: @(#)vid_icd2061.c 1.0.6 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -45,6 +45,7 @@ #include #include "../../emu.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_icd2061.h" @@ -132,7 +133,7 @@ icd2061_getclock(int clock, void *priv) static void * -icd2061_init(const device_t *info) +icd2061_init(const device_t *info, UNUSED(void *parent)) { icd2061_t *dev = (icd2061_t *)mem_alloc(sizeof(icd2061_t)); memset(dev, 0x00, sizeof(icd2061_t)); @@ -157,8 +158,7 @@ icd2061_close(void *priv) const device_t icd2061_device = { "ICD2061 Clock Generator", - 0, - 0, + 0, 0, NULL, icd2061_init, icd2061_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -166,8 +166,7 @@ const device_t icd2061_device = { const device_t ics9161_device = { "ICS9161 Clock Generator", - 0, - 0, + 0, 0, NULL, icd2061_init, icd2061_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_ics2595.c b/src/devices/video/vid_ics2595.c index 0fcedb5..95d0640 100644 --- a/src/devices/video/vid_ics2595.c +++ b/src/devices/video/vid_ics2595.c @@ -8,13 +8,13 @@ * * ICS2595 clock chip emulation. Used by ATI Mach64. * - * Version: @(#)vid_ics2595.c 1.0.3 2018/10/05 + * Version: @(#)vid_ics2595.c 1.0.5 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -43,6 +43,7 @@ #include #include "../../emu.h" #include "../../device.h" +#include "../../plat.h" #include "vid_ics2595.h" @@ -95,7 +96,7 @@ ics2595_write(ics2595_t *dev, int strobe, int dat) static void * -ics2595_init(const device_t *info) +ics2595_init(const device_t *info, UNUSED(void *parent)) { ics2595_t *dev = (ics2595_t *)mem_alloc(sizeof(ics2595_t)); memset(dev, 0x00, sizeof(ics2595_t)); @@ -116,8 +117,7 @@ ics2595_close(void *priv) const device_t ics2595_device = { "ICS2595 clock chip", - 0, - 0, + 0, 0, NULL, ics2595_init, ics2595_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_im1024.c b/src/devices/video/vid_im1024.c index 0597121..4dad5b3 100644 --- a/src/devices/video/vid_im1024.c +++ b/src/devices/video/vid_im1024.c @@ -38,7 +38,7 @@ * This is implemented by holding a FIFO of unlimited depth in * the IM1024 to receive the data. * - * Version: @(#)vid_im1024.c 1.0.3 2019/03/03 + * Version: @(#)vid_im1024.c 1.0.4 2019/04/19 * * Authors: Fred N. van Kempen, * John Elliott, @@ -76,8 +76,8 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" -#include "../system/pit.h" #include "../../plat.h" +#include "../system/pit.h" #include "video.h" #include "vid_pgc.h" @@ -158,12 +158,14 @@ input_byte(pgc_t *pgc, uint8_t *result) im1024_t *dev = (im1024_t *)pgc; /* If input buffer empty, wait for it to fill. */ - while ((dev->fifo_wrptr == dev->fifo_rdptr) && - (pgc->mapram[0x300] == pgc->mapram[0x301])) { + while (!pgc->stopped && ((dev->fifo_wrptr == dev->fifo_rdptr) && + (pgc->mapram[0x300] == pgc->mapram[0x301]))) { pgc->waiting_input_fifo = 1; pgc_sleep(pgc); } + if (pgc->stopped) return(0); + if (pgc->mapram[0x3ff]) { /* Reset triggered. */ pgc_reset(pgc); @@ -932,7 +934,7 @@ static const pgc_cmd_t im1024_commands[] = { static void * -im1024_init(const device_t *info) +im1024_init(const device_t *info, UNUSED(void *parent)) { im1024_t *dev; @@ -952,7 +954,8 @@ im1024_init(const device_t *info) mem_map_set_handler(&dev->pgc.mapping, im1024_read,NULL,NULL, im1024_write,NULL,NULL); - video_inform(VID_TYPE_CGA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); return(dev); } @@ -969,15 +972,6 @@ im1024_close(void *priv) } -#if 0 -static int -im1024_available(void) -{ - return rom_present(BIOS_ROM_PATH); -} -#endif - - static void speed_changed(void *priv) { @@ -991,15 +985,16 @@ static const video_timings_t im1024_timings = { VID_ISA,8,16,32,8,16,32 }; static const device_config_t im1024_config[] = { { - "", "", -1 + NULL } }; const device_t im1024_device = { "ImageManager 1024", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_CGA) | DEVICE_ISA, 0, + NULL, im1024_init, im1024_close, NULL, NULL, speed_changed, diff --git a/src/devices/video/vid_incolor.c b/src/devices/video/vid_incolor.c index 90f4b07..5a05789 100644 --- a/src/devices/video/vid_incolor.c +++ b/src/devices/video/vid_incolor.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.14 2019/03/07 + * Version: @(#)vid_incolor.c 1.0.16 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,6 +47,7 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pit.h" #include "../ports/parallel.h" #include "video.h" @@ -979,7 +980,7 @@ incolor_poll(void *priv) static void * -incolor_init(const device_t *info) +incolor_init(const device_t *info, UNUSED(void *parent)) { incolor_t *dev; int c; @@ -1011,13 +1012,14 @@ incolor_init(const device_t *info) dev->palette[c] = defpal[c]; dev->palette_idx = 0; - video_inform(VID_TYPE_MDA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); /* Force the LPT3 port to be enabled. */ parallel_enabled[2] = 1; parallel_setup(2, 0x03bc); - return dev; + return(dev); } @@ -1049,8 +1051,9 @@ static const video_timings_t incolor_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t incolor_device = { "Hercules InColor", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_MDA) | DEVICE_ISA, 0, + NULL, incolor_init, incolor_close, NULL, NULL, speed_changed, diff --git a/src/devices/video/vid_mda.c b/src/devices/video/vid_mda.c index d06d76e..5303de0 100644 --- a/src/devices/video/vid_mda.c +++ b/src/devices/video/vid_mda.c @@ -8,7 +8,7 @@ * * MDA emulation. * - * Version: @(#)vid_mda.c 1.0.11 2019/03/09 + * Version: @(#)vid_mda.c 1.0.13 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,6 +47,7 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" +#include "../../plat.h" #include "../system/pit.h" #include "../ports/parallel.h" #include "video.h" @@ -342,22 +343,11 @@ mda_init(mda_t *dev) if (cga_palette > 6) cga_palette = 0; video_palette_rebuild(); - - timer_add(mda_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); - - mem_map_add(&dev->mapping, 0xb0000, 0x08000, - mda_read,NULL,NULL, mda_write,NULL,NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); - - io_sethandler(0x03b0, 16, - mda_in,NULL,NULL, mda_out,NULL,NULL, dev); - - video_inform(VID_TYPE_MDA, &mda_timings); } static void * -mda_standalone_init(const device_t *info) +mda_standalone_init(const device_t *info, UNUSED(void *parent)) { mda_t *dev; @@ -369,6 +359,18 @@ mda_standalone_init(const device_t *info) mda_init(dev); + mem_map_add(&dev->mapping, 0xb0000, 0x08000, + mda_read,NULL,NULL, mda_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03b0, 16, + mda_in,NULL,NULL, mda_out,NULL,NULL, dev); + + timer_add(mda_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)&mda_timings); + /* Force the LPT3 port to be enabled. */ parallel_enabled[2] = 1; parallel_setup(2, 0x03bc); @@ -414,19 +416,20 @@ const device_config_t mda_config[] = { "Gray", 3 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; const device_t mda_device = { "MDA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_MDA) | DEVICE_ISA, 0, + NULL, mda_standalone_init, mda_close, NULL, NULL, speed_changed, diff --git a/src/devices/video/vid_oak_oti.c b/src/devices/video/vid_oak_oti.c index 93b9cf3..37c2a78 100644 --- a/src/devices/video/vid_oak_oti.c +++ b/src/devices/video/vid_oak_oti.c @@ -8,13 +8,13 @@ * * Oak OTI037C/67/077 emulation. * - * Version: @(#)vid_oak_oti.c 1.0.14 2018/10/08 + * Version: @(#)vid_oak_oti.c 1.0.16 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -46,6 +46,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" @@ -375,10 +376,9 @@ force_redraw(void *priv) static void * -oti_init(const device_t *info) +oti_init(const device_t *info, UNUSED(void *parent)) { oti_t *dev; - wchar_t *fn; dev = (oti_t *)mem_alloc(sizeof(oti_t)); memset(dev, 0x00, sizeof(oti_t)); @@ -386,10 +386,8 @@ oti_init(const device_t *info) dev->dipswitch_val = 0x18; - fn = NULL; switch(dev->chip_id) { case OTI_037C: - fn = BIOS_037C_PATH; dev->vram_size = 256; /* @@ -400,12 +398,6 @@ oti_init(const device_t *info) break; case OTI_067: -#ifdef BIOS_067_PATH - fn = BIOS_067_PATH; -#else - fn = BIOS_077_PATH; -#endif - dev->vram_size = device_get_config_int("memory"); /* @@ -435,7 +427,6 @@ oti_init(const device_t *info) break; case OTI_077: - fn = BIOS_077_PATH; dev->vram_size = device_get_config_int("memory"); /* @@ -449,8 +440,8 @@ oti_init(const device_t *info) break; } - if (fn != NULL) - rom_init(&dev->bios_rom, fn, + if (info->path) + rom_init(&dev->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); dev->vram_mask = (dev->vram_size << 10) - 1; @@ -466,7 +457,7 @@ oti_init(const device_t *info) dev->svga.miscout = 1; - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); return(dev); @@ -484,90 +475,67 @@ oti_close(void *priv) } -static int -oti037c_available(void) -{ - return(rom_present(BIOS_037C_PATH)); -} - -static int -oti067_available(void) -{ -#ifdef BIOS_67_PATH - return(rom_present(BIOS_067_PATH)); -#else - return(rom_present(BIOS_077_PATH)); -#endif -} - -static int -oti077_available(void) -{ - return(rom_present(BIOS_077_PATH)); -} - - static const device_config_t oti067_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 512, { - "memory", "Memory size", CONFIG_SELECTION, "", 512, { - { - "256 KB", 256 - }, - { - "512 KB", 512 - }, - { - "" - } + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + NULL } - }, - { - "", "", -1 } + }, + { + NULL + } }; static const device_config_t oti067_onboard_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 256, { - "memory", "Memory size", CONFIG_SELECTION, "", 256, { - { - "256 KB", 256 - }, - { - "512 KB", 512 - }, - { - "" - } + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + NULL } - }, - { - "", "", -1 } + }, + { + NULL + } }; static const device_config_t oti077_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 1024, { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, { - { - "256 KB", 256 - }, - { - "512 KB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + "1 MB", 1024 + }, + { + NULL } - }, - { - "", "", -1 } + }, + { + NULL + } }; static const video_timings_t oti_timing = {VID_ISA,6,8,16,6,8,16}; @@ -575,10 +543,11 @@ static const video_timings_t oti_timing = {VID_ISA,6,8,16,6,8,16}; const device_t oti037c_device = { "Oak OTI-037C", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, OTI_037C, + BIOS_037C_PATH, oti_init, oti_close, NULL, - oti037c_available, + NULL, speed_changed, force_redraw, &oti_timing, @@ -587,10 +556,15 @@ const device_t oti037c_device = { const device_t oti067_device = { "Oak OTI-067", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, OTI_067, +#ifdef BIOS_67_PATH + BIOS_067_PATH, +#else + BIOS_077_PATH, +#endif oti_init, oti_close, NULL, - oti067_available, + NULL, speed_changed, force_redraw, &oti_timing, @@ -599,8 +573,9 @@ const device_t oti067_device = { const device_t oti067_onboard_device = { "Onboard Oak OTI-067", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, OTI_067_AMA932J, + NULL, oti_init, oti_close, NULL, NULL, speed_changed, @@ -611,10 +586,11 @@ const device_t oti067_onboard_device = { const device_t oti077_device = { "Oak OTI-077", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, OTI_077, + BIOS_077_PATH, oti_init, oti_close, NULL, - oti077_available, + NULL, speed_changed, force_redraw, &oti_timing, diff --git a/src/devices/video/vid_paradise.c b/src/devices/video/vid_paradise.c index 325197f..a2461c3 100644 --- a/src/devices/video/vid_paradise.c +++ b/src/devices/video/vid_paradise.c @@ -13,13 +13,13 @@ * NOTE: The MegaPC video device should be moved to the MegaPC * machine file. * - * Version: @(#)vid_paradise.c 1.0.8 2018/10/08 + * Version: @(#)vid_paradise.c 1.0.10 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -51,6 +51,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -265,323 +266,369 @@ static void paradise_remap(paradise_t *paradise) } } -static void paradise_recalctimings(svga_t *svga) + +static void +paradise_recalctimings(svga_t *svga) { - paradise_t *paradise = (paradise_t *) svga->p; + paradise_t *paradise = (paradise_t *) svga->p; - if (paradise->type == WD90C30) - svga->interlace = (svga->crtc[0x2d] & 0x20); + if (paradise->type == WD90C30) + svga->interlace = (svga->crtc[0x2d] & 0x20); - svga->lowres = !(svga->gdcreg[0xe] & 0x01); - if (svga->bpp == 8 && !svga->lowres) - svga->render = svga_render_8bpp_highres; + svga->lowres = !(svga->gdcreg[0xe] & 0x01); + if (svga->bpp == 8 && !svga->lowres) + svga->render = svga_render_8bpp_highres; } -static void paradise_write(uint32_t addr, uint8_t val, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; - svga_write_linear(addr, val, ¶dise->svga); -} -static void paradise_writew(uint32_t addr, uint16_t val, void *p) +static void +paradise_write(uint32_t addr, uint8_t val, void *p) { - paradise_t *paradise = (paradise_t *)p; - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; - svga_writew_linear(addr, val, ¶dise->svga); + paradise_t *paradise = (paradise_t *)p; + + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + + svga_write_linear(addr, val, ¶dise->svga); } -static uint8_t paradise_read(uint32_t addr, void *p) + +static void +paradise_writew(uint32_t addr, uint16_t val, void *p) { - paradise_t *paradise = (paradise_t *)p; - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; - return svga_read_linear(addr, ¶dise->svga); -} -static uint16_t paradise_readw(uint32_t addr, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; - return svga_readw_linear(addr, ¶dise->svga); + paradise_t *paradise = (paradise_t *)p; + + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + svga_writew_linear(addr, val, ¶dise->svga); } -static void *paradise_pvga1a_init(const device_t *info, uint32_t memsize) + +static uint8_t +paradise_read(uint32_t addr, void *p) { - paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); - svga_t *svga = ¶dise->svga; - memset(paradise, 0, sizeof(paradise_t)); - - io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + paradise_t *paradise = (paradise_t *)p; - svga_init(¶dise->svga, paradise, memsize, /*256kb*/ - NULL, - paradise_in, paradise_out, - NULL, - NULL); + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; - mem_map_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); - mem_map_set_p(¶dise->svga.mapping, paradise); - - svga->crtc[0x31] = 'W'; - svga->crtc[0x32] = 'D'; - svga->crtc[0x33] = '9'; - svga->crtc[0x34] = '0'; - svga->crtc[0x35] = 'C'; - - svga->bpp = 8; - svga->miscout = 1; - - paradise->type = PVGA1A; - - video_inform(VID_TYPE_SPEC, - (const video_timings_t *)info->vid_timing); - - return paradise; + return svga_read_linear(addr, ¶dise->svga); } -static void *paradise_wd90c11_init(const device_t *info) + +static uint16_t +paradise_readw(uint32_t addr, void *p) { - paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); - svga_t *svga = ¶dise->svga; - memset(paradise, 0, sizeof(paradise_t)); - - io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + paradise_t *paradise = (paradise_t *)p; - svga_init(¶dise->svga, paradise, 1 << 19, /*512kb*/ - paradise_recalctimings, - paradise_in, paradise_out, - NULL, - NULL); + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; - mem_map_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); - mem_map_set_p(¶dise->svga.mapping, paradise); - - svga->crtc[0x31] = 'W'; - svga->crtc[0x32] = 'D'; - svga->crtc[0x33] = '9'; - svga->crtc[0x34] = '0'; - svga->crtc[0x35] = 'C'; - svga->crtc[0x36] = '1'; - svga->crtc[0x37] = '1'; - - svga->bpp = 8; - svga->miscout = 1; - - paradise->type = WD90C11; - - video_inform(VID_TYPE_SPEC, - (const video_timings_t *)info->vid_timing); - - return paradise; + return svga_readw_linear(addr, ¶dise->svga); } -static void *paradise_wd90c30_init(const device_t *info, uint32_t memsize) + +static paradise_t * +pvga1a_init(const device_t *info, uint32_t memsize) { - paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); - svga_t *svga = ¶dise->svga; - memset(paradise, 0, sizeof(paradise_t)); + paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); + svga_t *svga = ¶dise->svga; + + memset(paradise, 0, sizeof(paradise_t)); - io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + io_sethandler(0x03c0, 0x0020, + paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); - svga_init(¶dise->svga, paradise, memsize, - paradise_recalctimings, - paradise_in, paradise_out, - NULL, - NULL); + svga_init(¶dise->svga, paradise, memsize, /*256kb*/ + NULL, + paradise_in, paradise_out, + NULL, NULL); - mem_map_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); - mem_map_set_p(¶dise->svga.mapping, paradise); - - svga->crtc[0x31] = 'W'; - svga->crtc[0x32] = 'D'; - svga->crtc[0x33] = '9'; - svga->crtc[0x34] = '0'; - svga->crtc[0x35] = 'C'; - svga->crtc[0x36] = '3'; - svga->crtc[0x37] = '0'; - - svga->bpp = 8; - svga->miscout = 1; + mem_map_set_handler(¶dise->svga.mapping, + paradise_read, paradise_readw, NULL, + paradise_write, paradise_writew, NULL); + mem_map_set_p(¶dise->svga.mapping, paradise); - paradise->type = WD90C11; - - video_inform(VID_TYPE_SPEC, - (const video_timings_t *)info->vid_timing); + svga->crtc[0x31] = 'W'; + svga->crtc[0x32] = 'D'; + svga->crtc[0x33] = '9'; + svga->crtc[0x34] = '0'; + svga->crtc[0x35] = 'C'; - return paradise; + svga->bpp = 8; + svga->miscout = 1; + + paradise->type = PVGA1A; + + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); + + return paradise; } -static void *paradise_pvga1a_pc2086_init(const device_t *info) + +static paradise_t * +wd90c11_init(const device_t *info) { - paradise_t *paradise = (paradise_t *)paradise_pvga1a_init(info, 1 << 18); + paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); + svga_t *svga = ¶dise->svga; + + memset(paradise, 0, sizeof(paradise_t)); - if (paradise) - rom_init(¶dise->bios_rom, L"machines/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + io_sethandler(0x03c0, 0x0020, + paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + + svga_init(¶dise->svga, paradise, 1 << 19, /*512kb*/ + paradise_recalctimings, + paradise_in, paradise_out, + NULL, + NULL); + + mem_map_set_handler(¶dise->svga.mapping, + paradise_read, paradise_readw, NULL, + paradise_write, paradise_writew, NULL); + mem_map_set_p(¶dise->svga.mapping, paradise); + + svga->crtc[0x31] = 'W'; + svga->crtc[0x32] = 'D'; + svga->crtc[0x33] = '9'; + svga->crtc[0x34] = '0'; + svga->crtc[0x35] = 'C'; + svga->crtc[0x36] = '1'; + svga->crtc[0x37] = '1'; + + svga->bpp = 8; + svga->miscout = 1; + + paradise->type = WD90C11; + + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); + + return paradise; +} + + +static paradise_t * +wd90c30_init(const device_t *info, uint32_t memsize) +{ + paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); + svga_t *svga = ¶dise->svga; + + memset(paradise, 0, sizeof(paradise_t)); + + io_sethandler(0x03c0, 0x0020, + paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + + svga_init(¶dise->svga, paradise, memsize, + paradise_recalctimings, + paradise_in, paradise_out, + NULL, + NULL); + + mem_map_set_handler(¶dise->svga.mapping, + paradise_read, paradise_readw, NULL, + paradise_write, paradise_writew, NULL); + mem_map_set_p(¶dise->svga.mapping, paradise); + + svga->crtc[0x31] = 'W'; + svga->crtc[0x32] = 'D'; + svga->crtc[0x33] = '9'; + svga->crtc[0x34] = '0'; + svga->crtc[0x35] = 'C'; + svga->crtc[0x36] = '3'; + svga->crtc[0x37] = '0'; + + svga->bpp = 8; + svga->miscout = 1; + + paradise->type = WD90C11; + + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); + + return paradise; +} + + +static void * +pvga1a_pc2086_init(const device_t *info, UNUSED(void *parent)) +{ + paradise_t *paradise = pvga1a_init(info, 1 << 18); + + if (paradise) + rom_init(¶dise->bios_rom, info->path, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - return paradise; + return paradise; } -static void *paradise_pvga1a_pc3086_init(const device_t *info) -{ - paradise_t *paradise = (paradise_t *)paradise_pvga1a_init(info, 1 << 18); - if (paradise) - rom_init(¶dise->bios_rom, L"machines/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + +static void * +pvga1a_pc3086_init(const device_t *info, UNUSED(void *parent)) +{ + paradise_t *paradise = pvga1a_init(info, 1 << 18); + + if (paradise) + rom_init(¶dise->bios_rom, info->path, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - return paradise; + return paradise; } -static void *paradise_pvga1a_standalone_init(const device_t *info) + +static void * +pvga1a_standalone_init(const device_t *info, UNUSED(void *parent)) { - paradise_t *paradise; - uint32_t memory = 512; + paradise_t *paradise; + uint32_t memory = 512; - memory = device_get_config_int("memory"); - memory <<= 10; + memory = device_get_config_int("memory"); + memory <<= 10; - paradise = (paradise_t *)paradise_pvga1a_init(info, memory); + paradise = pvga1a_init(info, memory); - if (paradise) - rom_init(¶dise->bios_rom, L"video/paradise/pvga1a/bios.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (paradise) + rom_init(¶dise->bios_rom, info->path, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + + +static void * +wd90c11_megapc_init(const device_t *info, UNUSED(void *parent)) +{ + paradise_t *paradise = wd90c11_init(info); + + if (paradise) + rom_init_interleaved(¶dise->bios_rom, + L"machines/amstrad/megapc/41651-bios lo.u18", + L"machines/amstrad/megapc/211253-bios hi.u19", + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + + +static void * +wd90c11_standalone_init(const device_t *info, UNUSED(void *parent)) +{ + paradise_t *paradise = wd90c11_init(info); + + if (paradise) + rom_init(¶dise->bios_rom, info->path, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + + +static void * +wd90c30_standalone_init(const device_t *info, UNUSED(void *parent)) +{ + paradise_t *paradise; + uint32_t memory = 512; + + memory = device_get_config_int("memory"); + memory <<= 10; + + paradise = wd90c30_init(info, memory); - return paradise; -} + if (paradise) + rom_init(¶dise->bios_rom, L"video/wd/wd90c30/90c30-lr.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); -static int paradise_pvga1a_standalone_available(void) -{ - return rom_present(L"video/paradise/pvga1a/bios.bin"); -} - -static void *paradise_wd90c11_megapc_init(const device_t *info) -{ - paradise_t *paradise = (paradise_t *)paradise_wd90c11_init(info); - - if (paradise) - rom_init_interleaved(¶dise->bios_rom, - L"machines/amstrad/megapc/41651-bios lo.u18", - L"machines/amstrad/megapc/211253-bios hi.u19", - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static void *paradise_wd90c11_standalone_init(const device_t *info) -{ - paradise_t *paradise = (paradise_t *)paradise_wd90c11_init(info); - - if (paradise) - rom_init(¶dise->bios_rom, L"video/wd/wd90c11/wd90c11.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static int paradise_wd90c11_standalone_available(void) -{ - return rom_present(L"video/wd/wd90c11/wd90c11.vbi"); -} - -static void *paradise_wd90c30_standalone_init(const device_t *info) -{ - paradise_t *paradise; - uint32_t memory = 512; - - memory = device_get_config_int("memory"); - memory <<= 10; - - paradise = (paradise_t *)paradise_wd90c30_init(info, memory); - - if (paradise) - rom_init(¶dise->bios_rom, L"video/wd/wd90c30/90c30-lr.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static int paradise_wd90c30_standalone_available(void) -{ - return rom_present(L"video/wd/wd90c30/90c30-lr.vbi"); -} - -static void paradise_close(void *p) -{ - paradise_t *paradise = (paradise_t *)p; - - svga_close(¶dise->svga); - - free(paradise); -} - -static void paradise_speed_changed(void *p) -{ - paradise_t *paradise = (paradise_t *)p; - - svga_recalctimings(¶dise->svga); -} - -static void paradise_force_redraw(void *p) -{ - paradise_t *paradise = (paradise_t *)p; - - paradise->svga.fullchange = changeframecount; + return paradise; } -static const device_config_t paradise_pvga1a_config[] = +static void +paradise_close(void *p) { - { - "memory", "Memory size", CONFIG_SELECTION, "", 512, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 - } + paradise_t *paradise = (paradise_t *)p; + + svga_close(¶dise->svga); + + free(paradise); +} + + +static void +speed_changed(void *p) +{ + paradise_t *paradise = (paradise_t *)p; + + svga_recalctimings(¶dise->svga); +} + + +static void +force_redraw(void *p) +{ + paradise_t *paradise = (paradise_t *)p; + + paradise->svga.fullchange = changeframecount; +} + + +static const device_config_t pvga1a_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 512, + { + { + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + "1 MB", 1024 + }, + { + NULL + } + } + }, + { + NULL + } }; + static const video_timings_t pvga1a_timing = {VID_ISA,8,16,32,8,16,32}; const device_t paradise_pvga1a_device = { "Paradise PVGA1A", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 0, - paradise_pvga1a_standalone_init, paradise_close, NULL, - paradise_pvga1a_standalone_available, - paradise_speed_changed, - paradise_force_redraw, + L"video/paradise/pvga1a/bios.bin", + pvga1a_standalone_init, paradise_close, NULL, + NULL, + speed_changed, + force_redraw, &pvga1a_timing, - paradise_pvga1a_config + pvga1a_config }; const device_t paradise_pvga1a_pc2086_device = { "Paradise PVGA1A (Amstrad PC2086)", + DEVICE_VIDEO(VID_TYPE_SPEC) | 0, 0, - 0, - paradise_pvga1a_pc2086_init, paradise_close, NULL, + L"machines/pc2086/40186.ic171", + pvga1a_pc2086_init, paradise_close, NULL, NULL, - paradise_speed_changed, - paradise_force_redraw, + speed_changed, + force_redraw, &pvga1a_timing, NULL }; const device_t paradise_pvga1a_pc3086_device = { "Paradise PVGA1A (Amstrad PC3086)", + DEVICE_VIDEO(VID_TYPE_SPEC) | 0, 0, - 0, - paradise_pvga1a_pc3086_init, paradise_close, NULL, + L"machines/pc3086/c000.bin", + pvga1a_pc3086_init, paradise_close, NULL, NULL, - paradise_speed_changed, - paradise_force_redraw, + speed_changed, + force_redraw, &pvga1a_timing, NULL }; @@ -592,48 +639,49 @@ static const video_timings_t wd90c11_timing = {VID_ISA,8,16,32,8,16,32}; const device_t paradise_wd90c11_device = { "Paradise WD90C11-LR", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 0, - paradise_wd90c11_standalone_init, paradise_close, NULL, - paradise_wd90c11_standalone_available, - paradise_speed_changed, - paradise_force_redraw, + L"video/wd/wd90c11/wd90c11.vbi", + wd90c11_standalone_init, paradise_close, NULL, + NULL, + speed_changed, + force_redraw, &wd90c11_timing, NULL }; const device_t paradise_wd90c11_megapc_device = { "Paradise WD90C11 (Amstrad MegaPC)", + DEVICE_VIDEO(VID_TYPE_SPEC) | 0, 0, - 0, - paradise_wd90c11_megapc_init, paradise_close, NULL, NULL, - paradise_speed_changed, - paradise_force_redraw, + wd90c11_megapc_init, paradise_close, NULL, + NULL, + speed_changed, + force_redraw, &wd90c11_timing, NULL }; -static const device_config_t paradise_wd90c30_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, - { - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t wd90c30_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 1024, + { + { + "512 KB", 512 + }, + { + "1 MB", 1024 + }, + { + NULL + } + } + }, + { + NULL + } }; static const video_timings_t wd90c30_timing = {VID_ISA,6,8,16,6,8,16}; @@ -641,12 +689,13 @@ static const video_timings_t wd90c30_timing = {VID_ISA,6,8,16,6,8,16}; const device_t paradise_wd90c30_device = { "Paradise WD90C30-LR", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 0, - paradise_wd90c30_standalone_init, paradise_close, NULL, - paradise_wd90c30_standalone_available, - paradise_speed_changed, - paradise_force_redraw, + L"video/wd/wd90c30/90c30-lr.vbi", + wd90c30_standalone_init, paradise_close, NULL, + NULL, + speed_changed, + force_redraw, &wd90c30_timing, - paradise_wd90c30_config + wd90c30_config }; diff --git a/src/devices/video/vid_pgc.c b/src/devices/video/vid_pgc.c index d9a3109..0630dc2 100644 --- a/src/devices/video/vid_pgc.c +++ b/src/devices/video/vid_pgc.c @@ -44,7 +44,7 @@ * * This is expected to be done shortly. * - * Version: @(#)vid_pgc.c 1.0.3 2019/03/07 + * Version: @(#)vid_pgc.c 1.0.4 2019/04/19 * * Authors: Fred N. van Kempen, * John Elliott, @@ -83,8 +83,8 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" -#include "../system/pit.h" #include "../../plat.h" +#include "../system/pit.h" #include "video.h" #include "vid_cga.h" #include "vid_pgc.h" @@ -224,6 +224,8 @@ input_byte(pgc_t *dev, uint8_t *result) pgc_sleep(dev); } + if (dev->stopped) return 0; + if (dev->mapram[0x3ff]) { /* Reset triggered. */ pgc_reset(dev); @@ -1588,6 +1590,8 @@ pgc_setdisplay(pgc_t *dev, int cga) if (dev->cga_selected != (dev->cga_enabled && cga)) { dev->cga_selected = (dev->cga_enabled && cga); + dev->displine = 0; + if (dev->cga_selected) { mem_map_enable(&dev->cga_mapping); dev->screenw = PGC_CGA_WIDTH; @@ -2616,7 +2620,7 @@ pgc_init(pgc_t *dev, int maxw, int maxh, int visw, int vish, static void * -pgc_standalone_init(const device_t *info) +pgc_standalone_init(const device_t *info, UNUSED(void *parent)) { pgc_t *dev; @@ -2627,7 +2631,8 @@ pgc_standalone_init(const device_t *info) /* Framebuffer and screen are both 640x480. */ pgc_init(dev, 640, 480, 640, 480, input_byte); - video_inform(VID_TYPE_CGA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); return(dev); } @@ -2637,15 +2642,16 @@ static const video_timings_t pgc_timings = { VID_ISA,8,16,32,8,16,32 }; static const device_config_t pgc_config[] = { { - "", "", -1 + NULL } }; const device_t pgc_device = { "PGC", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_CGA) | DEVICE_ISA, 0, + NULL, pgc_standalone_init, pgc_close, NULL, NULL, pgc_speed_changed, diff --git a/src/devices/video/vid_s3.c b/src/devices/video/vid_s3.c index 2325655..e582dc6 100644 --- a/src/devices/video/vid_s3.c +++ b/src/devices/video/vid_s3.c @@ -10,7 +10,7 @@ * * NOTE: ROM images need more/better organization per chipset. * - * Version: @(#)vid_s3.c 1.0.15 2019/03/07 + * Version: @(#)vid_s3.c 1.0.17 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -2865,9 +2865,8 @@ static int vram_sizes[] = static void * -s3_init(const device_t *info) +s3_init(const device_t *info, UNUSED(void *parent)) { - const wchar_t *bios_fn; int chip, stepping; s3_t *s3 = (s3_t *)mem_alloc(sizeof(s3_t)); svga_t *svga = &s3->svga; @@ -2876,55 +2875,55 @@ s3_init(const device_t *info) switch(info->local) { case S3_V7MIRAGE_86C801: - bios_fn = ROM_V7MIRAGE_86C801; chip = S3_86C801; - video_inform(VID_TYPE_SPEC, &timing_s3_86c801); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_86c801); break; + case S3_PHOENIX_86C805: - bios_fn = ROM_PHOENIX_86C805; chip = S3_86C805; - video_inform(VID_TYPE_SPEC, &timing_s3_86c805); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_86c805); break; + case S3_PARADISE_BAHAMAS64: - bios_fn = ROM_PARADISE_BAHAMAS64; chip = S3_VISION864; - video_inform(VID_TYPE_SPEC, &timing_s3_vision864); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_vision864); break; + case S3_PHOENIX_VISION864: - bios_fn = ROM_PHOENIX_VISION864; chip = S3_VISION864; - video_inform(VID_TYPE_SPEC, &timing_s3_vision864); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_vision864); break; + case S3_DIAMOND_STEALTH64_964: - bios_fn = ROM_DIAMOND_STEALTH64_964; chip = S3_VISION964; - video_inform(VID_TYPE_SPEC, &timing_s3_vision964); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_vision964); break; + case S3_PHOENIX_TRIO32: - bios_fn = ROM_PHOENIX_TRIO32; chip = S3_TRIO32; - video_inform(VID_TYPE_SPEC, &timing_s3_trio32); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_trio32); break; + case S3_PHOENIX_TRIO64: - bios_fn = ROM_PHOENIX_TRIO64; chip = S3_TRIO64; - video_inform(VID_TYPE_SPEC, &timing_s3_trio64); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_trio64); break; + case S3_PHOENIX_TRIO64_ONBOARD: - bios_fn = NULL; chip = S3_TRIO64; - video_inform(VID_TYPE_SPEC, &timing_s3_trio64); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_trio64); break; + case S3_DIAMOND_STEALTH64_764: - bios_fn = ROM_DIAMOND_STEALTH64_764; chip = S3_TRIO64; - video_inform(VID_TYPE_SPEC, &timing_s3_stealth64); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_stealth64); break; + case S3_NUMBER9_9FX: - bios_fn = ROM_NUMBER9_9FX; chip = S3_TRIO64; - video_inform(VID_TYPE_SPEC, &timing_s3_trio64); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_s3_trio64); break; + default: free(s3); return NULL; @@ -2940,9 +2939,10 @@ s3_init(const device_t *info) vram_size = 512 << 10; s3->vram_mask = vram_size - 1; - s3->has_bios = (bios_fn != NULL); + s3->has_bios = (info->path != NULL); if (s3->has_bios) { - rom_init(&s3->bios_rom, (wchar_t *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&s3->bios_rom, info->path, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (info->flags & DEVICE_PCI) mem_map_disable(&s3->bios_rom.mapping); } @@ -3125,51 +3125,6 @@ s3_init(const device_t *info) } -static int s3_v7mirage_86c801_available(void) -{ - return rom_present(ROM_V7MIRAGE_86C801); -} - -static int s3_phoenix_86c805_available(void) -{ - return rom_present(ROM_PHOENIX_86C805); -} - -static int s3_bahamas64_available(void) -{ - return rom_present(ROM_PARADISE_BAHAMAS64); -} - -static int s3_phoenix_vision864_available(void) -{ - return rom_present(ROM_PHOENIX_VISION864); -} - -static int s3_diamond_stealth64_964_available(void) -{ - return rom_present(ROM_DIAMOND_STEALTH64_964); -} - -static int s3_phoenix_trio32_available(void) -{ - return rom_present(ROM_PHOENIX_TRIO32); -} - -static int s3_9fx_available(void) -{ - return rom_present(ROM_NUMBER9_9FX); -} - -static int s3_phoenix_trio64_available(void) -{ - return rom_present(ROM_PHOENIX_TRIO64); -} - -static int s3_diamond_stealth64_764_available(void) -{ - return rom_present(ROM_DIAMOND_STEALTH64_764); -} - static void s3_close(void *p) { s3_t *s3 = (s3_t *)p; @@ -3210,12 +3165,12 @@ static const device_config_t s3_9fx_config[] = }, /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -3234,12 +3189,12 @@ static const device_config_t s3_phoenix_trio32_config[] = "2 MB", 2 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -3258,12 +3213,12 @@ static const device_config_t s3_phoenix_trio64_onboard_config[] = "4 MB", 4 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -3282,22 +3237,23 @@ static const device_config_t s3_config[] = "4 MB", 4 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; const device_t s3_v7mirage_86c801_isa_device = { "SPEA V7 Mirage (S3 86c801) ISA", - DEVICE_AT | DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_AT | DEVICE_ISA, S3_V7MIRAGE_86C801, + ROM_V7MIRAGE_86C801, s3_init, s3_close, NULL, - s3_v7mirage_86c801_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3306,10 +3262,11 @@ const device_t s3_v7mirage_86c801_isa_device = { const device_t s3_phoenix_86c805_vlb_device = { "Phoenix S3 86c805 VLB", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_PHOENIX_86C805, + ROM_PHOENIX_86C805, s3_init, s3_close, NULL, - s3_phoenix_86c805_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3318,10 +3275,11 @@ const device_t s3_phoenix_86c805_vlb_device = { const device_t s3_bahamas64_vlb_device = { "Paradise Bahamas 64 (S3 Vision864)", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_PARADISE_BAHAMAS64, + ROM_PARADISE_BAHAMAS64, s3_init, s3_close, NULL, - s3_bahamas64_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3330,10 +3288,11 @@ const device_t s3_bahamas64_vlb_device = { const device_t s3_bahamas64_pci_device = { "Paradise Bahamas 64 (S3 Vision864)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_PARADISE_BAHAMAS64, + ROM_PARADISE_BAHAMAS64, s3_init, s3_close, NULL, - s3_bahamas64_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3342,10 +3301,11 @@ const device_t s3_bahamas64_pci_device = { const device_t s3_diamond_stealth64_964_vlb_device = { "S3 Vision964 (Diamond Stealth64 VRAM)", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_DIAMOND_STEALTH64_964, + ROM_DIAMOND_STEALTH64_964, s3_init, s3_close, NULL, - s3_diamond_stealth64_964_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3354,10 +3314,11 @@ const device_t s3_diamond_stealth64_964_vlb_device = { const device_t s3_diamond_stealth64_964_pci_device = { "S3 Vision964 (Diamond Stealth64 VRAM)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_DIAMOND_STEALTH64_964, + ROM_DIAMOND_STEALTH64_964, s3_init, s3_close, NULL, - s3_diamond_stealth64_964_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3366,10 +3327,11 @@ const device_t s3_diamond_stealth64_964_pci_device = { const device_t s3_9fx_vlb_device = { "Number 9 9FX (S3 Trio64)", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_NUMBER9_9FX, + ROM_NUMBER9_9FX, s3_init, s3_close, NULL, - s3_9fx_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3378,10 +3340,11 @@ const device_t s3_9fx_vlb_device = { const device_t s3_9fx_pci_device = { "Number 9 9FX (S3 Trio64)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_NUMBER9_9FX, + ROM_NUMBER9_9FX, s3_init, s3_close, NULL, - s3_9fx_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3390,10 +3353,11 @@ const device_t s3_9fx_pci_device = { const device_t s3_phoenix_trio32_vlb_device = { "Phoenix S3 Trio32", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_PHOENIX_TRIO32, + ROM_PHOENIX_TRIO32, s3_init, s3_close, NULL, - s3_phoenix_trio32_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3402,10 +3366,11 @@ const device_t s3_phoenix_trio32_vlb_device = { const device_t s3_phoenix_trio32_pci_device = { "Phoenix S3 Trio32", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_PHOENIX_TRIO32, + ROM_PHOENIX_TRIO32, s3_init, s3_close, NULL, - s3_phoenix_trio32_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3414,10 +3379,11 @@ const device_t s3_phoenix_trio32_pci_device = { const device_t s3_phoenix_trio64_vlb_device = { "Phoenix S3 Trio64", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_PHOENIX_TRIO64, + ROM_PHOENIX_TRIO64, s3_init, s3_close, NULL, - s3_phoenix_trio64_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3426,10 +3392,11 @@ const device_t s3_phoenix_trio64_vlb_device = { const device_t s3_phoenix_trio64_pci_device = { "Phoenix S3 Trio64", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_PHOENIX_TRIO64, + ROM_PHOENIX_TRIO64, s3_init, s3_close, NULL, - s3_phoenix_trio64_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3438,8 +3405,9 @@ const device_t s3_phoenix_trio64_pci_device = { const device_t s3_phoenix_trio64_onboard_pci_device = { "Onboard Phoenix S3 Trio64", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_PHOENIX_TRIO64_ONBOARD, + NULL, s3_init, s3_close, NULL, NULL, s3_speed_changed, @@ -3450,10 +3418,11 @@ const device_t s3_phoenix_trio64_onboard_pci_device = { const device_t s3_phoenix_vision864_vlb_device = { "Phoenix S3 Vision864", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_PHOENIX_VISION864, + ROM_PHOENIX_VISION864, s3_init, s3_close, NULL, - s3_phoenix_vision864_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3462,10 +3431,11 @@ const device_t s3_phoenix_vision864_vlb_device = { const device_t s3_phoenix_vision864_pci_device = { "Phoenix S3 Vision864", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_PHOENIX_VISION864, + ROM_PHOENIX_VISION864, s3_init, s3_close, NULL, - s3_phoenix_vision864_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, @@ -3474,10 +3444,11 @@ const device_t s3_phoenix_vision864_pci_device = { const device_t s3_diamond_stealth64_vlb_device = { "S3 Trio64 (Diamond Stealth64 DRAM)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_DIAMOND_STEALTH64_764, + ROM_DIAMOND_STEALTH64_764, s3_init, s3_close, NULL, - s3_diamond_stealth64_764_available, + NULL, s3_speed_changed, s3_force_redraw, s3_config @@ -3485,10 +3456,11 @@ const device_t s3_diamond_stealth64_vlb_device = { const device_t s3_diamond_stealth64_pci_device = { "S3 Trio64 (Diamond Stealth64 DRAM)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_DIAMOND_STEALTH64_764, + ROM_DIAMOND_STEALTH64_764, s3_init, s3_close, NULL, - s3_diamond_stealth64_764_available, + NULL, s3_speed_changed, s3_force_redraw, NULL, diff --git a/src/devices/video/vid_s3_virge.c b/src/devices/video/vid_s3_virge.c index 9502332..3cacb6c 100644 --- a/src/devices/video/vid_s3_virge.c +++ b/src/devices/video/vid_s3_virge.c @@ -8,7 +8,7 @@ * * S3 ViRGE emulation. * - * Version: @(#)vid_s3_virge.c 1.0.16 2019/03/07 + * Version: @(#)vid_s3_virge.c 1.0.18 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -3873,10 +3873,9 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) static void * -s3_virge_init(const device_t *info) +s3_virge_init(const device_t *info, UNUSED(void *parent)) { virge_t *virge; - const wchar_t *bios_fn; virge = (virge_t *)mem_alloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); @@ -3885,28 +3884,6 @@ s3_virge_init(const device_t *info) virge->dithering_enabled = device_get_config_int("dithering"); virge->memory_size = device_get_config_int("memory"); - switch(info->local) { - case S3_DIAMOND_STEALTH3D_2000: - bios_fn = ROM_DIAMOND_STEALTH3D_2000; - break; - - case S3_DIAMOND_STEALTH3D_3000: - bios_fn = ROM_DIAMOND_STEALTH3D_3000; - break; - - case S3_VIRGE_DX: - bios_fn = ROM_VIRGE_DX; - break; - - case S3_VIRGE_DX_VBE20: - bios_fn = ROM_VIRGE_DX_VBE20; - break; - - default: - free(virge); - return NULL; - } - svga_init(&virge->svga, virge, virge->memory_size << 20, s3_virge_recalctimings, s3_virge_in, s3_virge_out, @@ -3916,7 +3893,7 @@ s3_virge_init(const device_t *info) virge->pci = !!(info->flags & DEVICE_PCI); - rom_init(&virge->bios_rom, bios_fn, + rom_init(&virge->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (info->flags & DEVICE_PCI) mem_map_disable(&virge->bios_rom.mapping); @@ -3963,20 +3940,23 @@ s3_virge_init(const device_t *info) virge->svga.crtc[0x53] = 1 << 3; virge->svga.crtc[0x59] = 0x70; + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); + switch(info->local) { case S3_DIAMOND_STEALTH3D_2000: virge->svga.vblank_start = s3_virge_vblank_start; virge->virge_id_high = 0x56; virge->virge_id_low = 0x31; virge->chip = S3_VIRGE; - video_inform(VID_TYPE_SPEC, &timing_diamond_stealth3d_2000); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_diamond_stealth3d_2000); break; case S3_DIAMOND_STEALTH3D_3000: virge->virge_id_high = 0x88; virge->virge_id_low = 0x3d; virge->chip = S3_VIRGEVX; - video_inform(VID_TYPE_SPEC, &timing_diamond_stealth3d_3000); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_diamond_stealth3d_3000); break; default: @@ -3984,7 +3964,7 @@ s3_virge_init(const device_t *info) virge->virge_id_high = 0x8a; virge->virge_id_low = 0x01; virge->chip = S3_VIRGEDX; - video_inform(VID_TYPE_SPEC, &timing_virge_dx); + video_inform(DEVICE_VIDEO_GET(info->flags), &timing_virge_dx); break; } @@ -4001,9 +3981,6 @@ s3_virge_init(const device_t *info) virge->fifo_not_full_event = thread_create_event(); virge->fifo_thread = thread_create(fifo_thread, virge); - video_inform(VID_TYPE_SPEC, - (const video_timings_t *)info->vid_timing); - return virge; } @@ -4046,31 +4023,6 @@ s3_virge_force_redraw(void *p) } -static int -s3_virge_available(void) -{ - return rom_present(ROM_DIAMOND_STEALTH3D_2000); -} - -static int -s3_virge_988_available(void) -{ - return rom_present(ROM_DIAMOND_STEALTH3D_3000); -} - -static int -s3_virge_375_1_available(void) -{ - return rom_present(ROM_VIRGE_DX); -} - -static int -s3_virge_375_4_available(void) -{ - return rom_present(ROM_VIRGE_DX_VBE20); -} - - static const device_config_t s3_virge_config[] = { { @@ -4083,7 +4035,7 @@ static const device_config_t s3_virge_config[] = "4 MB", 4 }, { - "" + NULL } } }, @@ -4094,7 +4046,7 @@ static const device_config_t s3_virge_config[] = "dithering", "Dithering", CONFIG_BINARY, "", 1 }, { - "", "", -1 + NULL } }; @@ -4104,10 +4056,11 @@ static const video_timings_t virge375_pci_timing = {VID_BUS,2,2,3,28,28,45}; const device_t s3_virge_vlb_device = { "Diamond Stealth 3D 2000 (S3 ViRGE)", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_DIAMOND_STEALTH3D_2000, + ROM_DIAMOND_STEALTH3D_2000, s3_virge_init, s3_virge_close, NULL, - s3_virge_available, + NULL, s3_virge_speed_changed, s3_virge_force_redraw, &virge375_vlb_timing, @@ -4116,10 +4069,11 @@ const device_t s3_virge_vlb_device = { const device_t s3_virge_pci_device = { "Diamond Stealth 3D 2000 (S3 ViRGE)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_DIAMOND_STEALTH3D_2000, + ROM_DIAMOND_STEALTH3D_2000, s3_virge_init, s3_virge_close, NULL, - s3_virge_available, + NULL, s3_virge_speed_changed, s3_virge_force_redraw, &virge375_pci_timing, @@ -4128,10 +4082,11 @@ const device_t s3_virge_pci_device = { const device_t s3_virge_988_vlb_device = { "Diamond Stealth 3D 3000 (S3 ViRGE/VX)", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_DIAMOND_STEALTH3D_3000, + ROM_DIAMOND_STEALTH3D_3000, s3_virge_init, s3_virge_close, NULL, - s3_virge_988_available, + NULL, s3_virge_speed_changed, s3_virge_force_redraw, &virge375_vlb_timing, @@ -4140,10 +4095,11 @@ const device_t s3_virge_988_vlb_device = { const device_t s3_virge_988_pci_device = { "Diamond Stealth 3D 3000 (S3 ViRGE/VX)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_DIAMOND_STEALTH3D_3000, + ROM_DIAMOND_STEALTH3D_3000, s3_virge_init, s3_virge_close, NULL, - s3_virge_988_available, + NULL, s3_virge_speed_changed, s3_virge_force_redraw, &virge375_pci_timing, @@ -4152,10 +4108,11 @@ const device_t s3_virge_988_pci_device = { const device_t s3_virge_375_vlb_device = { "S3 ViRGE/DX", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_VIRGE_DX, + ROM_VIRGE_DX, s3_virge_init, s3_virge_close, NULL, - s3_virge_375_1_available, + NULL, s3_virge_speed_changed, s3_virge_force_redraw, &virge375_vlb_timing, @@ -4164,10 +4121,11 @@ const device_t s3_virge_375_vlb_device = { const device_t s3_virge_375_pci_device = { "S3 ViRGE/DX", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_VIRGE_DX, + ROM_VIRGE_DX, s3_virge_init, s3_virge_close, NULL, - s3_virge_375_1_available, + NULL, s3_virge_speed_changed, s3_virge_force_redraw, &virge375_pci_timing, @@ -4176,10 +4134,11 @@ const device_t s3_virge_375_pci_device = { const device_t s3_virge_375_4_vlb_device = { "S3 ViRGE/DX (VBE 2.0)", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, S3_VIRGE_DX_VBE20, + ROM_VIRGE_DX_VBE20, s3_virge_init, s3_virge_close, NULL, - s3_virge_375_4_available, + NULL, s3_virge_speed_changed, s3_virge_force_redraw, &virge375_vlb_timing, @@ -4188,10 +4147,11 @@ const device_t s3_virge_375_4_vlb_device = { const device_t s3_virge_375_4_pci_device = { "S3 ViRGE/DX (VBE 2.0)", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, S3_VIRGE_DX_VBE20, + ROM_VIRGE_DX_VBE20, s3_virge_init, s3_virge_close, NULL, - s3_virge_375_4_available, + NULL, s3_virge_speed_changed, s3_virge_force_redraw, &virge375_pci_timing, diff --git a/src/devices/video/vid_sc1502x_ramdac.c b/src/devices/video/vid_sc1502x_ramdac.c index 5ce55f5..728f077 100644 --- a/src/devices/video/vid_sc1502x_ramdac.c +++ b/src/devices/video/vid_sc1502x_ramdac.c @@ -8,13 +8,13 @@ * * Emulation of a Sierra SC1502X RAMDAC. * - * Version: @(#)vid_sc1502x_ramdac.c 1.0.3 2018/10/05 + * Version: @(#)vid_sc1502x_ramdac.c 1.0.5 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,6 +44,7 @@ #include "../../emu.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_sc1502x_ramdac.h" @@ -146,7 +147,7 @@ sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *dev, svga_t *svga) static void * -sc1502x_init(const device_t *info) +sc1502x_init(const device_t *info, UNUSED(void *parent)) { sc1502x_ramdac_t *dev = (sc1502x_ramdac_t *)mem_alloc(sizeof(sc1502x_ramdac_t)); memset(dev, 0x00, sizeof(sc1502x_ramdac_t)); @@ -167,8 +168,7 @@ sc1502x_close(void *priv) const device_t sc1502x_ramdac_device = { "Sierra SC1502x RAMDAC", - 0, - 0, + 0, 0, NULL, sc1502x_init, sc1502x_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_sdac_ramdac.c b/src/devices/video/vid_sdac_ramdac.c index 5e79f95..4919c0a 100644 --- a/src/devices/video/vid_sdac_ramdac.c +++ b/src/devices/video/vid_sdac_ramdac.c @@ -8,13 +8,13 @@ * * 87C716 'SDAC' true colour RAMDAC emulation. * - * Version: @(#)vid_sdac_ramdac.c 1.0.6 2018/10/05 + * Version: @(#)vid_sdac_ramdac.c 1.0.8 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,6 +44,7 @@ #include "../../emu.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_sdac_ramdac.h" @@ -216,7 +217,7 @@ sdac_getclock(int clock, void *priv) static void * -sdac_init(const device_t *info) +sdac_init(const device_t *info, UNUSED(void *parent)) { sdac_ramdac_t *dev = (sdac_ramdac_t *)mem_alloc(sizeof(sdac_ramdac_t)); memset(dev, 0x00, sizeof(sdac_ramdac_t)); @@ -240,8 +241,7 @@ sdac_close(void *priv) const device_t sdac_ramdac_device = { "S3 SDAC 86c716 RAMDAC", - 0, - 0, + 0, 0, NULL, sdac_init, sdac_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_sigma.c b/src/devices/video/vid_sigma.c index abaa4e3..ff64ded 100644 --- a/src/devices/video/vid_sigma.c +++ b/src/devices/video/vid_sigma.c @@ -41,7 +41,7 @@ * even-numbered columns, so the top bit of the control register * at 0x2D9 is used to adjust the position. * - * Version: @(#)vid_sigma.c 1.0.4 2019/03/07 + * Version: @(#)vid_sigma.c 1.0.6 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -866,7 +866,7 @@ load_font(sigma_t *dev, const wchar_t *s) static void * -sigma_init(const device_t *info) +sigma_init(const device_t *info, UNUSED(void *parent)) { sigma_t *dev; @@ -892,7 +892,7 @@ sigma_init(const device_t *info) sigma_read,NULL,NULL, sigma_write,NULL,NULL, NULL, MEM_MAPPING_EXTERNAL, dev); - rom_init(&dev->bios_rom, BIOS_ROM_PATH, + rom_init(&dev->bios_rom, info->path, 0xc0000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); /* @@ -919,9 +919,10 @@ sigma_init(const device_t *info) if (dev->enable_nmi) dev->sigmastat = STATUS_LPEN_T; - video_inform(VID_TYPE_CGA, &sigma_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)&sigma_timing); - return dev; + return(dev); } @@ -972,7 +973,7 @@ static const device_config_t sigma_config[] = { "Color (no brown)", 4 }, { - "" + NULL } } }, @@ -980,15 +981,16 @@ static const device_config_t sigma_config[] = { "enable_nmi", "Enable NMI for CGA emulation", CONFIG_BINARY, "", 1 }, { - "", "", -1 + NULL } }; const device_t sigma_device = { "Sigma Color 400", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_CGA) | DEVICE_ISA, 0, + BIOS_ROM_PATH, sigma_init, sigma_close, NULL, sigma_available, speed_changed, diff --git a/src/devices/video/vid_stg_ramdac.c b/src/devices/video/vid_stg_ramdac.c index 37df3c0..f7c5077 100644 --- a/src/devices/video/vid_stg_ramdac.c +++ b/src/devices/video/vid_stg_ramdac.c @@ -8,13 +8,13 @@ * * STG1702 true color RAMDAC emulation. * - * Version: @(#)vid_stg_ramdac.c 1.0.4 2018/10/05 + * Version: @(#)vid_stg_ramdac.c 1.0.6 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,6 +44,7 @@ #include "../../emu.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_stg_ramdac.h" @@ -238,7 +239,7 @@ stg_getclock(int clock, void *priv) static void * -stg_init(const device_t *info) +stg_init(const device_t *info, UNUSED(void *parent)) { stg_ramdac_t *dev = (stg_ramdac_t *)mem_alloc(sizeof(stg_ramdac_t)); memset(dev, 0x00, sizeof(stg_ramdac_t)); @@ -259,8 +260,7 @@ stg_close(void *priv) const device_t stg_ramdac_device = { "SGS-Thompson STG170x RAMDAC", - 0, - 0, + 0, 0, NULL, stg_init, stg_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_svga.c b/src/devices/video/vid_svga.c index 5ab3fad..bdc1498 100644 --- a/src/devices/video/vid_svga.c +++ b/src/devices/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.16 2019/03/07 + * Version: @(#)vid_svga.c 1.0.17 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,7 +47,6 @@ #include #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" diff --git a/src/devices/video/vid_tgui9440.c b/src/devices/video/vid_tgui9440.c index 18bf034..330a24b 100644 --- a/src/devices/video/vid_tgui9440.c +++ b/src/devices/video/vid_tgui9440.c @@ -47,7 +47,7 @@ * access size or host data has any affect, but the Windows 3.1 * driver always reads bytes and write words of 0xffff. * - * Version: @(#)vid_tgui9440.c 1.0.12 2019/03/07 + * Version: @(#)vid_tgui9440.c 1.0.14 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1665,9 +1665,8 @@ void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p) static void * -tgui_init(const device_t *info) +tgui_init(const device_t *info, UNUSED(void *parent)) { - const wchar_t *bios_fn; tgui_t *tgui = (tgui_t *)mem_alloc(sizeof(tgui_t)); memset(tgui, 0x00, sizeof(tgui_t)); tgui->type = info->local; @@ -1676,21 +1675,8 @@ tgui_init(const device_t *info) tgui->vram_size = device_get_config_int("memory") << 20; tgui->vram_mask = tgui->vram_size - 1; - switch(info->local) { - case TGUI_9400CXI: - bios_fn = ROM_TGUI_9400CXI; - break; - case TGUI_9440: - bios_fn = ROM_TGUI_9440; - break; - default: - free(tgui); - return NULL; - } - - rom_init(&tgui->bios_rom, (wchar_t *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - video_inform(VID_TYPE_SPEC, &tgui_timing); + rom_init(&tgui->bios_rom, info->path, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); svga_init(&tgui->svga, tgui, tgui->vram_size, tgui_recalctimings, @@ -1716,6 +1702,8 @@ tgui_init(const device_t *info) tgui->fifo_not_full_event = thread_create_event(); tgui->fifo_thread = thread_create(fifo_thread, tgui); + video_inform(DEVICE_VIDEO_GET(info->flags), &tgui_timing); + return tgui; } @@ -1736,7 +1724,7 @@ tgui_close(void *priv) static void -tgui_speed_changed(void *priv) +speed_changed(void *priv) { tgui_t *tgui = (tgui_t *)priv; @@ -1745,25 +1733,14 @@ tgui_speed_changed(void *priv) static void -tgui_force_redraw(void *priv) +force_redraw(void *priv) { tgui_t *tgui = (tgui_t *)priv; + tgui->svga.fullchange = changeframecount; } -static int -tgui9400cxi_available(void) -{ - return rom_present(ROM_TGUI_9400CXI); -} - -static int tgui9440_available(void) -{ - return rom_present(ROM_TGUI_9440); -} - - static const device_config_t tgui9440_config[] = { { @@ -1776,47 +1753,50 @@ static const device_config_t tgui9440_config[] = "2 MB",2 }, { - "" + NULL } }, }, { - "","",-1 + NULL } }; const device_t tgui9400cxi_device = { "Trident TGUI 9400CXi", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, TGUI_9400CXI, + ROM_TGUI_9400CXI, tgui_init, tgui_close, NULL, - tgui9400cxi_available, - tgui_speed_changed, - tgui_force_redraw, + NULL, + speed_changed, + force_redraw, NULL, tgui9440_config }; const device_t tgui9440_vlb_device = { "Trident TGUI 9440", - DEVICE_VLB, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_VLB, TGUI_9440, + ROM_TGUI_9440, tgui_init, tgui_close, NULL, - tgui9440_available, - tgui_speed_changed, - tgui_force_redraw, + NULL, + speed_changed, + force_redraw, NULL, tgui9440_config }; const device_t tgui9440_pci_device = { "Trident TGUI 9440", - DEVICE_PCI, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_PCI, TGUI_9440, + ROM_TGUI_9440, tgui_init, tgui_close, NULL, - tgui9440_available, - tgui_speed_changed, - tgui_force_redraw, + NULL, + speed_changed, + force_redraw, NULL, tgui9440_config }; diff --git a/src/devices/video/vid_ti_cf62011.c b/src/devices/video/vid_ti_cf62011.c index 42a59bb..deeaa63 100644 --- a/src/devices/video/vid_ti_cf62011.c +++ b/src/devices/video/vid_ti_cf62011.c @@ -42,13 +42,13 @@ * which are the same as the XGA. It supports up to 1MB of VRAM, * but we lock it down to 512K. The PS/1 2122 had 256K. * - * Version: @(#)vid_ti_cf62011.c 1.0.7 2018/10/08 + * Version: @(#)vid_ti_cf62011.c 1.0.9 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -80,6 +80,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" @@ -221,7 +222,7 @@ vid_in(uint16_t addr, void *priv) static void -vid_speed_changed(void *priv) +speed_changed(void *priv) { tivga_t *ti = (tivga_t *)priv; @@ -230,7 +231,7 @@ vid_speed_changed(void *priv) static void -vid_force_redraw(void *priv) +force_redraw(void *priv) { tivga_t *ti = (tivga_t *)priv; @@ -250,7 +251,7 @@ vid_close(void *priv) static void * -vid_init(const device_t *info) +vid_init(const device_t *info, UNUSED(void *parent)) { tivga_t *ti; @@ -277,7 +278,7 @@ vid_init(const device_t *info) ti->svga.bpp = 8; ti->svga.miscout = 1; - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); return(ti); @@ -285,7 +286,7 @@ vid_init(const device_t *info) #if defined(DEV_BRANCH) && defined(USE_TI) -static const device_config_t vid_config[] = +static const device_config_t ti_cf62011_config[] = { { "vram_size", "Memory Size", CONFIG_SELECTION, "", 256, @@ -300,38 +301,40 @@ static const device_config_t vid_config[] = "1024K", 1024 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; const device_t ti_cf62011_device = { "TI CF62011 SVGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 0, + NULL, vid_init, vid_close, NULL, NULL, - vid_speed_changed, - vid_force_redraw, + speed_changed, + force_redraw, &ti_cf62011_timing, - vid_config + ti_cf62011_config }; #endif const device_t ibm_ps1_2121_device = { "IBM PS/1 Model 2121 SVGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 512, + NULL, vid_init, vid_close, NULL, NULL, - vid_speed_changed, - vid_force_redraw, + speed_changed, + force_redraw, &ti_cf62011_timing, NULL }; diff --git a/src/devices/video/vid_tkd8001_ramdac.c b/src/devices/video/vid_tkd8001_ramdac.c index 1f4df6f..f5f25d2 100644 --- a/src/devices/video/vid_tkd8001_ramdac.c +++ b/src/devices/video/vid_tkd8001_ramdac.c @@ -8,13 +8,13 @@ * * Trident TKD8001 RAMDAC emulation. * - * Version: @(#)vid_tkd8001_ramdac.c 1.0.3 2018/10/05 + * Version: @(#)vid_tkd8001_ramdac.c 1.0.5 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,6 +44,7 @@ #include "../../emu.h" #include "../../mem.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_tkd8001_ramdac.h" @@ -114,7 +115,7 @@ tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *dev, svga_t *svga) static void * -tkd8001_init(const device_t *info) +tkd8001_init(const device_t *info, UNUSED(void *parent)) { tkd8001_ramdac_t *dev = (tkd8001_ramdac_t *)mem_alloc(sizeof(tkd8001_ramdac_t)); memset(dev, 0x00, sizeof(tkd8001_ramdac_t)); @@ -135,8 +136,7 @@ tkd8001_close(void *priv) const device_t tkd8001_ramdac_device = { "Trident TKD8001 RAMDAC", - 0, - 0, + 0, 0, NULL, tkd8001_init, tkd8001_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/video/vid_tvga.c b/src/devices/video/vid_tvga.c index 195bdfd..69fedc5 100644 --- a/src/devices/video/vid_tvga.c +++ b/src/devices/video/vid_tvga.c @@ -8,7 +8,7 @@ * * Trident TVGA (8900B/8900C/8900D) emulation. * - * Version: @(#)vid_tvga.c 1.0.11 2019/02/10 + * Version: @(#)vid_tvga.c 1.0.13 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,6 +46,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -346,9 +347,8 @@ tvga_recalctimings(svga_t *svga) static void * -tvga_init(const device_t *info) +tvga_init(const device_t *info, UNUSED(void *parent)) { - const wchar_t *fn = NULL; tvga_t *tvga; tvga = (tvga_t *)mem_alloc(sizeof(tvga_t)); @@ -363,34 +363,31 @@ tvga_init(const device_t *info) switch(info->local) { case TVGA8900B_ID: /* TVGA 8900B */ - fn = ROM_TVGA_8900B; tvga->svga.ramdac = device_add(&tkd8001_ramdac_device); break; case TVGA8900CLD_ID: /* TVGA 8900CX LC2 */ - fn = ROM_TVGA_8900CLD; tvga->svga.ramdac = device_add(&tkd8001_ramdac_device); break; #if 0 case 1: /* TVGA 8900D */ - fn = ROM_TVGA_8900D; tvga->svga.ramdac = device_add(&tkd8001_ramdac_device); break; #endif } - if (fn != NULL) - rom_init(&tvga->bios_rom, fn, + if (info->path) + rom_init(&tvga->bios_rom, info->path, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); io_sethandler(0x03c0, 32, tvga_in,NULL,NULL, tvga_out,NULL,NULL, tvga); - video_inform(VID_TYPE_SPEC, + video_inform(DEVICE_VIDEO_GET(info->flags), (const video_timings_t *)info->vid_timing); - return tvga; + return(tvga); } @@ -406,7 +403,7 @@ tvga_close(void *priv) static void -tvga_speed_changed(void *p) +speed_changed(void *p) { tvga_t *tvga = (tvga_t *)p; @@ -415,7 +412,7 @@ tvga_speed_changed(void *p) static void -tvga_force_redraw(void *p) +force_redraw(void *p) { tvga_t *tvga = (tvga_t *)p; @@ -423,25 +420,6 @@ tvga_force_redraw(void *p) } -static int -tvga8900b_available(void) -{ - return rom_present(ROM_TVGA_8900B); -} - -static int -tvga8900cx_available(void) -{ - return rom_present(ROM_TVGA_8900CLD); -} - -static int -tvga8900d_available(void) -{ - return rom_present(ROM_TVGA_8900D); -} - - static const device_config_t tvga_config[] = { { @@ -458,12 +436,12 @@ static const device_config_t tvga_config[] = }, /*Chip supports 2MB, but drivers are buggy*/ { - "" + NULL } } }, { - "", "", -1 + NULL } }; @@ -472,36 +450,39 @@ static const video_timings_t tvga8900_timing = {VID_ISA,3,3,6,8,8,12}; const device_t tvga8900b_device = { "Trident TVGA 8900B", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, TVGA8900B_ID, + ROM_TVGA_8900B, tvga_init, tvga_close, NULL, - tvga8900b_available, - tvga_speed_changed, - tvga_force_redraw, + NULL, + speed_changed, + force_redraw, &tvga8900_timing, tvga_config }; const device_t tvga8900cx_device = { "Trident TVGA 8900CX 2/4/8 LC2 Rev.A", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, TVGA8900CLD_ID, + ROM_TVGA_8900CLD, tvga_init, tvga_close, NULL, - tvga8900cx_available, - tvga_speed_changed, - tvga_force_redraw, + NULL, + speed_changed, + force_redraw, &tvga8900_timing, tvga_config }; const device_t tvga8900d_device = { "Trident TVGA 8900D", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 1, + ROM_TVGA_8900D, tvga_init, tvga_close, NULL, - tvga8900d_available, - tvga_speed_changed, - tvga_force_redraw, + NULL, + speed_changed, + force_redraw, &tvga8900_timing, tvga_config }; diff --git a/src/devices/video/vid_vga.c b/src/devices/video/vid_vga.c index d13ee0b..afbeb65 100644 --- a/src/devices/video/vid_vga.c +++ b/src/devices/video/vid_vga.c @@ -8,13 +8,13 @@ * * IBM VGA emulation. * - * Version: @(#)vid_vga.c 1.0.7 2018/09/22 + * Version: @(#)vid_vga.c 1.0.9 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -46,6 +46,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" @@ -131,22 +132,16 @@ vga_in(uint16_t port, void *priv) static void * -vga_init(const device_t *info) +vga_init(const device_t *info, UNUSED(void *parent)) { vga_t *dev; dev = (vga_t *)mem_alloc(sizeof(vga_t)); memset(dev, 0x00, sizeof(vga_t)); - switch(info->local) { - case 0: /* IBM VGA */ - rom_init(&dev->bios_rom, BIOS_ROM_PATH, - 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); - break; - - case 1: /* IBM PS/1 VGA */ - break; - } + if (info->path != NULL) + rom_init(&dev->bios_rom, info->path, + 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); svga_init(&dev->svga, dev, 1 << 18, /*256kb*/ NULL, vga_in, vga_out, NULL, NULL); @@ -157,14 +152,10 @@ vga_init(const device_t *info) dev->svga.bpp = 8; dev->svga.miscout = 1; - return dev; -} + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); - -static int -vga_available(void) -{ - return rom_present(BIOS_ROM_PATH); + return(dev); } @@ -201,10 +192,11 @@ static video_timings_t vga_timing = {VID_ISA, 8,16,32, 8,16,32}; const device_t vga_device = { "VGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 0, + BIOS_ROM_PATH, vga_init, vga_close, NULL, - vga_available, + NULL, speed_changed, force_redraw, &vga_timing, @@ -216,8 +208,9 @@ static const video_timings_t ps1vga_timing = {VID_ISA,6,8,16,6,8,16}; const device_t ps1vga_device = { "PS/1 VGA", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_ISA, 1, + NULL, vga_init, vga_close, NULL, NULL, speed_changed, @@ -228,8 +221,9 @@ const device_t ps1vga_device = { const device_t ps1vga_mca_device = { "PS/1 VGA", - DEVICE_MCA, + DEVICE_VIDEO(VID_TYPE_SPEC) | DEVICE_MCA, 1, + NULL, vga_init, vga_close, NULL, NULL, speed_changed, diff --git a/src/devices/video/vid_voodoo.c b/src/devices/video/vid_voodoo.c index 1f522e9..6150430 100644 --- a/src/devices/video/vid_voodoo.c +++ b/src/devices/video/vid_voodoo.c @@ -8,7 +8,7 @@ * * Emulation of the 3DFX Voodoo Graphics controller. * - * Version: @(#)vid_voodoo.c 1.0.15 2019/03/07 + * Version: @(#)vid_voodoo.c 1.0.18 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,9 +46,7 @@ #include #include #include "../../emu.h" -#undef ERROR #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../mem.h" #include "../../timer.h" #include "../../device.h" @@ -6271,6 +6269,7 @@ static void voodoo_pixelclock_update(voodoo_t *voodoo) static void voodoo_writel(uint32_t addr, uint32_t val, void *p) { voodoo_t *voodoo = (voodoo_t *)p; + uint32_t pci_time; voodoo->wr_count++; @@ -6354,8 +6353,9 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) case SST_fbiInit4: if (voodoo->initEnable & 0x01) { + pci_time = pci_get_speed(0) + pci_get_speed(1); voodoo->fbiInit4 = val; - voodoo->read_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit4 & 1) ? 2 : 1); + voodoo->read_time = pci_time * ((voodoo->fbiInit4 & 1) ? 2 : 1); // DEBUG("fbiInit4 write %08x - read_time=%i\n", val, voodoo->read_time); } break; @@ -6396,8 +6396,10 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) voodoo->retrace_count = 0; } voodoo->fbiInit1 = (val & ~5) | (voodoo->fbiInit1 & 5); - voodoo->write_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit1 & 2) ? 1 : 0); - voodoo->burst_time = pci_burst_time * ((voodoo->fbiInit1 & 2) ? 2 : 1); + pci_time = pci_get_speed(1); + voodoo->burst_time = pci_time * ((voodoo->fbiInit1 & 2) ? 2 : 1); + pci_time += pci_get_speed(0); + voodoo->write_time = pci_time * ((voodoo->fbiInit1 & 2) ? 1 : 0); // DEBUG("fbiInit1 write %08x - write_time=%i burst_time=%i\n", val, voodoo->write_time, voodoo->burst_time); } break; @@ -7535,17 +7537,20 @@ skip_draw: static void voodoo_speed_changed(void *p) { voodoo_set_t *voodoo_set = (voodoo_set_t *)p; + uint32_t pci_time = pci_get_speed(1); voodoo_pixelclock_update(voodoo_set->voodoos[0]); - voodoo_set->voodoos[0]->read_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit4 & 1) ? 2 : 1); - voodoo_set->voodoos[0]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 1 : 0); - voodoo_set->voodoos[0]->burst_time = pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 2 : 1); + voodoo_set->voodoos[0]->burst_time = pci_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 2 : 1); + pci_time += pci_get_speed(0); + voodoo_set->voodoos[0]->read_time = pci_time * ((voodoo_set->voodoos[0]->fbiInit4 & 1) ? 2 : 1); + voodoo_set->voodoos[0]->write_time = pci_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 1 : 0); if (voodoo_set->nr_cards == 2) { voodoo_pixelclock_update(voodoo_set->voodoos[1]); - voodoo_set->voodoos[1]->read_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit4 & 1) ? 2 : 1); - voodoo_set->voodoos[1]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 1 : 0); - voodoo_set->voodoos[1]->burst_time = pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 2 : 1); + voodoo_set->voodoos[1]->read_time = pci_time * ((voodoo_set->voodoos[1]->fbiInit4 & 1) ? 2 : 1); + voodoo_set->voodoos[1]->write_time = pci_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 1 : 0); + pci_time = pci_get_speed(1); + voodoo_set->voodoos[1]->burst_time = pci_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 2 : 1); } // DEBUG("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); } @@ -7687,7 +7692,9 @@ void *voodoo_card_init() return voodoo; } -void *voodoo_init(const device_t *info) + +static void * +voodoo_init(const device_t *info, UNUSED(void *parent)) { voodoo_set_t *voodoo_set = (voodoo_set_t *)mem_alloc(sizeof(voodoo_set_t)); uint32_t tmuConfig = 1; @@ -7752,7 +7759,9 @@ void *voodoo_init(const device_t *info) return voodoo_set; } -void voodoo_card_close(voodoo_t *voodoo) + +static void +voodoo_card_close(voodoo_t *voodoo) { #ifndef RELEASE_BUILD FILE *f; @@ -7805,7 +7814,9 @@ void voodoo_card_close(voodoo_t *voodoo) free(voodoo); } -void voodoo_close(void *p) + +static void +voodoo_close(void *p) { voodoo_set_t *voodoo_set = (voodoo_set_t *)p; @@ -7823,6 +7834,7 @@ void voodoo_close(void *p) free(voodoo_set); } + static const device_config_t voodoo_config[] = { { @@ -7838,7 +7850,7 @@ static const device_config_t voodoo_config[] = "Voodoo 2",VOODOO_2 }, { - "" + NULL } }, }, @@ -7852,7 +7864,7 @@ static const device_config_t voodoo_config[] = "4 MB",4 }, { - "" + NULL } }, }, @@ -7866,7 +7878,7 @@ static const device_config_t voodoo_config[] = "4 MB",4 }, { - "" + NULL } }, }, @@ -7886,7 +7898,7 @@ static const device_config_t voodoo_config[] = "2",2 }, { - "" + NULL } }, }, @@ -7899,21 +7911,20 @@ static const device_config_t voodoo_config[] = }, #endif { - "","",-1 + NULL } }; -const device_t voodoo_device = -{ - "3DFX Voodoo Graphics", - DEVICE_PCI, - 0, - voodoo_init, - voodoo_close, - NULL, - NULL, - voodoo_speed_changed, - NULL, - NULL, - voodoo_config + +const device_t voodoo_device = { + "3DFX Voodoo Graphics", + DEVICE_PCI, + 0, + NULL, + voodoo_init, voodoo_close, NULL, + NULL, + voodoo_speed_changed, + NULL, + NULL, + voodoo_config }; diff --git a/src/devices/video/vid_wy700.c b/src/devices/video/vid_wy700.c index 94c8c96..6926226 100644 --- a/src/devices/video/vid_wy700.c +++ b/src/devices/video/vid_wy700.c @@ -53,7 +53,7 @@ * What doesn't work, is untested or not well understood: * - Cursor detach (commands 4 and 5) * - * Version: @(#)vid_wy700.c 1.0.7 2019/03/07 + * Version: @(#)vid_wy700.c 1.0.9 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -92,8 +92,8 @@ #include "../../rom.h" #include "../../timer.h" #include "../../device.h" -#include "../system/pit.h" #include "../../plat.h" +#include "../system/pit.h" #include "video.h" @@ -877,7 +877,7 @@ load_font(wy700_t *dev, const wchar_t *s) static void * -wy700_init(const device_t *info) +wy700_init(const device_t *info, UNUSED(void *parent)) { wy700_t *dev; int c; @@ -886,7 +886,7 @@ wy700_init(const device_t *info) memset(dev, 0x00, sizeof(wy700_t)); dev->name = info->name; - if (! load_font(dev, FONT_ROM_PATH)) { + if (! load_font(dev, info->path)) { free(dev); return(NULL); } @@ -986,9 +986,10 @@ wy700_init(const device_t *info) dev->enabled = 1; memcpy(dev->real_crtc, mode_80x24, sizeof(mode_80x24)); - video_inform(VID_TYPE_CGA, info->vid_timing); + video_inform(DEVICE_VIDEO_GET(info->flags), + (const video_timings_t *)info->vid_timing); - return dev; + return(dev); } @@ -998,17 +999,11 @@ wy700_close(void *priv) wy700_t *dev = (wy700_t *)priv; free(dev->vram); + free(dev); } -static int -wy700_available(void) -{ - return rom_present(FONT_ROM_PATH); -} - - static void speed_changed(void *priv) { @@ -1022,10 +1017,11 @@ static const video_timings_t wy700_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t wy700_device = { "Wyse 700", - DEVICE_ISA, + DEVICE_VIDEO(VID_TYPE_CGA) | DEVICE_ISA, 0, + FONT_ROM_PATH, wy700_init, wy700_close, NULL, - wy700_available, + NULL, speed_changed, NULL, &wy700_timings, diff --git a/src/devices/video/video.c b/src/devices/video/video.c index 2a3f7f2..2155f64 100644 --- a/src/devices/video/video.c +++ b/src/devices/video/video.c @@ -8,7 +8,7 @@ * * Main video-rendering module. * - * Version: @(#)video.c 1.0.27 2019/03/09 + * Version: @(#)video.c 1.0.28 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,12 +47,15 @@ #define dbglog video_log #include "../../emu.h" #include "../../cpu/cpu.h" +#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" +#include "../../device.h" #include "../../timer.h" #include "../../plat.h" #include "video.h" +#include "vid_mda.h" #include "vid_svga.h" @@ -169,7 +172,6 @@ PALETTE cgapal_mono[6] = { static const video_timings_t timing_default = { VID_ISA, 8, 16, 32, 8, 16, 32 }; -static const video_timings_t *video_timing; static const uint32_t shade[5][256] = { {0},/* RGB Color (unused) */ {0},/* RGB Grayscale (unused) */ @@ -376,6 +378,7 @@ static uint32_t cga_2_table[16]; static uint8_t rotatevga[8][256]; static int video_force_resize; static int video_card_type; +static const video_timings_t *video_timing; static struct blitter { @@ -717,6 +720,10 @@ video_init(void) uint8_t total[2] = { 0, 1 }; int c, d, e; + /* Initialize video type and timing. */ + video_card_type = -1; + video_timing = &timing_default; + for (c = 0; c < 16; c++) { cga_2_table[c] = (total[(c >> 3) & 1] << 0 ) | (total[(c >> 2) & 1] << 8 ) | @@ -773,9 +780,6 @@ video_init(void) video_blit.busy_ev = thread_create_event(); video_blit.inuse_ev = thread_create_event(); video_blit.thread = thread_create(blit_thread, &video_blit); - - /* Initialize video type and timing. */ - video_inform(VID_TYPE_DFLT, NULL); } @@ -794,6 +798,86 @@ video_close(void) destroy_bitmap(screen); video_reset_font(); + + /* Close up. */ + video_card_type = -1; + video_timing = &timing_default; +} + + +void +video_reset(void) +{ + const device_t *dev; + + INFO("VIDEO: reset (video_card=%i, internal=%i)\n", + video_card, (machine->flags & MACHINE_VIDEO) ? 1 : 0); + + /* Initialize the video font tables. */ + video_load_font(MDA_FONT_ROM_PATH, FONT_MDA); + + /* Do not initialize internal cards here. */ + if ((video_card == VID_NONE) || \ + (video_card == VID_INTERNAL) || \ + (machine->flags_fixed & MACHINE_VIDEO)) return; + + /* Configure default timing parameters for the card. */ + video_inform(VID_TYPE_SPEC, NULL); + + /* Reset the CGA palette. */ + cga_palette = 0; + video_palette_rebuild(); + + /* Clear (deallocate) any video font memory. */ + video_reset_font(); + + dev = video_card_getdevice(video_card); + if (dev != NULL) + device_add(dev); + + /* Enable the Voodoo if configured. */ + if (voodoo_enabled) + device_add(&voodoo_device); +} + + +/* Inform the video module what type a card is, and what its timings are. */ +void +video_inform(int type, const video_timings_t *ptr) +{ + /* Save the video card type. */ + video_card_type = (type == VID_TYPE_DFLT) ? VID_TYPE_SPEC : type; + + /* Save the card's timing parameters. */ + video_timing = (ptr == NULL) ? &timing_default : ptr; + + /* Make sure these are used. */ + video_update_timing(); + + if (type != VID_TYPE_DFLT) + DEBUG("VIDEO: card type %i, timings {%i: %i,%i,%i %i,%i,%i}\n", + video_card_type, video_timing->type, + video_timing->write_b,video_timing->write_w,video_timing->write_l, + video_timing->read_b,video_timing->read_w,video_timing->read_l); +} + + +/* Return the current video card's type. */ +int +video_type(void) +{ + const device_t *dev; + int type = -1; + + if (video_card_type == -1) { + /* No video device loaded yet. */ + dev = video_card_getdevice(video_card); + if (dev != NULL) + type = DEVICE_VIDEO_GET(dev->flags); + } else + type = video_card_type; + + return(type); } @@ -826,35 +910,6 @@ video_update_timing(void) } -/* Inform the video module what type a card is, and what its timings are. */ -void -video_inform(int type, const video_timings_t *ptr) -{ - /* Save the video card type. */ - video_card_type = (type == VID_TYPE_DFLT) ? VID_TYPE_SPEC : type; - - /* Save the card's timing parameters. */ - video_timing = (ptr == NULL) ? &timing_default : ptr; - - /* Make sure these are used. */ - video_update_timing(); - - if (type != VID_TYPE_DFLT) - DEBUG("VIDEO: card type %i, timings {%i: %i,%i,%i %i,%i,%i}\n", - video_card_type, video_timing->type, - video_timing->write_b,video_timing->write_w,video_timing->write_l, - video_timing->read_b,video_timing->read_w,video_timing->read_l); -} - - -/* Return the current video card's type. */ -int -video_type(void) -{ - return(video_card_type); -} - - /* Zap any font memory allocated previously. */ void video_reset_font(void) diff --git a/src/devices/video/video.h b/src/devices/video/video.h index b534e39..955704f 100644 --- a/src/devices/video/video.h +++ b/src/devices/video/video.h @@ -8,7 +8,7 @@ * * Definitions for the video controller module. * - * Version: @(#)video.h 1.0.30 2019/03/09 + * Version: @(#)video.h 1.0.31 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -199,13 +199,17 @@ extern const device_t gd5440_pci_device; extern const device_t gd5446_stb_pci_device; extern const device_t gd5480_pci_device; +#if defined(DEV_BRANCH) && defined(USE_COMPAQ) /* COMPAQ CGA-derived cards. */ extern const device_t cga_compaq_device; extern const device_t cga_compaq2_device; +#endif /* IBM EGA and compatibles. */ extern const device_t ega_device; +#if defined(DEV_BRANCH) && defined(USE_COMPAQ) extern const device_t ega_compaq_device; +#endif extern const device_t sega_device; /* Tseng Labs ET4000 series cards. */ @@ -337,17 +341,13 @@ extern void video_blit_start(int pal, int x, int y, extern void video_blend(int x, int y); extern void video_palette_rebuild(void); -#ifdef VIDEO_SVGA_H -extern int ati28800k_load_font(svga_t *, const wchar_t *); -#endif - extern void video_log(int level, const char *fmt, ...); extern void video_init(void); extern void video_close(void); extern void video_reset(void); -extern void video_update_timing(void); extern void video_inform(int type, const video_timings_t *ptr); extern int video_type(void); +extern void video_update_timing(void); extern void video_reset_font(void); extern void video_load_font(const wchar_t *s, fontformat_t num); extern uint8_t video_force_resize_get(void); @@ -355,10 +355,6 @@ extern void video_force_resize_set(uint8_t res); extern uint32_t video_color_transform(uint32_t color); extern void video_transform_copy(uint32_t *dst, pel_t *src, int len); -extern void updatewindowsize(int x, int y); -extern int get_actual_size_x(void); -extern int get_actual_size_y(void); - #ifdef __cplusplus } #endif diff --git a/src/devices/video/video_dev.c b/src/devices/video/video_dev.c index 326ea5d..70911ff 100644 --- a/src/devices/video/video_dev.c +++ b/src/devices/video/video_dev.c @@ -12,7 +12,7 @@ * "extern" reference to its device into the video.h file, * and add an entry for it into the table here. * - * Version: @(#)video_dev.c 1.0.35 2019/03/09 + * Version: @(#)video_dev.c 1.0.37 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,12 +46,9 @@ #include #define HAVE_STDARG_H #include "../../emu.h" -#include "../../machines/machine.h" #include "../../mem.h" #include "../../device.h" -#include "../../plat.h" #include "video.h" -#include "vid_mda.h" #ifdef ENABLE_VIDEO_DEV_LOG @@ -98,9 +95,11 @@ static const struct { { "cl_gd5429_isa", &gd5429_isa_device }, { "cl_gd5434_isa", &gd5434_isa_device }, { "compaq_ati28800", &ati28800_compaq_device }, +#if defined(DEV_BRANCH) && defined(USE_COMPAQ) { "compaq_cga", &cga_compaq_device }, { "compaq_cga_2", &cga_compaq2_device }, { "compaq_ega", &ega_compaq_device }, +#endif { "hercules_plus", &herculesplus_device }, { "incolor", &incolor_device }, { "genius", &genius_device }, @@ -197,44 +196,6 @@ video_card_log(int level, const char *fmt, ...) #endif -void -video_reset(void) -{ - INFO("VIDEO: reset (video_card=%d, internal=%d)\n", - video_card, (machines[machine].flags & MACHINE_VIDEO) ? 1 : 0); - - /* Reset the CGA palette. */ - cga_palette = 0; - video_palette_rebuild(); - - /* - * Clear (deallocate) any video font memory. - * - * We have to do this before the machine is reset, as - * that *might* allocate it if that uses an internal - * controller using extended font memory.. - */ - video_reset_font(); - - /* Initialize the video font tables. */ - video_load_font(MDA_FONT_ROM_PATH, FONT_MDA); - - /* Do not initialize internal cards here. */ - if ((video_card == VID_NONE) || \ - (video_card == VID_INTERNAL) || \ - machines[machine].fixed_vidcard) return; - - /* Configure default timing parameters for the card. */ - video_inform(VID_TYPE_SPEC, NULL); - - device_add(video_cards[video_card].device); - - /* Enable the Voodoo if configured. */ - if (voodoo_enabled) - device_add(&voodoo_device); -} - - int video_card_available(int card) { diff --git a/src/emu.h b/src/emu.h index 965b378..7bf6802 100644 --- a/src/emu.h +++ b/src/emu.h @@ -8,11 +8,11 @@ * * Main include file for the application. * - * Version: @(#)emu.h 1.0.33 2018/10/16 + * Version: @(#)emu.h 1.0.34 2019/04/11 * * Author: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -214,9 +214,9 @@ extern int sound_card, /* (C) selected sound card */ midi_device; /* (C) selected midi device */ extern int joystick_type; /* (C) joystick type */ extern int mem_size; /* (C) memory size */ -extern int machine; /* (C) current machine ID */ +extern int machine_type; /* (C) current machine ID */ extern int cpu_manufacturer, /* (C) cpu manufacturer */ - cpu, /* (C) cpu type */ + cpu_type, /* (C) cpu type */ cpu_use_dynarec, /* (C) cpu uses/needs Dyna */ enable_external_fpu; /* (C) enable external FPU */ extern int network_type; /* (C) net provider type */ @@ -238,6 +238,9 @@ extern int config_changed, /* config has changed */ dopause, /* system is paused */ doresize, /* screen resize requested */ mouse_capture; /* mouse is captured in app */ +extern int AT, /* machine is AT class */ + MCA, /* machine has MCA bus */ + PCI; /* machine has PCI bus */ #ifdef _LOGGING extern int pci_do_log; @@ -287,9 +290,7 @@ extern void pc_reset_hard_init(void); extern void pc_reset_hard(void); extern void pc_reset(int hard); extern void pc_reload(const wchar_t *fn); -extern void pc_set_speed(void); -extern void pc_full_speed(void); -extern void pc_speed_changed(void); +extern void pc_set_speed(int); extern void pc_thread(void *param); extern void pc_pause(int p); extern void pc_onesec(void); diff --git a/src/io.c b/src/io.c index 575662b..8c41e8e 100644 --- a/src/io.c +++ b/src/io.c @@ -8,13 +8,13 @@ * * Implement I/O ports and their operations. * - * Version: @(#)io.c 1.0.3 2018/09/22 + * Version: @(#)io.c 1.0.4 2019/04/12 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -80,7 +80,7 @@ static void null_outl(uint16_t addr, uint32_t val, void *priv) { DEBUG("IO: writ void -io_init(void) +io_reset(void) { io_t *p, *q; int c; diff --git a/src/io.h b/src/io.h index 85a6e12..d99808f 100644 --- a/src/io.h +++ b/src/io.h @@ -8,13 +8,13 @@ * * Definitions for the I/O handler. * - * Version: @(#)io.h 1.0.1 2018/02/14 + * Version: @(#)io.h 1.0.2 2019/04/12 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -40,7 +40,7 @@ # define EMU_IO_H -extern void io_init(void); +extern void io_reset(void); extern void io_sethandler(uint16_t base, int size, uint8_t (*inb)(uint16_t addr, void *priv), diff --git a/src/machines/m_acer.c b/src/machines/m_acer.c new file mode 100644 index 0000000..9f9fb07 --- /dev/null +++ b/src/machines/m_acer.c @@ -0,0 +1,247 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Intel 430xx-based Acer machines. + * + * Version: @(#)m_acer.c 1.0.1 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/intel4x0.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/system/intel.h" +#include "../devices/system/intel_flash.h" +#include "../devices/system/intel_sio.h" +#include "../devices/system/intel_piix.h" +#include "../devices/input/keyboard.h" +#include "../devices/sio/sio.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "machine.h" + + +typedef struct { + int type; + + int indx; /* M3A */ +} acer_t; + + +static void +m3a_out(uint16_t port, uint8_t val, void *priv) +{ + acer_t *dev = (acer_t *)priv; + + if (port == 0xea) + dev->indx = val; +} + + +static uint8_t +m3a_in(uint16_t port, void *priv) +{ + acer_t *dev = (acer_t *)priv; + + if (port == 0xeb) { + switch (dev->indx) { + case 2: + return 0xfd; + } + } + + return(0xff); +} + + +static void +acer_close(void *priv) +{ + acer_t *dev = (acer_t *)priv; + + free(dev); +} + + +static void * +acer_init(const device_t *info, void *arg) +{ + acer_t *dev; + + dev = (acer_t *)mem_alloc(sizeof(acer_t)); + memset(dev, 0x00, sizeof(acer_t)); + dev->type = info->local; + + /* Add machine device to system. */ + device_add_ex(info, dev); + + m_at_common_init(); + + switch(dev->type) { + case 0: /* Acer M3A/430HX/Acer/SMC FDC37C932FR */ + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x1F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x10, PCI_CARD_ONBOARD, 4, 0, 0, 0); + + powermate_memregs_init(); + + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxb_device); + + device_add(&fdc37c932fr_device); + device_add(&keyboard_ps2_pci_device); + + io_sethandler(0x00ea, 2, + m3a_in,NULL,NULL, m3a_out,NULL,NULL, dev); + break; + + case 1: /* Acer V35N/430HX/Acer/SMC FDC37C932FR */ + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + + powermate_memregs_init(); + + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxb_device); + + device_add(&fdc37c932fr_device); + device_add(&keyboard_ps2_pci_device); + + io_sethandler(0x00ea, 2, + m3a_in,NULL,NULL, m3a_out,NULL,NULL, dev); + break; + + case 2: /* Acer V30/430FX/P54C P75-133/Acer/SMC FDC37C655 */ + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + + powermate_memregs_init(); + + device_add(&i430fx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxb_device); + + device_add(&fdc37c665_device); + device_add(&keyboard_ps2_ami_pci_device); + + break; + } + + return(dev); +} + + +static const machine_t m3a_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 192, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_acer_m3a = { + "Acer M3A", + DEVICE_ROOT, + 0, + L"acer/m3a", + acer_init, acer_close, NULL, + NULL, NULL, NULL, + &m3a_info, + NULL +}; + + +static const machine_t v35n_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 192, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_acer_v35n = { + "Acer V35N", + DEVICE_ROOT, + 1, + L"acer/v35n", + acer_init, acer_close, NULL, + NULL, NULL, NULL, + &v35n_info, + NULL +}; + + +static const machine_t v30_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 192, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_acer_v30 = { + "Acer V30", + DEVICE_ROOT, + 2, + L"acer/v30", + acer_init, acer_close, NULL, + NULL, NULL, NULL, + &v30_info, + NULL +}; diff --git a/src/machines/m_ali.c b/src/machines/m_ali.c new file mode 100644 index 0000000..505aeee --- /dev/null +++ b/src/machines/m_ali.c @@ -0,0 +1,116 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the ALi-based machines. + * + * Version: @(#)m_ali.c 1.0.8 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/ali1429.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Allocate machine device to system. */ + device_add_ex(info, arg); + + device_add(&ali1429_device); + + switch(info->local) { + case 0: /* AMI 486 (ALi-1429) */ + /*FALLTHROUGH*/ + + case 1: /* AMI Win486 (ALi-1429) */ + m_at_common_ide_init(); + device_add(&fdc_at_device); + device_add(&keyboard_at_ami_device); + break; + } + + return(arg); +} + + +static const machine_t ami486_info = { + MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 1, 64, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_ali1429_ami = { + "AMI 486 (ALi-1429)", + DEVICE_ROOT, + 0, + L"ali1429/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &ami486_info, + NULL +}; + + +static const machine_t win486_info = { + MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 1, 64, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_ali1429_win = { + "AMI Win486 (ALi-1429)", + DEVICE_ROOT, + 1, + L"ali1429/ami_win", + common_init, NULL, NULL, + NULL, NULL, NULL, + &win486_info, + NULL +}; diff --git a/src/machines/m_amstrad.c b/src/machines/m_amstrad.c index 8a9a34f..0444aa7 100644 --- a/src/machines/m_amstrad.c +++ b/src/machines/m_amstrad.c @@ -1,1470 +1,1096 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Emulation of the Amstrad series of PC's: PC1512, PC1640 and - * PC200, including their keyboard, mouse and video devices, as - * well as the PC2086 and PC3086 systems. - * - * PC1512: 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. - * - * PC1640: Mostly standard EGA, but with CGA & Hercules emulation. - * - * PC200: 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. - * - * TODO: This module is not complete yet: - * PC1512: The BIOS assumes 512K RAM, because I cannot figure out how to - * read the status of the LK4 jumper on the mainboard, which is - * somehow linked to the bus gate array on the NDMACS line... - * PC1612: EGA mode does not seem to work in the PC1640; it works fine - * in alpha mode, but in highres ("ECD350") mode, it displays - * some semi-random junk. Video-memory pointer maybe? - * BIOSES: I need to re-do the bios.txt format so we can load non-BIOS - * ROM files for a given machine, such as font roms here.. - * - * Version: @(#)m_amstrad.c 1.0.23 2019/03/07 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#define dbglog kbd_log -#include "../emu.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../nvr.h" -#include "../devices/system/nmi.h" -#include "../devices/system/pic.h" -#include "../devices/system/pit.h" -#include "../devices/system/ppi.h" -#include "../devices/ports/parallel.h" -#include "../devices/input/keyboard.h" -#include "../devices/input/mouse.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/sound/sound.h" -#include "../devices/sound/snd_speaker.h" -#include "../devices/video/video.h" -#include "../devices/video/vid_cga.h" -#include "../devices/video/vid_ega.h" -#include "../plat.h" -#include "machine.h" - - -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_LOCK 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 - - -typedef struct { - rom_t bios_rom; /* 1640 */ - cga_t cga; /* 1640/200 */ - ega_t ega; /* 1640 */ - uint8_t crtc[32]; - int crtcreg; - int cga_enabled; /* 1640 */ - int fontbase; /* 1512/200 */ - uint8_t cgacol, - cgamode, - stat; - uint8_t plane_write, /* 1512/200 */ - plane_read, /* 1512/200 */ - border; /* 1512/200 */ - int linepos, - displine; - int sc, vc; - int cgadispon; - int con, coff, - cursoron, - cgablink; - int64_t vsynctime; - int vadj; - uint16_t ma, maback; - int dispon; - int blink; - int64_t dispontime, /* 1512/1640 */ - dispofftime; /* 1512/1640 */ - int64_t vidtime; /* 1512/1640 */ - int firstline, - lastline; - uint8_t *vram; - uint8_t fontdat[1024][8]; /* 1512/200 */ -} amsvid_t; - -typedef struct { - /* Machine stuff. */ - int8_t type; - uint8_t dead; - uint8_t stat1, - stat2; - - /* Keyboard stuff. */ - int8_t wantirq; - uint8_t key_waiting; - uint8_t pa; - uint8_t pb; - - /* Mouse stuff. */ - uint8_t mousex, - mousey; - int oldb; - - /* Video stuff. */ - amsvid_t *vid; -} amstrad_t; - - -static uint8_t key_queue[16]; -static int key_queue_start = 0, - key_queue_end = 0; -static const uint8_t crtc_mask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, - 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static const video_timings_t pc1512_timing = {VID_BUS,0,0,0,0,0,0}; -static const video_timings_t pc1640_timing = {VID_ISA,8,16,32,8,16,32}; -static const video_timings_t pc200_timing = {VID_ISA,8,16,32,8,16,32}; -static const video_timings_t pvga1a_timing = {VID_ISA,6,8,16,6,8,16}; -static const video_timings_t wd90c11_timing = {VID_ISA,3,3,6,5,5,10}; - - -static void -recalc_timings_1512(amsvid_t *vid) -{ - double _dispontime, _dispofftime, disptime; - - disptime = 128; /*Fixed on PC1512*/ - _dispontime = 80; - _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST; - _dispofftime *= CGACONST; - vid->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - vid->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -static void -vid_out_1512(uint16_t addr, uint8_t val, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - uint8_t old; - - switch (addr) { - case 0x03d4: - vid->crtcreg = val & 31; - return; - - case 0x03d5: - old = vid->crtc[vid->crtcreg]; - vid->crtc[vid->crtcreg] = val & crtc_mask[vid->crtcreg]; - if (old != val) { - if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { - fullchange = changeframecount; - recalc_timings_1512(vid); - } - } - return; - - case 0x03d8: - if ((val & 0x12) == 0x12 && (vid->cgamode & 0x12) != 0x12) { - vid->plane_write = 0xf; - vid->plane_read = 0; - } - vid->cgamode = val; - return; - - case 0x03d9: - vid->cgacol = val; - return; - - case 0x03dd: - vid->plane_write = val; - return; - - case 0x03de: - vid->plane_read = val & 3; - return; - - case 0x03df: - vid->border = val; - return; - } -} - - -static uint8_t -vid_in_1512(uint16_t addr, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - uint8_t ret = 0xff; - - switch (addr) { - case 0x03d4: - ret = vid->crtcreg; - - case 0x03d5: - ret = vid->crtc[vid->crtcreg]; - - case 0x03da: - ret = vid->stat; - } - - return(ret); -} - - -static void -vid_write_1512(uint32_t addr, uint8_t val, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - cycles -= 12; - addr &= 0x3fff; - - if ((vid->cgamode & 0x12) == 0x12) { - if (vid->plane_write & 0x01) - vid->vram[addr] = val; - if (vid->plane_write & 0x02) - vid->vram[addr | 0x4000] = val; - if (vid->plane_write & 0x04) - vid->vram[addr | 0x8000] = val; - if (vid->plane_write & 0x08) - vid->vram[addr | 0xc000] = val; - } else - vid->vram[addr] = val; -} - - -static uint8_t -vid_read_1512(uint32_t addr, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - cycles -= 12; - addr &= 0x3fff; - - if ((vid->cgamode & 0x12) == 0x12) - return(vid->vram[addr | (vid->plane_read << 14)]); - - return(vid->vram[addr]); -} - - -static void -vid_poll_1512(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - uint8_t chr, attr; - uint16_t dat, dat2, dat3, dat4; - int cols[4]; - int col; - int oldsc; - - if (! vid->linepos) { - vid->vidtime += vid->dispofftime; - vid->stat |= 1; - vid->linepos = 1; - oldsc = vid->sc; - if (vid->dispon) { - if (vid->displine < vid->firstline) { - vid->firstline = vid->displine; - video_blit_wait_buffer(); - } - vid->lastline = vid->displine; - - for (c = 0; c < 8; c++) { - if ((vid->cgamode & 0x12) == 0x12) { - screen->line[vid->displine][c].pal = (vid->border & 15) + 16; - if (vid->cgamode & 1) - screen->line[vid->displine][c + (vid->crtc[1] << 3) + 8].pal = 0; - else - screen->line[vid->displine][c + (vid->crtc[1] << 4) + 8].pal = 0; - } else { - screen->line[vid->displine][c].pal = (vid->cgacol & 15) + 16; - if (vid->cgamode & 1) - screen->line[vid->displine][c + (vid->crtc[1] << 3) + 8].pal = (vid->cgacol & 15) + 16; - else - screen->line[vid->displine][c + (vid->crtc[1] << 4) + 8].pal = (vid->cgacol & 15) + 16; - } - } - if (vid->cgamode & 1) { - for (x = 0; x < 80; x++) { - chr = vid->vram[ ((vid->ma << 1) & 0x3fff)]; - attr = vid->vram[(((vid->ma << 1) + 1) & 0x3fff)]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->cgamode & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - if (drawcursor) { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 3) + c + 8].pal = cols[(vid->fontdat[chr + vid->fontbase][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 3) + c + 8].pal = cols[(vid->fontdat[chr + vid->fontbase][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - vid->ma++; - } - } else if (! (vid->cgamode & 2)) { - for (x = 0; x < 40; x++) { - chr = vid->vram[((vid->ma << 1) & 0x3fff)]; - attr = vid->vram[(((vid->ma << 1) + 1) & 0x3fff)]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->cgamode & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((vid->blink & 16) && (attr & 0x80)) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - vid->ma++; - if (drawcursor) { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(vid->fontdat[chr + vid->fontbase][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(vid->fontdat[chr + vid->fontbase][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } else if (! (vid->cgamode & 16)) { - cols[0] = (vid->cgacol & 15) | 16; - col = (vid->cgacol & 16) ? 24 : 16; - if (vid->cgamode & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else if (vid->cgacol & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - for (x = 0; x < 40; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[dat >> 14]; - dat <<= 2; - } - } - } else { - for (x = 0; x < 40; x++) { - ca = ((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000); - dat = (vid->vram[ca] << 8) | vid->vram[ca + 1]; - dat2 = (vid->vram[ca + 0x4000] << 8) | vid->vram[ca + 0x4001]; - dat3 = (vid->vram[ca + 0x8000] << 8) | vid->vram[ca + 0x8001]; - dat4 = (vid->vram[ca + 0xc000] << 8) | vid->vram[ca + 0xc001]; - - vid->ma++; - for (c = 0; c < 16; c++) { - screen->line[vid->displine][(x << 4) + c + 8].pal = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16; - dat <<= 1; - dat2 <<= 1; - dat3 <<= 1; - dat4 <<= 1; - } - } - } - } else { - cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16; - if (vid->cgamode & 1) - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); - else - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); - } - - vid->sc = oldsc; - if (vid->vsynctime) - vid->stat |= 8; - vid->displine++; - if (vid->displine >= 360) - vid->displine = 0; - } else { - vid->vidtime += vid->dispontime; - if ((vid->lastline - vid->firstline) == 199) - vid->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ - if (vid->dispon) - vid->stat &= ~1; - vid->linepos = 0; - if (vid->vsynctime) { - vid->vsynctime--; - if (! vid->vsynctime) - vid->stat &= ~8; - } - if (vid->sc == (vid->crtc[11] & 31)) { - vid->con = 0; - vid->coff = 1; - } - if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - vid->vadj--; - if (! vid->vadj) { - vid->dispon = 1; - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; - } - } else if (vid->sc == vid->crtc[9]) { - vid->maback = vid->ma; - vid->sc = 0; - vid->vc++; - vid->vc &= 127; - - if (vid->displine == 32) { - vid->vc = 0; - vid->vadj = 6; - if ((vid->crtc[10] & 0x60) == 0x20) - vid->cursoron = 0; - else - vid->cursoron = vid->blink & 16; - } - - if (vid->displine >= 262) { - vid->dispon = 0; - vid->displine = 0; - vid->vsynctime = 46; - - if (vid->cgamode&1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - vid->lastline++; - - if ((x != xsize) || ((vid->lastline - vid->firstline) != ysize) || video_force_resize_get()) { - xsize = x; - ysize = vid->lastline - vid->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, (ysize << 1) + 16); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - video_blit_start(1, 0, vid->firstline - 4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8); - - video_res_x = xsize - 16; - video_res_y = ysize; - if (vid->cgamode & 1) { - video_res_x /= 8; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->cgamode & 2)) { - video_res_x /= 16; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->cgamode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else { - video_bpp = 4; - } - - vid->firstline = 1000; - vid->lastline = 0; - vid->blink++; - } - } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - } - if (vid->sc == (vid->crtc[10] & 31)) - vid->con = 1; - } -} - - -static void -vid_close_1512(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - free(vid->vram); - free(vid); -} - - -static void -vid_speed_change_1512(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - recalc_timings_1512(vid); -} - - -static void -vid_init_1512(amstrad_t *ams, const wchar_t *fn, int num) -{ - amsvid_t *vid; - FILE *fp; - int c, d; - - /* Allocate a video controller block. */ - vid = (amsvid_t *)mem_alloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); - - /* Load the PC1512 CGA Character Set ROM. */ - fp = plat_fopen(rom_path(fn), L"rb"); - if (fp != NULL) { - if (num == FONT_CGA_THICK) { - /* Use the second ("thick") font in the ROM. */ - (void)fseek(fp, 2048, SEEK_SET); - } - - /* The ROM has 4 fonts. */ - for (d = 0; d < 4; d++) { - /* 8x8 CGA. */ - for (c = 0; c < 256; c++) - fread(&vid->fontdat[256 * d + c], 1, 8, fp); - } - - (void)fclose(fp); - } else { - ERRLOG("AMSTRAD: cannot load fonts from '%ls'\n", fn); - return; - } - - /* Add the device to the system. */ - device_add_ex(&m_amstrad_1512_device, vid); - - vid->fontbase = (device_get_config_int("codepage") & 3) * 256; - - vid->vram = (uint8_t *)mem_alloc(0x10000); - vid->cgacol = 7; - vid->cgamode = 0x12; - - timer_add(vid_poll_1512, &vid->vidtime, TIMER_ALWAYS_ENABLED, vid); - mem_map_add(&vid->cga.mapping, 0xb8000, 0x08000, - vid_read_1512, NULL, NULL, vid_write_1512, NULL, NULL, - NULL, 0, vid); - io_sethandler(0x03d0, 16, - vid_in_1512, NULL, NULL, vid_out_1512, NULL, NULL, vid); - - overscan_x = overscan_y = 16; - - video_palette_rebuild(); - - video_inform(VID_TYPE_CGA, &pc1512_timing); - - ams->vid = vid; -} - - -static const device_config_t pc1512_config[] = { - { - "codepage", "Hardware font", CONFIG_SELECTION, "", 3, - { - { - "US English", 3 - }, - // FIXME: what is 2 ?? - { - "Danish", 1 - }, - { - "Greek", 0 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - - -const device_t m_amstrad_1512_device = { - "Amstrad PC1512", - 0, 0, - NULL, vid_close_1512, NULL, - NULL, - vid_speed_change_1512, - NULL, - &pc1512_timing, - pc1512_config -}; - - -static void -recalc_timings_1640(amsvid_t *vid) -{ - cga_recalctimings(&vid->cga); - ega_recalctimings(&vid->ega); - - if (vid->cga_enabled) { - overscan_x = overscan_y = 16; - - vid->dispontime = vid->cga.dispontime; - vid->dispofftime = vid->cga.dispofftime; - } else { - overscan_x = 16; overscan_y = 28; - - vid->dispontime = vid->ega.dispontime; - vid->dispofftime = vid->ega.dispofftime; - } -} - - -static void -vid_out_1640(uint16_t addr, uint8_t val, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - switch (addr) { - case 0x03db: - vid->cga_enabled = val & 0x40; - if (vid->cga_enabled) { - mem_map_enable(&vid->cga.mapping); - mem_map_disable(&vid->ega.mapping); - video_inform(VID_TYPE_CGA, &pc1640_timing); - } else { - mem_map_disable(&vid->cga.mapping); - switch (vid->ega.gdcreg[6] & 0xc) { - case 0x0: /*128k at A0000*/ - mem_map_set_addr(&vid->ega.mapping, - 0xa0000, 0x20000); - break; - - case 0x4: /*64k at A0000*/ - mem_map_set_addr(&vid->ega.mapping, - 0xa0000, 0x10000); - break; - - case 0x8: /*32k at B0000*/ - mem_map_set_addr(&vid->ega.mapping, - 0xb0000, 0x08000); - break; - - case 0xC: /*32k at B8000*/ - mem_map_set_addr(&vid->ega.mapping, - 0xb8000, 0x08000); - break; - } - video_inform(VID_TYPE_SPEC, &pc1640_timing); - } - return; - } - - if (vid->cga_enabled) - cga_out(addr, val, &vid->cga); - else - ega_out(addr, val, &vid->ega); -} - - -static uint8_t -vid_in_1640(uint16_t addr, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - -#if 0 - switch (addr) { - } -#endif - - if (vid->cga_enabled) - return(cga_in(addr, &vid->cga)); - else - return(ega_in(addr, &vid->ega)); -} - - -static void -vid_poll_1640(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - if (vid->cga_enabled) { - overscan_x = overscan_y = 16; - - vid->cga.vidtime = vid->vidtime; - cga_poll(&vid->cga); - vid->vidtime = vid->cga.vidtime; - } else { - overscan_x = 16; overscan_y = 28; - - vid->ega.vidtime = vid->vidtime; - ega_poll(&vid->ega); - vid->vidtime = vid->ega.vidtime; - } -} - - -static void -vid_init_1640(amstrad_t *ams, wchar_t *fn, int sz) -{ - amsvid_t *vid; - - /* Allocate a video controller block. */ - vid = (amsvid_t *)mem_alloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); - - /* Load the BIOS. */ - rom_init(&vid->bios_rom, fn, 0xc0000, sz, sz - 1, 0, 0); - - ega_init(&vid->ega, 9, 0); - vid->cga.vram = vid->ega.vram; - vid->cga_enabled = 1; - cga_init(&vid->cga); - - mem_map_add(&vid->cga.mapping, 0xb8000, 0x08000, - cga_read,NULL,NULL, cga_write,NULL,NULL, NULL, 0, &vid->cga); - mem_map_add(&vid->ega.mapping, 0, 0, - ega_read,NULL,NULL, ega_write,NULL,NULL, NULL, 0, &vid->ega); - io_sethandler(0x03a0, 64, - vid_in_1640, NULL, NULL, vid_out_1640, NULL, NULL, vid); - - timer_add(vid_poll_1640, &vid->vidtime, TIMER_ALWAYS_ENABLED, vid); - - overscan_x = overscan_y = 16; - - video_inform(VID_TYPE_CGA, &pc1640_timing); - - ams->vid = vid; -} - - -static void -vid_close_1640(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - free(vid->ega.vram); - free(vid); -} - - -static void -vid_speed_changed_1640(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - recalc_timings_1640(vid); -} - - -static const device_t vid_1640_device = { - "Amstrad PC1640", - 0, 0, - NULL, vid_close_1640, NULL, - NULL, - vid_speed_changed_1640, - NULL, - &pc1640_timing, - NULL -}; - - -static void -vid_out_200(uint16_t addr, uint8_t val, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - cga_t *cga = &vid->cga; - uint8_t old; - - switch (addr) { - case 0x03d5: - if (!(vid->plane_read & 0x40) && cga->crtcreg <= 11) { - if (vid->plane_read & 0x80) - nmi = 1; - - vid->plane_write = 0x20 | (cga->crtcreg & 0x1f); - vid->border = val; - return; - } - old = cga->crtc[cga->crtcreg]; - cga->crtc[cga->crtcreg] = val & crtc_mask[cga->crtcreg]; - if (old != val) { - if (cga->crtcreg < 0xe || cga->crtcreg > 0x10) { - fullchange = changeframecount; - cga_recalctimings(cga); - } - } - return; - - case 0x03d8: - old = cga->cgamode; - cga->cgamode = val; - if ((cga->cgamode ^ old) & 3) - cga_recalctimings(cga); - vid->plane_write |= 0x80; - if (vid->plane_read & 0x80) - nmi = 1; - return; - - case 0x03de: - vid->plane_read = val; - vid->plane_write = 0x1f; - if (val & 0x80) - vid->plane_write |= 0x40; - return; - } - - cga_out(addr, val, cga); -} - - -static uint8_t -vid_in_200(uint16_t addr, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - cga_t *cga = &vid->cga; - uint8_t ret; - - switch (addr) { - case 0x03d8: - return(cga->cgamode); - - case 0x03dd: - ret = vid->plane_write; - vid->plane_write &= 0x1f; - nmi = 0; - return(ret); - - case 0x03de: - return((vid->plane_read & 0xc7) | 0x10); /*External CGA*/ - - case 0x03df: - return(vid->border); - } - - return(cga_in(addr, cga)); -} - - -static void -vid_init_200(amstrad_t *dev, const wchar_t *fn) -{ - amsvid_t *vid; - cga_t *cga; - FILE *fp; - int c, d; - - /* Allocate a video controller block. */ - vid = (amsvid_t *)mem_alloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); - - /* Add the device to the system. */ - device_add_ex(&m_amstrad_200_device, vid); - - vid->fontbase = (device_get_config_int("codepage") & 3) * 256; - - /* Load the PC200 CGA Character Set ROM. */ - fp = plat_fopen(rom_path(fn), L"rb"); - if (fp != NULL) { - /* The ROM has 4 fonts. */ - for (d = 0; d < 4; d++) { - /* 8x14 MDA in 8x16 cell. */ - for (c = 0; c < 256; c++) - fread(&fontdatm[256 * d + c], 1, 16, fp); - - /* 8x8 CGA in 8x16 cell. */ - for (c = 0; c < 256; c++) { - fread(&fontdat[256 * d + c], 1, 8, fp); - fseek(fp, 8, SEEK_CUR); - } - } - - (void)fclose(fp); - } else { - ERRLOG("AMSTRAD: cannot load fonts from '%ls'\n", fn); - return; - } - - cga = &vid->cga; - cga->vram = (uint8_t *)mem_alloc(0x4000); - cga_init(cga); - vid->cga.fontbase = vid->fontbase; - - mem_map_add(&vid->cga.mapping, 0xb8000, 0x08000, - cga_read,NULL,NULL, cga_write,NULL,NULL, NULL, 0, cga); - io_sethandler(0x03d0, 16, - vid_in_200, NULL, NULL, vid_out_200, NULL, NULL, vid); - - timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); - - overscan_x = overscan_y = 16; - - video_palette_rebuild(); - - video_inform(VID_TYPE_CGA, &pc200_timing); - - dev->vid = vid; -} - - -static void -vid_close_200(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - free(vid->cga.vram); - - free(vid); -} - - -static void -vid_speed_changed_200(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - cga_recalctimings(&vid->cga); -} - - -/* - * TODO: Should have options here for: - * - * > Video emulation (CGA / MDA) - * > Display port (TTL or RF) - */ -static const device_config_t pc200_config[] = { - { - "codepage", "Hardware font", CONFIG_SELECTION, "", 3, - { - { - "US English", 3 - }, - { - "Portugese", 2 - }, - { - "Norwegian", 1 - }, - { - "Greek", 0 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - - -const device_t m_amstrad_200_device = { - "Amstrad PC200", - 0, 0, - NULL, vid_close_200, NULL, - NULL, - vid_speed_changed_200, - NULL, - &pc200_timing, - pc200_config -}; - - -static void -mse_write(uint16_t addr, uint8_t val, void *priv) -{ - amstrad_t *dev = (amstrad_t *)priv; - - if (addr == 0x0078) - dev->mousex = 0; - else - dev->mousey = 0; -} - - -static uint8_t -mse_read(uint16_t addr, void *priv) -{ - amstrad_t *dev = (amstrad_t *)priv; - - if (addr == 0x0078) - return(dev->mousex); - - return(dev->mousey); -} - - -static int -mse_poll(int x, int y, int z, int b, void *priv) -{ - amstrad_t *dev = (amstrad_t *)priv; - - dev->mousex += x; - dev->mousey -= y; - - if ((b & 1) && !(dev->oldb & 1)) - keyboard_send(0x7e); - if ((b & 2) && !(dev->oldb & 2)) - keyboard_send(0x7d); - if (!(b & 1) && (dev->oldb & 1)) - keyboard_send(0xfe); - if (!(b & 2) && (dev->oldb & 2)) - keyboard_send(0xfd); - - dev->oldb = b; - - return(1); -} - - -static void -kbd_adddata(uint16_t val) -{ - key_queue[key_queue_end] = (uint8_t)(val & 0xff); - DBGLOG(1, "AMSkb: %02X added to key queue at %i\n", val, key_queue_end); - key_queue_end = (key_queue_end + 1) & 0x0f; -} - - -static void -kbd_adddata_ex(uint16_t val) -{ - kbd_adddata_process(val, kbd_adddata); -} - - -static void -kbd_write(uint16_t port, uint8_t val, void *priv) -{ - amstrad_t *dev = (amstrad_t *)priv; - - DBGLOG(2, "AMSkb: write %04X %02X %02X\n", port, val, dev->pb); - - switch (port) { - case 0x61: - /* - * PortB - System Control. - * - * 7 Enable Status-1/Disable Keyboard Code on Port A. - * 6 Enable incoming Keyboard Clock. - * 5 Prevent external parity errors from causing NMI. - * 4 Disable parity checking of on-board system Ram. - * 3 Undefined (Not Connected). - * 2 Enable Port C LSB / Disable MSB. (See 1.8.3) - * 1 Speaker Drive. - * 0 8253 GATE 2 (Speaker Modulate). - * - * This register is controlled by BIOS and/or ROS. - */ - DBGLOG(1, "AMSkb: write PB %02x (%02x)\n", val, dev->pb); - if (!(dev->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/ - DEBUG("AMSkb: reset keyboard\n"); - kbd_adddata(0xaa); - } - dev->pb = val; - ppi.pb = val; - - timer_process(); - timer_update_outstanding(); - - speaker_update(); - speaker_gated = val & 0x01; - speaker_enable = val & 0x02; - if (speaker_enable) - speaker_was_enable = 1; - pit_set_gate(&pit, 2, val & 0x01); - - if (val & 0x80) { - /* Keyboard enabled, so enable PA reading. */ - dev->pa = 0x00; - } - break; - - case 0x63: - break; - - case 0x64: - dev->stat1 = val; - break; - - case 0x65: - dev->stat2 = val; - break; - - case 0x66: - pc_reset(1); - break; - - default: - ERRLOG("AMSkb: bad keyboard write %04X %02X\n", port, val); - } -} - - -static uint8_t -kbd_read(uint16_t port, void *priv) -{ - amstrad_t *dev = (amstrad_t *)priv; - uint8_t ret = 0xff; - - switch (port) { - case 0x60: - if (dev->pb & 0x80) { - /* - * PortA - System Status 1 - * - * 7 Always 0 (KBD7) - * 6 Second Floppy disk drive installed (KBD6) - * 5 DDM1 - Default Display Mode bit 1 (KBD5) - * 4 DDM0 - Default Display Mode bit 0 (KBD4) - * 3 Always 1 (KBD3) - * 2 Always 1 (KBD2) - * 1 8087 NDP installed (KBD1) - * 0 Always 1 (KBD0) - * - * DDM00 - * 00 unknown, external color? - * 01 Color,alpha,40x25, bright white on black. - * 10 Color,alpha,80x25, bright white on black. - * 11 External Monochrome,80x25. - * - * Following a reset, the hardware selects VDU mode - * 2. The ROS then sets the initial VDU state based - * on the DDM value. - */ - ret = (0x0d | dev->stat1) & 0x7f; - } else { - ret = dev->pa; - if (key_queue_start == key_queue_end) { - dev->wantirq = 0; - } else { - dev->key_waiting = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - dev->wantirq = 1; - } - } - break; - - case 0x61: - ret = dev->pb; - break; - - case 0x62: - /* - * PortC - System Status 2. - * - * 7 On-board system RAM parity error. - * 6 External parity error (I/OCHCK from expansion bus). - * 5 8253 PIT OUT2 output. - * 4 Undefined (Not Connected). - *------------------------------------------- - * LSB MSB (depends on PB2) - *------------------------------------------- - * 3 RAM3 Undefined - * 2 RAM2 Undefined - * 1 RAM1 Undefined - * 0 RAM0 RAM4 - * - * PC7 is forced to 0 when on-board system RAM parity - * checking is disabled by PB4. - * - * RAM4:0 - * 01110 512K bytes on-board. - * 01111 544K bytes (32K external). - * 10000 576K bytes (64K external). - * 10001 608K bytes (96K external). - * 10010 640K bytes (128K external or fitted on-board). - */ - if (dev->pb & 0x04) - ret = dev->stat2 & 0x0f; - else - ret = dev->stat2 >> 4; - ret |= (ppispeakon ? 0x20 : 0); - if (nmi) - ret |= 0x40; - break; - - default: - ERRLOG("AMDkb: bad keyboard read %04X\n", port); - } - - return(ret); -} - - -static void -kbd_poll(void *priv) -{ - amstrad_t *dev = (amstrad_t *)priv; - - keyboard_delay += (1000 * TIMER_USEC); - - if (dev->wantirq) { - dev->wantirq = 0; - dev->pa = dev->key_waiting; - picint(2); - DBGLOG(1, "AMSkb: take IRQ\n"); - } - - if (key_queue_start != key_queue_end && !dev->pa) { - dev->key_waiting = key_queue[key_queue_start]; - DBGLOG(1, "AMSkb: reading %02X from the key queue at %i\n", - dev->key_waiting, key_queue_start); - key_queue_start = (key_queue_start + 1) & 0x0f; - dev->wantirq = 1; - } -} - - -static void -ams_write(uint16_t port, uint8_t val, void *priv) -{ - amstrad_t *dev = (amstrad_t *)priv; - - switch (port) { - case 0xdead: - dev->dead = val; - break; - } -} - - -static uint8_t -ams_read(uint16_t port, void *priv) -{ - amstrad_t *dev = (amstrad_t *)priv; - uint8_t ret = 0xff; - - switch (port) { - case 0x0379: /* printer control, also set LK1-3. - * 0 English Language. - * 1 German Language. - * 2 French Language. - * 3 Spanish Language. - * 4 Danish Language. - * 5 Swedish Language. - * 6 Italian Language. - * 7 Diagnostic Mode. - */ - ret = 0x02; /* ENGLISH. no Diags mode */ - break; - - case 0x037a: /* printer status */ - switch(dev->type) { - case 0: - ret = 0x20; - break; - - case 2: - ret = 0x80; - break; - - default: - ret = 0x00; - } - break; - - case 0xdead: - ret = dev->dead; - break; - } - - return(ret); -} - - -static void -amstrad_common_init(const machine_t *model, void *arg, int type) -{ - romdef_t *roms = (romdef_t *)arg; - amstrad_t *dev; - - dev = (amstrad_t *)mem_alloc(sizeof(amstrad_t)); - memset(dev, 0x00, sizeof(amstrad_t)); - dev->type = type; - - machine_common_init(model, arg); - - nmi_init(); - - switch(dev->type) { - case 0: /* 1512 */ - device_add(&fdc_xt_device); - if (video_card == VID_INTERNAL) { - /* Initialize the internal CGA controller. */ - vid_init_1512(dev, roms->fontfn, roms->fontnum); - } - break; - - case 1: /* 1640 */ - device_add(&fdc_xt_device); - if (video_card == VID_INTERNAL) { - /* Initialize the internal CGA/EGA controller. */ - vid_init_1640(dev, roms->vidfn, roms->vidsz); - device_add_ex(&vid_1640_device, dev->vid); - } - break; - - case 2: /* PC200 */ - device_add(&fdc_xt_device); - if (video_card == VID_INTERNAL) { - /* Initialize the internal CGA controller. */ - vid_init_200(dev, roms->fontfn); - } - break; - - case 3: /* PC2086 */ - device_add(&fdc_at_actlow_device); - if (video_card == VID_INTERNAL) { - device_add(¶dise_pvga1a_pc2086_device); - video_inform(VID_TYPE_SPEC, &pvga1a_timing); - } - break; - - case 4: /* PC3086 */ - device_add(&fdc_at_actlow_device); - if (video_card == VID_INTERNAL) { - device_add(¶dise_pvga1a_pc3086_device); - video_inform(VID_TYPE_SPEC, &pvga1a_timing); - } - break; - - case 5: /* MEGAPC */ - device_add(&fdc_at_actlow_device); - if (video_card == VID_INTERNAL) { - device_add(¶dise_wd90c11_megapc_device); - video_inform(VID_TYPE_SPEC, &wd90c11_timing); - } - break; - } - - device_add(&amstrad_nvr_device); - -//FIXME: parallel_remove_amstrad(); - - io_sethandler(0x0078, 1, - mse_read, NULL, NULL, mse_write, NULL, NULL, dev); - - io_sethandler(0x007a, 1, - mse_read, NULL, NULL, mse_write, NULL, NULL, dev); - - io_sethandler(0x0379, 2, - ams_read, NULL, NULL, NULL, NULL, NULL, dev); - - io_sethandler(0xdead, 1, - ams_read, NULL, NULL, ams_write, NULL, NULL, dev); - - /* Initialize the (custom) keyboard/mouse interface. */ - dev->wantirq = 0; - io_sethandler(0x0060, 7, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, dev); - keyboard_set_table(scancode_xt); - keyboard_send = kbd_adddata_ex; - keyboard_scan = 1; - - /* Tell mouse driver about our internal mouse. */ - if (mouse_type == MOUSE_INTERNAL) { - mouse_reset(); - mouse_set_poll(mse_poll, dev); - } -} - - -void -m_amstrad_1512_init(const machine_t *model, void *arg) -{ - amstrad_common_init(model, arg, 0); -} - - -void -m_amstrad_1640_init(const machine_t *model, void *arg) -{ - amstrad_common_init(model, arg, 1); -} - - -void -m_amstrad_200_init(const machine_t *model, void *arg) -{ - amstrad_common_init(model, arg, 2); -} - - -void -m_amstrad_2086_init(const machine_t *model, void *arg) -{ - amstrad_common_init(model, arg, 3); -} - - -void -m_amstrad_3086_init(const machine_t *model, void *arg) -{ - amstrad_common_init(model, arg, 4); -} - - -void -m_amstrad_mega_init(const machine_t *model, void *arg) -{ - amstrad_common_init(model, arg, 5); -} +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of the Amstrad series of PC's: PC1512, PPC512, + * PC1640 and PC200, including their keyboard/mouse devices, + * as well as the PC2086 and PC3086 systems. + * + * **NOTE** The PC200 still has the weirdness that if Television mode + * is selected, it will ignore that, and select CGA mode in + * 80 columns. To be fixed... + * Also, the DDM bits stuff needs to be verified. + * + * Version: @(#)m_amstrad.c 1.0.25 2019/04/20 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 John Elliott. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#define dbglog kbd_log +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../timer.h" +#include "../device.h" +#include "../machines/machine.h" +#include "../nvr.h" +#include "../devices/system/nmi.h" +#include "../devices/system/pic.h" +#include "../devices/system/pit.h" +#include "../devices/system/ppi.h" +#include "../devices/ports/parallel.h" +#include "../devices/input/keyboard.h" +#include "../devices/input/mouse.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/sound/sound.h" +#include "../devices/sound/snd_speaker.h" +#include "../devices/video/video.h" +#include "../plat.h" +#include "machine.h" +#include "m_amstrad.h" + + +/* Values for LK1-3 jumpers (BIOS language.) */ +#define LK13_EN 0 /* English */ +#define LK13_DE 1 /* German */ +#define LK13_FR 2 /* French */ +#define LK13_ES 3 /* Spanish */ +#define LK13_DK 4 /* Danish */ +#define LK13_SE 5 /* Swedish */ +#define LK13_IT 6 /* Italian */ +#define LK13_DIAG 7 /* Diagnostic Mode */ + +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_LOCK 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 + + +typedef struct { + /* Machine stuff. */ + int8_t type; + uint8_t dead; + uint8_t stat1, + stat2; + + /* Configuration options. */ + int flopswap; + int codepage; + int language; + int vidtype; + int disptype; + + /* Keyboard stuff. */ + int8_t wantirq; + uint8_t key_waiting; + uint8_t pa, + pb; + + /* Video stuff. */ + void *vid; + + /* Mouse stuff. */ + uint8_t mousex, + mousey; + int oldb; +} amstrad_t; + + +static const video_timings_t pvga1a_timing = {VID_ISA,6,8,16,6,8,16}; +static const video_timings_t wd90c11_timing = {VID_ISA,3,3,6,5,5,10}; + +static uint8_t key_queue[16]; +static int key_queue_start = 0, + key_queue_end = 0; + + +static void +mse_write(uint16_t port, uint8_t val, void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + + if (port == 0x0078) + dev->mousex = 0; + else + dev->mousey = 0; +} + + +static uint8_t +mse_read(uint16_t port, void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + uint8_t ret; + + if (port == 0x0078) { + ret = dev->mousex; + dev->mousex = 0; + } else { + ret = dev->mousey; + dev->mousey = 0; + } + + return(ret); +} + + +static int +mse_poll(int x, int y, int z, int b, void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + + dev->mousex += x; + dev->mousey -= y; + + if ((b & 1) && !(dev->oldb & 1)) + keyboard_send(0x7e); + if (!(b & 1) && (dev->oldb & 1)) + keyboard_send(0xfe); + + if ((b & 2) && !(dev->oldb & 2)) + keyboard_send(0x7d); + if (!(b & 2) && (dev->oldb & 2)) + keyboard_send(0xfd); + + dev->oldb = b; + + return(1); +} + + +static void +kbd_adddata(uint16_t val) +{ + key_queue[key_queue_end] = (uint8_t)(val & 0xff); + key_queue_end = (key_queue_end + 1) & 0x0f; +} + + +static void +kbd_adddata_ex(uint16_t val) +{ + kbd_adddata_process(val, kbd_adddata); +} + + +static void +kbd_write(uint16_t port, uint8_t val, void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + + DBGLOG(2, "AMSkb: write(%04x,%02x) pb=%02x\n", port, val, dev->pb); + + switch (port) { + case 0x61: + /* + * PortB - System Control. + * + * 7 Enable Status-1/Disable Keyboard Code on Port A. + * 6 Enable incoming Keyboard Clock. + * 5 Prevent external parity errors from causing NMI. + * 4 Disable parity checking of on-board system Ram. + * 3 Undefined (Not Connected). + * 2 Enable Port C LSB / Disable MSB. (See 1.8.3) + * 1 Speaker Drive. + * 0 8253 GATE 2 (Speaker Modulate). + * + * This register is controlled by BIOS and/or ROS. + */ + DBGLOG(1, "AMSkb: write PB=%02x (%02x)\n", val, dev->pb); + if (!(dev->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/ + DEBUG("AMSkb: reset keyboard\n"); + kbd_adddata(0xaa); + } + dev->pb = val; + ppi.pb = val; + + timer_process(); + timer_update_outstanding(); + + speaker_update(); + speaker_gated = val & 0x01; + speaker_enable = val & 0x02; + if (speaker_enable) + speaker_was_enable = 1; + pit_set_gate(&pit, 2, val & 0x01); + + if (val & 0x80) { + /* Keyboard disabled, so enable PA reading. */ + dev->pa = 0x00; + } + break; + + case 0x63: + break; + + case 0x64: + /* + * ROS writes to this port the bits that can be + * read back at the KBC controller, port C, the + * the DDM bits at 7:6. + */ + dev->stat1 = val; + break; + + case 0x65: + /* + * ROS writes to this register the bits that are + * normally read out at the printer status port, + * indicating memory size, DDM and so on. + */ + dev->stat2 = val; + break; + + case 0x66: + pc_reset(1); + break; + + default: + ERRLOG("AMSkb: bad keyboard write %04X %02X\n", port, val); + } +} + + +static uint8_t +kbd_read(uint16_t port, void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x60: + if (dev->pb & 0x80) { + /* + * PortA - System Status 1 + * + * 7 Always 0 (KBD7) + * 6 Second Floppy disk drive installed (KBD6) + * 5 DDM1 - Default Display Mode bit 1 (KBD5) + * 4 DDM0 - Default Display Mode bit 0 (KBD4) + * 3 Always 1 (KBD3) + * 2 Always 1 (KBD2) + * 1 8087 NDP installed (KBD1) + * 0 Always 1 (KBD0) + * + * DDM10 + * 00 External controller + * 01 Color,alpha,40x25, bright white on black. + * 10 Color,alpha,80x25, bright white on black. + * 11 Monochrome,80x25. + * + * Following a reset, the hardware selects VDU mode + * 2. The ROS then sets the initial VDU state based + * on the DDM value. + */ + ret = (0x0d | dev->stat1) & 0x7f; + } else { + ret = dev->pa; + if (key_queue_start == key_queue_end) { + dev->wantirq = 0; + } else { + dev->key_waiting = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + dev->wantirq = 1; + } + } + break; + + case 0x61: + ret = dev->pb; + break; + + case 0x62: + /* + * PortC - System Status 2. + * + * 7 On-board system RAM parity error. + * 6 External parity error (I/OCHCK from expansion bus). + * 5 8253 PIT OUT2 output. + * 4 Undefined (Not Connected). + *------------------------------------------- + * LSB MSB (depends on PB2) + *------------------------------------------- + * 3 RAM3 Undefined + * 2 RAM2 Undefined + * 1 RAM1 Undefined + * 0 RAM0 RAM4 + * + * PC7 is forced to 0 when on-board system RAM parity + * checking is disabled by PB4. + * + * RAM4:0 + * 01110 512K bytes on-board. + * 01111 544K bytes (32K external). + * 10000 576K bytes (64K external). + * 10001 608K bytes (96K external). + * 10010 640K bytes (128K external or fitted on-board). + */ + if (dev->pb & 0x04) + ret = (dev->stat2 & 0x0f); + else + ret = (dev->stat2 >> 4); + ret |= (ppispeakon ? 0x20 : 0); + if (nmi) + ret |= 0x40; + break; + + default: + ERRLOG("AMSkb: bad keyboard read %04X\n", port); + } + + return(ret); +} + + +static void +kbd_poll(void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + + keyboard_delay += (1000 * TIMER_USEC); + + if (dev->wantirq) { + dev->wantirq = 0; + dev->pa = dev->key_waiting; + picint(1 << 1); + } + + if (key_queue_start != key_queue_end && !dev->pa) { + dev->key_waiting = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0x0f; + dev->wantirq = 1; + } +} + + +static void +ams_write(uint16_t port, uint8_t val, void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + + switch (port) { + case 0xdead: + dev->dead = val; + break; + } +} + + +static uint8_t +ams_read(uint16_t port, void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + uint8_t ddm, ret = 0xff; + int i; + + switch (port) { + case 0x0379: /* printer status, also set LK1-3. + * 0 English Language. + * 1 German Language. + * 2 French Language. + * 3 Spanish Language. + * 4 Danish Language. + * 5 Swedish Language. + * 6 Italian Language. + * 7 Diagnostic Mode. + */ + ret = dev->language; + ret ^= 0x07; /* bits inverted! */ + break; + + case 0x037a: /* printer control */ + ret = 0x00; + switch(dev->type) { + case 0: /* PC1512 */ + ret |= 0x20; + break; + + case 2: /* PC200 */ + case 3: /* PPC */ + if (dev->vid != NULL) { + /* IDA is enabled. */ + ddm = m_amstrad_ida_ddm(dev->vid); +#if 0 + ret |= ((ddm & 0x01) << 7); /* DDM0 */ + ret |= ((ddm & 0x02) << 5); /* DDM1 */ +#else + ret |= ((ddm & 0x03) << 6); /* DDM */ +#endif + } else { + /* External controller. */ + i = video_type(); + if (i == VID_TYPE_MDA) + ret |= 0xc0; /* MDA/Herc */ + else + ret |= 0x40; /* CGA */ + } + +#if 0 + if (dev->type == 3) + ret ^= 0xc0; /* bits inverted! */ +#endif + break; + + default: + break; + } + break; + + case 0x03de: + /* + * This port is only mapped in for the PC200, and + * then only if External Video controller is in use. + */ + ret = 0x20; + break; + + case 0xdead: + ret = dev->dead; + break; + } + + return(ret); +} + + +static void +amstrad_close(void *priv) +{ + amstrad_t *dev = (amstrad_t *)priv; + + free(dev); +} + + +static void * +amstrad_init(const device_t *info, void *arg) +{ + romdef_t *roms = (romdef_t *)arg; + amstrad_t *dev; + void *lpt; + + dev = (amstrad_t *)mem_alloc(sizeof(amstrad_t)); + memset(dev, 0x00, sizeof(amstrad_t)); + dev->type = info->local; + + /* Add machine device to system. */ + device_add_ex(info, dev); + + /* Force the LPT1 port disabled and add our own. */ + parallel_enabled[0] = 0; + machine_common_init(); + lpt = device_add(¶llel_1_device); + + nmi_init(); + + device_add(&amstrad_nvr_device); + + switch(dev->type) { + case 0: /* PC1512 */ + dev->codepage = device_get_config_int("codepage"); + dev->language = device_get_config_int("language"); + + /* Initialize the internal CGA controller. */ + dev->vid = m_amstrad_1512_vid_init(roms->fontfn, + roms->fontnum, + dev->codepage); + device_add(&fdc_xt_device); + parallel_set_func(lpt, ams_read, dev); + break; + + case 1: /* PC1640 */ + dev->language = device_get_config_int("language"); + + /* Initialize the internal CGA/EGA controller. */ + dev->vid = m_amstrad_1640_vid_init(roms->vidfn, roms->vidsz); + + device_add(&fdc_xt_device); + parallel_set_func(lpt, ams_read, dev); + break; + + case 2: /* PC200 */ + dev->codepage = device_get_config_int("codepage"); + dev->language = device_get_config_int("language"); + dev->flopswap = device_get_config_int("floppy_swap"); + dev->vidtype = device_get_config_int("video_emulation"); + dev->disptype = device_get_config_int("display_type"); + + if (video_card == VID_INTERNAL) { + /* Initialize the internal video controller. */ + dev->vid = m_amstrad_ida_init(dev->type, roms->fontfn, + dev->codepage, + dev->vidtype, + dev->disptype); + } else { + io_sethandler(0x03de, 1, + ams_read,NULL,NULL, NULL,NULL,NULL, dev); + } + + device_add(&fdc_xt_device); + parallel_set_func(lpt, ams_read, dev); + break; + + case 3: /* PPC */ + dev->codepage = device_get_config_int("codepage"); + dev->language = device_get_config_int("language"); + dev->vidtype = device_get_config_int("video_emulation"); + dev->disptype = device_get_config_int("display_type"); + + if (video_card == VID_INTERNAL) { + /* Initialize the internal video controller. */ + dev->vid = m_amstrad_ida_init(1, roms->fontfn, + dev->codepage, + dev->vidtype, + dev->disptype); + } + + device_add(&fdc_xt_device); + parallel_set_func(lpt, ams_read, dev); + break; + + case 4: /* PC2086 */ + if (video_card == VID_INTERNAL) { + device_add(¶dise_pvga1a_pc2086_device); + video_inform(VID_TYPE_SPEC, &pvga1a_timing); + } + device_add(&fdc_at_actlow_device); + break; + + case 5: /* PC3086 */ + if (video_card == VID_INTERNAL) { + device_add(¶dise_pvga1a_pc3086_device); + video_inform(VID_TYPE_SPEC, &pvga1a_timing); + } + device_add(&fdc_at_actlow_device); + break; + + case 6: /* MEGAPC */ + if (video_card == VID_INTERNAL) { + device_add(¶dise_wd90c11_megapc_device); + video_inform(VID_TYPE_SPEC, &wd90c11_timing); + } + device_add(&fdc_at_actlow_device); + break; + } + parallel_enabled[0] = 1; + + io_sethandler(0xdead, 1, ams_read,NULL,NULL, ams_write,NULL,NULL, dev); + + /* Initialize the (custom) keyboard interface. */ + dev->wantirq = 0; + io_sethandler(0x0060, 7, kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); + timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, dev); + keyboard_set_table(scancode_xt); + keyboard_send = kbd_adddata_ex; + keyboard_scan = 1; + + /* Initialize the (custom) mouse intercace if needed. */ + if (mouse_type == MOUSE_INTERNAL) { + io_sethandler(0x0078, 1, mse_read,NULL,NULL, mse_write,NULL,NULL, dev); + io_sethandler(0x007a, 1, mse_read,NULL,NULL, mse_write,NULL,NULL, dev); + + mouse_reset(); + + mouse_set_poll(mse_poll, dev); + } + + return(dev); +} + + +static const device_config_t pc1512_config[] = { + { + "codepage", "Hardware font", CONFIG_SELECTION, "", 3, + { + { + "US English", 3 + }, + { + "Danish", 1 + }, + { + "Greek", 0 + }, + { + NULL + } + } + }, + { + "language", "ROS Language", CONFIG_SELECTION, "", 0, + { + { + "English", 0 + }, + { + "German", 1 + }, + { + "French", 2 + }, + { + "Spanish", 3 + }, + { + "Danish", 4 + }, + { + "Swedish", 5 + }, + { + "Italian", 6 + }, + { + "DIAG Mode (English)", 7 + }, + { + NULL + } + } + }, + { + NULL + } +}; + +static const device_config_t pc1640_config[] = { + { + "language", "ROS Language", CONFIG_SELECTION, "", 0, + { + { + "English", 0 + }, + { + "German", 1 + }, + { + "French", 2 + }, + { + "Spanish", 3 + }, + { + "Danish", 4 + }, + { + "Swedish", 5 + }, + { + "Italian", 6 + }, + { + "DIAG Mode (English)", 7 + }, + { + NULL + } + } + }, +#if 1 + { + "iga", "Internal Graphics Adapter", CONFIG_SELECTION, "", 1, + { + { + "Disabled", 0 + }, + { + "Enabled", 1 + }, + { + NULL + } + } + }, + { + "iga_mode", "Inititial Video Mode", CONFIG_SELECTION, "", 2, + { + { + "Monochrome", 0 + }, + { + "CO40", 1 + }, + { + "CO80", 2 + }, + { + "ECD200", 3 + }, + { + "ECD350", 4 + }, + { + NULL + } + } + }, +#endif + { + NULL + } +}; + +static const device_config_t pc200_config[] = { + { + "codepage", "Hardware font", CONFIG_SELECTION, "", 3, + { + { + "US English", 3 + }, + { + "Portugese", 2 + }, + { + "Norwegian", 1 + }, + { + "Greek", 0 + }, + { + NULL + } + } + }, + { + "language", "ROS Language", CONFIG_SELECTION, "", 0, + { + { + "English", 0 + }, + { + "German", 1 + }, + { + "French", 2 + }, + { + "Spanish", 3 + }, + { + "Danish", 4 + }, + { + "Swedish", 5 + }, + { + "Italian", 6 + }, + { + "DIAG Mode (English)", 7 + }, + { + NULL + } + } + }, + { + "video_emulation", "Display type", CONFIG_SELECTION, "", IDA_CGA, + { + { + "CGA monitor", IDA_CGA + }, + { + "MDA monitor", IDA_MDA + }, + { + "Television", IDA_TV + }, + { + NULL + } + } + }, + { + "floppy_swap", "Swap Diskette Drives", CONFIG_SELECTION, "", 0, + { + { + "Disabled", 0 + }, + { + "Enabled", 1 + }, + { + NULL + } + } + }, +#if 0 + { + "display_type", "Monitor type", CONFIG_SELECTION, "", DISPLAY_RGB, + { + { + "RGB", DISPLAY_RGB + }, + { + "RGB (no brown)", DISPLAY_RGB_NO_BROWN + }, + { + "Monochrome (green)", DISPLAY_GREEN + }, + { + "Monochrome (amber)", DISPLAY_AMBER + }, + { + "Monochrome (white)", DISPLAY_WHITE + }, + { + NULL + } + } + }, +#endif + { + NULL + } +}; + +static const device_config_t ppc_config[] = { + { + "codepage", "Hardware font", CONFIG_SELECTION, "", 3, + { + { + "US English", 3 + }, + { + "Portugese", 2 + }, + { + "Norwegian", 1 + }, + { + "Greek", 0 + }, + { + NULL + } + } + }, + { + "language", "ROS Language", CONFIG_SELECTION, "", 0, + { + { + "English", 0 + }, + { + "German", 1 + }, + { + "French", 2 + }, + { + "Spanish", 3 + }, + { + "Danish", 4 + }, + { + "Swedish", 5 + }, + { + "Italian", 6 + }, + { + "DIAG Mode (English)", 7 + }, + { + NULL + } + } + }, + { + "video_emulation", "Display type", CONFIG_SELECTION, "", IDA_LCD_C, + { + { + "External monitor (CGA)", IDA_CGA, + }, + { + "External monitor (MDA)", IDA_MDA, + }, + { + "LCD (CGA mode)", IDA_LCD_C, + }, + { + "LCD (MDA mode)", IDA_LCD_M, + }, + { + NULL + } + } + }, +#if 0 + { + "display_type", "External monitor", CONFIG_SELECTION, "", DISPLAY_RGB, + { + { + "RGB", DISPLAY_RGB + }, + { + "RGB (no brown)", DISPLAY_RGB_NO_BROWN + }, + { + "Monochrome (green)", DISPLAY_GREEN + }, + { + "Monochrome (amber)", DISPLAY_AMBER + }, + { + "Monochrome (white)", DISPLAY_WHITE + }, + { + NULL + } + } + }, +#endif + { + NULL + } +}; + + +static const CPU cpus_pc1512[] = { + { "8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { NULL } +}; + +static const machine_t pc1512_info = { + MACHINE_ISA | MACHINE_NONMI | MACHINE_VIDEO | MACHINE_MOUSE, + MACHINE_VIDEO, + 512, 640, 32, 64, -1, + {{"Intel",cpus_pc1512}} +}; + +const device_t m_amstrad_1512 = { + "Amstrad PC1512", + DEVICE_ROOT, + 0, + L"amstrad/pc1512", + amstrad_init, amstrad_close, NULL, + NULL, NULL, NULL, + &pc1512_info, + pc1512_config +}; + + +static const machine_t pc1640_info = { + MACHINE_ISA | MACHINE_NONMI | MACHINE_VIDEO | MACHINE_MOUSE, + MACHINE_VIDEO, + 640, 640, 0, 64, -1, + {{"Intel",cpus_8086}} +}; + +const device_t m_amstrad_1640 = { + "Amstrad PC1640", + DEVICE_ROOT, + 1, + L"amstrad/pc1640", + amstrad_init, amstrad_close, NULL, + NULL, NULL, NULL, + &pc1640_info, + pc1640_config +}; + + +static const machine_t pc200_info = { + MACHINE_ISA | MACHINE_NONMI | MACHINE_VIDEO | MACHINE_MOUSE, + MACHINE_VIDEO, + 512, 640, 32, 64, -1, + {{"Intel",cpus_8086}} +}; + +const device_t m_amstrad_200 = { + "Amstrad PC200", + DEVICE_ROOT, + 2, + L"amstrad/pc200", + amstrad_init, amstrad_close, NULL, + NULL, NULL, NULL, + &pc200_info, + pc200_config +}; + + +static const machine_t ppc_info = { + MACHINE_ISA | MACHINE_NONMI | MACHINE_VIDEO, + 0, + 512, 640, 32, 64, -1, + {{"Intel",cpus_8086}} +}; + +const device_t m_amstrad_ppc = { + "Amstrad PPC512/640", + DEVICE_ROOT, + 3, + L"amstrad/ppc512", + amstrad_init, amstrad_close, NULL, + NULL, NULL, NULL, + &ppc_info, + ppc_config +}; + + +static const machine_t pc2086_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, + MACHINE_VIDEO, + 640, 640, 0, 64, -1, + {{"Intel",cpus_8086}} +}; + +const device_t m_amstrad_2086 = { + "Amstrad 2086", + DEVICE_ROOT, + 4, + L"amstrad/pc2086", + amstrad_init, amstrad_close, NULL, + NULL, NULL, NULL, + &pc2086_info, + NULL +}; + + +static const machine_t pc3086_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, + MACHINE_VIDEO, + 640, 640, 0, 64, -1, + {{"Intel",cpus_8086}} +}; + +const device_t m_amstrad_3086 = { + "Amstrad 3086", + DEVICE_ROOT, + 5, + L"amstrad/pc3086", + amstrad_init, amstrad_close, NULL, + NULL, NULL, NULL, + &pc3086_info, + NULL +}; diff --git a/src/machines/m_amstrad.h b/src/machines/m_amstrad.h new file mode 100644 index 0000000..a136ecf --- /dev/null +++ b/src/machines/m_amstrad.h @@ -0,0 +1,79 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Amstrad machines. + * + * Version: @(#)m_amstrad.h 1.0.2 2019/04/14 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef MACHINE_AMSTRAD_H +# define MACHINE_AMSTRAD_H + + +/* Display type. */ +#define IDA_CGA 0 /* CGA monitor */ +#define IDA_MDA 1 /* MDA monitor */ +#define IDA_TV 2 /* Television */ +#define IDA_LCD_C 3 /* PPC LCD as CGA*/ +#define IDA_LCD_M 4 /* PPC LCD as MDA*/ + + +#ifdef EMU_DEVICE_H +extern const device_t m_amstrad_1512; +extern const device_t m_amstrad_1640; +extern const device_t m_amstrad_200; +extern const device_t m_amstrad_ppc; +extern const device_t m_amstrad_2086; +extern const device_t m_amstrad_3086; +extern const device_t m_amstrad_mega; +#endif + + +extern void *m_amstrad_1512_vid_init(const wchar_t *fn, int fnt, int cp); + +extern void *m_amstrad_1640_vid_init(const wchar_t *fn, int sz); + +extern void *m_amstrad_ida_init(int type, const wchar_t *fn, + int cp, int em, int dt); +extern uint8_t m_amstrad_ida_ddm(void *arg); + + +#endif /*MACHINE_AMSTRAD_H*/ diff --git a/src/machines/m_amstrad_vid.c b/src/machines/m_amstrad_vid.c new file mode 100644 index 0000000..edcfa9f --- /dev/null +++ b/src/machines/m_amstrad_vid.c @@ -0,0 +1,1747 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of the Amstrad video controllers. + * + * PC1512: 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. + * + * PC1640: Mostly standard EGA, but with CGA & Hercules emulation. + * + * PC200: CGA with some NMI stuff. + * + * **NOTES** This module is not complete yet: + * PC1612: IGA not complete; Hercules and InColor modes not implemented. + * PC200: TV mode does not seem to work; results in CGA being selected + * by the ROS. + * PPC: MDA Monitor results in half-screen, half-cell-height display?? + * + * Version: @(#)m_amstrad_vid.c 1.0.2 2019/04/20 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2019 John Elliott. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#define dbglog video_card_log +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../timer.h" +#include "../device.h" +#include "../devices/system/nmi.h" +#include "../devices/system/pit.h" +#include "../devices/video/video.h" +#include "../devices/video/vid_cga.h" +#include "../devices/video/vid_mda.h" +#include "../devices/video/vid_ega.h" +#include "../plat.h" +#include "machine.h" +#include "m_amstrad.h" + + +typedef struct { + int type; + + rom_t bios_rom; /* 1640 */ + + cga_t cga; /* 1640/200 */ + mem_map_t cga_mapping; + + mda_t mda; + mem_map_t mda_mapping; + + ega_t ega; /* 1640 */ + + uint8_t crtc[32]; /* 1512 */ + uint8_t crtcreg; /* 1512 */ + + uint8_t cga_enabled; /* 1640 */ + + int fontbase; /* 1512/IDA */ + + uint8_t ida_enabled; /* IDA */ + uint8_t ida_mode; /* Which display are we emulating? */ + uint8_t switches; /* DIP switches 1-3 */ + uint8_t crtc_index; /* CRTC index readback + * bit7: CGA control port written + * bit6: Operation control port written + * bit5: CRTC register written + * Bits0-4: Last CRTC reg selected + */ + + uint8_t opctrl; /* 200 */ + uint8_t reg_3df; + + uint8_t cgacol, + cgamode, + stat; + uint8_t plane_read, /* 1512 */ + plane_write, /* 1512 */ + border; /* 1512/200 */ + int linepos, + displine; + int sc, vc; + int cgadispon; + int con, coff, + cursoron, + cgablink; + int64_t vsynctime; + int vadj; + uint16_t ma, maback; + int dispon; + int blink; + int64_t dispontime, /* 1512/1640 */ + dispofftime; /* 1512/1640 */ + int64_t vidtime; /* 1512/1640 */ + int firstline, + lastline; + uint8_t *vram; + + uint32_t blue, green; /* IDA for LCD */ + uint32_t lcdcols[256][2][2]; + + /* Note that IDA mda.c/cga.c code also needs fonts.. */ + uint8_t fontdat[2048][8]; /* 1512/IDA, 2048 characters */ + uint8_t fontdatm[2048][16]; /* 1512/IDA, 2048 characters */ +} vid_t; + + +static const uint8_t mapping1[256] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + /*00*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /*10*/ 2, 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + /*20*/ 2, 2, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, + /*30*/ 2, 2, 2, 0, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1, 1, + /*40*/ 2, 2, 1, 1, 0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, + /*50*/ 2, 2, 1, 1, 2, 0, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, + /*60*/ 2, 2, 2, 2, 2, 2, 0, 1, 2, 2, 2, 2, 2, 2, 1, 1, + /*70*/ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, + /*80*/ 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + /*90*/ 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, + /*a0*/ 2, 2, 2, 1, 2, 2, 1, 1, 2, 2, 0, 1, 2, 2, 1, 1, + /*b0*/ 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 0, 2, 2, 1, 1, + /*c0*/ 2, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 0, 1, 1, 1, + /*d0*/ 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 0, 1, 1, + /*e0*/ 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 1, + /*f0*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 +}; +static const uint8_t mapping2[256] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + /*00*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /*10*/ 1, 3, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, + /*20*/ 1, 1, 3, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, + /*30*/ 1, 1, 1, 3, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 2, 2, + /*40*/ 1, 1, 2, 2, 3, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, + /*50*/ 1, 1, 2, 2, 1, 3, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, + /*60*/ 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 2, 2, + /*70*/ 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 2, + /*80*/ 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + /*90*/ 1, 1, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, + /*a0*/ 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 3, 2, 1, 1, 2, 2, + /*b0*/ 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 3, 1, 1, 2, 2, + /*c0*/ 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 3, 2, 2, 2, + /*d0*/ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 3, 2, 2, + /*e0*/ 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, + /*f0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 +}; +static const uint8_t crtc_mask[32] = { + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const video_timings_t pc1512_timing = {VID_BUS,0,0,0,0,0,0}; +static const video_timings_t pc1640_timing = {VID_ISA,8,16,32,8,16,32}; +static const video_timings_t ida_timing = {VID_ISA,8,16,32,8,16,32}; + + +static void +pc1512_recalc_timings(vid_t *dev) +{ + double _dispontime, _dispofftime, disptime; + + disptime = 128; /*Fixed on PC1512*/ + + _dispontime = 80; + _dispofftime = disptime - _dispontime; + _dispontime *= CGACONST; + _dispofftime *= CGACONST; + + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); +} + + +static void +pc1512_out(uint16_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + uint8_t old; + + switch (addr) { + case 0x03d4: + dev->crtcreg = val & 31; + return; + + case 0x03d5: + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val & crtc_mask[dev->crtcreg]; + if (old != val) { + if (dev->crtcreg < 0xe || dev->crtcreg > 0x10) { + fullchange = changeframecount; + pc1512_recalc_timings(dev); + } + } + return; + + case 0x03d8: + if ((val & 0x12) == 0x12 && (dev->cgamode & 0x12) != 0x12) { + dev->plane_write = 0xf; + dev->plane_read = 0; + } + dev->cgamode = val; + return; + + case 0x03d9: + dev->cgacol = val; + return; + + case 0x03dd: + dev->plane_write = val; + return; + + case 0x03de: + dev->plane_read = val & 3; + return; + + case 0x03df: + dev->border = val; + return; + } +} + + +static uint8_t +pc1512_in(uint16_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x03d4: + ret = dev->crtcreg; + + case 0x03d5: + ret = dev->crtc[dev->crtcreg]; + + case 0x03da: + ret = dev->stat; + } + + return(ret); +} + + +static void +pc1512_write(uint32_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + cycles -= 12; + addr &= 0x3fff; + + if ((dev->cgamode & 0x12) == 0x12) { + if (dev->plane_write & 0x01) + dev->vram[addr] = val; + if (dev->plane_write & 0x02) + dev->vram[addr | 0x4000] = val; + if (dev->plane_write & 0x04) + dev->vram[addr | 0x8000] = val; + if (dev->plane_write & 0x08) + dev->vram[addr | 0xc000] = val; + } else + dev->vram[addr] = val; +} + + +static uint8_t +pc1512_read(uint32_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + cycles -= 12; + addr &= 0x3fff; + + if ((dev->cgamode & 0x12) == 0x12) + return(dev->vram[addr | (dev->plane_read << 14)]); + + return(dev->vram[addr]); +} + + +static void +pc1512_poll(void *priv) +{ + vid_t *dev = (vid_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c; + uint8_t chr, attr; + uint16_t dat, dat2, dat3, dat4; + int cols[4]; + int col; + int oldsc; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_blit_wait_buffer(); + } + dev->lastline = dev->displine; + + for (c = 0; c < 8; c++) { + if ((dev->cgamode & 0x12) == 0x12) { + screen->line[dev->displine][c].pal = (dev->border & 15) + 16; + if (dev->cgamode & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = 0; + else + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = 0; + } else { + screen->line[dev->displine][c].pal = (dev->cgacol & 15) + 16; + if (dev->cgamode & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = (dev->cgacol & 15) + 16; + else + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = (dev->cgacol & 15) + 16; + } + } + if (dev->cgamode & 1) { + for (x = 0; x < 80; x++) { + chr = dev->vram[ ((dev->ma << 1) & 0x3fff)]; + attr = dev->vram[(((dev->ma << 1) + 1) & 0x3fff)]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((dev->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + if (drawcursor) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c + 8].pal = cols[(dev->fontdat[chr + dev->fontbase][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c + 8].pal = cols[(dev->fontdat[chr + dev->fontbase][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + dev->ma++; + } + } else if (! (dev->cgamode & 2)) { + for (x = 0; x < 40; x++) { + chr = dev->vram[((dev->ma << 1) & 0x3fff)]; + attr = dev->vram[(((dev->ma << 1) + 1) & 0x3fff)]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((dev->blink & 16) && (attr & 0x80)) + cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + dev->ma++; + if (drawcursor) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(dev->fontdat[chr + dev->fontbase][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(dev->fontdat[chr + dev->fontbase][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } else if (! (dev->cgamode & 16)) { + cols[0] = (dev->cgacol & 15) | 16; + col = (dev->cgacol & 16) ? 24 : 16; + if (dev->cgamode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (dev->cgacol & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + for (x = 0; x < 40; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000)] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1]; + dev->ma++; + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + for (x = 0; x < 40; x++) { + ca = ((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000); + dat = (dev->vram[ca] << 8) | dev->vram[ca + 1]; + dat2 = (dev->vram[ca + 0x4000] << 8) | dev->vram[ca + 0x4001]; + dat3 = (dev->vram[ca + 0x8000] << 8) | dev->vram[ca + 0x8001]; + dat4 = (dev->vram[ca + 0xc000] << 8) | dev->vram[ca + 0xc001]; + + dev->ma++; + for (c = 0; c < 16; c++) { + screen->line[dev->displine][(x << 4) + c + 8].pal = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (dev->cgacol & 15)) + 16; + dat <<= 1; + dat2 <<= 1; + dat3 <<= 1; + dat4 <<= 1; + } + } + } + } else { + cols[0] = ((dev->cgamode & 0x12) == 0x12) ? 0 : (dev->cgacol & 15) + 16; + if (dev->cgamode & 1) + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 3) + 16, cols[0]); + else + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 4) + 16, cols[0]); + } + + dev->sc = oldsc; + if (dev->vsynctime) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 360) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + if ((dev->lastline - dev->firstline) == 199) + dev->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; + } + if (dev->sc == (dev->crtc[11] & 31)) { + dev->con = 0; + dev->coff = 1; + } + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9]) { + dev->maback = dev->ma; + dev->sc = 0; + dev->vc++; + dev->vc &= 127; + + if (dev->displine == 32) { + dev->vc = 0; + dev->vadj = 6; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + + if (dev->displine >= 262) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 46; + + if (dev->cgamode&1) + x = (dev->crtc[1] << 3) + 16; + else + x = (dev->crtc[1] << 4) + 16; + dev->lastline++; + + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, (ysize << 1) + 16); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_start(1, 0, dev->firstline - 4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); + + video_res_x = xsize - 16; + video_res_y = ysize; + if (dev->cgamode & 1) { + video_res_x /= 8; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else if (! (dev->cgamode & 2)) { + video_res_x /= 16; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else if (! (dev->cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 4; + } + + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + if (dev->sc == (dev->crtc[10] & 31)) + dev->con = 1; + } +} + + +static void +pc1512_close(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + free(dev->vram); + + free(dev); +} + + +static void +pc1512_speed_change(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + pc1512_recalc_timings(dev); +} + + +static const device_t pc1512_video_device = { + "Amstrad PC1512 Video", + 0, 0, NULL, + NULL, pc1512_close, NULL, + NULL, + pc1512_speed_change, + NULL, + NULL, + NULL +}; + + +/* Initialize the PC1512 display controller, return the correct DDM bits. */ +void * +m_amstrad_1512_vid_init(const wchar_t *fn, int fnt, int cp) +{ + vid_t *dev; + FILE *fp; + int c, d; + + /* Allocate a video controller block. */ + dev = (vid_t *)mem_alloc(sizeof(vid_t)); + memset(dev, 0x00, sizeof(vid_t)); + + /* Process the options. */ + dev->fontbase = (cp & 0x03) * 256; + + /* Load the PC1512 CGA Character Set ROM. */ + fp = plat_fopen(rom_path(fn), L"rb"); + if (fp != NULL) { + if (fnt == FONT_CGA_THICK) { + /* Use the second ("thick") font in the ROM. */ + (void)fseek(fp, 2048, SEEK_SET); + } + + /* The ROM has 4 fonts. */ + for (d = 0; d < 4; d++) { + /* 8x8 CGA. */ + for (c = 0; c < 256; c++) + fread(&dev->fontdat[256 * d + c], 1, 8, fp); + } + + (void)fclose(fp); + } else { + ERRLOG("AMSTRAD: cannot load fonts from '%ls'\n", fn); + return(NULL); + } + + /* Add the device to the system. */ + device_add_ex(&pc1512_video_device, dev); + + dev->vram = (uint8_t *)mem_alloc(0x10000); + dev->cgacol = 7; + dev->cgamode = 0x12; + + timer_add(pc1512_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + mem_map_add(&dev->cga.mapping, 0xb8000, 0x08000, + pc1512_read,NULL,NULL, pc1512_write,NULL,NULL, NULL, 0, dev); + io_sethandler(0x03d0, 16, pc1512_in,NULL,NULL, pc1512_out,NULL,NULL, dev); + + overscan_x = overscan_y = 16; + + video_palette_rebuild(); + + video_inform(VID_TYPE_CGA, &pc1512_timing); + + return(dev); +} + + +static void +pc1640_recalc_timings(vid_t *dev) +{ + cga_recalctimings(&dev->cga); + + ega_recalctimings(&dev->ega); + + if (dev->cga_enabled) { + overscan_x = overscan_y = 16; + + dev->dispontime = dev->cga.dispontime; + dev->dispofftime = dev->cga.dispofftime; + } else { + overscan_x = 16; overscan_y = 28; + + dev->dispontime = dev->ega.dispontime; + dev->dispofftime = dev->ega.dispofftime; + } +} + + +static void +pc1640_out(uint16_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + switch (addr) { + case 0x03bb: /* IGA mode control */ + case 0x03db: /* IGA mode control */ + dev->cga_enabled = val & 0x40; + if (dev->cga_enabled) { + /* Disable EGA. */ + mem_map_disable(&dev->ega.mapping); + + /* Enable CGA. */ + mem_map_enable(&dev->cga.mapping); + video_inform(VID_TYPE_CGA, &pc1640_timing); + } else { + /* Disable CGA. */ + mem_map_disable(&dev->cga.mapping); + + /* Enable EGA. */ + switch (dev->ega.gdcreg[6] & 0xc) { + case 0x00: /* 128K at A0000 */ + mem_map_set_addr(&dev->ega.mapping, + 0xa0000, 0x20000); + break; + + case 0x04: /* 64K at A0000 */ + mem_map_set_addr(&dev->ega.mapping, + 0xa0000, 0x10000); + break; + + case 0x08: /* 32K at B0000 */ + mem_map_set_addr(&dev->ega.mapping, + 0xb0000, 0x08000); + break; + + case 0x0c: /* 32K at B8000 */ + mem_map_set_addr(&dev->ega.mapping, + 0xb8000, 0x08000); + break; + } + video_inform(VID_TYPE_SPEC, &pc1640_timing); + } + return; + + case 0x03bf: /* IGA Hercules control register */ + return; + + case 0x03dd: /* IGA Plantronics InColor control register */ + return; + } + + if (dev->cga_enabled) + cga_out(addr, val, &dev->cga); + else + ega_out(addr, val, &dev->ega); +} + + +static uint8_t +pc1640_in(uint16_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + +#if 0 + switch (addr) { + } +#endif + + if (dev->cga_enabled) + return(cga_in(addr, &dev->cga)); + else + return(ega_in(addr, &dev->ega)); +} + + +static void +pc1640_poll(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + if (dev->cga_enabled) { + overscan_x = overscan_y = 16; + + dev->cga.vidtime = dev->vidtime; + cga_poll(&dev->cga); + dev->vidtime = dev->cga.vidtime; + } else { + overscan_x = 16; overscan_y = 28; + + dev->ega.vidtime = dev->vidtime; + ega_poll(&dev->ega); + dev->vidtime = dev->ega.vidtime; + } +} + + +static void +pc1640_close(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + free(dev->ega.vram); + + free(dev); +} + + +static void +pc1640_speed_changed(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + pc1640_recalc_timings(dev); +} + + +static const device_t pc1640_video_device = { + "Amstrad PC1640 Video", + 0, 0, NULL, + NULL, pc1640_close, NULL, + NULL, + pc1640_speed_changed, + NULL, + NULL, + NULL +}; + + +/* Initialize the PC1640 display controller, return the correct DDM bits. */ +void * +m_amstrad_1640_vid_init(const wchar_t *fn, int sz) +{ + vid_t *dev; + + /* Allocate a video controller block. */ + dev = (vid_t *)mem_alloc(sizeof(vid_t)); + memset(dev, 0x00, sizeof(vid_t)); + + device_add_ex(&pc1640_video_device, dev); + + /* Load the EGA BIOS and initialize the EGA. */ + rom_init(&dev->bios_rom, fn, 0xc0000, sz, sz - 1, 0, 0); + ega_init(&dev->ega, 9, 0); + mem_map_add(&dev->ega.mapping, 0, 0, + ega_read,NULL,NULL, ega_write,NULL,NULL, NULL, 0, &dev->ega); + + /* Set up and initialize the CGA. */ + dev->cga.vram = dev->ega.vram; + dev->cga_enabled = 1; + cga_init(&dev->cga); + mem_map_add(&dev->cga.mapping, 0xb8000, 0x08000, + cga_read,NULL,NULL, cga_write,NULL,NULL, NULL, 0, &dev->cga); + video_load_font(CGA_FONT_ROM_PATH, FONT_CGA_THICK); + + /* We currently do not implement the MDA/Hercules mode regs at 3B0H */ + io_sethandler(0x03a0, 64, pc1640_in,NULL,NULL, pc1640_out,NULL,NULL, dev); + + timer_add(pc1640_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + overscan_x = overscan_y = 16; + + video_inform(VID_TYPE_CGA, &pc1640_timing); + + return(dev); +} + + +static void +set_vid_time(vid_t *dev) +{ + switch (dev->ida_mode) { + case IDA_CGA: + case IDA_TV: + case IDA_LCD_C: + dev->vidtime = dev->cga.vidtime; + break; + + case IDA_MDA: + case IDA_LCD_M: + dev->vidtime = dev->mda.vidtime; + break; + } +} + + +/* + * LCD color mappings: + * + * 0 => solid green + * 1 => blue on green + * 2 => green on blue + * 3 => solid blue + */ +static void +set_lcd_cols(vid_t *dev, uint8_t mode_reg) +{ + const uint8_t *mapping = (mode_reg & 0x80) ? mapping2 : mapping1; + int c; + + for (c = 0; c < 256; c++) switch (mapping[c]) { + case 0: + dev->lcdcols[c][0][0] = dev->lcdcols[c][1][0] = dev->green; + dev->lcdcols[c][0][1] = dev->lcdcols[c][1][1] = dev->green; + break; + + case 1: + dev->lcdcols[c][0][0] = dev->lcdcols[c][1][0] = + dev->lcdcols[c][1][1] = dev->green; + dev->lcdcols[c][0][1] = dev->blue; + break; + + case 2: + dev->lcdcols[c][0][0] = dev->lcdcols[c][1][0] = + dev->lcdcols[c][1][1] = dev->blue; + dev->lcdcols[c][0][1] = dev->green; + break; + + case 3: + dev->lcdcols[c][0][0] = dev->lcdcols[c][1][0] = dev->blue; + dev->lcdcols[c][0][1] = dev->lcdcols[c][1][1] = dev->blue; + break; + } +} + + +static void +lcd_draw_char_80(vid_t *dev, pel_t *pel, uint8_t chr, uint8_t attr, + int drawcursor, int blink, int sc, int mode160, + uint8_t control) +{ + uint8_t bits = fontdat[chr + dev->cga.fontbase][sc]; + uint8_t bright = 0; + uint16_t mask; + int c; + + if (attr & 8) { + /* bright */ + /* The brightness algorithm appears to be: replace any bit + * sequence 011 with 001 (assuming an extra 0 to the left + * of the byte). + */ + bright = bits; + for (c = 0, mask = 0x100; c < 7; c++, mask >>= 1) { + if (((bits & mask) == 0) && + ((bits & (mask >> 1)) != 0) && + ((bits & (mask >> 2)) != 0)) { + bright &= ~(mask >> 1); + } + } + bits = bright; + } + + if (drawcursor) + bits ^= 0xff; + + for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1) { + if (mode160) + pel[c].val = (attr & mask) ? dev->blue : dev->green; + else { + if (control & 0x20) /* blinking */ + attr &= 0x7f; + pel[c].val = dev->lcdcols[attr][blink][(bits & mask) ? 1 : 0]; + } + } +} + + +static void +lcd_draw_char_40(vid_t *dev, pel_t *pel, uint8_t chr, uint8_t attr, + int drawcursor, int blink, int sc, uint8_t control) +{ + uint8_t bits = fontdat[chr + dev->cga.fontbase][sc]; + uint8_t mask = 0x80; + int c; + + if (attr & 8) { + /* bright */ + bits = bits & (bits >> 1); + } + + if (drawcursor) + bits ^= 0xff; + + for (c = 0; c < 8; c++, mask >>= 1) { + if (control & 0x20) { + pel[c * 2].val = pel[c * 2 + 1].val = + dev->lcdcols[attr & 0x7f][blink][(bits & mask) ? 1 : 0]; + } else { + pel[c * 2].val = pel[c * 2 + 1].val = + dev->lcdcols[attr][blink][(bits & mask) ? 1 : 0]; + } + } +} + + +static void +lcd_poll_mda(vid_t *dev) +{ + mda_t *mda = &dev->mda; + uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; + uint8_t chr, attr; + int drawcursor; + int oldvc, oldsc; + int x, blink; + + if (! mda->linepos) { + dev->vidtime += mda->dispofftime; + mda->stat |= 1; + mda->linepos = 1; + oldsc = mda->sc; + + if ((mda->crtc[8] & 3) == 3) + mda->sc = (mda->sc << 1) & 7; + + if (mda->dispon) { + if (mda->displine < mda->firstline) { + mda->firstline = mda->displine; + video_blit_wait_buffer(); + } + mda->lastline = mda->displine; + + for (x = 0; x < mda->crtc[1]; x++) { + chr = mda->vram[(mda->ma << 1) & 0xfff]; + attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; + drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron); + blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + + lcd_draw_char_80(dev, &screen->line[mda->displine][x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl); + mda->ma++; + } + } + + mda->sc = oldsc; + if (mda->vc == mda->crtc[7] && !mda->sc) + mda->stat |= 8; + + mda->displine++; + if (mda->displine >= 500) + mda->displine = 0; + } else { + dev->vidtime += mda->dispontime; + + if (mda->dispon) + mda->stat &= ~1; + mda->linepos = 0; + + if (mda->vsynctime) { + mda->vsynctime--; + if (! mda->vsynctime) + mda->stat &= ~8; + } + + if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { + mda->con = 0; + mda->coff = 1; + } + + if (mda->vadj) { + mda->sc++; + mda->sc &= 31; + mda->ma = mda->maback; + + mda->vadj--; + if (! mda->vadj) { + mda->dispon = 1; + mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->sc = 0; + } + } else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) { + mda->maback = mda->ma; + mda->sc = 0; + + oldvc = mda->vc; + mda->vc++; + mda->vc &= 127; + if (mda->vc == mda->crtc[6]) + mda->dispon = 0; + if (oldvc == mda->crtc[4]) { + mda->vc = 0; + + mda->vadj = mda->crtc[5]; + if (! mda->vadj) + mda->dispon = 1; + if (! mda->vadj) + mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + if ((mda->crtc[10] & 0x60) == 0x20) + mda->cursoron = 0; + else + mda->cursoron = mda->blink & 16; + } + + if (mda->vc == mda->crtc[7]) { + mda->dispon = 0; + mda->displine = 0; + mda->vsynctime = 16; + + if (mda->crtc[7]) { + x = mda->crtc[1] * 8; + mda->lastline++; + + if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = mda->lastline - mda->firstline; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_start(0, 0, mda->firstline, 0, ysize, xsize, ysize); + frames++; + + video_res_x = mda->crtc[1]; + video_res_y = mda->crtc[6]; + video_bpp = 0; + } + + mda->firstline = 1000; + mda->lastline = 0; + mda->blink++; + } + } else { + mda->sc++; + mda->sc &= 31; + mda->ma = mda->maback; + } + + if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1)))) + mda->con = 1; + } +} + + +static void +lcd_poll_cga(vid_t *dev) +{ + cga_t *cga = &dev->cga; + uint8_t chr, attr; + uint16_t ca, dat; + int drawcursor; + int oldvc, oldsc; + int x, c, blink; + + ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; + + if (! cga->linepos) { + dev->vidtime += cga->dispofftime; + cga->cgastat |= 1; + cga->linepos = 1; + oldsc = cga->sc; + + if ((cga->crtc[8] & 3) == 3) + cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; + + if (cga->cgadispon) { + if (cga->displine < cga->firstline) { + cga->firstline = cga->displine; + video_blit_wait_buffer(); + } + cga->lastline = cga->displine; + + if (cga->cgamode & 1) { + for (x = 0; x < cga->crtc[1]; x++) { + chr = cga->charbuffer[x << 1]; + attr = cga->charbuffer[(x << 1) + 1]; + drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); + + lcd_draw_char_80(dev, &screen->line[cga->displine][x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); + cga->ma++; + } + } else if (! (cga->cgamode & 2)) { + for (x = 0; x < cga->crtc[1]; x++) { + chr = cga->vram[((cga->ma << 1) & 0x3fff)]; + attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)]; + drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); + + lcd_draw_char_40(dev, &screen->line[cga->displine][x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); +cga->ma++; + } + } else { + /* Graphics mode */ + for (x = 0; x < cga->crtc[1]; x++) { + dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; + cga->ma++; + + for (c = 0; c < 16; c++) { + screen->line[cga->displine][(x << 4) + c].val = (dat & 0x8000) ? dev->blue : dev->green; + dat <<= 1; + } + } + } + } else { + if (cga->cgamode & 1) + cga_hline(screen, 0, cga->displine, (cga->crtc[1] << 3), dev->green); + else + cga_hline(screen, 0, cga->displine, (cga->crtc[1] << 4), dev->green); + } + + if (cga->cgamode & 1) + x = (cga->crtc[1] << 3); + else + x = (cga->crtc[1] << 4); + + cga->sc = oldsc; + if (cga->vc == cga->crtc[7] && !cga->sc) + cga->cgastat |= 8; + + cga->displine++; + if (cga->displine >= 360) + cga->displine = 0; + } else { + dev->vidtime += cga->dispontime; + cga->linepos = 0; + if (cga->vsynctime) { + cga->vsynctime--; + if (! cga->vsynctime) + cga->cgastat &= ~8; + } + + if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { + cga->con = 0; + cga->coff = 1; + } + + if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) + cga->maback = cga->ma; + + if (cga->vadj) { + cga->sc++; + cga->sc &= 31; + cga->ma = cga->maback; + + cga->vadj--; + if (! cga->vadj) { + cga->cgadispon = 1; + cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + cga->sc = 0; + } + } else if (cga->sc == cga->crtc[9]) { + cga->maback = cga->ma; + cga->sc = 0; + oldvc = cga->vc; + cga->vc++; + cga->vc &= 127; + + if (cga->vc == cga->crtc[6]) + cga->cgadispon = 0; + + if (oldvc == cga->crtc[4]) { + cga->vc = 0; + cga->vadj = cga->crtc[5]; + + if (! cga->vadj) + cga->cgadispon = 1; + if (! cga->vadj) + cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + if ((cga->crtc[10] & 0x60) == 0x20) + cga->cursoron = 0; + else + cga->cursoron = cga->cgablink & 8; + } + + if (cga->vc == cga->crtc[7]) { + cga->cgadispon = 0; + cga->displine = 0; + cga->vsynctime = 16; + + if (cga->crtc[7]) { + if (cga->cgamode & 1) + x = (cga->crtc[1] << 3); + else + x = (cga->crtc[1] << 4); + + cga->lastline++; + if ((x != xsize) || ((cga->lastline - cga->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = cga->lastline - cga->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, (ysize << 1)); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_start(0, 0, cga->firstline, 0, (cga->lastline - cga->firstline), xsize, (cga->lastline - cga->firstline)); + frames++; + + video_res_x = xsize - 16; + video_res_y = ysize; + if (cga->cgamode & 1) { + video_res_x /= 8; + video_res_y /= cga->crtc[9] + 1; + video_bpp = 0; + } else if (! (cga->cgamode & 2)) { + video_res_x /= 16; + video_res_y /= cga->crtc[9] + 1; + video_bpp = 0; + } else if (! (cga->cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + + cga->firstline = 1000; + cga->lastline = 0; + cga->cgablink++; + cga->oddeven ^= 1; + } + } else { + cga->sc++; + cga->sc &= 31; + cga->ma = cga->maback; + } + + if (cga->cgadispon) + cga->cgastat &= ~1; + + if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1)))) + cga->con = 1; + + if (cga->cgadispon && (cga->cgamode & 1)) { + for (x = 0; x < (cga->crtc[1] << 1); x++) + cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)]; + } + } +} + + +static void +ida_poll(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + switch (dev->ida_mode) { + case IDA_CGA: + case IDA_TV: + dev->cga.vidtime = dev->vidtime; + cga_poll(&dev->cga); + dev->vidtime = dev->cga.vidtime; + return; + + case IDA_MDA: + dev->mda.vidtime = dev->vidtime; + mda_poll(&dev->mda); + dev->vidtime = dev->mda.vidtime; + return; + + case IDA_LCD_C: + lcd_poll_cga(dev); + return; + + case IDA_LCD_M: + lcd_poll_mda(dev); + return; + } +} + + +static void +ida_out(uint16_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + cga_t *cga = &dev->cga; + mda_t *mda = &dev->mda; + uint8_t old; + + /* Only allow writes (to non-internal registers) if IDA is enabled. */ + if (! (dev->opctrl & 0x04)) switch (addr) { + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: + /* Writes banned to CRTC registers 0-11? */ + if (!(dev->opctrl & 0x40) && mda->crtcreg <= 11) { + dev->crtc_index = 0x20 | (mda->crtcreg & 0x1f); + if (dev->opctrl & 0x80) { + DEBUG("IDA: NMI (CRTC access: reg=0x%02x val=0x%02x) nmi_mask=%i\n", mda->crtcreg & 0x1f, val, nmi_mask); + nmi = 1; + } + dev->reg_3df = val; + return; + } + old = mda->crtc[mda->crtcreg]; + mda->crtc[mda->crtcreg] = val & crtc_mask[mda->crtcreg]; + if (old != val) { + if (mda->crtcreg < 0xe || mda->crtcreg > 0x10) { + fullchange = changeframecount; + mda_recalctimings(mda); + set_vid_time(dev); + } + } + return; + + case 0x03b8: + old = mda->ctrl; + mda->ctrl = val; + if ((mda->ctrl ^ old) & 3) { + mda_recalctimings(mda); + set_vid_time(dev); + } + dev->crtc_index &= 0x1f; + dev->crtc_index |= 0x80; + if (dev->opctrl & 0x80) { + DEBUG("IDA: NMI (mode control access: val=0x%02x) nmi_mask=%i\n", val, nmi_mask); + nmi = 1; + } + return; + + case 0x03d1: + case 0x03d3: + case 0x03d5: + case 0x03d7: + /* Writes banned to CRTC registers 0-11? */ + if (!(dev->opctrl & 0x40) && cga->crtcreg <= 11) { + dev->crtc_index = 0x20 | (cga->crtcreg & 0x1f); + if (dev->opctrl & 0x80) { + DEBUG("IDA: NMI (CRTC access: reg=0x%02x val=0x%02x) nmi_mask=%i\n", cga->crtcreg & 0x1F, val, nmi_mask); + nmi = 1; + } + dev->reg_3df = val; + return; + } + + old = cga->crtc[cga->crtcreg]; + cga->crtc[cga->crtcreg] = val & crtc_mask[cga->crtcreg]; + if (old != val) { + if (cga->crtcreg < 0xe || cga->crtcreg > 0x10) { + fullchange = changeframecount; + cga_recalctimings(cga); + set_vid_time(dev); + } + } + return; + + case 0x03d8: + old = cga->cgamode; + cga->cgamode = val; + if ((cga->cgamode ^ old) & 3) { + cga_recalctimings(cga); + set_vid_time(dev); + } + dev->crtc_index &= 0x1f; + dev->crtc_index |= 0x80; + if (dev->opctrl & 0x80) { + DEBUG("IDA: NMI (mode ctrl access: val=0x%02x) nmi_mask=%i\n", val, nmi_mask); + nmi = 1; + } else + set_lcd_cols(dev, val); + return; + } + + /* Writes to internal registers are always allowed. */ + switch (addr) { + case 0x03de: + dev->crtc_index = 0x1f; + + /* + * NMI only seems to be triggered if the value being written + * has the high bit set (enable NMI). So it only protects + * writes to this port if you let it? + */ + if (val & 0x80) { + DEBUG("IDA: NMI (opctrl access: val=0x%02x) nmi_mask=%i\n", val, nmi_mask); + dev->opctrl = val; + dev->crtc_index |= 0x40; + nmi = 1; + return; + } + dev->opctrl = val; + + /* Bits 0 and 1 control emulation and output mode. */ + old = dev->ida_mode; + if (val & 1) { + /* Monitor */ + dev->ida_mode = (val & 2) ? IDA_MDA : IDA_CGA; + } else { + if (dev->type == 1) { + /* LCD */ + dev->ida_mode = (val & 2) ? IDA_LCD_M:IDA_LCD_C; + } else { + /* TV */ + dev->ida_mode = IDA_TV; + } + } + if (old != dev->ida_mode) + INFO("IDA: mode from %i to %i\n", old, dev->ida_mode); + + old = !(val & 0x04); + if (dev->ida_enabled ^ old) { + dev->ida_enabled = old; + INFO("IDA: %sabled\n", + dev->ida_enabled ? "en" : "dis"); + } + +#if 0 + if (dev->ida_enabled) { + /* + * IDA is enabled. + * + * Enable the appropriate memory ranges + * depending whether the IDA is configured + * as MDA or CGA. + */ + if (dev->ida_mode == IDA_MDA || + dev->ida_mode == IDA_LCD_M) { + mem_map_disable(&dev->cga_mapping); + mem_map_enable(&dev->mda_mapping); + } else { + mem_map_disable(&dev->mda_mapping); + mem_map_enable(&dev->cga_mapping); + } + } else { + /* IDA is disabled. */ + mem_map_disable(&dev->cga_mapping); + mem_map_disable(&dev->mda_mapping); + } +#endif + + return; + } + + if (addr >= 0x03d0 && addr <= 0x03df) + cga_out(addr, val, cga); + + if (addr >= 0x03b0 && addr <= 0x03bb) + mda_out(addr, val, mda); +} + + +static uint8_t +ida_in(uint16_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + cga_t *cga = &dev->cga; + mda_t *mda = &dev->mda; + uint8_t temp; + + /* Only allow reads if IDA is enabled. */ + if (! (dev->opctrl & 0x04)) switch (addr) { + case 0x03b8: /* MDA control register */ + return(mda->ctrl); + + case 0x03d8: /* CGA mode register */ + return(cga->cgamode); + + case 0x03dd: + temp = dev->crtc_index; /* read NMI reason */ + dev->crtc_index &= 0x1f; /* reset NMI reason */ + nmi = 0; /* and reset NMI flag */ + return(temp); + + case 0x03de: + temp = (dev->opctrl & 0xc7) | dev->switches; + DEBUG("IDA: read(opctrl) = %02x (switches=%02x)\n", temp, dev->switches); + return(temp); + + case 0x03df: + return(dev->reg_3df); + } + + if (addr >= 0x03d0 && addr <= 0x03df) + return cga_in(addr, cga); + + if (addr >= 0x03b0 && addr <= 0x03bb) + return mda_in(addr, mda); + + return(0xff); +} + + +static void +ida_close(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + free(dev->cga.vram); + + free(dev); +} + + +static void +ida_speed_changed(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + cga_recalctimings(&dev->cga); + mda_recalctimings(&dev->mda); + + set_vid_time(dev); +} + + +static const device_t ida_video_device = { + "Amstrad IDA Video", + 0, 0, NULL, + NULL, ida_close, NULL, + NULL, + ida_speed_changed, + NULL, + NULL, + NULL +}; + + +/* Initialize the PC200/PPC display controller, return the correct DDM bits. */ +void * +m_amstrad_ida_init(int type, const wchar_t *fn, int cp, int em, int dt) +{ + vid_t *dev; + FILE *fp; + int c, d; + + /* Allocate a video controller block. */ + dev = (vid_t *)mem_alloc(sizeof(vid_t)); + memset(dev, 0x00, sizeof(vid_t)); + dev->type = type; + + /* Add the device to the system. */ + device_add_ex(&ida_video_device, dev); + + dev->fontbase = (cp & 0x03) * 256; + + dev->ida_enabled = 1; + dev->ida_mode = em; + + /* Load the Character Set ROM. */ + fp = plat_fopen(rom_path(fn), L"rb"); + if (fp != NULL) { + /* The ROM has 4 fonts. */ + for (d = 0; d < 4; d++) { + /* 8x14 MDA in 8x16 cell. */ + for (c = 0; c < 256; c++) + fread(&fontdatm[256 * d + c], 1, 16, fp); + + /* 8x8 CGA in 8x16 cell. */ + for (c = 0; c < 256; c++) { + fread(&fontdat[256 * d + c], 1, 8, fp); + fseek(fp, 8, SEEK_CUR); + } + } + + (void)fclose(fp); + } else { + ERRLOG("IDA: cannot load fonts from '%ls'\n", fn); + return(NULL); + } + + /* + * DIP switch settings. + * + * For PC-200: + * Switch 3 ON is MDA (CGA) + * Switch 2 ON is CRT (TV) + * Switch 1 ON is 'swap floppy drives' (not implemented). + * + * For PPC: + * Switch 3 ON disables IDA. + * Switch 2 ON is MDA (CGA) + * Switch 1 ON is CRT (LCD) + * + * Positive logic, ON=1. + */ + switch (dev->ida_mode) { + case IDA_CGA: + if (dev->type == 1) + dev->switches = 0x08; /* PPC */ + else + dev->switches = 0x10; /* PC */ + break; + + case IDA_MDA: + if (dev->type == 1) + dev->switches = 0x18; /* PPC */ + else + dev->switches = 0x30; /* PC */ + break; + + case IDA_TV: + if (dev->type == 0) + dev->switches = 0x00; /* PC */ + break; + + case IDA_LCD_C: + if (dev->type == 1) + dev->switches = 0x00; /* PPC */ + break; + + case IDA_LCD_M: + if (dev->type == 1) + dev->switches = 0x10; /* PPC */ + break; + } + INFO("%s: IDA mode %i, switches %02x\n", + (dev->type==1)?"PPC":"PC200", dev->ida_mode, dev->switches); + + /* Set up the CGA emulation. */ + dev->cga.vram = (uint8_t *)mem_alloc(0x8000); + dev->cga.fontbase = dev->fontbase; + cga_init(&dev->cga); + mem_map_add(&dev->cga_mapping, 0xb8000, 0x08000, + cga_read,NULL,NULL, cga_write,NULL,NULL, NULL, 0, &dev->cga); + io_sethandler(0x03d0, 16, ida_in,NULL,NULL, ida_out,NULL,NULL, dev); + + /* Set up the MDA emulation (sharing the video RAM.) */ + dev->mda.vram = dev->cga.vram; + mda_init(&dev->mda); + mem_map_add(&dev->mda_mapping, 0xb0000, 0x08000, + mda_read,NULL,NULL, mda_write,NULL,NULL, NULL, 0, &dev->mda); + io_sethandler(0x03b0, 12, ida_in,NULL,NULL, ida_out,NULL,NULL, dev); + + mda_setcol(&dev->mda, 0x08, 0, 1, 15); /* white on black */ + mda_setcol(&dev->mda, 0x88, 0, 1, 15); + mda_setcol(&dev->mda, 0x40, 0, 1, 0); /* black on black */ + mda_setcol(&dev->mda, 0xc0, 0, 1, 0); + + /* Set up colors for the LCD panel. */ + dev->green = makecol(0x1c, 0x71, 0x31); + dev->blue = makecol(0x0f, 0x21, 0x3f); + set_lcd_cols(dev, 0); + + timer_add(ida_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + overscan_x = overscan_y = 16; + + video_palette_rebuild(); + + /* + * Flag whether the card is behaving like a CGA or an MDA, + * so that DIP switches are reported correctly. + */ + if ((dev->ida_mode == IDA_MDA) || (dev->ida_mode == IDA_LCD_M)) + video_inform(VID_TYPE_MDA, &ida_timing); + else + video_inform(VID_TYPE_CGA, &ida_timing); + + return(dev); +} + + +uint8_t +m_amstrad_ida_ddm(void *arg) +{ + vid_t *dev = (vid_t *)arg; + uint8_t ret = 0x00; + + switch (dev->ida_mode) { + case IDA_CGA: /* CGA, Color80 */ + case IDA_LCD_C: + ret = 0x02; + break; + + case IDA_TV: /* CGA, Color40 */ + ret = 0x01; + break; + + case IDA_MDA: /* MDA */ + case IDA_LCD_M: + ret = 0x03; + break; + } + + return(ret); +} diff --git a/src/machines/m_aopen.c b/src/machines/m_aopen.c new file mode 100644 index 0000000..b77c447 --- /dev/null +++ b/src/machines/m_aopen.c @@ -0,0 +1,119 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of various A/Open mainboards. + * + * Version: @(#)m_aopen.c 1.0.1 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/intel4x0.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/system/intel.h" +#include "../devices/system/intel_flash.h" +#include "../devices/system/intel_sio.h" +#include "../devices/system/intel_piix.h" +#include "../devices/input/keyboard.h" +#include "../devices/sio/sio.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "../devices/video/video.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Allocate machine device to system. */ + device_add_ex(info, arg); + + switch(info->local) { + /* AP53: AOpen AP53/430HX/AMI/SMC FDC37C665/669 */ + case 0: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_ONBOARD, 1, 2, 3, 4); + + memregs_init(); + powermate_memregs_init(); + + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&fdc37c669_device); + device_add(&keyboard_ps2_ami_pci_device); + + break; + } + + return(arg); +} + + +static const machine_t ap53_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 512, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_ap53 = { + "AOpen AP53", + DEVICE_ROOT, + 0, + L"aopen/ap53", + common_init, NULL, NULL, + NULL, NULL, NULL, + &ap53_info, + NULL +}; diff --git a/src/machines/m_asus.c b/src/machines/m_asus.c new file mode 100644 index 0000000..da343b5 --- /dev/null +++ b/src/machines/m_asus.c @@ -0,0 +1,195 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of several ASUS mainboards. + * + * Version: @(#)m_asus.c 1.0.1 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/intel4x0.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/system/intel.h" +#include "../devices/system/intel_flash.h" +#include "../devices/system/intel_sio.h" +#include "../devices/system/intel_piix.h" +#include "../devices/input/keyboard.h" +#include "../devices/sio/sio.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Allocate machine device to system. */ + device_add_ex(info, arg); + + switch(info->local) { + /* P54TP4XE: ASUS P/I-P55TP4XE/430FX/Award/SMC FDC37C665 */ + case 0: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&fdc37c665_device); + device_add(&keyboard_ps2_pci_device); + break; + + /* P55T2P4: ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/ + case 1: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&w83877f_device); + device_add(&keyboard_ps2_pci_device); + break; + + /* P55TVP4: ASUS P/I-P55TVP4/430VX/Award/Winbond W8387F*/ + case 2: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&w83877f_device); + device_add(&keyboard_ps2_pci_device); + break; + } + + return(arg); +} + + +static const machine_t tp4xe_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_PentiumS5},{"IDT",cpus_WinChip},CPU_AMD_K5} +}; + +const device_t m_p54tp4xe = { + "ASUS P54TP4XE", + DEVICE_ROOT, + 0, + L"asus/p54tp4xe", + common_init, NULL, NULL, + NULL, NULL, NULL, + &tp4xe_info, + NULL +}; + + +static const machine_t t2p4_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 512, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_p55t2p4 = { + "ASUS P55T2P4", + DEVICE_ROOT, + 1, + L"asus/p55t2p4", + common_init, NULL, NULL, + NULL, NULL, NULL, + &t2p4_info, + NULL +}; + + +static const machine_t tvp4_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_p55tvp4 = { + "ASUS P55TVP4", + DEVICE_ROOT, + 2, + L"asus/p55tvp4", + common_init, NULL, NULL, + NULL, NULL, NULL, + &tvp4_info, + NULL +}; diff --git a/src/machines/m_at.c b/src/machines/m_at.c index 6ba18c7..a768209 100644 --- a/src/machines/m_at.c +++ b/src/machines/m_at.c @@ -8,7 +8,7 @@ * * Standard PC/AT implementation. * - * Version: @(#)m_at.c 1.0.11 2019/02/16 + * Version: @(#)m_at.c 1.0.13 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include "../emu.h" +#include "../cpu/cpu.h" #include "../mem.h" #include "../device.h" #include "../nvr.h" @@ -55,9 +56,9 @@ void -m_at_common_init(const machine_t *model, void *arg) +m_at_common_init(void) { - machine_common_init(model, arg); + machine_common_init(); pit_set_out_func(&pit, 1, pit_refresh_timer_at); pic2_init(); @@ -68,56 +69,109 @@ m_at_common_init(const machine_t *model, void *arg) void -m_at_init(const machine_t *model, void *arg) +m_at_init(void) { - m_at_common_init(model, arg); + m_at_common_init(); device_add(&keyboard_at_device); } void -m_at_ibm_init(const machine_t *model, void *arg) +m_at_ps2_init(void) { - m_at_init(model, arg); - - mem_remap_top(384); - - device_add(&fdc_at_device); -} - - -void -m_at_ps2_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); + m_at_common_init(); device_add(&keyboard_ps2_device); } void -m_at_common_ide_init(const machine_t *model, void *arg) +m_at_common_ide_init(void) { - m_at_common_init(model, arg); + m_at_common_init(); device_add(&ide_isa_2ch_opt_device); } void -m_at_ide_init(const machine_t *model, void *arg) +m_at_ide_init(void) { - m_at_init(model, arg); + m_at_init(); device_add(&ide_isa_2ch_opt_device); } void -m_at_ps2_ide_init(const machine_t *model, void *arg) +m_at_ps2_ide_init(void) { - m_at_ps2_init(model, arg); + m_at_ps2_init(); device_add(&ide_isa_2ch_opt_device); } + + +static void * +ibm_at_init(const device_t *info, void *arg) +{ + device_add_ex(info, arg); + + m_at_init(); + + mem_remap_top(384); + + device_add(&fdc_at_device); + + return(arg); +} + + +static const CPU cpus_ibmat[] = { + { "286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1 }, + { "286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1 }, + { NULL } +}; + +static const machine_t at_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 256, 15872, 128, 64, -1, + {{"",cpus_ibmat}} +}; + +const device_t m_at = { + "IBM PC/AT", + DEVICE_ROOT, + 0, + L"ibm/at", + ibm_at_init, NULL, NULL, + NULL, NULL, NULL, + &at_info, + NULL +}; + + +static const CPU cpus_ibmxt286[] = { + { "286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1 }, + { NULL } +}; + +static const machine_t xt286_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 256, 15872, 128, 128, -1, + {{"",cpus_ibmxt286}} +}; + +const device_t m_xt286 = { + "IBM PC/XT286", + DEVICE_ROOT, + 1, + L"ibm/xt286", + ibm_at_init, NULL, NULL, + NULL, NULL, NULL, + &xt286_info, + NULL +}; diff --git a/src/machines/m_at_4x0.c b/src/machines/m_at_4x0.c deleted file mode 100644 index e5aea36..0000000 --- a/src/machines/m_at_4x0.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Intel 430xx 440xx PCISet chips. - * - * Version: @(#)m_at_4x0.c 1.0.4 2019/02/16 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include "../emu.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../devices/system/pci.h" -#include "../devices/system/memregs.h" -#include "../devices/system/intel.h" -#include "../devices/system/intel_flash.h" -#include "../devices/system/intel_sio.h" -#include "../devices/system/intel_piix.h" -#include "../devices/input/keyboard.h" -#include "../devices/sio/sio.h" -#include "../devices/disk/hdc.h" -#include "../devices/disk/hdc_ide.h" -#include "../devices/video/video.h" -#include "machine.h" - - -enum { - INTEL_430LX, - INTEL_430NX, - INTEL_430FX, - INTEL_430FX_PB640, - INTEL_430HX, - INTEL_430VX, -#if defined(DEV_BRANCH) && defined(USE_I686) - INTEL_440FX -#endif -}; - -typedef struct { - uint8_t regs[256]; - int type; -} i4x0_t; - -typedef struct { - int index; -} acerm3a_t; - - -static void -i4x0_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) { - case 0: - mem_set_mem_state(addr, size, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - - case 1: - mem_set_mem_state(addr, size, - MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - - case 2: - mem_set_mem_state(addr, size, - MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - - case 3: - mem_set_mem_state(addr, size, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - - flushmmucache_nopc(); -} - - -static void -i4x0_write(int func, int addr, uint8_t val, void *priv) -{ - i4x0_t *dev = (i4x0_t *)priv; - - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - if (dev->type >= INTEL_430FX) { - if (dev->type == INTEL_430FX_PB640) - val &= 0x06; - else - val &= 0x02; - } else - val &= 0x42; - val |= 0x04; - break; - - case 0x05: - if (dev->type >= INTEL_430FX) - val = 0; - else - val &= 0x01; - break; - - case 0x06: /*Status*/ - val = 0; - break; - - case 0x07: - if (dev->type >= INTEL_430HX) { - val &= 0x80; - val |= 0x02; - } else { - val = 0x02; - if (dev->type == INTEL_430FX_PB640) - val |= 0x20; - } - break; - - case 0x59: /*PAM0*/ - if ((dev->regs[0x59] ^ val) & 0xf0) { - i4x0_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - break; - - case 0x5a: /*PAM1*/ - if ((dev->regs[0x5a] ^ val) & 0x0f) - i4x0_map(0xc0000, 0x04000, val & 0xf); - if ((dev->regs[0x5a] ^ val) & 0xf0) - i4x0_map(0xc4000, 0x04000, val >> 4); - break; - - case 0x5b: /*PAM2*/ - if ((dev->regs[0x5b] ^ val) & 0x0f) - i4x0_map(0xc8000, 0x04000, val & 0xf); - if ((dev->regs[0x5b] ^ val) & 0xf0) - i4x0_map(0xcc000, 0x04000, val >> 4); - break; - - case 0x5c: /*PAM3*/ - if ((dev->regs[0x5c] ^ val) & 0x0f) - i4x0_map(0xd0000, 0x04000, val & 0xf); - if ((dev->regs[0x5c] ^ val) & 0xf0) - i4x0_map(0xd4000, 0x04000, val >> 4); - break; - - case 0x5d: /*PAM4*/ - if ((dev->regs[0x5d] ^ val) & 0x0f) - i4x0_map(0xd8000, 0x04000, val & 0xf); - if ((dev->regs[0x5d] ^ val) & 0xf0) - i4x0_map(0xdc000, 0x04000, val >> 4); - break; - - case 0x5e: /*PAM5*/ - if ((dev->regs[0x5e] ^ val) & 0x0f) - i4x0_map(0xe0000, 0x04000, val & 0xf); - if ((dev->regs[0x5e] ^ val) & 0xf0) - i4x0_map(0xe4000, 0x04000, val >> 4); - break; - - case 0x5f: /*PAM6*/ - if ((dev->regs[0x5f] ^ val) & 0x0f) - i4x0_map(0xe8000, 0x04000, val & 0xf); - if ((dev->regs[0x5f] ^ val) & 0xf0) - i4x0_map(0xec000, 0x04000, val >> 4); - break; - - case 0x72: /*SMRAM*/ - if ((dev->type >= INTEL_430FX) && - ((dev->regs[0x72] ^ val) & 0x48)) - i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - dev->regs[addr] = val; -} - - -static uint8_t -i4x0_read(int func, int addr, void *priv) -{ - i4x0_t *dev = (i4x0_t *)priv; - - if (func) - return 0xff; - - return dev->regs[addr]; -} - - -static void -i4x0_reset(void *priv) -{ - i4x0_t *dev = (i4x0_t *)priv; - - i4x0_write(0, 0x59, 0x00, priv); - if (dev->type >= INTEL_430FX) - i4x0_write(0, 0x72, 0x02, priv); -} - - -static void -i4x0_close(void *priv) -{ - i4x0_t *dev = (i4x0_t *)priv; - - free(dev); -} - - -static void * -i4x0_init(const device_t *info) -{ - i4x0_t *dev = (i4x0_t *) mem_alloc(sizeof(i4x0_t)); - memset(dev, 0x00, sizeof(i4x0_t)); - dev->type = info->local; - - dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/ - - switch(dev->type) { - case INTEL_430LX: - dev->regs[0x02] = 0xa3; dev->regs[0x03] = 0x04; /*82434LX/NX*/ - dev->regs[0x08] = 0x03; /*A3 stepping*/ - dev->regs[0x50] = 0x80; - dev->regs[0x52] = 0x40; /*256kb PLB cache*/ - break; - - case INTEL_430NX: - dev->regs[0x02] = 0xa3; dev->regs[0x03] = 0x04; /*82434LX/NX*/ - dev->regs[0x08] = 0x10; /*A0 stepping*/ - dev->regs[0x50] = 0xA0; - dev->regs[0x52] = 0x44; /*256kb PLB cache*/ - dev->regs[0x66] = dev->regs[0x67] = 0x02; - break; - - case INTEL_430FX: - case INTEL_430FX_PB640: - dev->regs[0x02] = 0x2d; dev->regs[0x03] = 0x12; /*SB82437FX-66*/ - if (dev->type == INTEL_430FX_PB640) - dev->regs[0x08] = 0x02; /*???? stepping*/ - else - dev->regs[0x08] = 0x00; /*A0 stepping*/ - dev->regs[0x52] = 0x40; /*256kb PLB cache*/ - break; - - case INTEL_430HX: - dev->regs[0x02] = 0x50; dev->regs[0x03] = 0x12; /*82439HX*/ - dev->regs[0x08] = 0x00; /*A0 stepping*/ - dev->regs[0x51] = 0x20; - dev->regs[0x52] = 0xB5; /*512kb cache*/ - dev->regs[0x56] = 0x52; /*DRAM control*/ - dev->regs[0x59] = 0x40; - dev->regs[0x5A] = dev->regs[0x5B] = \ - dev->regs[0x5C] = dev->regs[0x5D] = 0x44; - dev->regs[0x5E] = dev->regs[0x5F] = 0x44; - dev->regs[0x65] = dev->regs[0x66] = dev->regs[0x67] = 0x02; - dev->regs[0x68] = 0x11; - break; - - case INTEL_430VX: - dev->regs[0x02] = 0x30; dev->regs[0x03] = 0x70; /*82437VX*/ - dev->regs[0x08] = 0x00; /*A0 stepping*/ - dev->regs[0x52] = 0x42; /*256kb PLB cache*/ - dev->regs[0x53] = 0x14; - dev->regs[0x56] = 0x52; /*DRAM control*/ - dev->regs[0x67] = 0x11; - dev->regs[0x69] = 0x03; - dev->regs[0x70] = 0x20; - dev->regs[0x74] = 0x0e; - dev->regs[0x78] = 0x23; - break; - -#if defined(DEV_BRANCH) && defined(USE_I686) - case INTEL_440FX: - dev->regs[0x02] = 0x37; dev->regs[0x03] = 0x12; /*82441FX*/ - dev->regs[0x08] = 0x02; /*A0 stepping*/ - dev->regs[0x2c] = 0xf4; - dev->regs[0x2d] = 0x1a; - dev->regs[0x2f] = 0x11; - dev->regs[0x51] = 0x01; - dev->regs[0x53] = 0x80; - dev->regs[0x58] = 0x10; - dev->regs[0x5a] = dev->regs[0x5b] = \ - dev->regs[0x5c] = dev->regs[0x5d] = 0x11; - dev->regs[0x5e] = 0x11; - dev->regs[0x5f] = 0x31; - break; -#endif - } - - dev->regs[0x04] = 0x06; dev->regs[0x05] = 0x00; -#if defined(DEV_BRANCH) && defined(USE_I686) - if (dev->type == INTEL_440FX) - dev->regs[0x06] = 0x80; -#endif - - if (dev->type == INTEL_430FX) - dev->regs[0x07] = 0x82; -#if defined(DEV_BRANCH) && defined(USE_I686) - else if (dev->type != INTEL_440FX) -#else - else -#endif - dev->regs[0x07] = 0x02; - dev->regs[0x0b] = 0x06; - if (dev->type >= INTEL_430FX) - dev->regs[0x57] = 0x01; - else - dev->regs[0x57] = 0x31; - dev->regs[0x60] = dev->regs[0x61] = dev->regs[0x62] = \ - dev->regs[0x63] = 0x02; - dev->regs[0x64] = 0x02; - if (dev->type >= INTEL_430FX) - dev->regs[0x72] = 0x02; - - pci_add_card(0, i4x0_read, i4x0_write, dev); - - return dev; -} - - -static const device_t i430lx_device = { - "Intel 82434LX", - DEVICE_PCI, - INTEL_430LX, - i4x0_init, i4x0_close, i4x0_reset, - NULL, NULL, NULL, NULL, - NULL -}; - -static const device_t i430nx_device = { - "Intel 82434NX", - DEVICE_PCI, - INTEL_430NX, - i4x0_init, i4x0_close, i4x0_reset, - NULL, NULL, NULL, NULL, - NULL -}; - -static const device_t i430fx_device = { - "Intel SB82437FX-66", - DEVICE_PCI, - INTEL_430FX, - i4x0_init, i4x0_close, i4x0_reset, - NULL, NULL, NULL, NULL, - NULL -}; - -const device_t i430fx_pb640_device = { - "Intel SB82437FX-66 (PB640)", - DEVICE_PCI, - INTEL_430FX_PB640, - i4x0_init, i4x0_close, i4x0_reset, - NULL, NULL, NULL, NULL, - NULL -}; - -static const device_t i430hx_device = { - "Intel 82439HX", - DEVICE_PCI, - INTEL_430HX, - i4x0_init, i4x0_close, i4x0_reset, - NULL, NULL, NULL, NULL, - NULL -}; - -static const device_t i430vx_device = { - "Intel 82437VX", - DEVICE_PCI, - INTEL_430VX, - i4x0_init, i4x0_close, i4x0_reset, - NULL, NULL, NULL, NULL, - NULL -}; - -#if defined(DEV_BRANCH) && defined(USE_I686) -static const device_t i440fx_device = { - "Intel 82441FX", - DEVICE_PCI, - INTEL_440FX, - i4x0_init, i4x0_close, i4x0_reset, - NULL, NULL, NULL, NULL, - NULL -}; -#endif - - -static void -m_at_premiere_common_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_ami_pci_device); - - device_add(&ide_pci_2ch_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_2); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); - pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&sio_device); - device_add(&fdc37c665_device); - device_add(&intel_batman_device); - device_add(&intel_flash_bxt_ami_device); -} - - -/* Revenge: Intel Premiere/PCI I/430LX/AMI/SMC FDC37C665 */ -void -m_at_batman_init(const machine_t *model, void *arg) -{ - m_at_premiere_common_init(model, arg); - - device_add(&i430lx_device); -} - - -/* Plato: Intel Premiere/PCI II/430NX/AMI/SMC FDC37C665 */ -void -m_at_plato_init(const machine_t *model, void *arg) -{ - m_at_premiere_common_init(model, arg); - - device_add(&i430nx_device); -} - - -/* P54TP4XE: ASUS P/I-P55TP4XE/430FX/Award/SMC FDC37C665 */ -void -m_at_p54tp4xe_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_device); -} - - -/* Endeavor: Intel Advanced_EV/430FX/AMI/NS PC87306 */ -void -m_at_endeavor_init(const machine_t *model, void *arg) -{ - static video_timings_t endeavor_timing = {VID_BUS,3,2,4,25,25,40}; - - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_ami_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_ami_device); - - if (video_card == VID_INTERNAL) { - device_add(&s3_phoenix_trio64_onboard_pci_device); - video_inform(VID_TYPE_SPEC, &endeavor_timing); - } -} - - -/* Zappa: Intel Advanced_ZP/430FX/AMI/NS PC87306 */ -void -m_at_zappa_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_ami_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_ami_device); -} - - -/* MB500N: PC Partner MB500N/430FX/Award/SMC FDC37C665 */ -void -m_at_mb500n_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - 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); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_device); -} - - -/* President: President Award 430FX PCI/430FX/Award/Unknown SIO */ -void -m_at_president_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - memregs_init(); - - 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); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&w83877f_president_device); - device_add(&intel_flash_bxt_device); -} - - -/* Thor: Intel Advanced_ATX/430FX/AMI/NS PC87306 */ -/* MRthor: Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ -void -m_at_thor_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_ami_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_ami_device); -} - - -/* PB640: Packard Bell PB640/430FX/AMI/NS PC87306 */ -void -m_at_pb640_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_ami_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430fx_pb640_device); - device_add(&piix_pb640_device); - ide_enable_pio_override(); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_ami_device); - - if (video_card == VID_INTERNAL) { - device_add(&gd5440_onboard_pci_device); - } -} - - -/* AP53: AOpen AP53/430HX/AMI/SMC FDC37C665/669 */ -void -m_at_ap53_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_ami_pci_device); - - memregs_init(); - - powermate_memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_ONBOARD, 1, 2, 3, 4); - - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&fdc37c669_device); - device_add(&intel_flash_bxt_device); -} - - -/* P55T2P4: ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/ -void -m_at_p55t2p4_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&w83877f_device); - device_add(&intel_flash_bxt_device); -} - - -/* P55T2S: ASUS P/I-P55T2S/430HX/AMI/NS PC87306 */ -void -m_at_p55t2s_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_ami_pci_device); - - memregs_init(); - - powermate_memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_device); -} - - -/* P55TVP4: ASUS P/I-P55TVP4/430VX/Award/Winbond W8387F*/ -void -m_at_p55tvp4_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430vx_device); - device_add(&piix3_device); - device_add(&w83877f_device); - device_add(&intel_flash_bxt_device); -} - - -/* 430VX: Award 430VX PCI/430VX/Award/UMC UM8669F*/ -void -m_at_i430vx_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430vx_device); - device_add(&piix3_device); - device_add(&um8669f_device); - device_add(&intel_flash_bxt_device); -} - - -/* P55VA: Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ -void -m_at_p55va_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - 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); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430vx_device); - device_add(&piix3_device); - device_add(&fdc37c932fr_device); - device_add(&intel_flash_bxt_device); -} - - -/* J656VXD: Jetway J656VXD/430VX/Award/SMC FDC37C669*/ -void -m_at_j656vxd_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i430vx_device); - device_add(&piix3_device); - device_add(&fdc37c669_device); - device_add(&intel_flash_bxt_device); -} - - -#if defined(DEV_BRANCH) && defined(USE_I686) -/* 440FX: Tyan Titan-Pro AT/440FX/Award BIOS/SMC FDC37C665 */ -void -m_at_i440fx_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - - device_add(&i440fx_device); - device_add(&piix3_device); - device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_device); -} - - -/* S1668: Tyan Titan-Pro ATX/440FX/AMI/SMC FDC37C669 */ -void -m_at_s1668_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_ami_pci_device); - - memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - - device_add(&i440fx_device); - device_add(&piix3_device); - device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_device); -} -#endif - - -static void -acerm3a_out(uint16_t port, uint8_t val, void *priv) -{ - acerm3a_t *dev = (acerm3a_t *)priv; - - if (port == 0xea) - dev->index = val; -} - - -static uint8_t -acerm3a_in(uint16_t port, void *priv) -{ - acerm3a_t *dev = (acerm3a_t *)priv; - - if (port == 0xeb) { - switch (dev->index) { - case 2: - return 0xfd; - } - } - - return(0xff); -} - - -static void -acerm3a_close(void *priv) -{ - acerm3a_t *dev = (acerm3a_t *)priv; - - free(dev); -} - - -static void * -acerm3a_init(const device_t *info) -{ - acerm3a_t *dev = (acerm3a_t *)mem_alloc(sizeof(acerm3a_t)); - memset(dev, 0x00, sizeof(acerm3a_t)); - - io_sethandler(0x00ea, 2, - acerm3a_in,NULL,NULL, acerm3a_out,NULL,NULL, dev); - - return(dev); -} - - -static const device_t acerm3a_device = { - "Acer M3A Register", - 0, - 0, - acerm3a_init, acerm3a_close, NULL, - NULL, NULL, NULL, NULL, - NULL -}; - - -/* ACERM3A: Acer M3A/430HX/Acer/SMC FDC37C932FR */ -void -m_at_acerm3a_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - powermate_memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x1F, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x10, PCI_CARD_ONBOARD, 4, 0, 0, 0); - - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&fdc37c932fr_device); - device_add(&acerm3a_device); - device_add(&intel_flash_bxb_device); -} - - -/* ACERV35N: Acer V35N/430HX/Acer/SMC FDC37C932FR */ -void -m_at_acerv35n_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_ps2_pci_device); - - powermate_memregs_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&fdc37c932fr_device); - device_add(&acerm3a_device); - device_add(&intel_flash_bxb_device); -} diff --git a/src/machines/m_at_compaq.c b/src/machines/m_at_compaq.c deleted file mode 100644 index c080747..0000000 --- a/src/machines/m_at_compaq.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Emulation of various Compaq PC's. - * - * Version: @(#)m_at_compaq.c 1.0.9 2019/02/16 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * TheCollector1995, - * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../emu.h" -#include "../cpu/cpu.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/disk/hdc.h" -#include "../devices/disk/hdc_ide.h" -#include "machine.h" - - -/* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */ -static mem_map_t ram_mapping; - - -static uint8_t -read_ram(uint32_t addr, void *priv) -{ - addr = (addr & 0x7ffff) + 0x80000; - addreadlookup(mem_logical_addr, addr); - - return(ram[addr]); -} - - -static uint16_t -read_ramw(uint32_t addr, void *priv) -{ - addr = (addr & 0x7ffff) + 0x80000; - addreadlookup(mem_logical_addr, addr); - - return(*(uint16_t *)&ram[addr]); -} - - -static uint32_t -read_raml(uint32_t addr, void *priv) -{ - addr = (addr & 0x7ffff) + 0x80000; - addreadlookup(mem_logical_addr, addr); - - return(*(uint32_t *)&ram[addr]); -} - - -static void -write_ram(uint32_t addr, uint8_t val, void *priv) -{ - addr = (addr & 0x7ffff) + 0x80000; - addwritelookup(mem_logical_addr, addr); - - mem_write_ramb_page(addr, val, &pages[addr >> 12]); -} - - -static void -write_ramw(uint32_t addr, uint16_t val, void *priv) -{ - addr = (addr & 0x7ffff) + 0x80000; - addwritelookup(mem_logical_addr, addr); - - mem_write_ramw_page(addr, val, &pages[addr >> 12]); -} - - -static void -write_raml(uint32_t addr, uint32_t val, void *priv) -{ - addr = (addr & 0x7ffff) + 0x80000; - addwritelookup(mem_logical_addr, addr); - - mem_write_raml_page(addr, val, &pages[addr >> 12]); -} - - -static void -compaq_common_init(const machine_t *model, void *arg, int type) -{ - m_at_init(model, arg); - - mem_remap_top(384); - - device_add(&fdc_at_device); - - mem_map_add(&ram_mapping, 0xfa0000, 0x60000, - read_ram, read_ramw, read_raml, - write_ram, write_ramw, write_raml, - 0xa0000+ram, MEM_MAPPING_INTERNAL, NULL); - - switch(type) { - case 0: /* Portable 286 */ - break; - - case 2: /* Portable II */ - break; - -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - case 3: /* Portable III */ - m_olim24_video_init(); - break; - - case 3+386: /* Portable III/386 */ - m_olim24_video_init(); - if (hdc_type == 1) - device_add(&ide_isa_device); - break; -#endif - -#if defined(DEV_BRANCH) && defined(USE_DESKPRO386) - case 4+386: /* Deskpro 386 */ - if (hdc_type == 1) - device_add(&ide_isa_device); - break; -#endif - } -} - - -void -m_at_compaq_p1_init(const machine_t *model, void *arg) -{ - compaq_common_init(model, arg, 0); -} - - -void -m_at_compaq_p2_init(const machine_t *model, void *arg) -{ - compaq_common_init(model, arg, 2); -} - - -void -m_at_compaq_p3_init(const machine_t *model, void *arg) -{ - compaq_common_init(model, arg, 3); -} - - -void -m_at_compaq_p3_386_init(const machine_t *model, void *arg) -{ - compaq_common_init(model, arg, 3+386); -} diff --git a/src/machines/m_at_scat.c b/src/machines/m_at_scat.c deleted file mode 100644 index 4ab6827..0000000 --- a/src/machines/m_at_scat.c +++ /dev/null @@ -1,1438 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of Chips&Technology's SCAT (82C235) chipset. - * - * Version: @(#)m_at_scat.c 1.0.13 2019/02/16 - * - * Authors: Fred N. van Kempen, - * Original by GreatPsycho for PCem. - * Miran Grca, - * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../emu.h" -#include "../device.h" -#include "../cpu/cpu.h" -#include "../cpu/x86.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../devices/system/nmi.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.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 SCATSX_LAPTOP_FEATURES 0x60 -#define SCATSX_FAST_VIDEO_CONTROL 0x61 -#define SCATSX_FAST_VIDEORAM_ENABLE 0x62 -#define SCATSX_HIGH_PERFORMANCE_REFRESH 0x63 -#define SCATSX_CAS_TIMING_FOR_DMA 0x64 - -typedef struct scat_t -{ - uint8_t regs_2x8; - uint8_t regs_2x9; -} scat_t; - - -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_map_t scat_low_mapping[32]; -static mem_map_t scat_ems_mapping[32]; -static mem_map_t scat_high_mapping[16]; -static scat_t scat_stat[32]; -static uint32_t scat_xms_bound; -static mem_map_t scat_remap_mapping[6]; -static mem_map_t scat_4000_EFFF_mapping[44]; -static mem_map_t scat_low_ROMCS_mapping[8]; - - -static int scat_max_map[32] = { 0, 1, 1, 1, 2, 3, 4, 8, - 4, 8, 12, 16, 20, 24, 28, 32, - 0, 5, 9, 13, 6, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; -static int scatsx_max_map[32] = { 0, 1, 2, 1, 3, 4, 6, 10, - 5, 9, 13, 4, 8, 12, 16, 14, - 18, 22, 26, 20, 24, 28, 32, 18, - 20, 32, 0, 0, 0, 0, 0, 0 }; - -static int external_is_RAS = 0; - -static int scatsx_external_is_RAS[33] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0 }; - - -static uint8_t scat_read(uint16_t port, void *priv); -static void scat_write(uint16_t port, uint8_t val, void *priv); - - -static void -scat_romcs_state_update(uint8_t val) -{ - int i; - for(i = 0; i < 4; i++) { - if (val & 1) { - mem_map_enable(&scat_low_ROMCS_mapping[i << 1]); - mem_map_enable(&scat_low_ROMCS_mapping[(i << 1) + 1]); - } else { - mem_map_disable(&scat_low_ROMCS_mapping[i << 1]); - mem_map_disable(&scat_low_ROMCS_mapping[(i << 1) + 1]); - } - val >>= 1; - } - - for(i = 0; i < 4; i++) { - if (val & 1) { - mem_map_enable(&bios_mapping[i << 1]); - mem_map_enable(&bios_mapping[(i << 1) + 1]); - } else { - mem_map_disable(&bios_mapping[i << 1]); - mem_map_disable(&bios_mapping[(i << 1) + 1]); - } - val >>= 1; - } -} - - -static void -scat_shadow_state_update() -{ - int i, val; - - for (i = 0; i < 24; i++) { - val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL | MEM_WRITE_INTERNAL : MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; - mem_set_mem_state((i + 40) << 14, 0x4000, val); - } - - flushmmucache(); -} - - -static void -scat_set_xms_bound(uint8_t val) -{ - uint32_t max_xms_size = ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0xFE0000 : 0xFC0000; - - 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 = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x600000 : 0x500000; - break; - case 8: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x800000 : 0x700000; - break; - case 9: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xA00000 : 0x800000; - break; - case 10: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xC00000 : 0x900000; - break; - case 11: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xE00000 : 0xA00000; - break; - case 12: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xB00000; - break; - case 13: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xC00000; - break; - case 14: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xD00000; - break; - case 15: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xF00000; - break; - default: - scat_xms_bound = max_xms_size; - break; - } - - if ((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)) { - if((val & 0x0F) == 0 || scat_xms_bound > 0x160000) - scat_xms_bound = 0x160000; - 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 (scat_xms_bound > max_xms_size) - scat_xms_bound = max_xms_size; - if (scat_xms_bound > 0x100000) - mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (scat_xms_bound < ((uint32_t)mem_size << 10)) - mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } - - mem_map_set_addr(&scat_low_mapping[31], 0xF80000, ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000); - if(scat_regs[SCAT_VERSION] & 0xF0) { - int i; - for(i=0;i<8;i++) { - if(val & 0x10) - mem_map_disable(&scat_high_mapping[i]); - else - mem_map_enable(&scat_high_mapping[i]); - } - } -} - - -static uint32_t -get_scat_addr(uint32_t addr, scat_t *p) -{ - int nbank; - - if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80)) - addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; - - if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) { - switch((scat_regs[SCAT_EXTENDED_BOUNDARY] & ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 0x40 : 0)) | (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F)) { - case 0x41: - nbank = addr >> 19; - if(nbank < 4) - nbank = 1; - else if(nbank == 4) - nbank = 0; - else - nbank -= 3; - break; - case 0x42: - nbank = addr >> 19; - if(nbank < 8) - nbank = 1 + (nbank >> 2); - else if(nbank == 8) - nbank = 0; - else - nbank -= 6; - break; - case 0x43: - nbank = addr >> 19; - if(nbank < 12) - nbank = 1 + (nbank >> 2); - else if(nbank == 12) - nbank = 0; - else - nbank -= 9; - break; - case 0x44: - nbank = addr >> 19; - if(nbank < 4) - nbank = 2; - else if(nbank < 6) - nbank -= 4; - else - nbank -= 3; - break; - case 0x45: - nbank = addr >> 19; - if(nbank < 8) - nbank = 2 + (nbank >> 2); - else if(nbank < 10) - nbank -= 8; - else - nbank -= 6; - break; - default: - nbank = addr >> (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21); - break; - } - nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; - if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && nbank == 2 && (addr & 0x7FFFF) < 0x60000 && mem_size > 640) { - nbank = 1; - addr ^= 0x70000; - } - - if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { - if(nbank == 3) - nbank = 7; - else - return 0xFFFFFFFF; - } else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { - switch(nbank) { - case 7: - nbank = 3; - break; - /* Note - In the following cases, the chipset accesses multiple memory banks - at the same time, so it's impossible to predict which memory bank - is actually accessed. */ - case 5: - case 1: - nbank = 1; - break; - case 3: - nbank = 2; - break; - default: - nbank = 0; - break; - } - } - - if((scat_regs[SCAT_VERSION] & 0x0F) > 3 && (mem_size > 2048) && (mem_size & 1536)) { - if((mem_size & 1536) == 512) { - if(nbank == 0) - addr &= 0x7FFFF; - else - addr = 0x80000 + ((addr & 0x1FFFFF) | ((nbank - 1) << 21)); - } else { - if(nbank < 2) - addr = (addr & 0x7FFFF) | (nbank << 19); - else - addr = 0x100000 + ((addr & 0x1FFFFF) | ((nbank - 2) << 21)); - } - } else { - int nbanks_2048k, nbanks_512k; - if (mem_size <= ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 2048 : 4096) && (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8) || external_is_RAS)) { - nbanks_2048k = 0; - nbanks_512k = mem_size >> 9; - } else { - nbanks_2048k = mem_size >> 11; - nbanks_512k = (mem_size & 1536) >> 9; - } - if(nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))) { - addr &= 0x1FFFFF; - addr |= (nbank << 21); - } else if(nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)) { - addr &= 0x7FFFF; - addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19); - } else { - addr &= 0x1FFFF; - addr |= (nbanks_2048k << 21) | (nbanks_512k << 19) | ((nbank - nbanks_2048k - nbanks_512k) << 17); - } - } - } else { - uint32_t addr2; - switch(scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) { - case 2: - case 4: - nbank = addr >> 19; - if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else - addr2 = addr >> 10; - break; - case 3: - nbank = addr >> 19; - if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7FFFF) < 0x60000) { - addr ^= 0x1F0000; - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else - addr2 = addr >> 10; - break; - case 5: - nbank = addr >> 19; - if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { - nbank = (addr >> 10) & 3; - addr2 = addr >> 12; - } else - addr2 = addr >> 10; - break; - case 6: - nbank = addr >> 19; - if(nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else { - nbank = 2 + ((addr - 0x100000) >> 21); - addr2 = (addr - 0x100000) >> 11; - } - break; - case 7: - case 0x0F: - nbank = addr >> 19; - if(nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else if(nbank < 10) { - nbank = 2 + (((addr - 0x100000) >> 11) & 1); - addr2 = (addr - 0x100000) >> 12; - } else { - nbank = 4 + ((addr - 0x500000) >> 21); - addr2 = (addr - 0x500000) >> 11; - } - break; - case 8: - nbank = addr >> 19; - if(nbank < 4) { - nbank = 1; - addr2 = addr >> 11; - } else if(nbank == 4) { - nbank = 0; - addr2 = addr >> 10; - } else { - nbank -= 3; - addr2 = addr >> 10; - } - break; - case 9: - nbank = addr >> 19; - if(nbank < 8) { - nbank = 1 + ((addr >> 11) & 1); - addr2 = addr >> 12; - } else if(nbank == 8) { - nbank = 0; - addr2 = addr >> 10; - } else { - nbank -= 6; - addr2 = addr >> 10; - } - break; - case 0x0A: - nbank = addr >> 19; - if(nbank < 8) { - nbank = 1 + ((addr >> 11) & 1); - addr2 = addr >> 12; - } else if(nbank < 12) { - nbank = 3; - addr2 = addr >> 11; - } else if(nbank == 12) { - nbank = 0; - addr2 = addr >> 10; - } else { - nbank -= 9; - addr2 = addr >> 10; - } - break; - case 0x0B: - nbank = addr >> 21; - addr2 = addr >> 11; - break; - case 0x0C: - case 0x0D: - nbank = addr >> 21; - if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { - nbank = (addr >> 11) & 1; - addr2 = addr >> 12; - } else - addr2 = addr >> 11; - break; - case 0x0E: - case 0x13: - nbank = addr >> 21; - if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { - nbank = (addr >> 11) & 3; - addr2 = addr >> 13; - } else - addr2 = addr >> 11; - break; - case 0x10: - case 0x11: - nbank = addr >> 19; - if(nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else if(nbank < 10) { - nbank = 2 + (((addr - 0x100000) >> 11) & 1); - addr2 = (addr - 0x100000) >> 12; - } else if(nbank < 18) { - nbank = 4 + (((addr - 0x500000) >> 11) & 1); - addr2 = (addr - 0x500000) >> 12; - } else { - nbank = 6 + ((addr - 0x900000) >> 21); - addr2 = (addr - 0x900000) >> 11; - } - break; - case 0x12: - nbank = addr >> 19; - if(nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else if(nbank < 10) { - nbank = 2 + (((addr - 0x100000) >> 11) & 1); - addr2 = (addr - 0x100000) >> 12; - } else { - nbank = 4 + (((addr - 0x500000) >> 11) & 3); - addr2 = (addr - 0x500000) >> 13; - } - break; - case 0x14: - case 0x15: - nbank = addr >> 21; - if((nbank & 7) < 4) { - nbank = (addr >> 11) & 3; - addr2 = addr >> 13; - } else if((nbank & 7) < 6) { - nbank = 4 + (((addr - 0x800000) >> 11) & 1); - addr2 = (addr - 0x800000) >> 12; - } else { - nbank = 6 + (((addr - 0xC00000) >> 11) & 3); - addr2 = (addr - 0xC00000) >> 13; - } - break; - case 0x16: - nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3); - addr2 = addr >> 13; - break; - case 0x17: - if(external_is_RAS && (addr & 0x800) == 0) - return 0xFFFFFFFF; - nbank = addr >> 19; - if(nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else { - nbank = 2 + ((addr - 0x100000) >> 23); - addr2 = (addr - 0x100000) >> 12; - } - break; - case 0x18: - if(external_is_RAS && (addr & 0x800) == 0) - return 0xFFFFFFFF; - nbank = addr >> 21; - if(nbank < 4) { - nbank = 1; - addr2 = addr >> 12; - } else if(nbank == 4) { - nbank = 0; - addr2 = addr >> 11; - } else { - nbank -= 3; - addr2 = addr >> 11; - } - break; - case 0x19: - if(external_is_RAS && (addr & 0x800) == 0) - return 0xFFFFFFFF; - nbank = addr >> 23; - if((nbank & 3) < 2) { - nbank = (addr >> 12) & 1; - addr2 = addr >> 13; - } else - addr2 = addr >> 12; - break; - default: - if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6) { - nbank = addr >> 19; - addr2 = (addr >> 10) & 0x1FF; - } else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17) { - nbank = addr >> 21; - addr2 = (addr >> 11) & 0x3FF; - } else { - nbank = addr >> 23; - addr2 = (addr >> 12) & 0x7FF; - } - break; - } - - nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; - if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 0x16 && nbank == 3) - return 0xFFFFFFFF; - - if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { - if(nbank == 3) - nbank = 7; - else - return 0xFFFFFFFF; - } else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { - switch(nbank) { - case 7: - nbank = 3; - break; - /* Note - In the following cases, the chipset accesses multiple memory banks - at the same time, so it's impossible to predict which memory bank - is actually accessed. */ - case 5: - case 1: - nbank = 1; - break; - case 3: - nbank = 2; - break; - default: - nbank = 0; - break; - } - } - - switch(mem_size & ~511) { - case 1024: - case 1536: - addr &= 0x3FF; - if(nbank < 2) - addr |= (nbank << 10) | ((addr2 & 0x1FF) << 11); - else - addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19); - break; - case 2048: - if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 5) { - addr &= 0x3FF; - if(nbank < 4) - addr |= (nbank << 10) | ((addr2 & 0x1FF) << 12); - else - addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19); - } else { - addr &= 0x7FF; - addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); - } - break; - case 2560: - if(nbank == 0) - addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); - else { - addr &= 0x7FF; - addr2 &= 0x3FF; - addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); - } - break; - case 3072: - if(nbank < 2) - addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); - else - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); - break; - case 4096: - case 6144: - addr &= 0x7FF; - if(nbank < 2) - addr |= (nbank << 11) | ((addr2 & 0x3FF) << 12); - else - addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); - break; - case 4608: - if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18)) { - if(nbank == 0) - addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); - else if(nbank < 3) - addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12)); - else - addr = 0x480000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 3) << 19)); - } else if(nbank == 0) - addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); - else { - addr &= 0x7FF; - addr2 &= 0x3FF; - addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); - } - break; - case 5120: - case 7168: - if(nbank < 2) - addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); - else if(nbank < 4) - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); - else - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); - break; - case 6656: - if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18)) { - if(nbank == 0) - addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); - else if(nbank < 3) - addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12)); - else if(nbank == 3) - addr = 0x480000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11)); - else - addr = 0x680000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 4) << 19)); - } else if(nbank == 0) - addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); - else if(nbank == 1) { - addr &= 0x7FF; - addr2 &= 0x3FF; - addr = addr + 0x80000 + (addr2 << 11); - } else { - addr &= 0x7FF; - addr2 &= 0x3FF; - addr = addr + 0x280000 + ((addr2 << 12) | ((nbank & 1) << 11) | (((nbank - 2) & 6) << 21)); - } - break; - case 8192: - addr &= 0x7FF; - if(nbank < 4) - addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13); - else - addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); - break; - case 9216: - if(nbank < 2) - addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); - else if(external_is_RAS) { - if(nbank < 6) - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); - else - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); - } else - addr = 0x100000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23)); - break; - case 10240: - if(external_is_RAS) { - addr &= 0x7FF; - if(nbank < 4) - addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13); - else - addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); - } else if(nbank == 0) - addr = (addr & 0x7FF) | ((addr2 & 0x3FF) << 11); - else { - addr &= 0xFFF; - addr2 &= 0x7FF; - addr = addr + 0x200000 + ((addr2 << 12) | ((nbank - 1) << 23)); - } - break; - case 11264: - if(nbank < 2) - addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); - else if(nbank < 6) - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); - else - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); - break; - case 12288: - if(external_is_RAS) { - addr &= 0x7FF; - if(nbank < 4) - addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13); - else if(nbank < 6) - addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21); - else - addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); - } else { - if(nbank < 2) - addr = (addr & 0x7FF) | (nbank << 11) | ((addr2 & 0x3FF) << 12); - else - addr = 0x400000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23)); - } - break; - case 13312: - if(nbank < 2) - addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); - else if(nbank < 4) - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); - else - addr = 0x500000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 13) | ((nbank & 3) << 11)); - break; - case 14336: - addr &= 0x7FF; - if(nbank < 4) - addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13); - else if(nbank < 6) - addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21); - else - addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); - break; - case 16384: - if(external_is_RAS) { - addr &= 0x7FF; - addr2 &= 0x3FF; - addr |= ((nbank & 3) << 11) | (addr2 << 13) | ((nbank & 4) << 21); - } else { - addr &= 0xFFF; - addr2 &= 0x7FF; - if(nbank < 2) - addr |= (addr2 << 13) | (nbank << 12); - else - addr |= (addr2 << 12) | (nbank << 23); - } - break; - default: - if(mem_size < 2048 || ((mem_size & 1536) == 512) || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6)) { - addr &= 0x3FF; - addr2 &= 0x1FF; - addr |= (addr2 << 10) | (nbank << 19); - } else if(mem_size < 8192 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17) { - addr &= 0x7FF; - addr2 &= 0x3FF; - addr |= (addr2 << 11) | (nbank << 21); - } else { - addr &= 0xFFF; - addr2 &= 0x7FF; - addr |= (addr2 << 12) | (nbank << 23); - } - break; - } - } - return addr; -} - - -static void -scat_set_global_EMS_state(int state) -{ - int i; - uint32_t base_addr, virt_addr; - - for(i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; 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_map_disable(&scat_4000_EFFF_mapping[i]); - else mem_map_disable(&scat_4000_EFFF_mapping[i + 12]); - mem_map_enable(&scat_ems_mapping[i]); - if(virt_addr < ((uint32_t)mem_size << 10)) mem_map_set_exec(&scat_ems_mapping[i], ram + virt_addr); - else mem_map_set_exec(&scat_ems_mapping[i], NULL); - } else { - mem_map_set_exec(&scat_ems_mapping[i], ram + base_addr); - mem_map_disable(&scat_ems_mapping[i]); - - int conf = (scat_regs[SCAT_VERSION] & 0xF0) ? (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) : (scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2); - if(i < 24) { - if(conf > 1 || (conf == 1 && i < 16)) - mem_map_enable(&scat_4000_EFFF_mapping[i]); - else - mem_map_disable(&scat_4000_EFFF_mapping[i]); - } else if(conf > 3 || ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && conf == 2)) - mem_map_enable(&scat_4000_EFFF_mapping[i + 12]); - else - mem_map_disable(&scat_4000_EFFF_mapping[i + 12]); - } - } - flushmmucache(); -} - - -static void -scat_memmap_state_update() -{ - int i; - uint32_t addr; - - for(i=(((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 16);i<44;i++) { - addr = get_scat_addr(0x40000 + (i << 14), NULL); - mem_map_set_exec(&scat_4000_EFFF_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); - } - addr = get_scat_addr(0, NULL); - mem_map_set_exec(&scat_low_mapping[0], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); - addr = get_scat_addr(0xF0000, NULL); - mem_map_set_exec(&scat_low_mapping[1], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); - for(i=2;i<32;i++) { - addr = get_scat_addr(i << 19, NULL); - mem_map_set_exec(&scat_low_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); - } - - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) { - for(i=0;i < scat_max_map[(scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)];i++) - mem_map_enable(&scat_low_mapping[i]); - for(;i<32;i++) mem_map_disable(&scat_low_mapping[i]); - - for(i=24;i<36;i++) { - if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4) - mem_map_disable(&scat_4000_EFFF_mapping[i]); - else - mem_map_enable(&scat_4000_EFFF_mapping[i]); - } - } else { - for(i=0;i < scatsx_max_map[scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F];i++) - mem_map_enable(&scat_low_mapping[i]); - for(;i<32;i++) mem_map_disable(&scat_low_mapping[i]); - - for(i=24;i<36;i++) { - if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 2 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3) - mem_map_disable(&scat_4000_EFFF_mapping[i]); - else - mem_map_enable(&scat_4000_EFFF_mapping[i]); - } - } - - if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0)) { - if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)) { - mem_map_disable(&scat_low_mapping[2]); - for(i=0;i<6;i++) { - addr = get_scat_addr(0x100000 + (i << 16), NULL); - mem_map_set_exec(&scat_remap_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); - mem_map_enable(&scat_remap_mapping[i]); - } - } else { - for(i=0;i<6;i++) - mem_map_disable(&scat_remap_mapping[i]); - if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 4) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 3)) - mem_map_enable(&scat_low_mapping[2]); - } - } else { - for(i=0;i<6;i++) - mem_map_disable(&scat_remap_mapping[i]); - mem_map_enable(&scat_low_mapping[2]); - } - - scat_set_global_EMS_state(scat_regs[SCAT_EMS_CONTROL] & 0x80); -} - - -static 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_DMA_WAIT_STATE_CONTROL: - 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: - /* TODO - Only use AUX parity disable bit for this version. - Other bits should be implemented later. */ - val &= (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x40 : 0x60; - scat_reg_valid = 1; - break; - case SCAT_DRAM_CONFIGURATION: - scat_map_update = 1; - - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) { - cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; - cpu_update_waitstates(); - } - - scat_reg_valid = 1; - break; - case SCAT_EXTENDED_BOUNDARY: - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) { - if(scat_regs[SCAT_VERSION] < 4) { - val &= 0xBF; - scat_set_xms_bound(val & 0x0f); - } else { - val = (val & 0x7F) | 0x80; - scat_set_xms_bound(val & 0x4f); - } - } else - scat_set_xms_bound(val & 0x1f); - 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]) & 0xC0) scat_map_update = 1; - scat_reg_valid = 1; - break; - case SCAT_ROM_ENABLE: - scat_reg_valid = 1; - scat_romcs_state_update(val); - break; - case SCAT_RAM_WRITE_PROTECT: - scat_reg_valid = 1; - flushmmucache_cr3(); - break; - 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; - case SCATSX_LAPTOP_FEATURES: - if((scat_regs[SCAT_VERSION] & 0xF0) != 0) { - val = (val & ~8) | (scat_regs[SCATSX_LAPTOP_FEATURES] & 8); - scat_reg_valid = 1; - } - break; - case SCATSX_FAST_VIDEO_CONTROL: - case SCATSX_FAST_VIDEORAM_ENABLE: - case SCATSX_HIGH_PERFORMANCE_REFRESH: - case SCATSX_CAS_TIMING_FOR_DMA: - if((scat_regs[SCAT_VERSION] & 0xF0) != 0) scat_reg_valid = 1; - break; - default: - break; - } - if (scat_reg_valid) - scat_regs[scat_index] = val; - 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; - - case 0x208: - case 0x218: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; - else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; - 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 < ((uint32_t)mem_size << 10)) mem_map_set_exec(&scat_ems_mapping[index], ram + virt_addr); - else mem_map_set_exec(&scat_ems_mapping[index], NULL); - flushmmucache(); - } - } - break; - case 0x209: - case 0x219: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; - else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; - 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_map_disable(&scat_4000_EFFF_mapping[index]); - else mem_map_disable(&scat_4000_EFFF_mapping[index + 12]); - if(virt_addr < ((uint32_t)mem_size << 10)) mem_map_set_exec(&scat_ems_mapping[index], ram + virt_addr); - else mem_map_set_exec(&scat_ems_mapping[index], NULL); - mem_map_enable(&scat_ems_mapping[index]); - } else { - mem_map_set_exec(&scat_ems_mapping[index], ram + base_addr); - mem_map_disable(&scat_ems_mapping[index]); - if(index < 24) mem_map_enable(&scat_4000_EFFF_mapping[index]); - else mem_map_enable(&scat_4000_EFFF_mapping[index + 12]); - } - flushmmucache(); - } - - if (scat_ems_reg_2xA & 0x80) - scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & (((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0x1f : 3)); - } - break; - case 0x20A: - case 0x21A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - scat_ems_reg_2xA = ((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? val : val & 0xc3; - break; - } -} - - -static uint8_t -scat_read(uint16_t port, void *priv) -{ - uint8_t val = 0xff, index; - switch (port) { - case 0x23: - switch (scat_index) { - case SCAT_MISCELLANEOUS_STATUS: - val = (scat_regs[scat_index] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5); - break; - case SCAT_DRAM_CONFIGURATION: - if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); - else val = scat_regs[scat_index]; - break; - case SCAT_EXTENDED_BOUNDARY: - val = scat_regs[scat_index]; - if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) { - if((scat_regs[SCAT_VERSION] & 0x0F) >= 4) - val |= 0x80; - else - val &= 0xAF; - } - break; - default: - val = scat_regs[scat_index]; - break; - } - break; - - case 0x92: - val = scat_port_92; - break; - - case 0x208: - case 0x218: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; - else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; - val = scat_stat[index].regs_2x8; - } - break; - case 0x209: - case 0x219: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; - else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; - 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; -} - - -static uint8_t -mem_read_scatb(uint32_t addr, void *priv) -{ - uint8_t val = 0xff; - scat_t *stat = (scat_t *)priv; - - addr = get_scat_addr(addr, stat); - if (addr < ((uint32_t)mem_size << 10)) - val = ram[addr]; - - return val; -} - - -static void -mem_write_scatb(uint32_t addr, uint8_t val, void *priv) -{ - scat_t *stat = (scat_t *)priv; - uint32_t oldaddr = addr, chkaddr; - - addr = get_scat_addr(addr, stat); - chkaddr = stat ? addr : oldaddr; - if (chkaddr >= 0xC0000 && chkaddr < 0x100000) { - if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return; - } - if (addr < ((uint32_t)mem_size << 10)) - ram[addr] = val; -} - - -static uint16_t -mem_read_scatw(uint32_t addr, void *priv) -{ - uint16_t val = 0xffff; - scat_t *stat = (scat_t *)priv; - - addr = get_scat_addr(addr, stat); - if (addr < ((uint32_t)mem_size << 10)) - val = *(uint16_t *)&ram[addr]; - - return val; -} - - -static void -mem_write_scatw(uint32_t addr, uint16_t val, void *priv) -{ - scat_t *stat = (scat_t *)priv; - uint32_t oldaddr = addr, chkaddr; - - addr = get_scat_addr(addr, stat); - chkaddr = stat ? addr : oldaddr; - if (chkaddr >= 0xC0000 && chkaddr < 0x100000) { - if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return; - } - if (addr < ((uint32_t)mem_size << 10)) - *(uint16_t *)&ram[addr] = val; -} - - -static uint32_t -mem_read_scatl(uint32_t addr, void *priv) -{ - uint32_t val = 0xffffffff; - scat_t *stat = (scat_t *)priv; - - addr = get_scat_addr(addr, stat); - if (addr < ((uint32_t)mem_size << 10)) - val = *(uint32_t *)&ram[addr]; - - return val; -} - - -static void -mem_write_scatl(uint32_t addr, uint32_t val, void *priv) -{ - scat_t *stat = (scat_t *)priv; - uint32_t oldaddr = addr, chkaddr; - - addr = get_scat_addr(addr, stat); - chkaddr = stat ? addr : oldaddr; - if (chkaddr >= 0xC0000 && chkaddr < 0x100000) { - if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return; - } - if (addr < ((uint32_t)mem_size << 10)) - *(uint32_t *)&ram[addr] = val; -} - - -static void -scat_common_init(int type) -{ - int i; - - 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); - - for (i = 0; i < 256; i++) - scat_regs[i] = 0xff; - - scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; - switch(type) { - case 1: - case 2: - scat_regs[SCAT_VERSION] = 4; - break; - - default: - scat_regs[SCAT_VERSION] = 1; - break; - } - 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_map_disable(&ram_low_mapping); - mem_map_disable(&ram_mid_mapping); - mem_map_disable(&ram_high_mapping); - for (i = 0; i < 4; i++) - mem_map_disable(&bios_mapping[i]); - mem_map_add(&scat_low_mapping[0], 0, 0x40000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL); - mem_map_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL); - for(i=2;i<32;i++) - mem_map_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL); - mem_map_set_addr(&scat_low_mapping[31], 0xF80000, scat_regs[SCAT_VERSION] < 4 ? 0x40000 : 0x60000); - - for (i = 0; i < 44; i++) - mem_map_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); - for (i = 0; i < 8; i++) { - mem_map_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); - mem_map_disable(&scat_low_ROMCS_mapping[i]); - } - - for (i = 0; i < 32; i++) { - scat_stat[i].regs_2x8 = 0xff; - scat_stat[i].regs_2x9 = 0x03; - mem_map_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); - } - - for (i = (scat_regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++) { - mem_map_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) & biosmask), 0, NULL); - mem_map_enable(&scat_high_mapping[i]); - } - - for(i=0;i<6;i++) - mem_map_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); - - external_is_RAS = (scat_regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4; - - scat_set_xms_bound(0); - scat_memmap_state_update(); - scat_shadow_state_update(); -} - - -void -m_at_scat_init(const machine_t *model, void *arg) -{ - m_at_init(model, arg); - - device_add(&fdc_at_device); - - scat_common_init(0); -} - - -void -m_at_scat_gw286ct_init(const machine_t *model, void *arg) -{ - m_at_init(model, arg); - - device_add(&fdc_at_device); - - scat_common_init(1); -} - - -void -m_at_scat_spc4216p_init(const machine_t *model, void *arg) -{ - m_at_init(model, arg); - - device_add(&fdc_at_device); - - scat_common_init(2); -} - - -static void -scatsx_common_init(void) -{ - int i; - - 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); - - for (i = 0; i < 256; i++) - scat_regs[i] = 0xff; - - scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; - scat_regs[SCAT_VERSION] = 0x13; - scat_regs[SCAT_CLOCK_CONTROL] = 6; - scat_regs[SCAT_PERIPHERAL_CONTROL] = 0; - 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] = 1; - scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; - scat_regs[SCAT_EMS_CONTROL] = 0; - scat_regs[SCATSX_LAPTOP_FEATURES] = 0; - scat_regs[SCATSX_FAST_VIDEO_CONTROL] = 0; - scat_regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0; - scat_regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8; - scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; - scat_port_92 = 0; - - mem_map_disable(&ram_low_mapping); - mem_map_disable(&ram_mid_mapping); - mem_map_disable(&ram_high_mapping); - for (i = 0; i < 4; i++) - mem_map_disable(&bios_mapping[i]); - mem_map_add(&scat_low_mapping[0], 0, 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL); - mem_map_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL); - for(i=2;i<32;i++) - mem_map_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL); - mem_map_set_addr(&scat_low_mapping[31], 0xF80000, 0x40000); - - for (i = 16; i < 44; i++) { - mem_map_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); - mem_map_enable(&scat_4000_EFFF_mapping[i]); - } - for (i = 0; i < 8; i++) { - mem_map_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); - mem_map_disable(&scat_low_ROMCS_mapping[i]); - } - - for (i = 24; i < 32; i++) { - scat_stat[i].regs_2x8 = 0xff; - scat_stat[i].regs_2x9 = 0x03; - mem_map_add(&scat_ems_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + 28) << 14), 0, &scat_stat[i]); - mem_map_disable(&scat_ems_mapping[i]); - } - - for (i = 0; i < 16; i++) { - mem_map_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) & biosmask), 0, NULL); - mem_map_enable(&scat_high_mapping[i]); - } - - for(i=0;i<6;i++) - mem_map_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); - - external_is_RAS = scatsx_external_is_RAS[mem_size >> 9]; - - scat_set_xms_bound(0); - scat_memmap_state_update(); - scat_shadow_state_update(); -} - - -void -m_at_scatsx_init(const machine_t *model, void *arg) -{ - m_at_common_init(model, arg); - - device_add(&keyboard_at_ami_device); - device_add(&fdc_at_device); - - scatsx_common_init(); -} diff --git a/src/machines/m_at_commodore.c b/src/machines/m_commodore.c similarity index 68% rename from src/machines/m_at_commodore.c rename to src/machines/m_commodore.c index 6146472..c80b075 100644 --- a/src/machines/m_at_commodore.c +++ b/src/machines/m_commodore.c @@ -6,9 +6,9 @@ * * This file is part of the VARCem Project. * - * Implementation of the Commodore PC3 system. + * Implementation of the Commodore PC-30 system. * - * Version: @(#)m_at_commodore.c 1.0.12 2019/02/16 + * Version: @(#)m_commodore.c 1.0.14 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,9 +38,11 @@ */ #include #include +#include #include #include #include "../emu.h" +#include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" #include "../device.h" @@ -51,8 +53,13 @@ #include "machine.h" +typedef struct { + int type; +} pc30_t; + + static void -pc3_write(uint16_t port, uint8_t val, void *priv) +pc30_write(uint16_t port, uint8_t val, void *priv) { switch (val & 0x03) { case 1: @@ -81,21 +88,53 @@ pc3_write(uint16_t port, uint8_t val, void *priv) static void -pc3_init(void) +pc30_close(void *priv) { - io_sethandler(0x0230, 1, - NULL,NULL,NULL, pc3_write,NULL,NULL, NULL); + pc30_t *dev = (pc30_t *)priv; + + free(dev); } -void -m_at_cmdpc_init(const machine_t *model, void *arg) +static void * +pc30_init(const device_t *info, void *arg) { - m_at_ide_init(model, arg); + pc30_t *dev; + + dev = (pc30_t *)mem_alloc(sizeof(pc30_t)); + memset(dev, 0x00, sizeof(pc30_t)); + dev->type = info->local; + + /* Add machine device to system. */ + device_add_ex(info, dev); + + m_at_ide_init(); mem_remap_top(384); device_add(&fdc_at_device); - pc3_init(); + io_sethandler(0x0230, 1, + NULL,NULL,NULL, pc30_write,NULL,NULL, NULL); + + return(dev); } + + +static const machine_t pc30_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 640, 16384, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_cbm_pc30 = { + "Commodore PC-30", + DEVICE_ROOT, + 0, + L"commodore/pc30", + pc30_init, pc30_close, NULL, + NULL, NULL, NULL, + &pc30_info, + NULL +}; diff --git a/src/machines/m_compaq.c b/src/machines/m_compaq.c new file mode 100644 index 0000000..6e6b6f3 --- /dev/null +++ b/src/machines/m_compaq.c @@ -0,0 +1,371 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of various Compaq PC's. + * + * **NOTE** All Compaq machines are now in DevBranch, as none of them + * seem to be fully functional. The Portable, Portable/286 + * and Portable II machines need the 'Compaq VDU' video card + * (which is in m_compaq_vid.c), the Portable 3 needs the + * Plasma driver, there are some ROM issues, etc. + * + * Version: @(#)m_compaq.c 1.0.11 2019/04/14 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * TheCollector1995, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/system/nmi.h" +#include "../devices/system/pit.h" +#include "../devices/input/keyboard.h" +#include "../devices/ports/parallel.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "../devices/video/video.h" +#include "machine.h" +#include "m_compaq.h" +#include "m_olim24.h" + + +typedef struct { + int type; + + mem_map_t ram_mapping; /* Deskpro 386 remaps RAM from + * 0x0a0000-0x0fffff to 0xfa0000 */ +} cpq_t; + + +static uint8_t +read_ram(uint32_t addr, void *priv) +{ +// cpq_t *dev = (cpq_t *)priv; + + addr = (addr & 0x7ffff) + 0x80000; + addreadlookup(mem_logical_addr, addr); + + return(ram[addr]); +} + + +static uint16_t +read_ramw(uint32_t addr, void *priv) +{ +// cpq_t *dev = (cpq_t *)priv; + + addr = (addr & 0x7ffff) + 0x80000; + addreadlookup(mem_logical_addr, addr); + + return(*(uint16_t *)&ram[addr]); +} + + +static uint32_t +read_raml(uint32_t addr, void *priv) +{ +// cpq_t *dev = (cpq_t *)priv; + + addr = (addr & 0x7ffff) + 0x80000; + addreadlookup(mem_logical_addr, addr); + + return(*(uint32_t *)&ram[addr]); +} + + +static void +write_ram(uint32_t addr, uint8_t val, void *priv) +{ +// cpq_t *dev = (cpq_t *)priv; + + addr = (addr & 0x7ffff) + 0x80000; + addwritelookup(mem_logical_addr, addr); + + mem_write_ramb_page(addr, val, &pages[addr >> 12]); +} + + +static void +write_ramw(uint32_t addr, uint16_t val, void *priv) +{ +// cpq_t *dev = (cpq_t *)priv; + + addr = (addr & 0x7ffff) + 0x80000; + addwritelookup(mem_logical_addr, addr); + + mem_write_ramw_page(addr, val, &pages[addr >> 12]); +} + + +static void +write_raml(uint32_t addr, uint32_t val, void *priv) +{ +// cpq_t *dev = (cpq_t *)priv; + + addr = (addr & 0x7ffff) + 0x80000; + addwritelookup(mem_logical_addr, addr); + + mem_write_raml_page(addr, val, &pages[addr >> 12]); +} + + +static void +cpq_close(void *priv) +{ + cpq_t *dev = (cpq_t *)priv; + + free(dev); +} + + +static void * +cpq_init(const device_t *info, void *arg) +{ + cpq_t *dev; + + dev = (cpq_t *)mem_alloc(sizeof(cpq_t)); + memset(dev, 0x00, sizeof(cpq_t)); + dev->type = info->local; + + /* Add machine device to system. */ + device_add_ex(info, dev); + + switch(dev->type) { + case 0: /* Portable */ + machine_common_init(); + nmi_init(); + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + + device_add(&keyboard_xt_device); + parallel_setup(0, 0x03bc); + + if (video_card == VID_INTERNAL) + device_add(&compaq_video_device); + + device_add(&fdc_xt_device); + break; + + case 1: /* Portable/286 */ + m_at_init(); + mem_remap_top(384); + mem_map_add(&dev->ram_mapping, 0xfa0000, 0x60000, + read_ram,read_ramw,read_raml, + write_ram,write_ramw,write_raml, + ram + 0xa0000, MEM_MAPPING_INTERNAL, dev); + + if (video_card == VID_INTERNAL) + device_add(&compaq_video_device); + + device_add(&fdc_at_device); + break; + + case 2: /* Portable II */ + m_at_init(); + mem_remap_top(384); + mem_map_add(&dev->ram_mapping, 0xfa0000, 0x60000, + read_ram,read_ramw,read_raml, + write_ram,write_ramw,write_raml, + ram + 0xa0000, MEM_MAPPING_INTERNAL, dev); + + if (video_card == VID_INTERNAL) + device_add(&compaq_video_device); + + device_add(&fdc_at_device); + break; + + case 3: /* Portable III */ + m_at_init(); + mem_remap_top(384); + mem_map_add(&dev->ram_mapping, 0xfa0000, 0x60000, + read_ram,read_ramw,read_raml, + write_ram,write_ramw,write_raml, + ram + 0xa0000, MEM_MAPPING_INTERNAL, dev); + + if (video_card == VID_INTERNAL) + m_olim24_vid_init(1); + + device_add(&fdc_at_device); + break; + + case 4: /* Portable III/386 */ + m_at_init(); + mem_remap_top(384); + mem_map_add(&dev->ram_mapping, 0xfa0000, 0x60000, + read_ram,read_ramw,read_raml, + write_ram,write_ramw,write_raml, + ram + 0xa0000, MEM_MAPPING_INTERNAL, dev); + + if (video_card == VID_INTERNAL) + m_olim24_vid_init(1); + + device_add(&fdc_at_device); + + if (hdc_type == HDC_INTERNAL) + device_add(&ide_isa_device); + break; + + case 5: /* Deskpro 386 */ + m_at_init(); + mem_remap_top(384); + + device_add(&fdc_at_device); + + if (hdc_type == HDC_INTERNAL) + device_add(&ide_isa_device); + break; + } + + return(dev); +} + + +static const machine_t p1_info = { + MACHINE_ISA | MACHINE_VIDEO, + 0, + 128, 640, 128, 0, -1, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_cpq_p1 = { + "Compaq Portable", + DEVICE_ROOT, + 0, + L"compaq/portable", + cpq_init, cpq_close, NULL, + NULL, NULL, NULL, + &p1_info, + NULL +}; + + +static const machine_t p1_286_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 640, 16384, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_cpq_p1_286 = { + "Compaq Portable/286", + DEVICE_ROOT, + 1, + L"compaq/portable286", + cpq_init, cpq_close, NULL, + NULL, NULL, NULL, + &p1_286_info, + NULL +}; + + +static const machine_t p2_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 640, 16384, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_cpq_p2 = { + "Compaq Portable II", + DEVICE_ROOT, + 2, + L"compaq/portable2", + cpq_init, cpq_close, NULL, + NULL, NULL, NULL, + &p2_info, + NULL +}; + + +static const machine_t p3_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, + MACHINE_VIDEO, + 640, 16384, 128, 128, 6, + {{"",cpus_286}} +}; + +const device_t m_cpq_p3 = { + "Compaq Portable III", + DEVICE_ROOT, + 3, + L"compaq/portable3", + cpq_init, cpq_close, NULL, + NULL, NULL, NULL, + &p3_info, + NULL +}; + + +static const machine_t p3_386_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, + MACHINE_VIDEO, + 1, 14, 1, 128, -1, + {{"Intel",cpus_i386DX},{"AMD",cpus_Am386DX},{"Cyrix",cpus_486DLC}} +}; + +const device_t m_cpq_p3_386 = { + "Compaq Portable III/386", + DEVICE_ROOT, + 4, + L"compaq/deskpro386", + cpq_init, cpq_close, NULL, + NULL, NULL, NULL, + &p3_386_info, + NULL +}; + + +static const machine_t dp_386_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, + MACHINE_VIDEO, + 1, 14, 1, 128, -1, + {{"Intel",cpus_i386DX},{"AMD",cpus_Am386DX},{"Cyrix",cpus_486DLC}} +}; + +const device_t m_cpq_dp_386 = { + "Compaq Deskpro/386", + DEVICE_ROOT, + 5, + L"compaq/deskpro386", + cpq_init, cpq_close, NULL, + NULL, NULL, NULL, + &dp_386_info, + NULL +}; diff --git a/src/machines/m_xt_xi8088.h b/src/machines/m_compaq.h similarity index 63% rename from src/machines/m_xt_xi8088.h rename to src/machines/m_compaq.h index e7786c3..9a6a3d0 100644 --- a/src/machines/m_xt_xi8088.h +++ b/src/machines/m_compaq.h @@ -6,17 +6,13 @@ * * This file is part of the VARCem Project. * - * Definitions for the Xi8088 open-source machine. + * Definitions for the Compaq machines. * - * Version: @(#)m_xt_xi8088.h 1.0.2 2018/03/15 + * Version: @(#)m_compaq.h 1.0.1 2019/04/13 * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Author: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2019 Fred N. van Kempen. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,19 +32,24 @@ * Boston, MA 02111-1307 * USA. */ -#ifndef MACHINE_XI8088_H -# define MACHINE_XI8088_H +#ifndef MACHINE_COMPAQ_H +# define MACHINE_COMPAQ_H #ifdef EMU_DEVICE_H -extern const device_t xi8088_device; +extern const device_t m_cpq_p1; +extern const device_t m_cpq_p1_286; +extern const device_t m_cpq_p2; +extern const device_t m_cpq_p3; +extern const device_t m_cpq_p3_386; +extern const device_t m_cpq_dp_386; + +extern const device_t compaq_video_device; #endif -extern uint8_t xi8088_turbo_get(); -extern void xi8088_turbo_set(uint8_t value); -extern void xi8088_bios_128kb_set(int val); -extern int xi8088_bios_128kb(); +extern void compaq_video_options_set(uint8_t options); +extern void compaq_display_set(uint8_t internal); -#endif /*MACHINE_XI8088_H*/ +#endif /*MACHINE_COMPAQ_H*/ diff --git a/src/machines/m_compaq_vid.c b/src/machines/m_compaq_vid.c new file mode 100644 index 0000000..62dd314 --- /dev/null +++ b/src/machines/m_compaq_vid.c @@ -0,0 +1,796 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of Compaq's dual-mode VDU Controller card. + * + * As per the service manual for the Portable, Portable Plus + * and Portable 286 machines, this controller was a merge of + * the existing MDA and CGA controllers, where the CGA part + * was also extended to higher resolutions. This was copied + * from Olivetti's version for their M24 system. + * + * We also add a third mode here, the Plasma LCD used by the + * Compaq Portable III. This was a fixed-resolution amber gas + * plasma display. The code for this was taken from the code + * for the Toshiba 3100e machine, which used a similar display. + * + * Version: @(#)m_compaq_vid.c 1.0.1 2019/04/13 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * TheCollector1995, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../timer.h" +#include "../devices/system/nmi.h" +#include "../devices/system/pit.h" +#include "../devices/video/video.h" +#include "../devices/video/vid_mda.h" +#include "../devices/video/vid_cga.h" +#include "machine.h" +#include "m_compaq.h" + + +#define PLASMA_XSIZE 640 +#define PLASMA_YSIZE 400 + + +typedef struct { + int type; + + int mode; + uint8_t options; + + uint8_t attrmap; /* attribute mapping register */ + + uint8_t port_13c6; + + mda_t mda; + mem_map_t mda_mapping; + + cga_t cga; + mem_map_t cga_mapping; + + int64_t dispontime, + dispofftime; + int64_t vsynctime; + + int64_t vidtime; + + int linepos, displine; + int lineff; + int con, coff; + int vadj; + int vc; + int firstline, + lastline; + + int dispon; + + uint8_t *vram; + + /* Mapping of attributes to colors. */ + uint32_t amber, + black; + uint32_t blinkcols[256][2]; + uint32_t normcols[256][2]; +} vid_t; + + +static uint8_t st_video_options; +static int8_t st_display_mode = -1; + + +static void +recalc_timings(vid_t *dev) +{ + double disptime; + double _dispontime, _dispofftime; + + switch(dev->mode) { + case 0: + mda_recalctimings(&dev->mda); + return; + + case 1: + cga_recalctimings(&dev->cga); + return; + } + + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + + dev->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); +} + + +static void +recalc_attrs(vid_t *dev) +{ + int n; + + /* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold + */ + + /* Set up colors. */ + dev->amber = makecol(0xf7, 0x7c, 0x34); + dev->black = makecol(0x17, 0x0c, 0x00); + + /* + * Initialize the attribute mapping. + * Start by defaulting everything to black on amber, + * and with bold set by bit 3. + */ + for (n = 0; n < 256; n++) { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->amber; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->black; + } + + /* + * Colors 0x11-0xff are controlled by bits 2 and 3 of the + * passed value. Exclude x0 and x8, which are always black + * on amber. + */ + for (n = 0x11; n <= 0xff; n++) { + if ((n & 7) == 0) continue; + + if (dev->attrmap & 4) { + /* Inverse */ + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->amber; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->black; + } else { + /* Normal */ + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->black; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->amber; + } + } + + /* + * Set up the 01-0e range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects 81-8e. + */ + for (n = 0x01; n <= 0x0e; n++) { + if (n == 7) continue; + + if (dev->attrmap & 1) { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->amber; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->black; + dev->blinkcols[n+128][0] = dev->amber; + dev->blinkcols[n+128][1] = dev->black; + } else { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->black; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->amber; + dev->blinkcols[n+128][0] = dev->black; + dev->blinkcols[n+128][1] = dev->amber; + } + } + + /* + * Colors 07 and 0f are always amber on black. + * If blinking is enabled so are 87 and 8f. + */ + for (n = 0x07; n <= 0x0f; n += 8) { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->black; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->amber; + dev->blinkcols[n+128][0] = dev->black; + dev->blinkcols[n+128][1] = dev->amber; + } + + /* When not blinking, colors 81-8f are always amber on black. */ + for (n = 0x81; n <= 0x8f; n ++) { + dev->normcols[n][0] = dev->black; + dev->normcols[n][1] = dev->amber; + } + + /* + * Finally do the ones which are solid black. + * These differ between the normal and blinking mappings. + */ + for (n = 0; n <= 0xff; n += 0x11) { + dev->normcols[n][0] = dev->normcols[n][1] = dev->black; + } + + /* In the blinking range, 00 11 22 .. 77 and 80 91 a2 .. f7 are black. */ + for (n = 0; n <= 0x77; n += 0x11) { + dev->blinkcols[n][0] = dev->blinkcols[n][1] = dev->black; + dev->blinkcols[n+128][0] = dev->blinkcols[n+128][1] = dev->black; + } +} + + +static void +vid_poll_plasma(void *priv) +{ + vid_t *dev = (vid_t *)priv; + cga_t *cga = &dev->cga; + uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x7fff; + uint16_t ma = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x7fff; + uint16_t addr; + int drawcursor; + int cursorline; + int blink; + int x, c; + uint8_t chr, attr; + uint32_t cols[2]; + uint8_t sc = (dev->displine) & 15; + uint8_t dat, pattern; + uint32_t ink0 = 0, ink1 = 0; + uint32_t ink = 0; + uint32_t fg = (cga->cgacol & 0x0f) ? dev->amber : dev->black; + uint32_t bg = dev->black; + + if (! dev->linepos) { + cga->vidtime += dev->dispofftime; + cga->cgastat |= 1; + dev->linepos = 1; + + if (dev->dispon) { + if (cga->displine < cga->firstline) { + cga->firstline = cga->displine; + video_blit_wait_buffer(); + } + cga->lastline = cga->displine; + + if (cga->cgamode & 0x02) { + /* Graphics */ + if (cga->cgamode & 0x10) { + if (dev->options & 1) + addr = ((dev->displine) & 1) * 0x2000 + ((dev->displine >> 1) & 1) * 0x4000 + (dev->displine >> 2) * 80 + ((ma & ~1) << 1); + else + addr = ((dev->displine >> 1) & 1) * 0x2000 + (dev->displine >> 2) * 80 + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) { + dat = dev->vram[(addr & 0x7fff)]; + addr++; + + for (c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (! (cga->cgamode & 8)) + ink = dev->black; + screen->line[dev->displine][x * 8 + c].val = ink; + dat = dat << 1; + } + } + } else { + addr = ((dev->displine >> 1) & 1) * 0x2000 + (dev->displine >> 2) * 80 + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) { + dat = dev->vram[(addr & 0x7fff)]; + addr++; + + for (c = 0; c < 4; c++) { + pattern = (dat & 0xc0) >> 6; + if (! (cga->cgamode & 8)) + pattern = 0; + + switch (pattern & 3) { + case 0: + ink0 = ink1 = dev->black; + break; + + case 1: + if (dev->displine & 1) { + ink0 = dev->black; + ink1 = dev->black; + } else { + ink0 = dev->amber; + ink1 = dev->black; + } + break; + + case 2: + if (dev->displine & 1) { + ink0 = dev->black; + ink1 = dev->amber; + } else { + ink0 = dev->amber; + ink1 = dev->black; + } + break; + + case 3: + ink0 = ink1 = dev->amber; + break; + } + + screen->line[dev->displine][x*8 + 2*c].val = ink0; + screen->line[dev->displine][x*8 + 2*c + 1].val = ink1; + dat = dat << 2; + } + } + } + } else if (cga->cgamode & 1) { + /* High-res text */ + addr = ((ma & ~1) + (dev->displine >> 4) * 80) * 2; + ma += (dev->displine >> 4) * 80; + + if ((cga->crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((cga->crtc[10] & 0x0f) <= sc) && + ((cga->crtc[11] & 0x0f) >= sc); + } + + for (x = 0; x < 80; x++) { + chr = dev->vram[((addr + 2 * x) & 0x7fff)]; + attr = dev->vram[((addr + 2 * x + 1) & 0x7fff)]; + + drawcursor = ((ma == ca) && cursorline && + (cga->cgamode & 8) && + (dev->cga.cgablink & 16)); + + blink = ((cga->cgablink & 16) && + (cga->cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + if (cga->cgamode & 0x20) { + /* Blink */ + cols[1] = dev->blinkcols[attr][1]; + cols[0] = dev->blinkcols[attr][0]; + if (blink) + cols[1] = cols[0]; + } else { + cols[1] = dev->normcols[attr][1]; + cols[0] = dev->normcols[attr][0]; + } + + if (drawcursor) { + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 3) + c].val = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (dev->amber ^ dev->black); + } + } else { + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 3) + c].val = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + + ma++; + } + } else { + addr = ((ma & ~1) + (dev->displine >> 4) * 40) * 2; + ma += (dev->displine >> 4) * 40; + + if ((cga->crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((cga->crtc[10] & 0x0f) <= sc) && + ((cga->crtc[11] & 0x0f) >= sc); + } + + for (x = 0; x < 40; x++) { + chr = dev->vram[((addr + 2 * x) & 0x7fff)]; + attr = dev->vram[((addr + 2 * x + 1) & 0x7fff)]; + + drawcursor = ((ma == ca) && cursorline && + (cga->cgamode & 8) && + (cga->cgablink & 16)); + + blink = ((cga->cgablink & 16) && + (cga->cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + if (cga->cgamode & 0x20) { + /* Blink */ + cols[1] = dev->blinkcols[attr][1]; + cols[0] = dev->blinkcols[attr][0]; + if (blink) + cols[1] = cols[0]; + } else { + cols[1] = dev->normcols[attr][1]; + cols[0] = dev->normcols[attr][0]; + } + + if (drawcursor) { + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + c*2].val = screen->line[dev->displine][(x << 4) + c*2 + 1].val = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (dev->amber ^ dev->black); + } + } else { + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + c*2].val = screen->line[dev->displine][(x << 4) + c*2+1].val = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + + ma++; + } + } + } + + dev->displine++; + + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (dev->displine == 400) { + /* Start of VSYNC. */ + cga->cgastat |= 8; + dev->dispon = 0; + } + + if (dev->displine == 416) { + /* End of VSYNC. */ + dev->displine = 0; + cga->cgastat &= ~8; + dev->dispon = 1; + } + } else { + if (dev->dispon) + cga->cgastat &= ~1; + + cga->vidtime += dev->dispontime; + + dev->linepos = 0; + if (dev->displine == 400) { + /* Hardcode 640x400 window size. */ + if (PLASMA_XSIZE != xsize || PLASMA_YSIZE != ysize) { + xsize = PLASMA_XSIZE; + ysize = PLASMA_YSIZE; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + + set_screen_size(xsize, ysize); + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_start(0, 0, cga->firstline, 0, (cga->lastline - cga->firstline), xsize, (cga->lastline - cga->firstline)); + frames++; + + /* Fixed 640x400 resolution. */ + video_res_x = PLASMA_XSIZE; + video_res_y = PLASMA_YSIZE; + + if (cga->cgamode & 0x02) { + if (cga->cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + } else + video_bpp = 0; + + cga->cgablink++; + } + } +} + + +static void +vid_poll(void *priv) +{ + vid_t *dev = (vid_t *)priv; + +INFO("CPQ: poll (mode=%i)\n", dev->mode); + switch(dev->mode) { + case 1: /* CGA */ + cga_poll(&dev->cga); + break; + + case 2: /* Plasma */ + vid_poll_plasma(dev); + break; + } +} + + +static void +vid_out(uint16_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + mda_t *mda = &dev->mda; + cga_t *cga = &dev->cga; + uint8_t old; + + DEBUG("CPQ: vid_out(%04x, %02x)\n", addr, val); +if(addr>=0x3d0)INFO("CPQ: vid_out(%04x, %02x)\n", addr, val); + + switch (addr) { + case 0x03b8: /* MDA control register */ + INFO("CPQ: MDA control %02x", val); + old = mda->ctrl; + mda->ctrl = val; + if (mda->ctrl ^ old) { + INFO(":"); + if (mda->ctrl & 0x01) INFO(" [HIRES]"); + if (mda->ctrl & 0x08) INFO(" [ENABL]"); + if (mda->ctrl & 0x20) INFO(" [BLINK]"); + } + INFO("\n"); + if ((mda->ctrl ^ old) & 3) + mda_recalctimings(mda); + return; + + case 0x03d1: /* CGA CRTC, value */ + case 0x03d3: + case 0x03d5: + case 0x03d7: + /* + * Register 0x12 controls the attribute + * mappings for the plasma screen. + */ + if (dev->cga.crtcreg == 0x12) { + dev->attrmap = val; + recalc_attrs(dev); + return; + } + cga_out(addr, val, &dev->cga); + recalc_timings(dev); + return; + + case 0x13c6: +INFO("CPQ: write(%04x, %02x)\n", addr, val); + dev->port_13c6 = val; + compaq_display_set(dev->port_13c6 ? 1 : 0); + return; + + case 0x23c6: +INFO("CPQ: write(%04x, %02x)\n", addr, val); + compaq_video_options_set(val); + if (dev->options != st_video_options) { + dev->options = st_video_options; + + /* Set the font used for the external display */ + dev->cga.fontbase = ((dev->options & 3) * 256); + + if (dev->options & 8) { + /* Disable internal CGA. */ + mem_map_disable(&dev->cga_mapping); + } else { + mem_map_enable(&dev->cga_mapping); + } + } + return; + } + + if (addr >= 0x03b0 && addr <= 0x03bb) + mda_out(addr, val, mda); + + if (addr >= 0x03d0 && addr <= 0x03df) + cga_out(addr, val, cga); +} + + +static uint8_t +vid_in(uint16_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + mda_t *mda = &dev->mda; + cga_t *cga = &dev->cga; + uint8_t ret = 0xff; + +INFO("CPQ: vid_in(%04x) = ", addr); + + switch (addr) { + case 0x03b8: +INFO("%02x\n", mda->ctrl); + return(mda->ctrl); + + case 0x03d1: /* CGA CRTC, value */ + case 0x03d3: + case 0x03d5: + case 0x03d7: + if (cga->crtcreg == 0x12) { + ret = dev->attrmap & 0x0f; + if (dev->mode == 2) + ret |= 0x30; /* Plasma / CRT */ +INFO("%02x\n", ret); + return(ret); + } + break; + + case 0x13c6: + ret = dev->port_13c6; + break; + + case 0x23c6: + ret = 0x00; + break; + } + + if (addr >= 0x03b0 && addr <= 0x03bb) + ret = mda_in(addr, mda); + + if (addr >= 0x03d0 && addr <= 0x03df) + ret = cga_in(addr, cga); + +INFO("%02x\n", ret); + return(ret); +} + + +static void +vid_write(uint32_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + dev->vram[addr & 0x7fff] = val; + + cycles -= 4; +} + + +static uint8_t +vid_read(uint32_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + uint8_t ret; + + ret = dev->vram[addr & 0x7fff]; + + cycles -= 4; + + return(ret); +} + + +static void +vid_close(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + if (dev->vram) + free(dev->vram); + + free(dev); +} + + +static void +speed_changed(void *priv) +{ + vid_t *dev = (vid_t *)priv; + +INFO("CPQ: speed_changed(mode=%i)\n", dev->mode); + mda_recalctimings(&dev->mda); + + cga_recalctimings(&dev->cga); + + recalc_timings(dev); +} + + +static void * +vid_init(const device_t *info, void *arg) +{ + vid_t *dev; + + dev = (vid_t *)mem_alloc(sizeof(vid_t)); + memset(dev, 0x00, sizeof(vid_t)); + dev->type = info->local; +INFO("CPQ: video_init(type=%i)\n", dev->type); + + dev->mode = 0; + dev->options = 0xff; + + /* Default attribute mapping is 4. */ + dev->attrmap = 4; + recalc_attrs(dev); + + /* 32K video RAM. */ + dev->vram = (uint8_t *)mem_alloc(32768); + + /* Initialize the MDA. */ + dev->mda.vram = dev->vram; + mda_init(&dev->mda); + io_sethandler(0x03b0, 0x000c, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + mem_map_add(&dev->mda_mapping, 0xb0000, 0x08000, + vid_read,NULL,NULL, vid_write,NULL,NULL, dev->vram, 0, dev); + + /* Initialize the CGA, start off in 80x25 text mode. */ + dev->cga.vram = dev->vram; + cga_init(&dev->cga); + dev->cga.cgastat = 0xf4; + io_sethandler(0x03d0, 0x000c, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + mem_map_add(&dev->cga_mapping, 0xb8000, 0x08000, + vid_read,NULL,NULL, vid_write,NULL,NULL, dev->vram, 0, dev); + mem_map_disable(&dev->cga_mapping); + + /* Respond to the Compaq ports. */ + if (dev->type == 1) { + io_sethandler(0x13c6, 1, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + io_sethandler(0x23c6, 1, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + } + + if (dev->mode != 0) + timer_add(vid_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + +#if 0 + /* + * Flag whether the card is behaving like a CGA or an MDA, + * so that DIP switches are reported correctly. + */ + if (dev->mode == 0) + video_inform(VID_TYPE_MDA, &cpq_timing); + else + video_inform(VID_TYPE_CGA, &cpq_timing); +#endif + + return(dev); +} + + +const device_t compaq_video_device = { + "Compaq VDU Controller", + DEVICE_ISA, + 0, + NULL, + vid_init, vid_close, NULL, + NULL, + speed_changed, + NULL, + NULL, + NULL +}; + +const device_t compaq_video_plasma_device = { + "Compaq VDU Plasma Controller", + DEVICE_ISA, + 1, + NULL, + vid_init, vid_close, NULL, + NULL, + speed_changed, + NULL, + NULL, + NULL +}; + + +void +compaq_video_options_set(uint8_t options) +{ + st_video_options = options; +} + + +void +compaq_display_set(uint8_t val) +{ + st_display_mode = val; +} diff --git a/src/machines/m_europc.c b/src/machines/m_europc.c index e79265f..f44c992 100644 --- a/src/machines/m_europc.c +++ b/src/machines/m_europc.c @@ -69,7 +69,7 @@ * FIXME: Find a new way to handle the switching of color/mono on * external cards. New video_get_type(int card) function? * - * Version: @(#)m_europc.c 1.0.19 2019/02/16 + * Version: @(#)m_europc.c 1.0.21 2019/04/11 * * Author: Fred N. van Kempen, * @@ -117,6 +117,7 @@ #include #include #include "../emu.h" +#include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" #include "../rom.h" @@ -164,9 +165,6 @@ typedef struct { } europc_t; -static europc_t europc; - - /* * This is called every second through the NVR/RTC hook. * @@ -365,7 +363,7 @@ rtc_reset(nvr_t *nvr) /* Execute a JIM control command. */ static void -jim_set(europc_t *sys, uint8_t reg, uint8_t val) +jim_set(europc_t *dev, uint8_t reg, uint8_t val) { switch(reg) { case 0: /* MISC control (WO) */ @@ -427,7 +425,7 @@ jim_set(europc_t *sys, uint8_t reg, uint8_t val) break; } - sys->regs[reg] = val; + dev->regs[reg] = val; } @@ -435,7 +433,7 @@ jim_set(europc_t *sys, uint8_t reg, uint8_t val) static void jim_write(uint16_t addr, uint8_t val, void *priv) { - europc_t *sys = (europc_t *)priv; + europc_t *dev = (europc_t *)priv; uint8_t b; DBGLOG(2, "EuroPC: jim_wr(%04x, %02x)\n", addr, val); @@ -449,29 +447,29 @@ jim_write(uint16_t addr, uint8_t val, void *priv) case 0x05: case 0x06: case 0x07: - jim_set(sys, (addr & 0x07), val); + jim_set(dev, (addr & 0x07), val); break; case 0x0a: /* M3002 RTC INDEX/DATA register */ - switch(sys->nvr_stat) { + switch(dev->nvr_stat) { case 0: /* save index */ - sys->nvr_addr = val & 0x0f; - sys->nvr_stat++; + dev->nvr_addr = val & 0x0f; + dev->nvr_stat++; break; case 1: /* save data HI nibble */ - b = sys->nvr.regs[sys->nvr_addr] & 0x0f; + b = dev->nvr.regs[dev->nvr_addr] & 0x0f; b |= (val << 4); - sys->nvr.regs[sys->nvr_addr] = b; - sys->nvr_stat++; + dev->nvr.regs[dev->nvr_addr] = b; + dev->nvr_stat++; nvr_dosave++; break; case 2: /* save data LO nibble */ - b = sys->nvr.regs[sys->nvr_addr] & 0xf0; + b = dev->nvr.regs[dev->nvr_addr] & 0xf0; b |= (val & 0x0f); - sys->nvr.regs[sys->nvr_addr] = b; - sys->nvr_stat = 0; + dev->nvr.regs[dev->nvr_addr] = b; + dev->nvr_stat = 0; nvr_dosave++; break; } @@ -488,7 +486,7 @@ jim_write(uint16_t addr, uint8_t val, void *priv) static uint8_t jim_read(uint16_t addr, void *priv) { - europc_t *sys = (europc_t *)priv; + europc_t *dev = (europc_t *)priv; uint8_t r = 0xff; switch (addr & 0x000f) { @@ -503,23 +501,23 @@ jim_read(uint16_t addr, void *priv) case 0x05: case 0x06: case 0x07: - r = sys->regs[addr & 0x07]; + r = dev->regs[addr & 0x07]; break; case 0x0a: /* M3002 RTC INDEX/DATA register */ - switch(sys->nvr_stat) { + switch(dev->nvr_stat) { case 0: r = 0x00; break; case 1: /* read data HI nibble */ - r = (sys->nvr.regs[sys->nvr_addr] >> 4); - sys->nvr_stat++; + r = (dev->nvr.regs[dev->nvr_addr] >> 4); + dev->nvr_stat++; break; case 2: /* read data LO nibble */ - r = (sys->nvr.regs[sys->nvr_addr] & 0x0f); - sys->nvr_stat = 0; + r = (dev->nvr.regs[dev->nvr_addr] & 0x0f); + dev->nvr_stat = 0; break; } break; @@ -535,15 +533,39 @@ jim_read(uint16_t addr, void *priv) } -/* Initialize the mainboard 'device' of the machine. */ +/* + * Initialize the mainboard 'device' of the machine. + * + * Its task is to allocate a clean machine data block, + * and then simply enable the mainboard "device" which + * allows it to reset (dev init) and configured by the + * user. + */ static void * -europc_boot(const device_t *info) +europc_init(const device_t *info, void *arg) { - europc_t *sys = &europc; + europc_t *dev; uint8_t b; - int vid; + int i; - DEBUG("EuroPC: booting mainboard..\n"); + /* Clear the machine state. */ + dev = (europc_t *)mem_alloc(sizeof(europc_t)); + memset(dev, 0x00, sizeof(europc_t)); + + /* Add the machine device. */ + device_add_ex(info, dev); + + /* Get configurable things. */ + i = machine_get_config_int("js9"); + dev->jim = (i == 1) ? 0x0350 : 0x0250; + + /* Set up and initialize the NVR. */ + dev->nvr.size = machine->nvrsz; + dev->nvr.irq = -1; + dev->nvr.reset = rtc_reset; + dev->nvr.start = rtc_start; + dev->nvr.tick = rtc_ticker; + nvr_init(&dev->nvr); /* * This is not quite correct, but it works. @@ -559,17 +581,17 @@ europc_boot(const device_t *info) } DEBUG("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n", - sys->nvr.regs[MRTC_CONF_A], sys->nvr.regs[MRTC_CONF_B], - sys->nvr.regs[MRTC_CONF_C], sys->nvr.regs[MRTC_CONF_D], - sys->nvr.regs[MRTC_CONF_E], - (sys->nvr.regs[MRTC_CHECK_LO]!=rtc_checksum(sys->nvr.regs))?"IN":""); + dev->nvr.regs[MRTC_CONF_A], dev->nvr.regs[MRTC_CONF_B], + dev->nvr.regs[MRTC_CONF_C], dev->nvr.regs[MRTC_CONF_D], + dev->nvr.regs[MRTC_CONF_E], + (dev->nvr.regs[MRTC_CHECK_LO]!=rtc_checksum(dev->nvr.regs))?"IN":""); /* * Now that we have initialized the NVR (either from file, * or by setting it to defaults) we can start overriding it * with values set by the user. */ - b = (sys->nvr.regs[MRTC_CONF_D] & ~0x17); + b = (dev->nvr.regs[MRTC_CONF_D] & ~0x17); if (video_card != VID_INTERNAL) { /* * OK, this is not exactly correct, either. @@ -594,8 +616,8 @@ europc_boot(const device_t *info) b |= 0x10; /* external video, special */ } } else { - vid = video_type(); - switch(vid) { + i = video_type(); + switch(i) { case VID_TYPE_MDA: /* Monochrome, MDA, Hercules */ b |= 0x03; /* external video, mono */ break; @@ -609,14 +631,14 @@ europc_boot(const device_t *info) break; default: - ERRLOG("EuroPC: unknown video type %d !\n", vid); + ERRLOG("EuroPC: unknown video type %i !\n", i); break; } } - sys->nvr.regs[MRTC_CONF_D] = b; + dev->nvr.regs[MRTC_CONF_D] = b; /* Update the memory size. */ - b = (sys->nvr.regs[MRTC_CONF_C] & 0xf3); + b = (dev->nvr.regs[MRTC_CONF_C] & 0xf3); switch(mem_size) { case 256: b |= 0x04; @@ -630,11 +652,11 @@ europc_boot(const device_t *info) b |= 0x00; break; } - sys->nvr.regs[MRTC_CONF_C] = b; + dev->nvr.regs[MRTC_CONF_C] = b; /* Update CPU speed. */ - b = (sys->nvr.regs[MRTC_CONF_D] & 0x3f); - switch(cpu) { + b = (dev->nvr.regs[MRTC_CONF_D] & 0x3f); + switch(cpu_type) { case 0: /* 8088, 4.77 MHz */ b |= 0x00; break; @@ -647,10 +669,10 @@ europc_boot(const device_t *info) b |= 0x80; break; } - sys->nvr.regs[MRTC_CONF_D] = b; + dev->nvr.regs[MRTC_CONF_D] = b; /* Set up game port. */ - b = (sys->nvr.regs[MRTC_CONF_C] & 0xfc); + b = (dev->nvr.regs[MRTC_CONF_C] & 0xfc); if (mouse_type == MOUSE_INTERNAL) { /* Enable the Logitech Bus Mouse device. */ device_add(&mouse_logibus_internal_device); @@ -660,10 +682,10 @@ europc_boot(const device_t *info) } else if (game_enabled) { b |= 0x02; /* enable port as joysticks */ } - sys->nvr.regs[MRTC_CONF_C] = b; + dev->nvr.regs[MRTC_CONF_C] = b; /* Set up hard disks. */ - b = sys->nvr.regs[MRTC_CONF_B] & 0x84; + b = dev->nvr.regs[MRTC_CONF_B] & 0x84; if (hdc_type != HDC_NONE) b |= 0x20; /* HD20 #1 */ @@ -689,12 +711,18 @@ europc_boot(const device_t *info) } else ERRLOG("EuroPC: unsupported HD type for floppy drive 1\n"); } - sys->nvr.regs[MRTC_CONF_B] = b; + dev->nvr.regs[MRTC_CONF_B] = b; /* Validate the NVR checksum and save. */ - sys->nvr.regs[MRTC_CHECK_LO] = rtc_checksum(sys->nvr.regs); + dev->nvr.regs[MRTC_CHECK_LO] = rtc_checksum(dev->nvr.regs); nvr_dosave++; + machine_common_init(); + + nmi_init(); + + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + /* * Allocate the system's I/O handlers. * @@ -703,14 +731,14 @@ europc_boot(const device_t *info) * (JS9) can be used to "move" it to 0x0350, to get it out of * the way of other cards that need this range. */ - io_sethandler(sys->jim, 16, - jim_read,NULL,NULL, jim_write,NULL,NULL, sys); + io_sethandler(dev->jim, 16, + jim_read,NULL,NULL, jim_write,NULL,NULL, dev); /* Only after JIM has been initialized. */ - (void)device_add(&keyboard_xt_device); + device_add(&keyboard_xt_device); /* Enable and set up the FDC. */ - (void)device_add(&fdc_xt_device); + device_add(&fdc_xt_device); /* * Set up and enable the HD20 disk controller. @@ -720,19 +748,22 @@ europc_boot(const device_t *info) if (hdc_type == HDC_INTERNAL) (void)device_add(&xta_hd20_device); - return(sys); + return(dev); } static void europc_close(void *priv) { - nvr_t *nvr = &europc.nvr; + europc_t *dev = (europc_t *)priv; + nvr_t *nvr = &dev->nvr; if (nvr->fn != NULL) { free((wchar_t *)nvr->fn); nvr->fn = NULL; } + + free(dev); } @@ -747,59 +778,37 @@ static const device_config_t europc_config[] = { "Enabled (350h)", 1 }, { - "" + NULL } }, }, { - "", "", -1 + NULL } }; -const device_t europc_device = { - "EuroPC System Board", - 0, - 0, - europc_boot, europc_close, NULL, - NULL, NULL, NULL, NULL, - europc_config +static const CPU cpus_europc[] = { + { "8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1 }, + { "8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1 }, + { "8088/9.54", CPU_8088, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { NULL } }; +static const machine_t europc_info = { + MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, + 0, + 512, 640, 128, 16, 0, + {{"Siemens",cpus_europc}} +}; -/* - * This function sets up the Scheider EuroPC machine. - * - * Its task is to allocate a clean machine data block, - * and then simply enable the mainboard "device" which - * allows it to reset (dev init) and configured by the - * user. - */ -void -m_europc_init(const machine_t *model, void *arg) -{ - machine_common_init(model, arg); - - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - - nmi_init(); - - /* Clear the machine state. */ - memset(&europc, 0x00, sizeof(europc_t)); - europc.jim = 0x0250; - - /* This is machine specific. */ - europc.nvr.size = model->nvrsz; - europc.nvr.irq = -1; - - /* Set up any local handlers here. */ - europc.nvr.reset = rtc_reset; - europc.nvr.start = rtc_start; - europc.nvr.tick = rtc_ticker; - - /* Initialize the actual NVR. */ - nvr_init(&europc.nvr); - - /* Enable and set up the mainboard device. */ - device_add(&europc_device); -} +const device_t m_europc = { + "Schneider EuroPC", + DEVICE_ROOT, + 0, + L"schneider/europc", + europc_init, europc_close, NULL, + NULL, NULL, NULL, + &europc_info, + europc_config +}; diff --git a/src/machines/m_headland.c b/src/machines/m_headland.c new file mode 100644 index 0000000..5170c33 --- /dev/null +++ b/src/machines/m_headland.c @@ -0,0 +1,181 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the HEADLAND AT286 chipset. + * + * **NOTE** We need 'device continuation' implemented for this machine, + * so we can add configuration dialog for the onboard video + * controller for the AMA machine. + * + * Version: @(#)m_headland.c 1.0.12 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Original by GreatPsycho for PCem. + * Miran Grca, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017,2018 Miran Grca. + * Copyright 2017,2018 GreatPsycho. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../cpu/x86.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/headland.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" +#include "../devices/video/video.h" +#include "machine.h" + + +typedef struct { + int type; + + rom_t vid_bios; +} headland_t; + + +static void +headland_close(void *priv) +{ + headland_t *dev = (headland_t *)priv; + + free(dev); +} + + +static void * +headland_init(const device_t *info, void *arg) +{ + romdef_t *roms = (romdef_t *)arg; + headland_t *dev; + + dev = (headland_t *)mem_alloc(sizeof(headland_t)); + memset(dev, 0x00, sizeof(headland_t)); + dev->type = info->local; + + /* Add machine device to system. */ + device_add_ex(info, dev); + + m_at_common_init(); + + device_add(&keyboard_at_ami_device); + + device_add(&fdc_at_device); + + device_add(&ide_isa_device); + + switch(dev->type) { + case 0: /* Trigem 286M */ + device_add(&headland_device); + break; + + case 11: /* Headland 386SX */ + device_add(&headland_386_device); + break; + + case 12: /* Arche Technologies AMA-932J-25 */ + device_add(&headland_386_device); + if (video_card == VID_INTERNAL) { + /* Load the BIOS. */ + rom_init(&dev->vid_bios, roms->vidfn, + 0xc0000, roms->vidsz, roms->vidsz - 1, 0, 0); + + /* Initialize the on-board controller. */ + device_add(&oti067_onboard_device); + } + break; + } + + return(dev); +} + + +static const machine_t trigem_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 512, 8192, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_tg286m = { + "Trigem 286M", + DEVICE_ROOT, + 1, + L"trigem/tg286m", + headland_init, headland_close, NULL, + NULL, NULL, NULL, + &trigem_info, + NULL +}; + + +static const machine_t ami_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 512, 16384, 128, 128, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_headland_386_ami = { + "AMI 386SX (Headland)", + DEVICE_ROOT, + 11, + L"headland/386sx/ami", + headland_init, headland_close, NULL, + NULL, NULL, NULL, + &ami_info, + NULL +}; + + +static const machine_t ama_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, + 0, + 512, 8192, 128, 128, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_ama932j = { + "Arche Technologies AMA-932J-25", + DEVICE_ROOT, + 12, + L"arche/ama932j", + headland_init, headland_close, NULL, + NULL, NULL, NULL, + &ama_info, + NULL +}; diff --git a/src/machines/m_intel4x0.c b/src/machines/m_intel4x0.c new file mode 100644 index 0000000..ebfcbb9 --- /dev/null +++ b/src/machines/m_intel4x0.c @@ -0,0 +1,298 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Intel 430/440-based machines. + * + * Version: @(#)m_intel4x0.c 1.0.6 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/intel4x0.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/system/intel.h" +#include "../devices/system/intel_flash.h" +#include "../devices/system/intel_sio.h" +#include "../devices/system/intel_piix.h" +#include "../devices/input/keyboard.h" +#include "../devices/sio/sio.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "../devices/video/video.h" +#include "machine.h" + + +static void +premiere_init(int nx) +{ + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + if (nx) + device_add(&i430nx_device); + else + device_add(&i430lx_device); + + device_add(&sio_device); + device_add(&intel_batman_device); + device_add(&intel_flash_bxt_ami_device); + + m_at_common_init(); + + device_add(&keyboard_ps2_ami_pci_device); + + device_add(&ide_pci_2ch_device); + + device_add(&fdc37c665_device); +} + + +static void * +common_init(const device_t *info, void *arg) +{ + static video_timings_t endeavor_timing = {VID_BUS,3,2,4,25,25,40}; + + /* Allocate machine device to system. */ + device_add_ex(info, arg); + + switch(info->local) { + /* Revenge: Premiere/PCI I/430LX/AMI/SMC FDC37C665 */ + case 0: + premiere_init(0); + break; + + /* Plato: Premiere/PCI II/430NX/AMI/SMC FDC37C665 */ + case 1: + premiere_init(1); + break; + + /* Endeavor: Intel Advanced_EV/430FX/AMI/NS PC87306 */ + case 2: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&intel_flash_bxt_ami_device); + m_at_common_init(); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87306_device); + + if (video_card == VID_INTERNAL) { + device_add(&s3_phoenix_trio64_onboard_pci_device); + video_inform(VID_TYPE_SPEC, &endeavor_timing); + } + break; + + /* Zappa: Intel Advanced_ZP/430FX/AMI/NS PC87306 */ + case 3: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&intel_flash_bxt_ami_device); + m_at_common_init(); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87306_device); + break; + + /* Thor: Intel Advanced_ATX/430FX/AMI/NS PC87306 */ + /* MRthor: Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ + case 4: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&intel_flash_bxt_ami_device); + m_at_common_init(); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87306_device); + break; + } + + return(arg); +} + + +static const machine_t revenge_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 2, 128, 2, 128, -1, + {{"Intel",cpus_Pentium5V}} +}; + +const device_t m_batman = { + "Intel Batman", + DEVICE_ROOT, + 0, + L"intel/revenge", + common_init, NULL, NULL, + NULL, NULL, NULL, + &revenge_info, + NULL +}; + + +static const machine_t plato_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 2, 128, 2, 128, -1, + {{"Intel",cpus_PentiumS5},{"IDT",cpus_WinChip},CPU_AMD_K5} +}; + +const device_t m_plato = { + "Intel Plato", + DEVICE_ROOT, + 1, + L"intel/plato", + common_init, NULL, NULL, + NULL, NULL, NULL, + &plato_info, + NULL +}; + + +static const machine_t endeavor_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_PentiumS5},{"IDT",cpus_WinChip},CPU_AMD_K56} +}; + +const device_t m_endeavor = { + "Intel Endeavor", + DEVICE_ROOT, + 2, + L"intel/endeavor", + common_init, NULL, NULL, + NULL, NULL, NULL, + &endeavor_info, + NULL /* &s3_phoenix_trio64_onboard_pci_device */ +}; + + +static const machine_t zappa_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_PentiumS5},{"IDT",cpus_WinChip},CPU_AMD_K5} +}; + +const device_t m_zappa = { + "Intel Zappa", + DEVICE_ROOT, + 3, + L"intel/zappa", + common_init, NULL, NULL, + NULL, NULL, NULL, + &zappa_info, + NULL +}; + + +static const machine_t thor_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_thor = { + "Intel Thor", + DEVICE_ROOT, + 4, + L"intel/thor", + common_init, NULL, NULL, + NULL, NULL, NULL, + &thor_info, + NULL +}; + + +static const machine_t thor_mr_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_thor_mr = { + "Intel Thor (MR)", + DEVICE_ROOT, + 4, + L"intel/thor_mr", + common_init, NULL, NULL, + NULL, NULL, NULL, + &thor_mr_info, + NULL +}; diff --git a/src/machines/m_laserxt.c b/src/machines/m_laserxt.c new file mode 100644 index 0000000..99b8dfb --- /dev/null +++ b/src/machines/m_laserxt.c @@ -0,0 +1,281 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of the Laser XT series of machines. + * + * Version: @(#)m_laserxt.c 1.0.11 2019/04/20 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/system/nmi.h" +#include "../devices/system/pit.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "machine.h" + + +typedef struct { + int type; + + int ems_baseaddr_index; + int ems_page[4]; + int ems_control[4]; + mem_map_t ems_mapping[4]; +} laser_t; + + +static uint32_t +ems_addr(laser_t *dev, uint32_t addr) +{ + if (dev->ems_page[(addr >> 14) & 3] & 0x80) { + addr = (!dev->type ? 0x70000 + (((mem_size + 64) & 255) << 10) + : 0x30000 + (((mem_size + 320) & 511) << 10)) + ((dev->ems_page[(addr >> 14) & 3] & 0x0f) << 14) + ((dev->ems_page[(addr >> 14) & 3] & 0x40) << 12) + (addr & 0x3fff); + } + + return addr; +} + + +static void +do_write(uint16_t port, uint8_t val, void *priv) +{ + laser_t *dev = (laser_t *)priv; + uint32_t paddr, vaddr; + int i; + + switch (port) { + case 0x0208: + case 0x4208: + case 0x8208: + case 0xc208: + dev->ems_page[port >> 14] = val; + paddr = 0xc0000 + (port & 0xC000) + (((dev->ems_baseaddr_index + (4 - (port >> 14))) & 0x0c) << 14); + if (val & 0x80) { + mem_map_enable(&dev->ems_mapping[port >> 14]); + vaddr = ems_addr(dev, paddr); + mem_map_set_exec(&dev->ems_mapping[port >> 14], ram + vaddr); + } else { + mem_map_disable(&dev->ems_mapping[port >> 14]); + } + flushmmucache(); + break; + + case 0x0209: + case 0x4209: + case 0x8209: + case 0xc209: + dev->ems_control[port >> 14] = val; + dev->ems_baseaddr_index = 0; + for (i = 0; i < 4; i++) + dev->ems_baseaddr_index |= (dev->ems_control[i] & 0x80) >> (7 - i); + + mem_map_set_addr(&dev->ems_mapping[0], 0xc0000 + (((dev->ems_baseaddr_index + 4) & 0x0c) << 14), 0x4000); + mem_map_set_addr(&dev->ems_mapping[1], 0xc4000 + (((dev->ems_baseaddr_index + 3) & 0x0c) << 14), 0x4000); + mem_map_set_addr(&dev->ems_mapping[2], 0xc8000 + (((dev->ems_baseaddr_index + 2) & 0x0c) << 14), 0x4000); + mem_map_set_addr(&dev->ems_mapping[3], 0xcc000 + (((dev->ems_baseaddr_index + 1) & 0x0c) << 14), 0x4000); + flushmmucache(); + break; + } +} + + +static uint8_t +do_read(uint16_t port, void *priv) +{ + laser_t *dev = (laser_t *)priv; + + switch (port) { + case 0x0208: + case 0x4208: + case 0x8208: + case 0xc208: + return dev->ems_page[port >> 14]; + + case 0x0209: + case 0x4209: + case 0x8209: + case 0xc209: + return dev->ems_control[port >> 14]; + } + + return 0xff; +} + + +static void +ems_write(uint32_t addr, uint8_t val, void *priv) +{ + laser_t *dev = (laser_t *)priv; + + addr = ems_addr(dev, addr); + + if (addr < ((uint32_t)mem_size << 10)) + ram[addr] = val; +} + + +static uint8_t +ems_read(uint32_t addr, void *priv) +{ + laser_t *dev = (laser_t *)priv; + uint8_t val = 0xff; + + addr = ems_addr(dev, addr); + + if (addr < ((uint32_t)mem_size << 10)) + val = ram[addr]; + + return val; +} + + +static void * +laser_init(const device_t *info, void *arg) +{ + laser_t *dev; + int i; + + dev = (laser_t *)mem_alloc(sizeof(laser_t)); + memset(dev, 0x00, sizeof(laser_t)); + dev->type = info->local; + + /* Add machine device to system. */ + device_add_ex(info, dev); + + machine_common_init(); + + nmi_init(); + + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + + switch(dev->type) { + case 0: /* Laser XT */ + device_add(&keyboard_xt_device); + break; + + case 3: /* Laser XT3 */ + device_add(&keyboard_laserxt3_device); + break; + } + + device_add(&fdc_xt_device); + + if (mem_size > 640) { + io_sethandler(0x0208, 2, + do_read,NULL,NULL, do_write,NULL,NULL, dev); + io_sethandler(0x4208, 2, + do_read,NULL,NULL, do_write,NULL,NULL, dev); + io_sethandler(0x8208, 2, + do_read,NULL,NULL, do_write,NULL,NULL, dev); + io_sethandler(0xc208, 2, + do_read,NULL,NULL, do_write,NULL,NULL, dev); + + mem_map_set_addr(&ram_low_mapping, 0, + !dev->type ? 0x70000 + (((mem_size + 64) & 255) << 10) + : 0x30000 + (((mem_size + 320) & 511) << 10)); + } + + for (i = 0; i < 4; i++) { + dev->ems_page[i] = 0x7f; + dev->ems_control[i] = (i == 3) ? 0x00 : 0x80; + + mem_map_add(&dev->ems_mapping[i], 0xe0000 + (i << 14), 0x4000, + ems_read,NULL,NULL, ems_write,NULL,NULL, + ram + 0xa0000 + (i << 14), 0, dev); + + mem_map_disable(&dev->ems_mapping[i]); + } + + mem_set_mem_state(0x0c0000, 0x40000, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + return(dev); +} + + +static void +laser_close(void *priv) +{ + laser_t *dev = (laser_t *)priv; + + free(dev); +} + + +static const machine_t lxt_info = { + MACHINE_ISA, + 0, + 256, 640, 128, 0, -1, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_laser_xt = { + "Vtech Laser XT", + DEVICE_ROOT, + 0, + L"vtech/ltxt", + laser_init, laser_close, NULL, + NULL, NULL, NULL, + &lxt_info, + NULL +}; + + +static const machine_t lxt3_info = { + MACHINE_ISA, + 0, + 256, 640, 256, 0, -1, + {{"Intel",cpus_8086}} +}; + +const device_t m_laser_xt3 = { + "Vtech Laser XT/3", + DEVICE_ROOT, + 3, + L"vtech/lxt3", + laser_init, laser_close, NULL, + NULL, NULL, NULL, + &lxt3_info, + NULL +}; diff --git a/src/machines/m_misc.c b/src/machines/m_misc.c new file mode 100644 index 0000000..630f79c --- /dev/null +++ b/src/machines/m_misc.c @@ -0,0 +1,315 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of various systems and mainboards. + * + * Version: @(#)m_misc.c 1.0.1 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/intel4x0.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/system/intel.h" +#include "../devices/system/intel_flash.h" +#include "../devices/system/intel_sio.h" +#include "../devices/system/intel_piix.h" +#include "../devices/input/keyboard.h" +#include "../devices/sio/sio.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "../devices/video/video.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Allocate machine device to system. */ + device_add_ex(info, arg); + + switch(info->local) { + /* 430VX: Award 430VX PCI/430VX/Award/UMC UM8669F*/ + case 0: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&um8669f_device); + device_add(&keyboard_ps2_pci_device); + break; + + /* MB500N: PC Partner MB500N/430FX/Award/SMC FDC37C665 */ + case 10: + 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); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&fdc37c665_device); + device_add(&keyboard_ps2_pci_device); + break; + + /* President: Award 430FX PCI/430FX/Award/Unknown SIO */ + case 11: + 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); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&w83877f_president_device); + device_add(&keyboard_ps2_pci_device); + break; + + /* P55VA: Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ + case 12: + 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); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&fdc37c932fr_device); + device_add(&keyboard_ps2_pci_device); + break; + + /* J656VXD: Jetway J656VXD/430VX/Award/SMC FDC37C669*/ + case 13: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&fdc37c669_device); + device_add(&keyboard_ps2_pci_device); + break; + + /* P55T2S: Supermicro P/I-P55T2S/430HX/AMI/NS PC87306 */ + case 14: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + memregs_init(); + powermate_memregs_init(); + + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + + m_at_common_init(); + + device_add(&pc87306_device); + device_add(&keyboard_ps2_ami_pci_device); + break; + } + + return(arg); +} + + +static const machine_t aw430vx_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_aw430vx = { + "Award 430VX", + DEVICE_ROOT, + 0, + L"generic/430vx/award", + common_init, NULL, NULL, + NULL, NULL, NULL, + &aw430vx_info, + NULL +}; + + +static const machine_t mb500n_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_PentiumS5},{"IDT",cpus_WinChip},CPU_AMD_K5} +}; + +const device_t m_mb500n = { + "MB500N", + DEVICE_ROOT, + 10, + L"pcpartner/mb500n", + common_init, NULL, NULL, + NULL, NULL, NULL, + &mb500n_info, + NULL +}; + + +static const machine_t president_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_PentiumS5},{"IDT",cpus_WinChip},CPU_AMD_K5} +}; + +const device_t m_president = { + "President", + DEVICE_ROOT, + 11, + L"president/president", + common_init, NULL, NULL, + NULL, NULL, NULL, + &president_info, + NULL +}; + + +static const machine_t epox_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_p55va = { + "Epox P55VA", + DEVICE_ROOT, + 12, + L"epox/p55va", + common_init, NULL, NULL, + NULL, NULL, NULL, + &epox_info, + NULL +}; + + +static const machine_t jetway_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_j656vxd = { + "Jetway 656VXD", + DEVICE_ROOT, + 13, + L"jetway/j656vxd", + common_init, NULL, NULL, + NULL, NULL, NULL, + &jetway_info, + NULL +}; + + +static const machine_t t2s_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 768, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_p55t2s = { + "ASUS P55T2S", + DEVICE_ROOT, + 14, + L"supermicro/p55t2s", + common_init, NULL, NULL, + NULL, NULL, NULL, + &t2s_info, + NULL +}; diff --git a/src/machines/m_neat.c b/src/machines/m_neat.c new file mode 100644 index 0000000..c11d58f --- /dev/null +++ b/src/machines/m_neat.c @@ -0,0 +1,123 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of C&T CS8121 ("NEAT") based machines. + * + * Version: @(#)m_neat.c 1.0.5 2019/04/08 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018,2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../device.h" +#include "../devices/chipsets/neat.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Add machine device to system. */ + device_add_ex(info, arg); + + device_add(&neat_device); + + switch(info->local) { + case 1: /* Generic AT with AMI BIOS and KBC */ + m_at_common_init(); + device_add(&keyboard_at_ami_device); + break; + + case 2: /* DTK-386 using NEAT */ + m_at_init(); + break; + } + + device_add(&fdc_at_device); + + return(arg); +} + + +static const machine_t ami_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 512, 8192, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_neat_ami = { + "AMI 286 (NEAT)", + DEVICE_ROOT, + 1, + L"generic/at/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &ami_info, + NULL +}; + + +static const machine_t dtk_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 512, 8192, 128, 128, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_neat_dtk = { + "DTK-386 (NEAT)", + DEVICE_ROOT, + 2, + L"dtk/386", + common_init, NULL, NULL, + NULL, NULL, NULL, + &dtk_info, + NULL +}; diff --git a/src/machines/m_olim24.c b/src/machines/m_olim24.c new file mode 100644 index 0000000..6cb238e --- /dev/null +++ b/src/machines/m_olim24.c @@ -0,0 +1,770 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of the Olivetti M21, M24 and M240 machines. + * + * The base machine is the M24, a desktop system. The portable + * version of it was the M21, which is virtually the same, but + * has an onboard LCD instead of a CRT. An upgraded machine + * was released as the M240, with upgraded BIOS, default 640KB + * of RAM, high-density diskette drives, etc. + * + * **NOTE** This emulation is incomplete. Several of the DIP switches + * are not (properly) implemented. + * + * **TODO** The RTC clock is very limited, and does not store any 'year' + * data at all, so there seems to not be a way to properly do + * that.. The chip's interrupt pin is not connected. + * + * Version: @(#)m_olim24.c 1.0.17 2019/04/21 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include +#define dbglog kbd_log +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../timer.h" +#include "../device.h" +#include "../nvr.h" +#include "../devices/system/pic.h" +#include "../devices/system/pit.h" +#include "../devices/system/ppi.h" +#include "../devices/system/nmi.h" +#include "../devices/input/keyboard.h" +#include "../devices/input/mouse.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/sound/sound.h" +#include "../devices/sound/snd_speaker.h" +#include "machine.h" +#include "m_olim24.h" + + +/* MM58174AN registers. */ +enum RTC_REGS { + RTC_TEST = 0, /* TEST register */ + RTC_SECOND0, /* BCD */ + RTC_SECOND1, + RTC_SECOND10, + RTC_MINUTE1, /* BCD */ + RTC_MINUTE10, + RTC_HOUR1, /* BCD */ + RTC_HOUR10, + RTC_DAY1, /* BCD, 1-base */ + RTC_DAY10, + RTC_WEEKDAY, /* BCD, 1-base */ + RTC_MONTH1, /* BCD, 1-base */ + RTC_MONTH10, + RTC_YEAR, + RTC_RESET, /* RESET register */ + RTC_INTR /* Interrupts register */ +}; + + +/* Keyboard status flags. */ +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_LOCK 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 + + +typedef struct { + /* General. */ + int type; + + /* NVR/RTC stuff. */ + nvr_t nvr; + + /* Keyboard stuff. */ + int wantirq; + uint8_t command; + uint8_t status; + uint8_t out; + uint8_t output_port; + int param, + param_total; + uint8_t params[16]; + uint8_t scan[7]; + + /* Mouse stuff. */ + int mouse_mode; + int x, y, b; +} olim24_t; + + +extern const device_t st506_xt_olim240_hdc_device; + + +static uint8_t key_queue[16]; +static int key_queue_start = 0, + key_queue_end = 0; + + +static void +kbd_poll(void *priv) +{ + olim24_t *dev = (olim24_t *)priv; + + keyboard_delay += (1000LL * TIMER_USEC); + if (dev->wantirq) { + dev->wantirq = 0; + picint(1 << 1); + } + + if (!(dev->status & STAT_OFULL) && key_queue_start != key_queue_end) { + dev->out = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + dev->status |= STAT_OFULL; + dev->status &= ~STAT_IFULL; + dev->wantirq = 1; + } +} + + +static void +kbd_adddata(uint16_t val) +{ + key_queue[key_queue_end] = (uint8_t)(val&0xff); + key_queue_end = (key_queue_end + 1) & 0xf; +} + + +static void +kbd_adddata_ex(uint16_t val) +{ + kbd_adddata_process(val, kbd_adddata); +} + + +static void +kbd_write(uint16_t port, uint8_t val, void *priv) +{ + olim24_t *dev = (olim24_t *)priv; + + DBGLOG(2, "M24kbd: write(%04x,%02x)\n", port, val); + + switch (port) { + case 0x60: + if (dev->param != dev->param_total) { + dev->params[dev->param++] = val; + if (dev->param == dev->param_total) { + switch (dev->command) { + case 0x11: + dev->mouse_mode = 0; + dev->scan[0] = dev->params[0]; + dev->scan[1] = dev->params[1]; + dev->scan[2] = dev->params[2]; + dev->scan[3] = dev->params[3]; + dev->scan[4] = dev->params[4]; + dev->scan[5] = dev->params[5]; + dev->scan[6] = dev->params[6]; + break; + + case 0x12: + dev->mouse_mode = 1; + dev->scan[0] = dev->params[0]; + dev->scan[1] = dev->params[1]; + dev->scan[2] = dev->params[2]; + break; + + default: + DEBUG("M24: bad keyboard command complete %02X\n", dev->command); + break; + } + } + } else { + dev->command = val; + switch (val) { + case 0x01: /*Self-test*/ + break; + + case 0x05: /*Read ID*/ + kbd_adddata(0x00); + break; + + case 0x11: + dev->param = 0; + dev->param_total = 9; + break; + + case 0x12: + dev->param = 0; + dev->param_total = 4; + break; + + default: + ERRLOG("M24: bad keyboard command %02X\n", val); + break; + } + } + break; + + case 0x61: + ppi.pb = val; + + timer_process(); + timer_update_outstanding(); + + speaker_update(); + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) + speaker_was_enable = 1; + pit_set_gate(&pit, 2, val & 1); + break; + } +} + + +static uint8_t +kbd_read(uint16_t port, void *priv) +{ + olim24_t *dev = (olim24_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x60: + ret = dev->out; + if (key_queue_start == key_queue_end) { + dev->status &= ~STAT_OFULL; + dev->wantirq = 0; + } else { + dev->out = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + dev->status |= STAT_OFULL; + dev->status &= ~STAT_IFULL; + dev->wantirq = 1; + } + break; + + case 0x61: + ret = ppi.pb; + break; + + case 0x64: + ret = dev->status; + dev->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT); + break; + + default: + ERRLOG("\nBad M24 keyboard read %04X\n", port); + break; + } + + return(ret); +} + + +static int +mse_poll(int x, int y, int z, int b, void *priv) +{ + olim24_t *dev = (olim24_t *)priv; + + dev->x += x; + dev->y += y; + + if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); + + if ((b & 1) && !(dev->b & 1)) + kbd_adddata(dev->scan[0]); + if (!(b & 1) && (dev->b & 1)) + kbd_adddata(dev->scan[0] | 0x80); + dev->b = (dev->b & ~1) | (b & 1); + + if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); + + if ((b & 2) && !(dev->b & 2)) + kbd_adddata(dev->scan[2]); + if (!(b & 2) && (dev->b & 2)) + kbd_adddata(dev->scan[2] | 0x80); + dev->b = (dev->b & ~2) | (b & 2); + + if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); + + if ((b & 4) && !(dev->b & 4)) + kbd_adddata(dev->scan[1]); + if (!(b & 4) && (dev->b & 4)) + kbd_adddata(dev->scan[1] | 0x80); + dev->b = (dev->b & ~4) | (b & 4); + + if (dev->mouse_mode) { + if (((key_queue_end - key_queue_start) & 0xf) > 12) + return(0); + + if (!dev->x && !dev->y) + return(0); + + dev->y = -dev->y; + + if (dev->x < -127) dev->x = -127; + if (dev->x > 127) dev->x = 127; + if (dev->x < -127) dev->x = 0x80 | ((-dev->x) & 0x7f); + + if (dev->y < -127) dev->y = -127; + if (dev->y > 127) dev->y = 127; + if (dev->y < -127) dev->y = 0x80 | ((-dev->y) & 0x7f); + + kbd_adddata(0xfe); + kbd_adddata(dev->x); + kbd_adddata(dev->y); + + dev->x = dev->y = 0; + } else { + while (dev->x < -4) { + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return(0); + dev->x += 4; + kbd_adddata(dev->scan[3]); + } + while (dev->x > 4) { + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return(0); + dev->x -= 4; + kbd_adddata(dev->scan[4]); + } + while (dev->y < -4) { + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return(0); + dev->y += 4; + kbd_adddata(dev->scan[5]); + } + while (dev->y > 4) { + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return(0); + dev->y -= 4; + kbd_adddata(dev->scan[6]); + } + } + + return(1); +} + + +/* Set the current NVR time. */ +#define set_nibbles(a, v) regs[(a##10)] = ((v)/10) ; regs[(a##1)] = ((v)%10) +static void +rtc_time_set(uint8_t *regs, struct tm *tm) +{ + set_nibbles(RTC_SECOND, tm->tm_sec); + set_nibbles(RTC_MINUTE, tm->tm_min); + set_nibbles(RTC_HOUR, tm->tm_hour); + regs[RTC_WEEKDAY] = tm->tm_wday; + set_nibbles(RTC_DAY, tm->tm_mday); + set_nibbles(RTC_MONTH, (tm->tm_mon + 1)); + regs[RTC_YEAR] = ((tm->tm_year - 84) % 4); +} + + +/* Get the current NVR time. */ +#define get_nibbles(a) ((regs[(a##10)]*10)+regs[(a##1)]) +static void +rtc_time_get(uint8_t *regs, struct tm *tm) +{ + tm->tm_sec = get_nibbles(RTC_SECOND); + tm->tm_min = get_nibbles(RTC_MINUTE); + tm->tm_hour = get_nibbles(RTC_HOUR); + tm->tm_wday = regs[RTC_WEEKDAY]; + tm->tm_mday = get_nibbles(RTC_DAY); + tm->tm_mon = (get_nibbles(RTC_MONTH) - 1); + tm->tm_year = (regs[RTC_YEAR] + 1984); +} + + +/* Bump a dual-4bit-register. */ +static int +rtc_bump(uint8_t *regs, int base, int min, int max) +{ + int k; + + k = (regs[base + 1] * 10) + regs[base]; + if (++k >= (max + min)) { + /* Rollover, reset to 'min' and return. */ + regs[base] = min; + regs[base + 1] = 0; + return(1); + } + + /* No rollover, save the bumped value. */ + regs[base] = (k % 10); + regs[base + 1] = (k / 10); + + return(0); +} + + +/* + * This is called every second through the NVR/RTC hook. + * + * We fake a 'running' RTC by updating its registers on + * each passing second. Not exactly accurate, but good + * enough. + */ +static void +rtc_ticker(nvr_t *nvr) +{ + uint8_t *regs = nvr->regs; + int mon, yr, days; + + /* Only if RTC is running.. */ + if (! (regs[RTC_RESET] & 0x01)) return; + + if (rtc_bump(regs, RTC_SECOND1, 0, 60)) { + if (rtc_bump(regs, RTC_MINUTE1, 0, 60)) { + if (rtc_bump(regs, RTC_HOUR1, 0, 24)) { + mon = get_nibbles(RTC_MONTH); + yr = 1985 + regs[RTC_YEAR]; + days = nvr_get_days(mon, yr); + if (rtc_bump(regs, RTC_DAY1, 1, days)) { + if (rtc_bump(regs, RTC_MONTH1, 1, 12)) + regs[RTC_YEAR]++; + } + } + } + } +} + + +static void +rtc_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (time_sync != TIME_SYNC_DISABLED) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + rtc_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + rtc_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + + /* Start the RTC. */ + nvr->regs[RTC_RESET] |= 0x01; +} + + +/* Reset the machine's NVR to a sane state. */ +static void +rtc_reset(nvr_t *nvr) +{ + /* Initialize the RTC to a known state. */ + memset(nvr->regs, 0x00, sizeof(nvr->regs)); + + nvr->regs[RTC_WEEKDAY] = 0x01; + nvr->regs[RTC_DAY1] = 0x01; + nvr->regs[RTC_MONTH1] = 0x01; +} + + +/* Write to one of the RTC registers. */ +static void +rtc_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t *regs = nvr->regs; + + DBGLOG(2, "M24: rtc_wr(%04x, %02x)\n", addr, val); + + switch (addr & 0x000f) { + case RTC_TEST: /* not implemented */ + break; + + case RTC_MINUTE1: + case RTC_MINUTE10: + case RTC_HOUR1: + case RTC_HOUR10: + case RTC_DAY1: + case RTC_DAY10: + case RTC_WEEKDAY: + case RTC_MONTH1: + case RTC_MONTH10: + case RTC_YEAR: + regs[addr & 0x000f] = (val & 0x0f); + nvr_dosave = 1; + break; + + case RTC_RESET: + regs[addr & 0x000f] = (val & 0x0f); + nvr_dosave = 1; + break; + + case RTC_INTR: + regs[addr & 0x000f] = (val & 0x0f); + nvr_dosave = 1; + break; + } +} + + +/* Read from one of the RTC registers. */ +static uint8_t +rtc_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t *regs = nvr->regs; + uint8_t r = 0xff; + + switch (addr & 0x000f) { + case RTC_SECOND0: + r = regs[addr & 0x000f]; + break; + + case RTC_SECOND1: + case RTC_SECOND10: + case RTC_MINUTE1: + case RTC_MINUTE10: + case RTC_HOUR1: + case RTC_HOUR10: + case RTC_DAY1: + case RTC_DAY10: + case RTC_WEEKDAY: + case RTC_MONTH1: + case RTC_MONTH10: + r = regs[addr & 0x000f]; + break; + + case RTC_INTR: + r = regs[addr & 0x000f]; + break; + } + + DBGLOG(2, "M24: rtc_rd(%04x) = %02x\n", addr, r); + + return(r); +} + + +static uint8_t +m24_read(uint16_t port, void *priv) +{ + switch (port) { + case 0x66: /* System Configuration 1 (DIPSW-0) */ + /* + * 7-SW8: 0=2732, 1=2764 ROM + * 6-SW7: not used + * 5-SW6: 0=8250, 1=8530 SIO + * 4-SW5: 0=no 8087, 1=8087 + * 3-SW4: 0=64K, 1=256K chips used + * 2-SW3: DRAM config + * 1-SW2: DRAM config + * 0-SW1: DRAM config + * + * SW4 SW3 SW2 SW1 BANK_0 BANK_1 EXPBRD TOTAL + * 0 0 0 1 128 0 0 128 + * 0 0 1 0 128 128 0 256 + * 0 0 1 1 128 128 128 384 + * 0 1 0 0 128 128 256 512 + * 0 1 0 1 128 128 384 640 + * 1 0 0 0 512 0 0 512 + * 1 0 0 1 512 128 0 640 + */ + return(0x80); + + case 0x67: /* System Configuration 2 (DIPSW-1) */ + /* + * 7-SW8: #drives + * 6-SW7: #drives + * 5-SW6: monitor + * 4-SW5: monitor + * 3-SW4: HDU + * 2-SW3: HDU + * 1-SW2: *0=slow start, 1=fast start drive + * 0-SW1: *0=48tpi, 1=96tpi floppy + * + * SW6 SW5 Display type + * 1 1 Monochrome + * 1 0 *Color 80x25 + * 0 1 Color 40x25 + * 0 0 External card + * + * SW8 SW7 + * 1 1 4 diskette drives + * 1 0 3 drives + * 0 1 *2 drives + * 0 0 1 drive + */ + return(0x20 | 0x40 | 0x0c); + } + + return(0xff); +} + + +static void +olim24_close(void *priv) +{ + olim24_t *dev = (olim24_t *)priv; + nvr_t *nvr = &dev->nvr; + + /* Make sure NVR gets saved. */ + nvr_dosave = 1; + nvr_save(); + if (nvr->fn != NULL) + free((wchar_t *)nvr->fn); + + free(dev); +} + + +static void * +olim24_init(const device_t *info, void *arg) +{ + olim24_t *dev; + + dev = (olim24_t *)mem_alloc(sizeof(olim24_t)); + memset(dev, 0x00, sizeof(olim24_t)); + dev->type = info->local; + + /* Add machine device to system. */ + device_add_ex(info, dev); + + machine_common_init(); + + nmi_init(); + + /* Set up and initialize the NVR. */ + dev->nvr.size = 16; + dev->nvr.irq = -1; + dev->nvr.reset = rtc_reset; + dev->nvr.start = rtc_start; + dev->nvr.tick = rtc_ticker; + nvr_init(&dev->nvr); + io_sethandler(0x0070, 16, + rtc_read,NULL,NULL, rtc_write,NULL,NULL, &dev->nvr); + + io_sethandler(0x0066, 2, + m24_read,NULL,NULL, NULL,NULL,NULL, dev); + + /* Initialize the video adapter. */ + m_olim24_vid_init(0); + + /* Initialize the keyboard. */ + dev->status = STAT_LOCK | STAT_CD; + dev->scan[0] = 0x1c; + dev->scan[1] = 0x53; + dev->scan[2] = 0x01; + dev->scan[3] = 0x4b; + dev->scan[4] = 0x4d; + dev->scan[5] = 0x48; + dev->scan[6] = 0x50; + io_sethandler(0x0060, 2, + kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); + io_sethandler(0x0064, 1, + kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); + keyboard_set_table(scancode_xt); + keyboard_send = kbd_adddata_ex; + keyboard_scan = 1; + timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, dev); + + /* Tell mouse driver about our internal mouse. */ + mouse_reset(); + mouse_set_poll(mse_poll, dev); + + device_add(&fdc_xt_device); + + if (dev->type == 2) + device_add(&st506_xt_olim240_hdc_device); + + return(dev); +} + + +static const machine_t m24_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, + MACHINE_VIDEO, + 128, 640, 128, 0, -1, + {{"Intel",cpus_8086},{"NEC",cpus_nec}} +}; + +const device_t m_oli_m24 = { + "Olivetti M24", + DEVICE_ROOT, + 0, + L"olivetti/m24", + olim24_init, olim24_close, NULL, + NULL, NULL, NULL, + &m24_info, + NULL +}; + + +static const machine_t pc6300_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, + MACHINE_VIDEO, + 128, 640, 128, 0, -1, + {{"Intel",cpus_8086},{"NEC",cpus_nec}} +}; + +const device_t m_att_6300 = { + "AT&T PC6300", + DEVICE_ROOT, + 1, + L"att/pc6300", + olim24_init, olim24_close, NULL, + NULL, NULL, NULL, + &pc6300_info, + NULL +}; + + +static const machine_t m240_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, + MACHINE_VIDEO, + 128, 640, 128, 0, -1, + {{"Intel",cpus_8086},{"NEC",cpus_nec}} +}; + +const device_t m_oli_m240 = { + "Olivetti M240", + DEVICE_ROOT, + 2, + L"olivetti/m240", + olim24_init, olim24_close, NULL, + NULL, NULL, NULL, + &m240_info, + NULL +}; diff --git a/src/machines/m_olim24.h b/src/machines/m_olim24.h new file mode 100644 index 0000000..3e60533 --- /dev/null +++ b/src/machines/m_olim24.h @@ -0,0 +1,54 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Olivetti M24 machine. + * + * Version: @(#)m_olim24.h 1.0.1 2019/03/21 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef MACHINE_OLIM24_H +# define MACHINE_OLIM24_H + + +extern void m_olim24_vid_init(int type); + + +#endif /*MACHINE_OLIM24_H*/ diff --git a/src/machines/m_olivetti_m24.c b/src/machines/m_olim24_vid.c similarity index 60% rename from src/machines/m_olivetti_m24.c rename to src/machines/m_olim24_vid.c index 751470c..f4c0656 100644 --- a/src/machines/m_olivetti_m24.c +++ b/src/machines/m_olim24_vid.c @@ -6,9 +6,9 @@ * * This file is part of the VARCem Project. * - * Emulation of the Olivetti M24. + * Emulation of the Olivetti M24 built-in video controller. * - * Version: @(#)m_olivetti_m24.c 1.0.15 2019/03/07 + * Version: @(#)m_olim24_vid.c 1.0.2 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,34 +48,14 @@ #include "../mem.h" #include "../timer.h" #include "../device.h" -#include "../nvr.h" -#include "../devices/system/pic.h" #include "../devices/system/pit.h" -#include "../devices/system/ppi.h" -#include "../devices/system/nmi.h" -#include "../devices/input/keyboard.h" -#include "../devices/input/mouse.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/sound/sound.h" -#include "../devices/sound/snd_speaker.h" #include "../devices/video/video.h" #include "../devices/video/vid_cga.h" #include "machine.h" - - -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_LOCK 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 +#include "m_olim24.h" typedef struct { - /* Video stuff. */ mem_map_t mapping; uint8_t crtc[32]; int crtcreg; @@ -98,23 +78,7 @@ typedef struct { int64_t dispontime, dispofftime; int64_t vidtime; int firstline, lastline; - - /* Keyboard stuff. */ - int wantirq; - uint8_t command; - uint8_t status; - uint8_t out; - uint8_t output_port; - int param, - param_total; - uint8_t params[16]; - uint8_t scan[7]; - - /* Mouse stuff. */ - int mouse_mode; - int x, y, b; -} olim24_t; - +} olivid_t; static const uint8_t crtcmask[32] = { 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, @@ -122,13 +86,11 @@ static const uint8_t crtcmask[32] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static uint8_t key_queue[16]; -static int key_queue_start = 0, - key_queue_end = 0; +static video_timings_t m24_timing = {VID_ISA, 8,16,32, 8,16,32}; static void -recalc_timings(olim24_t *dev) +recalc_timings(olivid_t *dev) { double _dispontime, _dispofftime, disptime; @@ -151,7 +113,7 @@ recalc_timings(olim24_t *dev) static void vid_out(uint16_t addr, uint8_t val, void *priv) { - olim24_t *dev = (olim24_t *)priv; + olivid_t *dev = (olivid_t *)priv; uint8_t old; switch (addr) { @@ -197,7 +159,7 @@ vid_out(uint16_t addr, uint8_t val, void *priv) static uint8_t vid_in(uint16_t addr, void *priv) { - olim24_t *dev = (olim24_t *)priv; + olivid_t *dev = (olivid_t *)priv; uint8_t ret = 0xff; switch (addr) { @@ -229,7 +191,7 @@ vid_in(uint16_t addr, void *priv) static void vid_write(uint32_t addr, uint8_t val, void *priv) { - olim24_t *dev = (olim24_t *)priv; + olivid_t *dev = (olivid_t *)priv; dev->vram[addr & 0x7fff] = val; dev->charbuffer[ ((int)(((dev->dispontime - dev->vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val; @@ -240,7 +202,7 @@ vid_write(uint32_t addr, uint8_t val, void *priv) static uint8_t vid_read(uint32_t addr, void *priv) { - olim24_t *dev = (olim24_t *)priv; + olivid_t *dev = (olivid_t *)priv; return(dev->vram[addr & 0x7fff]); } @@ -249,7 +211,7 @@ vid_read(uint32_t addr, void *priv) static void vid_poll(void *priv) { - olim24_t *dev = (olim24_t *)priv; + olivid_t *dev = (olivid_t *)priv; uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; int drawcursor; int x, c; @@ -515,372 +477,66 @@ vid_poll(void *priv) static void speed_changed(void *priv) { - olim24_t *dev = (olim24_t *)priv; + olivid_t *dev = (olivid_t *)priv; recalc_timings(dev); } -static void -kbd_poll(void *priv) -{ - olim24_t *dev = (olim24_t *)priv; - - keyboard_delay += (1000LL * TIMER_USEC); - if (dev->wantirq) { - dev->wantirq = 0; - picint(2); - DBGLOG(1, "M24: take IRQ\n"); - } - - if (!(dev->status & STAT_OFULL) && key_queue_start != key_queue_end) { - DBGLOG(1, "M24: reading %02X from the key queue at %i\n", - dev->out, key_queue_start); - dev->out = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - dev->status |= STAT_OFULL; - dev->status &= ~STAT_IFULL; - dev->wantirq = 1; - } -} - - -static void -kbd_adddata(uint16_t val) -{ - key_queue[key_queue_end] = (uint8_t)(val&0xff); - key_queue_end = (key_queue_end + 1) & 0xf; -} - - -static void -kbd_adddata_ex(uint16_t val) -{ - kbd_adddata_process(val, kbd_adddata); -} - - -static void -kbd_write(uint16_t port, uint8_t val, void *priv) -{ - olim24_t *dev = (olim24_t *)priv; - - DBGLOG(2, "M24: write %04X %02X\n", port, val); - - switch (port) { - case 0x60: - if (dev->param != dev->param_total) { - dev->params[dev->param++] = val; - if (dev->param == dev->param_total) { - switch (dev->command) { - case 0x11: - dev->mouse_mode = 0; - dev->scan[0] = dev->params[0]; - dev->scan[1] = dev->params[1]; - dev->scan[2] = dev->params[2]; - dev->scan[3] = dev->params[3]; - dev->scan[4] = dev->params[4]; - dev->scan[5] = dev->params[5]; - dev->scan[6] = dev->params[6]; - break; - - case 0x12: - dev->mouse_mode = 1; - dev->scan[0] = dev->params[0]; - dev->scan[1] = dev->params[1]; - dev->scan[2] = dev->params[2]; - break; - - default: - DEBUG("M24: bad keyboard command complete %02X\n", dev->command); - break; - } - } - } else { - dev->command = val; - switch (val) { - case 0x01: /*Self-test*/ - break; - - case 0x05: /*Read ID*/ - kbd_adddata(0x00); - break; - - case 0x11: - dev->param = 0; - dev->param_total = 9; - break; - - case 0x12: - dev->param = 0; - dev->param_total = 4; - break; - - default: - ERRLOG("M24: bad keyboard command %02X\n", val); - break; - } - } - break; - - case 0x61: - ppi.pb = val; - - timer_process(); - timer_update_outstanding(); - - speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; - if (speaker_enable) - speaker_was_enable = 1; - pit_set_gate(&pit, 2, val & 1); - break; - } -} - - -static uint8_t -kbd_read(uint16_t port, void *priv) -{ - olim24_t *dev = (olim24_t *)priv; - uint8_t ret = 0xff; - - switch (port) { - case 0x60: - ret = dev->out; - if (key_queue_start == key_queue_end) { - dev->status &= ~STAT_OFULL; - dev->wantirq = 0; - } else { - dev->out = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - dev->status |= STAT_OFULL; - dev->status &= ~STAT_IFULL; - dev->wantirq = 1; - } - break; - - case 0x61: - ret = ppi.pb; - break; - - case 0x64: - ret = dev->status; - dev->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT); - break; - - default: - ERRLOG("\nBad M24 keyboard read %04X\n", port); - break; - } - - return(ret); -} - - -static int -mse_poll(int x, int y, int z, int b, void *priv) -{ - olim24_t *dev = (olim24_t *)priv; - - dev->x += x; - dev->y += y; - - if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - - if ((b & 1) && !(dev->b & 1)) - kbd_adddata(dev->scan[0]); - if (!(b & 1) && (dev->b & 1)) - kbd_adddata(dev->scan[0] | 0x80); - dev->b = (dev->b & ~1) | (b & 1); - - if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - - if ((b & 2) && !(dev->b & 2)) - kbd_adddata(dev->scan[2]); - if (!(b & 2) && (dev->b & 2)) - kbd_adddata(dev->scan[2] | 0x80); - dev->b = (dev->b & ~2) | (b & 2); - - if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - - if ((b & 4) && !(dev->b & 4)) - kbd_adddata(dev->scan[1]); - if (!(b & 4) && (dev->b & 4)) - kbd_adddata(dev->scan[1] | 0x80); - dev->b = (dev->b & ~4) | (b & 4); - - if (dev->mouse_mode) { - if (((key_queue_end - key_queue_start) & 0xf) > 12) return(0xff); - - if (!dev->x && !dev->y) return(0xff); - - dev->y = -dev->y; - - if (dev->x < -127) dev->x = -127; - if (dev->x > 127) dev->x = 127; - if (dev->x < -127) dev->x = 0x80 | ((-dev->x) & 0x7f); - - if (dev->y < -127) dev->y = -127; - if (dev->y > 127) dev->y = 127; - if (dev->y < -127) dev->y = 0x80 | ((-dev->y) & 0x7f); - - kbd_adddata(0xfe); - kbd_adddata(dev->x); - kbd_adddata(dev->y); - - dev->x = dev->y = 0; - } else { - while (dev->x < -4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) - return(0xff); - dev->x += 4; - kbd_adddata(dev->scan[3]); - } - while (dev->x > 4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) - return(0xff); - dev->x -= 4; - kbd_adddata(dev->scan[4]); - } - while (dev->y < -4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) - return(0xff); - dev->y += 4; - kbd_adddata(dev->scan[5]); - } - while (dev->y > 4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) - return(0xff); - dev->y -= 4; - kbd_adddata(dev->scan[6]); - } - } - - return(0); -} - - -static uint8_t -m24_read(uint16_t port, void *priv) -{ - switch (port) { - case 0x66: - return(0x00); - - case 0x67: - return(0x20 | 0x40 | 0x0c); - } - - return(0xff); -} - - static void vid_close(void *priv) { - olim24_t *dev = (olim24_t *)priv; + olivid_t *dev = (olivid_t *)priv; free(dev->vram); + free(dev); } -static video_timings_t m24_timing = {VID_ISA, 8,16,32, 8,16,32}; - -const device_t m24_device = { +static const device_t video_device = { "Olivetti M24 Video", 0, 0, + NULL, NULL, vid_close, NULL, NULL, speed_changed, NULL, - &m24_timing, + NULL, NULL }; void -m_olim24_init(const machine_t *model, void *arg) +m_olim24_vid_init(int type) { - olim24_t *dev; + olivid_t *dev; - dev = (olim24_t *)mem_alloc(sizeof(olim24_t)); - memset(dev, 0x00, sizeof(olim24_t)); + dev = (olivid_t *)mem_alloc(sizeof(olivid_t)); + memset(dev, 0x00, sizeof(olivid_t)); - machine_common_init(model, arg); - - io_sethandler(0x0066, 2, - m24_read,NULL,NULL, NULL,NULL,NULL, dev); - - /* Initialize the video adapter. */ dev->vram = (uint8_t *)mem_alloc(0x8000); overscan_x = overscan_y = 16; mem_map_add(&dev->mapping, 0xb8000, 0x08000, vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); io_sethandler(0x03d0, 16, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + + switch(type) { + case 0: /* Olivetti M24 */ + break; + + case 1: /* Compaq Portable3 */ + io_sethandler(0x13c6, 1, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + io_sethandler(0x23c6, 1, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + break; + } + timer_add(vid_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); - device_add_ex(&m24_device, dev); - video_inform(VID_TYPE_CGA, - (const video_timings_t *)&m24_device.vid_timing); - /* Initialize the keyboard. */ - dev->status = STAT_LOCK | STAT_CD; - dev->scan[0] = 0x1c; - dev->scan[1] = 0x53; - dev->scan[2] = 0x01; - dev->scan[3] = 0x4b; - dev->scan[4] = 0x4d; - dev->scan[5] = 0x48; - dev->scan[6] = 0x50; - io_sethandler(0x0060, 2, - kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); - io_sethandler(0x0064, 1, - kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); - keyboard_set_table(scancode_xt); - keyboard_send = kbd_adddata_ex; - keyboard_scan = 1; - timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, dev); + device_add_ex(&video_device, dev); - /* Tell mouse driver about our internal mouse. */ - mouse_reset(); - mouse_set_poll(mse_poll, dev); - - /* FIXME: make sure this is correct?? */ - device_add(&at_nvr_device); - - device_add(&fdc_xt_device); - - nmi_init(); + video_inform(VID_TYPE_CGA, &m24_timing); } - - -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) -/* Compaq Portable III also seems to use this. */ -void -m_olim24_video_init(void) -{ - olim24_t *dev; - - dev = (olim24_t *)mem_alloc(sizeof(olim24_t)); - memset(dev, 0x00, sizeof(olim24_t)); - - /* Initialize the video adapter. */ - dev->vram = (uint8_t *)mem_alloc(0x8000); - overscan_x = overscan_y = 16; - mem_map_add(&dev->mapping, 0xb8000, 0x08000, - vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); - io_sethandler(0x03d0, 16, - vid_in,NULL,NULL, vid_out,NULL,NULL, dev); - io_sethandler(0x13c6, 1, - vid_in,NULL,NULL, vid_out,NULL,NULL, dev); - io_sethandler(0x23c6, 1, - vid_in,NULL,NULL, vid_out,NULL,NULL, dev); - timer_add(vid_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); - device_add_ex(&m24_device, dev); - video_inform(VID_TYPE_CGA, - (const video_timings_t *)&m24_device.vid_timing); -} -#endif diff --git a/src/machines/m_opti495.c b/src/machines/m_opti495.c new file mode 100644 index 0000000..d458a1c --- /dev/null +++ b/src/machines/m_opti495.c @@ -0,0 +1,254 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Opti 82C495 based machines. + * + * Version: @(#)m_opti495.c 1.0.11 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/opti495.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Add machine device to system. */ + device_add_ex(info, arg); + + device_add(&opti495_device); + + m_at_common_ide_init(); + + device_add(&fdc_at_device); + + switch(info->local) { + case 0: /* Generic with AMI BIOS */ + device_add(&keyboard_at_ami_device); + break; + + case 1: /* Generic with Award BIOS */ + device_add(&keyboard_at_device); + break; + + case 2: /* Generic with MR BIOS */ + device_add(&keyboard_at_ami_device); + break; + } + + return(arg); +} + + +static const machine_t o386sx_ami_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 1, 16, 1, 128, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_opti495_386sx_ami = { + "Opti495 386SX (AMI)", + DEVICE_ROOT, + 0, + L"opti495/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o386sx_ami_info, + NULL +}; + + +static const machine_t o386sx_award_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 1, 16, 1, 128, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_opti495_386sx_award = { + "Opti495 386SX (Award)", + DEVICE_ROOT, + 1, + L"opti495/award", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o386sx_award_info, + NULL +}; + + +static const machine_t o386sx_mr_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 1, 16, 1, 128, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_opti495_386sx_mr = { + "Opti495 386SX (MR)", + DEVICE_ROOT, + 2, + L"opti495/mr", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o386sx_mr_info, + NULL +}; + + +static const machine_t o386dx_ami_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 1, 32, 1, 128, 0, + {{"Intel",cpus_i386DX},{"AMD",cpus_Am386DX},{"Cyrix",cpus_486DLC}} +}; + +const device_t m_opti495_386dx_ami = { + "Opti495 386DX (AMI)", + DEVICE_ROOT, + 0, + L"opti495/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o386dx_ami_info, + NULL +}; + + +static const machine_t o386dx_award_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 1, 32, 1, 128, 0, + {{"Intel",cpus_i386DX},{"AMD",cpus_Am386DX},{"Cyrix",cpus_486DLC}} +}; + +const device_t m_opti495_386dx_award = { + "Opti495 386DX (Award)", + DEVICE_ROOT, + 1, + L"opti495/award", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o386dx_award_info, + NULL +}; + + +static const machine_t o386dx_mr_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 1, 32, 1, 128, 0, + {{"Intel",cpus_i386DX},{"AMD",cpus_Am386DX},{"Cyrix",cpus_486DLC}} +}; + +const device_t m_opti495_386dx_mr = { + "Opti495 386DX (MR)", + DEVICE_ROOT, + 2, + L"opti495/mr", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o386dx_mr_info, + NULL +}; + + +static const machine_t o486_ami_info = { + MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 1, 32, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_opti495_486_ami = { + "Opti495 486 (AMI)", + DEVICE_ROOT, + 0, + L"opti495/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o486_ami_info, + NULL +}; + + +static const machine_t o486_award_info = { + MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 1, 32, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_opti495_486_award = { + "Opti495 486 (Award)", + DEVICE_ROOT, + 1, + L"opti495/award", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o486_award_info, + NULL +}; + + +static const machine_t o486_mr_info = { + MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 1, 32, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_opti495_486_mr = { + "Opti495 486 (MR)", + DEVICE_ROOT, + 2, + L"opti495/mr", + common_init, NULL, NULL, + NULL, NULL, NULL, + &o486_mr_info, + NULL +}; diff --git a/src/machines/m_pbell.c b/src/machines/m_pbell.c new file mode 100644 index 0000000..7c623fe --- /dev/null +++ b/src/machines/m_pbell.c @@ -0,0 +1,116 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of various Packard Bell machines. + * + * Version: @(#)m_pbell.c 1.0.1 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/intel4x0.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/system/intel.h" +#include "../devices/system/intel_flash.h" +#include "../devices/system/intel_sio.h" +#include "../devices/system/intel_piix.h" +#include "../devices/input/keyboard.h" +#include "../devices/sio/sio.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "../devices/video/video.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Allocate machine device to system. */ + device_add_ex(info, arg); + + switch(info->local) { + /* PB640: Packard Bell PB640/430FX/AMI/NS PC87306 */ + case 0: + device_add(&i430fx_pb640_device); + device_add(&piix_pb640_device); + device_add(&intel_flash_bxt_ami_device); + m_at_common_init(); + device_add(&keyboard_ps2_ami_pci_device); + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + ide_enable_pio_override(); + device_add(&pc87306_device); + + if (video_card == VID_INTERNAL) + device_add(&gd5440_onboard_pci_device); + break; + } + + return(arg); +} + + +static const machine_t pb640_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, + 0, + 8, 128, 8, 128, -1, + {{"Intel",cpus_Pentium},{"IDT",cpus_WinChip},CPU_AMD_K56,{"Cyrix",cpus_6x86}} +}; + +const device_t m_pb640 = { + "Packard Bell 640", + DEVICE_ROOT, + 0, + L"pbell/pb640", + common_init, NULL, NULL, + NULL, NULL, NULL, + &pb640_info, + NULL /* &gd5440_onboard_pci_device */ +}; diff --git a/src/machines/m_pcjr.c b/src/machines/m_pcjr.c index 2de8cb0..29b573e 100644 --- a/src/machines/m_pcjr.c +++ b/src/machines/m_pcjr.c @@ -8,7 +8,7 @@ * * Emulation of the IBM PCjr. * - * Version: @(#)m_pcjr.c 1.0.15 2019/03/07 + * Version: @(#)m_pcjr.c 1.0.17 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -80,6 +80,9 @@ typedef struct { + int display_type; + int composite; + /* Video Controller stuff. */ mem_map_t mapping; uint8_t crtc[32]; @@ -101,7 +104,6 @@ typedef struct { uint16_t ma, maback; int64_t dispontime, dispofftime, vidtime; int firstline, lastline; - int composite; void *cpriv; /* Keyboard Controller stuff. */ @@ -120,108 +122,109 @@ static const uint8_t crtcmask[32] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const video_timings_t pcjr_timings = { VID_BUS,0,0,0,0,0,0 }; static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; static void -recalc_address(pcjr_t *pcjr) +recalc_address(pcjr_t *dev) { - if ((pcjr->memctrl & 0xc0) == 0xc0) { - pcjr->vram = &ram[(pcjr->memctrl & 0x06) << 14]; - pcjr->b8000 = &ram[(pcjr->memctrl & 0x30) << 11]; + if ((dev->memctrl & 0xc0) == 0xc0) { + dev->vram = &ram[(dev->memctrl & 0x06) << 14]; + dev->b8000 = &ram[(dev->memctrl & 0x30) << 11]; } else { - pcjr->vram = &ram[(pcjr->memctrl & 0x07) << 14]; - pcjr->b8000 = &ram[(pcjr->memctrl & 0x38) << 11]; + dev->vram = &ram[(dev->memctrl & 0x07) << 14]; + dev->b8000 = &ram[(dev->memctrl & 0x38) << 11]; } } static void -recalc_timings(pcjr_t *pcjr) +recalc_timings(pcjr_t *dev) { double _dispontime, _dispofftime, disptime; - if (pcjr->array[0] & 1) { - disptime = pcjr->crtc[0] + 1; - _dispontime = pcjr->crtc[1]; + if (dev->array[0] & 1) { + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; } else { - disptime = (pcjr->crtc[0] + 1) << 1; - _dispontime = pcjr->crtc[1] << 1; + disptime = (dev->crtc[0] + 1) << 1; + _dispontime = dev->crtc[1] << 1; } _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - pcjr->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - pcjr->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } static void -vid_out(uint16_t addr, uint8_t val, void *p) +vid_out(uint16_t addr, uint8_t val, void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; + pcjr_t *dev = (pcjr_t *)priv; uint8_t old; switch (addr) { case 0x3d4: - pcjr->crtcreg = val & 0x1f; + dev->crtcreg = val & 0x1f; return; case 0x3d5: - old = pcjr->crtc[pcjr->crtcreg]; - pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg]; + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg]; if (old != val) { - if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) { + if (dev->crtcreg < 0xe || dev->crtcreg > 0x10) { fullchange = changeframecount; - recalc_timings(pcjr); + recalc_timings(dev); } } return; case 0x3da: - if (!pcjr->array_ff) - pcjr->array_index = val & 0x1f; + if (!dev->array_ff) + dev->array_index = val & 0x1f; else { - if (pcjr->array_index & 0x10) + if (dev->array_index & 0x10) val &= 0x0f; - pcjr->array[pcjr->array_index & 0x1f] = val; - if (!(pcjr->array_index & 0x1f)) - cga_comp_update(pcjr->cpriv, val); + dev->array[dev->array_index & 0x1f] = val; + if (!(dev->array_index & 0x1f)) + cga_comp_update(dev->cpriv, val); } - pcjr->array_ff = !pcjr->array_ff; + dev->array_ff = !dev->array_ff; break; case 0x3df: - pcjr->memctrl = val; - pcjr->addr_mode = val >> 6; - recalc_address(pcjr); + dev->memctrl = val; + dev->addr_mode = val >> 6; + recalc_address(dev); break; } } static uint8_t -vid_in(uint16_t addr, void *p) +vid_in(uint16_t addr, void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; + pcjr_t *dev = (pcjr_t *)priv; uint8_t ret = 0xff; switch (addr) { case 0x3d4: - ret = pcjr->crtcreg; + ret = dev->crtcreg; break; case 0x3d5: - ret = pcjr->crtc[pcjr->crtcreg]; + ret = dev->crtc[dev->crtcreg]; break; case 0x3da: - pcjr->array_ff = 0; - pcjr->stat ^= 0x10; - ret = pcjr->stat; + dev->array_ff = 0; + dev->stat ^= 0x10; + ret = dev->stat; break; } @@ -230,32 +233,32 @@ vid_in(uint16_t addr, void *p) static void -vid_write(uint32_t addr, uint8_t val, void *p) +vid_write(uint32_t addr, uint8_t val, void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; + pcjr_t *dev = (pcjr_t *)priv; - if (pcjr->memctrl == -1) return; + if (dev->memctrl == -1) return; - pcjr->b8000[addr & 0x3fff] = val; + dev->b8000[addr & 0x3fff] = val; } static uint8_t -vid_read(uint32_t addr, void *p) +vid_read(uint32_t addr, void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; + pcjr_t *dev = (pcjr_t *)priv; - if (pcjr->memctrl == -1) return(0xff); + if (dev->memctrl == -1) return(0xff); - return(pcjr->b8000[addr & 0x3fff]); + return(dev->b8000[addr & 0x3fff]); } static void -vid_poll(void *p) +vid_poll(void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; - uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff; + pcjr_t *dev = (pcjr_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; int drawcursor; int x, c; int oldvc; @@ -264,278 +267,280 @@ vid_poll(void *p) int cols[4]; int oldsc; - if (! pcjr->linepos) { - pcjr->vidtime += pcjr->dispofftime; - pcjr->stat &= ~1; - pcjr->linepos = 1; - oldsc = pcjr->sc; - if ((pcjr->crtc[8] & 3) == 3) - pcjr->sc = (pcjr->sc << 1) & 7; - if (pcjr->dispon) { + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat &= ~1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + if (dev->dispon) { uint16_t offset = 0; uint16_t mask = 0x1fff; - if (pcjr->displine < pcjr->firstline) { - pcjr->firstline = pcjr->displine; + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; video_blit_wait_buffer(); } - pcjr->lastline = pcjr->displine; - cols[0] = (pcjr->array[2] & 0xf) + 16; + dev->lastline = dev->displine; + cols[0] = (dev->array[2] & 0xf) + 16; for (c = 0; c < 8; c++) { - screen->line[pcjr->displine][c].pal = cols[0]; - if (pcjr->array[0] & 1) - screen->line[pcjr->displine][c + (pcjr->crtc[1] << 3) + 8].pal = cols[0]; + screen->line[dev->displine][c].pal = cols[0]; + if (dev->array[0] & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = cols[0]; else - screen->line[pcjr->displine][c + (pcjr->crtc[1] << 4) + 8].pal = cols[0]; + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = cols[0]; } - switch (pcjr->addr_mode) { + switch (dev->addr_mode) { case 0: /*Alpha*/ offset = 0; mask = 0x3fff; break; + case 1: /*Low resolution graphics*/ - offset = (pcjr->sc & 1) * 0x2000; + offset = (dev->sc & 1) * 0x2000; break; + case 3: /*High resolution graphics*/ - offset = (pcjr->sc & 3) * 0x2000; + offset = (dev->sc & 3) * 0x2000; break; } - switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { + switch ((dev->array[0] & 0x13) | ((dev->array[3] & 0x08) << 5)) { case 0x13: /*320x200x16*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - screen->line[pcjr->displine][(x << 3) + 8].pal = - screen->line[pcjr->displine][(x << 3) + 9].pal = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16; - screen->line[pcjr->displine][(x << 3) + 10].pal = - screen->line[pcjr->displine][(x << 3) + 11].pal = pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16; - screen->line[pcjr->displine][(x << 3) + 12].pal = - screen->line[pcjr->displine][(x << 3) + 13].pal = pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16; - screen->line[pcjr->displine][(x << 3) + 14].pal = - screen->line[pcjr->displine][(x << 3) + 15].pal = pcjr->array[(dat & pcjr->array[1]) + 16] + 16; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & mask) + offset] << 8) | + dev->vram[((dev->ma << 1) & mask) + offset + 1]; + dev->ma++; + screen->line[dev->displine][(x << 3) + 8].pal = + screen->line[dev->displine][(x << 3) + 9].pal = dev->array[((dat >> 12) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 10].pal = + screen->line[dev->displine][(x << 3) + 11].pal = dev->array[((dat >> 8) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 12].pal = + screen->line[dev->displine][(x << 3) + 13].pal = dev->array[((dat >> 4) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 14].pal = + screen->line[dev->displine][(x << 3) + 15].pal = dev->array[(dat & dev->array[1]) + 16] + 16; } break; case 0x12: /*160x200x16*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - screen->line[pcjr->displine][(x << 4) + 8].pal = - screen->line[pcjr->displine][(x << 4) + 9].pal = - screen->line[pcjr->displine][(x << 4) + 10].pal = - screen->line[pcjr->displine][(x << 4) + 11].pal = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16; - screen->line[pcjr->displine][(x << 4) + 12].pal = - screen->line[pcjr->displine][(x << 4) + 13].pal = - screen->line[pcjr->displine][(x << 4) + 14].pal = - screen->line[pcjr->displine][(x << 4) + 15].pal = pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16; - screen->line[pcjr->displine][(x << 4) + 16].pal = - screen->line[pcjr->displine][(x << 4) + 17].pal = - screen->line[pcjr->displine][(x << 4) + 18].pal = - screen->line[pcjr->displine][(x << 4) + 19].pal = pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16; - screen->line[pcjr->displine][(x << 4) + 20].pal = - screen->line[pcjr->displine][(x << 4) + 21].pal = - screen->line[pcjr->displine][(x << 4) + 22].pal = - screen->line[pcjr->displine][(x << 4) + 23].pal = pcjr->array[(dat & pcjr->array[1]) + 16] + 16; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & mask) + offset] << 8) | + dev->vram[((dev->ma << 1) & mask) + offset + 1]; + dev->ma++; + screen->line[dev->displine][(x << 4) + 8].pal = + screen->line[dev->displine][(x << 4) + 9].pal = + screen->line[dev->displine][(x << 4) + 10].pal = + screen->line[dev->displine][(x << 4) + 11].pal = dev->array[((dat >> 12) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 12].pal = + screen->line[dev->displine][(x << 4) + 13].pal = + screen->line[dev->displine][(x << 4) + 14].pal = + screen->line[dev->displine][(x << 4) + 15].pal = dev->array[((dat >> 8) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 16].pal = + screen->line[dev->displine][(x << 4) + 17].pal = + screen->line[dev->displine][(x << 4) + 18].pal = + screen->line[dev->displine][(x << 4) + 19].pal = dev->array[((dat >> 4) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 20].pal = + screen->line[dev->displine][(x << 4) + 21].pal = + screen->line[dev->displine][(x << 4) + 22].pal = + screen->line[dev->displine][(x << 4) + 23].pal = dev->array[(dat & dev->array[1]) + 16] + 16; } break; case 0x03: /*640x200x4*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & mask) + offset] << 8) | + dev->vram[((dev->ma << 1) & mask) + offset + 1]; + dev->ma++; for (c = 0; c < 8; c++) { chr = (dat >> 7) & 1; chr |= ((dat >> 14) & 2); - screen->line[pcjr->displine][(x << 3) + 8 + c].pal = pcjr->array[(chr & pcjr->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 8 + c].pal = dev->array[(chr & dev->array[1]) + 16] + 16; dat <<= 1; } } break; case 0x01: /*80 column text*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); - if (pcjr->array[3] & 4) { - cols[1] = pcjr->array[ ((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16; - if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[((dev->ma << 1) & mask) + offset]; + attr = dev->vram[((dev->ma << 1) & mask) + offset + 1]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->array[3] & 4) { + cols[1] = dev->array[ ((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[(((attr >> 4) & 7) & dev->array[1]) + 16] + 16; + if ((dev->blink & 16) && (attr & 0x80) && !drawcursor) cols[1] = cols[0]; } else { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16; + cols[1] = dev->array[((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[((attr >> 4) & dev->array[1]) + 16] + 16; } - if (pcjr->sc & 8) { + if (dev->sc & 8) { for (c = 0; c < 8; c++) - screen->line[pcjr->displine][(x << 3) + c + 8].pal = cols[0]; + screen->line[dev->displine][(x << 3) + c + 8].pal = cols[0]; } else { for (c = 0; c < 8; c++) - screen->line[pcjr->displine][(x << 3) + c + 8].pal = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + screen->line[dev->displine][(x << 3) + c + 8].pal = cols[(fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; } if (drawcursor) { for (c = 0; c < 8; c++) - screen->line[pcjr->displine][(x << 3) + c + 8].pal ^= 15; + screen->line[dev->displine][(x << 3) + c + 8].pal ^= 15; } - pcjr->ma++; + dev->ma++; } break; case 0x00: /*40 column text*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); - if (pcjr->array[3] & 4) { - cols[1] = pcjr->array[ ((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16; - if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[((dev->ma << 1) & mask) + offset]; + attr = dev->vram[((dev->ma << 1) & mask) + offset + 1]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->array[3] & 4) { + cols[1] = dev->array[ ((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[(((attr >> 4) & 7) & dev->array[1]) + 16] + 16; + if ((dev->blink & 16) && (attr & 0x80) && !drawcursor) cols[1] = cols[0]; } else { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16; + cols[1] = dev->array[((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[((attr >> 4) & dev->array[1]) + 16] + 16; } - pcjr->ma++; - if (pcjr->sc & 8) { + dev->ma++; + if (dev->sc & 8) { for (c = 0; c < 8; c++) - screen->line[pcjr->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[0]; + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[0]; } else { for (c = 0; c < 8; c++) - screen->line[pcjr->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; } if (drawcursor) { for (c = 0; c < 16; c++) - screen->line[pcjr->displine][(x << 4) + c + 8].pal ^= 15; + screen->line[dev->displine][(x << 4) + c + 8].pal ^= 15; } } break; case 0x02: /*320x200x4*/ - cols[0] = pcjr->array[0 + 16] + 16; - cols[1] = pcjr->array[1 + 16] + 16; - cols[2] = pcjr->array[2 + 16] + 16; - cols[3] = pcjr->array[3 + 16] + 16; - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; + cols[0] = dev->array[0 + 16] + 16; + cols[1] = dev->array[1 + 16] + 16; + cols[2] = dev->array[2 + 16] + 16; + cols[3] = dev->array[3 + 16] + 16; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & mask) + offset] << 8) | + dev->vram[((dev->ma << 1) & mask) + offset + 1]; + dev->ma++; for (c = 0; c < 8; c++) { - screen->line[pcjr->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[dat >> 14]; + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[dat >> 14]; dat <<= 2; } } break; case 0x102: /*640x200x2*/ - cols[0] = pcjr->array[0 + 16] + 16; - cols[1] = pcjr->array[1 + 16] + 16; - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; + cols[0] = dev->array[0 + 16] + 16; + cols[1] = dev->array[1 + 16] + 16; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & mask) + offset] << 8) | + dev->vram[((dev->ma << 1) & mask) + offset + 1]; + dev->ma++; for (c = 0; c < 16; c++) { - screen->line[pcjr->displine][(x << 4) + c + 8].pal = cols[dat >> 15]; + screen->line[dev->displine][(x << 4) + c + 8].pal = cols[dat >> 15]; dat <<= 1; } } break; } } else { - if (pcjr->array[3] & 4) { - if (pcjr->array[0] & 1) - cga_hline(screen, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); + if (dev->array[3] & 4) { + if (dev->array[0] & 1) + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 3) + 16, (dev->array[2] & 0xf) + 16); else - cga_hline(screen, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 4) + 16, (dev->array[2] & 0xf) + 16); } else { - cols[0] = pcjr->array[0 + 16] + 16; - if (pcjr->array[0] & 1) - cga_hline(screen, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, cols[0]); + cols[0] = dev->array[0 + 16] + 16; + if (dev->array[0] & 1) + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 3) + 16, cols[0]); else - cga_hline(screen, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, cols[0]); + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 4) + 16, cols[0]); } } - if (pcjr->array[0] & 1) - x = (pcjr->crtc[1] << 3) + 16; + if (dev->array[0] & 1) + x = (dev->crtc[1] << 3) + 16; else - x = (pcjr->crtc[1] << 4) + 16; + x = (dev->crtc[1] << 4) + 16; - if (pcjr->composite) - cga_comp_process(pcjr->cpriv, pcjr->array[0], 0, x >> 2, screen->line[pcjr->displine]); + if (dev->composite) + cga_comp_process(dev->cpriv, dev->array[0], 0, x >> 2, screen->line[dev->displine]); - pcjr->sc = oldsc; - if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) { - pcjr->stat |= 8; + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) { + dev->stat |= 8; } - pcjr->displine++; - if (pcjr->displine >= 360) - pcjr->displine = 0; + dev->displine++; + if (dev->displine >= 360) + dev->displine = 0; } else { - pcjr->vidtime += pcjr->dispontime; - if (pcjr->dispon) - pcjr->stat |= 1; - pcjr->linepos = 0; - if (pcjr->vsynctime) { - pcjr->vsynctime--; - if (!pcjr->vsynctime) { - pcjr->stat &= ~8; + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat |= 1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (!dev->vsynctime) { + dev->stat &= ~8; } } - if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) { - pcjr->con = 0; - pcjr->coff = 1; + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; } - if (pcjr->vadj) { - pcjr->sc++; - pcjr->sc &= 31; - pcjr->ma = pcjr->maback; - pcjr->vadj--; - if (!pcjr->vadj) { - pcjr->dispon = 1; - pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; - pcjr->sc = 0; + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (!dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; } - } else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1))) { - pcjr->maback = pcjr->ma; - pcjr->sc = 0; - oldvc = pcjr->vc; - pcjr->vc++; - pcjr->vc &= 127; - if (pcjr->vc == pcjr->crtc[6]) - pcjr->dispon = 0; - if (oldvc == pcjr->crtc[4]) { - pcjr->vc = 0; - pcjr->vadj = pcjr->crtc[5]; - if (!pcjr->vadj) - pcjr->dispon = 1; - if (!pcjr->vadj) - pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; - if ((pcjr->crtc[10] & 0x60) == 0x20) - pcjr->cursoron = 0; + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) + dev->dispon = 1; + if (!dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; else - pcjr->cursoron = pcjr->blink & 16; + dev->cursoron = dev->blink & 16; } - if (pcjr->vc == pcjr->crtc[7]) { - pcjr->dispon = 0; - pcjr->displine = 0; - pcjr->vsynctime = 16; + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; picint(1 << 5); - if (pcjr->crtc[7]) { - if (pcjr->array[0] & 1) - x = (pcjr->crtc[1] << 3) + 16; + if (dev->crtc[7]) { + if (dev->array[0] & 1) + x = (dev->crtc[1] << 3) + 16; else - x = (pcjr->crtc[1] << 4) + 16; - pcjr->lastline++; - if ((x != xsize) || ((pcjr->lastline - pcjr->firstline) != ysize) || video_force_resize_get()) { + x = (dev->crtc[1] << 4) + 16; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { xsize = x; - ysize = pcjr->lastline - pcjr->firstline; + ysize = dev->lastline - dev->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; set_screen_size(xsize, (ysize << 1) + 16); @@ -544,26 +549,26 @@ vid_poll(void *p) video_force_resize_set(0); } - if (pcjr->composite) - video_blit_start(0, 0, pcjr->firstline-4, 0, (pcjr->lastline - pcjr->firstline) + 8, xsize, (pcjr->lastline - pcjr->firstline) + 8); + if (dev->composite) + video_blit_start(0, 0, dev->firstline-4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); else - video_blit_start(1, 0, pcjr->firstline-4, 0, (pcjr->lastline - pcjr->firstline) + 8, xsize, (pcjr->lastline - pcjr->firstline) + 8); + video_blit_start(1, 0, dev->firstline-4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); frames++; video_res_x = xsize - 16; video_res_y = ysize; } - pcjr->firstline = 1000; - pcjr->lastline = 0; - pcjr->blink++; + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; } } else { - pcjr->sc++; - pcjr->sc &= 31; - pcjr->ma = pcjr->maback; + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; } - if ((pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1)))) - pcjr->con = 1; + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; } } @@ -571,15 +576,15 @@ vid_poll(void *p) static void kbd_write(uint16_t port, uint8_t val, void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; + pcjr_t *dev = (pcjr_t *)priv; switch (port) { case 0x60: - pcjr->pa = val; + dev->pa = val; break; case 0x61: - pcjr->pb = val; + dev->pb = val; timer_process(); timer_update_outstanding(); @@ -598,7 +603,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0x60: sn76489_mute = 0; - break; + break; } break; @@ -613,30 +618,30 @@ kbd_write(uint16_t port, uint8_t val, void *priv) static uint8_t kbd_read(uint16_t port, void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; + pcjr_t *dev = (pcjr_t *)priv; uint8_t ret = 0xff; switch (port) { case 0x60: - ret = pcjr->pa; + ret = dev->pa; break; case 0x61: - ret = pcjr->pb; + ret = dev->pb; break; case 0x62: - ret = (pcjr->latched ? 1 : 0); + ret = (dev->latched ? 1 : 0); ret |= 0x02; /*Modem card not installed*/ ret |= (ppispeakon ? 0x10 : 0); ret |= (ppispeakon ? 0x20 : 0); - ret |= (pcjr->data ? 0x40: 0); - if (pcjr->data) + ret |= (dev->data ? 0x40: 0); + if (dev->data) ret |= 0x40; break; case 0xa0: - pcjr->latched = 0; + dev->latched = 0; ret = 0; break; @@ -651,54 +656,54 @@ kbd_read(uint16_t port, void *priv) static void kbd_poll(void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; + pcjr_t *dev = (pcjr_t *)priv; int c, p = 0, key; keyboard_delay += (220LL * TIMER_USEC); if (key_queue_start != key_queue_end && - !pcjr->serial_pos && !pcjr->latched) { + !dev->serial_pos && !dev->latched) { key = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; - pcjr->latched = 1; - pcjr->serial_data[0] = 1; /*Start bit*/ - pcjr->serial_data[1] = 0; + dev->latched = 1; + dev->serial_data[0] = 1; /*Start bit*/ + dev->serial_data[1] = 0; for (c = 0; c < 8; c++) { if (key & (1 << c)) { - pcjr->serial_data[(c + 1) * 2] = 1; - pcjr->serial_data[(c + 1) * 2 + 1] = 0; + dev->serial_data[(c + 1) * 2] = 1; + dev->serial_data[(c + 1) * 2 + 1] = 0; p++; } else { - pcjr->serial_data[(c + 1) * 2] = 0; - pcjr->serial_data[(c + 1) * 2 + 1] = 1; + dev->serial_data[(c + 1) * 2] = 0; + dev->serial_data[(c + 1) * 2 + 1] = 1; } } if (p & 1) { /*Parity*/ - pcjr->serial_data[9 * 2] = 1; - pcjr->serial_data[9 * 2 + 1] = 0; + dev->serial_data[9 * 2] = 1; + dev->serial_data[9 * 2 + 1] = 0; } else { - pcjr->serial_data[9 * 2] = 0; - pcjr->serial_data[9 * 2 + 1] = 1; + dev->serial_data[9 * 2] = 0; + dev->serial_data[9 * 2 + 1] = 1; } for (c = 0; c < 11; c++) { /*11 stop bits*/ - pcjr->serial_data[(c + 10) * 2] = 0; - pcjr->serial_data[(c + 10) * 2 + 1] = 0; + dev->serial_data[(c + 10) * 2] = 0; + dev->serial_data[(c + 10) * 2 + 1] = 0; } - pcjr->serial_pos++; + dev->serial_pos++; } - if (pcjr->serial_pos) { - pcjr->data = pcjr->serial_data[pcjr->serial_pos - 1]; - nmi = pcjr->data; - pcjr->serial_pos++; - if (pcjr->serial_pos == 42+1) - pcjr->serial_pos = 0; + if (dev->serial_pos) { + dev->data = dev->serial_data[dev->serial_pos - 1]; + nmi = dev->data; + dev->serial_pos++; + if (dev->serial_pos == 42+1) + dev->serial_pos = 0; } } @@ -721,21 +726,86 @@ kbd_adddata_ex(uint16_t val) static void pcjr_close(void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; + pcjr_t *dev = (pcjr_t *)priv; - if (pcjr->composite && pcjr->cpriv) - cga_comp_close(pcjr->cpriv); + if (dev->composite && dev->cpriv) + cga_comp_close(dev->cpriv); - free(pcjr); + free(dev); } static void speed_changed(void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; + pcjr_t *dev = (pcjr_t *)priv; - recalc_timings(pcjr); + recalc_timings(dev); +} + + +static void * +pcjr_init(const device_t *info, UNUSED(void *arg)) +{ + pcjr_t *dev; + + dev = (pcjr_t *)mem_alloc(sizeof(pcjr_t)); + memset(dev, 0x00, sizeof(pcjr_t)); + + /* Add the machine device. */ + device_add_ex(info, dev); + + dev->memctrl = -1; + dev->display_type = machine_get_config_int("display_type"); + dev->composite = (dev->display_type != PCJR_RGB); + if (dev->composite) + dev->cpriv = cga_comp_init(0); + + pic_init(); + + pit_init(); + pit_set_out_func(&pit, 0, pit_irq0_timer_pcjr); + +#if 0 + // FIXME: already done in machine_reset() + (void)cpu_set(); + pc_set_speed(); +#endif + + nmi_mask = 0x80; + + if (serial_enabled[0]) { + serial_setup(1, 0x2f8, 3); + device_add(&serial_1_pcjr_device); + } + + /* Initialize the video controller. */ + mem_map_add(&dev->mapping, 0xb8000, 0x08000, + vid_read, NULL, NULL, + vid_write, NULL, NULL, NULL, 0, dev); + io_sethandler(0x03d0, 16, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + timer_add(vid_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + video_inform(VID_TYPE_CGA, &pcjr_timings); + + /* Initialize the keyboard. */ + keyboard_scan = 1; + key_queue_start = key_queue_end = 0; + io_sethandler(0x0060, 4, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x00a0, 8, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, dev); + keyboard_set_table(scancode_xt); + keyboard_send = kbd_adddata_ex; + + /* Add the built-in sound device. */ + device_add(&sn76489_device); + + /* Add the floppy controller. */ + device_add(&fdc_pcjr_device); + + return(dev); } @@ -750,82 +820,37 @@ static const device_config_t pcjr_config[] = { "Composite", PCJR_COMPOSITE }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; -static const video_timings_t pcjr_timings = { VID_BUS,0,0,0,0,0,0 }; +static const CPU cpus_pcjr[] = { + { "8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { NULL } +}; -const device_t m_pcjr_device = { +static const machine_t pcjr_info = { + MACHINE_ISA | MACHINE_VIDEO, + MACHINE_VIDEO, + 128, 640, 128, 0, -1, + {{"Intel",cpus_pcjr}} +}; + +const device_t m_pcjr = { "IBM PCjr", - 0, 0, - NULL, pcjr_close, NULL, + DEVICE_ROOT, + 0, + L"ibm/pcjr", + pcjr_init, pcjr_close, NULL, NULL, speed_changed, NULL, - &pcjr_timings, + &pcjr_info, pcjr_config }; - - -void -m_pcjr_init(const machine_t *model, UNUSED(void *arg)) -{ - int display_type; - pcjr_t *dev; - - dev = (pcjr_t *)mem_alloc(sizeof(pcjr_t)); - memset(dev, 0x00, sizeof(pcjr_t)); - dev->memctrl = -1; - display_type = machine_get_config_int("display_type"); - dev->composite = (display_type != PCJR_RGB); - if (dev->composite) - dev->cpriv = cga_comp_init(0); - - pic_init(); - pit_init(); - pit_set_out_func(&pit, 0, pit_irq0_timer_pcjr); - - cpu_set(); - - pc_set_speed(); - - if (serial_enabled[0]) { - serial_setup(1, 0x2f8, 3); - device_add(&serial_1_pcjr_device); - } - - /* Initialize the video controller. */ - mem_map_add(&dev->mapping, 0xb8000, 0x08000, - vid_read, NULL, NULL, - vid_write, NULL, NULL, NULL, 0, dev); - io_sethandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, dev); - timer_add(vid_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); - device_add_ex(&m_pcjr_device, dev); - video_inform(VID_TYPE_CGA, - (const video_timings_t *)&m_pcjr_device.vid_timing); - - /* Initialize the keyboard. */ - keyboard_scan = 1; - key_queue_start = key_queue_end = 0; - io_sethandler(0x0060, 4, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - io_sethandler(0x00a0, 8, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, dev); - keyboard_set_table(scancode_xt); - keyboard_send = kbd_adddata_ex; - - device_add(&sn76489_device); - - nmi_mask = 0x80; - - device_add(&fdc_pcjr_device); -} diff --git a/src/machines/m_ps1.c b/src/machines/m_ps1.c index cefc90b..dc98497 100644 --- a/src/machines/m_ps1.c +++ b/src/machines/m_ps1.c @@ -22,7 +22,7 @@ * The reserved 384K is remapped to the top of extended memory. * If this is not done then you get an error on startup. * - * Version: @(#)m_ps1.c 1.0.23 2019/02/16 + * Version: @(#)m_ps1.c 1.0.25 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -81,6 +81,7 @@ #include "../devices/video/video.h" #include "../plat.h" #include "machine.h" +#include "m_ps1.h" typedef struct { @@ -102,16 +103,16 @@ typedef struct { mem_map_t romext_mapping; uint8_t romext[32768]; - uint8_t ps1_91, - ps1_92, - ps1_94, - ps1_102, - ps1_103, - ps1_104, - ps1_105, - ps1_190; - int ps1_e0_addr; - uint8_t ps1_e0_regs[256]; + uint8_t reg_91, + reg_92, + reg_94, + reg_102, + reg_103, + reg_104, + reg_105, + reg_190; + int e0_addr; + uint8_t e0_regs[256]; } ps1_t; @@ -251,7 +252,7 @@ snd_get_buffer(int32_t *bufp, int len, void *priv) static void * -snd_init(const device_t *info) +snd_init(const device_t *info, UNUSED(void *parent)) { ps1snd_t *snd; @@ -284,7 +285,7 @@ snd_close(void *priv) static const device_t snd_device = { "PS/1 Audio", - 0, 0, + 0, 0, NULL, snd_init, snd_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -325,13 +326,13 @@ recalc_memory(ps1_t *dev) { /* Enable first 512K */ mem_set_mem_state(0x00000, 0x80000, - (dev->ps1_e0_regs[0] & 0x01) ? + (dev->e0_regs[0] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); /* Enable 512-640K */ mem_set_mem_state(0x80000, 0x20000, - (dev->ps1_e0_regs[1] & 0x01) ? + (dev->e0_regs[1] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); } @@ -346,29 +347,29 @@ ps1_write(uint16_t port, uint8_t val, void *priv) case 0x0092: if (dev->model != 2011) { if (val & 1) { - softresetx86(); + cpu_reset(0); cpu_set_edx(); } - dev->ps1_92 = val & ~1; + dev->reg_92 = val & ~1; } else { - dev->ps1_92 = val; + dev->reg_92 = val; } mem_a20_alt = val & 2; mem_a20_recalc(); break; case 0x0094: - dev->ps1_94 = val; + dev->reg_94 = val; break; case 0x00e0: if (dev->model != 2011) - dev->ps1_e0_addr = val; + dev->e0_addr = val; break; case 0x00e1: if (dev->model != 2011) { - dev->ps1_e0_regs[dev->ps1_e0_addr] = val; + dev->e0_regs[dev->e0_addr] = val; recalc_memory(dev); } break; @@ -395,23 +396,23 @@ ps1_write(uint16_t port, uint8_t val, void *priv) break; } } - dev->ps1_102 = val; + dev->reg_102 = val; break; case 0x0103: - dev->ps1_103 = val; + dev->reg_103 = val; break; case 0x0104: - dev->ps1_104 = val; + dev->reg_104 = val; break; case 0x0105: - dev->ps1_105 = val; + dev->reg_105 = val; break; case 0x0190: - dev->ps1_190 = val; + dev->reg_190 = val; break; } } @@ -425,47 +426,47 @@ ps1_read(uint16_t port, void *priv) switch (port) { case 0x0091: /* Card Select Feedback register */ - ret = dev->ps1_91; - dev->ps1_91 = 0; + ret = dev->reg_91; + dev->reg_91 = 0; break; case 0x0092: - ret = dev->ps1_92; + ret = dev->reg_92; break; case 0x0094: - ret = dev->ps1_94; + ret = dev->reg_94; break; case 0x00e1: if (dev->model != 2011) - ret = dev->ps1_e0_regs[dev->ps1_e0_addr]; + ret = dev->e0_regs[dev->e0_addr]; break; case 0x0102: if (dev->model == 2011) - ret = dev->ps1_102 | 0x08; + ret = dev->reg_102 | 0x08; else - ret = dev->ps1_102; + ret = dev->reg_102; break; case 0x0103: - ret = dev->ps1_103; + ret = dev->reg_103; break; case 0x0104: - ret = dev->ps1_104; + ret = dev->reg_104; break; case 0x0105: if (dev->model == 2011) - ret = dev->ps1_105; + ret = dev->reg_105; else - ret = dev->ps1_105 | 0x80; + ret = dev->reg_105 | 0x80; break; case 0x0190: - ret = dev->ps1_190; + ret = dev->reg_190; break; default: @@ -477,30 +478,29 @@ ps1_read(uint16_t port, void *priv) static void -ps1_setup(int model, romdef_t *bios) +ps1_close(void *priv) { - void *priv; + ps1_t *dev = (ps1_t *)priv; + + free(dev); +} + + +static void * +ps1_init(const device_t *info, void *arg) +{ +// romdef_t *bios = (romdef_t *)arg; ps1_t *dev; + int i; dev = (ps1_t *)mem_alloc(sizeof(ps1_t)); memset(dev, 0x00, sizeof(ps1_t)); - dev->model = model; + dev->model = info->local; - io_sethandler(0x0091, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); - io_sethandler(0x0092, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); - io_sethandler(0x0094, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); - io_sethandler(0x0102, 4, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); - io_sethandler(0x0190, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); + /* Add machine device to system. */ + device_add_ex(info, dev); - /* Set up the parallel port. */ - parallel_setup(0, 0x03bc); - - if (model == 2011) { + if (dev->model == 2011) { /* Force some configuration settings. */ video_card = VID_INTERNAL; mouse_type = MOUSE_PS2; @@ -518,8 +518,7 @@ ps1_setup(int model, romdef_t *bios) } /* Enable the PS/1 VGA controller. */ - if (video_card == VID_INTERNAL) - device_add(&ps1vga_device); + device_add(&ps1vga_device); /* Enable the builtin sound chip. */ device_add(&snd_device); @@ -528,24 +527,16 @@ ps1_setup(int model, romdef_t *bios) device_add(&fdc_at_actlow_device); /* Enable the builtin HDC. */ - if (hdc_type == HDC_INTERNAL) { - priv = device_add(&ps1_hdc_device); - - /* - * This is nasty, we will have to generalize this - * at some point for all PS/1 and/or PS/2 machines. - */ - ps1_hdc_inform(priv, dev); - } + if (hdc_type == HDC_INTERNAL) + device_add(&ps1_hdc_device); } - if (model == 2121) { + if (dev->model == 2121) { /* Force some configuration settings. */ video_card = VID_INTERNAL; mouse_type = MOUSE_PS2; - io_sethandler(0x00e0, 2, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); + io_sethandler(0x00e0, 2, ps1_read,NULL,NULL, ps1_write,NULL,NULL, dev); if (machine_get_config_int("rom_shell")) { DEBUG("PS1: loading ROM Shell..\n"); @@ -557,8 +548,7 @@ ps1_setup(int model, romdef_t *bios) } /* Initialize the video controller. */ - if (video_card == VID_INTERNAL) - device_add(&ibm_ps1_2121_device); + device_add(&ibm_ps1_2121_device); /* Enable the builtin sound chip. */ device_add(&snd_device); @@ -570,7 +560,7 @@ ps1_setup(int model, romdef_t *bios) device_add(&ide_isa_device); } - if (model == 2133) { + if (dev->model == 2133) { /* Force some configuration settings. */ hdc_type = HDC_INTERNAL; mouse_type = MOUSE_PS2; @@ -580,19 +570,23 @@ ps1_setup(int model, romdef_t *bios) /* Enable the builtin IDE port. */ device_add(&ide_isa_device); + + nmi_mask = 0x80; } -} + io_sethandler(0x0091, 1, ps1_read,NULL,NULL, ps1_write,NULL,NULL, dev); + io_sethandler(0x0092, 1, ps1_read,NULL,NULL, ps1_write,NULL,NULL, dev); + io_sethandler(0x0094, 1, ps1_read,NULL,NULL, ps1_write,NULL,NULL, dev); + io_sethandler(0x0102, 4, ps1_read,NULL,NULL, ps1_write,NULL,NULL, dev); + io_sethandler(0x0190, 1, ps1_read,NULL,NULL, ps1_write,NULL,NULL, dev); -static void -ps1_common_init(const machine_t *model, void *arg) -{ - int i; + /* Set up the parallel port. */ + parallel_setup(0, 0x03bc); /* Hack to prevent Game from being initialized there. */ i = game_enabled; game_enabled = 0; - machine_common_init(model, arg); + machine_common_init(); game_enabled = i; mem_remap_top(384); @@ -611,6 +605,8 @@ ps1_common_init(const machine_t *model, void *arg) /* Audio uses ports 200h,202-207h, so only initialize gameport on 201h. */ if (game_enabled) device_add(&game_201_device); + + return(dev); } @@ -625,21 +621,74 @@ static const device_config_t ps1_config[] = { "Enabled", 1 }, { - "" + NULL } } }, { - "", "", -1 + NULL } }; -const device_t m_ps1_device = { - "PS/1", - 0, 0, +static const CPU cpus_ps1_m2011[] = { + { "286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1 }, + { NULL } +}; + +static const machine_t m2011_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, + MACHINE_VIDEO, + 512, 6144, 512, 64, -1, + {{"",cpus_ps1_m2011}} +}; + +const device_t m_ps1_2011 = { + "IBM PS/1 2011", + DEVICE_ROOT, + 2011, + L"ibm/ps1_2011", + ps1_init, ps1_close, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, + &m2011_info, + ps1_config +}; + + +static const machine_t m2121_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, + MACHINE_VIDEO, + 1, 6, 1, 64, -1, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_ps1_2121 = { + "IBM PS/1 2121", + DEVICE_ROOT, + 2121, + L"ibm/ps1_2121", + ps1_init, ps1_close, NULL, + NULL, NULL, NULL, + &m2121_info, + ps1_config +}; + + +static const machine_t m2133_info = { + MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, + 0, + 1, 64, 1, 128, -1, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_ps1_2133 = { + "IBM PS/1 2133", + DEVICE_ROOT, + 2133, + L"ibm/ps1_2133", + ps1_init, ps1_close, NULL, + NULL, NULL, NULL, + &m2133_info, ps1_config }; @@ -650,34 +699,5 @@ ps1_set_feedback(void *priv) { ps1_t *dev = (ps1_t *)priv; - dev->ps1_91 |= 0x01; -} - - -void -m_ps1_m2011_init(const machine_t *model, void *arg) -{ - ps1_common_init(model, arg); - - ps1_setup(2011, (romdef_t *)arg); -} - - -void -m_ps1_m2121_init(const machine_t *model, void *arg) -{ - ps1_common_init(model, arg); - - ps1_setup(2121, (romdef_t *)arg); -} - - -void -m_ps1_m2133_init(const machine_t *model, void *arg) -{ - ps1_common_init(model, arg); - - ps1_setup(2133, (romdef_t *)arg); - - nmi_mask = 0x80; + dev->reg_91 |= 0x01; } diff --git a/src/machines/m_ps1.h b/src/machines/m_ps1.h new file mode 100644 index 0000000..f3e0873 --- /dev/null +++ b/src/machines/m_ps1.h @@ -0,0 +1,64 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the IBM PS/1 machines. + * + * Version: @(#)m_ps1.h 1.0.1 2019/04/19 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef MACHINE_PS1_H +# define MACHINE_PS1_H + + +#ifdef EMU_DEVICE_H +extern const device_t m_ps1_2011; +extern const device_t m_ps1_2121; +extern const device_t m_ps1_2133; + +extern const device_t m_ps1_device; +extern const device_t ps1_hdc_device; +#endif + + +extern void ps1_set_feedback(void *); + + +#endif /*MACHINE_PS1_H*/ diff --git a/src/machines/m_ps1_hdc.c b/src/machines/m_ps1_hdc.c index 695605f..ee3de77 100644 --- a/src/machines/m_ps1_hdc.c +++ b/src/machines/m_ps1_hdc.c @@ -43,14 +43,14 @@ * Type table with the main code, so the user can only select * items from that list... * - * Version: @(#)m_ps1_hdc.c 1.0.9 2018/10/15 + * Version: @(#)m_ps1_hdc.c 1.0.11 2018/04/19 * * Author: Fred N. van Kempen, * * Based on my earlier HD20 driver for the EuroPC. * Thanks to Marco Bortolin for the help and feedback !! * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -102,6 +102,7 @@ #include "../ui/ui.h" #include "../plat.h" #include "machine.h" +#include "m_ps1.h" #define HDC_TIME (50*TIMER_USEC) @@ -1379,8 +1380,32 @@ hdc_write(uint16_t port, uint8_t val, void *priv) } +static void +hdc_close(void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + drive_t *drive; + int d; + + /* Remove the I/O handler. */ + io_removehandler(dev->base, 5, + hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + + /* Close all disks and their images. */ + for (d = 0; d < PS1_HDD_NUM; d++) { + drive = &dev->drives[d]; + + if (drive->present) + hdd_image_close(drive->hdd_num); + } + + /* Release the device. */ + free(dev); +} + + static void * -ps1_hdc_init(const device_t *info) +hdc_init_ps1(const device_t *info, void *parent) { drive_t *drive; hdc_t *dev; @@ -1389,6 +1414,7 @@ ps1_hdc_init(const device_t *info) /* Allocate and initialize device block. */ dev = (hdc_t *)mem_alloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); + dev->sys = parent; /* Set up controller parameters for PS/1 2011. */ dev->base = 0x0320; @@ -1446,56 +1472,12 @@ ps1_hdc_init(const device_t *info) } -static void -ps1_hdc_close(void *priv) -{ - hdc_t *dev = (hdc_t *)priv; - drive_t *drive; - int d; - - /* Remove the I/O handler. */ - io_removehandler(dev->base, 5, - hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); - - /* Close all disks and their images. */ - for (d = 0; d < PS1_HDD_NUM; d++) { - drive = &dev->drives[d]; - - if (drive->present) - hdd_image_close(drive->hdd_num); - } - - /* Release the device. */ - free(dev); -} - - const device_t ps1_hdc_device = { "PS/1 2011 Fixed Disk Controller", DEVICE_ISA | DEVICE_PS2, 0, - ps1_hdc_init, ps1_hdc_close, NULL, + NULL, + hdc_init_ps1, hdc_close, NULL, NULL, NULL, NULL, NULL, NULL }; - - -/* - * Very nasty. - * - * The PS/1 systems employ a feedback system where external - * cards let the system know they were 'addressed' by setting - * their Card Selected Flag (CSF) in register 0x0091. Driver - * software can test this register to see if they are talking - * to hardware or not. - * - * This means, that we must somehow do the same, and yes, I - * agree that the current solution is nasty. - */ -void -ps1_hdc_inform(void *priv, void *arg) -{ - hdc_t *dev = (hdc_t *)priv; - - dev->sys = arg; -} diff --git a/src/machines/m_ps2_isa.c b/src/machines/m_ps2_isa.c index 428dc66..9f804a4 100644 --- a/src/machines/m_ps2_isa.c +++ b/src/machines/m_ps2_isa.c @@ -8,7 +8,7 @@ * * Implementation of ISA-based PS/2 machines. * - * Version: @(#)m_ps2_isa.c 1.0.15 2019/02/16 + * Version: @(#)m_ps2_isa.c 1.0.16 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "../emu.h" #include "../cpu/cpu.h" @@ -59,18 +60,27 @@ #include "machine.h" -static uint8_t ps2_94, ps2_102, ps2_103, ps2_104, ps2_105, ps2_190; +typedef struct { + uint8_t type; + uint8_t reg_94, + reg_102, + reg_103, + reg_104, + reg_105, + reg_190; -static struct { - uint8_t status, int_status; - uint8_t attention, ctrl; -} ps2_hd; + uint8_t hd_status, + hd_istat; + uint8_t hd_attn, + hd_ctrl; +} ps2_t; static uint8_t ps2_read(uint16_t port, void *priv) { + ps2_t *dev = (ps2_t *)priv; uint8_t ret = 0xff; switch (port) { @@ -79,52 +89,54 @@ ps2_read(uint16_t port, void *priv) break; case 0x0094: - ret = ps2_94; + ret = dev->reg_94; break; case 0x0102: - ret = ps2_102 | 8; + ret = dev->reg_102 | 8; break; case 0x0103: - ret = ps2_103; + ret = dev->reg_103; break; case 0x0104: - ret = ps2_104; + ret = dev->reg_104; break; case 0x0105: - ret = ps2_105; + ret = dev->reg_105; break; case 0x0190: - ret = ps2_190; + ret = dev->reg_190; break; case 0x0322: - ret = ps2_hd.status; + ret = dev->hd_status; break; case 0x0324: - ret = ps2_hd.int_status; - ps2_hd.int_status &= ~0x02; + ret = dev->hd_istat; + dev->hd_istat &= ~0x02; break; default: break; } - return ret; + return(ret); } static void ps2_write(uint16_t port, uint8_t val, void *priv) { + ps2_t *dev = (ps2_t *)priv; + switch (port) { case 0x0094: - ps2_94 = val; + dev->reg_94 = val; break; case 0x0102: @@ -147,77 +159,128 @@ ps2_write(uint16_t port, uint8_t val, void *priv) parallel_setup(0, 0x0278); break; } - ps2_102 = val; + dev->reg_102 = val; break; case 0x0103: - ps2_103 = val; + dev->reg_103 = val; break; case 0x0104: - ps2_104 = val; + dev->reg_104 = val; break; case 0x0105: - ps2_105 = val; + dev->reg_105 = val; break; case 0x0190: - ps2_190 = val; + dev->reg_190 = val; break; case 0x0322: - ps2_hd.ctrl = val; + dev->hd_ctrl = val; if (val & 0x80) - ps2_hd.status |= 0x02; + dev->hd_status |= 0x02; break; case 0x0324: - ps2_hd.attention = val & 0xf0; - if (ps2_hd.attention) - ps2_hd.status = 0x14; + dev->hd_attn = val & 0xf0; + if (dev->hd_attn) + dev->hd_status = 0x14; break; } } static void -ps2_common_init(void) +common_init(ps2_t *dev) { - io_sethandler(0x0091, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, NULL); - io_sethandler(0x0094, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, NULL); - io_sethandler(0x0102, 4, ps2_read,NULL,NULL, ps2_write,NULL,NULL, NULL); - io_sethandler(0x0190, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, NULL); + io_sethandler(0x0091, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, dev); + io_sethandler(0x0094, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, dev); + io_sethandler(0x0102, 4, ps2_read,NULL,NULL, ps2_write,NULL,NULL, dev); + io_sethandler(0x0190, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, dev); - io_sethandler(0x0320, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, NULL); - io_sethandler(0x0322, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, NULL); - io_sethandler(0x0324, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, NULL); + io_sethandler(0x0320, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, dev); + io_sethandler(0x0322, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, dev); + io_sethandler(0x0324, 1, ps2_read,NULL,NULL, ps2_write,NULL,NULL, dev); port_92_reset(); port_92_add(); - ps2_190 = 0; + dev->reg_190 = 0; parallel_setup(0, 0x03bc); - - memset(&ps2_hd, 0x00, sizeof(ps2_hd)); } -void -m_ps2_m30_286_init(const machine_t *model, void *arg) +static void +ps2_close(void *priv) { - machine_common_init(model, arg); + ps2_t *dev = (ps2_t *)priv; - device_add(&fdc_at_ps1_device); + free(dev); +} + + +static void * +ps2_init(const device_t *info, void *arg) +{ + ps2_t *dev; + + dev = (ps2_t *)mem_alloc(sizeof(ps2_t)); + memset(dev, 0x00, sizeof(ps2_t)); + dev->type = info->local; + + /* Add machine device to system. */ + device_add_ex(info, dev); + + machine_common_init(); pit_set_out_func(&pit, 1, pit_refresh_timer_at); dma16_init(); pic2_init(); - ps2_common_init(); + device_add(&ps_nvr_device); device_add(&keyboard_ps2_device); - device_add(&ps_nvr_device); - device_add(&ps1vga_device); + + device_add(&fdc_at_ps1_device); + + switch(dev->type) { + case 0: /* Model 30/286 */ + device_add(&ps1vga_device); + break; + } + + common_init(dev); + + return(dev); } + + +static const CPU cpus_ps2_m30_286[] = { + { "286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1 }, + { "286/12", CPU_286, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2 }, + { "286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2 }, + { "286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3 }, + { NULL } +}; + +static const machine_t m30_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, + MACHINE_VIDEO, + 1, 16, 1, 64, -1, + {{"",cpus_ps2_m30_286}} +}; + +const device_t m_ps2_m30_286 = { + "IBM PS/2 M30/286", + DEVICE_ROOT, + 0, + L"ibm/ps2_m30_286", + ps2_init, ps2_close, NULL, + NULL, NULL, NULL, + &m30_info, + NULL +}; diff --git a/src/machines/m_ps2_mca.c b/src/machines/m_ps2_mca.c index a997642..9c05827 100644 --- a/src/machines/m_ps2_mca.c +++ b/src/machines/m_ps2_mca.c @@ -48,7 +48,7 @@ * * This works around the timing loop mentioned above. * - * Version: @(#)m_ps2_mca.c 1.0.20 2019/02/16 + * Version: @(#)m_ps2_mca.c 1.0.21 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -79,6 +79,7 @@ #include #include #include +#include #include #include "../emu.h" #include "../cpu/cpu.h" @@ -110,13 +111,16 @@ #define PS2_CARD_SETUP 0x08 -typedef struct { +typedef struct _ps2_ { + int type; + uint8_t adapter_setup; uint8_t option[4]; uint8_t pos_vga; uint8_t setup; uint8_t sys_ctrl_port_a; - uint8_t subaddr_lo, subaddr_hi; + uint8_t subaddr_lo, + subaddr_hi; uint8_t memory_bank[8]; @@ -124,11 +128,11 @@ typedef struct { mem_map_t shadow_mapping; mem_map_t split_mapping; - mem_map_t expansion_mapping; + mem_map_t exp_mapping; mem_map_t cache_mapping; - uint8_t (*planar_read)(uint16_t port); - void (*planar_write)(uint16_t port, uint8_t val); + uint8_t (*planar_read)(struct _ps2_ *, uint16_t port); + void (*planar_write)(struct _ps2_ *, uint16_t port, uint8_t val); uint8_t mem_regs[3]; @@ -139,81 +143,93 @@ typedef struct { uint8_t mem_2mb_pos_regs[8]; int pending_cache_miss; + + uint8_t cache[65536]; + int cache_valid[65536/8]; } ps2_t; -static ps2_t ps2; -static uint8_t ps2_cache[65536]; -static int ps2_cache_valid[65536/8]; +static void *saved_dev = NULL; /* needed for clear_cache() */ static uint8_t -read_cache_ram(uint32_t addr, void *priv) +cache_read(uint32_t addr, void *priv) { + ps2_t *dev = (ps2_t *)priv; + DBGLOG(1, "ps2_read_cache_ram: addr=%08x %i %04x:%04x\n", - addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + addr, dev->cache_valid[addr >> 3], CS,cpu_state.pc); - if (! ps2_cache_valid[addr >> 3]) { - ps2_cache_valid[addr >> 3] = 1; - ps2.mem_regs[2] |= 0x80; + if (! dev->cache_valid[addr >> 3]) { + dev->cache_valid[addr >> 3] = 1; + dev->mem_regs[2] |= 0x80; } else - ps2.pending_cache_miss = 0; + dev->pending_cache_miss = 0; - return ps2_cache[addr]; + return dev->cache[addr]; } static uint16_t -read_cache_ramw(uint32_t addr, void *priv) +cache_readw(uint32_t addr, void *priv) { + ps2_t *dev = (ps2_t *)priv; + DBGLOG(1, "ps2_read_cache_ramw: addr=%08x %i %04x:%04x\n", - addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + addr, dev->cache_valid[addr >> 3], CS,cpu_state.pc); - if (! ps2_cache_valid[addr >> 3]) { - ps2_cache_valid[addr >> 3] = 1; - ps2.mem_regs[2] |= 0x80; + if (! dev->cache_valid[addr >> 3]) { + dev->cache_valid[addr >> 3] = 1; + dev->mem_regs[2] |= 0x80; } else - ps2.pending_cache_miss = 0; + dev->pending_cache_miss = 0; - return *((uint16_t *)(ps2_cache+addr)); + return *((uint16_t *)(dev->cache+addr)); } static uint32_t -read_cache_raml(uint32_t addr, void *priv) +cache_readl(uint32_t addr, void *priv) { + ps2_t *dev = (ps2_t *)priv; + DBGLOG(1, "ps2_read_cache_raml: addr=%08x %i %04x:%04x\n", - addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + addr, dev->cache_valid[addr >> 3], CS,cpu_state.pc); - if (! ps2_cache_valid[addr >> 3]) { - ps2_cache_valid[addr >> 3] = 1; - ps2.mem_regs[2] |= 0x80; + if (! dev->cache_valid[addr >> 3]) { + dev->cache_valid[addr >> 3] = 1; + dev->mem_regs[2] |= 0x80; } else - ps2.pending_cache_miss = 0; + dev->pending_cache_miss = 0; - return *((uint32_t *)ps2_cache+addr); + return *((uint32_t *)dev->cache+addr); } static void -write_cache_ram(uint32_t addr, uint8_t val, void *priv) +cache_write(uint32_t addr, uint8_t val, void *priv) { + ps2_t *dev = (ps2_t *)priv; + DBGLOG(1, "ps2_write_cache_ram: addr=%08x val=%02x %04x:%04x %i\n", addr, val, CS,cpu_state.pc, ins); - ps2_cache[addr] = val; + dev->cache[addr] = val; } void ps2_cache_clean(void) { - memset(ps2_cache_valid, 0, sizeof(ps2_cache_valid)); + ps2_t *dev = saved_dev; + + if (dev) + memset(dev->cache_valid, 0x00, sizeof(dev->cache_valid)); } static uint8_t -read_shadow_ram(uint32_t addr, void *priv) +shadow_read(uint32_t addr, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; @@ -222,7 +238,7 @@ read_shadow_ram(uint32_t addr, void *priv) static uint16_t -read_shadow_ramw(uint32_t addr, void *priv) +shadow_readw(uint32_t addr, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; @@ -231,7 +247,7 @@ read_shadow_ramw(uint32_t addr, void *priv) static uint32_t -read_shadow_raml(uint32_t addr, void *priv) +shadow_readl(uint32_t addr, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; @@ -240,7 +256,7 @@ read_shadow_raml(uint32_t addr, void *priv) static void -write_shadow_ram(uint32_t addr, uint8_t val, void *priv) +shadow_write(uint32_t addr, uint8_t val, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; @@ -249,7 +265,7 @@ write_shadow_ram(uint32_t addr, uint8_t val, void *priv) static void -write_shadow_ramw(uint32_t addr, uint16_t val, void *priv) +shadow_writew(uint32_t addr, uint16_t val, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; @@ -258,7 +274,7 @@ write_shadow_ramw(uint32_t addr, uint16_t val, void *priv) static void -write_shadow_raml(uint32_t addr, uint32_t val, void *priv) +shadow_writel(uint32_t addr, uint32_t val, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; @@ -267,221 +283,1042 @@ write_shadow_raml(uint32_t addr, uint32_t val, void *priv) static uint8_t -read_split_ram(uint32_t addr, void *priv) +split_read(uint32_t addr, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + ps2_t *dev = (ps2_t *)priv; + + addr = (addr % (dev->split_size << 10)) + dev->split_phys; return mem_read_ram(addr, priv); } static uint16_t -read_split_ramw(uint32_t addr, void *priv) +split_readw(uint32_t addr, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + ps2_t *dev = (ps2_t *)priv; + + addr = (addr % (dev->split_size << 10)) + dev->split_phys; return mem_read_ramw(addr, priv); } static uint32_t -read_split_raml(uint32_t addr, void *priv) +split_readl(uint32_t addr, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + ps2_t *dev = (ps2_t *)priv; + + addr = (addr % (dev->split_size << 10)) + dev->split_phys; return mem_read_raml(addr, priv); } static void -write_split_ram(uint32_t addr, uint8_t val, void *priv) +split_write(uint32_t addr, uint8_t val, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + ps2_t *dev = (ps2_t *)priv; + + addr = (addr % (dev->split_size << 10)) + dev->split_phys; mem_write_ram(addr, val, priv); } static void -write_split_ramw(uint32_t addr, uint16_t val, void *priv) +split_writew(uint32_t addr, uint16_t val, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + ps2_t *dev = (ps2_t *)priv; + + addr = (addr % (dev->split_size << 10)) + dev->split_phys; mem_write_ramw(addr, val, priv); } static void -write_split_raml(uint32_t addr, uint32_t val, void *priv) +split_writel(uint32_t addr, uint32_t val, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + ps2_t *dev = (ps2_t *)priv; + + addr = (addr % (dev->split_size << 10)) + dev->split_phys; mem_write_raml(addr, val, priv); } static uint8_t -mem_expansion_read(int port, void *p) +exp_read(int port, void *priv) { - return ps2.mem_pos_regs[port & 7]; + ps2_t *dev = (ps2_t *)priv; + + return dev->mem_pos_regs[port & 7]; } static void -mem_expansion_write(int port, uint8_t val, void *p) +exp_write(int port, uint8_t val, void *priv) { + ps2_t *dev = (ps2_t *)priv; + if (port < 0x102 || port == 0x104) return; - ps2.mem_pos_regs[port & 7] = val; + dev->mem_pos_regs[port & 7] = val; - if (ps2.mem_pos_regs[2] & 1) - mem_map_enable(&ps2.expansion_mapping); + if (dev->mem_pos_regs[2] & 1) + mem_map_enable(&dev->exp_mapping); else - mem_map_disable(&ps2.expansion_mapping); + mem_map_disable(&dev->exp_mapping); } static void -mem_fffc_init(int start_mb) +mem_fffc_init(ps2_t *dev, int start_mb) { - uint32_t planar_size, expansion_start; + uint32_t planar_size, exp_start; if (start_mb == 2) { planar_size = 0x160000; - expansion_start = 0x260000; + exp_start = 0x260000; } else { planar_size = (start_mb - 1) << 20; - expansion_start = start_mb << 20; + exp_start = start_mb << 20; } mem_map_set_addr(&ram_high_mapping, 0x100000, planar_size); - ps2.mem_pos_regs[0] = 0xff; - ps2.mem_pos_regs[1] = 0xfc; + dev->mem_pos_regs[0] = 0xff; + dev->mem_pos_regs[1] = 0xfc; switch ((mem_size / 1024) - start_mb) { case 1: - ps2.mem_pos_regs[4] = 0xfc; /* 11 11 11 00 = 0 0 0 1 */ + dev->mem_pos_regs[4] = 0xfc; /* 11 11 11 00 = 0 0 0 1 */ break; case 2: - ps2.mem_pos_regs[4] = 0xfe; /* 11 11 11 10 = 0 0 0 2 */ + dev->mem_pos_regs[4] = 0xfe; /* 11 11 11 10 = 0 0 0 2 */ break; case 3: - ps2.mem_pos_regs[4] = 0xf2; /* 11 11 00 10 = 0 0 1 2 */ + dev->mem_pos_regs[4] = 0xf2; /* 11 11 00 10 = 0 0 1 2 */ break; case 4: - ps2.mem_pos_regs[4] = 0xfa; /* 11 11 10 10 = 0 0 2 2 */ + dev->mem_pos_regs[4] = 0xfa; /* 11 11 10 10 = 0 0 2 2 */ break; case 5: - ps2.mem_pos_regs[4] = 0xca; /* 11 00 10 10 = 0 1 2 2 */ + dev->mem_pos_regs[4] = 0xca; /* 11 00 10 10 = 0 1 2 2 */ break; case 6: - ps2.mem_pos_regs[4] = 0xea; /* 11 10 10 10 = 0 2 2 2 */ + dev->mem_pos_regs[4] = 0xea; /* 11 10 10 10 = 0 2 2 2 */ break; case 7: - ps2.mem_pos_regs[4] = 0x2a; /* 00 10 10 10 = 1 2 2 2 */ + dev->mem_pos_regs[4] = 0x2a; /* 00 10 10 10 = 1 2 2 2 */ break; case 8: - ps2.mem_pos_regs[4] = 0xaa; /* 10 10 10 10 = 2 2 2 2 */ + dev->mem_pos_regs[4] = 0xaa; /* 10 10 10 10 = 2 2 2 2 */ break; } - mca_add(mem_expansion_read, mem_expansion_write, NULL); - mem_map_add(&ps2.expansion_mapping, - expansion_start, (mem_size - (start_mb << 10)) << 10, + mca_add(exp_read, exp_write, dev); + + mem_map_add(&dev->exp_mapping, exp_start, (mem_size - (start_mb << 10)) << 10, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, - &ram[expansion_start], MEM_MAPPING_INTERNAL, NULL); - mem_map_disable(&ps2.expansion_mapping); + &ram[exp_start], MEM_MAPPING_INTERNAL, dev); + mem_map_disable(&dev->exp_mapping); +} + + +static uint8_t +model_50_read(ps2_t *dev, uint16_t port) +{ + uint8_t ret = 0xff; + + switch (port) { + case 0x0100: + break; + + case 0x0101: + ret = 0xfb; + break; + + case 0x0102: + ret = dev->option[0]; + break; + + case 0x0103: + ret = dev->option[1]; + break; + + case 0x0104: + ret = dev->option[2]; + break; + + case 0x0105: + ret = dev->option[3]; + break; + + case 0x0106: + ret = dev->subaddr_lo; + break; + + case 0x0107: + ret = dev->subaddr_hi; + break; + } + + return ret; +} + + +static void +model_50_write(ps2_t *dev, uint16_t port, uint8_t val) +{ + switch (port) { + case 0x0100: + dev->io_id = val; + break; + + case 0x0101: + break; + + case 0x0102: +#if 0 + serial_remove(0); +#endif + if (val & 0x04) { + if (val & 0x08) + serial_setup(0, SERIAL1_ADDR, SERIAL1_IRQ); + else + serial_setup(0, SERIAL2_ADDR, SERIAL2_IRQ); + } + + if (val & 0x10) switch ((val >> 5) & 3) { + case 0: + parallel_setup(0, 0x03bc); + break; + + case 1: + parallel_setup(0, 0x0378); + break; + + case 2: + parallel_setup(0, 0x0278); + break; + } + dev->option[0] = val; + break; + + case 0x0103: + dev->option[1] = val; + break; + + case 0x0104: + dev->option[2] = val; + break; + + case 0x0105: + dev->option[3] = val; + break; + + case 0x0106: + dev->subaddr_lo = val; + break; + + case 0x0107: + dev->subaddr_hi = val; + break; + } +} + + +static void +model_50_init(ps2_t *dev) +{ + mem_remap_top(384); + + mca_init(4); + + dev->planar_read = model_50_read; + dev->planar_write = model_50_write; + + if (mem_size > 2048) { + /* Only 2 MB supported on planar, create a memory expansion card for the rest */ + mem_fffc_init(dev, 2); + } + + if (video_card == VID_INTERNAL) + device_add(&ps1vga_device); +} + + +static uint8_t +model_55sx_read(ps2_t *dev, uint16_t port) +{ + uint8_t ret = 0xff; + + switch (port) { + case 0x0100: + break; + + case 0x0101: + ret = 0xfb; + break; + + case 0x0102: + ret = dev->option[0]; + break; + + case 0x0103: + ret = dev->option[1]; + break; + + case 0x0104: + ret = dev->memory_bank[dev->option[3] & 7]; + break; + + case 0x0105: + ret = dev->option[3]; + break; + + case 0x0106: + ret = dev->subaddr_lo; + break; + + case 0x0107: + ret = dev->subaddr_hi; + break; + } + + return ret; +} + + +static void +model_55sx_write(ps2_t *dev, uint16_t port, uint8_t val) +{ + switch (port) { + case 0x0100: + dev->io_id = val; + break; + + case 0x0101: + break; + + case 0x0102: +#if 0 + serial_remove(0); +#endif + if (val & 0x04) { + if (val & 0x08) + serial_setup(0, SERIAL1_ADDR, SERIAL1_IRQ); + else + serial_setup(0, SERIAL2_ADDR, SERIAL2_IRQ); + } + + if (val & 0x10) switch ((val >> 5) & 3) { + case 0: + parallel_setup(0, 0x03bc); + break; + + case 1: + parallel_setup(0, 0x0378); + break; + + case 2: + parallel_setup(0, 0x0278); + break; + } + dev->option[0] = val; + break; + + case 0x0103: + dev->option[1] = val; + break; + + case 0x0104: + dev->memory_bank[dev->option[3] & 7] &= ~0xf; + dev->memory_bank[dev->option[3] & 7] |= (val & 0xf); + + DBGLOG(1, "Write memory bank %i %02x\n", dev->option[3] & 7, val); + break; + + case 0x0105: + DBGLOG(1, "Write POS3 %02x\n", val); + dev->option[3] = val; + shadowbios = !(val & 0x10); + shadowbios_write = val & 0x10; + + if (shadowbios) { + mem_set_mem_state(0xe0000, 0x20000, + MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + mem_map_disable(&dev->shadow_mapping); + } else { + mem_set_mem_state(0xe0000, 0x20000, + MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + mem_map_enable(&dev->shadow_mapping); + } + + if ((dev->option[1] & 1) && !(dev->option[3] & 0x20)) + mem_set_mem_state(mem_size * 1024, 256 * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state(mem_size * 1024, 256 * 1024, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + + case 0x0106: + dev->subaddr_lo = val; + break; + + case 0x0107: + dev->subaddr_hi = val; + break; + } +} + + +static void +model_55sx_init(ps2_t *dev) +{ + mem_map_add(&dev->shadow_mapping, (mem_size+256) * 1024, 128*1024, + shadow_read,shadow_readw,shadow_readl, + shadow_write, shadow_writew,shadow_writel, + &ram[0xe0000], MEM_MAPPING_INTERNAL, dev); + + mem_remap_top(256); + dev->option[3] = 0x10; + + memset(dev->memory_bank, 0xf0, 8); + switch (mem_size >> 10) { + case 1: + dev->memory_bank[0] = 0x61; + break; + + case 2: + dev->memory_bank[0] = 0x51; + break; + + case 3: + dev->memory_bank[0] = 0x51; + dev->memory_bank[1] = 0x61; + break; + + case 4: + dev->memory_bank[0] = 0x51; + dev->memory_bank[1] = 0x51; + break; + + case 5: + dev->memory_bank[0] = 0x01; + dev->memory_bank[1] = 0x61; + break; + + case 6: + dev->memory_bank[0] = 0x01; + dev->memory_bank[1] = 0x51; + break; + + case 7: /*Not supported*/ + dev->memory_bank[0] = 0x01; + dev->memory_bank[1] = 0x51; + break; + + case 8: + dev->memory_bank[0] = 0x01; + dev->memory_bank[1] = 0x01; + break; + } + + mca_init(4); + + dev->planar_read = model_55sx_read; + dev->planar_write = model_55sx_write; + + if (video_card == VID_INTERNAL) + device_add(&ps1vga_device); +} + + +static void +mem_encoding_update(ps2_t *dev) +{ + mem_map_disable(&dev->split_mapping); + + dev->split_addr = ((uint32_t) (dev->mem_regs[0] & 0xf)) << 20; + + if (dev->mem_regs[1] & 2) { + mem_set_mem_state(0xe0000, 0x20000, + MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + DEBUG("PS/2 Model 80-111: ROM space enabled\n"); + } else { + mem_set_mem_state(0xe0000, 0x20000, + MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + DEBUG("PS/2 Model 80-111: ROM space disabled\n"); + } + + if (dev->mem_regs[1] & 4) { + mem_map_set_addr(&ram_low_mapping, 0x00000, 0x80000); + DEBUG("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); + } else { + mem_map_set_addr(&ram_low_mapping, 0x00000, 0xa0000); + DEBUG("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); + } + + if (! (dev->mem_regs[1] & 8)) { + if (dev->mem_regs[1] & 4) { + dev->split_size = 384; + dev->split_phys = 0x80000; + } else { + dev->split_size = 256; + dev->split_phys = 0xa0000; + } + + mem_map_set_exec(&dev->split_mapping, &ram[dev->split_phys]); + mem_map_set_addr(&dev->split_mapping, dev->split_addr, dev->split_size << 10); + + DEBUG("PS/2 Model 80-111: Split memory block enabled at %08X\n", dev->split_addr); + } else { + DEBUG("PS/2 Model 80-111: Split memory block disabled\n"); + } +} + + +static uint8_t +mem_encoding_read(uint16_t addr, void *priv) +{ + ps2_t *dev = (ps2_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0xe0: + ret = dev->mem_regs[0]; + break; + + case 0xe1: + ret = dev->mem_regs[1]; + break; + } + + return ret; +} + + +static void +mem_encoding_write(uint16_t addr, uint8_t val, void *priv) +{ + ps2_t *dev = (ps2_t *)priv; + + switch (addr) { + case 0xe0: + dev->mem_regs[0] = val; + break; + + case 0xe1: + dev->mem_regs[1] = val; + break; + } + + mem_encoding_update(dev); +} + + +static uint8_t +mem_encoding_read_cached(uint16_t addr, void *priv) +{ + ps2_t *dev = (ps2_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0xe0: + ret = dev->mem_regs[0]; + break; + + case 0xe1: + ret = dev->mem_regs[1]; + break; + + case 0xe2: + ret = dev->mem_regs[2]; + break; + } + + return ret; +} + + +static void +mem_encoding_write_cached(uint16_t addr, uint8_t val, void *priv) +{ + ps2_t *dev = (ps2_t *)priv; + uint8_t old; + + switch (addr) { + case 0xe0: + dev->mem_regs[0] = val; + break; + + case 0xe1: + dev->mem_regs[1] = val; + break; + + case 0xe2: + old = dev->mem_regs[2]; + dev->mem_regs[2] = (dev->mem_regs[2] & 0x80) | (val & ~0x88); + if (val & 2) { + DBGLOG(1, "Clear latch - %i\n", dev->pending_cache_miss); + if (dev->pending_cache_miss) + dev->mem_regs[2] |= 0x80; + else + dev->mem_regs[2] &= ~0x80; + dev->pending_cache_miss = 0; + } + + if ((val & 0x21) == 0x20 && (old & 0x21) != 0x20) + dev->pending_cache_miss = 1; + if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) + ps2_cache_clean(); +#if 1 +// FIXME: Look into this!!! + if (val & 0x01) + ram_mid_mapping.flags |= MEM_MAPPING_ROM; + else + ram_mid_mapping.flags &= ~MEM_MAPPING_ROM; +#endif + break; + } + + DBGLOG(1, "mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", + addr, val, CS,cpu_state.pc, dev->mem_regs[1],dev->mem_regs[2]); + mem_encoding_update(dev); + + if ((dev->mem_regs[1] & 0x10) && (dev->mem_regs[2] & 0x21) == 0x20) { + mem_map_disable(&ram_low_mapping); + mem_map_enable(&dev->cache_mapping); + } else { + mem_map_disable(&dev->cache_mapping); + mem_map_enable(&ram_low_mapping); + } + + flushmmucache(); +} + + +static uint8_t +model_70_read(ps2_t *dev, uint16_t port) +{ + uint8_t ret = 0xff; + + switch (port) { + case 0x0100: + break; + + case 0x0101: + ret = 0xf9; + break; + + case 0x0102: + ret = dev->option[0]; + break; + + case 0x0103: + ret = dev->option[1]; + break; + + case 0x0104: + ret = dev->option[2]; + break; + + case 0x0105: + ret = dev->option[3]; + break; + + case 0x0106: + ret = dev->subaddr_lo; + break; + + case 0x0107: + ret = dev->subaddr_hi; + break; + + } + + return ret; +} + + +static void +model_70_write(ps2_t *dev, uint16_t port, uint8_t val) +{ + switch (port) { + case 0x0100: + break; + + case 0x0101: + break; + + case 0x0102: +#if 0 + serial_remove(0); +#endif + if (val & 0x04) { + if (val & 0x08) + serial_setup(0, SERIAL1_ADDR, SERIAL1_IRQ); + else + serial_setup(0, SERIAL2_ADDR, SERIAL2_IRQ); + } + + if (val & 0x10) switch ((val >> 5) & 3) { + case 0: + parallel_setup(0, 0x03bc); + break; + + case 1: + parallel_setup(0, 0x0378); + break; + + case 2: + parallel_setup(0, 0x0278); + break; + } + dev->option[0] = val; + break; + + case 0x0105: + dev->option[3] = val; + break; + + case 0x0106: + dev->subaddr_lo = val; + break; + + case 0x0107: + dev->subaddr_hi = val; + break; + } +} + + +static void +model_70_init(ps2_t *dev) +{ + int is_type4 = (dev->type == 74); + + dev->split_addr = mem_size * 1024; + mca_init(4); + + dev->planar_read = model_70_read; + dev->planar_write = model_70_write; + + device_add(&ps2_nvr_device); + + io_sethandler(0x00e0, 3, + mem_encoding_read_cached,NULL,NULL, + mem_encoding_write_cached,NULL,NULL, dev); + + dev->mem_regs[1] = 2; + + switch (mem_size >> 10) { + case 2: + dev->option[1] = 0xa6; + dev->option[2] = 0x01; + break; + + case 4: + dev->option[1] = 0xaa; + dev->option[2] = 0x01; + break; + + case 6: + dev->option[1] = 0xca; + dev->option[2] = 0x01; + break; + + case 8: + default: + dev->option[1] = 0xca; + dev->option[2] = 0x02; + break; + } + + if (is_type4) + dev->option[2] |= 0x04; /*486 CPU*/ + + mem_map_add(&dev->split_mapping, (mem_size+256) * 1024, 256*1024, + split_read,split_readw,split_readl, + split_write,split_writew,split_writel, + &ram[0xa0000], MEM_MAPPING_INTERNAL, dev); + mem_map_disable(&dev->split_mapping); + + mem_map_add(&dev->cache_mapping, 0, is_type4 ? (8 * 1024) : (64 * 1024), + cache_read,cache_readw,cache_readl, + cache_write,NULL,NULL, + dev->cache, MEM_MAPPING_INTERNAL, dev); + mem_map_disable(&dev->cache_mapping); + + if (mem_size > 8192) { + /* Only 8 MB supported on planar, create a memory expansion card for the rest */ + mem_fffc_init(dev, 8); + } + + if (video_card == VID_INTERNAL) + device_add(&ps1vga_device); +} + + +static uint8_t +model_80_read(ps2_t *dev, uint16_t port) +{ + uint8_t ret = 0xff; + + switch (port) { + case 0x0100: + break; + + case 0x0101: + ret = 0xfd; + break; + + case 0x0102: + ret = dev->option[0]; + break; + + case 0x0103: + ret = dev->option[1]; + break; + + case 0x0104: + ret = dev->option[2]; + break; + + case 0x0105: + ret = dev->option[3]; + break; + + case 0x0106: + ret = dev->subaddr_lo; + break; + + case 0x0107: + ret = dev->subaddr_hi; + break; + + } + + return ret; +} + + +static void +model_80_write(ps2_t *dev, uint16_t port, uint8_t val) +{ + switch (port) { + case 0x0100: + break; + + case 0x0101: + break; + + case 0x0102: +#if 0 + serial_remove(0); +#endif + if (val & 0x04) { + if (val & 0x08) + serial_setup(0, SERIAL1_ADDR, SERIAL1_IRQ); + else + serial_setup(0, SERIAL2_ADDR, SERIAL2_IRQ); + } + + if (val & 0x10) switch ((val >> 5) & 3) { + case 0: + parallel_setup(0, 0x03bc); + break; + + case 1: + parallel_setup(0, 0x0378); + break; + + case 2: + parallel_setup(0, 0x0278); + break; + } + dev->option[0] = val; + break; + + case 0x0103: + dev->option[1] = (dev->option[1] & 0x0f) | (val & 0xf0); + break; + + case 0x0104: + dev->option[2] = val; + break; + + case 0x0105: + dev->option[3] = val; + break; + + case 0x0106: + dev->subaddr_lo = val; + break; + + case 0x0107: + dev->subaddr_hi = val; + break; + } +} + + +static void +model_80_init(ps2_t *dev) +{ + int is_486 = (dev->type > 80); + + dev->split_addr = mem_size * 1024; + mca_init(8); + + dev->planar_read = model_80_read; + dev->planar_write = model_80_write; + + device_add(&ps2_nvr_device); + + io_sethandler(0x00e0, 2, + mem_encoding_read,NULL,NULL, + mem_encoding_write,NULL,NULL, dev); + + dev->mem_regs[1] = 2; + + switch (mem_size >> 10) { + case 1: + dev->option[1] = 0x0e; /* 11 10 = 0 2 */ + dev->mem_regs[1] = 0xd2; /* 01 = 1 (first) */ + dev->mem_regs[0] = 0xf0; /* 11 = invalid */ + break; + + case 2: + dev->option[1] = 0x0e; /* 11 10 = 0 2 */ + dev->mem_regs[1] = 0xc2; /* 00 = 2 */ + dev->mem_regs[0] = 0xf0; /* 11 = invalid */ + break; + + case 3: + dev->option[1] = 0x0a; /* 10 10 = 2 2 */ + dev->mem_regs[1] = 0xc2; /* 00 = 2 */ + dev->mem_regs[0] = 0xd0; /* 01 = 1 (first) */ + break; + + case 4: + default: + dev->option[1] = 0x0a; /* 10 10 = 2 2 */ + dev->mem_regs[1] = 0xc2; /* 00 = 2 */ + dev->mem_regs[0] = 0xc0; /* 00 = 2 */ + break; + } + + dev->mem_regs[0] |= ((mem_size / 1024) & 0x0f); + + mem_map_add(&dev->split_mapping, (mem_size+256) * 1024, 256*1024, + split_read,split_readw,split_readl, + split_write,split_writew,split_writel, + &ram[0xa0000], MEM_MAPPING_INTERNAL, dev); + mem_map_disable(&dev->split_mapping); + + if ((mem_size > 4096) && !is_486) { + /* Only 4 MB supported on planar, create a memory expansion card for the rest */ + mem_fffc_init(dev, 4); + } + + if (video_card == VID_INTERNAL) + device_add(&ps1vga_device); } static uint8_t ps2_mca_read(uint16_t port, void *priv) { + ps2_t *dev = (ps2_t *)priv; uint8_t ret = 0xff; switch (port) { case 0x0091: fatal("Read 91 setup=%02x adapter=%02x\n", - ps2.setup, ps2.adapter_setup); + dev->setup, dev->adapter_setup); /*NOTREACHED*/ case 0x0094: - ret = ps2.setup; + ret = dev->setup; break; case 0x0096: - ret = ps2.adapter_setup | 0x70; + ret = dev->adapter_setup | 0x70; break; case 0x0100: - if (!(ps2.setup & PS2_SETUP_IO)) - ret = ps2.planar_read(port); - else if (!(ps2.setup & PS2_SETUP_VGA)) + if (!(dev->setup & PS2_SETUP_IO)) + ret = dev->planar_read(dev, port); + else if (!(dev->setup & PS2_SETUP_VGA)) ret = 0xfd; - else if (ps2.adapter_setup & PS2_CARD_SETUP) + else if (dev->adapter_setup & PS2_CARD_SETUP) ret = mca_read(port); break; case 0x0101: - if (!(ps2.setup & PS2_SETUP_IO)) - ret = ps2.planar_read(port); - else if (!(ps2.setup & PS2_SETUP_VGA)) + if (!(dev->setup & PS2_SETUP_IO)) + ret = dev->planar_read(dev, port); + else if (!(dev->setup & PS2_SETUP_VGA)) ret = 0xef; - else if (ps2.adapter_setup & PS2_CARD_SETUP) + else if (dev->adapter_setup & PS2_CARD_SETUP) ret = mca_read(port); break; case 0x0102: - if (!(ps2.setup & PS2_SETUP_IO)) - ret = ps2.planar_read(port); - else if (!(ps2.setup & PS2_SETUP_VGA)) - ret = ps2.pos_vga; - else if (ps2.adapter_setup & PS2_CARD_SETUP) + if (!(dev->setup & PS2_SETUP_IO)) + ret = dev->planar_read(dev, port); + else if (!(dev->setup & PS2_SETUP_VGA)) + ret = dev->pos_vga; + else if (dev->adapter_setup & PS2_CARD_SETUP) ret = mca_read(port); break; case 0x0103: - if (!(ps2.setup & PS2_SETUP_IO)) - ret = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_CARD_SETUP)) + if (!(dev->setup & PS2_SETUP_IO)) + ret = dev->planar_read(dev, port); + else if ((dev->setup & PS2_SETUP_VGA) && (dev->adapter_setup & PS2_CARD_SETUP)) ret = mca_read(port); break; case 0x0104: - if (!(ps2.setup & PS2_SETUP_IO)) - ret = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_CARD_SETUP)) + if (!(dev->setup & PS2_SETUP_IO)) + ret = dev->planar_read(dev, port); + else if ((dev->setup & PS2_SETUP_VGA) && (dev->adapter_setup & PS2_CARD_SETUP)) ret = mca_read(port); break; case 0x0105: - if (!(ps2.setup & PS2_SETUP_IO)) - ret = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_CARD_SETUP)) + if (!(dev->setup & PS2_SETUP_IO)) + ret = dev->planar_read(dev, port); + else if ((dev->setup & PS2_SETUP_VGA) && (dev->adapter_setup & PS2_CARD_SETUP)) ret = mca_read(port); break; case 0x0106: - if (!(ps2.setup & PS2_SETUP_IO)) - ret = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_CARD_SETUP)) + if (!(dev->setup & PS2_SETUP_IO)) + ret = dev->planar_read(dev, port); + else if ((dev->setup & PS2_SETUP_VGA) && (dev->adapter_setup & PS2_CARD_SETUP)) ret = mca_read(port); break; case 0x0107: - if (!(ps2.setup & PS2_SETUP_IO)) - ret = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_CARD_SETUP)) + if (!(dev->setup & PS2_SETUP_IO)) + ret = dev->planar_read(dev, port); + else if ((dev->setup & PS2_SETUP_VGA) && (dev->adapter_setup & PS2_CARD_SETUP)) ret = mca_read(port); break; @@ -498,74 +1335,76 @@ ps2_mca_read(uint16_t port, void *priv) static void ps2_mca_write(uint16_t port, uint8_t val, void *priv) { + ps2_t *dev = (ps2_t *)priv; + DBGLOG(2, "ps2_write: port=%04x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc); switch (port) { case 0x0094: - ps2.setup = val; + dev->setup = val; break; case 0x0096: - ps2.adapter_setup = val; + dev->adapter_setup = val; mca_set_index(val & 7); break; case 0x0100: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_CARD_SETUP)) + if (!(dev->setup & PS2_SETUP_IO)) + dev->planar_write(dev, port, val); + else if ((dev->setup & PS2_SETUP_VGA) && (dev->adapter_setup & PS2_CARD_SETUP)) mca_write(port, val); break; case 0x0101: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_CARD_SETUP)) + if (!(dev->setup & PS2_SETUP_IO)) + dev->planar_write(dev, port, val); + else if ((dev->setup & PS2_SETUP_VGA) && (dev->setup & PS2_SETUP_VGA) && (dev->adapter_setup & PS2_CARD_SETUP)) mca_write(port, val); break; case 0x0102: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (!(ps2.setup & PS2_SETUP_VGA)) - ps2.pos_vga = val; - else if (ps2.adapter_setup & PS2_CARD_SETUP) + if (!(dev->setup & PS2_SETUP_IO)) + dev->planar_write(dev, port, val); + else if (!(dev->setup & PS2_SETUP_VGA)) + dev->pos_vga = val; + else if (dev->adapter_setup & PS2_CARD_SETUP) mca_write(port, val); break; case 0x0103: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_CARD_SETUP) + if (!(dev->setup & PS2_SETUP_IO)) + dev->planar_write(dev, port, val); + else if (dev->adapter_setup & PS2_CARD_SETUP) mca_write(port, val); break; case 0x0104: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_CARD_SETUP) + if (!(dev->setup & PS2_SETUP_IO)) + dev->planar_write(dev, port, val); + else if (dev->adapter_setup & PS2_CARD_SETUP) mca_write(port, val); break; case 0x0105: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_CARD_SETUP) + if (!(dev->setup & PS2_SETUP_IO)) + dev->planar_write(dev, port, val); + else if (dev->adapter_setup & PS2_CARD_SETUP) mca_write(port, val); break; case 0x0106: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_CARD_SETUP) + if (!(dev->setup & PS2_SETUP_IO)) + dev->planar_write(dev, port, val); + else if (dev->adapter_setup & PS2_CARD_SETUP) mca_write(port, val); break; case 0x0107: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_CARD_SETUP) + if (!(dev->setup & PS2_SETUP_IO)) + dev->planar_write(dev, port, val); + else if (dev->adapter_setup & PS2_CARD_SETUP) mca_write(port, val); break; } @@ -573,838 +1412,29 @@ ps2_mca_write(uint16_t port, uint8_t val, void *priv) static void -board_common_init(void) +ps2_close(void *priv) { - io_sethandler(0x0091, 1, - ps2_mca_read,NULL,NULL, ps2_mca_write,NULL,NULL, NULL); - io_sethandler(0x0094, 1, - ps2_mca_read,NULL,NULL, ps2_mca_write,NULL,NULL, NULL); - io_sethandler(0x0096, 1, - ps2_mca_read,NULL,NULL, ps2_mca_write,NULL,NULL, NULL); - io_sethandler(0x0100, 8, - ps2_mca_read,NULL,NULL, ps2_mca_write,NULL,NULL, NULL); + ps2_t *dev = (ps2_t *)priv; - port_92_reset(); + saved_dev = NULL; - port_92_add(); - - ps2.setup = 0xff; - - parallel_setup(0, 0x03bc); + free(dev); } -static uint8_t -model_50_read(uint16_t port) +static void * +ps2_init(const device_t *info, void *arg) { - uint8_t ret = 0xff; + ps2_t *dev; - switch (port) { - case 0x0100: - break; + dev = (ps2_t *)mem_alloc(sizeof(ps2_t)); + memset(dev, 0x00, sizeof(ps2_t)); + dev->type = info->local; - case 0x0101: - ret = 0xfb; - break; + /* Add machine device to system. */ + device_add_ex(info, dev); - case 0x0102: - ret = ps2.option[0]; - break; - - case 0x0103: - ret = ps2.option[1]; - break; - - case 0x0104: - ret = ps2.option[2]; - break; - - case 0x0105: - ret = ps2.option[3]; - break; - - case 0x0106: - ret = ps2.subaddr_lo; - break; - - case 0x0107: - ret = ps2.subaddr_hi; - break; - } - - return ret; -} - - -static void -model_50_write(uint16_t port, uint8_t val) -{ - switch (port) { - case 0x0100: - ps2.io_id = val; - break; - - case 0x0101: - break; - - case 0x0102: -#if 0 - serial_remove(0); -#endif - if (val & 0x04) { - if (val & 0x08) - serial_setup(0, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(0, SERIAL2_ADDR, SERIAL2_IRQ); - } - - if (val & 0x10) switch ((val >> 5) & 3) { - case 0: - parallel_setup(0, 0x03bc); - break; - - case 1: - parallel_setup(0, 0x0378); - break; - - case 2: - parallel_setup(0, 0x0278); - break; - } - ps2.option[0] = val; - break; - - case 0x0103: - ps2.option[1] = val; - break; - - case 0x0104: - ps2.option[2] = val; - break; - - case 0x0105: - ps2.option[3] = val; - break; - - case 0x0106: - ps2.subaddr_lo = val; - break; - - case 0x0107: - ps2.subaddr_hi = val; - break; - } -} - - -static void -model_50_init(void) -{ - board_common_init(); - - mem_remap_top(384); - - mca_init(4); - - ps2.planar_read = model_50_read; - ps2.planar_write = model_50_write; - - if (mem_size > 2048) { - /* Only 2 MB supported on planar, create a memory expansion card for the rest */ - mem_fffc_init(2); - } - - if (video_card == VID_INTERNAL) - device_add(&ps1vga_device); -} - - -static uint8_t -model_55sx_read(uint16_t port) -{ - uint8_t ret = 0xff; - - switch (port) { - case 0x0100: - break; - - case 0x0101: - ret = 0xfb; - break; - - case 0x0102: - ret = ps2.option[0]; - break; - - case 0x0103: - ret = ps2.option[1]; - break; - - case 0x0104: - ret = ps2.memory_bank[ps2.option[3] & 7]; - break; - - case 0x0105: - ret = ps2.option[3]; - break; - - case 0x0106: - ret = ps2.subaddr_lo; - break; - - case 0x0107: - ret = ps2.subaddr_hi; - break; - } - - return ret; -} - - -static void -model_55sx_write(uint16_t port, uint8_t val) -{ - switch (port) { - case 0x0100: - ps2.io_id = val; - break; - - case 0x0101: - break; - - case 0x0102: -#if 0 - serial_remove(0); -#endif - if (val & 0x04) { - if (val & 0x08) - serial_setup(0, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(0, SERIAL2_ADDR, SERIAL2_IRQ); - } - - if (val & 0x10) switch ((val >> 5) & 3) { - case 0: - parallel_setup(0, 0x03bc); - break; - - case 1: - parallel_setup(0, 0x0378); - break; - - case 2: - parallel_setup(0, 0x0278); - break; - } - ps2.option[0] = val; - break; - - case 0x0103: - ps2.option[1] = val; - break; - - case 0x0104: - ps2.memory_bank[ps2.option[3] & 7] &= ~0xf; - ps2.memory_bank[ps2.option[3] & 7] |= (val & 0xf); - - DBGLOG(1, "Write memory bank %i %02x\n", ps2.option[3] & 7, val); - break; - - case 0x0105: - DBGLOG(1, "Write POS3 %02x\n", val); - ps2.option[3] = val; - shadowbios = !(val & 0x10); - shadowbios_write = val & 0x10; - - if (shadowbios) { - mem_set_mem_state(0xe0000, 0x20000, - MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - mem_map_disable(&ps2.shadow_mapping); - } else { - mem_set_mem_state(0xe0000, 0x20000, - MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - mem_map_enable(&ps2.shadow_mapping); - } - - if ((ps2.option[1] & 1) && !(ps2.option[3] & 0x20)) - mem_set_mem_state(mem_size * 1024, 256 * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - else - mem_set_mem_state(mem_size * 1024, 256 * 1024, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - - case 0x0106: - ps2.subaddr_lo = val; - break; - - case 0x0107: - ps2.subaddr_hi = val; - break; - } -} - - -static void -model_55sx_init(void) -{ - board_common_init(); - - mem_map_add(&ps2.shadow_mapping, - (mem_size+256) * 1024, 128*1024, - read_shadow_ram, read_shadow_ramw, read_shadow_raml, - write_shadow_ram, write_shadow_ramw, write_shadow_raml, - &ram[0xe0000], MEM_MAPPING_INTERNAL, NULL); - - mem_remap_top(256); - ps2.option[3] = 0x10; - - memset(ps2.memory_bank, 0xf0, 8); - switch (mem_size >> 10) { - case 1: - ps2.memory_bank[0] = 0x61; - break; - - case 2: - ps2.memory_bank[0] = 0x51; - break; - - case 3: - ps2.memory_bank[0] = 0x51; - ps2.memory_bank[1] = 0x61; - break; - - case 4: - ps2.memory_bank[0] = 0x51; - ps2.memory_bank[1] = 0x51; - break; - - case 5: - ps2.memory_bank[0] = 0x01; - ps2.memory_bank[1] = 0x61; - break; - - case 6: - ps2.memory_bank[0] = 0x01; - ps2.memory_bank[1] = 0x51; - break; - - case 7: /*Not supported*/ - ps2.memory_bank[0] = 0x01; - ps2.memory_bank[1] = 0x51; - break; - - case 8: - ps2.memory_bank[0] = 0x01; - ps2.memory_bank[1] = 0x01; - break; - } - - mca_init(4); - - ps2.planar_read = model_55sx_read; - ps2.planar_write = model_55sx_write; - - if (video_card == VID_INTERNAL) - device_add(&ps1vga_device); -} - - -static void -mem_encoding_update(void) -{ - mem_map_disable(&ps2.split_mapping); - - ps2.split_addr = ((uint32_t) (ps2.mem_regs[0] & 0xf)) << 20; - - if (ps2.mem_regs[1] & 2) { - mem_set_mem_state(0xe0000, 0x20000, - MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - DEBUG("PS/2 Model 80-111: ROM space enabled\n"); - } else { - mem_set_mem_state(0xe0000, 0x20000, - MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - DEBUG("PS/2 Model 80-111: ROM space disabled\n"); - } - - if (ps2.mem_regs[1] & 4) { - mem_map_set_addr(&ram_low_mapping, 0x00000, 0x80000); - DEBUG("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); - } else { - mem_map_set_addr(&ram_low_mapping, 0x00000, 0xa0000); - DEBUG("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); - } - - if (! (ps2.mem_regs[1] & 8)) { - if (ps2.mem_regs[1] & 4) { - ps2.split_size = 384; - ps2.split_phys = 0x80000; - } else { - ps2.split_size = 256; - ps2.split_phys = 0xa0000; - } - - mem_map_set_exec(&ps2.split_mapping, &ram[ps2.split_phys]); - mem_map_set_addr(&ps2.split_mapping, ps2.split_addr, ps2.split_size << 10); - - DEBUG("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr); - } else { - DEBUG("PS/2 Model 80-111: Split memory block disabled\n"); - } -} - - -static uint8_t -mem_encoding_read(uint16_t addr, void *priv) -{ - uint8_t ret = 0xff; - - switch (addr) { - case 0xe0: - ret = ps2.mem_regs[0]; - break; - - case 0xe1: - ret = ps2.mem_regs[1]; - break; - } - - return ret; -} - - -static void -mem_encoding_write(uint16_t addr, uint8_t val, void *priv) -{ - switch (addr) { - case 0xe0: - ps2.mem_regs[0] = val; - break; - - case 0xe1: - ps2.mem_regs[1] = val; - break; - } - - mem_encoding_update(); -} - - -static uint8_t -mem_encoding_read_cached(uint16_t addr, void *priv) -{ - uint8_t ret = 0xff; - - switch (addr) { - case 0xe0: - ret = ps2.mem_regs[0]; - break; - - case 0xe1: - ret = ps2.mem_regs[1]; - break; - - case 0xe2: - ret = ps2.mem_regs[2]; - break; - } - - return ret; -} - - -static void -mem_encoding_write_cached(uint16_t addr, uint8_t val, void *priv) -{ - uint8_t old; - - switch (addr) { - case 0xe0: - ps2.mem_regs[0] = val; - break; - - case 0xe1: - ps2.mem_regs[1] = val; - break; - - case 0xe2: - old = ps2.mem_regs[2]; - ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); - if (val & 2) { - DBGLOG(1, "Clear latch - %i\n", ps2.pending_cache_miss); - if (ps2.pending_cache_miss) - ps2.mem_regs[2] |= 0x80; - else - ps2.mem_regs[2] &= ~0x80; - ps2.pending_cache_miss = 0; - } - - if ((val & 0x21) == 0x20 && (old & 0x21) != 0x20) - ps2.pending_cache_miss = 1; - if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) - ps2_cache_clean(); -#if 1 -// FIXME: Look into this!!! - if (val & 0x01) - ram_mid_mapping.flags |= MEM_MAPPING_ROM; - else - ram_mid_mapping.flags &= ~MEM_MAPPING_ROM; -#endif - break; - } - - DBGLOG(1, "mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", - addr, val, CS,cpu_state.pc, ps2.mem_regs[1],ps2.mem_regs[2]); - mem_encoding_update(); - - if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) { - mem_map_disable(&ram_low_mapping); - mem_map_enable(&ps2.cache_mapping); - } else { - mem_map_disable(&ps2.cache_mapping); - mem_map_enable(&ram_low_mapping); - } - - flushmmucache(); -} - - -static uint8_t -model_70_type3_read(uint16_t port) -{ - uint8_t ret = 0xff; - - switch (port) { - case 0x0100: - break; - - case 0x0101: - ret = 0xf9; - break; - - case 0x0102: - ret = ps2.option[0]; - break; - - case 0x0103: - ret = ps2.option[1]; - break; - - case 0x0104: - ret = ps2.option[2]; - break; - - case 0x0105: - ret = ps2.option[3]; - break; - - case 0x0106: - ret = ps2.subaddr_lo; - break; - - case 0x0107: - ret = ps2.subaddr_hi; - break; - - } - - return ret; -} - - -static void -model_70_type3_write(uint16_t port, uint8_t val) -{ - switch (port) { - case 0x0100: - break; - - case 0x0101: - break; - - case 0x0102: -#if 0 - serial_remove(0); -#endif - if (val & 0x04) { - if (val & 0x08) - serial_setup(0, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(0, SERIAL2_ADDR, SERIAL2_IRQ); - } - - if (val & 0x10) switch ((val >> 5) & 3) { - case 0: - parallel_setup(0, 0x03bc); - break; - - case 1: - parallel_setup(0, 0x0378); - break; - - case 2: - parallel_setup(0, 0x0278); - break; - } - ps2.option[0] = val; - break; - - case 0x0105: - ps2.option[3] = val; - break; - - case 0x0106: - ps2.subaddr_lo = val; - break; - - case 0x0107: - ps2.subaddr_hi = val; - break; - } -} - - -static void -model_70_type34_init(int is_type4) -{ - board_common_init(); - - ps2.split_addr = mem_size * 1024; - mca_init(4); - - ps2.planar_read = model_70_type3_read; - ps2.planar_write = model_70_type3_write; - - device_add(&ps2_nvr_device); - - io_sethandler(0x00e0, 3, - mem_encoding_read_cached,NULL,NULL, - mem_encoding_write_cached,NULL,NULL, NULL); - - ps2.mem_regs[1] = 2; - - switch (mem_size >> 10) { - case 2: - ps2.option[1] = 0xa6; - ps2.option[2] = 0x01; - break; - - case 4: - ps2.option[1] = 0xaa; - ps2.option[2] = 0x01; - break; - - case 6: - ps2.option[1] = 0xca; - ps2.option[2] = 0x01; - break; - - case 8: - default: - ps2.option[1] = 0xca; - ps2.option[2] = 0x02; - break; - } - - if (is_type4) - ps2.option[2] |= 0x04; /*486 CPU*/ - - mem_map_add(&ps2.split_mapping, - (mem_size+256) * 1024, 256*1024, - read_split_ram, read_split_ramw, read_split_raml, - write_split_ram, write_split_ramw, write_split_raml, - &ram[0xa0000], MEM_MAPPING_INTERNAL, NULL); - mem_map_disable(&ps2.split_mapping); - - mem_map_add(&ps2.cache_mapping, - 0, is_type4 ? (8 * 1024) : (64 * 1024), - read_cache_ram,read_cache_ramw,read_cache_raml, - write_cache_ram,NULL,NULL, - ps2_cache, MEM_MAPPING_INTERNAL, NULL); - mem_map_disable(&ps2.cache_mapping); - - if (mem_size > 8192) { - /* Only 8 MB supported on planar, create a memory expansion card for the rest */ - mem_fffc_init(8); - } - - if (video_card == VID_INTERNAL) - device_add(&ps1vga_device); -} - - -static uint8_t -model_80_read(uint16_t port) -{ - uint8_t ret = 0xff; - - switch (port) { - case 0x0100: - break; - - case 0x0101: - ret = 0xfd; - break; - - case 0x0102: - ret = ps2.option[0]; - break; - - case 0x0103: - ret = ps2.option[1]; - break; - - case 0x0104: - ret = ps2.option[2]; - break; - - case 0x0105: - ret = ps2.option[3]; - break; - - case 0x0106: - ret = ps2.subaddr_lo; - break; - - case 0x0107: - ret = ps2.subaddr_hi; - break; - - } - - return ret; -} - - -static void -model_80_write(uint16_t port, uint8_t val) -{ - switch (port) { - case 0x0100: - break; - - case 0x0101: - break; - - case 0x0102: -#if 0 - serial_remove(0); -#endif - if (val & 0x04) { - if (val & 0x08) - serial_setup(0, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(0, SERIAL2_ADDR, SERIAL2_IRQ); - } - - if (val & 0x10) switch ((val >> 5) & 3) { - case 0: - parallel_setup(0, 0x03bc); - break; - - case 1: - parallel_setup(0, 0x0378); - break; - - case 2: - parallel_setup(0, 0x0278); - break; - } - ps2.option[0] = val; - break; - - case 0x0103: - ps2.option[1] = (ps2.option[1] & 0x0f) | (val & 0xf0); - break; - - case 0x0104: - ps2.option[2] = val; - break; - - case 0x0105: - ps2.option[3] = val; - break; - - case 0x0106: - ps2.subaddr_lo = val; - break; - - case 0x0107: - ps2.subaddr_hi = val; - break; - } -} - - -static void -model_80_type2_init(int is_486) -{ - board_common_init(); - - ps2.split_addr = mem_size * 1024; - mca_init(8); - - ps2.planar_read = model_80_read; - ps2.planar_write = model_80_write; - - device_add(&ps2_nvr_device); - - io_sethandler(0x00e0, 2, - mem_encoding_read,NULL,NULL, - mem_encoding_write,NULL,NULL, NULL); - - ps2.mem_regs[1] = 2; - - switch (mem_size >> 10) { - case 1: - ps2.option[1] = 0x0e; /* 11 10 = 0 2 */ - ps2.mem_regs[1] = 0xd2; /* 01 = 1 (first) */ - ps2.mem_regs[0] = 0xf0; /* 11 = invalid */ - break; - - case 2: - ps2.option[1] = 0x0e; /* 11 10 = 0 2 */ - ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ - ps2.mem_regs[0] = 0xf0; /* 11 = invalid */ - break; - - case 3: - ps2.option[1] = 0x0a; /* 10 10 = 2 2 */ - ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ - ps2.mem_regs[0] = 0xd0; /* 01 = 1 (first) */ - break; - - case 4: - default: - ps2.option[1] = 0x0a; /* 10 10 = 2 2 */ - ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ - ps2.mem_regs[0] = 0xc0; /* 00 = 2 */ - break; - } - - ps2.mem_regs[0] |= ((mem_size/1024) & 0x0f); - - mem_map_add(&ps2.split_mapping, - (mem_size+256) * 1024, 256*1024, - read_split_ram,read_split_ramw,read_split_raml, - write_split_ram,write_split_ramw,write_split_raml, - &ram[0xa0000], MEM_MAPPING_INTERNAL, NULL); - mem_map_disable(&ps2.split_mapping); - - if ((mem_size > 4096) && !is_486) { - /* Only 4 MB supported on planar, create a memory expansion card for the rest */ - mem_fffc_init(4); - } - - if (video_card == VID_INTERNAL) - device_add(&ps1vga_device); -} - - -static void -ps2_common_init(const machine_t *model, void *arg) -{ - machine_common_init(model, arg); + machine_common_init(); dma16_init(); pic2_init(); @@ -1412,53 +1442,154 @@ ps2_common_init(const machine_t *model, void *arg) pit_ps2_init(); device_add(&ps_nvr_device); + device_add(&keyboard_ps2_mca_device); + device_add(&fdc_at_device); + parallel_setup(0, 0x03bc); + + port_92_reset(); + + port_92_add(); + nmi_mask = 0x80; + + io_sethandler(0x0091, 1, + ps2_mca_read,NULL,NULL, ps2_mca_write,NULL,NULL, dev); + io_sethandler(0x0094, 1, + ps2_mca_read,NULL,NULL, ps2_mca_write,NULL,NULL, dev); + io_sethandler(0x0096, 1, + ps2_mca_read,NULL,NULL, ps2_mca_write,NULL,NULL, dev); + io_sethandler(0x0100, 8, + ps2_mca_read,NULL,NULL, ps2_mca_write,NULL,NULL, dev); + + dev->setup = 0xff; + + switch(dev->type) { + case 50: /* Model 50 */ + model_50_init(dev); + break; + + case 55: /* Model 55SX */ + model_55sx_init(dev); + break; + + case 73: /* Model 70, Type 3 */ + case 74: /* Model 70, Type 4 */ + model_70_init(dev); + break; + + case 80: /* Model 80 */ + model_80_init(dev); + break; + } + + saved_dev = dev; + + return(dev); } -void -m_ps2_model_50_init(const machine_t *model, void *arg) -{ - ps2_common_init(model, arg); +static const CPU cpus_ps2_m30_286[] = { + { "286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1 }, + { "286/12", CPU_286, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2 }, + { "286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2 }, + { "286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3 }, + { "286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3 }, + { NULL } +}; - model_50_init(); -} +static const machine_t m50_info = { + MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, + 0, + 1, 10, 1, 64, -1, + {{"",cpus_ps2_m30_286}} //FIXME:??? is for M30-286! +}; + +const device_t m_ps2_m50 = { + "IBM PS/2 M50", + DEVICE_ROOT, + 50, + L"ibm/ps2_m50", + ps2_init, ps2_close, NULL, + NULL, NULL, NULL, + &m50_info, + NULL +}; -void -m_ps2_model_55sx_init(const machine_t *model, void *arg) -{ - ps2_common_init(model, arg); +static const machine_t m55_info = { + MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, + 0, + 1, 8, 1, 64, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; - model_55sx_init(); -} +const device_t m_ps2_m55sx = { + "IBM PS/2 M50", + DEVICE_ROOT, + 55, + L"ibm/ps2_m55sx", + ps2_init, ps2_close, NULL, + NULL, NULL, NULL, + &m55_info, + NULL +}; -void -m_ps2_model_70_type3_init(const machine_t *model, void *arg) -{ - ps2_common_init(model, arg); +static const machine_t m70_3_info = { + MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, + 0, + 2, 16, 2, 64, -1, + {{"Intel",cpus_i386DX},{"AMD",cpus_Am386DX},{"Cyrix",cpus_486DLC}} +}; - model_70_type34_init(0); -} +const device_t m_ps2_m70_3 = { + "IBM PS/2 M70 Type 3", + DEVICE_ROOT, + 73, + L"ibm/ps2_m70_type3", + ps2_init, ps2_close, NULL, + NULL, NULL, NULL, + &m70_3_info, + NULL +}; -void -m_ps2_model_70_type4_init(const machine_t *model, void *arg) -{ - ps2_common_init(model, arg); +static const machine_t m70_4_info = { + MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, + MACHINE_VIDEO, + 2, 16, 2, 64, -1, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; - model_70_type34_init(1); -} +const device_t m_ps2_m70_4 = { + "IBM PS/2 M70 Type 4", + DEVICE_ROOT, + 74, + L"ibm/ps2_m70_type4", + ps2_init, ps2_close, NULL, + NULL, NULL, NULL, + &m70_4_info, + NULL +}; -void -m_ps2_model_80_init(const machine_t *model, void *arg) -{ - ps2_common_init(model, arg); +static const machine_t m80_info = { + MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, + 0, + 1, 12, 1, 64, -1, + {{"Intel",cpus_i386DX},{"AMD",cpus_Am386DX},{"Cyrix",cpus_486DLC}} +}; - model_80_type2_init(0); -} +const device_t m_ps2_m80 = { + "IBM PS/2 M80", + DEVICE_ROOT, + 80, + L"ibm/ps2_m80", + ps2_init, ps2_close, NULL, + NULL, NULL, NULL, + &m80_info, + NULL +}; diff --git a/src/machines/m_scat.c b/src/machines/m_scat.c new file mode 100644 index 0000000..1079e4b --- /dev/null +++ b/src/machines/m_scat.c @@ -0,0 +1,209 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the C&T 82C235 ("SCAT") based machines. + * + * Version: @(#)m_scat.c 1.0.16 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Original by GreatPsycho for PCem. + * Miran Grca, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../device.h" +#include "../cpu/cpu.h" +#include "../cpu/x86.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/scat.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Add machine device to system. */ + device_add_ex(info, arg); + + switch(info->local) { + case 0: /* Generic Award SCAT */ + device_add(&scat_device); + m_at_init(); + break; + + case 1: /* Hyundai Super286TR */ + device_add(&scat_device); + m_at_init(); + break; + + + case 2: /* GEAR GW286CT */ + device_add(&scat_4_device); + m_at_init(); + break; + + case 3: /* Samsung SPC4200P / SPC4216P */ + device_add(&scat_4_device); + m_at_init(); + break; + + case 11: /* KMX-C-02 (SCATsx) */ + device_add(&scat_sx_device); + m_at_common_init(); + device_add(&keyboard_at_ami_device); + break; + } + + device_add(&fdc_at_device); + + return(arg); +} + + +static const machine_t award_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 512, 16384, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_scat_award = { + "Award 286 (SCAT)", + DEVICE_ROOT, + 0, + L"generic/at/award", + common_init, NULL, NULL, + NULL, NULL, NULL, + &award_info, + NULL +}; + + +static const machine_t super_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 512, 16384, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_hs286tr = { + "Hyundai Super286TR", + DEVICE_ROOT, + 1, + L"hyundai/super286tr", + common_init, NULL, NULL, + NULL, NULL, NULL, + &super_info, + NULL +}; + + +static const machine_t gear_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 512, 16384, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_gw286ct = { + "Gear GW286CT", + DEVICE_ROOT, + 2, + L"unknown/gw286ct", + common_init, NULL, NULL, + NULL, NULL, NULL, + &gear_info, + NULL +}; + + +static const machine_t spc4200_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_PS2, + 0, + 512, 2048, 128, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_spc4200p = { + "Samsung SPC4200P", + DEVICE_ROOT, + 3, + L"samsung/spc4200p", + common_init, NULL, NULL, + NULL, NULL, NULL, + &spc4200_info, + NULL +}; + + +static const machine_t spc4216_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_PS2, + 0, + 1, 5, 1, 128, 8, + {{"",cpus_286}} +}; + +const device_t m_spc4216p = { + "Samsung SPC4216P", + DEVICE_ROOT, + 3, + L"samsung/spc4216p", + common_init, NULL, NULL, + NULL, NULL, NULL, + &spc4216_info, + NULL +}; + + +static const machine_t kmx_info = { + MACHINE_ISA | MACHINE_AT, + 0, + 512, 16384, 512, 128, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_kmxc02 = { + "KMX-C-02 (SCATsx)", + DEVICE_ROOT, + 11, + L"unknown/kmxc02", + common_init, NULL, NULL, + NULL, NULL, NULL, + &kmx_info, + NULL +}; diff --git a/src/machines/m_xt_compaq.c b/src/machines/m_sis471.c similarity index 54% rename from src/machines/m_xt_compaq.c rename to src/machines/m_sis471.c index ca340f2..6c803a3 100644 --- a/src/machines/m_xt_compaq.c +++ b/src/machines/m_sis471.c @@ -6,17 +6,15 @@ * * This file is part of the VARCem Project. * - * Emulation of the Compaq XT-class PC's. + * Emulation of the SiS 85c471 based machines. * - * Version: @(#)m_xt_compaq.c 1.0.14 2019/02/16 + * Version: @(#)m_sis471.c 1.0.14 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, - * Sarah Walker, * * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,30 +40,70 @@ #include #include "../emu.h" #include "../cpu/cpu.h" -#include "../mem.h" -#include "../rom.h" +#include "../io.h" #include "../device.h" -#include "../devices/system/nmi.h" -#include "../devices/system/pit.h" -#include "../devices/ports/parallel.h" -#include "../devices/input/keyboard.h" +#include "../devices/chipsets/sis471.h" +#include "../devices/system/memregs.h" #include "../devices/floppy/fdd.h" #include "../devices/floppy/fdc.h" #include "machine.h" -void -m_xt_compaq_p1_init(const machine_t *model, void *arg) +static void * +common_init(const device_t *info, void *arg) { - machine_common_init(model, arg); + /* Add machine device to system. */ + device_add_ex(info, arg); - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + device_add(&sis_85c471_device); - device_add(&keyboard_xt_device); + switch(info->local) { + default: + m_at_ide_init(); + break; + } - device_add(&fdc_xt_device); + device_add(&fdc_at_device); - nmi_init(); + memregs_init(); - parallel_setup(0, 0x03bc); + return(arg); } + + +static const machine_t ami_info = { + MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 1, 128, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_sis471_ami = { + "AMI 486 (SiS 471)", + DEVICE_ROOT, + 0, + L"sis471/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &ami_info, + NULL +}; + + +static const machine_t dtk_info = { + MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 1, 128, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_dtk486 = { + "DTK 486 (SiS 471)", + DEVICE_ROOT, + 1, + L"dtk/486", + common_init, NULL, NULL, + NULL, NULL, NULL, + &dtk_info, + NULL +}; diff --git a/src/machines/m_sis496.c b/src/machines/m_sis496.c new file mode 100644 index 0000000..f29248a --- /dev/null +++ b/src/machines/m_sis496.c @@ -0,0 +1,150 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the SiS 85C496/497 based machines. + * + * Version: @(#)m_sis49x.c 1.0.11 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../device.h" +#include "../mem.h" +#include "../rom.h" +#include "../devices/chipsets/sis496.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/sio/sio.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" +#include "../devices/input/keyboard.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Add machine device to system. */ + device_add_ex(info, arg); + + switch(info->local) { + case 0: /* Generic SiS496 */ +////////// + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + 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); + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + memregs_init(); +///////// + device_add(&sis_85c496_device); + m_at_common_ide_init(); + device_add(&keyboard_at_ami_device); + device_add(&fdc_at_device); + break; + + case 1: /* Rise 418 */ + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + 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); + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + memregs_init(); + + device_add(&sis_85c496_device); + m_at_common_init(); + device_add(&keyboard_ps2_pci_device); + device_add(&ide_pci_device); + device_add(&fdc37c665_device); + } + + return(arg); +} + + +static const machine_t ami_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, + 0, + 1, 255, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_sis496_ami = { + "AMI 486 (SiS 496", + DEVICE_ROOT, + 0, + L"sis496/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &ami_info, + NULL +}; + + +static const machine_t rise_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, + 0, + 1, 255, 1, 128, 0, + {{"Intel",cpus_i486},{"AMD",cpus_Am486},{"Cyrix",cpus_Cx486}} +}; + +const device_t m_rise418 = { + "Rise 418 (SiS 496)", + DEVICE_ROOT, + 1, + L"rise/r418", + common_init, NULL, NULL, + NULL, NULL, NULL, + &rise_info, + NULL +}; diff --git a/src/machines/m_tandy.c b/src/machines/m_tandy.c deleted file mode 100644 index c4fd866..0000000 --- a/src/machines/m_tandy.c +++ /dev/null @@ -1,2021 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Emulation of Tandy models 1000, 1000HX and 1000SL2. - * - * NOTE: It might be better (after all..) to split off the video - * driver from the main code, to keep it a little cleaner. - * - * Version: @(#)m_tandy.c 1.0.17 2019/03/07 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include -#include "../emu.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" -#include "../nvr.h" -#include "../device.h" -#include "../devices/system/dma.h" -#include "../devices/system/pic.h" -#include "../devices/system/pit.h" -#include "../devices/system/nmi.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/sound/sound.h" -#include "../devices/sound/snd_sn76489.h" -#include "../devices/video/video.h" -#include "../devices/video/vid_cga.h" -#include "../devices/video/vid_cga_comp.h" -#include "../plat.h" -#include "machine.h" - - -#define TANDY_RGB 0 -#define TANDY_COMPOSITE 1 - - -enum { - EEPROM_IDLE = 0, - EEPROM_GET_OPERATION, - EEPROM_READ, - EEPROM_WRITE -}; - - -typedef struct { - mem_map_t mapping; - mem_map_t vram_mapping; - - uint8_t crtc[32]; - int crtcreg; - - int array_index; - uint8_t array[32]; - int memctrl; - uint8_t mode, col; - uint8_t stat; - - uint8_t *vram, *b8000; - uint32_t b8000_mask; - uint32_t b8000_limit; - uint8_t planar_ctrl; - - int linepos, - displine; - int sc, vc; - int dispon; - int con, coff, - cursoron, - blink; - int64_t vsynctime; - int vadj; - uint16_t ma, maback; - - int64_t dispontime, - dispofftime, - vidtime; - int firstline, - lastline; - - int composite; - void *cpriv; -} t1kvid_t; - -typedef struct { - sn76489_t sn76489; - - uint8_t ctrl; - uint8_t wave; - uint8_t dac_val; - uint16_t freq; - int amplitude; - - int irq; - int64_t timer_count; - int64_t enable; - - int wave_pos; - int pulse_width; - - int pos; - int16_t buffer[SOUNDBUFLEN]; -} t1ksnd_t; - -typedef struct { - wchar_t *fn; - - int state; - int count; - int addr; - int clk; - uint16_t data; - uint16_t store[64]; -} t1keep_t; - -typedef struct { - mem_map_t ram_mapping; - mem_map_t rom_mapping; /* SL2 */ - - uint8_t *rom; /* SL2 */ - uint8_t ram_bank; - uint8_t rom_bank; /* SL2 */ - int rom_offset; /* SL2 */ - - uint32_t base; - int type; - - t1ksnd_t *snd; - - t1kvid_t *vid; -} tandy_t; - - -static const scancode scancode_tandy[512] = { - { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, - { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} }, - { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, - { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} }, - { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, - { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} }, - { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, - { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} }, - { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, - { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} }, - { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, - { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} }, - { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, - { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} }, - { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, - { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} }, - { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, - { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} }, - { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, - { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} }, - { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, - { {0x2a, -1}, {0xaa, -1} }, { {0x2b, -1}, {0xab, -1} }, - { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, - { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} }, - { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, - { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} }, - { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, - { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} }, - { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, - { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} }, - { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, - { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} }, - { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, - { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} }, - { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, - { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, - { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, - { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} }, - { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, - { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} }, - { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, - { {0x52, -1}, {0xd2, -1} }, { {0x56, -1}, {0xd6, -1} }, - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*054*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*058*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*05c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*060*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*064*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*068*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*06c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*070*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*074*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*078*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*07c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*080*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*084*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*088*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*08c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*090*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*094*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*098*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*09c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0a0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0a4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0a8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0ac*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0b0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0b4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0b8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0bc*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0c0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0c4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0c8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0cc*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0d0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0d4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0d8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0dc*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0e0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0e4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0e8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0ec*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0f0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0f4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0f8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*0fc*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*100*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*104*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*108*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*10c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*110*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*114*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*118*/ - { {0x57, -1}, {0xd7, -1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*11c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*120*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*124*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*128*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*12c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*130*/ - { {-1}, {-1} }, { {0x35, -1}, {0xb5, -1} }, - { {-1}, {-1} }, { {0x37, -1}, {0xb7, -1} }, /*134*/ - { {0x38, -1}, {0xb8, -1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*138*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*13c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*140*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, /*144*/ - { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, - { {-1}, {-1} }, { {0x4b, -1}, {0xcb, -1} }, /*148*/ - { {-1}, {-1} }, { {0x4d, -1}, {0xcd, -1} }, - { {-1}, {-1} }, { {0x4f, -1}, {0xcf, -1} }, /*14c*/ - { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, - { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} }, /*150*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*154*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*158*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*15c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*160*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*164*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*168*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*16c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*170*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*174*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*148*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*17c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*180*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*184*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*88*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*18c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*190*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*194*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*198*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*19c*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1a0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1a4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1a8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1ac*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1b0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1b4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1b8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1bc*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1c0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1c4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1c8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1cc*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1d0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1d4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1d8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1dc*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1e0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1e4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1e8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1ec*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1f0*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1f4*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} }, /*1f8*/ - { {-1}, {-1} }, { {-1}, {-1} }, - { {-1}, {-1} }, { {-1}, {-1} } /*1fc*/ -}; -static uint8_t crtcmask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, - 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static uint8_t crtcmask_sl[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, - 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static int eep_data_out; - - -static uint8_t vid_in(uint16_t addr, void *priv); -static void vid_out(uint16_t addr, uint8_t val, void *priv); - -static void -recalc_mapping(tandy_t *dev) -{ - t1kvid_t *vid = dev->vid; - - mem_map_disable(&vid->mapping); - io_removehandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, dev); - - if (vid->planar_ctrl & 4) { - mem_map_enable(&vid->mapping); - if (vid->array[5] & 1) - mem_map_set_addr(&vid->mapping, 0xa0000, 0x10000); - else - mem_map_set_addr(&vid->mapping, 0xb8000, 0x8000); - io_sethandler(0x03d0, 16, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); - } -} - - -static void -recalc_timings(tandy_t *dev) -{ - t1kvid_t *vid = dev->vid; - - double _dispontime, _dispofftime, disptime; - - if (vid->mode & 1) { - disptime = vid->crtc[0] + 1; - _dispontime = vid->crtc[1]; - } else { - disptime = (vid->crtc[0] + 1) << 1; - _dispontime = vid->crtc[1] << 1; - } - - _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST; - _dispofftime *= CGACONST; - vid->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - vid->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -static void -recalc_address(tandy_t *dev) -{ - t1kvid_t *vid = dev->vid; - - if ((vid->memctrl & 0xc0) == 0xc0) { - vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; - vid->b8000_mask = 0x7fff; - } else { - vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; - vid->b8000_mask = 0x3fff; - } -} - - -static void -recalc_address_sl(tandy_t *dev) -{ - t1kvid_t *vid = dev->vid; - - vid->b8000_limit = 0x8000; - - if (vid->array[5] & 1) { - vid->vram = &ram[((vid->memctrl & 0x04) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x20) << 11) + dev->base]; - } else if ((vid->memctrl & 0xc0) == 0xc0) { - vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; - } else { - vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; - if ((vid->memctrl & 0x38) == 0x38) - vid->b8000_limit = 0x4000; - } -} - - -static void -vid_out(uint16_t addr, uint8_t val, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; - uint8_t old; - - switch (addr) { - case 0x03d4: - vid->crtcreg = val & 0x1f; - break; - - case 0x03d5: - old = vid->crtc[vid->crtcreg]; - if (dev->type == 2) - vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg]; - else - vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg]; - if (old != val) { - if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { - fullchange = changeframecount; - recalc_timings(dev); - } - } - break; - - case 0x03d8: - vid->mode = val; - if (dev->type != 2) - cga_comp_update(vid->cpriv, vid->mode); - break; - - case 0x03d9: - vid->col = val; - break; - - case 0x03da: - vid->array_index = val & 0x1f; - break; - - case 0x03de: - if (vid->array_index & 16) - val &= 0xf; - vid->array[vid->array_index & 0x1f] = val; - if (dev->type == 2) { - if ((vid->array_index & 0x1f) == 5) { - recalc_mapping(dev); - recalc_address_sl(dev); - } - } - break; - - case 0x03df: - vid->memctrl = val; - if (dev->type == 2) - recalc_address_sl(dev); - else - recalc_address(dev); - break; - - case 0x0065: - if (val == 8) return; /*Hack*/ - vid->planar_ctrl = val; - recalc_mapping(dev); - break; - } -} - - -static uint8_t -vid_in(uint16_t addr, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; - uint8_t ret = 0xff; - - switch (addr) { - case 0x03d4: - ret = vid->crtcreg; - break; - - case 0x03d5: - ret = vid->crtc[vid->crtcreg]; - break; - - case 0x03da: - ret = vid->stat; - break; - } - - return(ret); -} - - -static void -vid_write(uint32_t addr, uint8_t val, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; - - if (vid->memctrl == -1) return; - - if (dev->type == 2) { - if (vid->array[5] & 1) - vid->b8000[addr & 0xffff] = val; - else { - if ((addr & 0x7fff) < vid->b8000_limit) - vid->b8000[addr & 0x7fff] = val; - } - } else { - vid->b8000[addr & vid->b8000_mask] = val; - } -} - - -static uint8_t -vid_read(uint32_t addr, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; - uint8_t ret = 0xff; - - if (vid->memctrl == -1) return(ret); - - if (dev->type == 2) { - if (vid->array[5] & 1) - ret = vid->b8000[addr & 0xffff]; - if ((addr & 0x7fff) < vid->b8000_limit) - ret = vid->b8000[addr & 0x7fff]; - } else - ret = vid->b8000[addr & vid->b8000_mask]; - - return(ret); -} - - -static void -vid_poll(void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - uint16_t dat; - int cols[4]; - int col; - int oldsc; - - if (! vid->linepos) { - vid->vidtime += vid->dispofftime; - vid->stat |= 1; - vid->linepos = 1; - oldsc = vid->sc; - if ((vid->crtc[8] & 3) == 3) - vid->sc = (vid->sc << 1) & 7; - - if (vid->dispon) { - if (vid->displine < vid->firstline) { - vid->firstline = vid->displine; - video_blit_wait_buffer(); - } - vid->lastline = vid->displine; - cols[0] = (vid->array[2] & 0xf) + 16; - for (c = 0; c < 8; c++) { - if (vid->array[3] & 4) { - screen->line[vid->displine][c].pal = cols[0]; - if (vid->mode & 1) - screen->line[vid->displine][c + (vid->crtc[1] << 3) + 8].pal = cols[0]; - else - screen->line[vid->displine][c + (vid->crtc[1] << 4) + 8].pal = cols[0]; - } else if ((vid->mode & 0x12) == 0x12) { - screen->line[vid->displine][c].pal = 0; - if (vid->mode & 1) - screen->line[vid->displine][c + (vid->crtc[1] << 3) + 8].pal = 0; - else - screen->line[vid->displine][c + (vid->crtc[1] << 4) + 8].pal = 0; - } else { - screen->line[vid->displine][c].pal = (vid->col & 15) + 16; - if (vid->mode & 1) - screen->line[vid->displine][c + (vid->crtc[1] << 3) + 8].pal = (vid->col & 15) + 16; - else - screen->line[vid->displine][c + (vid->crtc[1] << 4) + 8].pal = (vid->col & 15) + 16; - } - } - - if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - screen->line[vid->displine][(x << 3) + 8].pal = - screen->line[vid->displine][(x << 3) + 9].pal = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 3) + 10].pal = - screen->line[vid->displine][(x << 3) + 11].pal = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 3) + 12].pal = - screen->line[vid->displine][(x << 3) + 13].pal = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 3) + 14].pal = - screen->line[vid->displine][(x << 3) + 15].pal = vid->array[(dat & vid->array[1]) + 16] + 16; - } - } else if (vid->array[3] & 0x10) { /*160x200x16*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - screen->line[vid->displine][(x << 4) + 8].pal = - screen->line[vid->displine][(x << 4) + 9].pal = - screen->line[vid->displine][(x << 4) + 10].pal = - screen->line[vid->displine][(x << 4) + 11].pal = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 4) + 12].pal = - screen->line[vid->displine][(x << 4) + 13].pal = - screen->line[vid->displine][(x << 4) + 14].pal = - screen->line[vid->displine][(x << 4) + 15].pal = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 4) + 16].pal = - screen->line[vid->displine][(x << 4) + 17].pal = - screen->line[vid->displine][(x << 4) + 18].pal = - screen->line[vid->displine][(x << 4) + 19].pal = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 4) + 20].pal = - screen->line[vid->displine][(x << 4) + 21].pal = - screen->line[vid->displine][(x << 4) + 22].pal = - screen->line[vid->displine][(x << 4) + 23].pal = vid->array[(dat & vid->array[1]) + 16] + 16; - } - } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - chr = (dat >> 7) & 1; - chr |= ((dat >> 14) & 2); - screen->line[vid->displine][(x << 3) + 8 + c].pal = vid->array[(chr & vid->array[1]) + 16] + 16; - dat <<= 1; - } - } - } else if (vid->mode & 1) { - for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[ (vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->mode & 0x20) { - cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; - } - if (vid->sc & 8) { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 3) + c + 8].pal = cols[0]; - } else { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 3) + c + 8].pal = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - if (drawcursor) { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 3) + c + 8].pal ^= 15; - } - vid->ma++; - } - } else if (! (vid->mode & 2)) { - for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[ (vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->mode & 0x20) { - cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; - } - vid->ma++; - if (vid->sc & 8) { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[0]; - } else { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - if (drawcursor) { - for (c = 0; c < 16; c++) - screen->line[vid->displine][(x << 4) + c + 8].pal ^= 15; - } - } - } else if (! (vid->mode& 16)) { - cols[0] = (vid->col & 15) | 16; - col = (vid->col & 16) ? 24 : 16; - if (vid->mode & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else if (vid->col & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[dat >> 14]; - dat <<= 2; - } - } - } else { - cols[0] = 0; - cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 16; c++) { - screen->line[vid->displine][(x << 4) + c + 8].pal = cols[dat >> 15]; - dat <<= 1; - } - } - } - } else { - if (vid->array[3] & 4) { - if (vid->mode & 1) - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); - else - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); - } else { - cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; - if (vid->mode & 1) - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); - else - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); - } - } - - if (vid->mode & 1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - if (vid->composite) - cga_comp_process(vid->cpriv, vid->mode, 0, x >> 2, screen->line[vid->displine]); - - vid->sc = oldsc; - if (vid->vc == vid->crtc[7] && !vid->sc) - vid->stat |= 8; - vid->displine++; - if (vid->displine >= 360) - vid->displine = 0; - } else { - vid->vidtime += vid->dispontime; - if (vid->dispon) - vid->stat &= ~1; - vid->linepos = 0; - if (vid->vsynctime) { - vid->vsynctime--; - if (! vid->vsynctime) - vid->stat &= ~8; - } - if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { - vid->con = 0; - vid->coff = 1; - } - if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - vid->vadj--; - if (! vid->vadj) { - vid->dispon = 1; - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; - } - } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { - vid->maback = vid->ma; - vid->sc = 0; - oldvc = vid->vc; - vid->vc++; - vid->vc &= 127; - if (vid->vc == vid->crtc[6]) - vid->dispon = 0; - if (oldvc == vid->crtc[4]) { - vid->vc = 0; - vid->vadj = vid->crtc[5]; - if (! vid->vadj) - vid->dispon = 1; - if (! vid->vadj) - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - if ((vid->crtc[10] & 0x60) == 0x20) - vid->cursoron = 0; - else - vid->cursoron = vid->blink & 16; - } - if (vid->vc == vid->crtc[7]) { - vid->dispon = 0; - vid->displine = 0; - vid->vsynctime = 16; - if (vid->crtc[7]) { - if (vid->mode & 1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - vid->lastline++; - if ((x != xsize) || ((vid->lastline - vid->firstline) != ysize) || video_force_resize_get()) { - xsize = x; - ysize = vid->lastline - vid->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, (ysize << 1) + 16); - if (video_force_resize_get()) - video_force_resize_set(0); - } - if (vid->composite) - video_blit_start(0, 0, vid->firstline-4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8); - else - video_blit_start(1, 0, vid->firstline-4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8); - - frames++; - - video_res_x = xsize - 16; - video_res_y = ysize; - if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ - video_res_x /= 2; - video_bpp = 4; - } else if (vid->array[3] & 0x10) { /*160x200x16*/ - video_res_x /= 4; - video_bpp = 4; - } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ - video_bpp = 2; - } else if (vid->mode & 1) { - video_res_x /= 8; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->mode & 2)) { - video_res_x /= 16; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->mode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else { - video_bpp = 1; - } - } - vid->firstline = 1000; - vid->lastline = 0; - vid->blink++; - } - } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - } - if ((vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1)))) - vid->con = 1; - } -} - - -static void -vid_poll_sl(void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - uint16_t dat; - int cols[4]; - int col; - int oldsc; - - if (! vid->linepos) { - vid->vidtime += vid->dispofftime; - vid->stat |= 1; - vid->linepos = 1; - oldsc = vid->sc; - if ((vid->crtc[8] & 3) == 3) - vid->sc = (vid->sc << 1) & 7; - if (vid->dispon) { - if (vid->displine < vid->firstline) { - vid->firstline = vid->displine; - video_blit_wait_buffer(); - } - vid->lastline = vid->displine; - cols[0] = (vid->array[2] & 0xf) + 16; - for (c = 0; c < 8; c++) { - if (vid->array[3] & 4) { - screen->line[vid->displine][c].pal = cols[0]; - if (vid->mode & 1) - screen->line[vid->displine][c + (vid->crtc[1] << 3) + 8].pal = cols[0]; - else - screen->line[vid->displine][c + (vid->crtc[1] << 4) + 8].pal = cols[0]; - } else if ((vid->mode & 0x12) == 0x12) { - screen->line[vid->displine][c].pal = 0; - if (vid->mode & 1) - screen->line[vid->displine][c + (vid->crtc[1] << 3) + 8].pal = 0; - else - screen->line[vid->displine][c + (vid->crtc[1] << 4) + 8].pal = 0; - } else { - screen->line[vid->displine][c].pal = (vid->col & 15) + 16; - if (vid->mode & 1) - screen->line[vid->displine][c + (vid->crtc[1] << 3) + 8].pal = (vid->col & 15) + 16; - else - screen->line[vid->displine][c + (vid->crtc[1] << 4) + 8].pal = (vid->col & 15) + 16; - } - } - if (vid->array[5] & 1) { /*640x200x16*/ - for (x = 0; x < vid->crtc[1]*2; x++) { - dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | - vid->vram[((vid->ma << 1) + 1) & 0xffff]; - vid->ma++; - screen->line[vid->displine][(x << 2) + 8].pal = vid->array[((dat >> 12) & 0xf)/*vid->array[1])*/ + 16] + 16; - screen->line[vid->displine][(x << 2) + 9].pal = vid->array[((dat >> 8) & 0xf)/*vid->array[1])*/ + 16] + 16; - screen->line[vid->displine][(x << 2) + 10].pal = vid->array[((dat >> 4) & 0xf)/*vid->array[1])*/ + 16] + 16; - screen->line[vid->displine][(x << 2) + 11].pal = vid->array[(dat & 0xf)/*vid->array[1])*/ + 16] + 16; - } - } else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - screen->line[vid->displine][(x << 3) + 8].pal = - screen->line[vid->displine][(x << 3) + 9].pal = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 3) + 10].pal = - screen->line[vid->displine][(x << 3) + 11].pal = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 3) + 12].pal = - screen->line[vid->displine][(x << 3) + 13].pal = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 3) + 14].pal = - screen->line[vid->displine][(x << 3) + 15].pal = vid->array[(dat & vid->array[1]) + 16] + 16; - } - } else if (vid->array[3] & 0x10) { /*160x200x16*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - screen->line[vid->displine][(x << 4) + 8].pal = - screen->line[vid->displine][(x << 4) + 9].pal = - screen->line[vid->displine][(x << 4) + 10].pal = - screen->line[vid->displine][(x << 4) + 11].pal = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 4) + 12].pal = - screen->line[vid->displine][(x << 4) + 13].pal = - screen->line[vid->displine][(x << 4) + 14].pal = - screen->line[vid->displine][(x << 4) + 15].pal = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 4) + 16].pal = - screen->line[vid->displine][(x << 4) + 17].pal = - screen->line[vid->displine][(x << 4) + 18].pal = - screen->line[vid->displine][(x << 4) + 19].pal = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; - screen->line[vid->displine][(x << 4) + 20].pal = - screen->line[vid->displine][(x << 4) + 21].pal = - screen->line[vid->displine][(x << 4) + 22].pal = - screen->line[vid->displine][(x << 4) + 23].pal = vid->array[(dat & vid->array[1]) + 16] + 16; - } - } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - chr = (dat >> 7) & 1; - chr |= ((dat >> 14) & 2); - screen->line[vid->displine][(x << 3) + 8 + c].pal = vid->array[(chr & vid->array[1]) + 16] + 16; - dat <<= 1; - } - } - } else if (vid->mode & 1) { - for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[ (vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->mode & 0x20) { - cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; - } - if (vid->sc & 8) { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 3) + c + 8].pal = cols[0]; - } else { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 3) + c + 8].pal = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - if (drawcursor) { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 3) + c + 8].pal ^= 15; - } - vid->ma++; - } - } else if (! (vid->mode & 2)) { - for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[ (vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->mode & 0x20) { - cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; - } - vid->ma++; - if (vid->sc & 8) { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[0]; - } else { - for (c = 0; c < 8; c++) - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - if (drawcursor) { - for (c = 0; c < 16; c++) - screen->line[vid->displine][(x << 4) + c + 8].pal ^= 15; - } - } - } else if (! (vid->mode & 16)) { - cols[0] = (vid->col & 15) | 16; - col = (vid->col & 16) ? 24 : 16; - if (vid->mode & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else if (vid->col & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - screen->line[vid->displine][(x << 4) + (c << 1) + 8].pal = - screen->line[vid->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[dat >> 14]; - dat <<= 2; - } - } - } else { - cols[0] = 0; - cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 16; c++) { - screen->line[vid->displine][(x << 4) + c + 8].pal = cols[dat >> 15]; - dat <<= 1; - } - } - } - } else { - if (vid->array[3] & 4) { - if (vid->mode & 1) - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); - else - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); - } else { - cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; - if (vid->mode & 1) - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); - else - cga_hline(screen, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); - } - } - - if (vid->mode & 1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - vid->sc = oldsc; - - if (vid->vc == vid->crtc[7] && !vid->sc) - vid->stat |= 8; - vid->displine++; - if (vid->displine >= 360) - vid->displine = 0; - } else { - vid->vidtime += vid->dispontime; - if (vid->dispon) - vid->stat &= ~1; - vid->linepos = 0; - if (vid->vsynctime) { - vid->vsynctime--; - if (! vid->vsynctime) - vid->stat &= ~8; - } - if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { - vid->con = 0; - vid->coff = 1; - } - if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - vid->vadj--; - if (! vid->vadj) { - vid->dispon = 1; - if (vid->array[5] & 1) - vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); - else - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; - } - } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { - vid->maback = vid->ma; - vid->sc = 0; - oldvc = vid->vc; - vid->vc++; - vid->vc &= 255; - if (vid->vc == vid->crtc[6]) - vid->dispon = 0; - if (oldvc == vid->crtc[4]) { - vid->vc = 0; - vid->vadj = vid->crtc[5]; - if (! vid->vadj) - vid->dispon = 1; - if (! vid->vadj) { - if (vid->array[5] & 1) - vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); - else - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - } - if ((vid->crtc[10] & 0x60) == 0x20) - vid->cursoron = 0; - else - vid->cursoron = vid->blink & 16; - } - if (vid->vc == vid->crtc[7]) { - vid->dispon = 0; - vid->displine = 0; - vid->vsynctime = 16; - if (vid->crtc[7]) { - if (vid->mode & 1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - vid->lastline++; - if ((x != xsize) || ((vid->lastline - vid->firstline) != ysize) || video_force_resize_get()) { - xsize = x; - ysize = vid->lastline - vid->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - - set_screen_size(xsize, (ysize << 1) + 16); - if (video_force_resize_get()) - video_force_resize_set(0); - } - - video_blit_start(1, 0, vid->firstline-4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8); - - frames++; - video_res_x = xsize - 16; - video_res_y = ysize; - if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ - video_res_x /= 2; - video_bpp = 4; - } else if (vid->array[3] & 0x10) { /*160x200x16*/ - video_res_x /= 4; - video_bpp = 4; - } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ - video_bpp = 2; - } else if (vid->mode & 1) { - video_res_x /= 8; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->mode & 2)) { - video_res_x /= 16; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->mode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else { - video_bpp = 1; - } - } - vid->firstline = 1000; - vid->lastline = 0; - vid->blink++; - } - } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - } - if ((vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1)))) - vid->con = 1; - } -} - - -static void -vid_speed_changed(void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - - recalc_timings(dev); -} - - -static void -vid_close(void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; - - if (vid->cpriv != NULL) { - cga_comp_close(vid->cpriv); - vid->cpriv = NULL; - } - - free(dev->vid); - dev->vid = NULL; -} - - -static void -vid_init(tandy_t *dev) -{ - int display_type; - t1kvid_t *vid; - - vid = (t1kvid_t *)mem_alloc(sizeof(t1kvid_t)); - memset(vid, 0x00, sizeof(t1kvid_t)); - vid->memctrl = -1; - dev->vid = vid; - - display_type = machine_get_config_int("display_type"); - vid->composite = (display_type != TANDY_RGB); - vid->cpriv = cga_comp_init(1); - - if (dev->type == 2) { - vid->b8000_limit = 0x8000; - vid->planar_ctrl = 4; - overscan_x = overscan_y = 16; - - io_sethandler(0x0065, 1, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); - - timer_add(vid_poll_sl, &vid->vidtime, TIMER_ALWAYS_ENABLED, dev); - } else { - vid->b8000_mask = 0x3fff; - - timer_add(vid_poll, &vid->vidtime, TIMER_ALWAYS_ENABLED, dev); - } - - mem_map_add(&vid->mapping, 0xb8000, 0x08000, - vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); - - io_sethandler(0x03d0, 16, - vid_in,NULL,NULL, vid_out,NULL,NULL, dev); -} - - -static void -snd_update_irq(t1ksnd_t *dev) -{ - if (dev->irq && (dev->ctrl & 0x10) && (dev->ctrl & 0x08)) - picint(1 << 7); -} - - -static void -snd_write(uint16_t port, uint8_t val, void *priv) -{ - t1ksnd_t *dev = (t1ksnd_t *)priv; - - switch (port & 3) { - case 0: - dev->ctrl = val; - dev->enable = (val & 4) && (dev->ctrl & 3); - sn74689_set_extra_divide(&dev->sn76489, val & 0x40); - if (!(val & 8)) - dev->irq = 0; - snd_update_irq(dev); - break; - - case 1: - switch (dev->ctrl & 3) { - case 1: /*Sound channel*/ - dev->wave = val; - dev->pulse_width = val & 7; - break; - - case 3: /*Direct DAC*/ - dev->dac_val = val; - break; - } - break; - - case 2: - dev->freq = (dev->freq & 0xf00) | val; - break; - - case 3: - dev->freq = (dev->freq & 0x0ff) | ((val & 0xf) << 8); - dev->amplitude = val >> 4; - break; - } -} - - -static uint8_t -snd_read(uint16_t port, void *priv) -{ - t1ksnd_t *dev = (t1ksnd_t *)priv; - uint8_t ret = 0xff; - - switch (port & 3) { - case 0: - ret = (dev->ctrl & ~0x88) | (dev->irq ? 8 : 0); - break; - - case 1: - switch (dev->ctrl & 3) { - case 0: /*Joystick*/ - ret = 0x00; - break; - - case 1: /*Sound channel*/ - ret = dev->wave; - break; - - case 2: /*Successive approximation*/ - ret = 0x80; - break; - - case 3: /*Direct DAC*/ - ret = dev->dac_val; - break; - } - break; - - case 2: - ret = dev->freq & 0xff; - break; - - case 3: - ret = (dev->freq >> 8) | (dev->amplitude << 4); - break; - - default: - break; - } - - return(ret); -} - - -static void -snd_update(t1ksnd_t *dev) -{ - for (; dev->pos < sound_pos_global; dev->pos++) - dev->buffer[dev->pos] = - (((int8_t)(dev->dac_val ^ 0x80) * 0x20) * dev->amplitude) / 15; -} - - -static void -snd_callback(void *priv) -{ - t1ksnd_t *dev = (t1ksnd_t *)priv; - int data; - - snd_update(dev); - - if (dev->ctrl & 2) { - if ((dev->ctrl & 3) == 3) { - data = dma_channel_read(1); - - if (data != DMA_NODATA) - dev->dac_val = data & 0xff; - } else { - data = dma_channel_write(1, 0x80); - } - - if ((data & DMA_OVER) && data != DMA_NODATA) { - if (dev->ctrl & 0x08) { - dev->irq = 1; - snd_update_irq(dev); - } - } - } else { - switch (dev->wave & 0xc0) { - case 0x00: /*Pulse*/ - dev->dac_val = - (dev->wave_pos > (dev->pulse_width << 1)) ? 0xff : 0; - break; - - case 0x40: /*Ramp*/ - dev->dac_val = dev->wave_pos << 3; - break; - - case 0x80: /*Triangle*/ - if (dev->wave_pos & 16) - dev->dac_val = (dev->wave_pos ^ 31) << 4; - else - dev->dac_val = dev->wave_pos << 4; - break; - - case 0xc0: - dev->dac_val = 0x80; - break; - } - - dev->wave_pos = (dev->wave_pos + 1) & 31; - } - - dev->timer_count += (int64_t)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(dev->freq ? dev->freq : 0x400)); -} - - -static void -snd_get_buffer(int32_t *bufp, int len, void *priv) -{ - t1ksnd_t *dev = (t1ksnd_t *)priv; - int c; - - snd_update(dev); - - for (c = 0; c < len * 2; c++) - bufp[c] += dev->buffer[c >> 1]; - - dev->pos = 0; -} - - -static void * -snd_init(const device_t *info) -{ - t1ksnd_t *dev; - - dev = (t1ksnd_t *)mem_alloc(sizeof(t1ksnd_t)); - memset(dev, 0x00, sizeof(t1ksnd_t)); - - sn76489_init(&dev->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); - - io_sethandler(0x00C4, 4, - snd_read,NULL,NULL, snd_write,NULL,NULL, dev); - - timer_add(snd_callback, &dev->timer_count, &dev->enable, dev); - - sound_add_handler(snd_get_buffer, dev); - - return dev; -} - - -static void -snd_close(void *priv) -{ - t1ksnd_t *dev = (t1ksnd_t *)priv; - - free(dev); -} - - -static const device_t snd_device = { - "Tandy PSSJ", - 0, 0, - snd_init, snd_close, NULL, - NULL, NULL, NULL, NULL, - NULL -}; - - -static void -eep_write(uint16_t addr, uint8_t val, void *priv) -{ - t1keep_t *eep = (t1keep_t *)priv; - - if ((val & 4) && !eep->clk) switch (eep->state) { - case EEPROM_IDLE: - switch (eep->count) { - case 0: - if (! (val & 3)) - eep->count = 1; - else - eep->count = 0; - break; - - case 1: - if ((val & 3) == 2) - eep->count = 2; - else - eep->count = 0; - break; - - case 2: - if ((val & 3) == 3) - eep->state = EEPROM_GET_OPERATION; - eep->count = 0; - break; - } - break; - - case EEPROM_GET_OPERATION: - eep->data = (eep->data << 1) | (val & 1); - eep->count++; - if (eep->count == 8) { - eep->count = 0; - eep->addr = eep->data & 0x3f; - switch (eep->data & 0xc0) { - case 0x40: - eep->state = EEPROM_WRITE; - break; - - case 0x80: - eep->state = EEPROM_READ; - eep->data = eep->store[eep->addr]; - break; - - default: - eep->state = EEPROM_IDLE; - break; - } - } - break; - - case EEPROM_READ: - eep_data_out = eep->data & 0x8000; - eep->data <<= 1; - eep->count++; - if (eep->count == 16) { - eep->count = 0; - eep->state = EEPROM_IDLE; - } - break; - - case EEPROM_WRITE: - eep->data = (eep->data << 1) | (val & 1); - eep->count++; - if (eep->count == 16) { - eep->count = 0; - eep->state = EEPROM_IDLE; - eep->store[eep->addr] = eep->data; - } - break; - } - - eep->clk = val & 4; -} - - -static void * -eep_init(const device_t *info) -{ - char temp[128]; - t1keep_t *eep; - FILE *fp = NULL; - int i; - - eep = (t1keep_t *)mem_alloc(sizeof(t1keep_t)); - memset(eep, 0x00, sizeof(t1keep_t)); - - /* Set up the EEPROM's file name. */ - sprintf(temp, "%s.bin", machine_get_internal_name()); - i = (int)strlen(temp) + 1; - eep->fn = (wchar_t *)mem_alloc(i * sizeof(wchar_t)); - mbstowcs(eep->fn, temp, i); - - fp = plat_fopen(nvr_path(eep->fn), L"rb"); - if (fp != NULL) { - fread(eep->store, 128, 1, fp); - (void)fclose(fp); - } - - io_sethandler(0x037c, 1, NULL,NULL,NULL, eep_write,NULL,NULL, eep); - - return(eep); -} - - -static void -eep_close(void *priv) -{ - t1keep_t *eep = (t1keep_t *)priv; - FILE *fp; - - fp = plat_fopen(nvr_path(eep->fn), L"rb"); - if (fp != NULL) { - (void)fwrite(eep->store, 128, 1, fp); - (void)fclose(fp); - } - - free(eep->fn); - free(eep); -} - - -static const device_t eep_device = { - "Tandy 1000 EEPROM", - 0, 0, - eep_init, eep_close, NULL, - NULL, NULL, NULL, NULL, - NULL -}; - - -static void -tandy_write(uint16_t addr, uint8_t val, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - - switch (addr) { - case 0x00a0: - mem_map_set_addr(&dev->ram_mapping, - ((val >> 1) & 7) * 128 * 1024, 0x20000); - dev->ram_bank = val; - break; - - case 0xffe8: - if ((val & 0xe) == 0xe) - mem_map_disable(&dev->ram_mapping); - else - mem_map_set_addr(&dev->ram_mapping, - ((val >> 1) & 7) * 128 * 1024, 0x20000); - recalc_address_sl(dev); - dev->ram_bank = val; - break; - - case 0xffea: - dev->rom_bank = val; - dev->rom_offset = ((val ^ 4) & 7) * 0x10000; - mem_map_set_exec(&dev->rom_mapping, - &dev->rom[dev->rom_offset]); - } -} - - -static uint8_t -tandy_read(uint16_t addr, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - uint8_t ret = 0xff; - - switch (addr) { - case 0x00a0: - ret = dev->ram_bank; - break; - - case 0xffe8: - ret = dev->ram_bank; - break; - - case 0xffea: - ret = (dev->rom_bank ^ 0x10); - break; - } - - return(ret); -} - - -static void -write_ram(uint32_t addr, uint8_t val, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - - ram[dev->base + (addr & 0x1ffff)] = val; -} - - -static uint8_t -read_ram(uint32_t addr, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - - return(ram[dev->base + (addr & 0x1ffff)]); -} - - -static uint8_t -read_rom(uint32_t addr, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; - - return(dev->rom[addr2]); -} - - -static uint16_t -read_romw(uint32_t addr, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; - - return(*(uint16_t *)&dev->rom[addr2]); -} - - -static uint32_t -read_roml(uint32_t addr, void *priv) -{ - tandy_t *dev = (tandy_t *)priv; - - return(*(uint32_t *)&dev->rom[addr]); -} - - -static void -init_rom(tandy_t *dev) -{ - dev->rom = (uint8_t *)mem_alloc(0x80000); - - if (! rom_load_interleaved(L"machines/tandy1000sl2/8079047.hu1", - L"machines/tandy1000sl2/8079048.hu2", - 0x000000, 0x80000, 0, dev->rom)) { - ERRLOG("TANDY: unable to load BIOS for 1000/SL2 !\n"); - free(dev->rom); - dev->rom = NULL; - return; - } - - mem_map_add(&dev->rom_mapping, 0xe0000, 0x10000, - read_rom, read_romw, read_roml, NULL, NULL, NULL, - dev->rom, MEM_MAPPING_EXTERNAL, dev); -} - - -static const device_config_t vid_config[] = { - { - "display_type", "Display type", CONFIG_SELECTION, "", TANDY_RGB, - { - { - "RGB", TANDY_RGB - }, - { - "Composite", TANDY_COMPOSITE - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - -static const video_timings_t tandy_timing = { VID_BUS,1,2,4,1,2,4 }; - -const device_t m_tandy1k_device = { - "Tandy 1000", - 0, 0, - NULL, vid_close, NULL, - NULL, - vid_speed_changed, - NULL, - NULL, - vid_config -}; - -const device_t m_tandy1k_hx_device = { - "Tandy 1000 HX", - 0, 0, - NULL, vid_close, NULL, - NULL, - vid_speed_changed, - NULL, - NULL, - vid_config -}; - -const device_t m_tandy1k_sl2_device = { - "Tandy 1000SL2", - 0, 1, - NULL, vid_close, NULL, - NULL, - vid_speed_changed, - NULL, - NULL, - NULL -}; - - -static void -tandy1k_common_init(const machine_t *model, void *arg, int type) -{ - tandy_t *dev; - - dev = (tandy_t *)mem_alloc(sizeof(tandy_t)); - memset(dev, 0x00, sizeof(tandy_t)); - dev->type = type; - - machine_common_init(model, arg); - - nmi_init(); - - /* - * Base 128K mapping is controlled via ports 0xA0 or - * 0xFFE8 (SL2), so we remove it from the main mapping. - */ - dev->base = (mem_size - 128) * 1024; - mem_map_add(&dev->ram_mapping, 0x80000, 0x20000, - read_ram,NULL,NULL, write_ram,NULL,NULL, NULL, 0, dev); - mem_map_set_addr(&ram_low_mapping, 0, dev->base); - - device_add(&keyboard_tandy_device); - keyboard_set_table(scancode_tandy); - - device_add(&fdc_xt_device); - - switch(dev->type) { - case 0: - io_sethandler(0x00a0, 1, - tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); - vid_init(dev); - device_add_ex(&m_tandy1k_device, dev); - - video_inform(VID_TYPE_CGA, &tandy_timing); - - device_add(&sn76489_device); - break; - - case 1: - io_sethandler(0x00a0, 1, - tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); - vid_init(dev); - device_add_ex(&m_tandy1k_hx_device, dev); - - video_inform(VID_TYPE_CGA, &tandy_timing); - - device_add(&ncr8496_device); - device_add(&eep_device); - break; - - case 2: - init_rom(dev); - io_sethandler(0xffe8, 8, - tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); - vid_init(dev); - device_add_ex(&m_tandy1k_sl2_device, dev); - - video_inform(VID_TYPE_CGA, &tandy_timing); - - device_add(&snd_device); - device_add(&eep_device); - } - - eep_data_out = 0x0000; -} - - -void -m_tandy1k_init(const machine_t *model, void *arg) -{ - tandy1k_common_init(model, arg, 0); -} - - -void -m_tandy1k_hx_init(const machine_t *model, void *arg) -{ - tandy1k_common_init(model, arg, 1); -} - - -void -m_tandy1k_sl2_init(const machine_t *model, void *arg) -{ - tandy1k_common_init(model, arg, 2); -} - - -int -tandy1k_eeprom_read(void) -{ - return(eep_data_out); -} diff --git a/src/machines/m_tandy1000.c b/src/machines/m_tandy1000.c new file mode 100644 index 0000000..448f922 --- /dev/null +++ b/src/machines/m_tandy1000.c @@ -0,0 +1,1055 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of Tandy models 1000, 1000HX and 1000SL2. + * + * Version: @(#)m_tandy1000.c 1.0.19 2019/04/11 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../timer.h" +#include "../nvr.h" +#include "../device.h" +#include "../devices/system/dma.h" +#include "../devices/system/pic.h" +#include "../devices/system/pit.h" +#include "../devices/system/nmi.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/sound/sound.h" +#include "../devices/sound/snd_sn76489.h" +#include "../plat.h" +#include "machine.h" +#include "m_tandy1000.h" + + +#define TANDY_EEP_SIZE 64 + +#define TANDY_RGB 0 +#define TANDY_COMPOSITE 1 + + +enum { + EEPROM_IDLE = 0, + EEPROM_GET_OPERATION, + EEPROM_READ, + EEPROM_WRITE +}; + + +typedef struct { + sn76489_t sn76489; + + uint8_t ctrl; + uint8_t wave; + uint8_t dac_val; + uint16_t freq; + int amplitude; + + int irq; + int64_t timer_count; + int64_t enable; + + int wave_pos; + int pulse_width; + + int pos; + int16_t buffer[SOUNDBUFLEN]; +} t1ksnd_t; + +typedef struct { + wchar_t *fn; + + int8_t state; + uint8_t count; + uint8_t addr; + uint8_t clk; + + uint16_t data_out, + data; + + uint16_t store[TANDY_EEP_SIZE]; +} t1keep_t; + +typedef struct { + int type; + int display_type; + + uint32_t base; + + mem_map_t ram_mapping; + mem_map_t rom_mapping; /* SL2 */ + + uint8_t *rom; /* SL2 */ + uint8_t ram_bank; + uint8_t rom_bank; /* SL2 */ + int rom_offset; /* SL2 */ +} tandy_t; + + +static const scancode scancode_tandy[512] = { + { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, + { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} }, + { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, + { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} }, + { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, + { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} }, + { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, + { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} }, + { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, + { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} }, + { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, + { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} }, + { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, + { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} }, + { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, + { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} }, + { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, + { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} }, + { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, + { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} }, + { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, + { {0x2a, -1}, {0xaa, -1} }, { {0x2b, -1}, {0xab, -1} }, + { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, + { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} }, + { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, + { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} }, + { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, + { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} }, + { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, + { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} }, + { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, + { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} }, + { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, + { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} }, + { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, + { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, + { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, + { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} }, + { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, + { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} }, + { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, + { {0x52, -1}, {0xd2, -1} }, { {0x56, -1}, {0xd6, -1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*054*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*058*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*05c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*060*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*064*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*068*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*06c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*070*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*074*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*078*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*07c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*080*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*084*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*088*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*08c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*090*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*094*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*098*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*09c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0a0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0a4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0a8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0ac*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0b0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0b4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0b8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0bc*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0c0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0c4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0c8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0cc*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0d0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0d4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0d8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0dc*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0e0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0e4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0e8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0ec*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0f0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0f4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0f8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*0fc*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*100*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*104*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*108*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*10c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*110*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*114*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*118*/ + { {0x57, -1}, {0xd7, -1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*11c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*120*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*124*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*128*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*12c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*130*/ + { {-1}, {-1} }, { {0x35, -1}, {0xb5, -1} }, + { {-1}, {-1} }, { {0x37, -1}, {0xb7, -1} }, /*134*/ + { {0x38, -1}, {0xb8, -1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*138*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*13c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*140*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, /*144*/ + { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, + { {-1}, {-1} }, { {0x4b, -1}, {0xcb, -1} }, /*148*/ + { {-1}, {-1} }, { {0x4d, -1}, {0xcd, -1} }, + { {-1}, {-1} }, { {0x4f, -1}, {0xcf, -1} }, /*14c*/ + { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, + { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} }, /*150*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*154*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*158*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*15c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*160*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*164*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*168*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*16c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*170*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*174*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*148*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*17c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*180*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*184*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*88*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*18c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*190*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*194*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*198*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*19c*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1a0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1a4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1a8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1ac*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1b0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1b4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1b8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1bc*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1c0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1c4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1c8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1cc*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1d0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1d4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1d8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1dc*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1e0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1e4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1e8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1ec*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1f0*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1f4*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, /*1f8*/ + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} } /*1fc*/ +}; + + +static void +snd_update_irq(t1ksnd_t *dev) +{ + if (dev->irq && (dev->ctrl & 0x10) && (dev->ctrl & 0x08)) + picint(1 << 7); +} + + +static void +snd_write(uint16_t port, uint8_t val, void *priv) +{ + t1ksnd_t *dev = (t1ksnd_t *)priv; + + switch (port & 3) { + case 0: + dev->ctrl = val; + dev->enable = (val & 4) && (dev->ctrl & 3); + sn74689_set_extra_divide(&dev->sn76489, val & 0x40); + if (!(val & 8)) + dev->irq = 0; + snd_update_irq(dev); + break; + + case 1: + switch (dev->ctrl & 3) { + case 1: /*Sound channel*/ + dev->wave = val; + dev->pulse_width = val & 7; + break; + + case 3: /*Direct DAC*/ + dev->dac_val = val; + break; + } + break; + + case 2: + dev->freq = (dev->freq & 0xf00) | val; + break; + + case 3: + dev->freq = (dev->freq & 0x0ff) | ((val & 0xf) << 8); + dev->amplitude = val >> 4; + break; + } +} + + +static uint8_t +snd_read(uint16_t port, void *priv) +{ + t1ksnd_t *dev = (t1ksnd_t *)priv; + uint8_t ret = 0xff; + + switch (port & 3) { + case 0: + ret = (dev->ctrl & ~0x88) | (dev->irq ? 8 : 0); + break; + + case 1: + switch (dev->ctrl & 3) { + case 0: /*Joystick*/ + ret = 0x00; + break; + + case 1: /*Sound channel*/ + ret = dev->wave; + break; + + case 2: /*Successive approximation*/ + ret = 0x80; + break; + + case 3: /*Direct DAC*/ + ret = dev->dac_val; + break; + } + break; + + case 2: + ret = dev->freq & 0xff; + break; + + case 3: + ret = (dev->freq >> 8) | (dev->amplitude << 4); + break; + + default: + break; + } + + return(ret); +} + + +static void +snd_update(t1ksnd_t *dev) +{ + for (; dev->pos < sound_pos_global; dev->pos++) + dev->buffer[dev->pos] = + (((int8_t)(dev->dac_val ^ 0x80) * 0x20) * dev->amplitude) / 15; +} + + +static void +snd_callback(void *priv) +{ + t1ksnd_t *dev = (t1ksnd_t *)priv; + int data; + + snd_update(dev); + + if (dev->ctrl & 2) { + if ((dev->ctrl & 3) == 3) { + data = dma_channel_read(1); + + if (data != DMA_NODATA) + dev->dac_val = data & 0xff; + } else { + data = dma_channel_write(1, 0x80); + } + + if ((data & DMA_OVER) && data != DMA_NODATA) { + if (dev->ctrl & 0x08) { + dev->irq = 1; + snd_update_irq(dev); + } + } + } else { + switch (dev->wave & 0xc0) { + case 0x00: /*Pulse*/ + dev->dac_val = + (dev->wave_pos > (dev->pulse_width << 1)) ? 0xff : 0; + break; + + case 0x40: /*Ramp*/ + dev->dac_val = dev->wave_pos << 3; + break; + + case 0x80: /*Triangle*/ + if (dev->wave_pos & 16) + dev->dac_val = (dev->wave_pos ^ 31) << 4; + else + dev->dac_val = dev->wave_pos << 4; + break; + + case 0xc0: + dev->dac_val = 0x80; + break; + } + + dev->wave_pos = (dev->wave_pos + 1) & 31; + } + + dev->timer_count += (int64_t)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(dev->freq ? dev->freq : 0x400)); +} + + +static void +snd_get_buffer(int32_t *bufp, int len, void *priv) +{ + t1ksnd_t *dev = (t1ksnd_t *)priv; + int c; + + snd_update(dev); + + for (c = 0; c < len * 2; c++) + bufp[c] += dev->buffer[c >> 1]; + + dev->pos = 0; +} + + +static void * +snd_init(const device_t *info, UNUSED(void *parent)) +{ + t1ksnd_t *dev; + + dev = (t1ksnd_t *)mem_alloc(sizeof(t1ksnd_t)); + memset(dev, 0x00, sizeof(t1ksnd_t)); + + sn76489_init(&dev->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); + + io_sethandler(0x00c4, 4, + snd_read,NULL,NULL, snd_write,NULL,NULL, dev); + + timer_add(snd_callback, &dev->timer_count, &dev->enable, dev); + + sound_add_handler(snd_get_buffer, dev); + + return(dev); +} + + +static void +snd_close(void *priv) +{ + t1ksnd_t *dev = (t1ksnd_t *)priv; + + free(dev); +} + + +static const device_t snd_device = { + "Tandy PSSJ", + 0, 0, + NULL, + snd_init, snd_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + + +static void +eep_write(uint16_t addr, uint8_t val, void *priv) +{ + t1keep_t *dev = (t1keep_t *)priv; + + if ((val & 4) && !dev->clk) switch (dev->state) { + case EEPROM_IDLE: + switch (dev->count) { + case 0: + if (val & 3) + dev->count = 0; + else + dev->count = 1; + break; + + case 1: + if ((val & 3) == 2) + dev->count = 2; + else + dev->count = 0; + break; + + case 2: + if ((val & 3) == 3) + dev->state = EEPROM_GET_OPERATION; + dev->count = 0; + break; + } + break; + + case EEPROM_GET_OPERATION: + dev->data = (dev->data << 1) | (val & 1); + if (++dev->count == 8) { + dev->count = 0; + dev->addr = dev->data & 0x3f; + switch (dev->data & 0xc0) { + case 0x40: + dev->state = EEPROM_WRITE; + break; + + case 0x80: + dev->state = EEPROM_READ; + dev->data = dev->store[dev->addr]; + break; + + default: + dev->state = EEPROM_IDLE; + break; + } + } + break; + + case EEPROM_READ: + dev->data_out = dev->data & 0x8000; + dev->data <<= 1; + if (++dev->count == 16) { + dev->count = 0; + dev->state = EEPROM_IDLE; + } + break; + + case EEPROM_WRITE: + dev->data = (dev->data << 1) | (val & 1); + if (++dev->count == 16) { + dev->count = 0; + dev->state = EEPROM_IDLE; + dev->store[dev->addr] = dev->data; + } + break; + } + + dev->clk = val & 4; +} + + +static void * +eep_init(const device_t *info, UNUSED(void *parent)) +{ + char temp[128]; + t1keep_t *dev; + FILE *fp; + int i; + + dev = (t1keep_t *)mem_alloc(sizeof(t1keep_t)); + memset(dev, 0x00, sizeof(t1keep_t)); + + /* Set up the EEPROM's file name. */ + sprintf(temp, "%s.bin", machine_get_internal_name()); + i = (int)strlen(temp) + 1; + dev->fn = (wchar_t *)mem_alloc(i * sizeof(wchar_t)); + mbstowcs(dev->fn, temp, i); + + fp = plat_fopen(nvr_path(dev->fn), L"rb"); + if (fp != NULL) { + fread(dev->store, sizeof(dev->store), 1, fp); + (void)fclose(fp); + } + + io_sethandler(0x037c, 1, NULL,NULL,NULL, eep_write,NULL,NULL, dev); + + return(dev); +} + + +static void +eep_close(void *priv) +{ + t1keep_t *dev = (t1keep_t *)priv; + FILE *fp; + + fp = plat_fopen(nvr_path(dev->fn), L"wb"); + if (fp != NULL) { + (void)fwrite(dev->store, sizeof(dev->store), 1, fp); + (void)fclose(fp); + } + + free(dev->fn); + + free(dev); +} + + +/* Called by the keyboard driver to read the next bit. */ +static uint8_t +eep_readbit(void *priv) +{ + t1keep_t *dev = (t1keep_t *)priv; + + return(dev->data_out ? 1 : 0); +} + + +static const device_t eep_device = { + "Tandy 1000 EEPROM", + 0, 0, NULL, + eep_init, eep_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + + +static void +tandy_write(uint16_t addr, uint8_t val, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + switch (addr) { + case 0x00a0: + mem_map_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, 0x20000); + dev->ram_bank = val; + break; + + case 0xffe8: + if ((val & 0x0e) == 0x0e) + mem_map_disable(&dev->ram_mapping); + else + mem_map_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, 0x20000); +// FIXME.. is this needed? + //recalc_address(dev, 1); + dev->ram_bank = val; + break; + + case 0xffea: + dev->rom_bank = val; + dev->rom_offset = ((val ^ 4) & 7) * 0x10000; + mem_map_set_exec(&dev->rom_mapping, + &dev->rom[dev->rom_offset]); + } +} + + +static uint8_t +tandy_read(uint16_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x00a0: + ret = dev->ram_bank; + break; + + case 0xffe8: + ret = dev->ram_bank; + break; + + case 0xffea: + ret = (dev->rom_bank ^ 0x10); + break; + } + + return(ret); +} + + +static void +write_ram(uint32_t addr, uint8_t val, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + ram[dev->base + (addr & 0x1ffff)] = val; +} + + +static uint8_t +read_ram(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + return(ram[dev->base + (addr & 0x1ffff)]); +} + + +static uint8_t +read_rom(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; + + return(dev->rom[addr2]); +} + + +static uint16_t +read_romw(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; + + return(*(uint16_t *)&dev->rom[addr2]); +} + + +static uint32_t +read_roml(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + return(*(uint32_t *)&dev->rom[addr]); +} + + +/* + * The Tandy 1000 SL/2 has 512KB of ROM on the board. + * + * Part of this is the 64KB ROM BIOS, which loads at + * the usual address (OK, that is F0000 ..), and the + * rest is their "DOS in ROM" data. + * + * This DOS data is loaded at E0000, but only using a + * single segment (64KB) at a time, through the bank + * switch register at FFEA. Because of this, we have + * set the bios.txt script to "no load", allowing us + * to implement the loading here. + */ +static void +init_romdos(tandy_t *dev, romdef_t *roms) +{ + uint32_t tot = 1024UL * 512; + int i; + + /* Allocate the space to store the (custom) ROM. */ + dev->rom = (uint8_t *)mem_alloc(tot); + + if (roms->mode == 1) { + /* Interleaved mode. */ + i = rom_load_interleaved(roms->files[0].path, roms->files[1].path, + 0x000000, tot, 0, dev->rom); + } else { + /* Linear mode. */ + i = rom_load_linear(roms->files[0].path, + 0x000000, tot, 0, dev->rom); + } + + if (! i) { + ERRLOG("TANDY: unable to load BIOS for 1000 SL/2 !\n"); + free(dev->rom); + dev->rom = NULL; + return; + } + + /* Set up a memory segment at E0000, 64KB in size. */ + mem_map_add(&dev->rom_mapping, 0xe0000, 0x10000, + read_rom, read_romw, read_roml, NULL, NULL, NULL, + dev->rom, MEM_MAPPING_EXTERNAL, dev); +} + + +static void * +tandy_init(const device_t *info, void *arg) +{ + romdef_t *roms = (romdef_t *)arg; + void *eep = NULL, *kbd; + tandy_t *dev; + + dev = (tandy_t *)mem_alloc(sizeof(tandy_t)); + memset(dev, 0x00, sizeof(tandy_t)); + dev->type = info->local; + + /* Add machine device. */ + device_add_ex(info, dev); + + dev->display_type = machine_get_config_int("display_type"); + + machine_common_init(); + + nmi_init(); + + /* + * Base 128K mapping is controlled via ports 0xA0 or + * 0xFFE8 (SL2), so we remove it from the main mapping. + */ + dev->base = (mem_size - 128) * 1024; + mem_map_add(&dev->ram_mapping, 0x80000, 0x20000, + read_ram,NULL,NULL, write_ram,NULL,NULL, NULL, 0, dev); + mem_map_set_addr(&ram_low_mapping, 0, dev->base); + + /* Set up the video controller. */ + tandy1k_video_init(dev->type, dev->display_type, dev->base, roms->fontfn); + + kbd = device_add(&keyboard_tandy_device); + keyboard_set_table(scancode_tandy); + + device_add(&fdc_xt_device); + + switch(dev->type) { + case 0: /* Tandy 1000 */ + io_sethandler(0x00a0, 1, + tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); + device_add(&sn76489_device); + break; + + case 1: /* Tandy 1000HX */ + io_sethandler(0x00a0, 1, + tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); + device_add(&ncr8496_device); + eep = device_add(&eep_device); + break; + + case 2: /* Tandy 1000SL2 */ + init_romdos(dev, roms); + io_sethandler(0xffe8, 8, + tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); + device_add(&snd_device); + eep = device_add(&eep_device); + break; + } + + /* Set the callback function for the keyboard controller. */ + keyboard_xt_set_funcs(kbd, eep_readbit, eep); + + return(dev); +} + + +static void +tandy_close(void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + if (dev->rom != NULL) + free(dev->rom); + + free(dev); +} + + +static const device_config_t tandy_config[] = { + { + "display_type", "Display type", CONFIG_SELECTION, "", TANDY_RGB, + { + { + "RGB", TANDY_RGB + }, + { + "Composite", TANDY_COMPOSITE + }, + { + NULL + } + } + }, + { + NULL + } +}; + + +static const CPU cpus_tandy[] = { + { "8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1 }, + { "8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1 }, + { "8088/9.54", CPU_8088, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 }, + { NULL } +}; + +static const machine_t tandy_1k_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_SOUND, + MACHINE_VIDEO, + 128, 640, 128, 0, -1, + {{"Intel",cpus_tandy},{"NEC",cpus_nec}} +}; + +const device_t m_tandy_1k = { + "Tandy 1000", + DEVICE_ROOT, + 0, + L"tandy/t1000", + tandy_init, tandy_close, NULL, + NULL, NULL, NULL, + &tandy_1k_info, + tandy_config +}; + + +static const machine_t tandy_1k_hx_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_SOUND, + MACHINE_VIDEO, + 256, 640, 128, 0, -1, + {{"Intel",cpus_tandy},{"NEC",cpus_nec}} +}; + +const device_t m_tandy_1k_hx = { + "Tandy 1000 HX", + DEVICE_ROOT, + 1, + L"tandy/t1000hx", + tandy_init, tandy_close, NULL, + NULL, NULL, NULL, + &tandy_1k_hx_info, + tandy_config +}; + + +static const machine_t tandy_1k_sl2_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_SOUND, + MACHINE_VIDEO, + 512, 640, 128, 0, -1, + {{"Intel",cpus_8086},{"NEC",cpus_nec}} +}; + +const device_t m_tandy_1k_sl2 = { + "Tandy 1000SL2", + DEVICE_ROOT, + 2, + L"tandy/t1000sl2", + tandy_init, tandy_close, NULL, + NULL, NULL, NULL, + &tandy_1k_sl2_info, + NULL +}; diff --git a/src/machines/m_tandy1000.h b/src/machines/m_tandy1000.h new file mode 100644 index 0000000..10687c5 --- /dev/null +++ b/src/machines/m_tandy1000.h @@ -0,0 +1,62 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Tandy 1000 machines. + * + * Version: @(#)m_tandy1000.h 1.0.1 2019/03/18 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef MACHINE_TANDY1000_H +# define MACHINE_TANDY1000_H + + +#ifdef EMU_DEVICE_H +extern const device_t m_tandy1k; +extern const device_t m_tandy1k_hx; +extern const device_t m_tandy1k_sl2; +#endif + + +extern void tandy1k_video_init(int type, int display_type, + uint32_t base, const wchar_t *fn); + + +#endif /*MACHINE_TANDY1000_H*/ diff --git a/src/machines/m_tandy1000_vid.c b/src/machines/m_tandy1000_vid.c new file mode 100644 index 0000000..fa8b051 --- /dev/null +++ b/src/machines/m_tandy1000_vid.c @@ -0,0 +1,1103 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of video controllers for Tandy models. + * + * Version: @(#)m_tandy1000_vid.c 1.0.2 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../timer.h" +#include "../nvr.h" +#include "../device.h" +#include "../devices/system/pit.h" +#include "../devices/video/video.h" +#include "../devices/video/vid_cga.h" +#include "../devices/video/vid_cga_comp.h" +#include "../plat.h" +#include "machine.h" +#include "m_tandy1000.h" + + +typedef struct { + int type; + int composite; + + uint32_t base; + + mem_map_t mapping; + mem_map_t vram_mapping; + + uint8_t crtc[32]; + int crtcreg; + + int array_index; + uint8_t array[32]; + int memctrl; + uint8_t mode, col; + uint8_t stat; + + uint8_t *vram, *b8000; + uint32_t b8000_mask; + uint32_t b8000_limit; + uint8_t planar_ctrl; + + int linepos, + displine; + int sc, vc; + int dispon; + int con, coff, + cursoron, + blink; + int64_t vsynctime; + int vadj; + uint16_t ma, maback; + + int64_t dispontime, + dispofftime, + vidtime; + int firstline, + lastline; + + void *cpriv; + + uint8_t fontdat[256][8]; +} t1kvid_t; + + +static const uint8_t crtcmask[32] = { + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const uint8_t crtcmask_sl[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const video_timings_t tandy_timing = { VID_BUS,1,2,4,1,2,4 }; + + +static uint8_t vid_in(uint16_t addr, void *priv); +static void vid_out(uint16_t addr, uint8_t val, void *priv); + + +static void +recalc_mapping(t1kvid_t *dev) +{ + mem_map_disable(&dev->mapping); + io_removehandler(0x03d0, 16, + vid_in, NULL, NULL, vid_out, NULL, NULL, dev); + + if (dev->planar_ctrl & 4) { + mem_map_enable(&dev->mapping); + if (dev->array[5] & 1) + mem_map_set_addr(&dev->mapping, 0xa0000, 0x10000); + else + mem_map_set_addr(&dev->mapping, 0xb8000, 0x8000); + io_sethandler(0x03d0, 16, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + } +} + + +static void +recalc_timings(t1kvid_t *dev) +{ + double _dispontime, _dispofftime, disptime; + + if (dev->mode & 1) { + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; + } else { + disptime = (dev->crtc[0] + 1) << 1; + _dispontime = dev->crtc[1] << 1; + } + + _dispofftime = disptime - _dispontime; + _dispontime *= CGACONST; + _dispofftime *= CGACONST; + + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); +} + + +static void +recalc_address(t1kvid_t *dev, int sl) +{ + if (sl) { + dev->b8000_limit = 0x8000; + + if (dev->array[5] & 1) { + dev->vram = &ram[((dev->memctrl & 0x04) << 14) + dev->base]; + dev->b8000 = &ram[((dev->memctrl & 0x20) << 11) + dev->base]; + } else if ((dev->memctrl & 0xc0) == 0xc0) { + dev->vram = &ram[((dev->memctrl & 0x06) << 14) + dev->base]; + dev->b8000 = &ram[((dev->memctrl & 0x30) << 11) + dev->base]; + } else { + dev->vram = &ram[((dev->memctrl & 0x07) << 14) + dev->base]; + dev->b8000 = &ram[((dev->memctrl & 0x38) << 11) + dev->base]; + if ((dev->memctrl & 0x38) == 0x38) + dev->b8000_limit = 0x4000; + } + } else { + if ((dev->memctrl & 0xc0) == 0xc0) { + dev->vram = &ram[((dev->memctrl & 0x06) << 14) + dev->base]; + dev->b8000 = &ram[((dev->memctrl & 0x30) << 11) + dev->base]; + dev->b8000_mask = 0x7fff; + } else { + dev->vram = &ram[((dev->memctrl & 0x07) << 14) + dev->base]; + dev->b8000 = &ram[((dev->memctrl & 0x38) << 11) + dev->base]; + dev->b8000_mask = 0x3fff; + } + } +} + + +static void +vid_out(uint16_t addr, uint8_t val, void *priv) +{ + t1kvid_t *dev = (t1kvid_t *)priv; + uint8_t old; + + switch (addr) { + case 0x03d4: + dev->crtcreg = val & 0x1f; + break; + + case 0x03d5: + old = dev->crtc[dev->crtcreg]; + if (dev->type == 2) + dev->crtc[dev->crtcreg] = val & crtcmask_sl[dev->crtcreg]; + else + dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg]; + if (old != val) { + if (dev->crtcreg < 0xe || dev->crtcreg > 0x10) { + fullchange = changeframecount; + recalc_timings(dev); + } + } + break; + + case 0x03d8: + dev->mode = val; + if ((dev->type != 2) && (dev->cpriv != NULL)) + cga_comp_update(dev->cpriv, dev->mode); + break; + + case 0x03d9: + dev->col = val; + break; + + case 0x03da: + dev->array_index = val & 0x1f; + break; + + case 0x03de: + if (dev->array_index & 16) + val &= 0xf; + dev->array[dev->array_index & 0x1f] = val; + if (dev->type == 2) { + if ((dev->array_index & 0x1f) == 5) { + recalc_mapping(dev); + recalc_address(dev, 1); + } + } + break; + + case 0x03df: + dev->memctrl = val; + if (dev->type == 2) + recalc_address(dev, 1); + else + recalc_address(dev, 0); + break; + + case 0x0065: + if (val == 8) return; /*Hack*/ + dev->planar_ctrl = val; + recalc_mapping(dev); + break; + } +} + + +static uint8_t +vid_in(uint16_t addr, void *priv) +{ + t1kvid_t *dev = (t1kvid_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x03d4: + ret = dev->crtcreg; + break; + + case 0x03d5: + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x03da: + ret = dev->stat; + break; + } + + return(ret); +} + + +static void +vid_write(uint32_t addr, uint8_t val, void *priv) +{ + t1kvid_t *dev = (t1kvid_t *)priv; + + if (dev->memctrl == -1) return; + + if (dev->type == 2) { + if (dev->array[5] & 1) + dev->b8000[addr & 0xffff] = val; + else { + if ((addr & 0x7fff) < dev->b8000_limit) + dev->b8000[addr & 0x7fff] = val; + } + } else { + dev->b8000[addr & dev->b8000_mask] = val; + } +} + + +static uint8_t +vid_read(uint32_t addr, void *priv) +{ + t1kvid_t *dev = (t1kvid_t *)priv; + uint8_t ret = 0xff; + + if (dev->memctrl == -1) return(ret); + + if (dev->type == 2) { + if (dev->array[5] & 1) + ret = dev->b8000[addr & 0xffff]; + if ((addr & 0x7fff) < dev->b8000_limit) + ret = dev->b8000[addr & 0x7fff]; + } else + ret = dev->b8000[addr & dev->b8000_mask]; + + return(ret); +} + + +static void +vid_poll(void *priv) +{ + t1kvid_t *dev = (t1kvid_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c; + int oldvc; + uint8_t chr, attr; + uint16_t dat; + int cols[4]; + int col; + int oldsc; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_blit_wait_buffer(); + } + dev->lastline = dev->displine; + + cols[0] = (dev->array[2] & 0xf) + 16; + for (c = 0; c < 8; c++) { + if (dev->array[3] & 4) { + screen->line[dev->displine][c].pal = cols[0]; + if (dev->mode & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = cols[0]; + else + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = cols[0]; + } else if ((dev->mode & 0x12) == 0x12) { + screen->line[dev->displine][c].pal = 0; + if (dev->mode & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = 0; + else + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = 0; + } else { + screen->line[dev->displine][c].pal = (dev->col & 15) + 16; + if (dev->mode & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = (dev->col & 15) + 16; + else + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = (dev->col & 15) + 16; + } + } + + if ((dev->array[3] & 0x10) && (dev->mode & 1)) { /*320x200x16*/ + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000) + 1]; + dev->ma++; + screen->line[dev->displine][(x << 3) + 8].pal = + screen->line[dev->displine][(x << 3) + 9].pal = dev->array[((dat >> 12) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 10].pal = + screen->line[dev->displine][(x << 3) + 11].pal = dev->array[((dat >> 8) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 12].pal = + screen->line[dev->displine][(x << 3) + 13].pal = dev->array[((dat >> 4) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 14].pal = + screen->line[dev->displine][(x << 3) + 15].pal = dev->array[(dat & dev->array[1]) + 16] + 16; + } + } else if (dev->array[3] & 0x10) { /*160x200x16*/ + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000) + 1]; + dev->ma++; + screen->line[dev->displine][(x << 4) + 8].pal = + screen->line[dev->displine][(x << 4) + 9].pal = + screen->line[dev->displine][(x << 4) + 10].pal = + screen->line[dev->displine][(x << 4) + 11].pal = dev->array[((dat >> 12) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 12].pal = + screen->line[dev->displine][(x << 4) + 13].pal = + screen->line[dev->displine][(x << 4) + 14].pal = + screen->line[dev->displine][(x << 4) + 15].pal = dev->array[((dat >> 8) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 16].pal = + screen->line[dev->displine][(x << 4) + 17].pal = + screen->line[dev->displine][(x << 4) + 18].pal = + screen->line[dev->displine][(x << 4) + 19].pal = dev->array[((dat >> 4) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 20].pal = + screen->line[dev->displine][(x << 4) + 21].pal = + screen->line[dev->displine][(x << 4) + 22].pal = + screen->line[dev->displine][(x << 4) + 23].pal = dev->array[(dat & dev->array[1]) + 16] + 16; + } + } else if (dev->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000) + 1]; + dev->ma++; + for (c = 0; c < 8; c++) { + chr = (dat >> 7) & 1; + chr |= ((dat >> 14) & 2); + screen->line[dev->displine][(x << 3) + 8 + c].pal = dev->array[(chr & dev->array[1]) + 16] + 16; + dat <<= 1; + } + } + } else if (dev->mode & 1) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[ (dev->ma << 1) & 0x3fff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->mode & 0x20) { + cols[1] = dev->array[ ((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[(((attr >> 4) & 7) & dev->array[1]) + 16] + 16; + if ((dev->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = dev->array[((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[((attr >> 4) & dev->array[1]) + 16] + 16; + } + if (dev->sc & 8) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c + 8].pal = cols[0]; + } else { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c + 8].pal = cols[(dev->fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + if (drawcursor) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c + 8].pal ^= 15; + } + dev->ma++; + } + } else if (! (dev->mode & 2)) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[ (dev->ma << 1) & 0x3fff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->mode & 0x20) { + cols[1] = dev->array[ ((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[(((attr >> 4) & 7) & dev->array[1]) + 16] + 16; + if ((dev->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = dev->array[((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[((attr >> 4) & dev->array[1]) + 16] + 16; + } + dev->ma++; + if (dev->sc & 8) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[0]; + } else { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(dev->fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + if (drawcursor) { + for (c = 0; c < 16; c++) + screen->line[dev->displine][(x << 4) + c + 8].pal ^= 15; + } + } + } else if (! (dev->mode& 16)) { + cols[0] = (dev->col & 15) | 16; + col = (dev->col & 16) ? 24 : 16; + if (dev->mode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (dev->col & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1]; + dev->ma++; + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + cols[0] = 0; + cols[1] = dev->array[(dev->col & dev->array[1]) + 16] + 16; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1]; + dev->ma++; + for (c = 0; c < 16; c++) { + screen->line[dev->displine][(x << 4) + c + 8].pal = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + if (dev->array[3] & 4) { + if (dev->mode & 1) + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 3) + 16, (dev->array[2] & 0xf) + 16); + else + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 4) + 16, (dev->array[2] & 0xf) + 16); + } else { + cols[0] = ((dev->mode & 0x12) == 0x12) ? 0 : (dev->col & 0xf) + 16; + if (dev->mode & 1) + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 3) + 16, cols[0]); + else + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 4) + 16, cols[0]); + } + } + + if (dev->mode & 1) + x = (dev->crtc[1] << 3) + 16; + else + x = (dev->crtc[1] << 4) + 16; + if (dev->composite) + cga_comp_process(dev->cpriv, dev->mode, 0, x >> 2, screen->line[dev->displine]); + + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 360) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; + } + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (! dev->vadj) + dev->dispon = 1; + if (! dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if (dev->mode & 1) + x = (dev->crtc[1] << 3) + 16; + else + x = (dev->crtc[1] << 4) + 16; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, (ysize << 1) + 16); + if (video_force_resize_get()) + video_force_resize_set(0); + } + if (dev->composite) + video_blit_start(0, 0, dev->firstline-4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); + else + video_blit_start(1, 0, dev->firstline-4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); + + frames++; + + video_res_x = xsize - 16; + video_res_y = ysize; + if ((dev->array[3] & 0x10) && (dev->mode & 1)) { /*320x200x16*/ + video_res_x /= 2; + video_bpp = 4; + } else if (dev->array[3] & 0x10) { /*160x200x16*/ + video_res_x /= 4; + video_bpp = 4; + } else if (dev->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + video_bpp = 2; + } else if (dev->mode & 1) { + video_res_x /= 8; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else if (! (dev->mode & 2)) { + video_res_x /= 16; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else if (! (dev->mode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } +} + + +static void +vid_poll_sl(void *priv) +{ + t1kvid_t *dev = (t1kvid_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c; + int oldvc; + uint8_t chr, attr; + uint16_t dat; + int cols[4]; + int col; + int oldsc; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_blit_wait_buffer(); + } + dev->lastline = dev->displine; + cols[0] = (dev->array[2] & 0xf) + 16; + for (c = 0; c < 8; c++) { + if (dev->array[3] & 4) { + screen->line[dev->displine][c].pal = cols[0]; + if (dev->mode & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = cols[0]; + else + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = cols[0]; + } else if ((dev->mode & 0x12) == 0x12) { + screen->line[dev->displine][c].pal = 0; + if (dev->mode & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = 0; + else + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = 0; + } else { + screen->line[dev->displine][c].pal = (dev->col & 15) + 16; + if (dev->mode & 1) + screen->line[dev->displine][c + (dev->crtc[1] << 3) + 8].pal = (dev->col & 15) + 16; + else + screen->line[dev->displine][c + (dev->crtc[1] << 4) + 8].pal = (dev->col & 15) + 16; + } + } + if (dev->array[5] & 1) { /*640x200x16*/ + for (x = 0; x < dev->crtc[1]*2; x++) { + dat = (dev->vram[(dev->ma << 1) & 0xffff] << 8) | + dev->vram[((dev->ma << 1) + 1) & 0xffff]; + dev->ma++; + screen->line[dev->displine][(x << 2) + 8].pal = dev->array[((dat >> 12) & 0xf)/*dev->array[1])*/ + 16] + 16; + screen->line[dev->displine][(x << 2) + 9].pal = dev->array[((dat >> 8) & 0xf)/*dev->array[1])*/ + 16] + 16; + screen->line[dev->displine][(x << 2) + 10].pal = dev->array[((dat >> 4) & 0xf)/*dev->array[1])*/ + 16] + 16; + screen->line[dev->displine][(x << 2) + 11].pal = dev->array[(dat & 0xf)/*dev->array[1])*/ + 16] + 16; + } + } else if ((dev->array[3] & 0x10) && (dev->mode & 1)) { /*320x200x16*/ + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000) + 1]; + dev->ma++; + screen->line[dev->displine][(x << 3) + 8].pal = + screen->line[dev->displine][(x << 3) + 9].pal = dev->array[((dat >> 12) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 10].pal = + screen->line[dev->displine][(x << 3) + 11].pal = dev->array[((dat >> 8) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 12].pal = + screen->line[dev->displine][(x << 3) + 13].pal = dev->array[((dat >> 4) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 3) + 14].pal = + screen->line[dev->displine][(x << 3) + 15].pal = dev->array[(dat & dev->array[1]) + 16] + 16; + } + } else if (dev->array[3] & 0x10) { /*160x200x16*/ + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1]; + dev->ma++; + screen->line[dev->displine][(x << 4) + 8].pal = + screen->line[dev->displine][(x << 4) + 9].pal = + screen->line[dev->displine][(x << 4) + 10].pal = + screen->line[dev->displine][(x << 4) + 11].pal = dev->array[((dat >> 12) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 12].pal = + screen->line[dev->displine][(x << 4) + 13].pal = + screen->line[dev->displine][(x << 4) + 14].pal = + screen->line[dev->displine][(x << 4) + 15].pal = dev->array[((dat >> 8) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 16].pal = + screen->line[dev->displine][(x << 4) + 17].pal = + screen->line[dev->displine][(x << 4) + 18].pal = + screen->line[dev->displine][(x << 4) + 19].pal = dev->array[((dat >> 4) & dev->array[1]) + 16] + 16; + screen->line[dev->displine][(x << 4) + 20].pal = + screen->line[dev->displine][(x << 4) + 21].pal = + screen->line[dev->displine][(x << 4) + 22].pal = + screen->line[dev->displine][(x << 4) + 23].pal = dev->array[(dat & dev->array[1]) + 16] + 16; + } + } else if (dev->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 3) * 0x2000) + 1]; + dev->ma++; + for (c = 0; c < 8; c++) { + chr = (dat >> 7) & 1; + chr |= ((dat >> 14) & 2); + screen->line[dev->displine][(x << 3) + 8 + c].pal = dev->array[(chr & dev->array[1]) + 16] + 16; + dat <<= 1; + } + } + } else if (dev->mode & 1) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[ (dev->ma << 1) & 0x3fff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->mode & 0x20) { + cols[1] = dev->array[ ((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[(((attr >> 4) & 7) & dev->array[1]) + 16] + 16; + if ((dev->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = dev->array[((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[((attr >> 4) & dev->array[1]) + 16] + 16; + } + if (dev->sc & 8) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c + 8].pal = cols[0]; + } else { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c + 8].pal = cols[(dev->fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + if (drawcursor) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c + 8].pal ^= 15; + } + dev->ma++; + } + } else if (! (dev->mode & 2)) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[ (dev->ma << 1) & 0x3fff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->mode & 0x20) { + cols[1] = dev->array[ ((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[(((attr >> 4) & 7) & dev->array[1]) + 16] + 16; + if ((dev->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = dev->array[((attr & 15) & dev->array[1]) + 16] + 16; + cols[0] = dev->array[((attr >> 4) & dev->array[1]) + 16] + 16; + } + dev->ma++; + if (dev->sc & 8) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[0]; + } else { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[(dev->fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + if (drawcursor) { + for (c = 0; c < 16; c++) + screen->line[dev->displine][(x << 4) + c + 8].pal ^= 15; + } + } + } else if (! (dev->mode & 16)) { + cols[0] = (dev->col & 15) | 16; + col = (dev->col & 16) ? 24 : 16; + if (dev->mode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (dev->col & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1]; + dev->ma++; + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + (c << 1) + 8].pal = + screen->line[dev->displine][(x << 4) + (c << 1) + 1 + 8].pal = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + cols[0] = 0; + cols[1] = dev->array[(dev->col & dev->array[1]) + 16] + 16; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000)] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1]; + dev->ma++; + for (c = 0; c < 16; c++) { + screen->line[dev->displine][(x << 4) + c + 8].pal = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + if (dev->array[3] & 4) { + if (dev->mode & 1) + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 3) + 16, (dev->array[2] & 0xf) + 16); + else + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 4) + 16, (dev->array[2] & 0xf) + 16); + } else { + cols[0] = ((dev->mode & 0x12) == 0x12) ? 0 : (dev->col & 0xf) + 16; + if (dev->mode & 1) + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 3) + 16, cols[0]); + else + cga_hline(screen, 0, dev->displine, (dev->crtc[1] << 4) + 16, cols[0]); + } + } + + if (dev->mode & 1) + x = (dev->crtc[1] << 3) + 16; + else + x = (dev->crtc[1] << 4) + 16; + dev->sc = oldsc; + + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 360) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; + } + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + if (dev->array[5] & 1) + dev->ma = dev->maback = dev->crtc[13] | (dev->crtc[12] << 8); + else + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 255; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (! dev->vadj) + dev->dispon = 1; + if (! dev->vadj) { + if (dev->array[5] & 1) + dev->ma = dev->maback = dev->crtc[13] | (dev->crtc[12] << 8); + else + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + } + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if (dev->mode & 1) + x = (dev->crtc[1] << 3) + 16; + else + x = (dev->crtc[1] << 4) + 16; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + + set_screen_size(xsize, (ysize << 1) + 16); + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_start(1, 0, dev->firstline-4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); + + frames++; + video_res_x = xsize - 16; + video_res_y = ysize; + if ((dev->array[3] & 0x10) && (dev->mode & 1)) { /*320x200x16*/ + video_res_x /= 2; + video_bpp = 4; + } else if (dev->array[3] & 0x10) { /*160x200x16*/ + video_res_x /= 4; + video_bpp = 4; + } else if (dev->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + video_bpp = 2; + } else if (dev->mode & 1) { + video_res_x /= 8; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else if (! (dev->mode & 2)) { + video_res_x /= 16; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else if (! (dev->mode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } +} + + +static void +speed_changed(void *priv) +{ + t1kvid_t *dev = (t1kvid_t *)priv; + + recalc_timings(dev); +} + + +static void +vid_close(void *priv) +{ + t1kvid_t *dev = (t1kvid_t *)priv; + + if (dev->cpriv != NULL) { + cga_comp_close(dev->cpriv); + dev->cpriv = NULL; + } + + free(dev); +} + + +static const device_t tandy1k_video = { + "Tandy 1000 Video", + 0, 0, + NULL, + NULL, vid_close, NULL, + NULL, + speed_changed, + NULL, NULL, + NULL +}; + + +/* Load a font from its ROM source. */ +static void +load_font(t1kvid_t *dev, const wchar_t *fn) +{ + FILE *fp; + int c; + + fp = plat_fopen(rom_path(fn), L"rb"); + if (fp == NULL) { + ERRLOG("Tandy1000: cannot load font '%ls'\n", fn); + return; + } + + for (c = 0; c < 256; c++) + (void)fread(&dev->fontdat[c][0], 1, 8, fp); + (void)fclose(fp); +} + + +void +tandy1k_video_init(int type, int display_type, uint32_t base, const wchar_t *fn) +{ + t1kvid_t *dev; + + dev = (t1kvid_t *)mem_alloc(sizeof(t1kvid_t)); + memset(dev, 0x00, sizeof(t1kvid_t)); + dev->type = type; + dev->base = base; + dev->memctrl = -1; + + /* Add the video device. */ + device_add_ex(&tandy1k_video, dev); + + load_font(dev, fn); + + dev->composite = (display_type != 0); + if (dev->composite) + dev->cpriv = cga_comp_init(1); + + if (dev->type == 2) { + dev->b8000_limit = 0x8000; + dev->planar_ctrl = 4; + overscan_x = overscan_y = 16; + + io_sethandler(0x0065, 1, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + + timer_add(vid_poll_sl, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + } else { + dev->b8000_mask = 0x3fff; + + timer_add(vid_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + } + + mem_map_add(&dev->mapping, 0xb8000, 0x08000, + vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); + + io_sethandler(0x03d0, 16, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + + video_inform(VID_TYPE_CGA, &tandy_timing); +} diff --git a/src/machines/m_xt_t1000.c b/src/machines/m_tosh1x00.c similarity index 57% rename from src/machines/m_xt_t1000.c rename to src/machines/m_tosh1x00.c index 93711e7..1d539fe 100644 --- a/src/machines/m_xt_t1000.c +++ b/src/machines/m_tosh1x00.c @@ -1,1109 +1,1162 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Toshiba T1000 and T1200 portables. - * - * The T1000 is the T3100e's little brother -- a real laptop - * with a rechargeable battery. - * - * Features: 80C88 at 4.77MHz - * - 512k system RAM - * - 640x200 monochrome LCD - * - 82-key keyboard - * - Real-time clock. Not the normal 146818, but a TC8521, - * which is a 4-bit chip. - * - A ROM drive (128k, 256k or 512k) which acts as a mini - * hard drive and contains a copy of DOS 2.11. - * - 160 bytes of non-volatile RAM for the CONFIG.SYS used - * when booting from the ROM drive. Possibly physically - * located in the keyboard controller RAM. - * - * An optional memory expansion board can be fitted. This adds - * 768k of RAM, which can be used for up to three purposes: - * > Conventional memory -- 128k between 512k and 640k - * > HardRAM -- a battery-backed RAM drive. - * > EMS - * - * This means that there are up to three different - * implementations of non-volatile RAM in the same computer - * (52 nibbles in the TC8521, 160 bytes of CONFIG.SYS, and - * up to 768k of HardRAM). - * - * The T1200 is a slightly upgraded version with a turbo mode - * (double CPU clock, 9.54MHz) and an optional hard drive. - * - * The hard drive is a JVC JD-3824R00-1 (20MB, 615/2/34) RLL - * 3.5" drive with custom 26-pin interface. This is what is - * known about the drive: - * - * JD-3824G is a 20MB hard disk drive that JVC made as one - * of OEM products. This HDD was shipped to Laptop PC - * manufactures. - * - * This HDD was discontinued about 10 years ago and JVC - * America does not have detail information because of the - * OEM product. - * - * This is the information that I have. - * [JD-3824G] - * 1. 3.5" 20MB Hard Disk Drive - * 2. JVC original interface (26 pin) - * This is not the IDE interface. This drive was made long - * before IDE standard. It required special controller board. - * This interface is not compatible with any other disk - * interface. - * - * Pin 1 GND Pin 2 -Read Data - * Pin 3 GND Pin 4 -Write data - * Pin 5 GND Pin 6 Reserved - * Pin 7 -Drive Select/+Power Save Pin 8 -Ship Ready - * Pin 9 GND Pin 10 +Read/-Write control - * Pin 11 -Motor On Pin 12 Head Select(+Head 0/ - Head1) - * Pin 13 -Direction In Pin 14 -Step - * Pin 15 -Write Fault Pin 16 -Seek Complete - * Pin 17 -Servo Gate Pin 18 -Index - * Pin 19 -Track 000 Pin 20 -Drive Ready - * Pin 21 GND Pin 22 +5V - * Pin 23 GND Pin 24 +5V - * Pin 25 GND Pin 26 +12V - * - * 3. Parameters( 2 heads, 34 sectors, 615 cylinders) - * 4. 2-7 RLL coding - * 5. Spindle Rotation: 2597 rpm - * 6. Data Transfer: 7.5M bps - * 7. Average Access: 78ms - * 8. Power Voltage: 5V and 12V - * - * (from Jeff Kishida, JVC Americas, Corp. - * Tel: 714-827-6267 Fax: 714-827-8740 - * Email: Jeff.Kishida@worldnet.att.net) - * - * The controller is on a separate PCB, and contains a T7518, - * DC2090P166A and a 27256 EPROM (label "036A") with BIOS. The - * interface for this is proprietary at the rogramming level. - * - * 01F2h: If hard drive is present, low 4 bits are 0Ch [20Mb] - * or 0Dh [10Mb]. - * - * The TC8521 is a 4-bit RTC, so each memory location can only - * hold a single BCD digit. Hence everything has 'ones' and - * 'tens' digits. - * - * FIXME: The ROM drive should be re-done using the "option file". - * - * Version: @(#)m_xt_t1000.c 1.0.16 2019/03/05 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * John Elliott, - * - * Copyright 2018,2019 Fred N. van Kempen. - * Copyright 2018 Miran Grca. - * Copyright 2017,2018 John Elliott. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include -#include "../emu.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../devices/system/nmi.h" -#include "../devices/system/pit.h" -#include "../devices/ports/parallel.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "../devices/disk/hdc.h" -#include "../devices/video/video.h" -#include "../plat.h" -#include "machine.h" -#include "m_xt_t1000.h" - - -#define T1000_ROMDOS_SIZE (512*1024UL) /* Max romdrive size is 512k */ -#define T1000_ROMDOS_PATH L"machines/toshiba/t1000/t1000dos.rom" -#define T1000_FONT_PATH L"machines/toshiba/t1000/t1000font.rom" -#define T1200_FONT_PATH L"machines/toshiba/t1200/t1000font.bin" - - -enum TC8521_ADDR { - /* Page 0 registers */ - TC8521_SECOND1 = 0, - TC8521_SECOND10, - TC8521_MINUTE1, - TC8521_MINUTE10, - TC8521_HOUR1, - TC8521_HOUR10, - TC8521_WEEKDAY, - TC8521_DAY1, - TC8521_DAY10, - TC8521_MONTH1, - TC8521_MONTH10, - TC8521_YEAR1, - TC8521_YEAR10, - TC8521_PAGE, /* PAGE register */ - TC8521_TEST, /* TEST register */ - TC8521_RESET, /* RESET register */ - - /* Page 1 registers */ - TC8521_24HR = 0x1A, - TC8521_LEAPYEAR = 0x1B -}; - - -typedef struct { - /* ROM drive */ - int8_t rom_dos, - is_t1200; - - uint8_t rom_ctl; - uint32_t rom_offset; - uint8_t *romdrive; - mem_map_t rom_mapping; - - /* CONFIG.SYS drive. */ - wchar_t cfgsys_fn[128]; - uint16_t cfgsys_len; - uint8_t *cfgsys; - - /* System control registers */ - uint8_t sys_ctl[16]; - uint8_t syskeys; - uint8_t turbo; - - /* NVRAM control */ - uint8_t nvr_c0; - uint8_t nvr_tick; - int nvr_addr; - uint8_t nvr_active; - mem_map_t nvr_mapping; /* T1200 NVRAM mapping */ - - /* EMS data */ - uint8_t ems_reg[4]; - mem_map_t mapping[4]; - uint32_t page_exec[4]; - uint8_t ems_port_index; - uint16_t ems_port; - uint8_t is_640k; - uint32_t ems_base; - int32_t ems_pages; - - fdc_t *fdc; - - nvr_t nvr; -} t1000_t; - - -static t1000_t t1000; - - -/* Set the chip time. */ -static void -tc8521_time_set(uint8_t *regs, struct tm *tm) -{ - regs[TC8521_SECOND1] = (tm->tm_sec % 10); - regs[TC8521_SECOND10] = (tm->tm_sec / 10); - regs[TC8521_MINUTE1] = (tm->tm_min % 10); - regs[TC8521_MINUTE10] = (tm->tm_min / 10); - if (regs[TC8521_24HR] & 0x01) { - regs[TC8521_HOUR1] = (tm->tm_hour % 10); - regs[TC8521_HOUR10] = (tm->tm_hour / 10); - } else { - regs[TC8521_HOUR1] = ((tm->tm_hour % 12) % 10); - regs[TC8521_HOUR10] = (((tm->tm_hour % 12) / 10) | - ((tm->tm_hour >= 12) ? 2 : 0)); - } - regs[TC8521_WEEKDAY] = tm->tm_wday; - regs[TC8521_DAY1] = (tm->tm_mday % 10); - regs[TC8521_DAY10] = (tm->tm_mday / 10); - regs[TC8521_MONTH1] = ((tm->tm_mon + 1) % 10); - regs[TC8521_MONTH10] = ((tm->tm_mon + 1) / 10); - regs[TC8521_YEAR1] = ((tm->tm_year - 80) % 10); - regs[TC8521_YEAR10] = (((tm->tm_year - 80) % 100) / 10); -} - - -/* Get the chip time. */ -#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) -static void -tc8521_time_get(uint8_t *regs, struct tm *tm) -{ - tm->tm_sec = nibbles(TC8521_SECOND); - tm->tm_min = nibbles(TC8521_MINUTE); - if (regs[TC8521_24HR] & 0x01) - tm->tm_hour = nibbles(TC8521_HOUR); - else - tm->tm_hour = ((nibbles(TC8521_HOUR) % 12) + - (regs[TC8521_HOUR10] & 0x02) ? 12 : 0); -//FIXME: wday - tm->tm_mday = nibbles(TC8521_DAY); - tm->tm_mon = (nibbles(TC8521_MONTH) - 1); - tm->tm_year = (nibbles(TC8521_YEAR) + 1980); -} - - -/* This is called every second through the NVR/RTC hook. */ -static void -tc8521_tick(nvr_t *nvr) -{ - DEBUG("TC8521: ping\n"); -} - - -static void -tc8521_start(nvr_t *nvr) -{ - struct tm tm; - - /* Initialize the internal and chip times. */ - if (time_sync != TIME_SYNC_DISABLED) { - /* Use the internal clock's time. */ - nvr_time_get(&tm); - tc8521_time_set(nvr->regs, &tm); - } else { - /* Set the internal clock from the chip time. */ - tc8521_time_get(nvr->regs, &tm); - nvr_time_set(&tm); - } - -#if 0 - /* Start the RTC - BIOS will do this. */ - nvr->regs[TC8521_PAGE] |= 0x80; -#endif -} - - -/* Write to one of the chip registers. */ -static void -tc8521_write(uint16_t addr, uint8_t val, void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - uint8_t page; - - /* Get to the correct register page. */ - addr &= 0x0f; - page = nvr->regs[0x0d] & 0x03; - if (addr < 0x0d) - addr += (16 * page); - - if (addr >= 0x10 && nvr->regs[addr] != val) - nvr_dosave = 1; - - /* Store the new value. */ - nvr->regs[addr] = val; -} - - -/* Read from one of the chip registers. */ -static uint8_t -tc8521_read(uint16_t addr, void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - uint8_t page; - - /* Get to the correct register page. */ - addr &= 0x0f; - page = nvr->regs[0x0d] & 0x03; - if (addr < 0x0d) - addr += (16 * page); - - /* Grab and return the desired value. */ - return(nvr->regs[addr]); -} - - -/* Reset the 8521 to a default state. */ -static void -tc8521_reset(nvr_t *nvr) -{ - /* Clear the NVRAM. */ - memset(nvr->regs, 0xff, nvr->size); - - /* Reset the RTC registers. */ - memset(nvr->regs, 0x00, 16); - nvr->regs[TC8521_WEEKDAY] = 0x01; - nvr->regs[TC8521_DAY1] = 0x01; - nvr->regs[TC8521_MONTH1] = 0x01; -} - - -static void -tc8521_init(nvr_t *nvr, int size) -{ - /* This is machine specific. */ - nvr->size = size; - nvr->irq = -1; - - /* Set up any local handlers here. */ - nvr->reset = tc8521_reset; - nvr->start = tc8521_start; - nvr->tick = tc8521_tick; - - /* Initialize the actual NVR. */ - nvr_init(nvr); - - io_sethandler(0x02c0, 16, - tc8521_read,NULL,NULL, tc8521_write,NULL,NULL, nvr); -} - - -/* Given an EMS page ID, return its physical address in RAM. */ -static uint32_t -ems_execaddr(t1000_t *sys, int pg, uint16_t val) -{ - if (!(val & 0x80)) return(0); /* Bit 7 reset => not mapped */ - if (!sys->ems_pages) return(0); /* No EMS available: all used by - * HardRAM or conventional RAM */ - val &= 0x7f; - - DBGLOG(1, "Select EMS page: %d of %d\n", val, sys->ems_pages); - if (val < sys->ems_pages) { - /* EMS is any memory above 512k, - with ems_base giving the start address */ - return((512 * 1024) + (sys->ems_base * 0x10000) + (0x4000 * val)); - } - - return(0); -} - - -static uint8_t -ems_in(uint16_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - uint8_t ret; - - ret = sys->ems_reg[(addr >> 14) & 3]; - DBGLOG(1, "ems_in(%04x)=%02x\n", addr, ret); - - return(ret); -} - - -static void -ems_out(uint16_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = (addr >> 14) & 3; - - DBGLOG(1, "ems_out(%04x, %02x) pg=%d\n", addr, val, pg); - - sys->ems_reg[pg] = val; - sys->page_exec[pg] = ems_execaddr(sys, pg, val); - if (sys->page_exec[pg]) { - /* Page present */ - mem_map_enable(&sys->mapping[pg]); - mem_map_set_exec(&sys->mapping[pg], ram + sys->page_exec[pg]); - } else { - mem_map_disable(&sys->mapping[pg]); - } -} - - -/* Hardram size is in 64k units */ -static void -ems_set_hardram(t1000_t *sys, uint8_t val) -{ - int n; - - val &= 0x1f; /* Mask off pageframe address */ - if (val && mem_size > 512) - sys->ems_base = val; - else - sys->ems_base = 0; - - DEBUG("EMS base set to %02x\n", val); - sys->ems_pages = ((mem_size - 512) / 16) - 4 * sys->ems_base; - if (sys->ems_pages < 0) sys->ems_pages = 0; - - /* Recalculate EMS mappings */ - for (n = 0; n < 4; n++) - ems_out(n << 14, sys->ems_reg[n], sys); -} - - -static void -ems_set_640k(t1000_t *sys, uint8_t val) -{ - if (val && mem_size >= 640) { - mem_map_set_addr(&ram_low_mapping, 0, 640 * 1024); - sys->is_640k = 1; - } else { - mem_map_set_addr(&ram_low_mapping, 0, 512 * 1024); - sys->is_640k = 0; - } -} - - -static void -ems_set_port(t1000_t *sys, uint8_t val) -{ - int n; - - DBGLOG(1, "ems_set_port(%d)", val & 0x0f); - if (sys->ems_port) { - for (n = 0; n <= 0xc000; n += 0x4000) { - io_removehandler(sys->ems_port+n, 1, - ems_in,NULL,NULL, ems_out,NULL,NULL, sys); - } - sys->ems_port = 0; - } - - val &= 0x0f; - sys->ems_port_index = val; - if (val == 7) { - /* No EMS */ - sys->ems_port = 0; - } else { - sys->ems_port = 0x208 | (val << 4); - for (n = 0; n <= 0xc000; n += 0x4000) { - io_sethandler(sys->ems_port+n, 1, - ems_in,NULL,NULL, ems_out,NULL,NULL, sys); - } - sys->ems_port = 0; - } - - DBGLOG(1, " -> %04x\n", sys->ems_port); -} - - -static int -addr_to_page(uint32_t addr) -{ - return((addr - 0xd0000) / 0x4000); -} - - -/* Read RAM in the EMS page frame. */ -static uint8_t -ems_read_ram(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return(0xff); - addr = sys->page_exec[pg] + (addr & 0x3fff); - - return(ram[addr]); -} - - -static uint16_t -ems_read_ramw(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return(0xff); - - DBGLOG(1, "ems_read_ramw addr=%05x ", addr); - addr = sys->page_exec[pg] + (addr & 0x3FFF); - DBGLOG(1, "-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); - - return(*(uint16_t *)&ram[addr]); -} - - -static uint32_t -ems_read_raml(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return(0xff); - addr = sys->page_exec[pg] + (addr & 0x3fff); - - return(*(uint32_t *)&ram[addr]); -} - - -/* Write RAM in the EMS page frame. */ -static void -ems_write_ram(uint32_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - - addr = sys->page_exec[pg] + (addr & 0x3fff); - if (ram[addr] != val) nvr_dosave = 1; - - ram[addr] = val; -} - - -static void -ems_write_ramw(uint32_t addr, uint16_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - - DBGLOG(1, "ems_write_ramw addr=%05x ", addr); - addr = sys->page_exec[pg] + (addr & 0x3fff); - DBGLOG(1, "-> %06x val=%04x\n", addr, val); - - if (*(uint16_t *)&ram[addr] != val) nvr_dosave = 1; - - *(uint16_t *)&ram[addr] = val; -} - - -static void -ems_write_raml(uint32_t addr, uint32_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - - addr = sys->page_exec[pg] + (addr & 0x3fff); - if (*(uint32_t *)&ram[addr] != val) nvr_dosave = 1; - - *(uint32_t *)&ram[addr] = val; -} - - -static uint8_t -read_ctl(uint16_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - uint8_t ret = 0xff; - - switch (addr & 0x0f) { - case 1: - ret = sys->syskeys; - break; - - case 0x0f: /* Detect EMS board */ - switch (sys->sys_ctl[0x0e]) { - case 0x50: - if (mem_size > 512) break; - ret = (0x90 | sys->ems_port_index); - break; - - case 0x51: - /* 0x60 is the page frame address: - (0xd000 - 0xc400) / 0x20 */ - ret = (sys->ems_base | 0x60); - break; - - case 0x52: - ret = (sys->is_640k ? 0x80 : 0); - break; - } - break; - - default: - ret = (sys->sys_ctl[addr & 0x0f]); - } - - return(ret); -} - - -/* Load contents of "CONFIG.SYS" device from file. */ -static void -cfgsys_load(t1000_t *dev) -{ - char temp[128]; - FILE *f; - - /* Set up the file's name. */ - sprintf(temp, "%s_cfgsys.nvr", machine_get_internal_name()); - mbstowcs(dev->cfgsys_fn, temp, sizeof_w(dev->cfgsys_fn)); - - /* Now attempt to load the file. */ - memset(dev->cfgsys, 0x1a, dev->cfgsys_len); - f = plat_fopen(nvr_path(dev->cfgsys_fn), L"rb"); - if (f != NULL) { - INFO("NVR: loaded CONFIG.SYS from '%ls'\n", dev->cfgsys_fn); - (void)fread(dev->cfgsys, dev->cfgsys_len, 1, f); - fclose(f); - } else - INFO("NVR: initialized CONFIG.SYS for '%ls'\n", dev->cfgsys_fn); -} - - -/* Write the contents of "CONFIG.SYS" to file. */ -static void -cfgsys_save(t1000_t *dev) -{ - FILE *f; - - /* Avoids writing empty files. */ - if (dev->cfgsys_len < 160) return; - - f = plat_fopen(nvr_path(dev->cfgsys_fn), L"wb"); - if (f != NULL) { - INFO("NVR: saved CONFIG.SYS to '%ls'\n", dev->cfgsys_fn); - (void)fwrite(dev->cfgsys, dev->cfgsys_len, 1, f); - fclose(f); - } -} - - -#if 0 /*NOT_USED*/ -/* All RAM beyond 512K is non-volatile */ -static void -emsboard_load(t1000_t *dev) -{ - FILE *f; - - if (mem_size > 512) { - f = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"rb"); - if (f != NULL) { - fread(&ram[512 * 1024], 1024, (mem_size - 512), f); - fclose(f); - } - } -} - - -static void -emsboard_save(t1000_t *dev) -{ - FILE *f; - - if (mem_size > 512) { - f = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"wb"); - if (f != NULL) { - fwrite(&ram[512 * 1024], 1024, (mem_size - 512), f); - fclose(f); - } - } -} -#endif - - -static void -t1200_turbo_set(uint8_t value) -{ - if (value == t1000.turbo) return; - - t1000.turbo = value; - if (! value) - cpu_dynamic_switch(0); - else - cpu_dynamic_switch(cpu); -} - - -static void -write_ctl(uint16_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - sys->sys_ctl[addr & 0x0f] = val; - switch (addr & 0x0f) { - case 4: /* Video control */ - if (sys->sys_ctl[3] == 0x5A) { - t1000_video_options_set((val & 0x20) ? 1 : 0); - t1000_display_set((val & 0x40) ? 0 : 1); - if (sys->is_t1200) - t1200_turbo_set((val & 0x80) ? 1 : 0); - } - break; - - /* - * It looks as if the T1200, like the T3100, can disable - * its builtin video chipset if it detects the presence of - * another video card. - */ - case 6: - if (sys->is_t1200) - t1000_video_enable(val & 0x01 ? 0 : 1); - break; - - case 0x0f: /* EMS control */ - switch (sys->sys_ctl[0x0e]) { - case 0x50: - ems_set_port(sys, val); - break; - - case 0x51: - ems_set_hardram(sys, val); - break; - - case 0x52: - ems_set_640k(sys, val); - break; - } - break; - } -} - - -/* Ports 0xC0 to 0xC3 appear to have two purposes: - * - * > Access to the 160 bytes of non-volatile RAM containing CONFIG.SYS - * > Reading the floppy changeline. I don't know why the Toshiba doesn't - * use the normal port 0x3F7 for this, but it doesn't. - * - */ -static uint8_t -t1000_read_nvram(uint16_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - uint8_t tmp = 0xff; - - switch (addr) { - case 0xc2: /* Read next byte from NVRAM */ - if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) - tmp = sys->cfgsys[sys->nvr_addr]; - sys->nvr_addr++; - break; - - case 0xc3: /* Read floppy changeline and NVRAM ready state */ - tmp = fdc_read(0x03f7, t1000.fdc); - - tmp = (tmp & 0x80) >> 3; /* Bit 4 is changeline */ - tmp |= (sys->nvr_active & 0xc0);/* Bits 6,7 are r/w mode */ - tmp |= 0x2e; /* Bits 5,3,2,1 always 1 */ - tmp |= (sys->nvr_active & 0x40) >> 6; /* Ready state */ - break; - } - - return(tmp); -} - - -static void -t1000_write_nvram(uint16_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - /* - * On the real T1000, port 0xC1 is only usable as the high byte - * of a 16-bit write to port 0xC0, with 0x5A in the low byte. - */ - switch (addr) { - case 0xc0: - sys->nvr_c0 = val; - break; - - case 0xc1: /* Write next byte to NVRAM */ - if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) { - if (sys->cfgsys[sys->nvr_addr] != val) - nvr_dosave = 1; - sys->cfgsys[sys->nvr_addr] = val; - } - sys->nvr_addr++; - break; - - case 0xc2: - break; - - case 0xc3: - /* - * At start of NVRAM read / write, 0x80 is written to - * port 0xC3. This seems to reset the NVRAM address - * counter. A single byte is then written (0xff for - * write, 0x00 for read) which appears to be ignored. - * Simulate that by starting the address counter off - * at -1. - */ - sys->nvr_active = val; - if (val == 0x80) - sys->nvr_addr = -1; - break; - } -} - - -/* Port 0xC8 controls the ROM drive */ -static uint8_t -t1000_read_rom_ctl(uint16_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - return(sys->rom_ctl); -} - - -static void -t1000_write_rom_ctl(uint16_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - sys->rom_ctl = val; - if (sys->romdrive && (val & 0x80)) { - /* Enable */ - sys->rom_offset = ((val & 0x7f) * 0x10000) % T1000_ROMDOS_SIZE; - mem_map_set_addr(&sys->rom_mapping, 0xa0000, 0x10000); - mem_map_set_exec(&sys->rom_mapping, sys->romdrive + sys->rom_offset); - mem_map_enable(&sys->rom_mapping); - } else { - mem_map_disable(&sys->rom_mapping); - } -} - - -/* Read the ROM drive */ -static uint8_t -t1000_read_rom(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - if (! sys->romdrive) return(0xff); - - return(sys->romdrive[sys->rom_offset + (addr & 0xffff)]); -} - - -static uint16_t -t1000_read_romw(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - if (! sys->romdrive) return(0xffff); - - return(*(uint16_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); -} - - -static uint32_t -t1000_read_roml(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - if (! sys->romdrive) return(0xffffffff); - - return(*(uint32_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); -} - - -static const device_config_t m_xt_t1000_config[] = { - { - "rom_dos", "ROM DOS", CONFIG_SELECTION, "", 0, - { - { - "Disabled", 0 - }, - { - "Enabled", 1 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - - -const device_t m_xt_t1000_device = { - "Toshiba T1000", - MACHINE_ISA, - 0, - NULL, NULL, NULL, - NULL, - NULL, NULL, NULL, - m_xt_t1000_config -}; - - -void -m_xt_t1000_init(const machine_t *model, void *arg) -{ - FILE *f; - int pg; - - memset(&t1000, 0x00, sizeof(t1000)); - t1000.turbo = 0xff; - t1000.ems_port_index = 7; /* EMS disabled */ - - /* - * The ROM drive is optional. - * - * If the file is missing, continue to boot; the BIOS will - * complain 'No ROM drive' but boot normally from floppy. - */ - t1000.rom_dos = machine_get_config_int("rom_dos"); - if (t1000.rom_dos) { - f = plat_fopen(rom_path(T1000_ROMDOS_PATH), L"rb"); - if (f != NULL) { - t1000.romdrive = (uint8_t *)mem_alloc(T1000_ROMDOS_SIZE); - if (t1000.romdrive) { - memset(t1000.romdrive, 0xff, T1000_ROMDOS_SIZE); - fread(t1000.romdrive, T1000_ROMDOS_SIZE, 1, f); - } - fclose(f); - } - mem_map_add(&t1000.rom_mapping, 0xa0000, 0x10000, - t1000_read_rom,t1000_read_romw,t1000_read_roml, - NULL,NULL,NULL, NULL, MEM_MAPPING_INTERNAL, &t1000); - mem_map_disable(&t1000.rom_mapping); - } - - /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) { - mem_map_add(&t1000.mapping[pg], 0xd0000 + (0x4000 * pg), 16384, - ems_read_ram,ems_read_ramw,ems_read_raml, - ems_write_ram,ems_write_ramw,ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, &t1000); - - /* Start them all off disabled */ - mem_map_disable(&t1000.mapping[pg]); - } - - /* Non-volatile RAM for CONFIG.SYS */ - t1000.cfgsys_len = 160; - t1000.cfgsys = (uint8_t *)mem_alloc(t1000.cfgsys_len); - io_sethandler(0xc0, 4, - t1000_read_nvram,NULL,NULL, - t1000_write_nvram,NULL,NULL, &t1000); - cfgsys_load(&t1000); - - /* ROM drive */ - io_sethandler(0xc8, 1, - t1000_read_rom_ctl,NULL,NULL, - t1000_write_rom_ctl,NULL,NULL, &t1000); - - /* System control functions, and add-on memory board */ - io_sethandler(0xe0, 16, - read_ctl,NULL,NULL, write_ctl,NULL,NULL, &t1000); - - machine_common_init(model, arg); - - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - device_add(&keyboard_xt_device); - t1000.fdc = (fdc_t *)device_add(&fdc_xt_device); - nmi_init(); - - tc8521_init(&t1000.nvr, model->nvrsz); - - if (video_card == VID_INTERNAL) { - /* Load the T1000 CGA Font ROM. */ - video_load_font(T1000_FONT_PATH, FONT_CGA_THICK); - - device_add(&t1000_video_device); - } -} - - -static uint8_t -t1200_nvram_read(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - return(sys->cfgsys[addr & 0x7ff]); -} - - -static void -t1200_nvram_write(uint32_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - if (sys->cfgsys[addr & 0x7ff] != val) - nvr_dosave = 1; - - sys->cfgsys[addr & 0x7ff] = val; -} - - -void -m_xt_t1200_init(const machine_t *model, void *arg) -{ - int pg; - - memset(&t1000, 0x00, sizeof(t1000)); - t1000.ems_port_index = 7; /* EMS disabled */ - t1000.is_t1200 = 1; - - /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) { - mem_map_add(&t1000.mapping[pg], - 0xd0000 + (0x4000 * pg), 16384, - ems_read_ram,ems_read_ramw,ems_read_raml, - ems_write_ram,ems_write_ramw,ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, &t1000); - - /* Start them all off disabled */ - mem_map_disable(&t1000.mapping[pg]); - } - - /* System control functions, and add-on memory board */ - io_sethandler(0xe0, 16, - read_ctl,NULL,NULL, write_ctl,NULL,NULL, &t1000); - - machine_common_init(model, arg); - - /* Non-volatile RAM for CONFIG.SYS */ - t1000.cfgsys_len = 2048; - t1000.cfgsys = (uint8_t *)mem_alloc(t1000.cfgsys_len); - mem_map_add(&t1000.nvr_mapping, - 0x000f0000, t1000.cfgsys_len, - t1200_nvram_read,NULL,NULL, - t1200_nvram_write,NULL,NULL, - NULL, 0, &t1000); - cfgsys_load(&t1000); - - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - device_add(&keyboard_xt_device); - t1000.fdc = (fdc_t *)device_add(&fdc_toshiba_device); - nmi_init(); - - tc8521_init(&t1000.nvr, model->nvrsz); - - if (video_card == VID_INTERNAL) { - /* Load the T1200 CGA Font ROM. */ - video_load_font(T1200_FONT_PATH, FONT_CGA_THICK); - - device_add(&t1200_video_device); - } - - if (hdc_type == HDC_INTERNAL) - (void)device_add(&xta_t1200_device); -} - - -void -m_xt_t1x00_close(void) -{ - cfgsys_save(&t1000); -} - - -void -t1000_syskey(uint8_t andmask, uint8_t ormask, uint8_t xormask) -{ - t1000.syskeys &= ~andmask; - t1000.syskeys |= ormask; - t1000.syskeys ^= xormask; -} +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Toshiba T1000 and T1200 portables. + * + * The T1000 is the T3100e's little brother -- a real laptop + * with a rechargeable battery. + * + * Features: 80C88 at 4.77MHz + * - 512k system RAM + * - 640x200 monochrome LCD + * - 82-key keyboard + * - Real-time clock. Not the normal 146818, but a TC8521, + * which is a 4-bit chip. + * - A ROM drive (128k, 256k or 512k) which acts as a mini + * hard drive and contains a copy of DOS 2.11. + * - 160 bytes of non-volatile RAM for the CONFIG.SYS used + * when booting from the ROM drive. Possibly physically + * located in the keyboard controller RAM. + * + * An optional memory expansion board can be fitted. This adds + * 768K of RAM, which can be used for up to three purposes: + * > Conventional memory -- 128K between 512K and 640K + * > HardRAM -- a battery-backed RAM drive. + * > EMS + * + * This means that there are up to three different + * implementations of non-volatile RAM in the same computer + * (52 nibbles in the TC8521, 160 bytes of CONFIG.SYS, and + * up to 768K of HardRAM). + * + * The T1200 is a slightly upgraded version with a turbo mode + * (double CPU clock, 9.54MHz) and an optional hard drive. + * + * The hard drive is a JVC JD-3824R00-1 (20MB, 615/2/34) RLL + * 3.5" drive with custom 26-pin interface. This is what is + * known about the drive: + * + * JD-3824G is a 20MB hard disk drive that JVC made as one + * of OEM products. This HDD was shipped to Laptop PC + * manufactures. + * + * This HDD was discontinued about 10 years ago and JVC + * America does not have detail information because of the + * OEM product. + * + * This is the information that I have. + * [JD-3824G] + * 1. 3.5" 20MB Hard Disk Drive + * 2. JVC original interface (26 pin) + * This is not the IDE interface. This drive was made long + * before IDE standard. It required special controller board. + * This interface is not compatible with any other disk + * interface. + * + * Pin 1 GND Pin 2 -Read Data + * Pin 3 GND Pin 4 -Write data + * Pin 5 GND Pin 6 Reserved + * Pin 7 -Drive Select/+Power Save Pin 8 -Ship Ready + * Pin 9 GND Pin 10 +Read/-Write control + * Pin 11 -Motor On Pin 12 Head Select(+Head 0/ - Head1) + * Pin 13 -Direction In Pin 14 -Step + * Pin 15 -Write Fault Pin 16 -Seek Complete + * Pin 17 -Servo Gate Pin 18 -Index + * Pin 19 -Track 000 Pin 20 -Drive Ready + * Pin 21 GND Pin 22 +5V + * Pin 23 GND Pin 24 +5V + * Pin 25 GND Pin 26 +12V + * + * 3. Parameters( 2 heads, 34 sectors, 615 cylinders) + * 4. 2-7 RLL coding + * 5. Spindle Rotation: 2597 rpm + * 6. Data Transfer: 7.5M bps + * 7. Average Access: 78ms + * 8. Power Voltage: 5V and 12V + * + * (from Jeff Kishida, JVC Americas, Corp. + * Tel: 714-827-6267 Fax: 714-827-8740 + * Email: Jeff.Kishida@worldnet.att.net) + * + * The controller is on a separate PCB, and contains a T7518, + * DC2090P166A and a 27256 EPROM (label "036A") with BIOS. The + * interface for this is proprietary at the rogramming level. + * + * 01F2h: If hard drive is present, low 4 bits are 0Ch [20Mb] + * or 0Dh [10Mb]. + * + * The TC8521 is a 4-bit RTC, so each memory location can only + * hold a single BCD digit. Hence everything has 'ones' and + * 'tens' digits. + * + * FIXME: The ROM drive should be re-done using the "option file". + * + * Version: @(#)m_tosh1x00.c 1.0.18 2019/04/11 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, + * + * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2018 Miran Grca. + * Copyright 2017,2018 John Elliott. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../nvr.h" +#include "../devices/system/nmi.h" +#include "../devices/system/pit.h" +#include "../devices/ports/parallel.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" +#include "../devices/video/video.h" +#include "../plat.h" +#include "machine.h" +#include "m_tosh1x00.h" + + +#define T1000_ROMDOS_SIZE (512*1024UL) /* Max romdrive size is 512k */ +#define T1000_ROMDOS_PATH L"machines/toshiba/t1000/t1000dos.rom" +#define T1000_FONT_PATH L"machines/toshiba/t1000/t1000font.rom" +#define T1200_FONT_PATH L"machines/toshiba/t1200/t1000font.bin" + + +enum TC8521_ADDR { + /* Page 0 registers */ + TC8521_SECOND1 = 0, + TC8521_SECOND10, + TC8521_MINUTE1, + TC8521_MINUTE10, + TC8521_HOUR1, + TC8521_HOUR10, + TC8521_WEEKDAY, + TC8521_DAY1, + TC8521_DAY10, + TC8521_MONTH1, + TC8521_MONTH10, + TC8521_YEAR1, + TC8521_YEAR10, + TC8521_PAGE, /* PAGE register */ + TC8521_TEST, /* TEST register */ + TC8521_RESET, /* RESET register */ + + /* Page 1 registers */ + TC8521_24HR = 0x1A, + TC8521_LEAPYEAR = 0x1B +}; + + +typedef struct { + /* ROM drive */ + int8_t rom_dos, + is_t1200; + + uint8_t rom_ctl; + uint32_t rom_offset; + uint8_t *romdrive; + mem_map_t rom_mapping; + + /* CONFIG.SYS drive. */ + wchar_t cfgsys_fn[128]; + uint16_t cfgsys_len; + uint8_t *cfgsys; + + /* System control registers */ + uint8_t sys_ctl[16]; + uint8_t syskeys; + uint8_t turbo; + + /* NVRAM control */ + uint8_t nvr_c0; + uint8_t nvr_tick; + int nvr_addr; + uint8_t nvr_active; + mem_map_t nvr_mapping; /* T1200 NVRAM mapping */ + + /* EMS data */ + uint8_t ems_reg[4]; + mem_map_t mapping[4]; + uint32_t page_exec[4]; + uint8_t ems_port_index; + uint16_t ems_port; + uint8_t is_640k; + uint32_t ems_base; + int32_t ems_pages; + + fdc_t *fdc; + + nvr_t nvr; +} t1000_t; + + +/* Set the chip time. */ +static void +tc8521_time_set(uint8_t *regs, struct tm *tm) +{ + regs[TC8521_SECOND1] = (tm->tm_sec % 10); + regs[TC8521_SECOND10] = (tm->tm_sec / 10); + regs[TC8521_MINUTE1] = (tm->tm_min % 10); + regs[TC8521_MINUTE10] = (tm->tm_min / 10); + if (regs[TC8521_24HR] & 0x01) { + regs[TC8521_HOUR1] = (tm->tm_hour % 10); + regs[TC8521_HOUR10] = (tm->tm_hour / 10); + } else { + regs[TC8521_HOUR1] = ((tm->tm_hour % 12) % 10); + regs[TC8521_HOUR10] = (((tm->tm_hour % 12) / 10) | + ((tm->tm_hour >= 12) ? 2 : 0)); + } + regs[TC8521_WEEKDAY] = tm->tm_wday; + regs[TC8521_DAY1] = (tm->tm_mday % 10); + regs[TC8521_DAY10] = (tm->tm_mday / 10); + regs[TC8521_MONTH1] = ((tm->tm_mon + 1) % 10); + regs[TC8521_MONTH10] = ((tm->tm_mon + 1) / 10); + regs[TC8521_YEAR1] = ((tm->tm_year - 80) % 10); + regs[TC8521_YEAR10] = (((tm->tm_year - 80) % 100) / 10); +} + + +/* Get the chip time. */ +#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) +static void +tc8521_time_get(uint8_t *regs, struct tm *tm) +{ + tm->tm_sec = nibbles(TC8521_SECOND); + tm->tm_min = nibbles(TC8521_MINUTE); + if (regs[TC8521_24HR] & 0x01) + tm->tm_hour = nibbles(TC8521_HOUR); + else + tm->tm_hour = ((nibbles(TC8521_HOUR) % 12) + + (regs[TC8521_HOUR10] & 0x02) ? 12 : 0); +//FIXME: wday + tm->tm_mday = nibbles(TC8521_DAY); + tm->tm_mon = (nibbles(TC8521_MONTH) - 1); + tm->tm_year = (nibbles(TC8521_YEAR) + 1980); +} + + +/* This is called every second through the NVR/RTC hook. */ +static void +tc8521_tick(nvr_t *nvr) +{ + DEBUG("TC8521: ping\n"); +} + + +static void +tc8521_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (time_sync != TIME_SYNC_DISABLED) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + tc8521_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + tc8521_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + +#if 0 + /* Start the RTC - BIOS will do this. */ + nvr->regs[TC8521_PAGE] |= 0x80; +#endif +} + + +/* Write to one of the chip registers. */ +static void +tc8521_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t page; + + /* Get to the correct register page. */ + addr &= 0x0f; + page = nvr->regs[0x0d] & 0x03; + if (addr < 0x0d) + addr += (16 * page); + + if (addr >= 0x10 && nvr->regs[addr] != val) + nvr_dosave = 1; + + /* Store the new value. */ + nvr->regs[addr] = val; +} + + +/* Read from one of the chip registers. */ +static uint8_t +tc8521_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t page; + + /* Get to the correct register page. */ + addr &= 0x0f; + page = nvr->regs[0x0d] & 0x03; + if (addr < 0x0d) + addr += (16 * page); + + /* Grab and return the desired value. */ + return(nvr->regs[addr]); +} + + +/* Reset the 8521 to a default state. */ +static void +tc8521_reset(nvr_t *nvr) +{ + /* Clear the NVRAM. */ + memset(nvr->regs, 0xff, nvr->size); + + /* Reset the RTC registers. */ + memset(nvr->regs, 0x00, 16); + nvr->regs[TC8521_WEEKDAY] = 0x01; + nvr->regs[TC8521_DAY1] = 0x01; + nvr->regs[TC8521_MONTH1] = 0x01; +} + + +static void +tc8521_init(nvr_t *nvr, int size) +{ + /* This is machine specific. */ + nvr->size = size; + nvr->irq = -1; + + /* Set up any local handlers here. */ + nvr->reset = tc8521_reset; + nvr->start = tc8521_start; + nvr->tick = tc8521_tick; + + /* Initialize the actual NVR. */ + nvr_init(nvr); + + io_sethandler(0x02c0, 16, + tc8521_read,NULL,NULL, tc8521_write,NULL,NULL, nvr); +} + + +/* Given an EMS page ID, return its physical address in RAM. */ +static uint32_t +ems_execaddr(t1000_t *dev, int pg, uint16_t val) +{ + if (! (val & 0x80)) return(0); /* Bit 7 reset => not mapped */ + if (! dev->ems_pages) return(0); /* No EMS available: all used by + * HardRAM or conventional RAM */ + val &= 0x7f; + + DBGLOG(1, "Select EMS page: %i of %i\n", val, dev->ems_pages); + if (val < dev->ems_pages) { + /* EMS is any memory above 512K, + with ems_base giving the start address */ + return((512 * 1024) + (dev->ems_base * 0x10000) + (0x4000 * val)); + } + + return(0); +} + + +static uint8_t +ems_in(uint16_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + uint8_t ret; + + ret = dev->ems_reg[(addr >> 14) & 3]; + DBGLOG(1, "ems_in(%04x)=%02x\n", addr, ret); + + return(ret); +} + + +static void +ems_out(uint16_t addr, uint8_t val, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + int pg = (addr >> 14) & 3; + + DBGLOG(1, "ems_out(%04x, %02x) pg=%d\n", addr, val, pg); + + dev->ems_reg[pg] = val; + dev->page_exec[pg] = ems_execaddr(dev, pg, val); + if (dev->page_exec[pg]) { + /* Page present */ + mem_map_enable(&dev->mapping[pg]); + mem_map_set_exec(&dev->mapping[pg], ram + dev->page_exec[pg]); + } else { + mem_map_disable(&dev->mapping[pg]); + } +} + + +/* Hardram size is in 64K units. */ +static void +ems_set_hardram(t1000_t *dev, uint8_t val) +{ + int n; + + val &= 0x1f; /* mask off pageframe address */ + if (val && mem_size > 512) + dev->ems_base = val; + else + dev->ems_base = 0; + + DEBUG("EMS base set to %02x\n", val); + dev ->ems_pages = ((mem_size - 512) / 16) - 4 * dev->ems_base; + if (dev->ems_pages < 0) + dev->ems_pages = 0; + + /* Recalculate EMS mappings */ + for (n = 0; n < 4; n++) + ems_out(n << 14, dev->ems_reg[n], dev); +} + + +static void +ems_set_640k(t1000_t *dev, uint8_t val) +{ + if (val && mem_size >= 640) { + mem_map_set_addr(&ram_low_mapping, 0, 640 * 1024); + dev->is_640k = 1; + } else { + mem_map_set_addr(&ram_low_mapping, 0, 512 * 1024); + dev->is_640k = 0; + } +} + + +static void +ems_set_port(t1000_t *dev, uint8_t val) +{ + int n; + + DBGLOG(1, "ems_set_port(%d)", val & 0x0f); + if (dev->ems_port) { + for (n = 0; n <= 0xc000; n += 0x4000) { + io_removehandler(dev->ems_port + n, 1, + ems_in,NULL,NULL, ems_out,NULL,NULL, dev); + } + + dev->ems_port = 0; + } + + val &= 0x0f; + dev->ems_port_index = val; + if (val == 7) { + /* No EMS */ + dev->ems_port = 0; + } else { + dev->ems_port = 0x208 | (val << 4); + for (n = 0; n <= 0xc000; n += 0x4000) { + io_sethandler(dev->ems_port + n, 1, + ems_in,NULL,NULL, ems_out,NULL,NULL, dev); + } + + dev->ems_port = 0; + } + + DBGLOG(1, " -> %04x\n", dev->ems_port); +} + + +static int +addr_to_page(uint32_t addr) +{ + return((addr - 0xd0000) / 0x4000); +} + + +/* Read RAM in the EMS page frame. */ +static uint8_t +ems_read(uint32_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return(0xff); + addr = dev->page_exec[pg] + (addr & 0x3fff); + + return(ram[addr]); +} + + +static uint16_t +ems_readw(uint32_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + int pg = addr_to_page(addr); + uint16_t ret; + + if (pg < 0) return(0xff); + + DBGLOG(1, "ems_read_ramw addr=%05x ", addr); + addr = dev->page_exec[pg] + (addr & 0x3fff); + ret = *(uint16_t *)&ram[addr]; + + DBGLOG(1, "-> %06x val=%04x\n", addr, ret); + + return(ret); +} + + +static uint32_t +ems_readl(uint32_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + int pg = addr_to_page(addr); + uint32_t ret; + + if (pg < 0) return(0xff); + addr = dev->page_exec[pg] + (addr & 0x3fff); + ret = *(uint32_t *)&ram[addr]; + + return(ret); +} + + +/* Write RAM in the EMS page frame. */ +static void +ems_write(uint32_t addr, uint8_t val, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return; + + addr = dev->page_exec[pg] + (addr & 0x3fff); + if (ram[addr] != val) + nvr_dosave = 1; + + ram[addr] = val; +} + + +static void +ems_writew(uint32_t addr, uint16_t val, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return; + + DBGLOG(1, "ems_write_ramw addr=%05x ", addr); + addr = dev->page_exec[pg] + (addr & 0x3fff); + DBGLOG(1, "-> %06x val=%04x\n", addr, val); + + if (*(uint16_t *)&ram[addr] != val) + nvr_dosave = 1; + + *(uint16_t *)&ram[addr] = val; +} + + +static void +ems_writel(uint32_t addr, uint32_t val, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return; + + addr = dev->page_exec[pg] + (addr & 0x3fff); + if (*(uint32_t *)&ram[addr] != val) + nvr_dosave = 1; + + *(uint32_t *)&ram[addr] = val; +} + + +static uint8_t +read_ctl(uint16_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + uint8_t ret = 0xff; + + switch (addr & 0x0f) { + case 1: + ret = dev->syskeys; + break; + + case 0x0f: /* Detect EMS board */ + switch (dev->sys_ctl[0x0e]) { + case 0x50: + if (mem_size > 512) break; + ret = (0x90 | dev->ems_port_index); + break; + + case 0x51: + /* 0x60 is the page frame address: + (0xd000 - 0xc400) / 0x20 */ + ret = (dev->ems_base | 0x60); + break; + + case 0x52: + ret = (dev->is_640k ? 0x80 : 0); + break; + } + break; + + default: + ret = (dev->sys_ctl[addr & 0x0f]); + } + + return(ret); +} + + +/* Load contents of "CONFIG.SYS" device from file. */ +static void +cfgsys_load(t1000_t *dev) +{ + char temp[128]; + FILE *fp; + + /* Set up the file's name. */ + sprintf(temp, "%s_cfgsys.nvr", machine_get_internal_name()); + mbstowcs(dev->cfgsys_fn, temp, sizeof_w(dev->cfgsys_fn)); + + /* Now attempt to load the file. */ + memset(dev->cfgsys, 0x1a, dev->cfgsys_len); + fp = plat_fopen(nvr_path(dev->cfgsys_fn), L"rb"); + if (fp != NULL) { + INFO("NVR: loaded CONFIG.SYS from '%ls'\n", dev->cfgsys_fn); + (void)fread(dev->cfgsys, dev->cfgsys_len, 1, fp); + fclose(fp); + } else + INFO("NVR: initialized CONFIG.SYS for '%ls'\n", dev->cfgsys_fn); +} + + +/* Write the contents of "CONFIG.SYS" to file. */ +static void +cfgsys_save(t1000_t *dev) +{ + FILE *fp; + + /* Avoids writing empty files. */ + if (dev->cfgsys_len < 160) return; + + fp = plat_fopen(nvr_path(dev->cfgsys_fn), L"wb"); + if (fp != NULL) { + INFO("NVR: saved CONFIG.SYS to '%ls'\n", dev->cfgsys_fn); + (void)fwrite(dev->cfgsys, dev->cfgsys_len, 1, fp); + fclose(fp); + } +} + + +#if 0 /*NOT_USED*/ +/* All RAM beyond 512K is non-volatile */ +static void +emsboard_load(t1000_t *dev) +{ + FILE *fp; + + if (mem_size > 512) { + fp = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"rb"); + if (fp != NULL) { + fread(&ram[512 * 1024], 1024, (mem_size - 512), fp); + fclose(fp); + } + } +} + + +static void +emsboard_save(t1000_t *dev) +{ + FILE *fp; + + if (mem_size > 512) { + fp = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"wb"); + if (fp != NULL) { + fwrite(&ram[512 * 1024], 1024, (mem_size - 512), fp); + fclose(fp); + } + } +} +#endif + + +static void +turbo_set(t1000_t *dev, uint8_t value) +{ + if (value == dev->turbo) return; + + dev->turbo = value; + + pc_set_speed(dev->turbo); +} + + +static void +write_ctl(uint16_t addr, uint8_t val, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + dev->sys_ctl[addr & 0x0f] = val; + switch (addr & 0x0f) { + case 4: /* Video control */ + if (dev->sys_ctl[3] == 0x5a) { + t1000_video_options_set((val & 0x20) ? 1 : 0); + t1000_display_set((val & 0x40) ? 0 : 1); + if (dev->is_t1200) + turbo_set(dev, (val & 0x80) ? 1 : 0); + } + break; + + /* + * It looks as if the T1200, like the T3100, can disable + * its built-in video chipset if it detects the presence + * of another video card. + */ + case 6: + if (dev->is_t1200) + t1000_video_enable(val & 0x01 ? 0 : 1); + break; + + case 0x0f: /* EMS control */ + switch (dev->sys_ctl[0x0e]) { + case 0x50: + ems_set_port(dev, val); + break; + + case 0x51: + ems_set_hardram(dev, val); + break; + + case 0x52: + ems_set_640k(dev, val); + break; + } + break; + } +} + + +/* + * Ports 0xc0 to 0xc3 appear to have two purposes: + * + * > Access to the 160 bytes of non-volatile RAM containing CONFIG.SYS + * > Reading the floppy changeline. I don't know why the Toshiba doesn't + * use the normal port 0x3f7 for this, but it doesn't. + * + */ +static uint8_t +read_nvram(uint16_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + uint8_t tmp = 0xff; + + switch (addr) { + case 0x00c2: /* read next byte from NVRAM */ + if (dev->nvr_addr >= 0 && dev->nvr_addr < 160) { + tmp = dev->cfgsys[dev->nvr_addr]; + dev->nvr_addr++; + } + break; + + case 0x00c3: /* read floppy changeline and NVRAM ready state */ + tmp = fdc_read(0x03f7, dev->fdc); + tmp = (tmp & 0x80) >> 3; /* Bit 4 is changeline */ + tmp |= (dev->nvr_active & 0xc0);/* Bits 6,7 are r/w mode */ + tmp |= 0x2e; /* Bits 5,3,2,1 always 1 */ + tmp |= (dev->nvr_active & 0x40) >> 6; /* Ready state */ + break; + } + + return(tmp); +} + + +/* Read from T1200 NVRAM. */ +static uint8_t +nvram_read(uint32_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + return(dev->cfgsys[addr & 0x7ff]); +} + + +static void +write_nvram(uint16_t addr, uint8_t val, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + /* + * On the real T1000, port 0xc1 is only usable as the high byte + * of a 16-bit write to port 0xc0, with 0x5a in the low byte. + */ + switch (addr) { + case 0x00c0: + dev->nvr_c0 = val; + break; + + case 0x00c1: /* write next byte to NVRAM */ + if (dev->nvr_addr > 0 && dev->nvr_addr <= 160) { + if (dev->cfgsys[dev->nvr_addr-1] != val) + nvr_dosave = 1; + dev->cfgsys[dev->nvr_addr-1] = val; + dev->nvr_addr++; + } else { + /* + * We ignore the first byte written after a + * RESET pulse, as that seems to indicate the + * type of operation (00=READ, FF=WRITE). So, + * we "ignore" byte 0 here. + */ + if (val == 0xff) + dev->nvr_addr++; + } + break; + + case 0x00c2: + break; + + case 0x00c3: + /* + * At start of NVRAM read / write, 0x80 is written to + * port 0xC3. This seems to reset the NVRAM address. + */ + dev->nvr_active = val; + if (val == 0x80) + dev->nvr_addr = 0; + break; + } +} + + +/* Write to T1200 NVRAM. */ +static void +nvram_write(uint32_t addr, uint8_t val, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + if (dev->cfgsys[addr & 0x7ff] != val) + nvr_dosave = 1; + + dev->cfgsys[addr & 0x7ff] = val; +} + + +/* Port 0xc8 controls the ROM drive. */ +static uint8_t +read_rom_ctl(uint16_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + return(dev->rom_ctl); +} + + +static void +write_rom_ctl(uint16_t addr, uint8_t val, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + dev->rom_ctl = val; + if (dev->romdrive && (val & 0x80)) { + /* Enable */ + dev->rom_offset = ((val & 0x7f) * 0x10000) % T1000_ROMDOS_SIZE; + mem_map_set_addr(&dev->rom_mapping, 0xa0000, 0x10000); + mem_map_set_exec(&dev->rom_mapping, dev->romdrive + dev->rom_offset); + mem_map_enable(&dev->rom_mapping); + } else { + mem_map_disable(&dev->rom_mapping); + } +} + + +/* Read the ROM drive */ +static uint8_t +read_rom(uint32_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + if (! dev->romdrive) + return(0xff); + + return(dev->romdrive[dev->rom_offset + (addr & 0xffff)]); +} + + +static uint16_t +read_romw(uint32_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + if (! dev->romdrive) + return(0xffff); + + return(*(uint16_t *)(&dev->romdrive[dev->rom_offset + (addr & 0xffff)])); +} + + +static uint32_t +read_roml(uint32_t addr, void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + if (! dev->romdrive) + return(0xffffffff); + + return(*(uint32_t *)(&dev->romdrive[dev->rom_offset + (addr & 0xffff)])); +} + + +static void * +t1000_init(const device_t *info, void *arg) +{ + t1000_t *dev; + FILE *fp; + int pg; + + dev = (t1000_t *)mem_alloc(sizeof(t1000_t)); + memset(dev, 0x00, sizeof(t1000_t)); + dev->is_t1200 = info->local; + + dev->turbo = 0xff; + dev->ems_port_index = 7; /* EMS disabled */ + + /* Add machine device to the system. */ + device_add_ex(info, dev); + + if (dev->is_t1200) { + /* Non-volatile RAM for CONFIG.SYS */ + dev->cfgsys_len = 2048; + dev->cfgsys = (uint8_t *)mem_alloc(dev->cfgsys_len); + mem_map_add(&dev->nvr_mapping, 0x0f0000, dev->cfgsys_len, + nvram_read,NULL,NULL, nvram_write,NULL,NULL, NULL, 0, dev); + } else { + /* + * The ROM drive is optional. + * + * If the file is missing, continue to boot; the BIOS will + * complain 'No ROM drive' but boot normally from floppy. + */ + dev->rom_dos = machine_get_config_int("rom_dos"); + if (dev->rom_dos) { + fp = plat_fopen(rom_path(T1000_ROMDOS_PATH), L"rb"); + if (fp != NULL) { + dev->romdrive = (uint8_t *)mem_alloc(T1000_ROMDOS_SIZE); + if (dev->romdrive) { + memset(dev->romdrive, 0xff, T1000_ROMDOS_SIZE); + fread(dev->romdrive, T1000_ROMDOS_SIZE, 1, fp); + } + fclose(fp); + + mem_map_add(&dev->rom_mapping, 0xa0000, 0x10000, + read_rom,read_romw,read_roml, NULL,NULL,NULL, + NULL, MEM_MAPPING_INTERNAL, dev); + mem_map_disable(&dev->rom_mapping); + } + + io_sethandler(0xc8, 1, + read_rom_ctl,NULL,NULL, write_rom_ctl,NULL,NULL, dev); + } + + /* Non-volatile RAM for CONFIG.SYS */ + dev->cfgsys_len = 160; + dev->cfgsys = (uint8_t *)mem_alloc(dev->cfgsys_len); + io_sethandler(0xc0, 4, + read_nvram,NULL,NULL, write_nvram,NULL,NULL, dev); + } + + /* Load or initialize the NVRAM "config.sys" file. */ + cfgsys_load(dev); + + /* Map the EMS page frame. */ + for (pg = 0; pg < 4; pg++) { + mem_map_add(&dev->mapping[pg], 0xd0000 + (0x4000 * pg), 16384, + ems_read,ems_readw,ems_readl, + ems_write,ems_writew,ems_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); + + /* Start them all off disabled */ + mem_map_disable(&dev->mapping[pg]); + } + + /* System control functions, and add-on memory board */ + io_sethandler(0xe0, 16, + read_ctl,NULL,NULL, write_ctl,NULL,NULL, dev); + + machine_common_init(); + + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + + nmi_init(); + + device_add(&keyboard_xt_device); + + tc8521_init(&dev->nvr, machine->nvrsz); + + if (dev->is_t1200) { + dev->fdc = (fdc_t *)device_add(&fdc_toshiba_device); + + if (video_card == VID_INTERNAL) { + /* Load the T1200 CGA Font ROM. */ + video_load_font(T1200_FONT_PATH, FONT_CGA_THICK); + + device_add(&t1200_video_device); + } + + if (hdc_type == HDC_INTERNAL) + (void)device_add(&xta_t1200_device); + } else { + dev->fdc = (fdc_t *)device_add(&fdc_xt_device); + + if (video_card == VID_INTERNAL) { + /* Load the T1000 CGA Font ROM. */ + video_load_font(T1000_FONT_PATH, FONT_CGA_THICK); + + device_add(&t1000_video_device); + } + } + + return(dev); +} + + +static void +t1000_close(void *priv) +{ + t1000_t *dev = (t1000_t *)priv; + + if (dev->romdrive != NULL) + free(dev->romdrive); + + cfgsys_save(dev); + + free(dev); +} + + +static const device_config_t t1000_config[] = { + { + "rom_dos", "ROM DOS", CONFIG_SELECTION, "", 0, + { + { + "Disabled", 0 + }, + { + "Enabled", 1 + }, + { + NULL + } + } + }, + { + "display_language", "Language", CONFIG_SELECTION, "", 0, + { + { "US English", 0 }, + { "Danish", 1 }, + { NULL } + } + }, + { + NULL + } +}; + +static const device_config_t t1200_config[] = { + { + "display_language", "Language", CONFIG_SELECTION, "", 0, + { + { "US English", 0 }, + { "Danish", 1 }, + { NULL } + } + }, + { + NULL + } +}; + + +static const machine_t t1000_info = { + MACHINE_ISA | MACHINE_VIDEO, + MACHINE_VIDEO, + 512, 768, 128, 64, -1, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_tosh_1000 = { + "Toshiba T1000", + MACHINE_ISA, + 0, + L"toshiba/t1000", + t1000_init, t1000_close, NULL, + NULL, NULL, NULL, + &t1000_info, + t1000_config +}; + + +static const machine_t t1200_info = { + MACHINE_ISA | MACHINE_VIDEO | MACHINE_HDC, + MACHINE_VIDEO, + 1024, 2048,1024, 64, -1, + {{"Intel",cpus_8086},{"NEC",cpus_nec}} +}; + +const device_t m_tosh_1200 = { + "Toshiba T1200", + MACHINE_ISA, + 1, + L"toshiba/t1200", + t1000_init, t1000_close, NULL, + NULL, NULL, NULL, + &t1200_info, + t1200_config +}; + + +void +t1000_syskey(uint8_t andmask, uint8_t ormask, uint8_t xormask) +{ +#if 0 + t1000.syskeys &= ~andmask; + t1000.syskeys |= ormask; + t1000.syskeys ^= xormask; +#endif +} diff --git a/src/machines/m_xt_t1000.h b/src/machines/m_tosh1x00.h similarity index 73% rename from src/machines/m_xt_t1000.h rename to src/machines/m_tosh1x00.h index 543a232..902e5a0 100644 --- a/src/machines/m_xt_t1000.h +++ b/src/machines/m_tosh1x00.h @@ -8,11 +8,11 @@ * * Definitions for the Toshiba T1000/T1200 machines. * - * Version: @(#)m_xt_t1000.h 1.0.5 2018/09/09 + * Version: @(#)m_tosh1x00.h 1.0.6 2019/03/18 * * Author: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,13 +32,16 @@ * Boston, MA 02111-1307 * USA. */ -#ifndef MACHINE_T1000_H -# define MACHINE_T1000_H +#ifndef MACHINE_TOSH1X00_H +# define MACHINE_TOSH1X00_H #ifdef EMU_DEVICE_H -extern const device_t t1000_video_device; -extern const device_t t1200_video_device; +extern const device_t m_tosh1000; +extern const device_t m_tosh1200; + +extern const device_t t1000_video_device; +extern const device_t t1200_video_device; #endif @@ -48,11 +51,11 @@ extern void t1000_display_set(uint8_t internal); extern void t1000_syskey(uint8_t amask, uint8_t omask, uint8_t xmask); -extern void t1000_configsys_load(void); -extern void t1000_configsys_save(void); +//extern void t1000_configsys_load(void); +//extern void t1000_configsys_save(void); -extern void t1000_emsboard_load(void); -extern void t1000_emsboard_save(void); +//extern void t1000_emsboard_load(void); +//extern void t1000_emsboard_save(void); -#endif /*MACHINE_T1000_H*/ +#endif /*MACHINE_TOSH1X00_H*/ diff --git a/src/machines/m_tosh1x00_vid.c b/src/machines/m_tosh1x00_vid.c new file mode 100644 index 0000000..2afe402 --- /dev/null +++ b/src/machines/m_tosh1x00_vid.c @@ -0,0 +1,757 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Toshiba T1000 plasma display, which + * has a fixed resolution of 640x200 pixels. + * + * Version: @(#)m_tosh1x00_vid.c 1.0.10 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, + * + * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2017,2018 Miran Grca. + * Copyright 2017,2018 John Elliott. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../timer.h" +#include "../device.h" +#include "../devices/video/video.h" +#include "../devices/video/vid_cga.h" +#include "../plat.h" +#include "m_tosh1x00.h" + + +#define T1000_XSIZE 640 +#define T1000_YSIZE 200 + + +static video_timings_t timing_t1000 = {VID_ISA, 8,16,32, 8,16,32}; + + +/* Video options set by the motherboard; they will be picked up by the card + * on the next poll. + * + * Bit 1: Danish + * Bit 0: Thin font + */ +static uint8_t st_options; +static uint8_t st_enabled = 1; +static int8_t st_internal = -1; +static uint8_t langid; + + +typedef struct { + mem_map_t mapping; + + cga_t cga; /* The CGA is used for the external + * display; most of its registers are + * ignored by the plasma display. */ + + int font; /* current font, 0-3 */ + int enabled; /* hardware enabled, 0 or 1 */ + int internal; /* using internal display? */ + uint8_t attrmap; /* attribute mapping register */ + + int64_t dispontime, + dispofftime, + vsynctime; + + int linepos, displine; + int vc, dispon; + + uint8_t options; + + uint8_t *vram; + + /* Mapping of attributes to colors. */ + uint32_t blue, grey; + uint8_t boldcols[256]; /* which attributes use the bold font */ + uint32_t blinkcols[256][2]; + uint32_t normcols[256][2]; +} vid_t; + + +static void +recalc_timings(vid_t *dev) +{ + double disptime; + double _dispontime, _dispofftime; + + if (dev->internal) { + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); + } else + cga_recalctimings(&dev->cga); +} + + +/* Draw a row of text in 80-column mode */ +static void +vid_text_80(vid_t *dev) +{ + uint32_t cols[2]; + int x, c; + uint8_t chr, attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x3fff; + + sc = (dev->displine) & 7; + addr = ((ma & ~1) + (dev->displine >> 3) * 80) * 2; + ma += (dev->displine >> 3) * 80; + + if ((dev->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((dev->cga.crtc[10] & 0x0F) <= sc) && + ((dev->cga.crtc[11] & 0x0F) >= sc); + } + + for (x = 0; x < 80; x++) { + chr = dev->vram[(addr + 2 * x) & 0x3fff]; + attr = dev->vram[(addr + 2 * x + 1) & 0x3fff]; + drawcursor = ((ma == ca) && cursorline && + (dev->cga.cgamode & 8) && (dev->cga.cgablink & 16)); + + blink = ((dev->cga.cgablink & 16) && (dev->cga.cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + if (dev->options & 1) + bold = dev->boldcols[attr] ? chr : chr + 256; + else + bold = dev->boldcols[attr] ? chr + 256 : chr; + if (dev->options & 2) + bold += 512; + + if (dev->cga.cgamode & 0x20) { + /* Blink */ + cols[1] = dev->blinkcols[attr][1]; + cols[0] = dev->blinkcols[attr][0]; + if (blink) + cols[1] = cols[0]; + } else { + cols[1] = dev->normcols[attr][1]; + cols[0] = dev->normcols[attr][0]; + } + + if (drawcursor) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (dev->blue ^ dev->grey); + } else { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + + ma++; + } +} + + +/* Draw a row of text in 40-column mode. */ +static void +vid_text_40(vid_t *dev) +{ + uint32_t cols[2]; + int x, c; + uint8_t chr, attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x3fff; + + sc = (dev->displine) & 7; + addr = ((ma & ~1) + (dev->displine >> 3) * 40) * 2; + ma += (dev->displine >> 3) * 40; + + if ((dev->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((dev->cga.crtc[10] & 0x0F) <= sc) && + ((dev->cga.crtc[11] & 0x0F) >= sc); + } + + for (x = 0; x < 40; x++) { + chr = dev->vram[(addr + 2 * x) & 0x3fff]; + attr = dev->vram[(addr + 2 * x + 1) & 0x3fff]; + drawcursor = ((ma == ca) && cursorline && + (dev->cga.cgamode & 8) && (dev->cga.cgablink & 16)); + + blink = ((dev->cga.cgablink & 16) && (dev->cga.cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + if (dev->options & 1) + bold = dev->boldcols[attr] ? chr : chr + 256; + else + bold = dev->boldcols[attr] ? chr + 256 : chr; + if (dev->options & 2) + bold += 512; + + if (dev->cga.cgamode & 0x20) { + /* Blink */ + cols[1] = dev->blinkcols[attr][1]; + cols[0] = dev->blinkcols[attr][0]; + if (blink) + cols[1] = cols[0]; + } else { + cols[1] = dev->normcols[attr][1]; + cols[0] = dev->normcols[attr][0]; + } + + if (drawcursor) { + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + c*2].val = + screen->line[dev->displine][(x << 4) + c*2 + 1].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (dev->blue ^ dev->grey); + } + } else { + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + c*2].val = + screen->line[dev->displine][(x << 4) + c*2+1].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + + ++ma; + } +} + + +/* Draw a line in CGA 640x200 mode */ +static void +vid_cgaline6(vid_t *dev) +{ + int x, c; + uint8_t dat; + uint32_t ink = 0; + uint16_t addr; + uint32_t fg = (dev->cga.cgacol & 0x0f) ? dev->blue : dev->grey; + uint32_t bg = dev->grey; + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + + addr = ((dev->displine) & 1) * 0x2000 + + (dev->displine >> 1) * 80 + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) { + dat = dev->vram[addr & 0x3FFF]; + addr++; + + for (c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (! (dev->cga.cgamode & 8)) + ink = dev->grey; + screen->line[dev->displine][x*8+c].val = ink; + dat = dat << 1; + } + } +} + + +/* Draw a line in CGA 320x200 mode. Here the CGA colours are converted to + * dither patterns: colour 1 to 25% grey, colour 2 to 50% grey */ +static void +vid_cgaline4(vid_t *dev) +{ + int x, c; + uint8_t dat, pattern; + uint32_t ink0, ink1; + uint16_t addr; + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + + addr = ((dev->displine) & 1) * 0x2000 + + (dev->displine >> 1) * 80 + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) { + dat = dev->vram[addr & 0x3FFF]; + addr++; + + for (c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (! (dev->cga.cgamode & 8)) + pattern = 0; + + switch (pattern & 3) { + default: + case 0: + ink0 = ink1 = dev->grey; break; + + case 1: + if (dev->displine & 1) { + ink0 = dev->grey; ink1 = dev->grey; + } else { + ink0 = dev->blue; ink1 = dev->grey; + } + break; + + case 2: if (dev->displine & 1) { + ink0 = dev->grey; ink1 = dev->blue; + } else { + ink0 = dev->blue; ink1 = dev->grey; + } + break; + + case 3: + ink0 = ink1 = dev->blue; break; + } + + screen->line[dev->displine][x*8+2*c].val = ink0; + screen->line[dev->displine][x*8+2*c+1].val = ink1; + dat = dat << 2; + } + } +} + + +static void +vid_poll(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + if (dev->options != st_options || dev->enabled != st_enabled) { + dev->options = st_options; + dev->enabled = st_enabled; + + /* Set the font used for the external display */ + dev->cga.fontbase = ((dev->options & 3) * 256); + + /* Enable or disable internal chipset. */ + if (dev->enabled) + mem_map_enable(&dev->mapping); + else + mem_map_disable(&dev->mapping); + } + + /* Switch between internal plasma and external CRT display. */ + if (st_internal != -1 && st_internal != dev->internal) { + dev->internal = st_internal; + recalc_timings(dev); + } + + if (! dev->internal) { + cga_poll(&dev->cga); + return; + } + + if (! dev->linepos) { + dev->cga.vidtime += dev->dispofftime; + dev->cga.cgastat |= 1; + dev->linepos = 1; + if (dev->dispon) { + if (dev->displine == 0) { + video_blit_wait_buffer(); + } + + if (dev->cga.cgamode & 0x02) { + /* Graphics */ + if (dev->cga.cgamode & 0x10) + vid_cgaline6(dev); + else + vid_cgaline4(dev); + } else if (dev->cga.cgamode & 0x01) { + /* High-res text */ + vid_text_80(dev); + } else + vid_text_40(dev); + } + + dev->displine++; + + /* Hardcode a fixed refresh rate and VSYNC timing. */ + if (dev->displine == 200) { + /* Start of VSYNC */ + dev->cga.cgastat |= 8; + dev->dispon = 0; + } + + if (dev->displine == 216) { + /* End of VSYNC */ + dev->displine = 0; + dev->cga.cgastat &= ~8; + dev->dispon = 1; + } + } else { + if (dev->dispon) { + dev->cga.cgastat &= ~1; + } + dev->cga.vidtime += dev->dispontime; + dev->linepos = 0; + + if (dev->displine == 200) { + /* Hardcode 640x200 window size. */ + if (T1000_XSIZE != xsize || T1000_YSIZE != ysize) { + xsize = T1000_XSIZE; + ysize = T1000_YSIZE; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); + } + + video_blit_start(0, 0, 0, 0, ysize, xsize, ysize); + frames++; + + /* Fixed 640x200 resolution. */ + video_res_x = T1000_XSIZE; + video_res_y = T1000_YSIZE; + + if (dev->cga.cgamode & 0x02) { + if (dev->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + + } else + video_bpp = 0; + + dev->cga.cgablink++; + } + } +} + + +static void +recalc_attrs(vid_t *dev) +{ + int n; + + /* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold + */ + + /* Set up colors */ + dev->blue = makecol(0x2d, 0x39, 0x5a); + dev->grey = makecol(0x85, 0xa0, 0xd6); + + /* Initialize the attribute mapping. + * Start by defaulting everything to grey on blue, + * and with bold set by bit 3. + */ + for (n = 0; n < 256; n++) { + dev->boldcols[n] = (n & 8) != 0; + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->blue; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->grey; + } + + /* Colors 0x11-0xff are controlled by bits 2 and 3 + * of the passed value. Exclude x0 and x8, which are + * always grey on blue. + */ + for (n = 0x11; n <= 0xff; n++) { + if ((n & 7) == 0) continue; + + if (dev->attrmap & 4) { + /* Inverse */ + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->blue; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->grey; + } else { + /* Normal */ + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->grey; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->blue; + } + + if (dev->attrmap & 8) + dev->boldcols[n] = 1; /* Bold */ + } + + /* Set up the 01-0E range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects 81-8e. + */ + for (n = 0x01; n <= 0x0e; n++) { + if (n == 7) continue; + + if (dev->attrmap & 1) { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->blue; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->grey; + dev->blinkcols[n+128][0] = dev->blue; + dev->blinkcols[n+128][1] = dev->grey; + } else { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->grey; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->blue; + dev->blinkcols[n+128][0] = dev->grey; + dev->blinkcols[n+128][1] = dev->blue; + } + + if (dev->attrmap & 2) + dev->boldcols[n] = 1; + } + + /* Colors 07 and 0f are always blue on grey. + * If blinking is enabled so are 87 and 8f. + */ + for (n = 0x07; n <= 0x0f; n += 8) { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->grey; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->blue; + dev->blinkcols[n+128][0] = dev->grey; + dev->blinkcols[n+128][1] = dev->blue; + } + + /* When not blinking, colors 81-8f are always blue on grey. */ + for (n = 0x81; n <= 0x8f; n ++) { + dev->normcols[n][0] = dev->grey; + dev->normcols[n][1] = dev->blue; + dev->boldcols[n] = (n & 0x08) != 0; + } + + /* Finally do the ones which are solid grey. + * These differ between the normal and blinking mappings. + */ + for (n = 0; n <= 0xff; n += 0x11) + dev->normcols[n][0] = dev->normcols[n][1] = dev->grey; + + /* In the blinking range, 00 11 22 .. 77 and 80 91 a2 .. f7 are grey. */ + for (n = 0; n <= 0x77; n += 0x11) { + dev->blinkcols[n][0] = dev->blinkcols[n][1] = dev->grey; + dev->blinkcols[n+128][0] = dev->blinkcols[n+128][1] = dev->grey; + } +} + + +static void +vid_out(uint16_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + switch (addr) { + case 0x03d0: /* emulated CRTC, register select */ + case 0x03d2: + case 0x03d4: + case 0x03d6: + break; + + case 0x03d1: /* emulated CRTC, value */ + case 0x03d3: + case 0x03d5: + case 0x03d7: + if (dev->cga.crtcreg == 0x12) { + /* + * Register 0x12 controls the attribute + * mappings for the LCD screen. + */ + dev->attrmap = val; + recalc_attrs(dev); + return; + } + cga_out(addr, val, &dev->cga); + recalc_timings(dev); + return; + + case 0x03d8: /* CGA control register */ + break; + + case 0x03d9: /* CGA color register */ + break; + } + + cga_out(addr, val, &dev->cga); +} + + +static uint8_t +vid_in(uint16_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + uint8_t ret; + + switch (addr) { + case 0x03d1: + case 0x03d3: + case 0x03d5: + case 0x03d7: + if (dev->cga.crtcreg == 0x12) { + ret = dev->attrmap & 0x0F; + if (dev->internal) + ret |= 0x20; /* LCD / CRT */ + return(ret); + } + break; + } + + return(cga_in(addr, &dev->cga)); +} + + +static void +vid_write(uint32_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + dev->vram[addr & 0x3fff] = val; + + cycles -= 4; +} + + +static uint8_t +vid_read(uint32_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + cycles -= 4; + + return(dev->vram[addr & 0x3fff]); +} + + +static void * +vid_init(const device_t *info, UNUSED(void *parent)) +{ + vid_t *dev; + + dev = (vid_t *)mem_alloc(sizeof(vid_t)); + memset(dev, 0x00, sizeof(vid_t)); + + cga_init(&dev->cga); + + dev->internal = 1; + dev->options = 0x01; + dev->enabled = 1; + + /* Default attribute mapping is 4 */ + dev->attrmap = 4; + recalc_attrs(dev); + + /* Start off in 80x25 text mode. */ + dev->cga.cgastat = 0xf4; + dev->cga.vram = dev->vram; + +// langid = device_get_config_int("display_language") ? 2 : 0; + langid = 0; + + /* Allocate 16K video RAM. */ + dev->vram = (uint8_t *)mem_alloc(0x4000); + mem_map_add(&dev->mapping, 0xb8000, 0x8000, + vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); + + /* Respond to CGA I/O ports. */ + io_sethandler(0x03d0, 0x000c, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + + timer_add(vid_poll, &dev->cga.vidtime, TIMER_ALWAYS_ENABLED, dev); + + video_inform(VID_TYPE_CGA, &timing_t1000); + + return(dev); +} + + +static void +vid_close(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + free(dev->vram); + + free(dev); +} + + +static void +speed_changed(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + recalc_timings(dev); +} + + +const device_t t1000_video_device = { + "Toshiba T1000 Video", + 0, 0, + NULL, + vid_init, vid_close, NULL, + NULL, + speed_changed, + NULL, + NULL, + NULL +}; + +const device_t t1200_video_device = { + "Toshiba T1200 Video", + 0, 1, + NULL, + vid_init, vid_close, NULL, + NULL, + speed_changed, + NULL, + NULL, + NULL +}; + + +void +t1000_video_options_set(uint8_t options) +{ + st_options = options & 1; + st_options |= langid; +} + + +void +t1000_video_enable(uint8_t enabled) +{ + st_enabled = enabled; +} + + +void +t1000_display_set(uint8_t internal) +{ + st_internal = (int8_t)internal; +} + + +uint8_t +t1000_display_get(void) +{ + return((uint8_t)st_internal); +} diff --git a/src/machines/m_at_t3100e.c b/src/machines/m_tosh3100e.c similarity index 72% rename from src/machines/m_at_t3100e.c rename to src/machines/m_tosh3100e.c index a3772ec..b622f88 100644 --- a/src/machines/m_at_t3100e.c +++ b/src/machines/m_tosh3100e.c @@ -121,7 +121,7 @@ * bit 2 set for single-pixel LCD font * bits 0,1 for display font * - * Version: @(#)m_at_t3100e.c 1.0.10 2019/02/16 + * Version: @(#)m_t3100e.c 1.0.12 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -165,13 +165,13 @@ #include "../devices/floppy/fdd.h" #include "../devices/floppy/fdc.h" #include "machine.h" -#include "m_at_t3100e.h" +#include "m_tosh3100e.h" -static const unsigned ems_page_reg[] = { - 0x0208, 0x4208, 0x8208, 0xc208, /* The first four map the first 2Mb */ +static const uint16_t ems_page_reg[] = { + 0x0208, 0x4208, 0x8208, 0xc208, /* The first four map the first 2MB */ /* of RAM into the page frame */ - 0x0218, 0x4218, 0x8218, 0xc218, /* The next four map the next 2Mb */ + 0x0218, 0x4218, 0x8218, 0xc218, /* The next four map the next 2MB */ /* of RAM */ 0x0258, 0x4258, 0x8258, 0xc258, /* and so on. */ 0x0268, 0x4268, 0x8268, 0xc268, @@ -193,10 +193,7 @@ typedef struct { } t3100e_t; -static t3100e_t t3100e; - - -static void t3100e_ems_out(uint16_t addr, uint8_t val, void *p); +static void ems_out(uint16_t addr, uint8_t val, void *priv); /* Given a memory address (which ought to be in the page frame at 0xD0000), @@ -204,7 +201,7 @@ static void t3100e_ems_out(uint16_t addr, uint8_t val, void *p); static int addr_to_page(uint32_t addr) { - if ((addr & 0xF0000) == 0xD0000) + if ((addr & 0xf0000) == 0xd0000) return ((addr >> 14) & 3); return -1; @@ -216,22 +213,22 @@ addr_to_page(uint32_t addr) static uint32_t page_to_addr(int pg) { - return 0xD0000 + ((pg & 3) * 16384); + return 0xd0000 + ((pg & 3) * 16384); } /* Given an EMS page ID, return its physical address in RAM. */ static uint32_t -ems_execaddr(t3100e_t *dev, int pg, uint16_t val) +ems_addr(t3100e_t *dev, int pg, uint16_t val) { uint32_t addr; if (!(val & 0x80)) return 0; /* Bit 7 reset => not mapped */ - val &= 0x7F; + val &= 0x7f; val += (0x80 * (pg >> 2)); /* high bits of the register bank */ /* are used to extend val to allow up */ - /* to 8Mb of EMS to be accessed */ + /* to 8MB of EMS to be accessed */ /* Is it in the upper memory range? */ if (dev->upper_is_ems) { @@ -262,30 +259,30 @@ port_to_page(uint16_t addr) case 0x208: return 0; case 0x4208: return 1; case 0x8208: return 2; - case 0xC208: return 3; + case 0xc208: return 3; case 0x218: return 4; case 0x4218: return 5; case 0x8218: return 6; - case 0xC218: return 7; + case 0xc218: return 7; case 0x258: return 8; case 0x4258: return 9; case 0x8258: return 10; - case 0xC258: return 11; + case 0xc258: return 11; case 0x268: return 12; case 0x4268: return 13; case 0x8268: return 14; - case 0xC268: return 15; + case 0xc268: return 15; } return -1; } +#ifdef _DEBUG /* Used to dump the memory mapping table, for debugging. */ static void -dump_mappings(void) +dump_mappings(t3100e_t *dev) { -#if 0 /*NOT_USED*/ mem_map_t *mm = base_mapping.next; while (mm) { @@ -295,22 +292,22 @@ dump_mappings(void) if (mm == &ram_low_mapping ) name = "LOW "; if (mm == &ram_mid_mapping ) name = "MID "; if (mm == &ram_high_mapping) name = "HIGH"; - if (mm == &t3100e.upper_mapping) name = "UPPR"; - if (mm == &t3100e.mapping[0]) { + if (mm == &dev->upper_mapping) name = "UPPR"; + if (mm == &dev->mapping[0]) { name = "EMS0"; - offset = t3100e.page_exec[0]; + offset = dev->page_exec[0]; } - if (mm == &t3100e.mapping[1]) { + if (mm == &dev->mapping[1]) { name = "EMS1"; - offset = t3100e.page_exec[1]; + offset = dev->page_exec[1]; } - if (mm == &t3100e.mapping[2]) { + if (mm == &dev->mapping[2]) { name = "EMS2"; - offset = t3100e.page_exec[2]; + offset = dev->page_exec[2]; } - if (mm == &t3100e.mapping[3]) { + if (mm == &dev->mapping[3]) { name = "EMS3"; - offset = t3100e.page_exec[3]; + offset = dev->page_exec[3]; } DEBUG(" %p | base=%05x size=%05x %c @ %06x %s\n", mm, @@ -319,8 +316,8 @@ dump_mappings(void) mm = mm->next; } -#endif } +#endif static void @@ -372,33 +369,35 @@ map_ram(t3100e_t *dev, uint8_t val) /* Recalculate EMS mappings */ for (n = 0; n < 4; n++) - t3100e_ems_out(ems_page_reg[n], dev->page[n], dev); + ems_out(ems_page_reg[n], dev->page[n], dev); - dump_mappings(); +#ifdef _DEBUG + dump_mappings(dev); +#endif } static uint8_t -t3100e_sys_in(uint16_t addr, void *p) +sys_in(uint16_t addr, void *priv) { - t3100e_t *dev = (t3100e_t *)p; + t3100e_t *dev = (t3100e_t *)priv; /* The low 4 bits always seem to be 0x0C. The high 4 are a * notification sent by the keyboard controller when it detects * an [Fn] key combination */ DEBUG("IN 0x8084\n"); - return 0x0C | (dev->notify << 4); + return 0x0c | (dev->notify << 4); } /* Handle writes to the T3100e system control port at 0x8084 */ static void -t3100e_sys_out(uint16_t addr, uint8_t val, void *p) +sys_out(uint16_t addr, uint8_t val, void *priv) { - t3100e_t *dev = (t3100e_t *)p; + t3100e_t *dev = (t3100e_t *)priv; - switch (val & 0xE0) { + switch (val & 0xe0) { case 0x00: /* Set serial port IRQs. Not implemented */ DEBUG("OUT 0x8084, %02x [ set serial port IRQs]\n", val); break; @@ -408,7 +407,7 @@ t3100e_sys_out(uint16_t addr, uint8_t val, void *p) break; case 0x80: /* Set video options. */ - t3100e_video_options_set(val & 0x1F); + t3100e_video_options_set(val & 0x1f); break; default: /* Other options not implemented. */ @@ -420,9 +419,9 @@ t3100e_sys_out(uint16_t addr, uint8_t val, void *p) /* Read EMS page register */ static uint8_t -t3100e_ems_in(uint16_t addr, void *p) +ems_in(uint16_t addr, void *priv) { - t3100e_t *dev = (t3100e_t *)p; + t3100e_t *dev = (t3100e_t *)priv; return dev->page[port_to_page(addr)]; @@ -431,12 +430,12 @@ t3100e_ems_in(uint16_t addr, void *p) /* Write EMS page register */ static void -t3100e_ems_out(uint16_t addr, uint8_t val, void *p) +ems_out(uint16_t addr, uint8_t val, void *priv) { - t3100e_t *dev = (t3100e_t *)p; + t3100e_t *dev = (t3100e_t *)priv; int pg = port_to_page(addr); - dev->page_exec[pg & 3] = ems_execaddr(dev, pg, val); + dev->page_exec[pg & 3] = ems_addr(dev, pg, val); DEBUG("EMS: page %d %02x -> %02x [%06x]\n", pg, dev->page[pg], val, dev->page_exec[pg & 3]); dev->page[pg] = val; @@ -454,30 +453,31 @@ t3100e_ems_out(uint16_t addr, uint8_t val, void *p) } -/* Read RAM in the EMS page frame */ +/* Read RAM in the EMS page frame. */ static uint8_t -ems_read_ram(uint32_t addr, void *priv) +ems_read(uint32_t addr, void *priv) { t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); - if (pg < 0) return 0xFF; - addr = dev->page_exec[pg] + (addr & 0x3FFF); + if (pg < 0) return 0xff; + + addr = dev->page_exec[pg] + (addr & 0x3fff); return ram[addr]; } static uint16_t -ems_read_ramw(uint32_t addr, void *priv) +ems_readw(uint32_t addr, void *priv) { t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); - if (pg < 0) return 0xFF; + if (pg < 0) return 0xffff; - DBGLOG(1, "ems_read_ramw addr=%05x ", addr); - addr = dev->page_exec[pg] + (addr & 0x3FFF); + DBGLOG(1, "ems_readw(%05x) ", addr); + addr = dev->page_exec[pg] + (addr & 0x3fff); DBGLOG(1, "-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); return *(uint16_t *)&ram[addr]; @@ -485,40 +485,43 @@ ems_read_ramw(uint32_t addr, void *priv) static uint32_t -ems_read_raml(uint32_t addr, void *priv) +ems_readl(uint32_t addr, void *priv) { t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); - if (pg < 0) return 0xFF; - addr = dev->page_exec[pg] + (addr & 0x3FFF); + if (pg < 0) return 0xffffffff; + + addr = dev->page_exec[pg] + (addr & 0x3fff); return *(uint32_t *)&ram[addr]; } -/* Write RAM in the EMS page frame */ +/* Write RAM in the EMS page frame. */ static void -ems_write_ram(uint32_t addr, uint8_t val, void *priv) +ems_write(uint32_t addr, uint8_t val, void *priv) { t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return; - addr = dev->page_exec[pg] + (addr & 0x3FFF); + + addr = dev->page_exec[pg] + (addr & 0x3fff); ram[addr] = val; } static void -ems_write_ramw(uint32_t addr, uint16_t val, void *priv) +ems_writew(uint32_t addr, uint16_t val, void *priv) { t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return; - DBGLOG(1, "ems_write_ramw addr=%05x ", addr); - addr = dev->page_exec[pg] + (addr & 0x3FFF); + + DBGLOG(1, "ems_writew(%05x) ", addr); + addr = dev->page_exec[pg] + (addr & 0x3fff); DBGLOG(1, "-> %06x val=%04x\n", addr, val); *(uint16_t *)&ram[addr] = val; @@ -526,13 +529,14 @@ ems_write_ramw(uint32_t addr, uint16_t val, void *priv) static void -ems_write_raml(uint32_t addr, uint32_t val, void *priv) +ems_writel(uint32_t addr, uint32_t val, void *priv) { t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return; - addr = dev->page_exec[pg] + (addr & 0x3FFF); + + addr = dev->page_exec[pg] + (addr & 0x3fff); *(uint32_t *)&ram[addr] = val; } @@ -540,7 +544,7 @@ ems_write_raml(uint32_t addr, uint32_t val, void *priv) /* Read RAM in the upper area. This is basically what the 'remapped' * mapping in mem.c does, except that the upper area can move around */ static uint8_t -upper_read_ram(uint32_t addr, void *priv) +upper_read(uint32_t addr, void *priv) { t3100e_t *dev = (t3100e_t *)priv; @@ -551,7 +555,7 @@ upper_read_ram(uint32_t addr, void *priv) static uint16_t -upper_read_ramw(uint32_t addr, void *priv) +upper_readw(uint32_t addr, void *priv) { t3100e_t *dev = (t3100e_t *)priv; @@ -562,7 +566,7 @@ upper_read_ramw(uint32_t addr, void *priv) static uint32_t -upper_read_raml(uint32_t addr, void *priv) +upper_readl(uint32_t addr, void *priv) { t3100e_t *dev = (t3100e_t *)priv; @@ -573,7 +577,7 @@ upper_read_raml(uint32_t addr, void *priv) static void -upper_write_ram(uint32_t addr, uint8_t val, void *priv) +upper_write(uint32_t addr, uint8_t val, void *priv) { t3100e_t *dev = (t3100e_t *)priv; @@ -583,7 +587,7 @@ upper_write_ram(uint32_t addr, uint8_t val, void *priv) static void -upper_write_ramw(uint32_t addr, uint16_t val, void *priv) +upper_writew(uint32_t addr, uint16_t val, void *priv) { t3100e_t *dev = (t3100e_t *)priv; @@ -593,7 +597,7 @@ upper_write_ramw(uint32_t addr, uint16_t val, void *priv) static void -upper_write_raml(uint32_t addr, uint32_t val, void *priv) +upper_writel(uint32_t addr, uint32_t val, void *priv) { t3100e_t *dev = (t3100e_t *)priv; @@ -602,79 +606,135 @@ upper_write_raml(uint32_t addr, uint32_t val, void *priv) } -void -m_at_t3100e_init(const machine_t *model, void *arg) +static uint8_t +kbd_get(void *priv) { + t3100e_t *dev = (t3100e_t *)priv; + + return(dev->turbo); +} + + +static void +kbd_set(void *priv, uint8_t value) +{ + t3100e_t *dev = (t3100e_t *)priv; + + dev->turbo = !!value; +} + + +static void +t3100e_close(void *priv) +{ + t3100e_t *dev = (t3100e_t *)priv; + + free(dev); +} + + +static void * +t3100e_init(const device_t *info, void *arg) +{ + t3100e_t *dev; + void *kbd; int pg; - memset(&t3100e, 0x00, sizeof(t3100e_t)); + dev = (t3100e_t *)mem_alloc(sizeof(t3100e_t)); + memset(dev, 0x00, sizeof(t3100e_t)); - m_at_common_ide_init(model, arg); + /* Add machine device to system. */ + device_add_ex(info, dev); - device_add(&keyboard_at_toshiba_device); + m_at_common_ide_init(); + + /* Tell keyboard driver we want to handle some stuff here. */ + kbd = device_add(&keyboard_at_toshiba_device); + keyboard_at_set_funcs(kbd, kbd_get, kbd_set, dev); device_add(&fdc_at_device); - /* Hook up system control port */ + /* Hook up system control port. */ io_sethandler(0x8084, 1, - t3100e_sys_in,NULL,NULL, t3100e_sys_out,NULL,NULL, &t3100e); + sys_in,NULL,NULL, sys_out,NULL,NULL, dev); /* Start monitoring all 16 EMS registers */ for (pg = 0; pg < 16; pg++) { io_sethandler(ems_page_reg[pg], 1, - t3100e_ems_in, NULL, NULL, - t3100e_ems_out, NULL, NULL, &t3100e); + ems_in,NULL,NULL, ems_out,NULL,NULL, dev); } - /* Map the EMS page frame */ + /* Map the EMS page frame. */ for (pg = 0; pg < 4; pg++) { DBGLOG(1, "Adding memory map at %x for page %d\n",page_to_addr(pg),pg); - mem_map_add(&t3100e.mapping[pg], - page_to_addr(pg), 16384, - ems_read_ram, ems_read_ramw, ems_read_raml, - ems_write_ram, ems_write_ramw, ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, - &t3100e); + mem_map_add(&dev->mapping[pg], page_to_addr(pg), 16384, + ems_read,ems_readw,ems_readl, + ems_write,ems_writew,ems_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); /* Start them all off disabled */ - mem_map_disable(&t3100e.mapping[pg]); + mem_map_disable(&dev->mapping[pg]); } /* Mapping for upper RAM when in use as XMS*/ - mem_map_add(&t3100e.upper_mapping, mem_size * 1024, 384 * 1024, - upper_read_ram, upper_read_ramw, upper_read_raml, - upper_write_ram, upper_write_ramw, upper_write_raml, - NULL, MEM_MAPPING_INTERNAL, &t3100e); + mem_map_add(&dev->upper_mapping, mem_size * 1024, 384 * 1024, + upper_read,upper_readw,upper_readl, + upper_write,upper_writew,upper_writel, + NULL, MEM_MAPPING_INTERNAL, dev); - mem_map_disable(&t3100e.upper_mapping); + mem_map_disable(&dev->upper_mapping); - device_add(&t3100e_device); + device_add(&t3100e_vid_device); + + return(dev); } +static const machine_t t3100e_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_HDC, + MACHINE_VIDEO, + 1024, 5120, 256, 64, 8, + {{"",cpus_286}} +}; + +const device_t m_tosh_3100e = { + "Toshiba 3100e", + DEVICE_ROOT, + 0, + L"toshiba/t3100e", + t3100e_init, t3100e_close, NULL, + NULL, NULL, NULL, + &t3100e_info, + NULL +}; + + +/* The byte returned: + * Bit 7: Set if internal plasma display enabled + * Bit 6: Set if running at 6MHz, clear at full speed + * Bit 5: Always 1? + * Bit 4: Set if the FD2MB jumper is present (internal floppy is ?tri-mode) + * Bit 3: Clear if the FD2 jumper is present (two internal floppies) + * Bit 2: Set if the internal drive is A:, clear if B: + * Bit 1: Set if the parallel port is configured as a floppy connector + * for the second drive. + * Bit 0: Set if the F2HD jumper is present (internal floppy is 720k) + */ uint8_t -t3100e_config_get(void) +t3100e_config_get(void *priv) { - /* The byte returned: - * Bit 7: Set if internal plasma display enabled - * Bit 6: Set if running at 6MHz, clear at full speed - * Bit 5: Always 1? - * Bit 4: Set if the FD2MB jumper is present (internal floppy is ?tri-mode) - * Bit 3: Clear if the FD2 jumper is present (two internal floppies) - * Bit 2: Set if the internal drive is A:, clear if B: - * Bit 1: Set if the parallel port is configured as a floppy connector - * for the second drive. - * Bit 0: Set if the F2HD jumper is present (internal floppy is 720k) - */ - uint8_t value = 0x28; /* Start with bits 5 and 3 set. */ + t3100e_t *dev = (t3100e_t *)priv; + uint8_t ret = 0x28; /* start with bits 5 and 3 set */ int type_a = fdd_get_type(0); int type_b = fdd_get_type(1); int prt_switch; /* External drive type: 0=> none, 1=>A, 2=>B */ /* Get display setting */ - if (t3100e_display_get()) value |= 0x80; - if (! t3100e.turbo) value |= 0x40; + if (t3100e_display_get()) + ret |= 0x80; + if (! dev->turbo) + ret |= 0x40; /* Try to determine the floppy types.*/ prt_switch = (type_b ? 2 : 0); @@ -690,16 +750,16 @@ t3100e_config_get(void) prt_switch = 1; /* External drive is A: */ switch (type_b) { case 1: /* 360k */ - case 4: value |= 1; break; /* 720k */ - case 6: value |= 0x10; break; /* Tri-mode */ + case 4: ret |= 1; break; /* 720k */ + case 6: ret |= 0x10; break; /* Tri-mode */ /* All others will be treated as 1.4M */ } break; case 4: - value |= 0x01; /* 720k */ + ret |= 0x01; /* 720k */ if (type_a == type_b) { - value &= (~8); /* Two internal drives */ + ret &= (~8); /* Two internal drives */ prt_switch = 0; /* No external drive */ } break; @@ -707,58 +767,63 @@ t3100e_config_get(void) case 5: /* 1.4M */ case 7: /* 2.8M */ if (type_a == type_b) { - value &= (~8); /* Two internal drives */ + ret &= (~8); /* Two internal drives */ prt_switch = 0; /* No external drive */ } break; case 6: /* 3-mode */ - value |= 0x10; + ret |= 0x10; if (type_a == type_b) { - value &= (~8); /* Two internal drives */ + ret &= (~8); /* Two internal drives */ prt_switch = 0; /* No external drive */ } break; } switch (prt_switch) { - case 0: value |= 4; break; /* No external floppy */ - case 1: value |= 2; break; /* External floppy is A: */ - case 2: value |= 6; break; /* External floppy is B: */ + case 0: ret |= 4; break; /* No external floppy */ + case 1: ret |= 2; break; /* External floppy is A: */ + case 2: ret |= 6; break; /* External floppy is B: */ } - return value; + return ret; } void -t3100e_notify_set(uint8_t val) +t3100e_notify_set(void *priv, uint8_t val) { - t3100e.notify = val; + t3100e_t *dev = (t3100e_t *)priv; + + dev->notify = val; } void -t3100e_mono_set(uint8_t val) +t3100e_mono_set(void *priv, uint8_t val) { - t3100e.mono = val; + t3100e_t *dev = (t3100e_t *)priv; + + dev->mono = val; } uint8_t -t3100e_mono_get(void) +t3100e_mono_get(void *priv) { - return t3100e.mono; + t3100e_t *dev = (t3100e_t *)priv; + + return dev->mono; } void -t3100e_turbo_set(uint8_t val) +t3100e_turbo_set(void *priv, uint8_t val) { - t3100e.turbo = val; + t3100e_t *dev = (t3100e_t *)priv; - if (! val) - cpu_dynamic_switch(0); /* 286/6 */ - else - cpu_dynamic_switch(cpu); + dev->turbo = val; + + pc_set_speed(dev->turbo); } diff --git a/src/machines/m_at_t3100e.h b/src/machines/m_tosh3100e.h similarity index 77% rename from src/machines/m_at_t3100e.h rename to src/machines/m_tosh3100e.h index 187a5cd..d5b127b 100644 --- a/src/machines/m_at_t3100e.h +++ b/src/machines/m_tosh3100e.h @@ -8,13 +8,13 @@ * * Definitions for the Toshiba T3100e system. * - * Version: @(#)m_at_t3100e.h 1.0.3 2018/03/15 + * Version: @(#)m_tosh3100e.h 1.0.4 2019/03/31 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -40,19 +40,19 @@ # define MACHINE_T3100E_H -extern const device_t t3100e_device; +extern const device_t t3100e_vid_device; -extern void t3100e_notify_set(uint8_t value); -extern void t3100e_display_set(uint8_t value); -extern uint8_t t3100e_display_get(void); -extern uint8_t t3100e_config_get(void); -extern void t3100e_turbo_set(uint8_t value); -extern uint8_t t3100e_mono_get(void); -extern void t3100e_mono_set(uint8_t value); +/* Used by the AT keyboard driver. */ +extern void t3100e_notify_set(void *priv, uint8_t value); +extern uint8_t t3100e_config_get(void *priv); +extern void t3100e_turbo_set(void *priv, uint8_t value); +extern uint8_t t3100e_mono_get(void *priv); +extern void t3100e_mono_set(void *priv, uint8_t value); extern void t3100e_video_options_set(uint8_t options); -extern void t3100e_display_set(uint8_t internal); +extern void t3100e_display_set(uint8_t value); +extern uint8_t t3100e_display_get(void); #endif /*MACHINE_T3100E_H*/ diff --git a/src/machines/m_at_t3100e_vid.c b/src/machines/m_tosh3100e_vid.c similarity index 73% rename from src/machines/m_at_t3100e_vid.c rename to src/machines/m_tosh3100e_vid.c index 69ab1d1..1884f5b 100644 --- a/src/machines/m_at_t3100e_vid.c +++ b/src/machines/m_tosh3100e_vid.c @@ -22,7 +22,7 @@ * 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO * 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400 * - * Version: @(#)m_at_t3100e_vid.c 1.0.8 2019/03/07 + * Version: @(#)m_t3100e_vid.c 1.0.10 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -65,7 +65,7 @@ #include "../devices/video/video.h" #include "../devices/video/vid_cga.h" #include "../plat.h" -#include "m_at_t3100e.h" +#include "m_tosh3100e.h" #define FONT_ROM_PATH L"machines/toshiba/t3100e/t3100e_font.bin" @@ -73,12 +73,6 @@ #define T3100E_YSIZE 400 -/* Mapping of attributes to colours */ -static uint32_t amber, black; -static uint8_t boldcols[256]; /* Which attributes use the bold font */ -static uint32_t blinkcols[256][2]; -static uint32_t normcols[256][2]; - /* Video options set by the motherboard; they will be picked up by the card * on the next poll. * @@ -93,32 +87,43 @@ static int8_t st_display_internal = -1; typedef struct { mem_map_t mapping; - cga_t cga; /* The CGA is used for the external - * display; most of its registers are - * ignored by the plasma display. */ + cga_t cga; /* The CGA is used for the external + * display; most of its registers are + * ignored by the plasma display. */ - int font; /* Current font, 0-3 */ - int enabled; /* Hardware enabled, 0 or 1 */ - int internal; /* Using internal display? */ - uint8_t attrmap; /* Attribute mapping register */ + int font; /* current font, 0-3 */ + int enabled; /* hardware enabled, 0 or 1 */ + int internal; /* using internal display? */ + uint8_t attrmap; /* attribute mapping register */ - int dispontime, dispofftime; + int64_t dispontime, + dispofftime, + vsynctime; int linepos, displine; int vc; int dispon; - int vsynctime; uint8_t video_options; uint8_t *vram; + /* Mapping of attributes to colors. */ + uint32_t amber, + black; + uint8_t boldcols[256]; /* which attrs use the bold font */ + uint32_t blinkcols[256][2]; + uint32_t normcols[256][2]; + uint8_t fontdat[2048][8]; uint8_t fontdatm[2048][16]; -} t3100e_t; +} vid_t; + + +static video_timings_t t3100e_timing = { VID_ISA, 8,16,32, 8,16,32 }; static void -recalc_timings(t3100e_t *dev) +recalc_timings(vid_t *dev) { double disptime; double _dispontime, _dispofftime; @@ -138,7 +143,7 @@ recalc_timings(t3100e_t *dev) static void -recalc_attrs(t3100e_t *dev) +recalc_attrs(vid_t *dev) { int n; @@ -152,93 +157,93 @@ recalc_attrs(t3100e_t *dev) */ /* Set up colors. */ - amber = makecol(0xf7, 0x7C, 0x34); - black = makecol(0x17, 0x0C, 0x00); + dev->amber = makecol(0xf7, 0x7c, 0x34); + dev->black = makecol(0x17, 0x0c, 0x00); /* Initialize the attribute mapping. Start by defaulting * everything to black on amber, and with bold set by bit 3. */ for (n = 0; n < 256; n++) { - boldcols[n] = (n & 8) != 0; - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; + dev->boldcols[n] = (n & 8) != 0; + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->amber; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->black; } /* Colors 0x11-0xFF are controlled by bits 2 and 3 of the * passed value. Exclude x0 and x8, which are always black * on amber. */ - for (n = 0x11; n <= 0xFF; n++) { + for (n = 0x11; n <= 0xff; n++) { if ((n & 7) == 0) continue; if (dev->attrmap & 4) { /* Inverse */ - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->amber; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->black; } else { /* Normal */ - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->black; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->amber; } if (dev->attrmap & 8) - boldcols[n] = 1; /* Bold */ + dev->boldcols[n] = 1; /* Bold */ } /* Set up the 01-0E range, controlled by bits 0 and 1 of the * passed value. When blinking is enabled this also affects * 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) { + for (n = 0x01; n <= 0x0e; n++) { if (n == 7) continue; if (dev->attrmap & 1) { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - blinkcols[n+128][0] = amber; - blinkcols[n+128][1] = black; + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->amber; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->black; + dev->blinkcols[n+128][0] = dev->amber; + dev->blinkcols[n+128][1] = dev->black; } else { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->black; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->amber; + dev->blinkcols[n+128][0] = dev->black; + dev->blinkcols[n+128][1] = dev->amber; } if (dev->attrmap & 2) - boldcols[n] = 1; + dev->boldcols[n] = 1; } /* Colors 07 and 0F are always amber on black. If * blinking is enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; + for (n = 0x07; n <= 0x0f; n += 8) { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->black; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->amber; + dev->blinkcols[n+128][0] = dev->black; + dev->blinkcols[n+128][1] = dev->amber; } /* When not blinking, colors 81-8F are always amber on black. */ - for (n = 0x81; n <= 0x8F; n ++) { - normcols[n][0] = black; - normcols[n][1] = amber; - boldcols[n] = (n & 0x08) != 0; + for (n = 0x81; n <= 0x8f; n ++) { + dev->normcols[n][0] = dev->black; + dev->normcols[n][1] = dev->amber; + dev->boldcols[n] = (n & 0x08) != 0; } /* Finally do the ones which are solid black. These * differ between the normal and blinking mappings. */ - for (n = 0; n <= 0xFF; n += 0x11) - normcols[n][0] = normcols[n][1] = black; + for (n = 0; n <= 0xff; n += 0x11) + dev->normcols[n][0] = dev->normcols[n][1] = dev->black; /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ for (n = 0; n <= 0x77; n += 0x11) { - blinkcols[n][0] = blinkcols[n][1] = black; - blinkcols[n+128][0] = blinkcols[n+128][1] = black; + dev->blinkcols[n][0] = dev->blinkcols[n][1] = dev->black; + dev->blinkcols[n+128][0] = dev->blinkcols[n+128][1] = dev->black; } } static void -t3100e_out(uint16_t port, uint8_t val, void *priv) +vid_out(uint16_t port, uint8_t val, void *priv) { - t3100e_t *dev = (t3100e_t *)priv; + vid_t *dev = (vid_t *)priv; switch (port) { /* Emulated CRTC, register select */ @@ -261,12 +266,12 @@ t3100e_out(uint16_t port, uint8_t val, void *priv) return; /* CGA control register */ - case 0x3D8: + case 0x3d8: cga_out(port, val, &dev->cga); return; - /* CGA colour register */ - case 0x3D9: + /* CGA color register */ + case 0x3d9: cga_out(port, val, &dev->cga); return; } @@ -274,15 +279,15 @@ t3100e_out(uint16_t port, uint8_t val, void *priv) static uint8_t -t3100e_in(uint16_t port, void *priv) +vid_in(uint16_t port, void *priv) { - t3100e_t *dev = (t3100e_t *)priv; + vid_t *dev = (vid_t *)priv; uint8_t ret; switch (port) { case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: if (dev->cga.crtcreg == 0x12) { - ret = dev->attrmap & 0x0F; + ret = dev->attrmap & 0x0f; if (dev->internal) ret |= 0x30; /* Plasma / CRT */ return ret; @@ -295,9 +300,9 @@ t3100e_in(uint16_t port, void *priv) static void -t3100e_write(uint32_t addr, uint8_t val, void *priv) +vid_write(uint32_t addr, uint8_t val, void *priv) { - t3100e_t *dev = (t3100e_t *)priv; + vid_t *dev = (vid_t *)priv; dev->vram[addr & 0x7fff] = val; @@ -306,9 +311,9 @@ t3100e_write(uint32_t addr, uint8_t val, void *priv) static uint8_t -t3100e_read(uint32_t addr, void *priv) +vid_read(uint32_t addr, void *priv) { - t3100e_t *dev = (t3100e_t *)priv; + vid_t *dev = (vid_t *)priv; cycles -= 4; @@ -318,7 +323,7 @@ t3100e_read(uint32_t addr, void *priv) /* Draw a row of text in 80-column mode. */ static void -text_row80(t3100e_t *dev) +text_row80(vid_t *dev) { uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x7fff; uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x7fff; @@ -339,13 +344,13 @@ text_row80(t3100e_t *dev) if ((dev->cga.crtc[10] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((dev->cga.crtc[10] & 0x0F)*2 <= sc) && - ((dev->cga.crtc[11] & 0x0F)*2 >= sc); + cursorline = ((dev->cga.crtc[10] & 0x0f)*2 <= sc) && + ((dev->cga.crtc[11] & 0x0f)*2 >= sc); } for (x = 0; x < 80; x++) { - chr = dev->vram[(addr + 2 * x) & 0x7FFF]; - attr = dev->vram[(addr + 2 * x + 1) & 0x7FFF]; + chr = dev->vram[(addr + 2 * x) & 0x7fff]; + attr = dev->vram[(addr + 2 * x + 1) & 0x7fff]; drawcursor = ((ma == ca) && cursorline && (dev->cga.cgamode & 8) && (dev->cga.cgablink & 16)); @@ -353,23 +358,24 @@ text_row80(t3100e_t *dev) (attr & 0x80) && !drawcursor); if (dev->video_options & 4) - bold = boldcols[attr] ? chr + 256 : chr; + bold = dev->boldcols[attr] ? chr + 256 : chr; else - bold = boldcols[attr] ? chr : chr + 256; + bold = dev->boldcols[attr] ? chr : chr + 256; bold += 512 * (dev->video_options & 3); if (dev->cga.cgamode & 0x20) { /* Blink */ - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; + cols[1] = dev->blinkcols[attr][1]; + cols[0] = dev->blinkcols[attr][0]; + if (blink) + cols[1] = cols[0]; } else { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; + cols[1] = dev->normcols[attr][1]; + cols[0] = dev->normcols[attr][0]; } if (drawcursor) { for (c = 0; c < 8; c++) { - screen->line[dev->displine][(x << 3) + c].val = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + screen->line[dev->displine][(x << 3) + c].val = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (dev->amber ^ dev->black); } } else { for (c = 0; c < 8; c++) @@ -382,7 +388,7 @@ text_row80(t3100e_t *dev) /* Draw a row of text in 40-column mode. */ static void -text_row40(t3100e_t *dev) +text_row40(vid_t *dev) { uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x7fff; uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x7fff; @@ -403,13 +409,13 @@ text_row40(t3100e_t *dev) if ((dev->cga.crtc[10] & 0x60) == 0x20) { cursorline = 0; } else { - cursorline = ((dev->cga.crtc[10] & 0x0F)*2 <= sc) && - ((dev->cga.crtc[11] & 0x0F)*2 >= sc); + cursorline = ((dev->cga.crtc[10] & 0x0f)*2 <= sc) && + ((dev->cga.crtc[11] & 0x0f)*2 >= sc); } for (x = 0; x < 40; x++) { - chr = dev->vram[(addr + 2 * x) & 0x7FFF]; - attr = dev->vram[(addr + 2 * x + 1) & 0x7FFF]; + chr = dev->vram[(addr + 2 * x) & 0x7fff]; + attr = dev->vram[(addr + 2 * x + 1) & 0x7fff]; drawcursor = ((ma == ca) && cursorline && (dev->cga.cgamode & 8) && (dev->cga.cgablink & 16)); @@ -417,41 +423,43 @@ text_row40(t3100e_t *dev) (attr & 0x80) && !drawcursor); if (dev->video_options & 4) - bold = boldcols[attr] ? chr + 256 : chr; + bold = dev->boldcols[attr] ? chr + 256 : chr; else - bold = boldcols[attr] ? chr : chr + 256; + bold = dev->boldcols[attr] ? chr : chr + 256; bold += 512 * (dev->video_options & 3); if (dev->cga.cgamode & 0x20) { /* Blink */ - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; + cols[1] = dev->blinkcols[attr][1]; + cols[0] = dev->blinkcols[attr][0]; + if (blink) + cols[1] = cols[0]; } else { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; + cols[1] = dev->normcols[attr][1]; + cols[0] = dev->normcols[attr][0]; } if (drawcursor) { for (c = 0; c < 8; c++) { - screen->line[dev->displine][(x << 4) + c*2].val = screen->line[dev->displine][(x << 4) + c*2 + 1].val = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + screen->line[dev->displine][(x << 4) + c*2].val = screen->line[dev->displine][(x << 4) + c*2 + 1].val = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (dev->amber ^ dev->black); } } else { for (c = 0; c < 8; c++) { screen->line[dev->displine][(x << 4) + c*2].val = screen->line[dev->displine][(x << 4) + c*2+1].val = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; } } - ++ma; + + ma++; } } /* Draw a line in CGA 640x200 or T3100e 640x400 mode. */ static void -cga_line6(t3100e_t *dev) +cga_line6(vid_t *dev) { uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x7fff; - uint32_t fg = (dev->cga.cgacol & 0x0F) ? amber : black; - uint32_t bg = black; + uint32_t fg = (dev->cga.cgacol & 0x0f) ? dev->amber : dev->black; + uint32_t bg = dev->black; uint8_t dat; uint32_t ink = 0; uint16_t addr; @@ -469,13 +477,13 @@ cga_line6(t3100e_t *dev) } for (x = 0; x < 80; x++) { - dat = dev->vram[addr & 0x7FFF]; + dat = dev->vram[addr & 0x7fff]; addr++; for (c = 0; c < 8; c++) { ink = (dat & 0x80) ? fg : bg; if (!(dev->cga.cgamode & 8)) - ink = black; + ink = dev->black; screen->line[dev->displine][x*8+c].val = ink; dat = dat << 1; } @@ -488,7 +496,7 @@ cga_line6(t3100e_t *dev) * 2 to 50% grey. */ static void -cga_line4(t3100e_t *dev) +cga_line4(vid_t *dev) { uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x7fff; uint8_t dat, pattern; @@ -508,35 +516,35 @@ cga_line4(t3100e_t *dev) } for (x = 0; x < 80; x++) { - dat = dev->vram[addr & 0x7FFF]; + dat = dev->vram[addr & 0x7fff]; addr++; for (c = 0; c < 4; c++) { - pattern = (dat & 0xC0) >> 6; + pattern = (dat & 0xc0) >> 6; if (!(dev->cga.cgamode & 8)) pattern = 0; switch (pattern & 3) { case 0: - ink0 = ink1 = black; break; + ink0 = ink1 = dev->black; break; case 1: if (dev->displine & 1) { - ink0 = black; ink1 = black; + ink0 = dev->black; ink1 = dev->black; } else { - ink0 = amber; ink1 = black; + ink0 = dev->amber; ink1 = dev->black; } break; case 2: if (dev->displine & 1) { - ink0 = black; ink1 = amber; + ink0 = dev->black; ink1 = dev->amber; } else { - ink0 = amber; ink1 = black; + ink0 = dev->amber; ink1 = dev->black; } break; case 3: - ink0 = ink1 = amber; break; + ink0 = ink1 = dev->amber; break; } @@ -549,9 +557,9 @@ cga_line4(t3100e_t *dev) static void -t3100e_poll(void *priv) +vid_poll(void *priv) { - t3100e_t *dev = (t3100e_t *)priv; + vid_t *dev = (vid_t *)priv; if (dev->video_options != st_video_options) { dev->video_options = st_video_options; @@ -627,7 +635,7 @@ t3100e_poll(void *priv) set_screen_size(xsize, ysize); } - video_blit_start(1, 0, 0, 0, ysize, xsize, ysize); + video_blit_start(0, 0, 0, 0, ysize, xsize, ysize); frames++; /* Fixed 640x400 resolution */ @@ -648,7 +656,7 @@ t3100e_poll(void *priv) static int -load_font(t3100e_t *dev, const wchar_t *s) +load_font(vid_t *dev, const wchar_t *s) { FILE *fp; int c, d; @@ -686,12 +694,12 @@ load_font(t3100e_t *dev, const wchar_t *s) static void * -t3100e_init(const device_t *info) +vid_init(const device_t *info, UNUSED(void *parent)) { - t3100e_t *dev; + vid_t *dev; - dev = (t3100e_t *)mem_alloc(sizeof(t3100e_t)); - memset(dev, 0x00, sizeof(t3100e_t)); + dev = (vid_t *)mem_alloc(sizeof(vid_t)); + memset(dev, 0x00, sizeof(vid_t)); if (! load_font(dev, FONT_ROM_PATH)) { free(dev); @@ -705,16 +713,14 @@ t3100e_init(const device_t *info) /* 32K video RAM */ dev->vram = (uint8_t *)mem_alloc(0x8000); - timer_add(t3100e_poll, &dev->cga.vidtime, TIMER_ALWAYS_ENABLED, dev); + timer_add(vid_poll, &dev->cga.vidtime, TIMER_ALWAYS_ENABLED, dev); /* Occupy memory between 0xB8000 and 0xBFFFF */ mem_map_add(&dev->mapping, 0xb8000, 0x8000, - t3100e_read,NULL,NULL, t3100e_write,NULL,NULL, - NULL, 0, dev); + vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 12, - t3100e_in,NULL,NULL, t3100e_out,NULL,NULL, dev); + io_sethandler(0x03d0, 12, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); /* Default attribute mapping is 4 */ dev->attrmap = 4; @@ -726,19 +732,19 @@ t3100e_init(const device_t *info) dev->enabled = 1; dev->video_options = 0xff; - video_inform(VID_TYPE_CGA, - (const video_timings_t *)info->vid_timing); + video_inform(VID_TYPE_CGA, &t3100e_timing); - return dev; + return(dev); } static void -t3100e_close(void *priv) +vid_close(void *priv) { - t3100e_t *dev = (t3100e_t *)priv; + vid_t *dev = (vid_t *)priv; free(dev->vram); + free(dev); } @@ -746,23 +752,20 @@ t3100e_close(void *priv) static void speed_changed(void *priv) { - t3100e_t *dev = (t3100e_t *)priv; + vid_t *dev = (vid_t *)priv; recalc_timings(dev); } -static video_timings_t t3100e_timing = { VID_ISA, 8,16,32, 8,16,32 }; - -const device_t t3100e_device = { - "Toshiba T3100e", - 0, - 0, - t3100e_init, t3100e_close, NULL, +const device_t t3100e_vid_device = { + "Toshiba T3100e Video", + 0, 0, NULL, + vid_init, vid_close, NULL, NULL, speed_changed, NULL, - &t3100e_timing, + NULL, NULL }; diff --git a/src/machines/m_tyan.c b/src/machines/m_tyan.c new file mode 100644 index 0000000..ea3d854 --- /dev/null +++ b/src/machines/m_tyan.c @@ -0,0 +1,193 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of some of the Tyan mainboards. + * + * **NOTE** Although these machines have been tested with DOS, Windows + * (XP SP3) and Linux (Debian), they are known to still have + * some issues: + * + * - the 440FX chipset apparently wants ACPI, which we do not + * yet have + * - PentiumPro+ support has not been thoroughly tested for + * proper operation (but adding the machine back hopefully + * means we will get more testing done..) + * - the Tyan boards apparently include a PCI EIDE controller, + * but it is unknown which one. Spotted was an FDC37C665 on + * an S1662 board, and the manual for the S1668 board shows + * that those can also have an FDC37C669. That said, neither + * of those does EIDE/UDMA, so until we know which chip is + * actually being used, UDMA will not work. + * + * As stated above, it is hoped that by re-adding these, more + * testing will get done so they can be 'completed' sometime. + * + * Version: @(#)m_tyan.c 1.0.1 2019/04/13 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/chipsets/intel4x0.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/system/intel.h" +#include "../devices/system/intel_flash.h" +#include "../devices/system/intel_sio.h" +#include "../devices/system/intel_piix.h" +#include "../devices/input/keyboard.h" +#include "../devices/sio/sio.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Allocate machine device to system. */ + device_add_ex(info, arg); + + switch(info->local) { + /* S1662: Tyan Titan-Pro AT/440FX/Award BIOS/SMC FDC37C665 */ + case 0: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i440fx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + m_at_common_init(); + device_add(&keyboard_ps2_pci_device); + memregs_init(); + + device_add(&fdc37c669_device); + break; + + /* S1668: Tyan Titan-Pro ATX/440FX/AMI/SMC FDC37C669 */ + case 1: + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + + device_add(&i440fx_device); + device_add(&piix3_device); + device_add(&intel_flash_bxt_device); + m_at_common_init(); + device_add(&keyboard_ps2_ami_pci_device); + memregs_init(); + + device_add(&fdc37c665_device); + break; + } + + return(arg); +} + + +static const machine_t s1662_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 1024, 8, 128, -1, + {{"Intel",cpus_PentiumPro}} +}; + +const device_t m_tyan_1662_ami = { + "Tyan Titan-Pro AT (S1662)", + DEVICE_ROOT, + 0, + L"tyan/s1662/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &s1662_info, + NULL +}; + +const device_t m_tyan_1662_award = { + "Tyan Titan-Pro AT (S1662)", + DEVICE_ROOT, + 0, + L"tyan/s1662/award", + common_init, NULL, NULL, + NULL, NULL, NULL, + &s1662_info, + NULL +}; + + +static const machine_t s1668_info = { + MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, + 0, + 8, 1024, 8, 128, -1, + {{"Intel",cpus_PentiumPro}} +}; + +const device_t m_tyan_1668_ami = { + "Tyan Ttan-Pro ATX (S1668)", + DEVICE_ROOT, + 1, + L"tyan/s1668/ami", + common_init, NULL, NULL, + NULL, NULL, NULL, + &s1668_info, + NULL +}; + +const device_t m_tyan_1668_award = { + "Tyan Ttan-Pro ATX (S1668)", + DEVICE_ROOT, + 1, + L"tyan/s1668/award", + common_init, NULL, NULL, + NULL, NULL, NULL, + &s1668_info, + NULL +}; diff --git a/src/machines/m_wd76c10.c b/src/machines/m_wd76c10.c new file mode 100644 index 0000000..fecd694 --- /dev/null +++ b/src/machines/m_wd76c10.c @@ -0,0 +1,110 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the WD76C10 based machines. + * + * Version: @(#)m_wd76c10.c 1.0.12 2019/04/08 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../device.h" +#include "../devices/chipsets/wd76c10.h" +#include "../devices/input/keyboard.h" +#include "../devices/video/video.h" +#include "machine.h" + + +static void * +common_init(const device_t *info, void *arg) +{ + /* Add machine device to system. */ + device_add_ex(info, arg); + + device_add(&wd76c10_device); + + m_at_common_ide_init(); + + switch(info->local) { + case 1: /* Amstrad MegaPC */ + device_add(&keyboard_ps2_quadtel_device); + device_add(¶dise_wd90c11_megapc_device); + break; + } + + return(arg); +} + + +static const machine_t sx_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, + 0, + 1, 16, 1, 128, 16, + {{"Intel",cpus_i386SX},{"AMD",cpus_Am386SX},{"Cyrix",cpus_486SLC}} +}; + +const device_t m_amstrad_mega_sx = { + "Amstrad MegaPC (WD76c10)", + DEVICE_ROOT, + 1, + L"amstrad/megapc", + common_init, NULL, NULL, + NULL, NULL, NULL, + &sx_info, + NULL +}; + + +static const machine_t dx_info = { + MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, + 0, + 1, 32, 1, 128, 0, + {{"Intel",cpus_i386DX},{"AMD",cpus_Am386DX},{"Cyrix",cpus_486DLC}} +}; + +const device_t m_amstrad_mega_dx = { + "Amstrad MegaPC (WD76c10)", + DEVICE_ROOT, + 1, + L"amstrad/megapc", + common_init, NULL, NULL, + NULL, NULL, NULL, + &dx_info, + NULL +}; diff --git a/src/machines/m_xt_xi8088.c b/src/machines/m_xi8088.c similarity index 57% rename from src/machines/m_xt_xi8088.c rename to src/machines/m_xi8088.c index 7707ca8..761ba19 100644 --- a/src/machines/m_xt_xi8088.c +++ b/src/machines/m_xi8088.c @@ -8,7 +8,7 @@ * * Implementation of the Xi8088 open-source machine. * - * Version: @(#)m_xt_xi8088.c 1.0.12 2019/02/16 + * Version: @(#)m_xi8088.c 1.0.14 2019/04/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,11 +38,13 @@ */ #include #include +#include #include #include #include "../emu.h" #include "../cpu/cpu.h" #include "../mem.h" +#include "../rom.h" #include "../device.h" #include "../nvr.h" #include "../devices/system/dma.h" @@ -55,127 +57,143 @@ #include "../devices/floppy/fdc.h" #include "../devices/disk/hdc.h" #include "machine.h" -#include "m_xt_xi8088.h" typedef struct { - uint8_t turbo; - - int turbo_setting; - int bios_128kb; + int8_t turbo, + turbo_setting, + bios_128k; + char pad; } xi8088_t; -static xi8088_t xi8088; - - -uint8_t -xi8088_turbo_get(void) +static int +bios_128k_get(xi8088_t *dev) { - return(xi8088.turbo); + return(dev->bios_128k); } -void -xi8088_turbo_set(uint8_t value) +static void +bios_128k_set(xi8088_t *dev, int val) { - int c; - - if (! xi8088.turbo_setting) return; - - xi8088.turbo = value; - if (! value) { - DEBUG("Xi8088 turbo off\n"); - c = cpu; - cpu = 0; /* 8088/4.77 */ - cpu_set(); - cpu = c; - } else { - DEBUG("Xi8088 turbo on\n"); - cpu_set(); - } + dev->bios_128k = (int8_t)val; } -void -xi8088_bios_128kb_set(int val) +static uint8_t +turbo_get(void *priv) { - xi8088.bios_128kb = val; + xi8088_t *dev = (xi8088_t *)priv; + + return(dev->turbo); } -int -xi8088_bios_128kb(void) +static void +turbo_set(void *priv, uint8_t val) { - return(xi8088.bios_128kb); + xi8088_t *dev = (xi8088_t *)priv; + + if (! dev->turbo_setting) return; + + dev->turbo = (int8_t)val; + + pc_set_speed(dev->turbo); } -static const device_config_t xi8088_config[] = { - { - "turbo_setting","Turbo",CONFIG_SELECTION,"",0, - { - { - "Always at selected speed",0 - }, - { - "Hotkeys (starts off)",1 - }, - { - "" - } - } - }, - { - "","",-1 - } -}; - - -const device_t m_xi8088_device = { - "Xi8088", - 0, 0, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - xi8088_config -}; - - -void -m_xt_xi8088_init(const machine_t *model, void *arg) +static void * +xi_init(const device_t *info, void *arg) { - /* Initialize local state. */ - memset(&xi8088, 0x00, sizeof(xi8088_t)); + xi8088_t *dev; + void *kbd; - if (biosmask < 0x010000) - xi8088_bios_128kb_set(0); - else - xi8088_bios_128kb_set(1); + dev = (xi8088_t *)mem_alloc(sizeof(xi8088_t)); + memset(dev, 0x00, sizeof(xi8088_t)); - if (xi8088_bios_128kb()) - mem_add_upper_bios(); + /* Add machine device to system. */ + device_add_ex(info, dev); - /* - * Get the selected Turbo Speed setting. - * Even though the bios by default turns the turbo off when - * controlling by hotkeys, we always start at full speed. - */ - xi8088.turbo = 1; - xi8088.turbo_setting = device_get_config_int("turbo_setting"); - - /* - * TODO: set UMBs? - * See if PCem always sets when we have > 640KB ram and avoids - * conflicts when a peripheral uses the same memory space - */ - machine_common_init(model, arg); + machine_common_init(); nmi_init(); pic2_init(); device_add(&at_nvr_device); - device_add(&keyboard_ps2_xi8088_device); + /* + * Get the selected Turbo Speed setting. + * + * Even though the bios by default turns the turbo off when + * controlling by hotkeys, we always start at full speed. + */ + dev->turbo = 1; + dev->turbo_setting = (int8_t)device_get_config_int("turbo_setting"); + + if (biosmask < 0x010000) + bios_128k_set(dev, 0); + else + bios_128k_set(dev, 1); + + if (bios_128k_get(dev)) + rom_add_upper_bios(); + + /* + * TODO: set UMBs? + * See if PCem always sets when we have > 640KB ram and avoids + * conflicts when a peripheral uses the same memory space + */ + + kbd = device_add(&keyboard_ps2_xi8088_device); + + /* Tell keyboard driver we want to handle some stuff here. */ + keyboard_at_set_funcs(kbd, turbo_get, turbo_set, dev); device_add(&fdc_xt_device); + + return(dev); } + + +static void +xi_close(void *priv) +{ + xi8088_t *dev = (xi8088_t *)priv; + + free(dev); +} + + +static const device_config_t xi_config[] = { + { + "turbo_setting", "Turbo", CONFIG_SELECTION, "", 0, + { + { "Always at selected speed", 0 }, + { "Hotkeys (starts off)", 1 }, + { NULL } + } + }, + { + NULL + } +}; + + +static const machine_t xi_info = { + MACHINE_ISA /*| MACHINE_AT*/ | MACHINE_PS2, + 0, + 64, 1024, 128, 128, -1, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xi8088 = { + "Xi8088", + DEVICE_ROOT, + 0, + L"malinov/xi8088", + xi_init, xi_close, NULL, + NULL, NULL, NULL, + &xi_info, + xi_config +}; diff --git a/src/machines/m_xt.c b/src/machines/m_xt.c index cd2b525..cbe0503 100644 --- a/src/machines/m_xt.c +++ b/src/machines/m_xt.c @@ -8,7 +8,7 @@ * * Implementation of standard IBM PC/XT class machine. * - * Version: @(#)m_xt.c 1.0.15 2019/02/16 + * Version: @(#)m_xt.c 1.0.17 2019/04/13 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,14 +38,17 @@ */ #include #include +#include #include #include #include "../emu.h" +#include "../cpu/cpu.h" #include "../mem.h" #include "../device.h" #include "../devices/system/nmi.h" #include "../devices/system/pit.h" #include "../devices/input/keyboard.h" +#include "../devices/ports/parallel.h" #include "../devices/floppy/fdd.h" #include "../devices/floppy/fdc.h" #ifdef USE_CASSETTE @@ -54,79 +57,78 @@ #include "machine.h" -/* Generic PC/XT system board with just the basics. */ -void -m_pc_common_init(const machine_t *model, void *arg) -{ - int rom_basic; +typedef struct { + uint8_t type; - machine_common_init(model, arg); + int8_t basic; + int8_t floppy; +} pcxt_t; + + +/* Generic PC/XT system board with just the basics. */ +static void * +xt_common_init(const device_t *info, void *arg) +{ + pcxt_t *dev; + + /* Allocate private control block for machine. */ + dev = (pcxt_t *)mem_alloc(sizeof(pcxt_t)); + memset(dev, 0x00, sizeof(pcxt_t)); + dev->type = info->local; + + /* First of all, add the root device. */ + device_add_ex(info, dev); /* Check if we support a BASIC ROM. */ - if (model->device != NULL) { - DEBUG("This (%s) machine supports a BASIC ROM.\n", model->name); + dev->basic = machine_get_config_int("rom_basic"); + dev->floppy = machine_get_config_int("floppy"); - rom_basic = machine_get_config_int("rom_basic"); - DEBUG("ROM BASIC is currently %sabled.\n", (rom_basic)?"en":"dis"); - } + machine_common_init(); + + nmi_init(); pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - device_add(&fdc_xt_device); - - nmi_init(); -} - - -/* The original IBM PC, 1981 model. */ -void -m_pc_init(const machine_t *model, void *arg) -{ - m_pc_common_init(model, arg); - - device_add(&keyboard_pc_device); - + switch(dev->type) { + case 0: /* PC, 1981 */ + case 1: /* PC, 1982 */ + if (dev->type == 1) + device_add(&keyboard_pc82_device); + else + device_add(&keyboard_pc_device); #ifdef USE_CASSETTE - device_add(&cassette_device); + device_add(&cassette_device); #endif + break; + + case 10: /* XT, 1982 */ + case 11: /* XT, 1986 */ + if (dev->type == 11) + device_add(&keyboard_xt86_device); + else + device_add(&keyboard_xt_device); + break; + + default: /* clones */ + device_add(&keyboard_xt86_device); + } + + /* Not entirely correct, they were optional. */ + if (dev->floppy) + device_add(&fdc_xt_device); + + return(dev); } -/* The later IBM PC from 1982. */ -void -m_pc82_init(const machine_t *model, void *arg) +static void +xt_close(void *priv) { - m_pc_common_init(model, arg); - - device_add(&keyboard_pc82_device); - -#ifdef USE_CASSETTE - device_add(&cassette_device); -#endif + free(priv); } -/* The original IBM PC/XT, 1982 model. */ -void -m_xt_init(const machine_t *model, void *arg) -{ - m_pc_common_init(model, arg); - - device_add(&keyboard_xt_device); -} - - -/* The later IBM PC/XT from 1986. */ -void -m_xt86_init(const machine_t *model, void *arg) -{ - m_pc_common_init(model, arg); - - device_add(&keyboard_xt86_device); -} - - -static const device_config_t pcxt_config[] = { +static const device_config_t xt_config[] = { { "rom_basic", "ROM BASIC", CONFIG_SELECTION, "", 0, { @@ -137,28 +139,215 @@ static const device_config_t pcxt_config[] = { "Enabled", 1 }, { - "" + NULL } } }, { - "", "", -1 + "floppy", "Floppy Controller", CONFIG_SELECTION, "", 1, + { + { + "Not present", 0 + }, + { + "Present", 1 + }, + { + NULL + } + } + }, + { + NULL } }; -const device_t m_pc_device = { - "IBM PC", - 0, 0, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - pcxt_config +static const machine_t pc81_info = { + MACHINE_ISA, + 0, + 16, 256, 16, 0, -1, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} }; -const device_t m_xt_device = { - "PC/XT", - 0, 0, +const device_t m_pc81 = { + "IBM PC (1981)", + DEVICE_ROOT, + 0, + L"ibm/pc", + xt_common_init, xt_close, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - pcxt_config + &pc81_info, + xt_config +}; + + +static const machine_t pc82_info = { + MACHINE_ISA, + 0, + 64, 256, 32, 0, -1, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_pc82 = { + "IBM PC (1982)", + DEVICE_ROOT, + 1, + L"ibm/pc82", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &pc82_info, + xt_config +}; + + +static const machine_t xt82_info = { + MACHINE_ISA, + 0, + 64, 640, 64, 0, -1, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xt82 = { + "PC/XT (1982)", + DEVICE_ROOT, + 10, + L"ibm/xt", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &xt82_info, + xt_config +}; + + +static const machine_t xt86_info = { + MACHINE_ISA, + 0, + 64, 640, 64, 0, -1, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xt86 = { + "PC/XT (1986)", + DEVICE_ROOT, + 11, + L"ibm/xt86", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &xt86_info, + xt_config +}; + + +static const machine_t ami_info = { + MACHINE_ISA, + 0, + 64, 640, 64, 0, 0, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xt_ami = { + "XT (AMI, generic)", + DEVICE_ROOT, + 100, + L"generic/xt/ami", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &ami_info, + xt_config +}; + + +static const machine_t award_info = { + MACHINE_ISA, + 0, + 64, 640, 64, 0, 0, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xt_award = { + "XT (Award, generic)", + DEVICE_ROOT, + 101, + L"generic/xt/award", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &award_info, + xt_config +}; + + +static const machine_t phoenix_info = { + MACHINE_ISA, + 0, + 64, 640, 64, 0, 0, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xt_phoenix = { + "XT (generic, Phoenix)", + DEVICE_ROOT, + 102, + L"generic/xt/phoenix", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &phoenix_info, + xt_config +}; + + +static const machine_t openxt_info = { + MACHINE_ISA, + 0, + 64, 640, 64, 0, 0, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xt_openxt = { + "XT (generic, OpenXT)", + DEVICE_ROOT, + 103, + L"generic/xt/open_xt", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &openxt_info, + xt_config +}; + + +static const machine_t dtk_info = { + MACHINE_ISA, + 0, + 64, 640, 64, 0, 0, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xt_dtk = { + "DTK Data-1000 Turbo XT", + DEVICE_ROOT, + 104, + L"dtk/xt", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &dtk_info, + xt_config +}; + + +static const machine_t juko_info = { + MACHINE_ISA, + 0, + 64, 640, 64, 0, 0, + {{"Intel",cpus_8088},{"NEC",cpus_nec}} +}; + +const device_t m_xt_juko = { + "Juko XT", + DEVICE_ROOT, + 105, + L"juko/pc", + xt_common_init, xt_close, NULL, + NULL, NULL, NULL, + &juko_info, + xt_config }; diff --git a/src/machines/m_xt_laserxt.c b/src/machines/m_xt_laserxt.c deleted file mode 100644 index 4d411e1..0000000 --- a/src/machines/m_xt_laserxt.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Emulation of the Laser XT series of machines. - * - * Version: @(#)m_xt_laserxt.c 1.0.9 2019/02/16 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../emu.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../devices/system/nmi.h" -#include "../devices/system/pit.h" -#include "../devices/input/keyboard.h" -#include "../devices/floppy/fdd.h" -#include "../devices/floppy/fdc.h" -#include "machine.h" - - -static int ems_page[4]; -static int ems_control[4]; -static mem_map_t ems_mapping[4]; -static int ems_baseaddr_index = 0; -static int is_lxt3 = 0; - - -static uint32_t -get_ems_addr(uint32_t addr) -{ - if (ems_page[(addr >> 14) & 3] & 0x80) { - addr = (!is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)) + ((ems_page[(addr >> 14) & 3] & 0x0F) << 14) + ((ems_page[(addr >> 14) & 3] & 0x40) << 12) + (addr & 0x3FFF); - } - - return addr; -} - - -static void -do_write(uint16_t port, uint8_t val, void *priv) -{ - uint32_t paddr, vaddr; - int i; - - switch (port) { - case 0x0208: - case 0x4208: - case 0x8208: - case 0xC208: - ems_page[port >> 14] = val; - paddr = 0xC0000 + (port & 0xC000) + (((ems_baseaddr_index + (4 - (port >> 14))) & 0x0C) << 14); - if (val & 0x80) { - mem_map_enable(&ems_mapping[port >> 14]); - vaddr = get_ems_addr(paddr); - mem_map_set_exec(&ems_mapping[port >> 14], ram + vaddr); - } else { - mem_map_disable(&ems_mapping[port >> 14]); - } - flushmmucache(); - break; - - case 0x0209: - case 0x4209: - case 0x8209: - case 0xC209: - ems_control[port >> 14] = val; - ems_baseaddr_index = 0; - for (i = 0; i < 4; i++) { - ems_baseaddr_index |= (ems_control[i] & 0x80) >> (7 - i); - } - - mem_map_set_addr(&ems_mapping[0], 0xC0000 + (((ems_baseaddr_index + 4) & 0x0C) << 14), 0x4000); - mem_map_set_addr(&ems_mapping[1], 0xC4000 + (((ems_baseaddr_index + 3) & 0x0C) << 14), 0x4000); - mem_map_set_addr(&ems_mapping[2], 0xC8000 + (((ems_baseaddr_index + 2) & 0x0C) << 14), 0x4000); - mem_map_set_addr(&ems_mapping[3], 0xCC000 + (((ems_baseaddr_index + 1) & 0x0C) << 14), 0x4000); - flushmmucache(); - break; - } -} - - -static uint8_t -do_read(uint16_t port, void *priv) -{ - switch (port) { - case 0x0208: - case 0x4208: - case 0x8208: - case 0xC208: - return ems_page[port >> 14]; - - case 0x0209: - case 0x4209: - case 0x8209: - case 0xC209: - return ems_control[port >> 14]; - } - - return 0xff; -} - - -static void -mem_write_ems(uint32_t addr, uint8_t val, void *priv) -{ - addr = get_ems_addr(addr); - - if (addr < ((uint32_t)mem_size << 10)) - ram[addr] = val; -} - - -static uint8_t -mem_read_ems(uint32_t addr, void *priv) -{ - uint8_t val = 0xFF; - - addr = get_ems_addr(addr); - - if (addr < ((uint32_t)mem_size << 10)) - val = ram[addr]; - - return val; -} - - -static void -laserxt_init(int lxt3) -{ - int i; - - is_lxt3 = lxt3; - - if (mem_size > 640) { - io_sethandler(0x0208, 2, - do_read,NULL,NULL, do_write,NULL,NULL, NULL); - io_sethandler(0x4208, 2, - do_read,NULL,NULL, do_write,NULL,NULL, NULL); - io_sethandler(0x8208, 2, - do_read,NULL,NULL, do_write,NULL,NULL, NULL); - io_sethandler(0xc208, 2, - do_read,NULL,NULL, do_write,NULL,NULL, NULL); - - mem_map_set_addr(&ram_low_mapping, 0, !is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)); - } - - for (i = 0; i < 4; i++) { - ems_page[i] = 0x7F; - ems_control[i] = (i == 3) ? 0x00 : 0x80; - - mem_map_add(&ems_mapping[i], 0xE0000 + (i << 14), 0x4000, - mem_read_ems,NULL,NULL, - mem_write_ems,NULL,NULL, - ram + 0xA0000 + (i << 14), 0, NULL); - mem_map_disable(&ems_mapping[i]); - } - - mem_set_mem_state(0x0c0000, 0x40000, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); -} - - -void -m_xt_laserxt_init(const machine_t *model, void *arg) -{ - m_xt_init(model, arg); - - laserxt_init(0); -} - - -void -m_xt_lxt3_init(const machine_t *model, void *arg) -{ - machine_common_init(model, arg); - - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - - device_add(&keyboard_xt_lxt3_device); - - device_add(&fdc_xt_device); - - nmi_init(); - - laserxt_init(1); -} diff --git a/src/machines/m_xt_t1000_vid.c b/src/machines/m_xt_t1000_vid.c deleted file mode 100644 index f2736a1..0000000 --- a/src/machines/m_xt_t1000_vid.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Toshiba T1000 plasma display, which - * has a fixed resolution of 640x200 pixels. - * - * Version: @(#)m_xt_t1000_vid.c 1.0.8 2019/03/07 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * John Elliott, - * - * Copyright 2018,2019 Fred N. van Kempen. - * Copyright 2017,2018 Miran Grca. - * Copyright 2017,2018 John Elliott. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include "../emu.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../timer.h" -#include "../device.h" -#include "../devices/video/video.h" -#include "../devices/video/vid_cga.h" -#include "m_xt_t1000.h" - - -#define T1000_XSIZE 640 -#define T1000_YSIZE 200 - - -/* Mapping of attributes to colours */ -static uint32_t blue, grey; -static uint8_t boldcols[256]; /* Which attributes use the bold font */ -static uint32_t blinkcols[256][2]; -static uint32_t normcols[256][2]; -static uint8_t langid; - - -/* Video options set by the motherboard; they will be picked up by the card - * on the next poll. - * - * Bit 1: Danish - * Bit 0: Thin font - */ -static uint8_t st_video_options; -static uint8_t st_enabled = 1; -static int8_t st_display_internal = -1; - - -void -t1000_video_options_set(uint8_t options) -{ - st_video_options = options & 1; - st_video_options |= langid; -} - - -void -t1000_video_enable(uint8_t enabled) -{ - st_enabled = enabled; -} - - -void -t1000_display_set(uint8_t internal) -{ - st_display_internal = (int8_t)internal; -} - - -uint8_t -t1000_display_get(void) -{ - return((uint8_t)st_display_internal); -} - - -typedef struct t1000_t { - mem_map_t mapping; - - cga_t cga; /* The CGA is used for the external - * display; most of its registers are - * ignored by the plasma display. */ - - int font; /* Current font, 0-3 */ - int enabled; /* Hardware enabled, 0 or 1 */ - int internal; /* Using internal display? */ - uint8_t attrmap; /* Attribute mapping register */ - - int dispontime, dispofftime; - - int linepos, displine; - int vc; - int dispon; - int vsynctime; - uint8_t video_options; - - uint8_t *vram; -} t1000_t; - - -static void t1000_recalctimings(t1000_t *t1000); -static void t1000_write(uint32_t addr, uint8_t val, void *p); -static uint8_t t1000_read(uint32_t addr, void *p); -static void t1000_recalcattrs(t1000_t *t1000); - - -static void -t1000_out(uint16_t addr, uint8_t val, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - switch (addr) - { - /* Emulated CRTC, register select */ - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - cga_out(addr, val, &t1000->cga); - break; - - /* Emulated CRTC, value */ - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - /* Register 0x12 controls the attribute mappings for the - * LCD screen. */ - if (t1000->cga.crtcreg == 0x12) - { - t1000->attrmap = val; - t1000_recalcattrs(t1000); - return; - } - cga_out(addr, val, &t1000->cga); - - t1000_recalctimings(t1000); - return; - - /* CGA control register */ - case 0x3D8: - cga_out(addr, val, &t1000->cga); - return; - /* CGA colour register */ - case 0x3D9: - cga_out(addr, val, &t1000->cga); - return; - } -} - - -static uint8_t -t1000_in(uint16_t addr, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - uint8_t val; - - switch (addr) - { - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - if (t1000->cga.crtcreg == 0x12) - { - val = t1000->attrmap & 0x0F; - if (t1000->internal) val |= 0x20; /* LCD / CRT */ - return val; - } - } - - return cga_in(addr, &t1000->cga); -} - - -static void -t1000_write(uint32_t addr, uint8_t val, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - t1000->vram[addr & 0x3fff] = val; - cycles -= 4; -} - - -static uint8_t -t1000_read(uint32_t addr, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - cycles -= 4; - - return t1000->vram[addr & 0x3fff]; -} - - -static void -t1000_recalctimings(t1000_t *t1000) -{ - double disptime; - double _dispontime, _dispofftime; - - if (!t1000->internal) - { - cga_recalctimings(&t1000->cga); - return; - } - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; - t1000->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - t1000->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -/* Draw a row of text in 80-column mode */ -static void -t1000_text_row80(t1000_t *t1000) -{ - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; - - sc = (t1000->displine) & 7; - addr = ((ma & ~1) + (t1000->displine >> 3) * 80) * 2; - ma += (t1000->displine >> 3) * 80; - - if ((t1000->cga.crtc[10] & 0x60) == 0x20) { - cursorline = 0; - } else { - cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && - ((t1000->cga.crtc[11] & 0x0F) >= sc); - } - - for (x = 0; x < 80; x++) { - chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; - attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && - (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); - - blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t1000->video_options & 1) - bold = boldcols[attr] ? chr : chr + 256; - else - bold = boldcols[attr] ? chr + 256 : chr; - if (t1000->video_options & 2) - bold += 512; - - if (t1000->cga.cgamode & 0x20) /* Blink */ - { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; - } - else - { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - { - screen->line[t1000->displine][(x << 3) + c].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); - } - } - else - { - for (c = 0; c < 8; c++) - screen->line[t1000->displine][(x << 3) + c].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; - } -} - - -/* Draw a row of text in 40-column mode */ -static void -t1000_text_row40(t1000_t *t1000) -{ - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; - - sc = (t1000->displine) & 7; - addr = ((ma & ~1) + (t1000->displine >> 3) * 40) * 2; - ma += (t1000->displine >> 3) * 40; - - if ((t1000->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && - ((t1000->cga.crtc[11] & 0x0F) >= sc); - } - for (x = 0; x < 40; x++) - { - chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; - attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && - (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); - - blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t1000->video_options & 1) - bold = boldcols[attr] ? chr : chr + 256; - else - bold = boldcols[attr] ? chr + 256 : chr; - if (t1000->video_options & 2) - bold += 512; - - if (t1000->cga.cgamode & 0x20) /* Blink */ - { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; - } - else - { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - { - screen->line[t1000->displine][(x << 4) + c*2].val = - screen->line[t1000->displine][(x << 4) + c*2 + 1].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); - } - } - else - { - for (c = 0; c < 8; c++) - { - screen->line[t1000->displine][(x << 4) + c*2].val = - screen->line[t1000->displine][(x << 4) + c*2+1].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ++ma; - } -} - - -/* Draw a line in CGA 640x200 mode */ -static void -t1000_cgaline6(t1000_t *t1000) -{ - int x, c; - uint8_t dat; - uint32_t ink = 0; - uint16_t addr; - uint32_t fg = (t1000->cga.cgacol & 0x0F) ? blue : grey; - uint32_t bg = grey; - - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - - addr = ((t1000->displine) & 1) * 0x2000 + - (t1000->displine >> 1) * 80 + - ((ma & ~1) << 1); - - for (x = 0; x < 80; x++) - { - dat = t1000->vram[addr & 0x3FFF]; - addr++; - - for (c = 0; c < 8; c++) - { - ink = (dat & 0x80) ? fg : bg; - if (!(t1000->cga.cgamode & 8)) - ink = grey; - screen->line[t1000->displine][x*8+c].val = ink; - dat = dat << 1; - } - } -} - - -/* Draw a line in CGA 320x200 mode. Here the CGA colours are converted to - * dither patterns: colour 1 to 25% grey, colour 2 to 50% grey */ -static void -t1000_cgaline4(t1000_t *t1000) -{ - int x, c; - uint8_t dat, pattern; - uint32_t ink0, ink1; - uint16_t addr; - - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - addr = ((t1000->displine) & 1) * 0x2000 + - (t1000->displine >> 1) * 80 + - ((ma & ~1) << 1); - - for (x = 0; x < 80; x++) - { - dat = t1000->vram[addr & 0x3FFF]; - addr++; - - for (c = 0; c < 4; c++) - { - pattern = (dat & 0xC0) >> 6; - if (!(t1000->cga.cgamode & 8)) pattern = 0; - - switch (pattern & 3) - { - default: - case 0: ink0 = ink1 = grey; break; - case 1: if (t1000->displine & 1) - { - ink0 = grey; ink1 = grey; - } - else - { - ink0 = blue; ink1 = grey; - } - break; - case 2: if (t1000->displine & 1) - { - ink0 = grey; ink1 = blue; - } - else - { - ink0 = blue; ink1 = grey; - } - break; - case 3: ink0 = ink1 = blue; break; - - } - screen->line[t1000->displine][x*8+2*c].val = ink0; - screen->line[t1000->displine][x*8+2*c+1].val = ink1; - dat = dat << 2; - } - } -} - - -static void -t1000_poll(void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - if (t1000->video_options != st_video_options || - t1000->enabled != st_enabled) - { - t1000->video_options = st_video_options; - t1000->enabled = st_enabled; - - /* Set the font used for the external display */ - t1000->cga.fontbase = ((t1000->video_options & 3) * 256); - - /* Enable or disable internal chipset. */ - if (t1000->enabled) - mem_map_enable(&t1000->mapping); - else - mem_map_disable(&t1000->mapping); - } - /* Switch between internal plasma and external CRT display. */ - if (st_display_internal != -1 && st_display_internal != t1000->internal) - { - t1000->internal = st_display_internal; - t1000_recalctimings(t1000); - } - if (!t1000->internal) - { - cga_poll(&t1000->cga); - return; - } - - if (!t1000->linepos) - { - t1000->cga.vidtime += t1000->dispofftime; - t1000->cga.cgastat |= 1; - t1000->linepos = 1; - if (t1000->dispon) - { - if (t1000->displine == 0) - { - video_blit_wait_buffer(); - } - - /* Graphics */ - if (t1000->cga.cgamode & 0x02) - { - if (t1000->cga.cgamode & 0x10) - t1000_cgaline6(t1000); - else t1000_cgaline4(t1000); - } - else - if (t1000->cga.cgamode & 0x01) /* High-res text */ - { - t1000_text_row80(t1000); - } - else - { - t1000_text_row40(t1000); - } - } - t1000->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (t1000->displine == 200) /* Start of VSYNC */ - { - t1000->cga.cgastat |= 8; - t1000->dispon = 0; - } - if (t1000->displine == 216) /* End of VSYNC */ - { - t1000->displine = 0; - t1000->cga.cgastat &= ~8; - t1000->dispon = 1; - } - } - else - { - if (t1000->dispon) - { - t1000->cga.cgastat &= ~1; - } - t1000->cga.vidtime += t1000->dispontime; - t1000->linepos = 0; - - if (t1000->displine == 200) - { - /* Hardcode 640x200 window size */ - if (T1000_XSIZE != xsize || T1000_YSIZE != ysize) - { - xsize = T1000_XSIZE; - ysize = T1000_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - } - video_blit_start(0, 0, 0, 0, ysize, xsize, ysize); - - frames++; - - /* Fixed 640x200 resolution */ - video_res_x = T1000_XSIZE; - video_res_y = T1000_YSIZE; - - if (t1000->cga.cgamode & 0x02) - { - if (t1000->cga.cgamode & 0x10) - video_bpp = 1; - else video_bpp = 2; - - } - else video_bpp = 0; - t1000->cga.cgablink++; - } - } -} - - -static void -t1000_recalcattrs(t1000_t *t1000) -{ - int n; - - /* val behaves as follows: - * Bit 0: Attributes 01-06, 08-0E are inverse video - * Bit 1: Attributes 01-06, 08-0E are bold - * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are inverse video - * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are bold */ - - /* Set up colours */ - blue = makecol(0x2D, 0x39, 0x5A); - grey = makecol(0x85, 0xa0, 0xD6); - - /* Initialise the attribute mapping. Start by defaulting everything - * to grey on blue, and with bold set by bit 3 */ - for (n = 0; n < 256; n++) - { - boldcols[n] = (n & 8) != 0; - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - } - - /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the - * passed value. Exclude x0 and x8, which are always grey on - * blue. */ - for (n = 0x11; n <= 0xFF; n++) - { - if ((n & 7) == 0) continue; - if (t1000->attrmap & 4) /* Inverse */ - { - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - } - else /* Normal */ - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - } - if (t1000->attrmap & 8) boldcols[n] = 1; /* Bold */ - } - /* Set up the 01-0E range, controlled by bits 0 and 1 of the - * passed value. When blinking is enabled this also affects 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) - { - if (n == 7) continue; - if (t1000->attrmap & 1) - { - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - blinkcols[n+128][0] = blue; - blinkcols[n+128][1] = grey; - } - else - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - blinkcols[n+128][0] = grey; - blinkcols[n+128][1] = blue; - } - if (t1000->attrmap & 2) boldcols[n] = 1; - } - /* Colours 07 and 0F are always blue on grey. If blinking is - * enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - blinkcols[n+128][0] = grey; - blinkcols[n+128][1] = blue; - } - /* When not blinking, colours 81-8F are always blue on grey. */ - for (n = 0x81; n <= 0x8F; n ++) - { - normcols[n][0] = grey; - normcols[n][1] = blue; - boldcols[n] = (n & 0x08) != 0; - } - - - /* Finally do the ones which are solid grey. These differ between - * the normal and blinking mappings */ - for (n = 0; n <= 0xFF; n += 0x11) - { - normcols[n][0] = normcols[n][1] = grey; - } - /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are grey */ - for (n = 0; n <= 0x77; n += 0x11) - { - blinkcols[n][0] = blinkcols[n][1] = grey; - blinkcols[n+128][0] = blinkcols[n+128][1] = grey; - } -} - - -static void * -t1000_init(const device_t *info) -{ - t1000_t *t1000 = (t1000_t *)mem_alloc(sizeof(t1000_t)); - memset(t1000, 0, sizeof(t1000_t)); - cga_init(&t1000->cga); - - t1000->internal = 1; - - /* 16k video RAM */ - t1000->vram = (uint8_t *)mem_alloc(0x4000); - - timer_add(t1000_poll, &t1000->cga.vidtime, TIMER_ALWAYS_ENABLED, t1000); - - /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_map_add(&t1000->mapping, 0xb8000, 0x8000, t1000_read, NULL, NULL, t1000_write, NULL, NULL, NULL, 0, t1000); - /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 0x000c, t1000_in, NULL, NULL, t1000_out, NULL, NULL, t1000); - - /* Default attribute mapping is 4 */ - t1000->attrmap = 4; - t1000_recalcattrs(t1000); - - /* Start off in 80x25 text mode */ - t1000->cga.cgastat = 0xF4; - t1000->cga.vram = t1000->vram; - t1000->enabled = 1; - t1000->video_options = 0x01; - langid = device_get_config_int("display_language") ? 2 : 0; - - video_inform(VID_TYPE_CGA, - (const video_timings_t *)info->vid_timing); - - return t1000; -} - - -static void -t1000_close(void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - free(t1000->vram); - free(t1000); -} - - -static void -t1000_speed_changed(void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - t1000_recalctimings(t1000); -} - - -static const device_config_t t1000_config[] = { - { - "display_language","Language",CONFIG_SELECTION,"",0, - { - { - "USA",0 - }, - { - "Danish",1 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - -static video_timings_t timing_t1000 = {VID_ISA, 8,16,32, 8,16,32}; - -const device_t t1000_video_device = { - "Toshiba T1000 Video", - 0, 0, - t1000_init, t1000_close, NULL, - NULL, - t1000_speed_changed, - NULL, - &timing_t1000, - t1000_config -}; - -const device_t t1200_video_device = { - "Toshiba T1200 Video", - 0, 0, - t1000_init, t1000_close, NULL, - NULL, - t1000_speed_changed, - NULL, - &timing_t1000, - t1000_config -}; diff --git a/src/machines/m_zenith.c b/src/machines/m_zenith.c index 77174f8..c70348d 100644 --- a/src/machines/m_zenith.c +++ b/src/machines/m_zenith.c @@ -6,16 +6,31 @@ * * This file is part of the VARCem Project. * - * Implementation of the Zenith SupersPORT. + * Implementation of the Zenith SupersPORT, ZWL-184-02. * - * Version: @(#)m_zenith.c 1.0.3 2019/02/16 + * This machine has a 80C88 running at 4.77 or 8 MHz, 1 MB + * of RAM (640K of which usable), an embedded EMS controller, + * an embedded CGA-like controller that for the internal LCD, + * or for driving an external monitor, it has a Ricoh RP5C15 + * RTC chip, one or two internal 3.5" (720K) drives, one or + * two external floppy drives (3.5" or 5.25"), and it can + * have one or two internal hard disks, 10 or 20 MB. + * + * **NOTES** We need to know how to read the 'configuration switches', + * so we can make this more complete. The TRM does mention it, + * but sadly, no details, it just refers to the interrupt they + * made for it. + * + * Although the video code sort-of works, much more work has + * to be done on implementing other parts of the Yamaha V6355 + * chip that implements the video controller. + * + * Version: @(#)m_zenith.c 1.0.5 2019/04/21 * * Authors: Fred N. van Kempen, * Original patch for PCem by 'Tux' - * Sarah Walker, * * Copyright 2019 Fred N. van Kempen. - * Copyright 2018,2019 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,90 +73,360 @@ #include "../devices/video/video.h" #include "../plat.h" #include "machine.h" +#include "m_zenith.h" + + +/* + * Ricoh RP5C15 registers. + * + * In modes 0 and 1, registers are accessible as noted. + * In modes 2 and 3, addresses 00 through 0c are treated + * as non-volatile RAM, 4 bits wide. + */ +enum RTC_REGS { + RTC_SECOND1 = 0, /* BCD */ + RTC_CLOCK_OUT = RTC_SECOND1, /* Bank 1 */ + RTC_SECOND10, + RTC_ADJUST = RTC_SECOND10, /* Bank 1 */ + RTC_MINUTE1, /* BCD */ + RTC_MINUTE10, + RTC_HOUR1, /* BCD */ + RTC_HOUR10, + RTC_WEEKDAY, /* BCD, 1-base */ + RTC_DAY1, /* BCD, 1-base */ + RTC_DAY10, + RTC_MONTH1, /* BCD, 1-base */ + RTC_MONTH10, + RTC_SELECT24 = RTC_MONTH10, /* Bank 1 */ + RTC_YEAR1, /* BCD */ + RTC_LEAP = RTC_YEAR1, /* Bank 1 */ + RTC_YEAR10, + RTC_MODE, /* MODE */ + RTC_TEST, /* TEST */ + RTC_RESET /* RESET */ +}; typedef struct { - mem_map_t scratchpad_mapping; - uint8_t *scratchpad_ram; + int lcd; /* use internal LCD */ + + /* NVR/RTC stuff. */ + nvr_t nvr; + + mem_map_t sp_mapping; + + uint8_t *sp_ram; } zenith_t; -static uint8_t -scratchpad_read(uint32_t addr, void *priv) +/* Set the current NVR time. */ +#define set_nibbles(a, v) regs[(a##10)] = ((v)/10) ; regs[(a##1)] = ((v)%10) +static void +rtc_time_set(uint8_t *regs, struct tm *tm) { - zenith_t *dev = (zenith_t *)priv; + set_nibbles(RTC_SECOND, tm->tm_sec); + set_nibbles(RTC_MINUTE, tm->tm_min); + set_nibbles(RTC_HOUR, tm->tm_hour); + regs[RTC_WEEKDAY] = (tm->tm_wday - 1); + set_nibbles(RTC_DAY, (tm->tm_mday - 1)); + set_nibbles(RTC_MONTH, (tm->tm_mon - 1)); + set_nibbles(RTC_YEAR, (tm->tm_year - 80)); +} - return dev->scratchpad_ram[addr & 0x3fff]; + +/* Get the current NVR time. */ +#define get_nibbles(a) ((regs[(a##10)]*10)+regs[(a##1)]) +static void +rtc_time_get(uint8_t *regs, struct tm *tm) +{ + tm->tm_sec = get_nibbles(RTC_SECOND); + tm->tm_min = get_nibbles(RTC_MINUTE); + tm->tm_hour = get_nibbles(RTC_HOUR); + tm->tm_wday = regs[RTC_WEEKDAY] + 1; + tm->tm_mday = get_nibbles(RTC_DAY) + 1; + tm->tm_mon = get_nibbles(RTC_MONTH) + 1; + tm->tm_year = get_nibbles(RTC_YEAR) + 80; +} + + +/* Bump a dual-4bit-register. */ +static int +rtc_bump(uint8_t *regs, int base, int min, int max) +{ + int k; + + k = (regs[base + 1] * 10) + regs[base]; + if (++k >= (max + min)) { + /* Rollover, reset to 'min' and return. */ + regs[base] = min; + regs[base + 1] = 0; + return(1); + } + + /* No rollover, save the bumped value. */ + regs[base] = (k % 10); + regs[base + 1] = (k / 10); + + return(0); +} + + +/* + * This is called every second through the NVR/RTC hook. + * + * We fake a 'running' RTC by updating its registers on + * each passing second. Not exactly accurate, but good + * enough. + */ +static void +rtc_ticker(nvr_t *nvr) +{ + uint8_t *regs = nvr->regs; + int mon, yr, days; + + /* Only if RTC is running.. */ + if (! (regs[RTC_MODE] & 0x08)) return; + + if (rtc_bump(regs, RTC_SECOND1, 0, 60)) { + if (rtc_bump(regs, RTC_MINUTE1, 0, 60)) { + if (rtc_bump(regs, RTC_HOUR1, 0, 24)) { + mon = get_nibbles(RTC_MONTH); + yr = 1980 + get_nibbles(RTC_YEAR); + days = nvr_get_days(mon, yr); + if (rtc_bump(regs, RTC_DAY1, 0, days)) { + if (rtc_bump(regs, RTC_MONTH1, 0, 12)) + rtc_bump(regs, RTC_YEAR1, 0, 99); + } + } + } + } } static void -scratchpad_write(uint32_t addr, uint8_t val, void *priv) +rtc_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (time_sync != TIME_SYNC_DISABLED) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + rtc_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + rtc_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + +#if 0 + /* Start the RTC (done by BIOS.) */ + nvr->regs[RTC_MODE] |= 0x08; +#endif +} + + +/* Reset the machine's NVR to a sane state. */ +static void +rtc_reset(nvr_t *nvr) +{ + /* Initialize the RTC to a known state. */ + memset(nvr->regs, 0x00, sizeof(nvr->regs)); + +#if 0 + /* Not needed, chip is 0-based. */ + nvr->regs[RTC_WEEKDAY] = 0x00; + nvr->regs[RTC_DAY1] = 0x00; + nvr->regs[RTC_MONTH1] = 0x00; +#endif +} + + +/* Write to one of the RTC registers. */ +static void +rtc_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t *ptr; + +INFO("Zenith: rtc_wr(%04x, %02x)\n", addr, val); + + /* Point to the correct bank. */ + ptr = &nvr->regs[16 * (nvr->regs[RTC_MODE] & 0x03)]; + + switch (addr & 0x000f) { + case RTC_MODE: + case RTC_TEST: + case RTC_RESET: + nvr->regs[addr & 0x000f] = (val & 0x0f); + nvr_dosave = 1; + break; + + default: + ptr[addr & 0x000f] = (val & 0x0f); + nvr_dosave = 1; + break; + + } +} + + +/* Read from one of the RTC registers. */ +static uint8_t +rtc_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t r = 0xff; + uint8_t *ptr; + + /* Point to the correct bank. */ + ptr = &nvr->regs[16 * (nvr->regs[RTC_MODE] & 0x03)]; + + switch (addr & 0x000f) { + case RTC_MODE: /* write-only registers */ + case RTC_TEST: + case RTC_RESET: + r = 0x00; + break; + + default: + r = ptr[addr & 0x000f]; + break; + } + r &= 0x0f; + +INFO("Zenith: rtc_rd(%04x) = %02x\n", addr, r); + return(r); +} + + +/* Read from the Scratchpad RAM, which is apparently 2K in size. */ +static uint8_t +sp_read(uint32_t addr, void *priv) { zenith_t *dev = (zenith_t *)priv; - dev->scratchpad_ram[addr & 0x3fff] = val; + return dev->sp_ram[addr & 0x3fff]; +} + + +/* Write to the Scratchpad RAM, which is apparently 2K in size. */ +static void +sp_write(uint32_t addr, uint8_t val, void *priv) +{ + zenith_t *dev = (zenith_t *)priv; + + dev->sp_ram[addr & 0x3fff] = val; +} + + +static void +zenith_close(void *priv) +{ + zenith_t *dev = (zenith_t *)priv; + + /* Make sure NVR gets saved. */ + nvr_dosave = 1; + nvr_save(); + + if (dev->sp_ram != NULL) + free(dev->sp_ram); + + free(dev); } static void * -scratchpad_init(const device_t *info) -{ +zenith_init(const device_t *info, void *arg) +{ zenith_t *dev; + void *vid; dev = (zenith_t *)mem_alloc(sizeof(zenith_t)); memset(dev, 0x00, sizeof(zenith_t)); + /* Add machine device to system. */ + device_add_ex(info, dev); + + dev->lcd = machine_get_config_int("lcd"); + + machine_common_init(); + + nmi_init(); + + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + + /* Set up and initialize the Ricoh RP5C15 RTC. */ + dev->nvr.size = 64; + dev->nvr.irq = -1; + dev->nvr.reset = rtc_reset; + dev->nvr.start = rtc_start; + dev->nvr.tick = rtc_ticker; + nvr_init(&dev->nvr); + io_sethandler(0x0050, 16, + rtc_read,NULL,NULL, rtc_write,NULL,NULL, &dev->nvr); + /* Disable ROM area at F0000, need it for Scratchpad RAM. */ mem_map_disable(&bios_mapping[4]); mem_map_disable(&bios_mapping[5]); /* Allocate and initialize the Scratchpad RAM area. */ - dev->scratchpad_ram = mem_alloc(16384); - memset(dev->scratchpad_ram, 0x00, 16384); - + dev->sp_ram = (uint8_t *)mem_alloc(16384); + memset(dev->sp_ram, 0x00, 16384); + /* Create and enable a mapping for this memory. */ - mem_map_add(&dev->scratchpad_mapping, 0xf0000, 16384, - scratchpad_read,NULL,NULL, scratchpad_write,NULL,NULL, - dev->scratchpad_ram, MEM_MAPPING_EXTERNAL, dev); + mem_map_add(&dev->sp_mapping, 0xf0000, 16384, + sp_read,NULL,NULL, sp_write,NULL,NULL, + dev->sp_ram, MEM_MAPPING_EXTERNAL, dev); - return dev; -} + /* Only use the LCD if configured. */ + if (video_card == VID_INTERNAL) { + vid = device_add_parent(&zenith_ss_video_device, dev); + zenith_vid_set_internal(vid, dev->lcd); + } - -static void -scratchpad_close(void *priv) -{ - zenith_t *dev = (zenith_t *)priv; - - if (dev->scratchpad_ram != NULL) - free(dev->scratchpad_ram); - - free(dev); -} - - -static const device_t scratchpad_device = { - "Zenith scratchpad RAM", - 0, 0, - scratchpad_init, scratchpad_close, NULL, - NULL, NULL, NULL, NULL, - NULL -}; - - -void -m_zenith_supersport_init(const machine_t *model, void *arg) -{ - machine_common_init(model, arg); - - device_add(&scratchpad_device); - - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - - device_add(&keyboard_xt_device); + device_add(&keyboard_generic_device); device_add(&fdc_xt_device); - nmi_init(); + return(dev); } + + +static const device_config_t ss_config[] = { + { + "lcd", "Internal LCD", CONFIG_SELECTION, "", 1, + { + { + "Disabled", 0 + }, + { + "Enabled", 1 + }, + { + NULL + } + } + }, + { + NULL + } +}; + +static const machine_t ss_info = { + MACHINE_ISA | MACHINE_VIDEO, + 0, + 128, 640, 128, 0, -1, + {{"Intel",cpus_8088}} +}; + +const device_t m_zenith_ss = { + "Zenith SupersPort", + DEVICE_ROOT, + 0, + L"zenith/supersport", + zenith_init, zenith_close, NULL, + NULL, NULL, NULL, + &ss_info, + ss_config +}; diff --git a/src/machines/m_zenith.h b/src/machines/m_zenith.h new file mode 100644 index 0000000..99f2deb --- /dev/null +++ b/src/machines/m_zenith.h @@ -0,0 +1,49 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Zenith machines. + * + * Version: @(#)m_zenith.h 1.0.1 2019/04/20 + * + * Author: Fred N. van Kempen, + * + * Copyright 2019 Fred N. van Kempen. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#ifndef MACHINE_ZENITH_H +# define MACHINE_ZENITH_H + + +#ifdef EMU_DEVICE_H +extern const device_t m_zenith_ss; + +extern const device_t zenith_ss_video_device; +#endif + + +extern void zenith_vid_set_internal(void *arg, int val); + + +#endif /*MACHINE_ZENITH_H*/ diff --git a/src/machines/m_zenith_vid.c b/src/machines/m_zenith_vid.c new file mode 100644 index 0000000..dcffbe5 --- /dev/null +++ b/src/machines/m_zenith_vid.c @@ -0,0 +1,687 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the display system for the SupersPort + * machine, which is a CGA-ish design based around a V6355 + * controller chip made by Yamaha. + * + * The LCD "part" of this code is based on the plasma driver + * for the Toshiba T1000, written by John Elliott. + * + * **NOTES** Although this code sort-of works, much more work has to be + * done on implementing other parts of the Yamaha V6355 chip + * that implements the video controller. + * + * Version: @(#)m_zenith_vid.c 1.0.2 2019/04/21 + * + * Authors: Fred N. van Kempen, + * John Elliott, + * + * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2017,2018 John Elliott. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../mem.h" +#include "../timer.h" +#include "../device.h" +#include "../devices/video/video.h" +#include "../devices/video/vid_cga.h" +#include "../plat.h" +#include "m_zenith.h" + + +#define LCD_XSIZE 640 +#define LCD_YSIZE 200 + + +static video_timings_t timing_zenith = {VID_ISA, 8,16,32, 8,16,32}; + + +typedef struct { + int internal, /* using internal display? */ + st_internal; + + uint8_t attrmap; + + mem_map_t mapping; + + cga_t cga; + + uint8_t bank_indx; /* V6355 extended bank */ + uint8_t bank_data[0x6a]; /* V6355 extended bank */ + + int64_t dispontime, + dispofftime, + vsynctime; + + int linepos, displine; + int vc, dispon; + + uint8_t *vram; + + /* Mapping of attributes to colors. */ + uint32_t fgcol, + bgcol; + uint8_t boldcols[256]; /* which attributes use the bold font */ + uint32_t blinkcols[256][2]; + uint32_t normcols[256][2]; +} vid_t; + + +static void +recalc_timings(vid_t *dev) +{ + double disptime; + double _dispontime, _dispofftime; + + if (dev->internal) { + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); + } else + cga_recalctimings(&dev->cga); +} + + +/* Draw a row of text in 80-column mode */ +static void +vid_text_80(vid_t *dev) +{ + uint32_t cols[2]; + int x, c; + uint8_t chr, attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x3fff; + + sc = (dev->displine) & 7; + addr = ((ma & ~1) + (dev->displine >> 3) * 80) * 2; + ma += (dev->displine >> 3) * 80; + + if ((dev->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((dev->cga.crtc[10] & 0x0f) <= sc) && + ((dev->cga.crtc[11] & 0x0f) >= sc); + } + + for (x = 0; x < 80; x++) { + chr = dev->vram[(addr + 2 * x) & 0x3fff]; + attr = dev->vram[(addr + 2 * x + 1) & 0x3fff]; + drawcursor = ((ma == ca) && cursorline && + (dev->cga.cgamode & 8) && (dev->cga.cgablink & 16)); + + blink = ((dev->cga.cgablink & 16) && (dev->cga.cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + bold = dev->boldcols[attr] ? chr + 256 : chr; + + if (dev->cga.cgamode & 0x20) { + /* Blink */ + cols[1] = dev->blinkcols[attr][1]; + cols[0] = dev->blinkcols[attr][0]; + if (blink) + cols[1] = cols[0]; + } else { + cols[1] = dev->normcols[attr][1]; + cols[0] = dev->normcols[attr][0]; + } + + if (drawcursor) { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (dev->fgcol ^ dev->bgcol); + } else { + for (c = 0; c < 8; c++) + screen->line[dev->displine][(x << 3) + c].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + + ma++; + } +} + + +/* Draw a row of text in 40-column mode. */ +static void +vid_text_40(vid_t *dev) +{ + uint32_t cols[2]; + int x, c; + uint8_t chr, attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x3fff; + + sc = (dev->displine) & 7; + addr = ((ma & ~1) + (dev->displine >> 3) * 40) * 2; + ma += (dev->displine >> 3) * 40; + + if ((dev->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((dev->cga.crtc[10] & 0x0f) <= sc) && + ((dev->cga.crtc[11] & 0x0f) >= sc); + } + + for (x = 0; x < 40; x++) { + chr = dev->vram[(addr + 2 * x) & 0x3fff]; + attr = dev->vram[(addr + 2 * x + 1) & 0x3fff]; + drawcursor = ((ma == ca) && cursorline && + (dev->cga.cgamode & 8) && (dev->cga.cgablink & 16)); + + blink = ((dev->cga.cgablink & 16) && (dev->cga.cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + bold = dev->boldcols[attr] ? chr + 256 : chr; + + if (dev->cga.cgamode & 0x20) { + /* Blink */ + cols[1] = dev->blinkcols[attr][1]; + cols[0] = dev->blinkcols[attr][0]; + if (blink) + cols[1] = cols[0]; + } else { + cols[1] = dev->normcols[attr][1]; + cols[0] = dev->normcols[attr][0]; + } + + if (drawcursor) { + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + c*2].val = + screen->line[dev->displine][(x << 4) + c*2 + 1].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (dev->fgcol ^ dev->bgcol); + } + } else { + for (c = 0; c < 8; c++) { + screen->line[dev->displine][(x << 4) + c*2].val = + screen->line[dev->displine][(x << 4) + c*2+1].val = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + + ma++; + } +} + + +/* Draw a line in CGA 640x200 mode */ +static void +vid_cgaline6(vid_t *dev) +{ + int x, c; + uint8_t dat; + uint32_t ink = 0; + uint16_t addr; + uint32_t fg = (dev->cga.cgacol & 0x0f) ? dev->fgcol : dev->bgcol; + uint32_t bg = dev->bgcol; + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + + addr = ((dev->displine) & 1) * 0x2000 + + (dev->displine >> 1) * 80 + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) { + dat = dev->vram[addr & 0x3fff]; + addr++; + + for (c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (! (dev->cga.cgamode & 8)) + ink = dev->bgcol; + screen->line[dev->displine][x*8+c].val = ink; + dat = dat << 1; + } + } +} + + +/* Draw a line in CGA 320x200 mode. Here the CGA colours are converted to + * dither patterns: colour 1 to 25% grey, colour 2 to 50% grey */ +static void +vid_cgaline4(vid_t *dev) +{ + int x, c; + uint8_t dat, pattern; + uint32_t ink0, ink1; + uint16_t addr; + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + + addr = ((dev->displine) & 1) * 0x2000 + + (dev->displine >> 1) * 80 + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) { + dat = dev->vram[addr & 0x3fff]; + addr++; + + for (c = 0; c < 4; c++) { + pattern = (dat & 0xc0) >> 6; + if (! (dev->cga.cgamode & 8)) + pattern = 0; + + switch (pattern & 3) { + default: + case 0: + ink0 = ink1 = dev->bgcol; break; + + case 1: + if (dev->displine & 1) { + ink0 = dev->bgcol; ink1 = dev->bgcol; + } else { + ink0 = dev->fgcol; ink1 = dev->bgcol; + } + break; + + case 2: if (dev->displine & 1) { + ink0 = dev->bgcol; ink1 = dev->fgcol; + } else { + ink0 = dev->fgcol; ink1 = dev->bgcol; + } + break; + + case 3: + ink0 = ink1 = dev->fgcol; break; + } + + screen->line[dev->displine][x*8+2*c].val = ink0; + screen->line[dev->displine][x*8+2*c+1].val = ink1; + dat = dat << 2; + } + } +} + + +static void +vid_poll(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + /* Switch between internal LCD and external CRT display. */ + if (dev->st_internal != -1 && dev->st_internal != dev->internal) { + dev->internal = dev->st_internal; + recalc_timings(dev); + } + + if (! dev->internal) { + cga_poll(&dev->cga); + return; + } + + if (! dev->linepos) { + dev->cga.vidtime += dev->dispofftime; + dev->cga.cgastat |= 1; + dev->linepos = 1; + + if (dev->dispon) { + if (dev->displine == 0) { + video_blit_wait_buffer(); + } + + if (dev->cga.cgamode & 0x02) { + /* Graphics */ + if (dev->cga.cgamode & 0x10) + vid_cgaline6(dev); + else + vid_cgaline4(dev); + } else if (dev->cga.cgamode & 0x01) { + /* High-res text */ + vid_text_80(dev); + } else + vid_text_40(dev); + } + + dev->displine++; + + /* Hardcode a fixed refresh rate and VSYNC timing. */ + if (dev->displine == 200) { + /* Start of VSYNC */ + dev->cga.cgastat |= 8; + dev->dispon = 0; + } + + if (dev->displine == 216) { + /* End of VSYNC */ + dev->displine = 0; + dev->cga.cgastat &= ~8; + dev->dispon = 1; + } + } else { + if (dev->dispon) { + dev->cga.cgastat &= ~1; + } + dev->cga.vidtime += dev->dispontime; + dev->linepos = 0; + + if (dev->displine == 200) { + /* Hardcode 640x200 window size. */ + if (LCD_XSIZE != xsize || LCD_YSIZE != ysize) { + xsize = LCD_XSIZE; + ysize = LCD_YSIZE; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); + } + + video_blit_start(0, 0, 0, 0, ysize, xsize, ysize); + frames++; + + /* Fixed 640x200 resolution. */ + video_res_x = LCD_XSIZE; + video_res_y = LCD_YSIZE; + + if (dev->cga.cgamode & 0x02) { + if (dev->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + } else + video_bpp = 0; + + dev->cga.cgablink++; + } + } +} + + +/* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold + */ +static void +recalc_attrs(vid_t *dev) +{ + int n; + + /* Set up colors */ + dev->fgcol = makecol(0x33, 0x33, 0xff); /* king blue */ + dev->bgcol = makecol(0xe0, 0xe0, 0xe0); /* light grey */ + + /* Initialize the attribute mapping. + * Start by defaulting everything to grey on blue, + * and with bold set by bit 3. + */ + for (n = 0; n < 256; n++) { + dev->boldcols[n] = (n & 8) != 0; + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->fgcol; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->bgcol; + } + + /* Colors 0x11-0xff are controlled by bits 2 and 3 + * of the passed value. Exclude x0 and x8, which are + * always grey on blue. + */ + for (n = 0x11; n <= 0xff; n++) { + if ((n & 7) == 0) continue; + + if (dev->attrmap & 4) { + /* Inverse */ + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->fgcol; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->bgcol; + } else { + /* Normal */ + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->bgcol; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->fgcol; + } + + if (dev->attrmap & 8) + dev->boldcols[n] = 1; /* Bold */ + } + + /* Set up the 01-0E range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects 81-8e. + */ + for (n = 0x01; n <= 0x0e; n++) { + if (n == 7) continue; + + if (dev->attrmap & 1) { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->fgcol; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->bgcol; + dev->blinkcols[n+128][0] = dev->fgcol; + dev->blinkcols[n+128][1] = dev->bgcol; + } else { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->bgcol; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->fgcol; + dev->blinkcols[n+128][0] = dev->bgcol; + dev->blinkcols[n+128][1] = dev->fgcol; + } + + if (dev->attrmap & 2) + dev->boldcols[n] = 1; + } + + /* Colors 07 and 0f are always blue on grey. + * If blinking is enabled so are 87 and 8f. + */ + for (n = 0x07; n <= 0x0f; n += 8) { + dev->blinkcols[n][0] = dev->normcols[n][0] = dev->bgcol; + dev->blinkcols[n][1] = dev->normcols[n][1] = dev->fgcol; + dev->blinkcols[n+128][0] = dev->bgcol; + dev->blinkcols[n+128][1] = dev->fgcol; + } + + /* When not blinking, colors 81-8f are always blue on grey. */ + for (n = 0x81; n <= 0x8f; n ++) { + dev->normcols[n][0] = dev->bgcol; + dev->normcols[n][1] = dev->fgcol; + dev->boldcols[n] = (n & 0x08) != 0; + } + + /* Finally do the ones which are solid grey. + * These differ between the normal and blinking mappings. + */ + for (n = 0; n <= 0xff; n += 0x11) + dev->normcols[n][0] = dev->normcols[n][1] = dev->bgcol; + + /* In the blinking range, 00 11 22 .. 77 and 80 91 a2 .. f7 are grey. */ + for (n = 0; n <= 0x77; n += 0x11) { + dev->blinkcols[n][0] = dev->blinkcols[n][1] = dev->bgcol; + dev->blinkcols[n+128][0] = dev->blinkcols[n+128][1] = dev->bgcol; + } +} + + +static void +vid_out(uint16_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + switch (addr) { + case 0x03d1: /* emulated CRTC, value */ + case 0x03d3: + case 0x03d5: + case 0x03d7: + cga_out(addr, val, &dev->cga); + recalc_timings(dev); + return; + + case 0x03d8: /* CGA control register */ +INFO("Zenith: vid_out(%04x, %02x)\n", addr, val); + if (val == 0xff) return; + break; + + case 0x03dd: /* V6355 Register Bank Index */ + dev->bank_indx = val; +INFO("Zenith: vid_out(%04x, %02x)\n", addr, val); + return; + + case 0x03de: /* V6355 Register Bank Data */ + if (dev->bank_indx < 0x6a) + dev->bank_data[dev->bank_indx] = val; +INFO("Zenith: vid_out(%04x, %02x)\n", addr, val); + return; + } + + cga_out(addr, val, &dev->cga); +} + + +static uint8_t +vid_in(uint16_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x03dd: /* V6355 Register Bank Index */ + ret = dev->bank_indx; +INFO("Zenith: vid_in(%04x) = %02x\n", addr, ret); + return(ret); + + case 0x03de: /* V6355 Register Bank Data */ + if (dev->bank_indx < 0x6a) + ret = dev->bank_data[dev->bank_indx]; +INFO("Zenith: vid_in(%04x) = %02x\n", addr, ret); + return(ret); + } + + ret = cga_in(addr, &dev->cga); + + return(ret); +} + + +static void +vid_write(uint32_t addr, uint8_t val, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + dev->vram[addr & 0x3fff] = val; + + cycles -= 4; +} + + +static uint8_t +vid_read(uint32_t addr, void *priv) +{ + vid_t *dev = (vid_t *)priv; + + cycles -= 4; + + return(dev->vram[addr & 0x3fff]); +} + + +static void +vid_close(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + free(dev->vram); + + free(dev); +} + + +static void +speed_changed(void *priv) +{ + vid_t *dev = (vid_t *)priv; + + recalc_timings(dev); +} + + +static void * +vid_init(const device_t *info, UNUSED(void *parent)) +{ + vid_t *dev; + + dev = (vid_t *)mem_alloc(sizeof(vid_t)); + memset(dev, 0x00, sizeof(vid_t)); + dev->internal = 1; + dev->st_internal = -1; + + /* Default attribute mapping is 4 */ + dev->attrmap = 0; + recalc_attrs(dev); + + /* Allocate 16K video RAM. */ + dev->vram = (uint8_t *)mem_alloc(0x4000); + mem_map_add(&dev->mapping, 0xb8000, 0x8000, + vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); + + dev->cga.vram = dev->vram; + cga_init(&dev->cga); + + /* Start off in 80x25 text mode. */ + dev->cga.cgastat = 0xf4; + + /* Respond to CGA I/O ports. */ + io_sethandler(0x03d0, 0x000c, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + + timer_add(vid_poll, &dev->cga.vidtime, TIMER_ALWAYS_ENABLED, dev); + + /* Load the CGA Font ROM. */ + video_load_font(CGA_FONT_ROM_PATH, FONT_CGA_THICK); + + video_inform(VID_TYPE_CGA, &timing_zenith); + + return(dev); +} + + +const device_t zenith_ss_video_device = { + "Zenith SupersPORT Video", + 0, 0, NULL, + vid_init, vid_close, NULL, + NULL, + speed_changed, + NULL, + NULL, + NULL +}; + + +void +zenith_vid_set_internal(void *arg, int val) +{ + vid_t *dev = (vid_t *)arg; + + dev->st_internal = val; +} diff --git a/src/machines/machine.c b/src/machines/machine.c index 33e90f8..28c27e6 100644 --- a/src/machines/machine.c +++ b/src/machines/machine.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.c 1.0.19 2019/02/16 + * Version: @(#)machine.c 1.0.20 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -51,41 +51,69 @@ #include "../devices/ports/game.h" #include "../devices/ports/serial.h" #include "../devices/ports/parallel.h" -#include "../devices/video/video.h" #include "../plat.h" #include "../ui/ui.h" #include "machine.h" -int AT, MCA, PCI; +const machine_t *machine; + + +static void *m_priv; + + +/* Get the machine definition for the selected machine. */ +const device_t * +machine_load(void) +{ + const device_t *dev; + + dev = machine_get_device_ex(machine_type); + if (dev != NULL) + machine = (machine_t *)dev->mach_info; + + return(dev); +} void machine_reset(void) { wchar_t temp[1024]; - romdef_t r; + const device_t *dev; + romdef_t roms; - INFO("Initializing as \"%s\"\n", machine_getname()); + INFO("Initializing as \"%s\"\n", machine_get_name()); + + /* Initialize the configured machine and CPU. */ + dev = machine_load(); + + /* Set up the selected CPU at default speed. */ + cpu_set_type(machine->cpu[cpu_manufacturer].cpus, cpu_type); + + /* Start with (max/turbo) speed. */ + pc_set_speed(1); /* Set up the architecture flags. */ - AT = IS_ARCH(machine, MACHINE_AT); - PCI = IS_ARCH(machine, MACHINE_PCI); - MCA = IS_ARCH(machine, MACHINE_MCA); + AT = IS_ARCH(MACHINE_AT); + MCA = IS_ARCH(MACHINE_MCA); + PCI = IS_ARCH(MACHINE_PCI); /* Reset memory and the MMU. */ mem_reset(); + rom_reset(); + + /* Disable shadowing for now. */ + shadowbios = 0; /* Load the machine's ROM BIOS. */ - wcscpy(temp, MACHINES_PATH); - plat_append_slash(temp); - wcscat(temp, machines[machine].bios_path); - if (! rom_load_bios(&r, temp, 0)) { + plat_append_filename(temp, MACHINES_PATH, dev->path); + if (! rom_load_bios(&roms, temp, 0)) { /* * The machine's ROM BIOS could not be loaded. * - * Since this is kinda fatal, we inform the user - * and bail out, since continuing is pointless. + * This is kinda fatal, inform the user and + * bail out, since continuing is pointless. */ ui_msgbox(MBX_ERROR|MBX_FATAL, get_string(IDS_ERR_NOBIOS)); @@ -93,62 +121,61 @@ machine_reset(void) } /* Activate the ROM BIOS. */ - mem_add_bios(); - - /* - * If this is not a PCI or MCA machine, reset the video - * card before initializing the machine, to please the - * EuroPC and other systems that need this. - */ - if (!PCI && !MCA) - video_reset(); + rom_add_bios(); /* All good, boot the machine! */ - machines[machine].init(&machines[machine], &r); - - /* - * If this is a PCI or MCA machine, reset the video - * card after initializing the machine, so the bus - * slots work correctly. - */ - if (PCI || MCA) - video_reset(); + m_priv = dev->init(dev, &roms); } -/* Close down the machine (saving stuff, etc.) */ -void -machine_close(void) -{ - if (machines[machine].close != NULL) - machines[machine].close(); -} - - -/* Return the machine type. */ +/* Return the current machine's flags. */ int -machine_type(void) +machine_get_flags(void) { - return (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type); + int ret = 0; + + if (machine != NULL) + ret = machine->flags; + + return(ret); +} + + +/* Return a machine's (adjusted) memory size. */ +int +machine_get_memsize(int mem) +{ + int k; + + k = ((machine->flags & MACHINE_AT) && (machine->ram_granularity < 128)) + ? machine->min_ram * 1024 : machine->min_ram; + + if (mem < k) + mem = k; + + if (mem > 1048576) + mem = 1048576; + + return(mem); } /* Return this machine's default or slow speed. */ uint32_t -machine_speed(int turbo) +machine_get_speed(int turbo) { uint32_t k; int mhz; /* Get the current CPU's maximum speed. */ - k = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; + k = cpu_get_speed(); /* * If not on turbo, use the speed the mainboard * has set as its fallback ("slow") speed. */ if (! turbo) { - mhz = machines[machine].slow_mhz; + mhz = machine->slow_mhz; switch(mhz) { case -1: /* machine has no slow/turbo switching */ break; @@ -172,12 +199,15 @@ int machine_available(int id) { wchar_t temp[1024]; + const device_t *dev; romdef_t r; int i; + dev = machine_get_device_ex(machine_type); + wcscpy(temp, MACHINES_PATH); plat_append_slash(temp); - wcscat(temp, machines[id].bios_path); + wcscat(temp, dev->path); i = rom_load_bios(&r, temp, 1); return(i); @@ -185,18 +215,13 @@ machine_available(int id) void -machine_common_init(const machine_t *model, UNUSED(void *arg)) +machine_common_init(void) { /* System devices first. */ pic_init(); dma_init(); pit_init(); - cpu_set(); - - /* Start with (max/turbo) speed. */ - pc_set_speed(); - if (game_enabled) device_add(&game_device); diff --git a/src/machines/machine.h b/src/machines/machine.h index a6f146c..78c6c58 100644 --- a/src/machines/machine.h +++ b/src/machines/machine.h @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.28 2019/03/05 + * Version: @(#)machine.h 1.0.30 2019/04/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -58,214 +58,211 @@ #define MACHINE_SOUND 0x080000 /* sys has int sound */ #define MACHINE_VIDEO 0x100000 /* sys has int video */ -#define IS_ARCH(m, a) (machines[(m)].flags & (a)) ? 1 : 0; +#define IS_ARCH(a) (machine->flags & (a)) ? 1 : 0; -typedef struct _machine_ { - const char *name; - const char *internal_name; - const wchar_t *bios_path; - int slow_mhz; - struct { - const char *name; -#ifdef EMU_CPU_H - CPU *cpus; -#else - void *cpus; -#endif - } cpu[5]; - int fixed_vidcard; /* FIXME: change to "fixed_flags" */ - int flags; +typedef struct { + uint32_t flags, + flags_fixed; uint32_t min_ram, max_ram; int ram_granularity; int nvrsz; - void (*init)(const struct _machine_ *, void *); -#ifdef EMU_DEVICE_H - const device_t *device; + int slow_mhz; + + struct { + const char *name; +#ifdef EMU_CPU_H + const CPU *cpus; #else - const void *device; + void *cpus; #endif - void (*close)(void); + } cpu[5]; } machine_t; /* Global variables. */ -extern const machine_t machines[]; -extern int AT, PCI; +extern const machine_t *machine; + + +#ifdef EMU_DEVICE_H +extern const device_t m_pc81, + m_pc82; + +extern const device_t m_xt82, + m_xt86; + +extern const device_t m_xt_ami, + m_xt_award, + m_xt_phoenix; +extern const device_t m_xt_openxt; + +extern const device_t m_xt_dtk; +extern const device_t m_xt_juko; + +extern const device_t m_pcjr; + +extern const device_t m_amstrad_1512; +extern const device_t m_amstrad_1640; +extern const device_t m_amstrad_200; +extern const device_t m_amstrad_ppc; +extern const device_t m_amstrad_2086; +extern const device_t m_amstrad_3086; + +extern const device_t m_amstrad_mega_sx; +extern const device_t m_amstrad_mega_dx; + +extern const device_t m_europc; + +extern const device_t m_laser_xt; +extern const device_t m_laser_xt3; + +extern const device_t m_oli_m24; +extern const device_t m_oli_m240; +extern const device_t m_att_6300; + +extern const device_t m_tandy_1k; +extern const device_t m_tandy_1k_hx; +extern const device_t m_tandy_1k_sl2; + +extern const device_t m_tosh_1000; +extern const device_t m_tosh_1200; + +extern const device_t m_xi8088; + +extern const device_t m_zenith_ss; + +extern const device_t m_at; +extern const device_t m_xt286; + +extern const device_t m_neat_ami; +extern const device_t m_neat_dtk; + +extern const device_t m_tg286m; +extern const device_t m_headland_386_ami; +extern const device_t m_ama932j; + +extern const device_t m_scat_award; +extern const device_t m_hs286tr; +extern const device_t m_gw286ct; +extern const device_t m_spc4200p; +extern const device_t m_spc4216p; +extern const device_t m_kmxc02; + +extern const device_t m_tosh_3100e; + +extern const device_t m_cbm_pc30; + +#if defined(DEV_BRANCH) && defined(USE_COMPAQ) +extern const device_t m_cpq_p1; +extern const device_t m_cpq_p1_286; +extern const device_t m_cpq_p2; +extern const device_t m_cpq_p3; +extern const device_t m_cpq_p3_386; +extern const device_t m_cpq_dp_386; +#endif + +extern const device_t m_ps1_2011; +extern const device_t m_ps1_2121; +extern const device_t m_ps1_2133; + +extern const device_t m_ps2_m30_286; + +extern const device_t m_ps2_m50; +extern const device_t m_ps2_m55sx; +extern const device_t m_ps2_m70_3; +extern const device_t m_ps2_m70_4; +extern const device_t m_ps2_m80; + +extern const device_t m_ali1429_ami; +extern const device_t m_ali1429_win; + +extern const device_t m_opti495_386sx_ami; +extern const device_t m_opti495_386dx_ami; +extern const device_t m_opti495_486_ami; +extern const device_t m_opti495_386sx_award; +extern const device_t m_opti495_386dx_award; +extern const device_t m_opti495_486_award; +extern const device_t m_opti495_386sx_mr; +extern const device_t m_opti495_386dx_mr; +extern const device_t m_opti495_486_mr; + +#if defined(DEV_BRANCH) && defined(USE_SIS471) +extern const device_t m_sis471_ami; +#endif +extern const device_t m_dtk486; + +#if defined(DEV_BRANCH) && defined(USE_SIS496) +extern const device_t m_sis496_ami; +#endif +extern const device_t m_rise418; + +extern const device_t m_acer_m3a; +extern const device_t m_acer_v30; +extern const device_t m_acer_v35n; + +extern const device_t m_batman; +extern const device_t m_plato; +extern const device_t m_endeavor; +extern const device_t m_zappa; +extern const device_t m_thor; +extern const device_t m_thor_mr; + +extern const device_t m_p54tp4xe; +extern const device_t m_p55t2p4; +extern const device_t m_p55tvp4; + +extern const device_t m_ap53; +extern const device_t m_mb500n; +extern const device_t m_president; +extern const device_t m_aw430vx; +extern const device_t m_p55va; +extern const device_t m_j656vxd; +extern const device_t m_p55t2s; +extern const device_t m_pb640; + +extern const device_t m_tyan_1662_ami; +extern const device_t m_tyan_1662_award; +extern const device_t m_tyan_1668_ami; +extern const device_t m_tyan_1668_award; + +#endif /* Core functions. */ -extern const char *machine_getname(void); -extern const char *machine_getname_ex(int id); -extern const char *machine_get_internal_name(void); -extern const char *machine_get_internal_name_ex(int m); extern int machine_get_from_internal_name(const char *s); -extern int machine_available(int id); -extern void machine_reset(void); -extern void machine_close(void); -extern int machine_type(void); -extern uint32_t machine_speed(int turbo); +extern const char *machine_get_name(void); +extern const char *machine_get_internal_name(void); #ifdef EMU_DEVICE_H -extern const device_t *machine_getdevice(int machine); +extern const device_t *machine_get_device(void); #endif +extern int machine_get_flags(void); +extern int machine_get_memsize(int memsz); +extern uint32_t machine_get_speed(int turbo); + +extern const char *machine_get_name_ex(int m); +extern const char *machine_get_internal_name_ex(int m); +#ifdef EMU_DEVICE_H +extern const device_t *machine_get_device_ex(int m); +extern const device_t *machine_load(void); +#endif +extern int machine_available(int m); +extern void machine_reset(void); extern int machine_get_config_int(const char *s); extern const char *machine_get_config_string(const char *s); /* Initialization functions for boards and systems. */ -extern void machine_common_init(const machine_t *, void *); +extern void machine_common_init(void); -extern void m_at_common_init(const machine_t *, void *); -extern void m_at_init(const machine_t *, void *); -extern void m_at_ibm_init(const machine_t *, void *); -extern void m_at_ps2_init(const machine_t *, void *); -extern void m_at_common_ide_init(const machine_t *, void *); -extern void m_at_ide_init(const machine_t *, void *); -extern void m_at_ps2_ide_init(const machine_t *, void *); +/* Functions shared by other machines. */ +extern void m_at_common_init(void); +extern void m_at_init(void); +extern void m_at_common_ide_init(void); +extern void m_at_ide_init(void); -extern void m_at_t3100e_init(const machine_t *, void *); - -extern void m_at_p54tp4xe_init(const machine_t *, void *); -extern void m_at_endeavor_init(const machine_t *, void *); -extern void m_at_zappa_init(const machine_t *, void *); -extern void m_at_mb500n_init(const machine_t *, void *); -extern void m_at_president_init(const machine_t *, void *); -extern void m_at_thor_init(const machine_t *, void *); -extern void m_at_pb640_init(const machine_t *, void *); - -extern void m_at_acerm3a_init(const machine_t *, void *); -extern void m_at_acerv35n_init(const machine_t *, void *); -extern void m_at_ap53_init(const machine_t *, void *); -extern void m_at_p55t2p4_init(const machine_t *, void *); -extern void m_at_p55t2s_init(const machine_t *, void *); - -extern void m_at_batman_init(const machine_t *, void *); -extern void m_at_plato_init(const machine_t *, void *); - -extern void m_at_p55tvp4_init(const machine_t *, void *); -extern void m_at_i430vx_init(const machine_t *, void *); -extern void m_at_p55va_init(const machine_t *, void *); -extern void m_at_j656vxd_init(const machine_t *, void *); - -#if defined(DEV_BRANCH) && defined(USE_I686) -extern void m_at_i440fx_init(const machine_t *, void *); -extern void m_at_s1668_init(const machine_t *, void *); -#endif -extern void m_at_ali1429_init(const machine_t *, void *); -extern void m_at_cmdpc_init(const machine_t *, void *); - -extern void m_at_tg286m_init(const machine_t *, void *); -extern void m_at_headland_init(const machine_t *, void *); -extern void m_at_ama932j_init(const machine_t *, void *); -extern void m_at_neat_init(const machine_t *, void *); -extern void m_at_neat_ami_init(const machine_t *, void *); - -extern void m_at_opti495_ami_init(const machine_t *, void *); -extern void m_at_opti495_award_init(const machine_t *, void *); -extern void m_at_opti495_mr_init(const machine_t *, void *); - -extern void m_at_sis471_ami_init(const machine_t *, void *); -extern void m_at_dtk486_init(const machine_t *, void *); - -extern void m_at_sis496_ami_init(const machine_t *, void *); -extern void m_at_r418_init(const machine_t *, void *); - -extern void m_at_scat_init(const machine_t*, void*); -extern void m_at_scat_gw286ct_init(const machine_t*, void*); -extern void m_at_scat_spc4216p_init(const machine_t*, void*); - -extern void m_at_scatsx_init(const machine_t*, void*); - -extern void m_at_compaq_p1_init(const machine_t*, void*); -extern void m_at_compaq_p2_init(const machine_t*, void*); -extern void m_at_compaq_p3_init(const machine_t*, void*); -extern void m_at_compaq_p3_386_init(const machine_t*, void*); - -extern void m_at_wd76c10_init(const machine_t *, void *); - -extern void m_pcjr_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t m_pcjr_device; -#endif - -extern void m_ps1_m2011_init(const machine_t *, void *); -extern void m_ps1_m2121_init(const machine_t *, void *); -extern void m_ps1_m2133_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern void ps1_hdc_inform(void *, void *); -extern void ps1_set_feedback(void *); -extern const device_t m_ps1_device; -extern const device_t ps1_hdc_device; -#endif - -extern void m_ps2_m30_286_init(const machine_t *, void *); -extern void m_ps2_model_50_init(const machine_t *, void *); -extern void m_ps2_model_55sx_init(const machine_t *, void *); -extern void m_ps2_model_70_type3_init(const machine_t *, void *); -extern void m_ps2_model_70_type4_init(const machine_t *, void *); -extern void m_ps2_model_80_init(const machine_t *, void *); - -extern void m_amstrad_1512_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t m_amstrad_1512_device; -#endif -extern void m_amstrad_1640_init(const machine_t *, void *); -extern void m_amstrad_200_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t m_amstrad_200_device; -#endif -extern void m_amstrad_2086_init(const machine_t *, void *); -extern void m_amstrad_3086_init(const machine_t *, void *); -extern void m_amstrad_mega_init(const machine_t *, void *); - -extern void m_europc_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t m_europc_device; -#endif - -extern void m_olim24_init(const machine_t *, void *); -extern void m_olim24_video_init(void); - -extern void m_tandy1k_init(const machine_t *, void *); -extern void m_tandy1k_hx_init(const machine_t *, void *); -extern void m_tandy1k_sl2_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t m_tandy1k_device; -extern const device_t m_tandy1k_hx_device; -extern const device_t m_tandy1k_sl2_device; -#endif -extern int tandy1k_eeprom_read(void); - -extern void m_zenith_supersport_init(const machine_t *, void *); - -extern void m_pc_init(const machine_t *, void *); -extern void m_pc82_init(const machine_t *, void *); -extern void m_xt_init(const machine_t *, void *); -extern void m_xt86_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t m_pc_device; -extern const device_t m_xt_device; -#endif - -extern void m_xt_compaq_p1_init(const machine_t *, void *); - -extern void m_xt_laserxt_init(const machine_t *, void *); -extern void m_xt_lxt3_init(const machine_t *, void *); - -extern void m_xt_t1000_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t m_xt_t1000_device; -extern const device_t t1000_video_device; -extern const device_t t1200_video_device; -#endif -extern void m_xt_t1200_init(const machine_t *, void *); -extern void m_xt_t1x00_close(void); - -extern void m_xt_xi8088_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t m_xi8088_device; -#endif +extern void m_at_ps2_init(void); +extern void m_at_ps2_ide_init(void); #endif /*EMU_MACHINE_H*/ diff --git a/src/machines/machine_table.c b/src/machines/machine_table.c index ba81ef1..43c1035 100644 --- a/src/machines/machine_table.c +++ b/src/machines/machine_table.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine_table.c 1.0.37 2019/03/05 + * Version: @(#)machine_table.c 1.0.39 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,186 +47,197 @@ #include "../nvr.h" #include "../rom.h" #include "../device.h" -#include "../devices/video/video.h" #include "machine.h" -/* To keep the table clean. */ -#if defined(DEV_BRANCH) && defined(USE_AMD_K) -# define CPU_AMD_K5 {"AMD", cpus_K5} -# define CPU_AMD_K56 {"AMD", cpus_K56} -#else -# define CPU_AMD_K5 {"", NULL} -# define CPU_AMD_K56 {"", NULL} -#endif - - -const machine_t machines[] = { +static const struct { + const char *name; + const char *internal_name; + const device_t *device; +} machines[] = { /* 8088 */ - { "[8088] IBM PC (1981)", "ibm_pc", L"ibm/pc", -1, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 16, 256, 16, 0, m_pc_init, &m_pc_device, NULL }, - { "[8088] IBM PC (1982)", "ibm_pc82", L"ibm/pc82", -1, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 256, 32, 0, m_pc82_init, &m_pc_device, NULL }, - { "[8088] IBM PCjr", "ibm_pcjr", L"ibm/pcjr", -1, {{"Intel", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, m_pcjr_init, &m_pcjr_device, NULL }, - { "[8088] IBM XT (1982)", "ibm_xt", L"ibm/xt", -1, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, m_xt_init, &m_xt_device, NULL }, - { "[8088] IBM XT (1986)", "ibm_xt86", L"ibm/xt86", -1, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, m_xt86_init, &m_xt_device, NULL }, + { "[8088] IBM PC (1981)", "ibm_pc", &m_pc81 }, + { "[8088] IBM PC (1982)", "ibm_pc82", &m_pc82 }, + { "[8088] IBM PCjr", "ibm_pcjr", &m_pcjr }, + { "[8088] IBM XT (1982)", "ibm_xt", &m_xt82 }, + { "[8088] IBM XT (1986)", "ibm_xt86", &m_xt86 }, - { "[8088] AMI XT (generic)", "ami_xt", L"generic/xt/ami", 0, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, m_xt_init, &m_xt_device, NULL }, - { "[8088] Award XT (generic)", "awd_xt", L"generic/xt/award", 0, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, m_xt_init, &m_xt_device, NULL }, - { "[8088] Phoenix XT (generic)", "phoenix_xt", L"generic/xt/phoenix", 0, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, m_xt_init, NULL, NULL }, + { "[8088] AMI XT (generic)", "ami_xt", &m_xt_ami }, + { "[8088] Award XT (generic)", "awd_xt", &m_xt_award }, + { "[8088] Phoenix XT (generic)", "phoenix_xt", &m_xt_phoenix }, - { "[8088] OpenXT (generic)", "open_xt", L"generic/xt/open_xt", 0, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"Intel", cpus_186}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, m_xt_init, &m_xt_device, NULL }, + { "[8088] OpenXT (generic)", "open_xt", &m_xt_openxt }, - { "[8088] Compaq Portable", "compaq_portable", L"compaq/portable", -1, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, m_xt_compaq_p1_init, NULL, NULL }, - { "[8088] DTK XT", "dtk_xt", L"dtk/xt", 0, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, m_xt_init, &m_xt_device, NULL }, - { "[8088] Juko XT", "juko_pc", L"juko/pc", 0, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, m_xt_init, NULL, NULL }, - { "[8088] Schneider EuroPC", "schneider_europc", L"schneider/europc", 0, {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 16, m_europc_init, NULL, NULL }, - { "[8088] Tandy 1000", "tandy_1000", L"tandy/t1000", -1, {{"Intel", cpus_europc}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, m_tandy1k_init, &m_tandy1k_device, NULL }, - { "[8088] Tandy 1000 HX", "tandy_1000hx", L"tandy/t1000hx", -1, {{"Intel", cpus_europc}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 256, 640, 128, 0, m_tandy1k_hx_init, &m_tandy1k_hx_device, NULL }, - { "[8088] Toshiba T1000", "toshiba_t1000", L"toshiba/t1000", -1, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 64, m_xt_t1000_init, &m_xt_t1000_device, m_xt_t1x00_close }, - { "[8088] VTech Laser Turbo XT", "vtech_ltxt", L"vtech/ltxt", -1, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 640, 256, 0, m_xt_laserxt_init, NULL, NULL }, - { "[8088] Xi8088", "malinov_xi8088", L"malinov/xi8088", -1, {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA /*| MACDHINE_AT*/ | MACHINE_PS2, 64, 1024, 128, 128, m_xt_xi8088_init, NULL, NULL }, - { "[8088] Zenith Data SupersPORT", "zenith_supersport", L"zenith/supersport", -1, {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 128, 640, 128, 0, m_zenith_supersport_init, NULL, NULL }, +#if defined(DEV_BRANCH) && defined(USE_COMPAQ) + { "[8088] Compaq Portable", "compaq_portable", &m_cpq_p1 }, +#endif + { "[8088] DTK XT", "dtk_xt", &m_xt_dtk }, + { "[8088] Juko XT", "juko_pc", &m_xt_juko }, + { "[8088] Schneider EuroPC", "schneider_europc", &m_europc }, + { "[8088] Tandy 1000", "tandy_1000", &m_tandy_1k }, + { "[8088] Tandy 1000 HX", "tandy_1000hx", &m_tandy_1k_hx }, + { "[8088] Toshiba T1000", "toshiba_t1000", &m_tosh_1000 }, + { "[8088] VTech Laser Turbo XT", "vtech_ltxt", &m_laser_xt }, + { "[8088] Xi8088", "malinov_xi8088", &m_xi8088 }, +#if defined(DEV_BRANCH) && defined(USE_SUPERSPORT) + { "[8088] Zenith SupersPORT", "zenith_supersport", &m_zenith_ss }, +#endif /* 8086 */ - { "[8086] Amstrad PC1512", "amstrad_pc1512", L"amstrad/pc1512", -1, {{"Intel", cpus_pc1512}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 64, m_amstrad_1512_init, &m_amstrad_1512_device, NULL }, - { "[8086] Amstrad PC1640", "amstrad_pc1640", L"amstrad/pc1640", -1, {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, m_amstrad_1640_init, NULL, NULL }, - { "[8086] Amstrad PC2086", "amstrad_pc2086", L"amstrad/pc2086", -1, {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, m_amstrad_2086_init, NULL, NULL }, - { "[8086] Amstrad PC3086", "amstrad_pc3086", L"amstrad/pc3086", -1, {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, m_amstrad_3086_init, NULL, NULL }, - { "[8086] Amstrad PC20(0)", "amstrad_pc200", L"amstrad/pc200", -1, {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 64, m_amstrad_200_init, &m_amstrad_200_device, NULL }, - { "[8086] Olivetti M24", "olivetti_m24", L"olivetti/m24", -1, {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, m_olim24_init, NULL, NULL }, - { "[8086] Tandy 1000 SL/2", "tandy_1000sl2", L"tandy/t1000sl2", -1, {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, m_tandy1k_sl2_init, &m_tandy1k_sl2_device, NULL }, - { "[8086] Toshiba T1200", "toshiba_t1200", L"toshiba/t1200", -1, {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_HDC, 1024, 2048,1024, 64, m_xt_t1200_init, &t1200_video_device, m_xt_t1x00_close }, - { "[8086] VTech Laser XT3", "vtech_lxt3", L"vtech/lxt3", -1, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 640, 256, 0, m_xt_lxt3_init, NULL, NULL }, + { "[8086] Amstrad PC1512", "amstrad_pc1512", &m_amstrad_1512 }, + { "[8086] Amstrad PC1640", "amstrad_pc1640", &m_amstrad_1640 }, + { "[8086] Amstrad PC2086", "amstrad_pc2086", &m_amstrad_2086 }, + { "[8086] Amstrad PC3086", "amstrad_pc3086", &m_amstrad_3086 }, + { "[8086] Amstrad PC20(0)", "amstrad_pc200", &m_amstrad_200 }, + { "[8086] Amstrad PPC512/640", "amstrad_ppc512", &m_amstrad_ppc }, + { "[8086] AT&T PC6300", "att_6300", &m_att_6300 }, + { "[8086] Olivetti M24", "olivetti_m24", &m_oli_m24 }, + { "[8086] Olivetti M240", "olivetti_m240", &m_oli_m240 }, + { "[8086] Tandy 1000 SL/2", "tandy_1000sl2", &m_tandy_1k_sl2 }, + { "[8086] Toshiba T1200", "toshiba_t1200", &m_tosh_1200 }, + { "[8086] VTech Laser XT/3", "vtech_lxt3", &m_laser_xt3 }, /* 80286 */ - { "[286 ISA] IBM AT", "ibm_at", L"ibm/at", -1, {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 64, m_at_ibm_init, NULL, NULL }, - { "[286 ISA] IBM XT Model 286", "ibm_xt286", L"ibm/xt286", -1, {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 128, m_at_ibm_init, NULL, NULL }, - { "[286 ISA] IBM PS/1 model 2011", "ibm_ps1_2011", L"ibm/ps1_2011", -1, {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 512, 6144, 512, 64, m_ps1_m2011_init, &m_ps1_device, NULL }, - { "[286 ISA] IBM PS/2 model 30-286", "ibm_ps2_m30_286", L"ibm/ps2_m30_286", -1, {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 64, m_ps2_m30_286_init, NULL, NULL }, + { "[286 ISA] IBM AT", "ibm_at", &m_at }, + { "[286 ISA] IBM XT Model 286", "ibm_xt286", &m_xt286 }, + { "[286 ISA] IBM PS/1 model 2011", "ibm_ps1_2011", &m_ps1_2011 }, + { "[286 ISA] IBM PS/2 model 30-286", "ibm_ps2_m30_286", &m_ps2_m30_286 }, - { "[286 ISA] AMI 286 (generic)", "ami_286", L"generic/at/ami", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 128, m_at_neat_ami_init, NULL, NULL }, - { "[286 ISA] Award 286 (generic)", "award_286", L"generic/at/award", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, m_at_scat_init, NULL, NULL }, + { "[286 ISA] AMI 286 (NEAT)", "ami_286", &m_neat_ami }, + { "[286 ISA] Award 286 (SCAT)", "award_286", &m_scat_award }, - { "[286 ISA] Commodore PC 30 III", "commodore_pc30", L"commodore/pc30", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 128, m_at_cmdpc_init, NULL, NULL }, - { "[286 ISA] Compaq Portable II", "compaq_portable2", L"compaq/portable2", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 128, m_at_compaq_p2_init, NULL, NULL }, -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[286 ISA] Compaq Portable III", "compaq_portable3", L"compaq/portable3", 6, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 128, m_at_compaq_p3_init, NULL, NULL }, + { "[286 ISA] Commodore PC-30", "commodore_pc30", &m_cbm_pc30 }, +#if defined(DEV_BRANCH) && defined(USE_COMPAQ) + { "[286 ISA] Compaq Portable (286)", "compaq_portable286", &m_cpq_p1_286 }, + { "[286 ISA] Compaq Portable II", "compaq_portable2", &m_cpq_p2 }, + { "[286 ISA] Compaq Portable III", "compaq_portable3", &m_cpq_p3 }, #endif - { "[286 ISA] GW-286CT GEAR", "gw286ct", L"unknown/gw286ct", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, m_at_scat_gw286ct_init, NULL, NULL }, - { "[286 ISA] Hyundai Super-286TR", "hyundai_super286tr", L"hyundai/super286tr", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, m_at_scat_init, NULL, NULL }, - { "[286 ISA] Samsung SPC-4200P", "samsung_spc4200p", L"samsung/spc4200p", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 128, m_at_scat_init, NULL, NULL }, - { "[286 ISA] Samsung SPC-4216P", "samsung_spc4216p", L"samsung/spc4216p", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 128, m_at_scat_spc4216p_init, NULL, NULL }, - { "[286 ISA] Toshiba T3100e", "toshiba_t3100e", L"toshiba/t3100e", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_HDC, 1024, 5120, 256, 64, m_at_t3100e_init, NULL, NULL }, - { "[286 ISA] Trigem 286M", "tg286m", L"trigem/tg286m", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 128, m_at_tg286m_init, NULL, NULL }, + { "[286 ISA] Gear GW-286CT", "gw286ct", &m_gw286ct }, + { "[286 ISA] Hyundai Super-286TR", "hyundai_super286tr", &m_hs286tr }, + { "[286 ISA] Samsung SPC-4200P", "samsung_spc4200p", &m_spc4200p }, + { "[286 ISA] Samsung SPC-4216P", "samsung_spc4216p", &m_spc4216p }, + { "[286 ISA] Toshiba T3100e", "toshiba_t3100e", &m_tosh_3100e }, + { "[286 ISA] Trigem 286M", "tg286m", &m_tg286m }, - { "[286 MCA] IBM PS/2 model 50", "ibm_ps2_m50", L"ibm/ps2_m50", -1, {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 10, 1, 64, m_ps2_model_50_init, NULL, NULL }, + { "[286 MCA] IBM PS/2 model 50", "ibm_ps2_m50", &m_ps2_m50 }, /* 80386SX */ - { "[386SX ISA] IBM PS/1 model 2121", "ibm_ps1_2121", L"ibm/ps1_2121", -1, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 64, m_ps1_m2121_init, &m_ps1_device, NULL }, - { "[386SX ISA] IBM PS/1 m.2121+ISA", "ibm_ps1_2121_isa", L"ibm/ps1_2121", -1, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 64, m_ps1_m2121_init, &m_ps1_device, NULL }, + { "[386SX ISA] IBM PS/1 model 2121", "ibm_ps1_2121", &m_ps1_2121 }, + { "[386SX ISA] IBM PS/1 m.2121+ISA", "ibm_ps1_2121_isa", &m_ps1_2121 }, - { "[386SX ISA] AMI 386SX", "ami_386sx", L"headland/386sx/ami", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 128, m_at_headland_init, NULL, NULL }, - { "[386SX ISA] AMI 386SX (OPTi495)", "ami_386sx_opti495", L"opti495/ami", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 16, 1, 128, m_at_opti495_ami_init, NULL, NULL }, - { "[386SX ISA] Award 386SX (Opti495)", "award_386sx_opti495", L"opti495/award", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 16, 1, 128, m_at_opti495_award_init, NULL, NULL }, - { "[386SX ISA] MR 386SX (OPTi495)", "mr_386sx_opti495", L"opti495/mr", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 16, 1, 128, m_at_opti495_mr_init, NULL, NULL }, + { "[386SX ISA] AMI 386SX (Headland)", "ami_386sx", &m_headland_386_ami }, + { "[386SX ISA] AMI 386SX (OPTi495)", "ami_386sx_opti495", &m_opti495_386sx_ami }, + { "[386SX ISA] Award 386SX (Opti495)", "award_386sx_opti495", &m_opti495_386sx_award }, + { "[386SX ISA] MR 386SX (OPTi495)", "mr_386sx_opti495", &m_opti495_386sx_mr }, - { "[386SX ISA] Amstrad MegaPC", "amstrad_megapc", L"amstrad/megapc", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 16, 1, 128, m_at_wd76c10_init, NULL, NULL }, - { "[386SX ISA] Arche AMA-932J", "arche_ama932j", L"arche/ama932j", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 128, m_at_ama932j_init, &oti067_onboard_device, NULL }, - { "[386SX ISA] DTK 386SX clone", "dtk_386", L"dtk/386", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 128, m_at_neat_init, NULL, NULL }, - { "[386SX ISA] KMX-C-02", "kmxc02", L"unknown/kmxc02", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 128, m_at_scatsx_init, NULL, NULL }, + { "[386SX ISA] Amstrad MegaPC", "amstrad_megapc", &m_amstrad_mega_sx }, + { "[386SX ISA] Arche AMA-932J", "arche_ama932j", &m_ama932j }, + { "[386SX ISA] DTK 386SX clone", "dtk_386", &m_neat_dtk }, + { "[386SX ISA] KMX-C-02", "kmxc02", &m_kmxc02 }, - { "[386SX MCA] IBM PS/2 model 55SX", "ibm_ps2_m55sx", L"ibm/ps2_m55sx", 16, {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 8, 1, 64, m_ps2_model_55sx_init, NULL, NULL }, + { "[386SX MCA] IBM PS/2 model 55SX", "ibm_ps2_m55sx", &m_ps2_m55sx }, /* 80386DX */ - { "[386DX ISA] AMI 386DX (Opti495)", "ami_386dx_opti495", L"opti495/ami", 0, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 128, m_at_opti495_ami_init, NULL, NULL }, - { "[386DX ISA] Award 386DX (Opti495)", "award_386dx_opti495", L"opti495/award", 0, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 128, m_at_opti495_award_init, NULL, NULL }, - { "[386DX ISA] MR 386DX (Opti495)", "mr_386dx_opti495", L"opti495/mr", 0, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 128, m_at_opti495_mr_init, NULL, NULL }, + { "[386DX ISA] AMI 386DX (Opti495)", "ami_386dx_opti495", &m_opti495_386dx_ami }, + { "[386DX ISA] Award 386DX (Opti495)", "award_386dx_opti495", &m_opti495_386dx_award }, + { "[386DX ISA] MR 386DX (Opti495)", "mr_386dx_opti495", &m_opti495_386dx_mr }, - { "[386DX ISA] Amstrad MegaPC 386DX", "amstrad_megapc_dx", L"amstrad/megapc", 0, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 32, 1, 128, m_at_wd76c10_init, NULL, NULL }, -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[386DX ISA] Compaq Portable III (386)", "portable3_386", L"compaq/deskpro386", -1, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 128, m_at_compaq_p3_386_init, NULL, NULL }, + { "[386DX ISA] Amstrad MegaPC 386DX", "amstrad_megapc_dx", &m_amstrad_mega_dx }, +#if defined(DEV_BRANCH) && defined(USE_COMPAQ) + { "[386DX ISA] Compaq Portable III (386)", "portable3_386", &m_cpq_p3_386 }, #endif - { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibm_ps2_m70_type3", L"ibm/ps2_m70_type3", -1, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 2, 16, 2, 64, m_ps2_model_70_type3_init, NULL, NULL }, - { "[386DX MCA] IBM PS/2 model 80", "ibm_ps2_m80", L"ibm/ps2_m80", -1, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 12, 1, 64, m_ps2_model_80_init, NULL, NULL }, + { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibm_ps2_m70_type3", &m_ps2_m70_3 }, + { "[386DX MCA] IBM PS/2 model 80", "ibm_ps2_m80", &m_ps2_m80 }, /* 80486 */ - { "[486 ISA] IBM PS/1 model 2133", "ibm_ps1_2133", L"ibm/ps1_2133", -1, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 128, m_ps1_m2133_init, NULL, NULL }, + { "[486 ISA] IBM PS/1 model 2133", "ibm_ps1_2133", &m_ps1_2133 }, - { "[486 ISA] AMI 486 (ALi1429)", "ami_486_ali1429", L"ali1429/ami", 0, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, m_at_ali1429_init, NULL, NULL }, + { "[486 ISA] AMI 486 (ALi1429)", "ami_486_ali1429", &m_ali1429_ami }, #if defined(DEV_BRANCH) && defined(USE_SIS471) - { "[486 ISA] AMI 486 (SiS471)", "ami_486_sis471", L"sis471/ami", 0, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 128, m_at_sis471_ami_init, NULL, NULL }, + { "[486 ISA] AMI 486 (SiS471)", "ami_486_sis471", &m_sis471_ami }, #endif - { "[486 ISA] AMI WinBIOS486 (ALi1429)", "ami_win486_ali1429", L"ali1429/ami_win", 0, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, m_at_ali1429_init, NULL, NULL }, - { "[486 ISA] Award 486 (Opti495)", "award_486_opti495", L"opti495/award", 0, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 128, m_at_opti495_award_init, NULL, NULL }, - { "[486 ISA] MR 486 (Opti495)", "mr_486dx_opti495", L"opti495/mr", 0, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 128, m_at_opti495_mr_init, NULL, NULL }, + { "[486 ISA] AMI WinBIOS486 (ALi1429)", "ami_win486_ali1429", &m_ali1429_win }, + { "[486 ISA] Award 486 (Opti495)", "award_486_opti495", &m_opti495_486_award }, + { "[486 ISA] MR 486 (Opti495)", "mr_486dx_opti495", &m_opti495_486_mr }, - { "[486 ISA] DTK PKM-0038S E-2", "dtk_486", L"dtk/486", 0, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 128, m_at_dtk486_init, NULL, NULL }, + { "[486 ISA] DTK PKM-0038S E-2", "dtk_486", &m_dtk486 }, - { "[486 MCA] IBM PS/2 model 70 (type 4)", "ibm_ps2_m70_type4", L"ibm/ps2_m70_type4", -1, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 2, 16, 2, 64, m_ps2_model_70_type4_init, NULL, NULL }, + { "[486 MCA] IBM PS/2 model 70 (type 4)", "ibm_ps2_m70_type4", &m_ps2_m70_4 }, #if defined(DEV_BRANCH) && defined(USE_SIS496) - { "[486 PCI] AMI 486 (SiS496)", "ami_486_sis496", L"sis496/ami", 0, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 128, m_at_sis496_ami_init, NULL, NULL }, + { "[486 PCI] AMI 486 (SiS496)", "ami_486_sis496", &m_sis496_ami }, #endif - { "[486 PCI] Rise Computer R418", "rise_r418", L"rise/r418", 0, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 128, m_at_r418_init, NULL, NULL }, + { "[486 PCI] Rise Computer R418", "rise_r418", &m_rise418 }, /* Pentium, Socket4 (LX) */ - { "[Socket 4 LX] Intel Premiere/PCI", "intel_revenge", L"intel/revenge", -1, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, m_at_batman_init, NULL, NULL }, + { "[Socket 4 LX] Intel Premiere/PCI", "intel_revenge", &m_batman }, /* Pentium, Socket5 (NX) */ - { "[Socket 5 NX] Intel Premiere/PCI II", "intel_plato", L"intel/plato", -1, {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, CPU_AMD_K5, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, m_at_plato_init, NULL, NULL }, + { "[Socket 5 NX] Intel Premiere/PCI II", "intel_plato", &m_plato }, /* Pentium, Socket5 (FX) */ - { "[Socket 5 FX] ASUS P/I-P54TP4XE", "asus_p54tp4xe", L"asus/p54tp4xe", -1, {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, CPU_AMD_K5, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, m_at_p54tp4xe_init, NULL, NULL }, - { "[Socket 5 FX] Intel Advanced/ZP", "intel_zappa", L"intel/zappa", -1, {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, CPU_AMD_K5, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, m_at_zappa_init, NULL, NULL }, - { "[Socket 5 FX] PC Partner MB500N", "pcpartner_mb500n", L"pcpartner/mb500n", -1, {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, CPU_AMD_K5, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, m_at_mb500n_init, NULL, NULL }, - { "[Socket 5 FX] President Award 430FX PCI","president", L"president/president", -1, {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, CPU_AMD_K5, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, m_at_president_init, NULL, NULL }, + { "[Socket 5 FX] ASUS P/I-P54TP4XE", "asus_p54tp4xe", &m_p54tp4xe }, + { "[Socket 5 FX] Intel Advanced/ZP", "intel_zappa", &m_zappa }, + { "[Socket 5 FX] PC Partner MB500N", "pcpartner_mb500n", &m_mb500n }, + { "[Socket 5 FX] President Award 430FX PCI","president", &m_president }, /* Pentium, Socket7 (FX) */ - { "[Socket 7 FX] Intel Advanced/ATX", "intel_thor", L"intel/thor", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, m_at_thor_init, NULL, NULL }, - { "[Socket 7 FX] MR Intel Advanced/ATX", "intel_thor_mr", L"intel/thor_mr", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, m_at_thor_init, NULL, NULL }, - { "[Socket 7 FX] Intel Advanced/EV", "intel_endeavor", L"intel/endeavor", -1, {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, m_at_endeavor_init, &s3_phoenix_trio64_onboard_pci_device, NULL }, - { "[Socket 7 FX] Packard Bell PB640", "pbell_pb640", L"pbell/pb640", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, m_at_pb640_init, &gd5440_onboard_pci_device, NULL }, + { "[Socket 7 FX] Intel Advanced/ATX", "intel_thor", &m_thor }, + { "[Socket 7 FX] MR Intel Advanced/ATX", "intel_thor_mr", &m_thor_mr }, + { "[Socket 7 FX] Intel Advanced/EV", "intel_endeavor", &m_endeavor }, + { "[Socket 7 FX] Packard Bell PB640", "pbell_pb640", &m_pb640 }, /* Pentium, Socket7 (HX) */ - { "[Socket 7 HX] Acer M3a", "acer_m3a", L"acer/m3a", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, m_at_acerm3a_init, NULL, NULL }, - { "[Socket 7 HX] Acer V35n", "acer_v35n", L"acer/v35n", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, m_at_acerv35n_init, NULL, NULL }, - { "[Socket 7 HX] AOpen AP53", "aopen_ap53", L"aopen/ap53", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, m_at_ap53_init, NULL, NULL }, - { "[Socket 7 HX] ASUS P/I-P55T2P4", "asus_p55t2p4", L"asus/p55t2p4", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, m_at_p55t2p4_init, NULL, NULL }, - { "[Socket 7 HX] SuperMicro Super P55T2S", "supermicro_p55t2s", L"supermicro/p55t2s", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 128, m_at_p55t2s_init, NULL, NULL }, + { "[Socket 7 HX] Acer M3a", "acer_m3a", &m_acer_m3a }, + { "[Socket 7 HX] Acer V30", "acer_v30", &m_acer_v30 }, + { "[Socket 7 HX] Acer V35n", "acer_v35n", &m_acer_v35n }, + { "[Socket 7 HX] AOpen AP53", "aopen_ap53", &m_ap53 }, + { "[Socket 7 HX] ASUS P/I-P55T2P4", "asus_p55t2p4", &m_p55t2p4 }, + { "[Socket 7 HX] SuperMicro Super P55T2S", "supermicro_p55t2s", &m_p55t2s }, /* Pentium, Socket7 (VX) */ - { "[Socket 7 VX] ASUS P/I-P55TVP4", "asus_p55tvp4", L"asus/p55tvp4", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, m_at_p55tvp4_init, NULL, NULL }, - { "[Socket 7 VX] Award 430VX PCI", "award_430vx", L"generic/430vx/award", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, m_at_i430vx_init, NULL, NULL }, - { "[Socket 7 VX] Epox P55-VA", "epox_p55va", L"epox/p55va", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, m_at_p55va_init, NULL, NULL }, - { "[Socket 7 VX] Jetway J656VXD", "jetway_j656vxd", L"jetway/j656vxd", -1, {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, CPU_AMD_K56, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, m_at_j656vxd_init, NULL, NULL }, + { "[Socket 7 VX] ASUS P/I-P55TVP4", "asus_p55tvp4", &m_p55tvp4 }, + { "[Socket 7 VX] Award 430VX PCI", "award_430vx", &m_aw430vx }, + { "[Socket 7 VX] Epox P55-VA", "epox_p55va", &m_p55va }, + { "[Socket 7 VX] Jetway J656VXD", "jetway_j656vxd", &m_j656vxd }, -#if defined(DEV_BRANCH) && defined(USE_I686) /* Pentium, Socket5 */ - { "[Socket 8 FX] Tyan Titan-Pro AT", "tyan_440fx", L"tyan/440fx", -1, {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 128, m_at_i440fx_init, NULL, NULL }, - { "[Socket 8 FX] Tyan Titan-Pro ATX", "tyan_tpatx", L"tyan/tpatx", -1, {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 128, m_at_s1668_init, NULL, NULL }, -#endif - { NULL, NULL, NULL, -1, {{"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } + { "[Socket 8 FX] Tyan Titan-Pro AT (S1662, AMI)","tyan_s1662_ami", &m_tyan_1662_ami }, + { "[Socket 8 FX] Tyan Titan-Pro AT (S1662, Award)","tyan_s1662_award", &m_tyan_1662_award }, + { "[Socket 8 FX] Tyan Titan-Pro ATX (S1668, AMI)","tyan_s1668_ami", &m_tyan_1668_ami }, + { "[Socket 8 FX] Tyan Titan-Pro ATX (S1668), Award","tyan_s1668_award", &m_tyan_1668_award }, + + { NULL, NULL, NULL } }; -const char * -machine_getname(void) +int +machine_get_from_internal_name(const char *s) { - return(machines[machine].name); + int c; + + for (c = 0; machines[c].internal_name != NULL; c++) { + if (! strcmp(machines[c].internal_name, s)) + return(c); + } + + /* Not found. */ + return(-1); } const char * -machine_getname_ex(int m) +machine_get_name_ex(int m) { return(machines[m].name); } const char * -machine_get_internal_name(void) +machine_get_name(void) { - return(machines[machine].internal_name); + return(machine_get_name_ex(machine_type)); } @@ -237,43 +248,38 @@ machine_get_internal_name_ex(int m) } -int -machine_get_from_internal_name(const char *s) +const char * +machine_get_internal_name(void) { - int c = 0; - - while (machines[c].internal_name != NULL) { - if (! strcmp(machines[c].internal_name, s)) - return(c); - c++; - } - - /* Not found. */ - return(-1); + return(machine_get_internal_name_ex(machine_type)); } const device_t * -machine_getdevice(int m) +machine_get_device_ex(int m) { return(machines[m].device); } +const device_t * +machine_get_device(void) +{ + return(machine_get_device_ex(machine_type)); +} + + int machine_get_config_int(const char *s) { - const device_t *d = machine_getdevice(machine); + const device_t *d = machine_get_device(); const device_config_t *c; if (d == NULL) return(0); - c = d->config; - while (c && c->type != -1) { + for (c = d->config; c && c->name; c++) { if (! strcmp(s, c->name)) return(config_get_int(d->name, s, c->default_int)); - - c++; } return(0); @@ -283,17 +289,14 @@ machine_get_config_int(const char *s) const char * machine_get_config_string(const char *s) { - const device_t *d = machine_getdevice(machine); + const device_t *d = machine_get_device(); const device_config_t *c; if (d == NULL) return(0); - c = d->config; - while (c && c->type != -1) { + for (c = d->config; c && c->name; c++) { if (! strcmp(s, c->name)) return(config_get_string(d->name, s, c->default_string)); - - c++; } return(NULL); diff --git a/src/mem.c b/src/mem.c index 3e9f78d..c2ab1ca 100644 --- a/src/mem.c +++ b/src/mem.c @@ -8,7 +8,7 @@ * * Memory handling and MMU. * - * Version: @(#)mem.c 1.0.26 2019/02/10 + * Version: @(#)mem.c 1.0.29 2019/04/20 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,7 +46,6 @@ #include "cpu/x86_ops.h" #include "cpu/x86.h" #include "machines/machine.h" -#include "machines/m_xt_xi8088.h" //FIXME: remove? #include "config.h" #include "io.h" #include "mem.h" @@ -61,24 +60,19 @@ #endif +uint8_t *ram; /* the virtual RAM */ +uint32_t rammask; + mem_map_t base_mapping, ram_low_mapping, /* 0..640K mapping */ ram_mid_mapping, ram_remapped_mapping, /* 640..1024K mapping */ - ram_high_mapping, /* 1024K+ mapping */ - bios_mapping[8], - bios_high_mapping[8]; + ram_high_mapping; /* 1024K+ mapping */ page_t *pages, /* RAM page table */ **page_lookup; /* pagetable lookup */ uint32_t pages_sz = 0; /* #pages in table */ -uint8_t *ram; /* the virtual RAM */ -uint32_t rammask; - -uint8_t *rom; /* the virtual ROM */ -uint32_t biosmask; - uint32_t pccache; uint8_t *pccache2; @@ -93,8 +87,6 @@ uintptr_t *writelookup2; uint32_t mem_logical_addr; -int shadowbios = 0, - shadowbios_write; int pctrans = 0; int cachesize = 256; @@ -433,7 +425,7 @@ getpccache(uint32_t a) a2 = a; if (cr0 >> 31) { - pctrans=1; + pctrans = 1; a = mmutranslate_read(a); pctrans = 0; @@ -1143,27 +1135,6 @@ mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) } -uint8_t -mem_read_bios(uint32_t addr, void *priv) -{ - return rom[addr & biosmask]; -} - - -uint16_t -mem_read_biosw(uint32_t addr, void *priv) -{ - return *(uint16_t *)&rom[addr & biosmask]; -} - - -uint32_t -mem_read_biosl(uint32_t addr, void *priv) -{ - return *(uint32_t *)&rom[addr & biosmask]; -} - - void mem_write_null(uint32_t addr, uint8_t val, void *p) { @@ -1218,7 +1189,7 @@ mem_map_read_allowed(uint32_t fl, int state) return !(fl & MEM_MAPPING_EXTERNAL); default: - fatal("mem_mapping_read_allowed : bad state %x\n", state); + fatal("mem_map_read_allowed : bad state %x\n", state); } return 0; @@ -1238,7 +1209,7 @@ mem_map_write_allowed(uint32_t fl, int state) case MEM_WRITE_INTERNAL: return !(fl & MEM_MAPPING_EXTERNAL); default: - fatal("mem_mapping_write_allowed : bad state %x\n", state); + fatal("mem_map_write_allowed : bad state %x\n", state); } return 0; @@ -1358,6 +1329,7 @@ mem_map_add(mem_map_t *map, uint32_t base, uint32_t size, map->exec = exec; map->flags = fl; map->p = p; + map->p2 = NULL; map->dev = NULL; map->next = NULL; @@ -1417,6 +1389,13 @@ mem_map_set_p(mem_map_t *map, void *p) } +void +mem_map_set_p2(mem_map_t *map, void *p) +{ + map->p2 = p; +} + + void mem_map_set_dev(mem_map_t *map, void *p) { @@ -1454,114 +1433,6 @@ mem_set_mem_state(uint32_t base, uint32_t size, int state) } -void -mem_add_upper_bios(void) -{ - mem_map_add(&bios_mapping[0], 0xe0000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom,MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_mapping[1], 0xe4000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x4000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_mapping[2], 0xe8000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x8000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_mapping[3], 0xec000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0xc000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); -} - - -void -mem_add_bios(void) -{ - if (AT) - mem_add_upper_bios(); - - mem_map_add(&bios_mapping[4], 0xf0000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x10000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_mapping[5], 0xf4000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x14000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_mapping[6], 0xf8000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x18000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_mapping[7], 0xfc000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x1c000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_high_mapping[0], - (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom, MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_high_mapping[1], - (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x4000 & biosmask), MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_high_mapping[2], - (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x8000 & biosmask), MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_high_mapping[3], - (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0xc000 & biosmask), MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_high_mapping[4], - (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x10000 & biosmask), MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_high_mapping[5], - (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x14000 & biosmask), MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_high_mapping[6], - (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x18000 & biosmask), MEM_MAPPING_ROM, 0); - - mem_map_add(&bios_high_mapping[7], - (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x1c000 & biosmask), MEM_MAPPING_ROM, 0); -} - - void mem_a20_init(void) { @@ -1583,20 +1454,13 @@ mem_reset(void) { uint32_t c, m; - /* Free the ROM memory and reset size mask. */ - if (rom != NULL) { - free(rom); - rom = NULL; - } - biosmask = 0xffff; - /* * Make sure the configured amount of RAM does not * exceed the physical limit of the machine to avoid * nasty crashes all over the place. */ m = mem_size; - c = machines[machine].max_ram; + c = machine->max_ram; if (AT) c <<= 10; /* make KB */ if (m > c) { @@ -1639,8 +1503,8 @@ mem_reset(void) if (pages_sz != m || pages_sz == 0) { pages_sz = m; free(pages); - pages = (page_t *)mem_alloc(m*sizeof(page_t)); - memset(pages, 0x00, m*sizeof(page_t)); + pages = (page_t *)mem_alloc(m * sizeof(page_t)); + memset(pages, 0x00, m * sizeof(page_t)); } /* Initialize the page table. */ @@ -1718,7 +1582,7 @@ void mem_init(void) { /* Perform a one-time init. */ - ram = rom = NULL; + ram = NULL; pages = NULL; pages_sz = 0; @@ -1831,7 +1695,7 @@ port_92_write(uint16_t port, uint8_t val, void *priv) } if ((~port_92_reg & val) & 1) { - softresetx86(); + cpu_reset(0); cpu_set_edx(); } diff --git a/src/mem.h b/src/mem.h index c01297c..cf45d7b 100644 --- a/src/mem.h +++ b/src/mem.h @@ -8,7 +8,7 @@ * * Definitions for the memory interface. * - * Version: @(#)mem.h 1.0.12 2019/02/10 + * Version: @(#)mem.h 1.0.14 2019/03/29 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -102,9 +102,6 @@ typedef struct _page_ { extern uint8_t *ram; extern uint32_t rammask; -extern uint8_t *rom; -extern uint32_t biosmask; - extern int readlookup[256], readlookupp[256]; extern uintptr_t *readlookup2; @@ -119,10 +116,7 @@ extern mem_map_t base_mapping, ram_low_mapping, ram_mid_mapping, ram_remapped_mapping, - ram_high_mapping, - bios_mapping[8], - bios_high_mapping[8], - romext_mapping; + ram_high_mapping; extern uint32_t mem_logical_addr; @@ -131,9 +125,6 @@ extern page_t *pages, extern uint32_t get_phys_virt,get_phys_phys; -extern int shadowbios, - shadowbios_write; - extern int memspeed[11]; extern int mmu_perm; @@ -198,6 +189,7 @@ extern void mem_map_set_handler(mem_map_t *, void (*write_l)(uint32_t addr, uint32_t val, void *p)); extern void mem_map_set_p(mem_map_t *, void *p); +extern void mem_map_set_p2(mem_map_t *, void *p); extern void mem_map_set_dev(mem_map_t *, void *dev); @@ -219,10 +211,6 @@ extern void mem_write_ram(uint32_t addr, uint8_t val, void *priv); extern void mem_write_ramw(uint32_t addr, uint16_t val, void *priv); extern void mem_write_raml(uint32_t addr, uint32_t val, void *priv); -extern uint8_t mem_read_bios(uint32_t addr, void *priv); -extern uint16_t mem_read_biosw(uint32_t addr, void *priv); -extern uint32_t mem_read_biosl(uint32_t addr, void *priv); - extern void mem_write_null(uint32_t addr, uint8_t val, void *p); extern void mem_write_nullw(uint32_t addr, uint16_t val, void *p); extern void mem_write_nulll(uint32_t addr, uint32_t val, void *p); @@ -245,9 +233,6 @@ extern void mmu_invalidate(uint32_t addr); extern void mem_a20_recalc(void); -extern void mem_add_bios(void); -extern void mem_add_upper_bios(void); - extern void mem_init(void); extern void mem_reset(void); extern void mem_remap_top(int kb); diff --git a/src/pc.c b/src/pc.c index 2895e80..f2d2f68 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.65 2019/02/28 + * Version: @(#)pc.c 1.0.68 2019/04/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -55,6 +55,7 @@ #include "machines/machine.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "devices/system/dma.h" #include "devices/system/pic.h" #include "devices/system/pit.h" @@ -65,9 +66,9 @@ #include "devices/ports/game.h" #include "devices/ports/serial.h" #include "devices/ports/parallel.h" +#include "devices/input/game/joystick.h" #include "devices/input/keyboard.h" #include "devices/input/mouse.h" -#include "devices/input/game/joystick.h" #include "devices/floppy/fdd.h" #include "devices/floppy/fdd_common.h" #include "devices/disk/hdd.h" @@ -148,10 +149,10 @@ int sound_card = 0, /* (C) selected sound card */ midi_device; /* (C) selected midi device */ int joystick_type = 0; /* (C) joystick type */ int mem_size = 0; /* (C) memory size */ -int machine = -1; /* (C) current machine ID */ +int machine_type = -1; /* (C) current machine ID */ int cpu_manufacturer = 0, /* (C) cpu manufacturer */ + cpu_type = 3, /* (C) cpu type */ cpu_use_dynarec = 0, /* (C) cpu uses/needs Dyna */ - cpu = 3, /* (C) cpu type */ enable_external_fpu = 0; /* (C) enable external FPU */ int network_type; /* (C) net provider type */ int network_card; /* (C) net interface num */ @@ -172,13 +173,14 @@ int config_changed, /* config has changed */ dopause = 0, /* system is paused */ doresize = 0, /* screen resize requested */ mouse_capture = 0; /* mouse is captured in app */ +int AT, /* machine is AT class */ + MCA, /* machine has MCA bus */ + PCI; /* machine has PCI bus */ /* Local variables. */ static int fps, /* statistics */ framecount, - title_update, /* we want title updated */ - atfullspeed, - cpuspeed2; + title_update; /* we want title updated */ static int unscaled_size_x = SCREEN_RES_X, /* current unscaled size X */ unscaled_size_y = SCREEN_RES_Y, /* current unscaled size Y */ efscrnsz_y = SCREEN_RES_Y; @@ -342,7 +344,7 @@ fatal(const char *fmt, ...) config_save(); pic_dump(); - dumpregs(1); + cpu_dumpregs(1); /* * Attempt to perform a clean exit by terminating the @@ -735,23 +737,39 @@ usage: } -/* Set the active processor speed for this machine. */ +/* + * Set the active processor speed for this machine. + * + * The argument is either 0 for 'slowest speed', or an + * index into the CPU table to select that model' speed. + * + * This function handles two things: + * + * - it sets up the correct/expected XTAL frequency for + * the desired operating speed; + * + * - it then tells the CPU module to activate that CPU + * and/or speed. + * + * In addition, after the speed change, it updates timings. + */ void -pc_set_speed(void) +pc_set_speed(int turbo) { uint32_t speed; - int turbo = 1; /* for now */ /* + * Part One - Set up the correct XTAL frequency. + * * Get the selected processor's desired speed. * * For 286+, this is usually 8 (slow) or max speed. * For PC and XT class, this will return max speed. */ - speed = machine_speed(turbo); -INFO("PC: set_speed(%d): speed=%lu\n", speed); + speed = machine_get_speed(turbo); +INFO("PC: set_speed(%i) -> speed %lu\n", turbo, speed); - if (machine_type() >= CPU_286) { + if (cpu_get_type() >= CPU_286) { /* For 286+, we are done. */ pit_setclock(speed); } else { @@ -764,33 +782,22 @@ INFO("PC: set_speed(%d): speed=%lu\n", speed); * much all cases, the original 4.77MHz setting. */ if (turbo) - pit_setclock(14318184); + pit_setclock(14318184); // speed * xt_multi ? else pit_setclock(14318184); } -} + /* + * Part Two - set the correct processor type. + */ -void -pc_full_speed(void) -{ - cpuspeed2 = cpuspeed; - - if (! atfullspeed) { - DEBUG("Set fullspeed - %i\n", cpuspeed2); - pc_set_speed(); - atfullspeed = 1; - } - - nvr_period_recalc(); -} - - -void -pc_speed_changed(void) -{ - pc_set_speed(); - + /* + * Part Three - update several timing constants. + * + * This is necessary because the emulator's entire + * timer system is built around the CPU clock as a + * base unit. So, if we change that, everything does.. + */ nvr_period_recalc(); } @@ -839,25 +846,25 @@ pc_init(void) const char *stransi; /* If no machine selected, force user into Setup Wizard. */ - if (machine < 0) { + if (machine_type < 0) { str = get_string(IDS_ERR_NOCONF); /* Show the messagebox, and abort if 'No' was selected. */ if (ui_msgbox(MBX_QUESTION, str) != 0) return(0); /* OK, user wants to set up a machine. */ - machine = 0; + machine_type = 0; return(2); } /* Load the ROMs for the selected machine. */ - if (! machine_available(machine)) { + if (! machine_available(machine_type)) { /* Whoops, selected machine not available. */ - stransi = machine_getname(); + stransi = machine_get_name(); if (stransi == NULL) { /* This happens if configured machine is not even in table.. */ - sprintf(tempA, "machine_%i", machine); + sprintf(tempA, "machine_%i", machine_type); stransi = (const char *)tempA; } @@ -893,9 +900,6 @@ pc_init(void) * video card are available, so we can proceed with the * initialization of things. */ - cpuspeed2 = (machine_type() >= CPU_286) ? 2 : 1; - atfullspeed = 0; - random_init(); mem_init(); @@ -904,14 +908,13 @@ pc_init(void) codegen_init(); #endif + timer_reset(); + keyboard_init(); joystick_init(); + video_init(); - device_init(); - - timer_reset(); - sound_init(); #if 0 @@ -920,9 +923,6 @@ pc_init(void) floppy_init(); //FIXME: fdd_init() now? #endif - pc_full_speed(); - shadowbios = 0; - return(1); } @@ -947,8 +947,6 @@ pc_close(thread_t *ptr) nvr_save(); - machine_close(); - config_save(); ui_mouse_capture(0); @@ -961,12 +959,12 @@ pc_close(thread_t *ptr) if (dump_on_exit) pic_dump(); - dumpregs(0); - - video_close(); + cpu_dumpregs(0); device_close_all(); + video_close(); + network_close(); sound_close(); @@ -978,12 +976,8 @@ pc_close(thread_t *ptr) void pc_reset_hard_close(void) { - suppress_overscan = 0; - nvr_save(); - machine_close(); - mouse_close(); cdrom_close(); @@ -1010,11 +1004,17 @@ void pc_reset_hard_init(void) { /* Reset the general machine support modules. */ - io_init(); + io_reset(); timer_reset(); - device_init(); + device_reset(); - /* Reset the ports [before machine!] so they can be configured. */ + /* + * Reset the portsi. + * + * We do this before the machine is initialized, so its + * BIOS can override port settings on SIO chips etc. + */ + game_reset(); parallel_reset(); serial_reset(); @@ -1027,18 +1027,8 @@ pc_reset_hard_init(void) */ machine_reset(); - /* - * 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 ! - */ -#if 1 - /* FIXME: move elsewhere? */ - shadowbios = 0; -#endif + /* Reset the video system. */ + video_reset(); /* Reset any ISA memory cards. */ isamem_reset(); @@ -1067,10 +1057,6 @@ pc_reset_hard_init(void) /* Reset and reconfigure the Network Card layer. */ network_reset(); - //FIXME: this needs to be re-done. */ - if (joystick_type != JOYSTICK_NONE) - game_update_joystick_type(); - if (config_changed) { ui_sb_reset(); @@ -1086,11 +1072,22 @@ pc_reset_hard_init(void) /* Needs the status bar initialized. */ ui_mouse_capture(-1); + /* + * At this point, all configurable hardware has + * been initialized, and we are about ready to + * start executing instructions. + */ +#ifdef _DEBUG + device_dump(); +#endif + /* Reset the CPU module. */ - resetx86(); + cpu_reset(1); dma_reset(); pic_reset(); - pc_set_speed(); + + //FIXME: already done in machine_reset() - why needed here?? + pc_set_speed(1); } @@ -1112,8 +1109,6 @@ pc_reset(int hard) nvr_save(); - machine_close(); - config_save(); if (hard) @@ -1149,6 +1144,7 @@ pc_thread(void *param) title_update = 1; old_time = plat_get_ticks(); done = drawits = frm = 0; + while (! *quitp) { /* See if it is time to run a frame of code. */ new_time = plat_get_ticks(); @@ -1163,8 +1159,7 @@ pc_thread(void *param) /* Run a block of code. */ plat_startblit(); - clockrate = machine_speed(1); -//INFO("PC: clockrate=%lu, cpuspeed=%lu\n", clockrate, cpuspeed); + clockrate = machine_get_speed(1); if (is386) { #ifdef USE_DYNAREC @@ -1173,7 +1168,7 @@ pc_thread(void *param) else #endif exec386(clockrate/100); - } else if (machine_type() >= CPU_286) { + } else if (cpu_get_type() >= CPU_286) { exec386(clockrate/100); } else { execx86(clockrate/100); @@ -1188,8 +1183,8 @@ pc_thread(void *param) if (title_update) { swprintf(temp, sizeof_w(temp), L"%s %s - %i%% - %s - %s", - EMU_NAME,emu_version,fps,machine_getname(), - machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name); + EMU_NAME, emu_version, fps, + machine_get_name(), cpu_get_name()); ui_window_title(temp); title_update = 0; @@ -1300,6 +1295,7 @@ set_screen_size(int x, int y) /* Account for possible overscan. */ vid = video_type(); +INFO("SetScreenSize(%d,%d) type=%d\n", x, y, vid); if ((vid == VID_TYPE_CGA) && (temp_overscan_y == 16)) { /* CGA */ dy = (((dx - dtx) / 4.0) * 3.0) + dty; diff --git a/src/random.c b/src/random.c index 09b75b7..023f73a 100644 --- a/src/random.c +++ b/src/random.c @@ -9,10 +9,12 @@ * A better random number generation, used for floppy weak bits * and network MAC address generation. * - * Version: @(#)random.c 1.0.2 2018/10/05 + * Version: @(#)random.c 1.0.3 2019/03/21 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -40,6 +42,10 @@ #include "random.h" +#define ROTATE_LEFT rotl32c +#define ROTATE_RIGHT rotr32c + + static uint32_t preconst = 0x6ed9eba1; @@ -65,38 +71,6 @@ rotr32c (uint32_t x, uint32_t n) } -#define ROTATE_LEFT rotl32c -#define ROTATE_RIGHT rotr32c - - -#if 0 /* deprecated */ -static __inline unsigned long long -rdtsc(void) -{ - unsigned hi, lo; - -#ifdef _MSC_VER - __asm { - rdtsc - mov hi, edx ; EDX:EAX is already standard return!! - mov lo, eax - } -#else - __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); -#endif - - return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); -} - - -static uint32_t -RDTSC(void) -{ - return (uint32_t) (rdtsc()); -} -#endif /* deprecated */ - - static void random_twist(uint32_t *val) { @@ -121,11 +95,7 @@ random_generate(void) void random_init(void) { -#if 0 /* deprecated */ - uint32_t seed = RDTSC(); -#else uint32_t seed = (uint32_t)plat_timer_read(); -#endif srand(seed); } diff --git a/src/rom.c b/src/rom.c index a9c883f..49dedf0 100644 --- a/src/rom.c +++ b/src/rom.c @@ -8,13 +8,13 @@ * * Handling of ROM image files. * - * Version: @(#)rom.c 1.0.15 2018/10/05 + * Version: @(#)rom.c 1.0.18 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -42,11 +42,108 @@ #include #include #include "emu.h" +#include "cpu/cpu.h" #include "mem.h" #include "rom.h" #include "plat.h" +mem_map_t bios_mapping[8], + bios_high_mapping[8]; +uint8_t *bios = NULL; +uint32_t biosmask; +int shadowbios = 0, + shadowbios_write; + + +/* Read one byte from the BIOS ROM area. */ +uint8_t +rom_bios_read(uint32_t addr, void *priv) +{ + return bios[addr & biosmask]; +} + + +/* Read one word from the BIOS ROM area. */ +uint16_t +rom_bios_readw(uint32_t addr, void *priv) +{ + return *(uint16_t *)&bios[addr & biosmask]; +} + + +/* Read one doubleword from the BIOS ROM area. */ +uint32_t +rom_bios_readl(uint32_t addr, void *priv) +{ + return *(uint32_t *)&bios[addr & biosmask]; +} + + +/* Read a byte from some area in ROM. */ +uint8_t +rom_read(uint32_t addr, void *priv) +{ + rom_t *ptr = (rom_t *)priv; + +#ifdef ROM_TRACE + if (ptr->mapping.base == ROM_TRACE) + DEBUG("ROM: read byte from BIOS at %06lX\n", addr); +#endif + + return(ptr->rom[addr & ptr->mask]); +} + + +/* Read a word from some area in ROM. */ +uint16_t +rom_readw(uint32_t addr, void *priv) +{ + rom_t *ptr = (rom_t *)priv; + +#ifdef ROM_TRACE + if (ptr->mapping.base == ROM_TRACE) + DEBUG("ROM: read word from BIOS at %06lX\n", addr); +#endif + + return(*(uint16_t *)&ptr->rom[addr & ptr->mask]); +} + + +/* Read a double-word from some area in ROM. */ +uint32_t +rom_readl(uint32_t addr, void *priv) +{ + rom_t *ptr = (rom_t *)priv; + +#ifdef ROM_TRACE + if (ptr->mapping.base == ROM_TRACE) + DEBUG("ROM: read long from BIOS at %06lX\n", addr); +#endif + + return(*(uint32_t *)&ptr->rom[addr & ptr->mask]); +} + + +/* (Re-)allocate ROM area and reset size mask. */ +void +rom_reset(void) +{ + uint32_t c; + + if (bios != NULL) + free(bios); + + /* Allocate 128KB of BIOS space. */ + c = 1024UL * 128; + bios = (uint8_t *)mem_alloc(c); + memset(bios, 0xff, c); + + /* Set mask for a 64K (or smaller) ROM. */ + biosmask = 0x00ffff; +} + + /* Return the base path for ROM images. */ wchar_t * rom_path(const wchar_t *str) @@ -70,11 +167,11 @@ rom_path(const wchar_t *str) int rom_present(const wchar_t *fn) { - FILE *f; + FILE *fp; - f = plat_fopen(rom_path(fn), L"rb"); - if (f != NULL) { - (void)fclose(f); + fp = plat_fopen(rom_path(fn), L"rb"); + if (fp != NULL) { + (void)fclose(fp); return(1); } @@ -84,48 +181,56 @@ rom_present(const wchar_t *fn) } -/* Read a byte from some area in ROM. */ -uint8_t -rom_read(uint32_t addr, void *priv) +/* Map in the E0000 ROM segments. */ +void +rom_add_upper_bios(void) { - rom_t *ptr = (rom_t *)priv; + uint32_t base = 0x0e0000; + uint32_t size = 0x4000; + int i; -#ifdef ROM_TRACE - if (ptr->mapping.base==ROM_TRACE) - DEBUG("ROM: read byte from BIOS at %06lX\n", addr); -#endif - - return(ptr->rom[addr & ptr->mask]); + for (i = 0; i < 4; i++) { + mem_map_add(&bios_mapping[i], base, size, + rom_bios_read,rom_bios_readw,rom_bios_readl, + mem_write_null,mem_write_nullw,mem_write_nulll, + bios + ((0x10000 + (size * i)) & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + base += size; + } } -/* Read a word from some area in ROM. */ -uint16_t -rom_readw(uint32_t addr, void *priv) +/* Map in the BIOS ROM segments. */ +void +rom_add_bios(void) { - rom_t *ptr = (rom_t *)priv; + uint32_t hibase = (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000; + uint32_t lobase = 0x0f0000; + uint32_t size = 0x4000; + int i; -#ifdef ROM_TRACE - if (ptr->mapping.base==ROM_TRACE) - DEBUG("ROM: read word from BIOS at %06lX\n", addr); -#endif + /* Add E0000-EFFFF mappings for AT+ systems. */ + if (AT) + rom_add_upper_bios(); - return(*(uint16_t *)&ptr->rom[addr & ptr->mask]); -} + /* Add F0000-FFFFF mappings. */ + for (i = 0; i < 4; i++) { + mem_map_add(&bios_mapping[i + 4], lobase, size, + rom_bios_read,rom_bios_readw,rom_bios_readl, + mem_write_null,mem_write_nullw,mem_write_nulll, + bios + ((0x10000 + (size * i)) & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + lobase += size; + } - -/* Read a double-word from some area in ROM. */ -uint32_t -rom_readl(uint32_t addr, void *priv) -{ - rom_t *ptr = (rom_t *)priv; - -#ifdef ROM_TRACE - if (ptr->mapping.base==ROM_TRACE) - DEBUG("ROM: read long from BIOS at %06lX\n", addr); -#endif - - return(*(uint32_t *)&ptr->rom[addr & ptr->mask]); + /* Add FE0000-FFFFFF mappings for 286+ systems. */ + for (i = 0; i < 8; i++) { + mem_map_add(&bios_high_mapping[i], hibase, size, + rom_bios_read,rom_bios_readw,rom_bios_readl, + mem_write_null,mem_write_nullw,mem_write_nulll, + bios + ((size * i) & biosmask), MEM_MAPPING_ROM, 0); + hibase += size; + } } @@ -133,10 +238,10 @@ rom_readl(uint32_t addr, void *priv) int rom_load_linear(const wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { - FILE *f; + FILE *fp; - f = plat_fopen(rom_path(fn), L"rb"); - if (f == NULL) { + fp = plat_fopen(rom_path(fn), L"rb"); + if (fp == NULL) { ERRLOG("ROM: image '%ls' not found\n", fn); return(0); } @@ -147,9 +252,9 @@ rom_load_linear(const wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) else addr &= 0x03ffff; - (void)fseek(f, off, SEEK_SET); - (void)fread(ptr+addr, sz, 1, f); - (void)fclose(f); + (void)fseek(fp, off, SEEK_SET); + (void)fread(ptr + addr, sz, 1, fp); + (void)fclose(fp); return(1); } @@ -180,9 +285,9 @@ rom_load_interleaved(const wchar_t *fnl, const wchar_t *fnh, uint32_t addr, int (void)fseek(fl, off, SEEK_SET); (void)fseek(fh, off, SEEK_SET); - for (c=0; c * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -76,13 +76,32 @@ typedef struct { } romdef_t; -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 uint8_t *bios; +extern uint32_t biosmask; + +extern mem_map_t bios_mapping[8], + bios_high_mapping[8]; + +extern int shadowbios, + shadowbios_write; + + +extern uint8_t rom_bios_read(uint32_t addr, void *priv); +extern uint16_t rom_bios_readw(uint32_t addr, void *priv); +extern uint32_t rom_bios_readl(uint32_t addr, void *priv); + +extern uint8_t rom_read(uint32_t addr, void *priv); +extern uint16_t rom_readw(uint32_t addr, void *priv); +extern uint32_t rom_readl(uint32_t addr, void *priv); + +extern void rom_reset(void); extern wchar_t *rom_path(const wchar_t *fn); extern int rom_present(const wchar_t *fn); +extern void rom_add_upper_bios(void); +extern void rom_add_bios(void); + extern int rom_load_linear(const wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr); extern int rom_load_interleaved(const wchar_t *fnl, const wchar_t *fnh, diff --git a/src/rom_load.c b/src/rom_load.c index 9582a24..f035fef 100644 --- a/src/rom_load.c +++ b/src/rom_load.c @@ -17,11 +17,11 @@ * or to use a generic handler, and then pass it a pointer * to a command table. For now, we don't. * - * Version: @(#)rom_load.c 1.0.13 2018/10/05 + * Version: @(#)rom_load.c 1.0.14 2019/03/17 * * Author: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -72,8 +72,10 @@ /* Process a single (logical) command line. */ static int -process(int ln, int argc, char **argv, romdef_t *r) +process(int ln, int argc, char **argv, romdef_t *r, const wchar_t *path) { + wchar_t temp[1024]; + again: if (! strcmp(argv[0], "size")) { /* Total size of image. */ @@ -88,7 +90,7 @@ again: else if (! strcmp(argv[1], "interleaved")) r->mode = 1; else { - ERRLOG("ROM: invalid mode '%s' on line %d.\n", argv[1], ln); + ERRLOG("ROM: invalid mode '%s' on line %i.\n", argv[1], ln); return(0); } } else if (! strcmp(argv[0], "optional")) { @@ -106,8 +108,8 @@ again: goto again; } else if (! strcmp(argv[0], "file")) { /* Specify the image filename and/or additional parameters. */ - mbstowcs(r->files[r->nfiles].path, argv[1], - sizeof_w(r->files[r->nfiles].path)); + mbstowcs(temp, argv[1], sizeof_w(temp)); + plat_append_filename(r->files[r->nfiles].path, path, temp); r->files[r->nfiles].skip = 0; r->files[r->nfiles].offset = r->offset; r->files[r->nfiles].size = r->total; @@ -136,7 +138,7 @@ again: mbstowcs(r->vidfn, argv[1], sizeof_w(r->vidfn)); sscanf(argv[2], "%i", &r->vidsz); } else { - ERRLOG("ROM: invalid command '%s' on line %d.\n", argv[0], ln); + ERRLOG("ROM: invalid command '%s' on line %i.\n", argv[0], ln); return(0); } @@ -146,7 +148,7 @@ again: /* Parse a script file, and call the command handler for each command. */ static int -parser(FILE *fp, romdef_t *r) +parser(FILE *fp, romdef_t *r, const wchar_t *path) { char line[1024]; char *args[MAX_ARGS]; @@ -323,7 +325,7 @@ parser(FILE *fp, romdef_t *r) *sp = '\0'; if (feof(fp)) break; if (ferror(fp)) { - ERRLOG("ROM: Read Error on line '%s'\n", l); + ERRLOG("ROM: Read Error on line %i\n", l); return(0); } l++; @@ -332,7 +334,7 @@ parser(FILE *fp, romdef_t *r) if (*args[0] == '\0') continue; /* Process this line. */ - if (! process(l, a, args, r)) return(0); + if (! process(l, a, args, r, path)) return(0); } return(1); @@ -349,127 +351,112 @@ rom_load_bios(romdef_t *r, const wchar_t *fn, int test_only) FILE *fp; int c, i; + /* Clear ROM definition and default to a 64K ROM BIOS image. */ + memset(r, 0x00, sizeof(romdef_t)); + r->total = 65536; + r->fontnum = -1; + /* Generate the BIOS pathname. */ wcscpy(path, fn); - plat_append_slash(path); /* Generate the full script pathname. */ - wcscpy(script, path); - wcscat(script, BIOS_FILE); + plat_append_filename(script, path, BIOS_FILE); pc_path(script, sizeof_w(script), NULL); - if (! test_only) { + if (! test_only) INFO("ROM: loading script '%ls'\n", rom_path(script)); - /* If not done yet, allocate a 128KB buffer for the BIOS ROM. */ - if (rom == NULL) - rom = (uint8_t *)mem_alloc(131072); - memset(rom, 0xff, 131072); - - /* Default to a 64K ROM BIOS image. */ - biosmask = 0xffff; - } - /* Open the script file. */ if ((fp = plat_fopen(rom_path(script), L"rb")) == NULL) { ERRLOG("ROM: unable to open '%ls'\n", rom_path(script)); return(0); } - /* Clear ROM definition. */ - memset(r, 0x00, sizeof(romdef_t)); - r->fontnum = -1; - /* Parse and process the file. */ - i = parser(fp, r); - + i = parser(fp, r, path); (void)fclose(fp); - - /* Show the resulting data. */ - if (! test_only) { - INFO("Size : %lu\n", r->total); - INFO("Offset : 0x%06lx (%lu)\n", r->offset, r->offset); - INFO("Mode : %s\n", (r->mode == 1)?"interleaved":"linear"); - INFO("Files : %d\n", r->nfiles); - for (c = 0; c < r->nfiles; c++) { - INFO("%c[%d] : '%ls', %i, 0x%06lx, %i\n", - (r->files[c].offset==0xffffffff)?'*':' ', c+1, - r->files[c].path, r->files[c].skip, - r->files[c].offset, r->files[c].size); - } - if (r->fontnum != -1) - INFO("Font : %i, '%ls'\n", r->fontnum, r->fontfn); - if (r->vidsz != 0) - INFO("VideoBIOS: '%ls', %i\n", r->vidfn, r->vidsz); - - /* Actually perform the work. */ - switch(r->mode) { - case 0: /* linear file(s) */ - /* We loop on all files. */ - for (c = 0; c < r->nfiles; c++) { - /* If this is a no-load file, skip. */ - if (r->files[c].offset == 0xffffffff) - continue; - - wcscpy(script, path); - wcscat(script, r->files[c].path); - pc_path(script, sizeof_w(script), NULL); - - i = rom_load_linear(script, - r->files[c].offset, - r->files[c].size, - r->files[c].skip, rom); - if (i != 1) break; - } - if (r->total >= 0x010000) - biosmask = (r->total - 1); - break; - - case 1: /* interleaved file(s) */ - /* We loop on all files. */ - for (c = 0; c < r->nfiles / 2; c += 2) { - /* If this is a no-load file, skip. */ - if (r->files[c].offset == 0xffffffff) - continue; - - wcscpy(script, path); - wcscat(script, r->files[c].path); - pc_path(script, sizeof_w(script), NULL); - wcscpy(temp, path); - wcscat(temp, r->files[c+1].path); - pc_path(temp, sizeof_w(temp), NULL); - - i = rom_load_interleaved(script, temp, - r->files[c].offset, - r->files[c].size, - r->files[c].skip, rom); - if (i != 1) break; - } - if (r->total >= 0x010000) - biosmask = (r->total - 1); - break; - } - - /* Create a full pathname for the video font file. */ - if (r->fontnum != -1) { - wcscpy(temp, path); - wcscat(temp, r->fontfn); - pc_path(r->fontfn, sizeof_w(r->fontfn), temp); - } - - /* Create a full pathname for the video BIOS file. */ - if (r->vidsz != 0) { - wcscpy(temp, path); - wcscat(temp, r->vidfn); - pc_path(r->vidfn, sizeof_w(r->vidfn), temp); - } - - INFO("ROM: status %d, tot %u, mask 0x%06lx\n", - i, r->total, biosmask); + if (i == 0) { + ERRLOG("ROM: error in script '%ls'\n", script); + return(0); } - if (! i) - ERRLOG("ROM: error in script '%ls'\n", script); + /* All done if just testing for presence. */ + if (test_only) + return(1); - return(i); + /* Show the resulting data. */ + INFO("Size : %lu\n", r->total); + INFO("Offset : 0x%06lx (%lu)\n", r->offset, r->offset); + INFO("Mode : %s\n", (r->mode == 1)?"interleaved":"linear"); + INFO("Files : %i\n", r->nfiles); + for (c = 0; c < r->nfiles; c++) { + INFO("%c[%i] : '%ls', %i, 0x%06lx, %i\n", + (r->files[c].offset==0xffffffff)?'*':' ', c+1, + r->files[c].path, r->files[c].skip, + r->files[c].offset, r->files[c].size); + } + if (r->fontnum != -1) + INFO("Font : %i, '%ls'\n", r->fontnum, r->fontfn); + if (r->vidsz != 0) + INFO("VideoBIOS: '%ls', %i\n", r->vidfn, r->vidsz); + + /* Actually perform the work. */ + switch(r->mode) { + case 0: /* linear file(s) */ + /* We loop on all files. */ + for (c = 0; c < r->nfiles; c++) { + /* If this is a no-load file, skip. */ + if (r->files[c].offset == 0xffffffff) + continue; + + pc_path(script, sizeof_w(script), r->files[c].path); + + i = rom_load_linear(script, + r->files[c].offset, + r->files[c].size, + r->files[c].skip, bios); + if (i != 1) break; + } + break; + + case 1: /* interleaved file(s) */ + /* We loop on all files. */ + for (c = 0; c < r->nfiles / 2; c += 2) { + /* If this is a no-load file, skip. */ + if (r->files[c].offset == 0xffffffff) + continue; + + pc_path(script, sizeof_w(script), r->files[c].path); + pc_path(temp, sizeof_w(temp), r->files[c+1].path); + + i = rom_load_interleaved(script, temp, + r->files[c].offset, + r->files[c].size, + r->files[c].skip, bios); + if (i != 1) break; + } + break; + } + + /* Update BIOS mask. */ + if (r->total >= 0x10000) + biosmask = (r->total - 1); + else + biosmask = 0x00ffff; + + /* Create a full pathname for the video font file. */ + if (r->fontnum != -1) { + plat_append_filename(temp, path, r->fontfn); + pc_path(r->fontfn, sizeof_w(r->fontfn), temp); + } + + /* Create a full pathname for the video BIOS file. */ + if (r->vidsz != 0) { + plat_append_filename(temp, path, r->vidfn); + pc_path(r->vidfn, sizeof_w(r->vidfn), temp); + } + + INFO("ROM: tot %lu, mask 0x%06lx\n", r->total, biosmask); + + return(1); } diff --git a/src/ui/lang/VARCem-KZ.str b/src/ui/lang/VARCem-KZ.str index 9f7c9c272feff5ef76f4a2eec20551de7d00459f..749e0b6e8af0d3a04ba23064301a5c8b28a16d07 100644 GIT binary patch literal 30088 zcmezWPoF`HftP`cL4iSwL4hHR!I2?|!I>eIA(w%ZA&eoDp@^Y`p_Cz!A%{T$ESJoX z!H~$1%8<{H!;sIA&XCEF43%|e$Y;o9C}1dMC}ButC}L1xaAojiC}qfDNMtBs$Y&^G z(1Y8=$-v3r$dJdN0JaHPjRHeHLmGnug9bw`Lq0<>LkU9;LnVVIg91YZg9U>bgDyi7 zLn1>lLn=cGg91YUgENByLoq`oSS85S#S97zi41vQ*%XFUhBB}VQyGdGbWm(BWhiFI zWXNMkXHZ}$VaQ-eWl&)7WC&((WYA%7g|osKd>EVZsSK&$a57}D zWUyc`L~;R0#FD`jDO8bd2w})z$YcP8MjAsVLk`$~5I)FeP^`j28s>ZCxCezS$n{wa zsSL>sB{=K|W+-7Og8Kjz+910?ekx(eWXNa8gW3;@dj$q125*K$hAM_chHQoma10~! zK`{-AH%$g51_f}M0mTg{<)t&EVzD2TRzYC}ibar3Rt%gB4h$L$$_$z)saTi6n<0up z51c-V7&sXW8T1$o81xv-7&sY>7z`Ldp{UPbz+lXv&tSx022Uffumq)gP>Rj~r{H1+ zkUfqJMc`Ce1omGPLn1>uLn1>8LpC@pbQlyEY#0)e)aZeIjjYCjA(tT$94~qdMGU13 zc5r(^sl$z-2%5hA81xtv7|OtDMS;N^oLdUODFR{(D9n=?${8{lsu&y?Dj55ON?>LB0f)DJcw@44`xhDz{*60)-~XbWkY(3g04zT!u`B5^zZdDrXcJ3c$G; zRGNUo93%#^6I8On$`54wK`zVzmyn>i0i|RGaEyS;C6Kv@+yS#SmjRUDt>EbZ*)&j^ zRbapurl5QdDK|005R?)?ZdPE(1&22%96;%-1e^jvWiZGmAfJOu8c>LUWRdL$#SbVh zk{I$C%D^#`$B@qeQVEJDP}qS?0L3;a=YnXE9T4|`Y{%wnkQglFATf#>UYPcS;;on= z8C*7GGJwJhxkf=&Zv@UYgu)Aw;;^SI^ss`&ehNb=G-ZPP3ktDB23VLN+YbpZkk8R` znF0fP$U(vY6lTa_2P>O#r5aFdKtd3rKNX&CK=~VDKejZ8EesXFc?+Zm=BpHje1>F( zQg9gOF@VwuD6T=JEX-bga1I2y5~8OFi~XPy4$>0H1h)`CX%rHU$hioVKR{-{{Gq@A zaU*8AfxVF- z1^EEPf|Wj?(hC%#m}w0Xu8{Nza{xW2f)fr?Dm7oG*EbzgXgAaoz)U66oKLs&>ObG#t z2Qz?5P*CgBkHMM2har@~g~5}-kHH-*4sjF6EI$T+h7fq#QvjRl%izfn0yP`ta*#=& za0G<}y4{e_M70^@Qa1(#244nOaJ%0F>MlnHCk9Wj4IyA3f?Nv8h`7Q+9PXpNribaTv zAZat00b~xu22gwkgMAK5ub}t=<(D9aAcjze0I)0l8T`QgOHld^AH;T0 z$_J%aNWKTD2Za|XPedZ6dq}$L1LZbY}2i zfTSQ;{y@}3`rx<(xeqiZ0xAh4p_yHM<75 z?_|JW01hu*uuc99ps)soD9D|V(l;1fDuU9XB6!>dVzV;1pi9cW(_mo7(e9Dvev5CbQJ5(EA|s}k7nxXc2TM4*z{2W%3kl>i!p z0rh?f_iXW-><2EXT*2ldk3Zno1u0uVB{Ilo)E=dR*bPbtAPh?jpfR0da8ExK+~%)f z0JZTzV_TqB4M-L=W@W@+$N-9eJ#Y%pV!$7>Fx4Pm%wjQMabhuLf!K~KCLlTt!Qmyw zV#ngg;>hC7V$Pz#FdM4hktK{MGmOAy%wpNd;=tm~V$I^sV#8v>;>|LfMS;PJ#gxU7 z#fl}2#TJZ7H{BR)x;)ezQx*pnCzdc4gxf$N3&N1l4MrNj1C0n4fm^De^aTl1&^Qff z%my?HNH|O(szG52vfqKlmc^9CiN%0rHkfpP`*J;t30MZ?PY-a|JFqA)n6a#9u>$j) zSriy-Sk|-HKtn=-!IZ@Y>?1`6La_vL10UxXCQu;M5BW1p^jCa4MY4V!&bx4keH+ zjs#OO$OaQ|TElOH3Dj0c63sRRo2?4&(-8_2{Gkj=`{pbrEMY8*q2W6j96Jsy)+`3# zbOrLaA&WDM4LIz*S!`JhSQHpy81lgR5tM#FW`J^M7&K;F!J!3;DQ~c;vsoaqX9iB! zVc;AMNoA%iRxFMzpnM3))8;H7a}^k@z~+P4AU{G>P#8kB2MO9NOR6w<>6*#znZ7co>a5YB}lGaf!KID`I8H%jEU0uv z{yJz^|TL*0)rikBa1Cq1Vmc0*fS_F z$g-G1YX?vrfm(_ifMX8kc2Ew*-AVw(g(=>oVhwgRBn%? zP@X_egQ#^8tiFYmOZa_j4lb!d{WT{BP&$XCU{H<+nU7vBLi`Rf7vv8R#$VonN*>HI z&V-~g4x$=V#>ul7un-^KptJxVd6_yPz*pyS0xs277rFsDQycbWkDfe#p2B3z~aba z#{#OoHbUEOpgg;t#RJ;ra02VI0=F3;`2yr?h>t;i2uNF7vVclAP>%-G zw*a}rjlqIJo5792kiiICCnxzUux99jZfu|R4QGZs+$0Aw=A9gy4sNm-D%1GNi5V?RL* zJ`CCnpfSD>25kn=C@W~>1~i)C&k)W48Y2Of;>alv5~H9T1;UW>%@@2XAQ`-lfcQ}j zQeYH=sI`_`bV8gEs?cu1$#n#Ddt2EAN0t z5+NgOkP#F?aC-pM+jaoA44nz|b0WdxqY&F9SZ)$f4I0OVs0ED>%qE~3GU5mtJ9TFO zjnG5JVsN*r@cYyWJUbH(9Ggp}7Y{n#wvw%VbG~Nkv5iwx`8rKAk&IK`m#-|{0CdCp4PJy6055j`fZngx% z7c?6HT2wP)dJSdpV*rigJA?Cx5(B6dux7Dm0hRZlwi&1og5O5my3JTX zV+Dj<0GhP|&8mQ6T#02pIOg!%2+9GVkOjp!Xifv9Qw7>a1?5ywEeom7tO)dkAhQwf z44~N&(0m}sBzYDG7CRPW7EtTi5j3_&zzoRD1tb?MvDmTLgIjK(mJ}h|K_lFtnF&yO zhooFFSbamlPSA`h#6}Q{kUgMzN?59ZunFk^<*G1-cyOM=6~YcI8(C(vfO;KH;E@{8 z_!umofl>~rzJ`sVWiptvWHKyf0nwnABmUkTXkO8sA)Wy=vj&=P2m$9rSSu3L9)^tp zK+Ff_B#LZnCxNJ`L2?Ex=Fm|Ed+^u}NR0uwg$Qa7f?A%izB;TGh+b2J zTIZmaG^F>3yOobW4TI*rL8U}IIPHPvNqjjk!M9f<3gZzKB#Ab zTBoAd8KBuT(3*yL28i8|kP=`qVsQfZ5kS3T2Nsx*2TL$ zK`njI7%PYd%^N_*ra?UjP=6LQnhP3B0ga%5S^?P0AM}`j^x;4=RWV+K(90V`YF z8T=SR89;O8pp|%_5mrzrf!0oxG9*FgA3-z9pf%SZ6`)nnp!8+LpvwU2cmVtb?m<7~B1eIZ+-XCaI#hS%}#SJ{NWzJ&3;tw8^c7T>; zmf(8Z13VfHs(l^cDnLCXP?+f9s9Dhc4(UD0u-pWXK!M!p1fFRD*#w%^2CW0|1GgRZ z7)lr_7(lBCVPzDky$>460r|mzWifcx3zDlrc@aGY!{$yQ?Fdkx$&(=pyn+KXCIDK~ zBftXbnL}FO5R=eNL3O_&c=a_zKa5mj5MTj?0;rb@>Xn1iFDSf0DF%{yL3uWe1vDxG zD&IkA1yqkA+YQN!AW`hO6XZX9WesQ*HfUBFw2};z8bCST2)r&F6tl4TGKdKp4518p z;8mch;1%+qHE!i7bCrZ`1C7Xo)~JEfDQt#Z16X2~QfjhRC01W^CQ13cpf(F=-kkk3FE5)z<(2WGhq zT1Qw8UTpwcr3YGh4hvCpj1WanEwD5PYI%XyP53gngWDLO`VcagV*#EEw1>9GKsg`O zmIcjBg7Oupl}SuGGzYI;S7HE}3rc6RSzx+BPr@D7Lf04K=u(8ZsrV-@l((W zEzpbzsGSNMmmsc|FlVp;`&I;;yFsg!0~maXwA&JkP6Y--236=tkv|J))&?|QimNw^ zno}(p3~-pJ$6!i!CPHS%Ef_$(3s5aXx`~i<23k*V!2mLc_;7)wv?vBoh5%4529F;SQ@Vk6G=bW^ zFrA>9%mA7z2$kN!;5`(ewd$Z97qC%1$haP{^%7`R9%y|LX#H(4xD)}6=Yz@~NP7h~ zH-_CWusXn)0Wv}b@`)6S9g7W%J&O;EAGEbYj9yq-V*#E&1kF5H5*TTM*a=AkqAajg zCZK*8WPSwHMgg_0L2W)_TmXrCM7>Om9!RW%Ml3)fW>1uhA!Um^xL*Ql4}w~FpjsEy z&jZy(Y7C$@FKDeMu6%$R>X0%A)L#ItTmhwfXBH1|{~Tm8F}{G5KA_n&kb6KaW>C8h zxvnL~6i8Vl0jh&paM$^e5e+l&7!{;f0V0VpA5vxsuz>o#wk#mmfmon6GH6C07TX~I zJ3!-soc!aD3p5%BT6YFo zWd&=u5$7UMIR+|Eh%19Zu>>hYl)-cO-Yk%`3~C=bvRJU#vbciBBq6h%&P0s`fXsxH zFK*Cy0Iht$Jsymj20*$&?iT^u4qEeM!2+6%1f^Qgx)@NK(+XNvTCiBN_(R7kym8J8 zqni&YeY}aP^+B$Iq{*A$)g1QVReqpx2Rjx-j~9DBM7I}`HbGO;m5L4B?e z24@CX=|xU11g&ue?dQpd=Rm@JEmT*6)Pq7_5Zo&QjS~=;>R>&pFot}Fdyato+80SZYI0;Z6Yf`h?(;X&gD zka!052nem|MUH2PdXVc7EfP@O2`V{2r3h$+u>nz~7|0|@$q3p#1)87JWk78q5flF) zQy^s_s6+>?i~{W#0M$;q;NFfQG*6(95}^AD(#rB z_RzLG%rtVsEdacW7PMazmM1`^H1X{!69$laP?*U<>nuhOo2O9EP9?Sgiai2{Q$g9!tu<|8GwfYgIh3uvz;XqObIwF4S` z1oag_>)=4WBv9!9OVjw%4XpO`0Pmv(^*>PiTcnr-sY%zdfc9a4_Dg_v#DQkzh)H#@ z8dQnpC3v3+XwDe4whA&CL7XKomSOCD0{Z%|1E8I=XCq5zfbpqUZW@o!Myin#t1 z$TUa@fJVVVqwAn`tPp?VOSK?o)rF=2F=%jN;~Z1cc6GDX5JFyHb{!WZVt$`>shS9d$?>_G{Nhsi8U7z z!=TYCP;8hH6|$hY0+6pjJDNdlS7OqIA+#++Y>5c+Gc2~989+4!akfC>9I^%P*_36i$H7GK=}oKsRnBIfn53m-2YHuK$Ja% z(+2S_A;uk$(hKHGP|F51Ljv00puhkUjR4L2z(<=vGZ>(C9-y)XG&cuoFM?V^khN~0 zHaRHPLH!p{iwHD>4KfX~ss%I)1_~$8oHocDkX@ja6rhzBkUR@&Iaq_&QiImNgGLOA z@d2c^#9u0aT!RQVknM;S>KP0v4E7Ax;MMA&6RBYAG6s+gXhk|H>(&XyJESClwRZ@` zHf${bXdVW(Qb~gWH1h1g0$LY>NQH>?Q1&cg;1$83F=12icmrr3xGBqG7Gsu7@Xj|- zoWNFGfIKAV<2r`OBNe&Ytk5;mqGIxkXjRe zN`Uo^ofrbZWe%vMh3)PouHG_bfVE0t?jg=zNRG#6FFEM}bWR&+Uk2!uL(nQW(5YA0 z`n#qi_IDxbLE$b39<2e5>_S#ff<{O{b1$GWh-bY0tdES%cf_O~Sg#l~9_h#sz~D(#YZr9lDJTYEBNoKj z1Zl6Mw?k3WCTNu|>dHAMa9hK| zKw2#t46fkaa!xF|44`@plqwNxx)c~x8Il>S;Il{Qv4mLXfRsIm z*(=a`NzgtLV)aAndeCe+q>TZ}m7wu2(E379djirn1JwHNVMzT7Y7K#Q z^%*eO!`n=TNNmX3GDuqrvhEAQ2CeW;gSN3iJIM2(>|};QxH%~d#SGa{@ic}Uh5{%X z)C$XmvXR?oSq#PC(}^KAlrW?)7(i8NF{B~2=_(jf7}CHy3qhwWfc9O3QVVE&5ixoU zYVU$l45;-Ao5{xIcaR%Wpf+K111OA?z$cZUwu%XvOKO->D;y!=0|`Y~$btMI!(zZ< z%wo%80bX+e8P5f+-Up>;&`KCkX@o0`K;fSW4s$`W^h44M$Q6jRh`fdz(RxSTGm1a| zKuT4FdAQsTu^SQ|xY8sj4Z!*d$YDlKyc1&w$i8%FnnSivfdMsqAv0t)EV>MaEE~aR z2+RhrTEZ4rpi^ledvqZ_28A{;Wdx)qLA96IbU~U;kopFs2eh`*7kv5+Vx9-o3Ivs) zppp}W@x?x94JD}bbY^g2&;{>q1+7U_Wq_5Gpz@KlvJ!NL7tBO`@OgG1lR-TzP*~${ z3uutg8Zd&c2Ss%`uCxm}4K^Q|PC#e>rb6=|Xp921Hyt$(fm%tR(p-x{6RZxxCN3R- z&c^}yA2E*)n)Lvk{s4*#5XKiDu(2Ziy>?K|g+GP}*#jDp1-TN^QdR|@5Dzkul9-3} z9wBCeLJJgbpd1P-5vstaA47VF$n8Kg@c9m)m4TqsH$byTpfM59=nrUw1e9*D#Vex3 zLXAC`&BT^~u>LE(+)cPF0j-w@#SUV29+V;>?H0ni&7rHd5h)N|Hz;+0F!I<2WDp~Z>2i-N0o`eRAHw&Vz4@xT_j4Qo>*6*by;*3$r;kL$`1 z4ql0_$l?v2;RemKgUSfdzIMXS|4ZMpGHaiYV$B^_3I<1hHRAC5R zAp+__fyUfH{XtNR1+;zzRKG*U;6Z*dV*#D85XKV2P{M$jh612xdV)>^CeB_+YLo+? zxCc9z1=N$=2tGLxbOsNoy{^FE$lwD$dmM8e7brhMc8e01X6zV1`>8-XK0#|hL8oGX zRwh7F5~zKGKP922UyyoG8KMB*?FktV2Gu1HzZ37CaPX}Gp!J}jR2>Yx1qd{D=LTLe z4!Q9MRIY;31gO>~#g!oSAXg%vnFBgC2{alHDmOqm0MvtrxEeFZqWT%M7XxG(Xhg@9 zp#o<~hOP^ejtxoB0V(}JyMait2a=+U;Pwz73vS^1l|XIKWN=vsN+Td&fbJat-6sNC zxer>G2wJ%diW^9p0mTR@u>n#K3O_0E3LDU#XINscUWE~t+W+C2>#^#PS$&ft?) zL3;~8yB&!&6;g)@fJgK|^BbVHAfm(uwcJ6cX+X}t1%(zU7GM}xZ3S8D13K|KkpVPE z14%WY7BT)*1FN$@>k@*&_Z~PhM1pHB(3*eHIf$Sd2iHC()Ub!Ol_4bn=}q z7wAk&Qq6+IJ!t$9GA0TeW!nfo4-+&qk9zV5s5OoITpV^ z9e~P7(Eff6 z@`GCH_)`rcG-2rm`Sc#tlmqh{Y(+3}xx@@!s(@Nd)-0I}ppo|V;8XHIeYzk9(Cj_2 zWz^9pIGJw_)gU-PNm8H|T@U7XpvLZ0y=9B z(FZ!q3{tiWvViJa(AW%UEC!nk&|}^Ln%_X<6$%X2NbZ2N13)zds7xTX1_F(9f>IJ_ zccm?h3yTGdF?hVlfCbUZ+QzZy~c=xXnbgD~Rp0f%cGt+^NW7#R57- z#+Jo{#ST120ICl`r60&lVp}O544_jS3&1m0pcDm~g(WWag6=l)VF&=XOh9c~(AcXL qQN4fIu6^96GC|@W6uuw~$$PHQ`$!>Yn1gQk0F{ZLv%z4evj6}%lZnIt literal 18722 zcmaFAd%wOGFPDOrLYQNab80SUSY}a4X=09oV^DHNVrqU)etKqdVvd4yer`c&NotXT zt8ZyeVo83H9!L`>r(>Q%YA!@XAwNw)BR9XeB&SkSp~AvUHz~0=HANx7S)sVHxFj{V zSRpYlMIj}%EHgQ^SO=oLv^X;_U7;i+RlzgZQO6ZTg!wq>_&Pf(fK>-LdqQ<9B$XDY z7V9V!<(H;s|GcU6wGe56bAuYd1LCHI@ zDlt1lK?6b;mn7zCDkS#dgOC~HD2(e;kfD=sPGG}JTD zGvzcgFtpG&G|)G+0J#u^6&y=TGV+UxtvDTvk`jxG6`~T;6H~G?^K=w!62T&RRZtO! z+{DZry`oY(kUmaMx1!V(1wTE7vcxF%jQo7PwcAQt8qDS&zTr6mfv`6-!cnaPPDlXMgki&7N|Qj2mk zOG;8x6ch@I^2;()Qd1O4G7?Kb=>wuaEk7qGzZ?`F$@zIH(C7eZ%}p(_0x1DuPEJET z1yq+7gQ6Mk!sPsvRE6Bq;u3|T)RM%^JdpVcsd*)tMX3<|3JMB|N%>`|3VHb@naQa- z3MHUqlapBtPA%sFx{1zr+^e#Fjo~6<)@S; zr-B^@b_qnkf`URaJj&pXLvkJ1n@H}1#862F!e4NgDj-}4iaoGZDf!8zxv6<2;5Y&4 z)z2?d$S=uAErQ#hn^=-sl$n@QjEEvo^g^^Fr46J+W2~p(mzoJO1*}RTFEKY2w@kWWBKv$!BN z8I(5R_7@ao<`*fH7lBe|9weO>gR(W;mkJ>sp1}&i{%#@RjzO*p3ZB6V3IRd>VV*9o zE(%VO3Lze@3JT8t0g*wT?j9iu3LgGGF0Mhr3XXm*3eNt1Awix_p&|Z3!5|wIlpKQ< zJcE_Mk_wJ~kqWL60YR?8!3qlgK?(|KA|q2 ze(pL7PN5+R3V!|}V6%KYeLX{5T@*t6b-<2*=|*T)@OM-2bq#X%aP$jtbn^7^42cBW z?B*Hb2eQ=7KS;q5Y*v6{P>82U~66oNe*eSE++!+j4n3lace4gpHb>FA@N z;Ns}(=2h2T)9;1JJ{&=6Mz1$Tdcmtc_VgI$Bd zJe^&GtrZk}{DXr*ff*X?3UQZ;NKrtLznf=Bur-M76dLRa4p&dV5Z9of(0~w6 ze?LtH5C3r2FxMajXUEWBP~?IVhQFTzDEh(S72@IQ9~22P9vnX4Xwp##_izpIa18iBjQX!rpJ|HB6)N`!4ofY`oZgVY|Ym z*$|Z%8!t}7RBZ$@>e9xG4HvsF?7rB2Vb6sv7rQUbR=BY1!q$t87j|8oc403F6EMb@ zQ|ZEdh>i&2!E z8!pWTkrx}F4!gAe!WOW^u8Y$yc7TH5VuQkkZI{+x*ahY^D_q!fY5j#g5T`3#*m_|P z$X$x)UN-^<)S`>iKt8>&`@+@>J3)%~Uf6tb+J)^GrzwE_&;XLXNW7UwoJs-Ci3JK5 z_Fvd=VdsS{7dBkjjZ3=@noIXx*sXA3aERi`@zrwq0z7_zdI^kdc_N zXk=gvwf53%SX5q`e6bsp02IJxZ3M;crO6jIT-XcpBsfGc1H=TkDHpat48GWiN53hj zl4>y_FW?RhP=dLz{lb=u(=IIrn{sI~C;%@uT-beK1K9U_6)tSN*nD9RIE=b4?7gr- zAtnzLL!kHrX;%QnI@rhiFSdew3sHG#F(~Giv+0zlJd;%w7g`B=el$4>#9@NIjPgBTE&CM^W#7K(9 zprm+d)`fi+c7r|K42msqE)4Sb1%<@c3p+u%0qn~L+%c-Cq<~ti85tWGaVlL{4bDP4 zK;Z_;;R?x z3;RF`QQ^Xdiya`*ZI@?)JOZ=7S>eLI3wtkigJNd`IF@&U((HxpAWv_wM^B-~pmcs= z;-!sXJ*qjyFmvz~UEsJ>P*5!fx%<*=P#`N@fTsdbqPehLk0_s9*bK^#P@n9%u)!Wn zaGP){sjC*ND_m^2u=T=Ta7onwNn9X5qNYH&-7_vWUf2(E*u|a;+b`_9unAOPU+hu1 zuxJE*@~sgR zhmgqIe__ML21q8m*aXgSTQ4>!Tx^7wzRlnW2K#Ckmh@}JsRW9Sq|B1s!~)%mE#Sg$ zH#lO!vQ3OMY!6DePsV9%E(pnQ2@J_$Ys)d=9Y1ck^} zaDBK35_ynxs-OX?jW6s36+EBBYTcN0({aCyar z?VuRB*pLaX1yExFR6Jbl)>F8&?!s=6Do`|n(!s?JP#A5%;sCH)w_~JJ6L7Hr%}C(F z5fn?HK!;QspsWJRG9XcKbZ)t@0hDnzfKml0sex*$28eoaN(ae8v-gEPmuG?sRd|7Q zu^Ci*Uu*#BL#mzi6hQF+s?;F1fRur3ffNd06F`j*l)%OeH&EMS(Z%kI9iW!Zg}tD{ z;nHGIP0)O?;bP;3eHR-PE^Pz{Cn$?tT7R(vT*F*!0_nN13tUZrJqPj;sLiw&)NaDG z$AnYq0s(t2Yy{`o4Is0@6~CK>wws|5B--&9ZAyXBdtptS3mZUf7L0J%2WpOiJP9s| zFE)XTY;X(U;xvK|GXpscl$bAUy|5ipa9r30Dc!bR*l}Uc#c4=M4;;Uc@V&5C!8s(z zN88aSL_5II-BrQGKim(ayh3DQ-^}7<1?;^5Q|#H;6qJoG%>pG{NOcLW(lMK^3b4`$ zT(vgD7-;F0B^D*e7+jcmdFI6iP(cVSt`G{eVhj*Y3-z>8NY2mA&CgRv%}E7~mJ};! z7#m=9mA^M9r;@)nTH0}T^mBIg;Z(XX5md-SassF_zSxYWFw!-clT+!!jLS38B>enA z;?pkdyEGe3#@XM`&C@+J$dywGXKjq8#VN=?JQ$>Y1;{xUyY=++P<@+{nV6HGu27tj z2pV35_s5K}_ecEv{Xm9ca~!zG>*oma`mBr7K!FX)h7cCC2-}P1I2X@g&|rWIs9OSZ z9;nFK3TjqdfR+Mi>RtVCDF-zq(G>f;xp8tTU0wky0YHfrUD}TmV(rC7jHn6q^YM4~ z21#GqcwzU2{TI7IO=)mr0L>I^>b70j0BX6SsSJq>0EOJ5OY1>FgC^EjCNX))yNuHlnL^3I!*!MHlv6*bl0g zK(z?E8qnB~A2`WQgJgPi1)eUPoJyW9=)yjspdj=K^+T8N^b3o}>YIxVmo{FS4X#s~ z6rgQ$NaeN{)M{)3HMu}7sm+-ewr5^ioOxlpk^)*Q*VETM-ZjEAI0Tf#pp8RN4Gd{C zgZe9bL1_U})`9wpuv!Y#90S)Gu$ueAh6~%Fg~@)9a!`YO11Q+_K>ZA8n-@|!A$RZ~ zO)pS~8Pw|A3@TC@LCrrH?t@)PrKE*)S5i@eQn7^@EfyOn@{rFE)T`VWe~m4K+hUkTMWfx-bFcN=TUi9&G}T zpn&269Oa;dI1SV+2RD(x{ooDAX2XJE17=DD5Bnh{|KO6ul2TC1!pO)JI_jsdrJxa- zR|=X_&C4%`j09q6%P-AKQE&$hqG}i$nPM9-4EA$zcl7k*RJt(bV)uoO;3j+1#cohl zvI|t=fQG&E%wf)l#VKfn z*3UKE)7Kq5GPwafZgXJ=c;szAqXyRP zL7V%RS6;f;zBmm_MmIO-R0<04MQOQWQ)U4QB~ZFk2nz7U;si@%c?CmNPzv90 zvHxQ8#cpuwLvEfyQz+-V7xGsP-tX#kQmF~Kfr z$f@Mw>!zS#XkcUl>UHl15B@cQvgXBU$o*|-#8?_ZH5eI~SP-Sbm{Z9}&%y$`^(LH3 zQJw(`h6bR%11#;stTKg28kvG5G4gO~Nl7Mn%EK7@SYohiNQkGOdoZYR2QERu!=Z?g z8l>n3Wj14DLr|In4Jhupu>WGu#Xd;siKz^n$S&*vk3WHjz%iA81`wxSfDMZ`BMrHM zsy|TakEsXLBZrqYn9`uaeG#}`-f&?*rZlKCJRc-|5mf4LxY(ee;q33Lpr+sx5P}?y zP_KeY1yHp+8&pbznqn6_psWT=v&}(G8SwBLsAUPN#F0xKO!c7hU$RuE0{d2E&twZ(?#rW?rg}g0V5Yl0Z#q z#zvsf!-#pzqR!aJj8n-uAXEV~AOPxqU{hiaR)S3i6fU58p$XJ#oek=rfWvYRWE=R!I!2s$~Yyp+~kWzok#cnJrjSV=Ju#^wR#-Jp-7*qjV>;|O|a6NXh@xqP^doQ+v zJ3gS1x(yebv6%^K?FEE_+6w#7x_FR$YHSQnxgf*9gP}XXqeHvFL-C;Q)P-Fa_FdR> zVgH347j|FlhqNs(b}M1DyNr!ZIF+!J!p6p?oJyBxf*Wo7K~oi=>I12Pgp~eZ4l)BL zSWr&|)K`Oagu%TTjnEKhP;S6on1p4fq~?Rt3P!5{YPcz=l$Z#r{y{B1ECB|p{=@R~ zQ}Xi_+=~(mGBT4Pb0Vm{CS^B3M)NR31U!E1>*?aDi8J$GS0*yP!u zz8R<&v>#HDg2EJc+y>+ql@x>Ajw9chfb-ovNWTaaOrV(E52^4lqXCo$LDLJM@)bNY zv*BVRC_KT#x(Zn0%@o|@2Gw!krUJMXgwSAw#Rg+=83S5Q0Gb6t(_oB61GoYQ&mL_A z&!0AdN^|gx#9o9=*qjE*{?jgiy0xH*SF9RAPQ)F${@`_GF3?4#3dSZl${G_;SrhCW z>pqMc9H zDX8u4>!hIJ>=A6GpjxT}#h|(#Eg%d*Z6T}^nUEoUbmgF8AFFZ&jZ5n<>;^BS*sF?;5<4t>xDJcr@^rxd> zY>K0fFa^~SkfIZN0tBx+0JQ``>j#kMVxS2HRA;~vBB;>_8h8h__CZB4s1c7CtN_X4 zGYC|rOoXIZkW%su0=2uBftsJ-VY1OcdNfll-8f3Ea5$Z~+(7 z&~+}LF>_ews96CtO9yfrWO4wrv26-!Y+qghs+koK$(TSeBjyM2T80=zgeD1410L*H z&HO(o?{lv_Rv1pz0cFDG_KgG$X~{ zT1zi87etn2q!2MLidL)`gAzBixCXfvw+o;{b>M~-bmUqC)EBzgpoxfX_?Y;G{onfEIy+>na?LGE;D) z40~7q!Y){i1s;|MP1hm1`jF_xlFmU5w+pzl0jQaFVbMj{z0~^#_a}03|@Wdiz$f*QsrDBmWLR5v&NU>6Y&Js8!7Aa^L zTVh><021a@(ts>QL2fmG$IC21tt*X-t)O)(7n^jkRAs8kR#f}Wi(55e-WgU1t61))i!k&xW3gAVlpxGnvn%0ZW;JIu>B?GY*)BwDIS`xvc36^aX zR5KMcREssO6jXCSLo%?G2{i!JE`+UaK?EbDqym-s2KJ!R-VjV0n;BSZ>6sgWNDH$x zYc0K`%sgu?z2riWnv~*fYc0LBoC0ety^NGxcukR2oDWh|k^<7El?JXuDpJy73=}TR z0##d}K_y6E1llbG%_V|@8Pv@M4Ss_9yjW_Z%-j@fEj@(kF$NbFftL87)}W9PIZ}K^ zjGrn}K)wfgCdS~xoC_N+Y`(Df!Vd5tPHcO-==rYV`Z>DF3$5VI66 zOhoc8D6T+Dighn+ytEONYA?;k5nc+Qgb4OKMu}kv8ihqRm589nVUh`_l7*R@!o^?a1P7CmBowjf_BMfGxw8lrxL-LD{f06=&*D(9qJ;(gcMgWWgG08ZiQeB4Pv)wEA#6xL<{; z4Al6?-$_Cb3G_e%wVa|n15^!+Ga=;?&QJq2iK09MKrV(P$EuV}P)i1->;&z2K%Ps1 zWG|$(F&M=L!IgZdJ_fbCXy6KrWNZc+UWX4+g3D_RHRd2S@JNEGK{RM{Q}ar#6daR5 zduA0hOt7yybaV!7DdSYS&~~vA$p&zj#l!$q;a`AEJ?#evHfRmrg$)<>gB$Ch?#YD> zprz)Z4L6{+doxBC%ftXQlVG=ZutQ1J^I z)dlTC0xgaO_nfwYSEfyiDS^jWKw^4oXaHuA8iHD6^DZq0ujW+%73vpugX-dapgLT^ z(I*5n-V0r*4;o(uO$dQwFM46CY(w}AU)7Fy#h)Ixs~SR6ekyfPBaKE zDM~F#&QS0LZC=+fF)+d5D-%!=G7B`q3>t-pr9bc>E};Z~lGCByH32mqu_qu<3t!>F zF1S^wB?U~s5vP)g70RpuOa@dTtpF#@4p2uLG>r=0dj)EqgJK0s2%CV?-^NSpL78kX zDB*!t4{ZVIhDI7_1s7=b4K}@?;$i~G(V*eK3wyysE|5$JYG@&CZULt+)cA18EH21N ztOTW0j1dD+E8E30IKam-6121j$NCAVuR(PlB+-GlL^gpV=)x8Pnn3M4P)7*T+1d;0 zynr?_bb!37fVyTDveyJ-2*AVuG*n<>1zP$C8gvJh8_-RZi$VRR29O|la30(}fyOJS znGRYDh8&zA@0u8Z2NWh;nym|7^w$8YGf+GMnv@1_B>_b+c=mh)Sm}kGpq>+`xB%rZ zP#i#axInGJ9_)6Y$pvr(gj5!!f?~l8Yw`z019Tbn6yzXjNZHaRsD%QDS8=xP)}h&nttRPNDz{ zRdcMN>K^168SLx`+RA(Z+0&rep?w$jUf2Z6t)N907yCg|Y0$ndI1C%G2DZ5&r;<~M znSr5#hF?gqvwnc15AqlTEKbagK+4PwEEP07TtdRIDgg!ZJkY=~sLu~>1)$gSA^G_^ z#h@f(f$lj_N)GY&_X!3~c!Ihr;6c?bpcIQ7Eg)qk2B5hyVzyL3qs0Q0LO|PzcO!=Y zCrlRPY|!Sz&7l79MdX!9FcqLg09FBNHGwnyg^A!n;?0n8P%JKlZn)hITJ8@q7nHL> zYY`hkMIPD~2be{mRuX81(B6wJ7j|6O3?3uga1qwVxU>=6O$Y4}#8ReMfQCeHX$Gz0 z2X8e6H8!wm291;~ys+zH189`v koiCSHg1ce6Faycb5bLUOghj4-DWJniKxYK$fj8R&02|XtApigX diff --git a/src/ui/ui_stbar.c b/src/ui/ui_stbar.c index d94611a..d3e5d76 100644 --- a/src/ui/ui_stbar.c +++ b/src/ui/ui_stbar.c @@ -8,12 +8,12 @@ * * Common UI support functions for the Status Bar module. * - * Version: @(#)ui_stbar.c 1.0.17 2018/11/06 + * Version: @(#)ui_stbar.c 1.0.18 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -41,10 +41,9 @@ #include #include "../emu.h" #include "../config.h" -#include "../cpu/cpu.h" -#include "../machines/machine.h" #include "../device.h" #include "../plat.h" +#include "../machines/machine.h" #include "../devices/input/keyboard.h" #include "../devices/floppy/fdd.h" #include "../devices/disk/hdd.h" @@ -58,7 +57,6 @@ #include "../devices/sound/sound.h" #include "../devices/video/video.h" #include "ui.h" -#include "ui_resource.h" #define USE_SPACER 1 /* include a spacer field */ @@ -488,7 +486,7 @@ ui_sb_reset(void) sb_nparts = 0; } - hdint = (machines[machine].flags & MACHINE_HDC) ? 1 : 0; + hdint = (machine_get_flags() & MACHINE_HDC) ? 1 : 0; do_net = !!((network_type != 0) && (network_card != 0)); do_sound = !!(sound_card != 0); diff --git a/src/win/mingw/Makefile.MinGW b/src/win/mingw/Makefile.MinGW index 65b0cfa..8b6e3d5 100644 --- a/src/win/mingw/Makefile.MinGW +++ b/src/win/mingw/Makefile.MinGW @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW32 environment. # -# Version: @(#)Makefile.mingw 1.0.77 2019/03/01 +# Version: @(#)Makefile.mingw 1.0.80 2019/04/20 # # Author: Fred N. van Kempen, # @@ -83,8 +83,20 @@ endif ifndef X64 X64 := n endif +ifndef ARM +ARM := n +endif +ifndef ARM64 +ARM64 := n +endif ifndef DYNAREC DYNAREC := y + ifeq ($(ARM), y) + DYNAREC := n + endif + ifeq ($(ARM64), y) + DYNAREC := n + endif endif ifndef WX WX := n @@ -119,11 +131,32 @@ endif ifndef AMD_K AMD_K := n endif -ifndef PORTABLE3 - PORTABLE3 := n +ifndef SIS471 + SIS471 := n endif -ifndef I686 - I686 := n +ifndef SIS496 + SIS496 := n +endif +ifndef COMPAQ + COMPAQ := n +endif +ifndef SUPERSPORT + SUPERSPORT := n +endif +ifndef DINPUT + DINPUT := y + ifeq ($(ARM), y) + DINPUT := n + endif +endif +ifndef D3DX + D3DX := y + ifeq ($(ARM), y) + D3DX := n + endif + ifeq ($(ARM64), y) + D3DX := n + endif endif ifndef OPENAL OPENAL := y @@ -182,8 +215,12 @@ ifeq ($(DEV_BUILD), y) CRASHDUMP := y DEV_BRANCH := y AMD_K := y - PORTABLE3 := y - I686 := y + SIS471 := y + SIS496 := y + COMPAQ := y + SUPERSPORT := y + ST11 := y + WD1002 := y PAS16 := y GUSMAX := y XL24 := y @@ -230,10 +267,11 @@ endif ######################################################################### VPATH := $(EXPATH) . cpu \ devices \ - devices/cdrom devices/disk devices/floppy \ - devices/floppy/lzf devices/input devices/input/game \ - devices/network devices/ports devices/printer \ - devices/sio devices/system devices/scsi devices/misc \ + devices/chipsets devices/system devices/sio \ + devices/input devices/input/game devices/ports \ + devices/network devices/printer devices/misc \ + devices/floppy devices/floppy/lzf \ + devices/disk devices/cdrom devices/scsi \ devices/sound \ devices/sound/munt devices/sound/munt/c_interface \ devices/sound/munt/sha1 devices/sound/munt/srchelper \ @@ -267,17 +305,35 @@ ifneq ($(CROSS), n) SYSLIB := -L/usr/$(MINGW)/lib else # Native compilation using MinGW for Windows. + CPP := g++ -m32 + CC := gcc -m32 + PREPROC := cpp + WINDRES := windres + STRIP := strip + ifndef CAT + CAT := cat + endif + + # Overrides for Windows, X64. ifeq ($(X64), y) CPP := g++ -m64 CC := gcc -m64 - else - CPP := g++ -m32 - CC := gcc -m32 endif - PREPROC := cpp - WINDRES := windres - ifndef CAT - CAT := cat + + # Overrides for Windows, ARM. + ifeq ($(ARM), y) + CPP := armv7-w64-mingw32-g++ + CC := armv7-w64-mingw32-gcc + WINDRES := armv7-w64-mingw32-windres + STRIP := armv7-w64-mingw32-strip + endif + + # Overrides for Windows, ARM64. + ifeq ($(ARM64), y) + CPP := aarch64-w64-mingw32-g++ + CC := aarch64-w64-mingw32-gcc + WINDRES := aarch64-w64-mingw32-windres + STRIP := aarch64-w64-mingw32-strip endif SYSINC := -Iwin/mingw/include @@ -291,9 +347,37 @@ DEPFILE := win/mingw/.depends OPTS := $(EXTRAS) $(STUFF) \ -D_CRT_NON_CONFORMING_SWPRINTFS \ -D__USE_MINGW_ANSI_STDIO_X -AFLAGS := -msse2 -mfpmath=sse RFLAGS := --input-format=rc -O coff LDFLAGS := + +# Options fow Windows, X86. +AFLAGS := -msse2 -mfpmath=sse +ifeq ($(OPTIM), y) + DFLAGS := -march=native +else + DFLAGS := -march=i686 +endif + +# Options for Windows, X64. +ifeq ($(X64), y) + ifeq ($(OPTIM), y) + DFLAGS := -march=native + endif +endif + +# Options for Windows, ARM. +ifeq ($(ARM), y) + AFLAGS := -mfloat-abi=hard + DFLAGS := -march=armv7-a +endif + +# Options for Windows, ARM64. +ifeq ($(ARM64), y) + AFLAGS := -mfloat-abi=hard + DFLAGS := -march=armv8-a +endif + + ifdef BUILD OPTS += -DBUILD=$(BUILD) endif @@ -313,19 +397,6 @@ endif ifneq ($(CROSS), n) OPTS += -DUSE_CROSS 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 -D_DEBUG RFLAGS += -D_DEBUG @@ -373,8 +444,15 @@ else VCG := vid_voodoo_codegen_x86.h endif LIBS := -mwindows \ - -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ - -lversion -lcomctl32 -lwinmm + -lddraw -ldxguid -ld3d9 -lversion -lcomctl32 -lwinmm +ifeq ($(DINPUT), y) + LIBS += -ldinput8 +else + LIBS += -lxinput +endif +ifeq ($(D3DX), y) + LIBS += -ld3dx9 +endif LIBS += -lws2_32 -lwsock32 -liphlpapi -lpsapi LIBS += -static -lstdc++ -lgcc #ifneq ($(X64), y) @@ -459,6 +537,14 @@ ifneq ($(D2D), n) D2DOBJ := win_d2d.o endif +ifeq ($(D3DX), y) +OPTS += -DUSE_D3DX +endif + +ifeq ($(DINPUT), y) +OPTS += -DUSE_DINPUT +endif + # N=no, Y=yes,linked, D=yes,dynamic, S=yes,static ifneq ($(VNC), n) OPTS += -DUSE_VNC @@ -539,12 +625,30 @@ ifeq ($(DEV_BRANCH), y) OPTS += -DUSE_AMD_K endif - ifeq ($(PORTABLE3), y) - OPTS += -DUSE_PORTABLE3 + ifeq ($(SIS471), y) + OPTS += -DUSE_SIS471 endif - ifeq ($(I686), y) - OPTS += -DUSE_I686 + ifeq ($(SIS496), y) + OPTS += -DUSE_SIS496 + endif + + ifeq ($(COMPAQ), y) + OPTS += -DUSE_COMPAQ + DEVBROBJ += m_compaq.o m_compaq_vid.o vid_cga_compaq.o + endif + + ifeq ($(SUPERSPORT), y) + OPTS += -DUSE_SUPERSPORT + DEVBROBJ += m_zenith.o m_zenith_vid.o + endif + + ifeq ($(ST11), y) + OPTS += -DUSE_ST11 + endif + + ifeq ($(WD1002), y) + OPTS += -DUSE_WD1002 endif ifeq ($(PAS16), y) @@ -605,36 +709,36 @@ MAINOBJ := pc.o config.o misc.o random.o timer.o io.o mem.o \ UIOBJ += ui_main.o ui_lang.o ui_stbar.o ui_vidapi.o \ ui_cdrom.o ui_new_image.o ui_misc.o -SYSOBJ := dma.o nmi.o pic.o pit.o ppi.o pci.o mca.o mcr.o \ - memregs.o nvr_at.o nvr_ps2.o - CPUOBJ := cpu.o cpu_table.o \ 808x.o 386.o x86seg.o x87.o \ 386_dynarec.o $(DYNARECOBJ) +SYSOBJ := dma.o nmi.o pic.o pit.o ppi.o pci.o mca.o mcr.o \ + memregs.o nvr_at.o nvr_ps2.o + +CHIPOBJ := neat.o scat.o headland.o \ + intel4x0.o ali1429.o opti495.o sis471.o sis496.o \ + wd76c10.o + MCHOBJ := machine.o machine_table.o \ - m_xt.o m_xt_compaq.o \ - m_xt_t1000.o m_xt_t1000_vid.o \ - m_xt_laserxt.o m_xt_xi8088.o \ - m_zenith.o \ + m_xt.o \ + m_amstrad.o m_amstrad_vid.o \ + m_europc.o m_laserxt.o \ + m_olim24.o m_olim24_vid.o \ + m_tandy1000.o m_tandy1000_vid.o \ + m_tosh1x00.o m_tosh1x00_vid.o \ + m_xi8088.o \ m_pcjr.o \ - m_amstrad.o m_europc.o \ - m_olivetti_m24.o m_tandy.o \ - m_at.o \ - m_at_ali1429.o m_at_commodore.o \ - m_at_neat.o m_at_headland.o \ - m_at_t3100e.o m_at_t3100e_vid.o \ m_ps1.o m_ps1_hdc.o \ m_ps2_isa.o m_ps2_mca.o \ - m_at_opti495.o m_at_scat.o \ - m_at_compaq.o m_at_wd76c10.o \ - m_at_sis471.o m_at_sis496.o \ - m_at_4x0.o - -INTELOBJ := intel.o \ - intel_flash.o \ - intel_sio.o \ - intel_piix.o + m_at.o \ + m_neat.o m_headland.o m_scat.o \ + m_commodore.o \ + m_tosh3100e.o m_tosh3100e_vid.o \ + m_ali.o m_opti495.o m_sis471.o m_sis496.o \ + m_wd76c10.o m_intel4x0.o \ + m_acer.o m_aopen.o m_asus.o m_pbell.o m_tyan.o \ + m_misc.o DEVOBJ := bugger.o \ isamem.o isartc.o \ @@ -644,6 +748,7 @@ DEVOBJ := bugger.o \ serial.o \ sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o \ sio_pc87306.o sio_w83877f.o sio_um8669f.o \ + intel.o intel_flash.o intel_sio.o intel_piix.o \ keyboard.o \ keyboard_xt.o keyboard_at.o \ mouse.o \ @@ -712,7 +817,6 @@ SNDOBJ := sound.o \ VIDOBJ := video.o \ video_dev.o \ vid_cga.o vid_cga_comp.o \ - vid_cga_compaq.o \ vid_mda.o \ vid_hercules.o vid_herculesplus.o vid_incolor.o \ vid_colorplus.o \ @@ -742,15 +846,19 @@ VIDOBJ := video.o \ PLATOBJ := win.o \ win_lang.o win_dynld.o win_opendir.o win_thread.o \ - win_cdrom.o win_keyboard.o win_mouse.o win_joystick.o \ - win_serial.o win_midi.o + win_cdrom.o win_keyboard.o win_serial.o win_midi.o +ifeq ($(DINPUT), y) + PLATOBJ += win_mouse.o win_joystick.o +else + PLATOBJ += win_mouse_ri.o win_joystick_xi.o +endif ifeq ($(CRASHDUMP), y) PLATOBJ += win_crashdump.o endif -OBJ := $(MAINOBJ) $(CPUOBJ) $(MCHOBJ) $(SYSOBJ) $(DEVOBJ) \ - $(INTELOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \ +OBJ := $(MAINOBJ) $(CPUOBJ) $(MCHOBJ) $(SYSOBJ) $(CHIPOBJ) \ + $(DEVOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \ $(USBOBJ) $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \ $(UIOBJ) $(PLATOBJ) $(MISCOBJ) $(DEVBROBJ) ifdef EXOBJ @@ -801,7 +909,7 @@ $(PROG).exe: $(OBJ) VARCem.res @$(CC) $(LDFLAGS) -o $@ \ $(OBJ) VARCem.res $(LIBS) ifneq ($(DEBUG), y) - @strip $(PROG).exe + @$(STRIP) $(PROG).exe endif pcap_if.res: pcap_if.rc @@ -813,7 +921,7 @@ $(NETIF).exe: pcap_if.o win_dynld.o pcap_if.res @$(CC) $(LDFLAGS) -o $@ \ pcap_if.o win_dynld.o pcap_if.res ifneq ($(DEBUG), y) - @strip $(NETIF).exe + @$(STRIP) $(NETIF).exe endif diff --git a/src/win/msvc/Makefile.VC b/src/win/msvc/Makefile.VC index af3f575..c54c735 100644 --- a/src/win/msvc/Makefile.VC +++ b/src/win/msvc/Makefile.VC @@ -8,7 +8,7 @@ # # Makefile for Windows using Visual Studio 2015. # -# Version: @(#)Makefile.VC 1.0.63 2019/03/01 +# Version: @(#)Makefile.VC 1.0.65 2019/04/20 # # Author: Fred N. van Kempen, # @@ -84,8 +84,20 @@ endif ifndef X64 X64 := n endif +ifndef ARM +ARM := n +endif +ifndef ARM64 +ARM64 := n +endif ifndef DYNAREC DYNAREC := y + ifeq ($(ARM), y) + DYNAREC := n + endif + ifeq ($(ARM64), y) + DYNAREC := n + endif endif ifndef WX WX := n @@ -120,11 +132,32 @@ endif ifndef AMD_K AMD_K := n endif -ifndef PORTABLE3 - PORTABLE3 := n +ifndef SIS471 + SIS471 := n endif -ifndef I686 - I686 := n +ifndef SIS496 + SIS496 := n +endif +ifndef COMPAQ + COMPAQ := n +endif +ifndef SUPERSPORT + SUPERSPORT := n +endif +ifndef DINPUT + DINPUT := y + ifeq ($(ARM), y) + DINPUT := n + endif +endif +ifndef D3DX + D3DX := y + ifeq ($(ARM), y) + D3DX := n + endif + ifeq ($(ARM64), y) + D3DX := n + endif endif ifndef OPENAL OPENAL := y @@ -182,8 +215,12 @@ ifeq ($(DEV_BUILD), y) CRASHDUMP := y DEV_BRANCH := y AMD_K := y - PORTABLE3 := y - I686 := y + SIS471 := y + SIS496 := y + COMPAQ := y + SUPERSPORT := y + ST11 := y + WD1002 := y PAS16 := y GUSMAX := y XL24 := y @@ -231,11 +268,11 @@ endif VPATH := $(EXPATH) . cpu \ devices \ - devices/cdrom devices/disk devices/floppy \ - devices/floppy/lzf devices/input devices/input/game \ - devices/network devices/network/slirp devices/ports \ - devices/printer devices/sio devices/system devices/scsi \ - devices/misc \ + devices/chipsets devices/system devices/sio \ + devices/input devices/input/game devices/ports \ + devices/network devices/printer devices/misc \ + devices/floppy devices/floppy/lzf \ + devices/disk devices/cdrom devices/scsi \ devices/sound \ devices/sound/munt devices/sound/munt/c_interface \ devices/sound/munt/sha1 devices/sound/munt/srchelper \ @@ -351,10 +388,18 @@ else CGOPS := codegen_ops_x86.h VCG := vid_voodoo_codegen_x86.h endif -LIBS := ddraw.lib dinput8.lib dxguid.lib d3d9.lib d3dx9.lib \ - version.lib comctl32.lib winmm.lib comdlg32.lib \ - advapi32.lib gdi32.lib shell32.lib user32.lib \ - ws2_32.lib wsock32.lib iphlpapi.lib psapi.lib +LIBS := ddraw.lib dxguid.lib d3d9.lib version.lib winmm.lib +ifeq ($(DINPUT), y) + LIBS += dinput8.lib +else + LIBS += xinput.lib +endif +ifeq ($(D3DX), y) + LIBS += d3dx9.lib +endif +LIBS += comctl32.lib comdlg32.lib advapi32.lib gdi32.lib \ + shell32.lib user32.lib +LIBS += ws2_32.lib wsock32.lib iphlpapi.lib psapi.lib ifeq ($(DEBUG), y) LIBS += libcmtd.lib libvcruntimed.lib libucrtd.lib endif @@ -438,6 +483,14 @@ ifneq ($(D2D), n) D2DOBJ := win_d2d.obj endif +ifeq ($(D3DX), y) +OPTS += -DUSE_D3DX +endif + +ifeq ($(DINPUT), y) +OPTS += -DUSE_DINPUT +endif + # N=no, Y=yes,linked, D=yes,dynamic, S=yes,static ifneq ($(VNC), n) OPTS += -DUSE_VNC @@ -518,12 +571,30 @@ ifeq ($(DEV_BRANCH), y) OPTS += -DUSE_AMD_K endif - ifeq ($(PORTABLE3), y) - OPTS += -DUSE_PORTABLE3 + ifeq ($(SIS471), y) + OPTS += -DUSE_SIS471 endif - ifeq ($(I686), y) - OPTS += -DUSE_I686 + ifeq ($(SIS496), y) + OPTS += -DUSE_SIS496 + endif + + ifeq ($(COMPAQ), y) + OPTS += -DUSE_COMPAQ + DEVBROBJ += m_compaq.obj m_compaq_vid.obj vid_cga_compaq.obj + endif + + ifeq ($(SUPERSPORT), y) + OPTS += -DUSE_SUPERSPORT + DEVBROBJ += m_zenith.obj m_zenith_vid.obj + endif + + ifeq ($(ST11), y) + OPTS += -DUSE_ST11 + endif + + ifeq ($(WD1002), y) + OPTS += -DUSE_WD1002 endif ifeq ($(PAS16), y) @@ -579,36 +650,36 @@ MAINOBJ := pc.obj config.obj misc.obj random.obj timer.obj io.obj \ UIOBJ += ui_main.obj ui_lang.obj ui_stbar.obj ui_vidapi.obj \ ui_cdrom.obj ui_new_image.obj ui_misc.obj -SYSOBJ := dma.obj nmi.obj pic.obj pit.obj ppi.obj pci.obj mca.obj \ - mcr.obj memregs.obj nvr_at.obj nvr_ps2.obj - CPUOBJ := cpu.obj cpu_table.obj \ 808x.obj 386.obj x86seg.obj x87.obj \ 386_dynarec.obj $(DYNARECOBJ) +SYSOBJ := dma.obj nmi.obj pic.obj pit.obj ppi.obj pci.obj mca.obj \ + mcr.obj memregs.obj nvr_at.obj nvr_ps2.obj + +CHIPOBJ := neat.obj scat.obj headland.obj \ + intel4x0.obj ali1429.obj opti495.obj sis471.obj sis496.obj \ + wd76c10.obj + MCHOBJ := machine.obj machine_table.obj \ - m_xt.obj m_xt_compaq.obj \ - m_xt_t1000.obj m_xt_t1000_vid.obj \ - m_xt_laserxt.obj m_xt_xi8088.obj \ - m_zenith.obj \ + m_xt.obj \ + m_amstrad.obj m_amstrad_vid.obj \ + m_europc.obj m_laserxt.obj \ + m_olim24.obj m_olim24_vid.obj \ + m_tandy1000.obj m_tandy1000_vid.obj \ + m_tosh1x00.obj m_tosh1x00_vid.obj \ + m_xi8088.obj \ m_pcjr.obj \ - m_amstrad.obj m_europc.obj \ - m_olivetti_m24.obj m_tandy.obj \ - m_at.obj \ - m_at_ali1429.obj m_at_commodore.obj \ - m_at_neat.obj m_at_headland.obj \ - m_at_t3100e.obj m_at_t3100e_vid.obj \ m_ps1.obj m_ps1_hdc.obj \ m_ps2_isa.obj m_ps2_mca.obj \ - m_at_opti495.obj m_at_scat.obj \ - m_at_compaq.obj m_at_wd76c10.obj \ - m_at_sis471.obj m_at_sis496.obj \ - m_at_4x0.obj - -INTELOBJ := intel.obj \ - intel_flash.obj \ - intel_sio.obj \ - intel_piix.obj + m_at.obj \ + m_neat.obj m_headland.obj m_scat.obj \ + m_commodore.obj \ + m_tosh3100e.obj m_tosh3100e_vid.obj \ + m_ali.obj m_opti495.obj m_sis471.obj m_sis496.obj \ + m_wd76c10.obj m_intel4x0.obj \ + m_acer.obj m_aopen.obj m_asus.obj m_pbell.obj m_tyan.obj \ + m_misc.obj DEVOBJ := bugger.obj \ isamem.obj isartc.obj \ @@ -618,6 +689,7 @@ DEVOBJ := bugger.obj \ serial.obj \ sio_fdc37c66x.obj sio_fdc37c669.obj sio_fdc37c93x.obj \ sio_pc87306.obj sio_w83877f.obj sio_um8669f.obj \ + intel.obj intel_flash.obj intel_sio.obj intel_piix.obj \ keyboard.obj \ keyboard_xt.obj keyboard_at.obj \ mouse.obj \ @@ -688,7 +760,6 @@ SNDOBJ := sound.obj \ VIDOBJ := video.obj \ video_dev.obj \ vid_cga.obj vid_cga_comp.obj \ - vid_cga_compaq.obj \ vid_mda.obj \ vid_hercules.obj vid_herculesplus.obj vid_incolor.obj \ vid_colorplus.obj \ @@ -725,8 +796,8 @@ PLATOBJ += win_crashdump.obj endif -OBJ := $(MAINOBJ) $(CPUOBJ) $(MCHOBJ) $(SYSOBJ) $(DEVOBJ) \ - $(INTELOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \ +OBJ := $(MAINOBJ) $(CPUOBJ) $(MCHOBJ) $(SYSOBJ) $(CHIPOBJ) \ + $(DEVOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \ $(USBOBJ) $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \ $(UIOBJ) $(PLATOBJ) $(MISCOBJ) $(DEVBROBJ) ifdef EXOBJ diff --git a/src/win/win.c b/src/win/win.c index 287d891..5bbc7fb 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -523,6 +523,8 @@ plat_get_extension(const wchar_t *path) void plat_append_filename(wchar_t *dest, const wchar_t *s1, const wchar_t *s2) { + dest[0] = L'\0'; + wcscat(dest, s1); plat_append_slash(dest); wcscat(dest, s2); diff --git a/src/win/win.h b/src/win/win.h index 05863d6..3b7e49b 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -10,12 +10,12 @@ * only things used globally within the Windows platform; the * generic platform defintions are in the plat.h file. * - * Version: @(#)win.h 1.0.23 2018/10/25 + * Version: @(#)win.h 1.0.24 2019/03/21 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * Redistribution and use in source and binary forms, with @@ -85,7 +85,7 @@ extern "C" { /* Cleans up the WinAPI sources a bit. */ #if (defined(_MSC_VER) && defined(_M_X64)) || \ - (defined(__GNUC__) && defined(__amd64__)) + (defined(__GNUC__) && defined(__amd64__)) || defined(__aarch64__) # define WIN_RESULT LRESULT #else # define WIN_RESULT BOOL diff --git a/src/win/win_d2d.cpp b/src/win/win_d2d.cpp index 4a8fb3e..dbcce97 100644 --- a/src/win/win_d2d.cpp +++ b/src/win/win_d2d.cpp @@ -336,7 +336,7 @@ d2d_init(int fs) { WCHAR title[200]; D2D1_HWND_RENDER_TARGET_PROPERTIES props; - HRESULT hr = S_OK; + HRESULT hr; INFO("D2D: init(fs=%d)\n", fs); @@ -346,7 +346,8 @@ d2d_init(int fs) if (d2d_handle == NULL) { ERRLOG("D2D: unable to load '%s', D2D not available.\n", PATH_D2D_DLL); return(0); - } + } else + INFO("D2D: module '%s' loaded.\n", PATH_D2D_DLL); #endif /* Get and log the version of the DLL we are using. */ @@ -378,11 +379,15 @@ d2d_init(int fs) 0,0, d2d_screen_width,d2d_screen_height, SWP_SHOWWINDOW); } - if (SUCCEEDED(hr)) - hr = DLLFUNC(CreateFactory)(D2D1_FACTORY_TYPE_MULTI_THREADED, - __uuidof(ID2D1Factory), - NULL, - reinterpret_cast (&d2d_factory)); + hr = DLLFUNC(CreateFactory)(D2D1_FACTORY_TYPE_MULTI_THREADED, + __uuidof(ID2D1Factory), + NULL, + reinterpret_cast (&d2d_factory)); + if (FAILED(hr)) { + ERRLOG("D2D: unable to load factory, D2D not available.\n"); + d2d_close(); + return(0); + } if (fs) { props = D2D1::HwndRenderTargetProperties(d2d_hwnd, @@ -393,10 +398,8 @@ d2d_init(int fs) props = D2D1::HwndRenderTargetProperties(hwndRender); } - if (SUCCEEDED(hr)) - hr = d2d_factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), - props, - &d2d_hwndRT); + hr = d2d_factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), + props, &d2d_hwndRT); if (SUCCEEDED(hr)) { // Create a bitmap for storing intermediate data hr = d2d_hwndRT->CreateBitmap(D2D1::SizeU(2048, 2048), diff --git a/src/win/win_d3d.cpp b/src/win/win_d3d.cpp index 73866a6..5ee90ac 100644 --- a/src/win/win_d3d.cpp +++ b/src/win/win_d3d.cpp @@ -8,7 +8,7 @@ * * Rendering module for Microsoft Direct3D 9. * - * Version: @(#)win_d3d.cpp 1.0.14 2019/03/08 + * Version: @(#)win_d3d.cpp 1.0.16 2019/04/07 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -608,6 +608,7 @@ d3d_resize(int x, int y) static void d3d_screenshot(const wchar_t *fn) { +#ifdef USE_D3DX LPDIRECT3DSURFACE9 d3dSurface = NULL; if (! d3dTexture) return; @@ -617,6 +618,10 @@ d3d_screenshot(const wchar_t *fn) d3dSurface->Release(); d3dSurface = NULL; +#else + /* OK, screenshots not yet possible without D3DX. */ + (void)fn; +#endif } diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index 2de80d7..86b808d 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -12,13 +12,13 @@ * and builds a complete Win32 DIALOG resource block in a * buffer in memory, and then passes that to the API handler. * - * Version: @(#)win_devconf.c 1.0.22 2018/10/24 + * Version: @(#)win_devconf.c 1.0.23 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -79,7 +79,7 @@ dlg_init(HWND hdlg) id = IDC_CONFIGURE_DEV; cfg = dev->config; - while (cfg->type != -1) { + while (cfg->name != NULL) { sel = cfg->selection; h = GetDlgItem(hdlg, id); @@ -95,7 +95,7 @@ dlg_init(HWND hdlg) val = config_get_int(dev->name, cfg->name, cfg->default_int); c = 0; - while (sel->description && sel->description[0]) { + while (sel->description) { mbstowcs(temp, sel->description, sizeof_w(temp)); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)temp); if (val == sel->value) @@ -139,7 +139,7 @@ dlg_init(HWND hdlg) val = config_get_hex16(dev->name, cfg->name, cfg->default_int); c = 0; - while (sel->description && sel->description[0]) { + while (sel->description) { mbstowcs(temp, sel->description, sizeof_w(temp)); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)temp); if (val == sel->value) @@ -154,7 +154,7 @@ dlg_init(HWND hdlg) val = config_get_hex20(dev->name, cfg->name, cfg->default_int); c = 0; - while (sel->description && sel->description[0]) { + while (sel->description) { mbstowcs(temp, sel->description, sizeof_w(temp)); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)temp); if (val == sel->value) @@ -193,7 +193,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) id = IDC_CONFIGURE_DEV; changed = 0; - while (cfg->type != -1) { + while (cfg->name != NULL) { sel = cfg->selection; h = GetDlgItem(hdlg, id); @@ -293,7 +293,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) id = IDC_CONFIGURE_DEV; cfg = dev->config; - while (cfg->type != -1) { + while (cfg->name != NULL) { sel = cfg->selection; h = GetDlgItem(hdlg, id); @@ -372,7 +372,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) id = IDC_CONFIGURE_DEV; cfg = dev->config; - while (cfg->type != -1) { + while (cfg->name != NULL) { switch (cfg->type) { case CONFIG_BINARY: id++; @@ -392,13 +392,13 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) file_filter[0] = 0; c = 0; - while (cfg->file_filter[c].description && cfg->file_filter[c].description[0]) { + while (cfg->file_filter[c].description) { if (c > 0) strcat(file_filter, "|"); strcat(file_filter, cfg->file_filter[c].description); strcat(file_filter, " ("); d = 0; - while (cfg->file_filter[c].extensions[d] && cfg->file_filter[c].extensions[d][0]) { + while (cfg->file_filter[c].extensions[d]) { if (d > 0) strcat(file_filter, ";"); strcat(file_filter, "*."); @@ -407,7 +407,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } strcat(file_filter, ")|"); d = 0; - while (cfg->file_filter[c].extensions[d] && cfg->file_filter[c].extensions[d][0]) { + while (cfg->file_filter[c].extensions[d]) { if (d > 0) strcat(file_filter, ";"); strcat(file_filter, "*."); @@ -508,7 +508,7 @@ dlg_devconf(HWND hwnd, const device_t *device) /* Now add the items from the configuration. */ id = IDC_CONFIGURE_DEV; - while (cfg->type != -1) { + while (cfg->name != NULL) { /* Align 'data' to DWORD */ itm = (DLGITEMTEMPLATE *)data; @@ -554,7 +554,7 @@ dlg_devconf(HWND hwnd, const device_t *device) if (((uintptr_t)data) & 2) data++; /* align */ - /* static tex t*/ + /* static text */ itm = (DLGITEMTEMPLATE *)data; itm->style = WS_CHILD | WS_VISIBLE; itm->x = 10; diff --git a/src/win/win_mouse.cpp b/src/win/win_mouse.cpp index e2f4549..919f121 100644 --- a/src/win/win_mouse.cpp +++ b/src/win/win_mouse.cpp @@ -52,6 +52,16 @@ static LPDIRECTINPUTDEVICE8 lpdi_mouse = NULL; static DIMOUSESTATE mousestate; +void +win_mouse_close(void) +{ + if (lpdi_mouse != NULL) { + lpdi_mouse->Release(); + lpdi_mouse = NULL; + } +} + + void win_mouse_init(void) { @@ -75,16 +85,6 @@ win_mouse_init(void) } -void -win_mouse_close(void) -{ - if (lpdi_mouse != NULL) { - lpdi_mouse->Release(); - lpdi_mouse = NULL; - } -} - - void mouse_poll(void) { diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 366f617..776f99d 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,12 +8,12 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings.c 1.0.38 2018/10/26 + * Version: @(#)win_settings.c 1.0.40 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -178,10 +178,10 @@ settings_init(void) int i; /* Machine category */ - temp_machine = machine; + temp_machine = machine_type; temp_cpu_m = cpu_manufacturer; temp_wait_states = cpu_waitstates; - temp_cpu = cpu; + temp_cpu = cpu_type; temp_mem_size = mem_size; #ifdef USE_DYNAREC temp_dynarec = cpu_use_dynarec; @@ -256,10 +256,10 @@ settings_changed(void) int i = 0, j; /* Machine category */ - i = i || (machine != temp_machine); + i = i || (machine_type != temp_machine); i = i || (cpu_manufacturer != temp_cpu_m); i = i || (cpu_waitstates != temp_wait_states); - i = i || (cpu != temp_cpu); + i = i || (cpu_type != temp_cpu); i = i || (mem_size != temp_mem_size); #ifdef USE_DYNAREC i = i || (temp_dynarec != cpu_use_dynarec); @@ -359,10 +359,10 @@ settings_save(void) pc_reset_hard_close(); /* Machine category */ - machine = temp_machine; + machine_type = temp_machine; cpu_manufacturer = temp_cpu_m; cpu_waitstates = temp_wait_states; - cpu = temp_cpu; + cpu_type = temp_cpu; mem_size = temp_mem_size; #ifdef USE_DYNAREC cpu_use_dynarec = temp_dynarec; @@ -560,7 +560,7 @@ image_list_init(HWND hwndList) for (i = 0; i < PAGE_MAX; i++) { #if (defined(_MSC_VER) && defined(_M_X64)) || \ - (defined(__GNUC__) && defined(__amd64__)) + (defined(__GNUC__) && defined(__amd64__)) || defined(__aarch64__) hiconItem = LoadIcon(hInstance, (LPCWSTR)((uint64_t)icons[i])); #else hiconItem = LoadIcon(hInstance, (LPCWSTR)((uint32_t)icons[i])); @@ -643,7 +643,7 @@ settings_confirm(HWND hdlg, int button) static WIN_RESULT CALLBACK dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; + HWND h = NULL; int category; int i, j; @@ -721,7 +721,7 @@ find_roms(void) c = d = 0; while(1) { /* Get ANSI name of machine. */ - str = machine_getname_ex(c); + str = machine_get_name_ex(c); if (str == NULL) break; diff --git a/src/win/win_settings_disk.h b/src/win/win_settings_disk.h index 1accf4a..df5bc33 100644 --- a/src/win/win_settings_disk.h +++ b/src/win/win_settings_disk.h @@ -8,12 +8,12 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_disk.h 1.0.18 2018/10/24 + * Version: @(#)win_settings_disk.h 1.0.19 2019/03/21 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -1044,13 +1044,16 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) fwrite(&zero, 1, 4, f); /* 00000004: [Translation] Heads per cylinder */ } +INFO("DISK: new_image(size=%i, sector=%i)", size, sector_size); memset(buf, 0, 512); size >>= 9; r = (size >> 11) << 11; size -= r; r >>= 11; +INFO(" = %i blocks (+%i sectors)\n", size, r); if (size || r) { + /* Hide filename controls. */ h = GetDlgItem(hdlg, IDT_1731); EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); @@ -1063,21 +1066,24 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); - h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); - SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) (size + r - 1)); - SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - + /* Enable PB label. */ h = GetDlgItem(hdlg, IDT_1752); EnableWindow(h, TRUE); ShowWindow(h, SW_SHOW); + + /* Create progress bar. */ + h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); + EnableWindow(h, TRUE); + SendMessage(h, PBM_SETRANGE32, (WPARAM)0, (LPARAM)(size + r - 1)); + SendMessage(h, PBM_SETPOS, (WPARAM)0, (LPARAM)0); + ShowWindow(h, SW_SHOW); + } if (size) { for (i = 0; i < size; i++) { fwrite(buf, 1, 512, f); - SendMessage(h, PBM_SETPOS, (WPARAM) i, (LPARAM) 0); + SendMessage(h, PBM_SETPOS, (WPARAM)i, (LPARAM)0); } } @@ -1086,12 +1092,20 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) memset(big_buf, 0, 1048576); for (i = 0; i < r; i++) { fwrite(big_buf, 1, 1048576, f); - SendMessage(h, PBM_SETPOS, (WPARAM) (size + i), (LPARAM) 0); + SendMessage(h, PBM_SETPOS, (WPARAM)(size + i), (LPARAM)0); } free(big_buf); } + /* Hide progress bar and label. */ + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + h = GetDlgItem(hdlg, IDT_1752); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + fclose(f); + settings_msgbox(MBX_INFO, (wchar_t *)IDS_3537); } @@ -1574,7 +1588,7 @@ disk_track_all(void) static WIN_RESULT CALLBACK disk_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; + HWND h = NULL; int old_sel = 0; int b = 0; int assign = 0; diff --git a/src/win/win_settings_floppy.h b/src/win/win_settings_floppy.h index c66034b..4c6f528 100644 --- a/src/win/win_settings_floppy.h +++ b/src/win/win_settings_floppy.h @@ -8,12 +8,12 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_floppy.h 1.0.10 2018/10/25 + * Version: @(#)win_settings_floppy.h 1.0.11 2019/03/21 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -211,7 +211,7 @@ static WIN_RESULT CALLBACK floppy_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { WCHAR temp[128]; - HWND h; + HWND h = NULL; int i; int old_sel = 0; diff --git a/src/win/win_settings_input.h b/src/win/win_settings_input.h index fb4788c..d5cf55e 100644 --- a/src/win/win_settings_input.h +++ b/src/win/win_settings_input.h @@ -8,12 +8,12 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_input.h 1.0.11 2018/10/24 + * Version: @(#)win_settings_input.h 1.0.12 2018/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -47,16 +47,20 @@ static int mouse_to_list[20], static int -mouse_valid(int num, int m) +mouse_valid(int num, int nm) { const device_t *dev; + const machine_t *m; - if ((num == MOUSE_INTERNAL) && - !(machines[m].flags & MACHINE_MOUSE)) return(0); + /* Get info about the selected machine. */ + dev = machine_get_device_ex(nm); + m = (machine_t *)dev->mach_info; + + if ((num == MOUSE_INTERNAL) && !(m->flags & MACHINE_MOUSE)) return(0); dev = mouse_get_device(num); - return(device_is_valid(dev, machines[m].flags)); + return(device_is_valid(dev, m->flags)); } @@ -65,12 +69,18 @@ input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { WCHAR temp[128]; const char *stransi; + const device_t *dev; + const machine_t *m; HWND h; int c; int d = 0; switch (message) { case WM_INITDIALOG: + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); c = d = 0; @@ -87,7 +97,7 @@ input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if (c == 0) { SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_NONE)); } else if (c == 1) { - if (! (machines[temp_machine].flags&MACHINE_MOUSE)) { + if (! (m->flags & MACHINE_MOUSE)) { /* Skip "Internal" if machine doesn't have one. */ c++; continue; diff --git a/src/win/win_settings_machine.h b/src/win/win_settings_machine.h index 9069836..093904f 100644 --- a/src/win/win_settings_machine.h +++ b/src/win/win_settings_machine.h @@ -8,12 +8,12 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_machine.h 1.0.12 2018/11/13 + * Version: @(#)win_settings_machine.h 1.0.13 2019/04/11 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -51,14 +51,20 @@ static void machine_recalc_cpu(HWND hdlg) { HWND h; + const device_t *dev; + const machine_t *m; #ifdef USE_DYNAREC int cpu_flags; #endif int cpu_type; - cpu_type = machines[temp_machine].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + + cpu_type = m->cpu[temp_cpu_m].cpus[temp_cpu].type; #ifdef USE_DYNAREC - cpu_flags = machines[temp_machine].cpu[temp_cpu_m].cpus[temp_cpu].cpu_flags; + cpu_flags = m->cpu[temp_cpu_m].cpus[temp_cpu].flags; #endif h = GetDlgItem(hdlg, IDC_COMBO_WS); @@ -123,15 +129,24 @@ static void machine_recalc_cpu_m(HWND hdlg) { WCHAR temp[128]; + const device_t *dev; + const machine_t *m; const char *stransi; HWND h; int c = 0; + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + h = GetDlgItem(hdlg, IDC_COMBO_CPU); SendMessage(h, CB_RESETCONTENT, 0, 0); c = 0; - while (machines[temp_machine].cpu[temp_cpu_m].cpus[c].cpu_type != -1) { - stransi = machines[temp_machine].cpu[temp_cpu_m].cpus[c].name; + for (;;) { + stransi = m->cpu[temp_cpu_m].cpus[c].name; + if (stransi == NULL) + break; + mbstowcs(temp, stransi, sizeof_w(temp)); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); c++; @@ -152,12 +167,16 @@ machine_recalc_machine(HWND hdlg) WCHAR temp[128]; const char *stransi; const device_t *dev; + const machine_t *m; UDACCEL accel; HWND h; int c; + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + h = GetDlgItem(hdlg, IDC_CONFIGURE_MACHINE); - dev = machine_getdevice(temp_machine); if (dev != NULL && dev->config != NULL) EnableWindow(h, TRUE); else @@ -166,8 +185,8 @@ machine_recalc_machine(HWND hdlg) h = GetDlgItem(hdlg, IDC_COMBO_CPU_TYPE); SendMessage(h, CB_RESETCONTENT, 0, 0); c = 0; - while (machines[temp_machine].cpu[c].cpus != NULL && c < 4) { - stransi = machines[temp_machine].cpu[c].name; + while (m->cpu[c].cpus != NULL && c < 4) { + stransi = m->cpu[c].name; mbstowcs(temp, stransi, sizeof_w(temp)); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); c++; @@ -185,12 +204,12 @@ machine_recalc_machine(HWND hdlg) machine_recalc_cpu_m(hdlg); h = GetDlgItem(hdlg, IDC_MEMSPIN); - SendMessage(h, UDM_SETRANGE, 0, (machines[temp_machine].min_ram << 16) | machines[temp_machine].max_ram); + SendMessage(h, UDM_SETRANGE, 0, (m->min_ram << 16) | m->max_ram); accel.nSec = 0; - accel.nInc = machines[temp_machine].ram_granularity; + accel.nInc = m->ram_granularity; SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); - if (!(machines[temp_machine].flags & MACHINE_AT) || (machines[temp_machine].ram_granularity >= 128)) { + if (!(m->flags & MACHINE_AT) || (m->ram_granularity >= 128)) { SendMessage(h, UDM_SETPOS, 0, temp_mem_size); h = GetDlgItem(hdlg, IDC_TEXT_MB); SendMessage(h, WM_SETTEXT, 0, win_string(IDS_3334)); @@ -207,6 +226,8 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { WCHAR temp[128]; char tempA[128]; + const device_t *dev; + const machine_t *m; wchar_t *str; HWND h; int c, d; @@ -296,7 +317,8 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); d = (int)SendMessage(h, CB_GETCURSEL, 0, 0); temp_machine = list_to_mach[d]; - temp_deviceconfig |= dlg_devconf(hdlg, machine_getdevice(temp_machine)); + dev = machine_get_device_ex(temp_machine); + temp_deviceconfig |= dlg_devconf(hdlg, dev); break; case IDC_COMBO_SYNC: @@ -310,6 +332,10 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) return FALSE; case WM_SAVE_CFG: + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + #ifdef USE_DYNAREC h = GetDlgItem(hdlg, IDC_CHECK_DYNAREC); temp_dynarec = (int)SendMessage(h, BM_GETCHECK, 0, 0); @@ -325,20 +351,20 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) SendMessage(h, WM_GETTEXT, sizeof_w(temp), (LPARAM)temp); wcstombs(tempA, temp, sizeof(tempA)); sscanf(tempA, "%i", &temp_mem_size); - temp_mem_size &= ~(machines[temp_machine].ram_granularity - 1); - if (temp_mem_size < (int)machines[temp_machine].min_ram) - temp_mem_size = machines[temp_machine].min_ram; - else if (temp_mem_size > (int)machines[temp_machine].max_ram) - temp_mem_size = machines[temp_machine].max_ram; - if ((machines[temp_machine].flags & MACHINE_AT) && (machines[temp_machine].ram_granularity < 128)) + temp_mem_size &= ~(m->ram_granularity - 1); + if (temp_mem_size < (int)m->min_ram) + temp_mem_size = m->min_ram; + else if (temp_mem_size > (int)m->max_ram) + temp_mem_size = m->max_ram; + if ((m->flags & MACHINE_AT) && (m->ram_granularity < 128)) temp_mem_size *= 1024; - if (machines[temp_machine].flags & MACHINE_VIDEO) + if (m->flags & MACHINE_VIDEO) video_card = VID_INTERNAL; - if (machines[temp_machine].flags & MACHINE_MOUSE) + if (m->flags & MACHINE_MOUSE) mouse_type = MOUSE_INTERNAL; - if (machines[temp_machine].flags & MACHINE_SOUND) + if (m->flags & MACHINE_SOUND) sound_card = SOUND_INTERNAL; - if (machines[temp_machine].flags & MACHINE_HDC) + if (m->flags & MACHINE_HDC) hdc_type = HDC_INTERNAL; return FALSE; diff --git a/src/win/win_settings_network.h b/src/win/win_settings_network.h index 6915905..2490b64 100644 --- a/src/win/win_settings_network.h +++ b/src/win/win_settings_network.h @@ -8,12 +8,12 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_network.h 1.0.11 2018/11/06 + * Version: @(#)win_settings_network.h 1.0.12 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -91,11 +91,16 @@ network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) WCHAR temp[128]; const char *stransi; const device_t *dev; + const machine_t *m; HWND h; int c, d; switch (message) { case WM_INITDIALOG: + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + h = GetDlgItem(hdlg, IDC_COMBO_NET_TYPE); c = d = 0; for (;;) { @@ -149,8 +154,7 @@ network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if (stransi == NULL) break; dev = network_card_getdevice(c); - if (!network_card_available(c) || - !device_is_valid(dev, machines[temp_machine].flags)) { + if (!network_card_available(c) || !device_is_valid(dev, m->flags)) { c++; continue; } diff --git a/src/win/win_settings_periph.h b/src/win/win_settings_periph.h index cb698f0..d400651 100644 --- a/src/win/win_settings_periph.h +++ b/src/win/win_settings_periph.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_periph.h 1.0.17 2019/01/15 + * Version: @(#)win_settings_periph.h 1.0.18 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,7 +50,7 @@ static int hdc_to_list[20], /* Populate the HDC combo. */ static void -recalc_scsi_list(HWND hdlg) +recalc_scsi_list(const machine_t *m, HWND hdlg) { WCHAR temp[128]; char tempA[128]; @@ -69,8 +69,7 @@ recalc_scsi_list(HWND hdlg) dev = scsi_card_getdevice(c); - if (!scsi_card_available(c) || - !device_is_valid(dev, machines[temp_machine].flags)) { + if (!scsi_card_available(c) || !device_is_valid(dev, m->flags)) { c++; continue; } @@ -96,7 +95,7 @@ recalc_scsi_list(HWND hdlg) /* Populate the HDC combo. */ static void -recalc_hdc_list(HWND hdlg) +recalc_hdc_list(const machine_t *m, HWND hdlg) { WCHAR temp[128]; char tempA[128]; @@ -116,8 +115,7 @@ recalc_hdc_list(HWND hdlg) dev = hdc_get_device(c); - if (!hdc_available(c) || - !device_is_valid(dev, machines[temp_machine].flags)) { + if (!hdc_available(c) || !device_is_valid(dev, m->flags)) { c++; continue; } @@ -125,7 +123,7 @@ recalc_hdc_list(HWND hdlg) if (c == 0) { SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_NONE)); } else if (c == 1) { - if (! (machines[temp_machine].flags&MACHINE_HDC)) { + if (! (m->flags & MACHINE_HDC)) { /* Skip "Internal" if machine doesn't have one. */ c++; continue; @@ -158,12 +156,17 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) WCHAR temp[128]; const char *stransi; const device_t *dev; + const machine_t *m; int c, d; HWND h; switch (message) { case WM_INITDIALOG: - recalc_scsi_list(hdlg); + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + + recalc_scsi_list(m, hdlg); h = GetDlgItem(hdlg, IDC_CONFIGURE_SCSI); if (scsi_card_has_config(temp_scsi_card)) @@ -171,7 +174,7 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) else EnableWindow(h, FALSE); - recalc_hdc_list(hdlg); + recalc_hdc_list(m, hdlg); h = GetDlgItem(hdlg, IDC_CONFIGURE_HDC); if (hdc_has_config(temp_hdc_type)) @@ -179,7 +182,7 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) else EnableWindow(h, FALSE); - if (machines[temp_machine].flags & MACHINE_AT) { + if (m->flags & MACHINE_AT) { h = GetDlgItem(hdlg, IDC_CHECK_IDE_TER); EnableWindow(h, TRUE); SendMessage(h, BM_SETCHECK, temp_ide_ter, 0); diff --git a/src/win/win_settings_remov.h b/src/win/win_settings_remov.h index 1fc8167..6927eb2 100644 --- a/src/win/win_settings_remov.h +++ b/src/win/win_settings_remov.h @@ -8,12 +8,12 @@ * * Implementation of the "Removable Devices" dialog. * - * Version: @(#)win_settings_remov.h 1.0.12 2018/10/24 + * Version: @(#)win_settings_remov.h 1.0.13 2019/03/21 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -723,7 +723,7 @@ zip_track_all(void) static WIN_RESULT CALLBACK rmv_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; + HWND h = NULL; int old_sel = 0; int assign = 0; int b; diff --git a/src/win/win_settings_sound.h b/src/win/win_settings_sound.h index 2cb6869..a41ba6f 100644 --- a/src/win/win_settings_sound.h +++ b/src/win/win_settings_sound.h @@ -8,12 +8,12 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_sound.h 1.0.14 2018/10/25 + * Version: @(#)win_settings_sound.h 1.0.15 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -81,11 +81,16 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) char tempA[128]; const char *stransi; const device_t *dev; + const machine_t *m; HWND h; int c, d; switch (message) { case WM_INITDIALOG: + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + h = GetDlgItem(hdlg, IDC_COMBO_SOUND); c = d = 0; for (;;) { @@ -95,7 +100,7 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) dev = sound_card_getdevice(c); if (!sound_card_available(c) || - !device_is_valid(dev, machines[temp_machine].flags)) { + !device_is_valid(dev, m->flags)) { c++; continue; } @@ -105,7 +110,7 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_NONE)); } else if (c == 1) { - if (! (machines[temp_machine].flags&MACHINE_SOUND)) { + if (! (m->flags & MACHINE_SOUND)) { c++; continue; } @@ -246,7 +251,10 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) break; case IDC_CONFIGURE_MPU401: - temp_deviceconfig |= dlg_devconf(hdlg, (machines[temp_machine].flags & MACHINE_MCA) ? + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + temp_deviceconfig |= dlg_devconf(hdlg, (m->flags & MACHINE_MCA) ? &mpu401_mca_device : &mpu401_device); break; } diff --git a/src/win/win_settings_video.h b/src/win/win_settings_video.h index b11dccd..ebc4919 100644 --- a/src/win/win_settings_video.h +++ b/src/win/win_settings_video.h @@ -8,12 +8,12 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_video.h 1.0.10 2018/10/28 + * Version: @(#)win_settings_video.h 1.0.11 2019/04/08 * * Authors: Fred N. van Kempen, * Miran Grca, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -53,10 +53,15 @@ video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) WCHAR temp[128]; const char *stransi; const device_t *dev; + const machine_t *m; int c, d; int vid; HWND h; + /* Get info about the selected machine. */ + dev = machine_get_device_ex(temp_machine); + m = (machine_t *)dev->mach_info; + switch (message) { case WM_INITDIALOG: /* Clear the video cards combo. */ @@ -73,8 +78,7 @@ video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if (stransi == NULL) break; /* Skip "internal" if machine doesn't have it. */ - if (c == VID_INTERNAL && - !(machines[temp_machine].flags&MACHINE_VIDEO)) { + if (c == VID_INTERNAL && !(m->flags & MACHINE_VIDEO)) { c++; continue; } @@ -88,7 +92,7 @@ video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) /* Translate "Internal". */ wcscpy(temp, get_string(IDS_INTERNAL)); } else if (video_card_available(c) && - device_is_valid(dev, machines[temp_machine].flags)) { + device_is_valid(dev, m->flags)) { sprintf(tempA, "[%s] %s", device_get_bus_name(dev), video_card_getname(c)); @@ -117,13 +121,13 @@ video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } /* Machine with fixed video card have this disabled. */ - EnableWindow(h, machines[temp_machine].fixed_vidcard ? FALSE : TRUE); + EnableWindow(h, (m->flags_fixed&MACHINE_VIDEO) ? FALSE : TRUE); /* Disable Voodoo on PCI machine? */ h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); - EnableWindow(h, (machines[temp_machine].flags & MACHINE_PCI) ? TRUE:FALSE); + EnableWindow(h, (m->flags & MACHINE_PCI) ? TRUE:FALSE); h = GetDlgItem(hdlg, IDC_CONFIGURE_VOODOO); - EnableWindow(h, ((machines[temp_machine].flags & MACHINE_PCI) && temp_voodoo) ? TRUE : FALSE); + EnableWindow(h, ((m->flags & MACHINE_PCI) && temp_voodoo) ? TRUE : FALSE); return TRUE;