From ce1c65ec8729683f6e5b464123a0ffc20d9c30a3 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 8 Jan 2025 15:45:55 -0500 Subject: [PATCH 01/65] Merge SB 1/1.5 init format Update snd_sb.c --- src/sound/snd_sb.c | 89 ++++++++++++++-------------------------------- 1 file changed, 27 insertions(+), 62 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 3213e3cf0..d83ab98a4 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -43,6 +43,9 @@ #include <86box/snd_sb.h> #include <86box/plat_unused.h> +#define SB_1 0 +#define SB_15 1 + #define SB_16_PNP_NOIDE 0 #define SB_16_PNP_IDE 1 @@ -2818,16 +2821,30 @@ sb_1_init(UNUSED(const device_t *info)) 2x0 to 2x3 -> CMS chip 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip */ - sb_t *sb = malloc(sizeof(sb_t)); - const uint16_t addr = device_get_config_hex16("base"); + sb_t *sb = malloc(sizeof(sb_t)); + uint8_t model = 0; + const uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); + switch (info->local) { + default: + case SB_1: + model = SB1; + sb->cms_enabled = 1; + break; + + case SB_15: + model = SB15; + sb->cms_enabled = device_get_config_int("cms"); + break; + } + sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) fm_driver_get(FM_YM3812, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, model, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -2843,58 +2860,6 @@ sb_1_init(UNUSED(const device_t *info)) sb->opl.priv); } - sb->cms_enabled = 1; - memset(&sb->cms, 0, sizeof(cms_t)); - io_sethandler(addr, 0x0004, - cms_read, NULL, NULL, - cms_write, NULL, NULL, - &sb->cms); - - sb->mixer_enabled = 0; - sound_add_handler(sb_get_buffer_sb2, sb); - if (sb->opl_enabled) - music_add_handler(sb_get_music_buffer_sb2, sb); - sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); - - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - - return sb; -} - -void * -sb_15_init(UNUSED(const device_t *info)) -{ - /* SB1/2 port mappings, 210h to 260h in 10h steps - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip */ - sb_t *sb = malloc(sizeof(sb_t)); - const uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); - - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - fm_driver_get(FM_YM3812, &sb->opl); - - sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); - sb_dsp_setaddr(&sb->dsp, addr); - sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); - sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - if (sb->opl_enabled) { - io_sethandler(addr + 8, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_sethandler(0x0388, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - } - - sb->cms_enabled = device_get_config_int("cms"); if (sb->cms_enabled) { memset(&sb->cms, 0, sizeof(cms_t)); io_sethandler(addr, 0x0004, @@ -4211,7 +4176,8 @@ static const device_config_t sb_config[] = { }, { .description = "0x260", - .value = 0x260 }, + .value = 0x260 + }, { .description = "" } } }, @@ -4260,7 +4226,7 @@ static const device_config_t sb_config[] = { .description = "DMA 3", .value = 3 }, - { "" } + { .description = "" } } }, { @@ -4314,8 +4280,7 @@ static const device_config_t sb15_config[] = { .description = "0x260", .value = 0x260 }, - { - .description = "" } + { .description = "" } } }, { @@ -5769,7 +5734,7 @@ const device_t sb_1_device = { .name = "Sound Blaster v1.0", .internal_name = "sb", .flags = DEVICE_ISA, - .local = 0, + .local = SB_1, .init = sb_1_init, .close = sb_close, .reset = NULL, @@ -5783,8 +5748,8 @@ const device_t sb_15_device = { .name = "Sound Blaster v1.5", .internal_name = "sb1.5", .flags = DEVICE_ISA, - .local = 0, - .init = sb_15_init, + .local = SB_15, + .init = sb_1_init, .close = sb_close, .reset = NULL, .available = NULL, From ace946259767207a2df92e38ed73d3e577e3fca4 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 8 Jan 2025 16:21:53 -0500 Subject: [PATCH 02/65] Merge SB1/SB2 init --- src/sound/snd_sb.c | 141 ++++++++++++++++----------------------------- 1 file changed, 49 insertions(+), 92 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index d83ab98a4..d26b3e716 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -45,6 +45,7 @@ #define SB_1 0 #define SB_15 1 +#define SB_2 2 #define SB_16_PNP_NOIDE 0 #define SB_16_PNP_IDE 1 @@ -2815,15 +2816,25 @@ ess_chipchat_mca_write(int port, uint8_t val, void *priv) } void * -sb_1_init(UNUSED(const device_t *info)) +sb_init(UNUSED(const device_t *info)) { - /* SB1/2 port mappings, 210h to 260h in 10h steps - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip */ - sb_t *sb = malloc(sizeof(sb_t)); - uint8_t model = 0; - const uint16_t addr = device_get_config_hex16("base"); + /* SB1.x port mappings, 210h to 260h in 10h steps: + (SB2 port mappings are 220h or 240h) + 2x0 to 2x3 -> CMS chip + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip + SB2 "CD version" also uses 250h or 260h: + 2x0 to 2x3 -> CDROM interface + 2x4 to 2x5 -> Mixer interface */ + /* My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is disabled when the + CMS chips are present. + This mirror may also exist on SB 1.5 & MCV, however I am unable to test this. It shouldn't + exist on SB 1.0 as the CMS chips are always present there. Syndicate requires this mirror + for music to play. */ + sb_t *sb = malloc(sizeof(sb_t)); + const uint16_t addr = device_get_config_hex16("base"); + uint16_t mixer_addr = 0x0000; + uint8_t model = 0; memset(sb, 0, sizeof(sb_t)); switch (info->local) { @@ -2837,6 +2848,12 @@ sb_1_init(UNUSED(const device_t *info)) model = SB15; sb->cms_enabled = device_get_config_int("cms"); break; + + case SB_2: + model = SB2; + sb->cms_enabled = device_get_config_int("cms"); + mixer_addr = device_get_config_int("mixaddr"); + break; } sb->opl_enabled = device_get_config_int("opl"); @@ -2848,8 +2865,19 @@ sb_1_init(UNUSED(const device_t *info)) sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); + + if (mixer_addr > 0x0000) + sb_ct1335_mixer_reset(sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { + // TODO: See if this applies to the SB1.5 as well + if ((!sb->cms_enabled) && (model == SB2)) { + io_sethandler(addr, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + } io_sethandler(addr + 8, 0x0002, sb->opl.read, NULL, NULL, sb->opl.write, NULL, NULL, @@ -2868,7 +2896,15 @@ sb_1_init(UNUSED(const device_t *info)) &sb->cms); } - sb->mixer_enabled = 0; + if (mixer_addr > 0x000) { + sb->mixer_enabled = 1; + io_sethandler(mixer_addr + 4, 0x0002, + sb_ct1335_mixer_read, NULL, NULL, + sb_ct1335_mixer_write, NULL, NULL, + sb); + } else + sb->mixer_enabled = 0; + sound_add_handler(sb_get_buffer_sb2, sb); if (sb->opl_enabled) music_add_handler(sb_get_music_buffer_sb2, sb); @@ -2916,85 +2952,6 @@ sb_mcv_init(UNUSED(const device_t *info)) return sb; } -void * -sb_2_init(UNUSED(const device_t *info)) -{ - /* SB2 port mappings, 220h or 240h. - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip - "CD version" also uses 250h or 260h for - 2x0 to 2x3 -> CDROM interface - 2x4 to 2x5 -> Mixer interface */ - /* My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is disabled when the - CMS chips are present. - This mirror may also exist on SB 1.5 & MCV, however I am unable to test this. It shouldn't - exist on SB 1.0 as the CMS chips are always present there. Syndicate requires this mirror - for music to play.*/ - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - uint16_t mixer_addr = device_get_config_int("mixaddr"); - - memset(sb, 0, sizeof(sb_t)); - - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - fm_driver_get(FM_YM3812, &sb->opl); - - sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb); - sb_dsp_setaddr(&sb->dsp, addr); - sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); - sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - if (mixer_addr > 0x000) - sb_ct1335_mixer_reset(sb); - - sb->cms_enabled = device_get_config_int("cms"); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - if (sb->opl_enabled) { - if (!sb->cms_enabled) { - io_sethandler(addr, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - } - io_sethandler(addr + 8, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_sethandler(0x0388, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - } - - if (sb->cms_enabled) { - memset(&sb->cms, 0, sizeof(cms_t)); - io_sethandler(addr, 0x0004, - cms_read, NULL, NULL, - cms_write, NULL, NULL, - &sb->cms); - } - - if (mixer_addr > 0x000) { - sb->mixer_enabled = 1; - io_sethandler(mixer_addr + 4, 0x0002, - sb_ct1335_mixer_read, NULL, NULL, - sb_ct1335_mixer_write, NULL, NULL, - sb); - } else - sb->mixer_enabled = 0; - sound_add_handler(sb_get_buffer_sb2, sb); - if (sb->opl_enabled) - music_add_handler(sb_get_music_buffer_sb2, sb); - sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); - - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - - return sb; -} - static uint8_t sb_pro_v1_opl_read(uint16_t port, void *priv) { @@ -5735,7 +5692,7 @@ const device_t sb_1_device = { .internal_name = "sb", .flags = DEVICE_ISA, .local = SB_1, - .init = sb_1_init, + .init = sb_init, .close = sb_close, .reset = NULL, .available = NULL, @@ -5749,7 +5706,7 @@ const device_t sb_15_device = { .internal_name = "sb1.5", .flags = DEVICE_ISA, .local = SB_15, - .init = sb_1_init, + .init = sb_init, .close = sb_close, .reset = NULL, .available = NULL, @@ -5776,8 +5733,8 @@ const device_t sb_2_device = { .name = "Sound Blaster v2.0", .internal_name = "sb2.0", .flags = DEVICE_ISA, - .local = 0, - .init = sb_2_init, + .local = SB_2, + .init = sb_init, .close = sb_close, .reset = NULL, .available = NULL, From a4d34661ea7b1b82f5280e99f57d75c9204e403b Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 8 Jan 2025 16:53:27 -0500 Subject: [PATCH 03/65] malloc to calloc in snd_sb --- src/sound/snd_sb.c | 66 ++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index d26b3e716..9a44d8e98 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -2831,11 +2831,10 @@ sb_init(UNUSED(const device_t *info)) This mirror may also exist on SB 1.5 & MCV, however I am unable to test this. It shouldn't exist on SB 1.0 as the CMS chips are always present there. Syndicate requires this mirror for music to play. */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); const uint16_t addr = device_get_config_hex16("base"); uint16_t mixer_addr = 0x0000; uint8_t model = 0; - memset(sb, 0, sizeof(sb_t)); switch (info->local) { default: @@ -2922,8 +2921,7 @@ sb_mcv_init(UNUSED(const device_t *info)) /* SB1/2 port mappings, 210h to 260h in 10h steps 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip */ - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) @@ -2981,9 +2979,8 @@ sb_pro_v1_init(UNUSED(const device_t *info)) 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) 2x0+10 to 2x0+13 CDROM interface. */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) { @@ -3044,9 +3041,8 @@ sb_pro_v2_init(UNUSED(const device_t *info)) 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) 2x0+10 to 2x0+13 CDROM interface. */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) @@ -3098,8 +3094,7 @@ sb_pro_mcv_init(UNUSED(const device_t *info)) 2x4 to 2x5 -> Mixer interface 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) */ - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); @@ -3127,8 +3122,7 @@ sb_pro_mcv_init(UNUSED(const device_t *info)) static void * sb_pro_compat_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); fm_driver_get(FM_YMF262, &sb->opl); @@ -3141,8 +3135,7 @@ sb_pro_compat_init(UNUSED(const device_t *info)) if (sb->opl_enabled) music_add_handler(sb_get_music_buffer_sbpro, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, 1); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3152,12 +3145,10 @@ sb_pro_compat_init(UNUSED(const device_t *info)) static void * sb_16_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); const uint16_t addr = device_get_config_hex16("base"); const uint16_t mpu_addr = device_get_config_hex16("base401"); - memset(sb, 0x00, sizeof(sb_t)); - sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) fm_driver_get((int) (intptr_t) info->local, &sb->opl); @@ -3199,8 +3190,7 @@ sb_16_init(UNUSED(const device_t *info)) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); if (mpu_addr) { - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART, device_get_config_int("receive_input401")); } else @@ -3220,8 +3210,7 @@ sb_16_init(UNUSED(const device_t *info)) static void * sb_16_reply_mca_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0x00, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); @@ -3240,8 +3229,7 @@ sb_16_reply_mca_init(UNUSED(const device_t *info)) if (device_get_config_int("control_pc_speaker")) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3275,8 +3263,7 @@ sb_16_pnp_ide_available(void) static void * sb_16_pnp_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0x00, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->pnp = 1; @@ -3295,8 +3282,7 @@ sb_16_pnp_init(UNUSED(const device_t *info)) if (device_get_config_int("control_pc_speaker")) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3379,8 +3365,7 @@ sb_vibra16xv_available(void) static void * sb_vibra16_pnp_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0x00, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->pnp = 1; @@ -3401,8 +3386,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) if (device_get_config_int("control_pc_speaker")) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3480,8 +3464,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) static void * sb_16_compat_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); fm_driver_get(FM_YMF262, &sb->opl); @@ -3496,7 +3479,7 @@ sb_16_compat_init(const device_t *info) sound_add_handler(sb_get_buffer_sb16_awe32, sb); music_add_handler(sb_get_music_buffer_sb16_awe32, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, (int) (intptr_t) info->local); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3559,7 +3542,7 @@ sb_awe64_gold_available(void) static void * sb_awe32_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); uint16_t mpu_addr = device_get_config_hex16("base401"); uint16_t emu_addr = device_get_config_hex16("emu_base"); @@ -3609,7 +3592,7 @@ sb_awe32_init(UNUSED(const device_t *info)) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); if (mpu_addr) { - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART, device_get_config_int("receive_input401")); @@ -3632,11 +3615,9 @@ sb_awe32_init(UNUSED(const device_t *info)) static void * sb_goldfinch_init(const device_t *info) { - goldfinch_t *goldfinch = malloc(sizeof(goldfinch_t)); + goldfinch_t *goldfinch = calloc(1, sizeof(goldfinch_t)); int onboard_ram = device_get_config_int("onboard_ram"); - memset(goldfinch, 0x00, sizeof(goldfinch_t)); - wavetable_add_handler(sb_get_wavetable_buffer_goldfinch, goldfinch); emu8k_init(&goldfinch->emu8k, 0, onboard_ram); @@ -3680,11 +3661,9 @@ sb_goldfinch_init(const device_t *info) static void * sb_awe32_pnp_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); int onboard_ram = device_get_config_int("onboard_ram"); - memset(sb, 0x00, sizeof(sb_t)); - sb->pnp = 1; sb->opl_enabled = 1; @@ -3705,8 +3684,7 @@ sb_awe32_pnp_init(const device_t *info) if (device_get_config_int("control_pc_speaker")) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&sb->dsp, sb->mpu); From cdf67d015fe67e4fe4266aa7908545c8d089d205 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 8 Jan 2025 17:28:55 -0500 Subject: [PATCH 04/65] Correct SB2/SB2CD(OmniCD) IO ranges --- src/sound/snd_sb.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 9a44d8e98..edf65fa3e 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -4308,10 +4308,6 @@ static const device_config_t sb2_config[] = { .description = "0x240", .value = 0x240 }, - { - .description = "0x260", - .value = 0x260 - }, { .description = "" } } }, @@ -4328,14 +4324,6 @@ static const device_config_t sb2_config[] = { .description = "Disabled", .value = 0 }, - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x240", - .value = 0x240 - }, { .description = "0x250", .value = 0x250 From 1244b61d8b620771895569b182c3ad51351f899b Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 8 Jan 2025 20:55:22 -0500 Subject: [PATCH 05/65] Cleaning --- src/sound/snd_sb.c | 14 +++++++------- src/sound/snd_sb_dsp.c | 32 ++++++++++++++++---------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index edf65fa3e..13beba3d6 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -419,7 +419,7 @@ sb_get_music_buffer_sb16_awe32(int32_t *buffer, const int len, void *priv) const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; const int dsp_rec_pos = sb->dsp.record_pos_write; double bass_treble; - const int32_t *opl_buf = NULL; + const int32_t *opl_buf = NULL; if (sb->opl_enabled) opl_buf = sb->opl.update(sb->opl.priv); @@ -1812,8 +1812,8 @@ sb_mcv_read(int port, void *priv) void sb_mcv_write(int port, uint8_t val, void *priv) { - uint16_t addr; - sb_t *sb = (sb_t *) priv; + uint16_t addr = 0; + sb_t *sb = (sb_t *) priv; if (port < 0x102) return; @@ -1876,8 +1876,8 @@ sb_pro_mcv_read(int port, void *priv) static void sb_pro_mcv_write(int port, uint8_t val, void *priv) { - uint16_t addr; - sb_t *sb = (sb_t *) priv; + uint16_t addr = 0; + sb_t *sb = (sb_t *) priv; if (port < 0x102) return; @@ -1947,8 +1947,8 @@ sb_16_reply_mca_read(int port, void *priv) static void sb_16_reply_mca_write(const int port, const uint8_t val, void *priv) { - uint16_t addr; - sb_t *sb = (sb_t *) priv; + uint16_t addr = 0; + sb_t *sb = (sb_t *) priv; if (port < 0x102) return; diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 2cabde8cc..f9e481095 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -1836,31 +1836,31 @@ sb_do_reset(sb_dsp_t *dsp, const uint8_t v) } void -sb_write(uint16_t a, uint8_t v, void *priv) +sb_write(uint16_t addr, uint8_t val, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *) priv; - sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, a, v); + sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((a & 0xF) != 0xE))) - a &= 0xfffe; + if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xE))) + addr &= 0xfffe; - switch (a & 0xF) { + switch (addr & 0xF) { case 6: /* Reset */ - sb_do_reset(dsp, v); + sb_do_reset(dsp, val); - if (!(v & 2) && (dsp->espcm_fifo_reset & 2)) { + if (!(val & 2) && (dsp->espcm_fifo_reset & 2)) { fifo_reset(dsp->espcm_fifo); } - dsp->espcm_fifo_reset = v; + dsp->espcm_fifo_reset = val; dsp->uart_midi = 0; dsp->uart_irq = 0; dsp->onebyte_midi = 0; return; case 0xC: /* Command/data write */ if (dsp->uart_midi || dsp->onebyte_midi) { - midi_raw_out_byte(v); + midi_raw_out_byte(val); dsp->onebyte_midi = 0; return; } @@ -1873,8 +1873,8 @@ sb_write(uint16_t a, uint8_t v, void *priv) return; } if (dsp->sb_data_stat == -1) { - dsp->sb_command = v; - if (v == 0x01) + dsp->sb_command = val; + if (val == 0x01) sb_add_data(dsp, 0); dsp->sb_data_stat++; if (IS_AZTECH(dsp)) { @@ -1901,7 +1901,7 @@ sb_write(uint16_t a, uint8_t v, void *priv) } } } else { - dsp->sb_data[dsp->sb_data_stat++] = v; + dsp->sb_data[dsp->sb_data_stat++] = val; } if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) { sb_exec_command(dsp); @@ -1920,17 +1920,17 @@ sb_write(uint16_t a, uint8_t v, void *priv) } uint8_t -sb_read(uint16_t a, void *priv) +sb_read(uint16_t addr, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *) priv; uint8_t ret = 0x00; /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((a & 0xF) != 0xF))) + if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xF))) /* Exception: ESS AudioDrive does not alias port base+0xf */ - a &= 0xfffe; + addr &= 0xfffe; - switch (a & 0xf) { + switch (addr & 0xf) { case 0x6: if (IS_ESS(dsp)) { ret = (dsp->espcm_fifo_reset & 0x03) | 0x08 | (dsp->activity & 0xe0); From 3d55d937157c79e2149a057098acff3dce421582 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 8 Jan 2025 21:58:45 -0500 Subject: [PATCH 06/65] Make sb_dsp_versions more readable --- src/sound/snd_sb_dsp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index f9e481095..6666e7317 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -78,7 +78,19 @@ static int sb_commands[256] = { }; char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; -uint16_t sb_dsp_versions[] = { 0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40c, 0x40d, 0x410 }; +uint16_t sb_dsp_versions[] = { + 0, /* Pad */ + 0, /* SADLIB - No DSP */ + 0x105, /* SB1 - DSP v1.05 */ + 0x200, /* SB15 - DSP v2.00 */ + 0x201, /* SB2 - DSP v2.01 - needed for high-speed DMA */ + 0x300, /* SBPRO - DSP v3.00 */ + 0x302, /* SBPRO2 - DSP v3.02 + OPL3 */ + 0x405, /* SB16 - DSP v4.05 + OPL3 */ + 0x40c, /* SBAWE32 - DSP v4.12 + OPL3 */ + 0x40d, /* SBAWE32PNP - DSP v4.13 + OPL3 */ + 0x410 /* SBAWE64 - DSP v4.16 + OPL3 */ +}; /*These tables were 'borrowed' from DOSBox*/ int8_t scaleMap4[64] = { From a0442233625fadf3d7dba60e0a4e688879ddb0ff Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 9 Jan 2025 01:07:26 -0500 Subject: [PATCH 07/65] A few bug fixes according to docs and fw Also skeleton support for DSP versions --- src/include/86box/snd_sb.h | 22 ++--- src/sound/snd_azt2316a.c | 2 +- src/sound/snd_cmi8x38.c | 4 +- src/sound/snd_optimc.c | 2 +- src/sound/snd_pas16.c | 2 +- src/sound/snd_sb.c | 52 ++++++------ src/sound/snd_sb_dsp.c | 162 +++++++++++++++++++++---------------- 7 files changed, 137 insertions(+), 109 deletions(-) diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index a85f1515c..06fbbfa3b 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -29,15 +29,19 @@ enum { SADLIB = 1, /* No DSP */ - SB1, /* DSP v1.05 */ - SB15, /* DSP v2.00 */ - SB2, /* DSP v2.01 - needed for high-speed DMA */ - SBPRO, /* DSP v3.00 */ - SBPRO2, /* DSP v3.02 + OPL3 */ - SB16, /* DSP v4.05 + OPL3 */ - SBAWE32, /* DSP v4.12 + OPL3 */ - SBAWE32PNP, /* DSP v4.13 + OPL3 */ - SBAWE64 /* DSP v4.16 + OPL3 */ + SB_DSP_105, /* DSP v1.05, Original CT1320 (Also known as CT1310) */ + SB_DSP_200, /* DSP v2.00 */ + SB_DSP_201, /* DSP v2.01 - needed for high-speed DMA, Seen on CT1350B with CT1336 */ + SB_DSP_202, /* DSP v2.02 - Seen on CT1350B with CT1336A */ + SBPRO_DSP_300, /* DSP v3.00 */ + SBPRO2_DSP_302, /* DSP v3.02 + OPL3 */ + SB16_DSP_404, /* DSP v4.05 + OPL3 */ + SB16_DSP_405, /* DSP v4.05 + OPL3 */ + SB16_DSP_406, /* DSP v4.06 + OPL3 */ + SB16_DSP_411, /* DSP v4.11 + OPL3 */ + SBAWE32_DSP_412, /* DSP v4.12 + OPL3 */ + SBAWE32_DSP_413, /* DSP v4.13 + OPL3 */ + SBAWE64_DSP_416 /* DSP v4.16 + OPL3 */ }; /* SB 2.0 CD version */ diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index a3a763244..cf05203f3 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -1238,7 +1238,7 @@ azt_init(const device_t *info) fm_driver_get(FM_YMF262, &azt2316a->sb->opl); sb_dsp_set_real_opl(&azt2316a->sb->dsp, 1); - sb_dsp_init(&azt2316a->sb->dsp, SBPRO2, azt2316a->type, azt2316a); + sb_dsp_init(&azt2316a->sb->dsp, SBPRO2_DSP_302, azt2316a->type, azt2316a); sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); diff --git a/src/sound/snd_cmi8x38.c b/src/sound/snd_cmi8x38.c index 8ba344ec9..833124bb2 100644 --- a/src/sound/snd_cmi8x38.c +++ b/src/sound/snd_cmi8x38.c @@ -497,7 +497,7 @@ cmi8x38_sb_mixer_write(uint16_t addr, uint8_t val, void *priv) /* Set TDMA channels if auto-detection is enabled. */ if ((dev->io_regs[0x27] & 0x01) && (mixer->index == 0x81)) { dev->tdma_8 = dev->sb->dsp.sb_8_dmanum; - if (dev->sb->dsp.sb_type >= SB16) + if (dev->sb->dsp.sb_type >= SB16_DSP_404) dev->tdma_16 = dev->sb->dsp.sb_16_dmanum; } } else { @@ -879,7 +879,7 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) dev->sb->dsp.sbleftright_default = !!(val & 0x02); /* Enable or disable SB16 mode. */ - dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2 : SB16; + dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2_DSP_302 : SB16_DSP_405; break; case 0x22: diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index 9c8b0b460..d69986d98 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -394,7 +394,7 @@ optimc_init(const device_t *info) optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262; sb_dsp_set_real_opl(&optimc->sb->dsp, optimc->fm_type != FM_YMF278B); - sb_dsp_init(&optimc->sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, optimc); + sb_dsp_init(&optimc->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, optimc); sb_dsp_setaddr(&optimc->sb->dsp, optimc->cur_addr); sb_dsp_setirq(&optimc->sb->dsp, optimc->cur_irq); sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma); diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index f9bab8d87..fab2a6a75 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -2314,7 +2314,7 @@ pas16_init(const device_t *info) pas16->has_scsi = (!pas16->type) || (pas16->type == 0x0f); fm_driver_get(FM_YMF262, &pas16->opl); sb_dsp_set_real_opl(&pas16->dsp, 1); - sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16); + sb_dsp_init(&pas16->dsp, SB_DSP_201, SB_SUBTYPE_DEFAULT, pas16); pas16->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(pas16->mpu, 0, sizeof(mpu_t)); mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 13beba3d6..016e50c40 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -292,7 +292,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv) if (!sb->opl_enabled) return; - if (sb->dsp.sb_type == SBPRO) { + if (sb->dsp.sb_type == SBPRO_DSP_300) { opl_buf = sb->opl.update(sb->opl.priv); opl2_buf = sb->opl2.update(sb->opl2.priv); } else @@ -304,7 +304,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv) out_l = 0.0; out_r = 0.0; - if (sb->dsp.sb_type == SBPRO) { + if (sb->dsp.sb_type == SBPRO_DSP_300) { /* Two chips for LEFT and RIGHT channels. Each chip stores data into the LEFT channel only (no sample alternating.) */ out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375; @@ -326,7 +326,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv) } sb->opl.reset_buffer(sb->opl.priv); - if (sb->dsp.sb_type == SBPRO) + if (sb->dsp.sb_type == SBPRO_DSP_300) sb->opl2.reset_buffer(sb->opl2.priv); } @@ -1161,7 +1161,7 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) break; case 0xff: - if ((sb->dsp.sb_type > SBAWE32) && !sb->dsp.sb_16_dma_supported) { + if ((sb->dsp.sb_type > SBAWE32_DSP_412) && !sb->dsp.sb_16_dma_supported) { /* Bit 5: High DMA channel enabled (0 = yes, 1 = no); Bit 2: ????; @@ -1345,7 +1345,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) /* http://the.earth.li/~tfm/oldpage/sb_mixer.html - 0x10, 0x20, 0x80. */ const uint8_t temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | ((sb->dsp.sb_irq401) ? 4 : 0); - if (sb->dsp.sb_type >= SBAWE32) + if (sb->dsp.sb_type >= SBAWE32_DSP_412) ret = temp | 0x80; else ret = temp | 0x40; @@ -1390,7 +1390,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) - Register FF = FF: Volume playback normal. - Register FF = Not FF: Volume playback low unless bit 6 of 82h is set. */ - if (sb->dsp.sb_type > SBAWE32) + if (sb->dsp.sb_type > SBAWE32_DSP_412) ret = mixer->regs[mixer->index]; break; @@ -2223,7 +2223,7 @@ sb_16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void break; case 2: /* Reserved (16) / WaveTable (32+) */ - if (sb->dsp.sb_type > SB16) + if (sb->dsp.sb_type >= SBAWE32_DSP_412) emu8k_change_addr(&sb->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); break; @@ -2839,17 +2839,17 @@ sb_init(UNUSED(const device_t *info)) switch (info->local) { default: case SB_1: - model = SB1; + model = SB_DSP_105; sb->cms_enabled = 1; break; case SB_15: - model = SB15; + model = SB_DSP_200; sb->cms_enabled = device_get_config_int("cms"); break; case SB_2: - model = SB2; + model = SB_DSP_201; sb->cms_enabled = device_get_config_int("cms"); mixer_addr = device_get_config_int("mixaddr"); break; @@ -2871,7 +2871,7 @@ sb_init(UNUSED(const device_t *info)) /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { // TODO: See if this applies to the SB1.5 as well - if ((!sb->cms_enabled) && (model == SB2)) { + if ((!sb->cms_enabled) && ((model == SB_DSP_201) || (model == SB_DSP_202))) { io_sethandler(addr, 0x0002, sb->opl.read, NULL, NULL, sb->opl.write, NULL, NULL, @@ -2928,7 +2928,7 @@ sb_mcv_init(UNUSED(const device_t *info)) fm_driver_get(FM_YM3812, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SB_DSP_105, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, 0); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -2991,7 +2991,7 @@ sb_pro_v1_init(UNUSED(const device_t *info)) } sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO_DSP_300, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3049,7 +3049,7 @@ sb_pro_v2_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3100,7 +3100,7 @@ sb_pro_mcv_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_ct1345_mixer_reset(sb); sb->mixer_enabled = 1; @@ -3127,7 +3127,7 @@ sb_pro_compat_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_ct1345_mixer_reset(sb); sb->mixer_enabled = 1; @@ -3154,7 +3154,7 @@ sb_16_init(UNUSED(const device_t *info)) fm_driver_get((int) (intptr_t) info->local, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, (info->local == FM_YMF289B) ? SBAWE32PNP : SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, (info->local == FM_YMF289B) ? SBAWE32_DSP_413 : SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3216,7 +3216,7 @@ sb_16_reply_mca_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); @@ -3270,7 +3270,7 @@ sb_16_pnp_init(UNUSED(const device_t *info)) sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); - sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); @@ -3373,7 +3373,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, (info->local == SB_VIBRA16XV) ? SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, (info->local == SB_VIBRA16XV) ? SBAWE64_DSP_416 : SBAWE32_DSP_413, SB_SUBTYPE_DEFAULT, sb); /* The ViBRA 16XV does 16-bit DMA through 8-bit DMA. */ sb_dsp_setdma16_supported(&sb->dsp, info->local != SB_VIBRA16XV); sb_ct1745_mixer_reset(sb); @@ -3469,7 +3469,7 @@ sb_16_compat_init(const device_t *info) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); @@ -3555,7 +3555,7 @@ sb_awe32_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBAWE32, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBAWE32_DSP_412, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3670,7 +3670,7 @@ sb_awe32_pnp_init(const device_t *info) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_init(&sb->dsp, (info->local >= SB_AWE64_VALUE) ? - SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb); + SBAWE64_DSP_416 : SBAWE32_DSP_413, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); @@ -3803,7 +3803,7 @@ ess_x688_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setaddr(&ess->dsp, addr); sb_dsp_setirq(&ess->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&ess->dsp, device_get_config_int("dma")); @@ -3914,7 +3914,7 @@ ess_x688_pnp_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setdma16_supported(&ess->dsp, 0); ess_mixer_reset(ess); @@ -4000,7 +4000,7 @@ ess_x688_mca_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setdma16_supported(&ess->dsp, 0); ess_mixer_reset(ess); diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 6666e7317..9ce0b9fb7 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -77,25 +77,33 @@ static int sb_commands[256] = { -1, -1, 0, 0, -1, -1, -1, -1, -1, 1, 2, -1, -1, -1, -1, 0 }; +#if 0 +// Currently unused, here for reference if ever needed +char sb202_copyright[] = "COPYRIGHT(C) CREATIVE TECHNOLOGY PTE. LTD. (1991) " +#endif char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; uint16_t sb_dsp_versions[] = { - 0, /* Pad */ - 0, /* SADLIB - No DSP */ - 0x105, /* SB1 - DSP v1.05 */ - 0x200, /* SB15 - DSP v2.00 */ - 0x201, /* SB2 - DSP v2.01 - needed for high-speed DMA */ - 0x300, /* SBPRO - DSP v3.00 */ - 0x302, /* SBPRO2 - DSP v3.02 + OPL3 */ - 0x405, /* SB16 - DSP v4.05 + OPL3 */ - 0x40c, /* SBAWE32 - DSP v4.12 + OPL3 */ - 0x40d, /* SBAWE32PNP - DSP v4.13 + OPL3 */ - 0x410 /* SBAWE64 - DSP v4.16 + OPL3 */ + 0, /* Pad */ + 0, /* SADLIB - No DSP */ + 0x105, /* SB_DSP_105 - SB1/1.5, DSP v1.05 */ + 0x200, /* SB_DSP_200 - SB1.5/2, DSP v2.00 */ + 0x201, /* SB_DSP_201 - SB1.5/2, DSP v2.01 - needed for high-speed DMA */ + 0x202, /* SB_DSP_202 - SB2, DSP v2.02 */ + 0x300, /* SB_PRO_DSP_300 - SB Pro, DSP v3.00 */ + 0x302, /* SBPRO2_DSP_302 - SB Pro 2, DSP v3.02 + OPL3 */ + 0x404, /* SB16_DSP_404 - DSP v4.04 + OPL3 */ + 0x405, /* SB16_405 - DSP v4.05 + OPL3 */ + 0x406, /* SB16_406 - DSP v4.06 + OPL3 */ + 0x40b, /* SB16_411 - DSP v4.11 + OPL3 */ + 0x40c, /* SBAWE32 - DSP v4.12 + OPL3 */ + 0x40d, /* SBAWE32PNP - DSP v4.13 + OPL3 */ + 0x410 /* SBAWE64 - DSP v4.16 + OPL3 */ }; /*These tables were 'borrowed' from DOSBox*/ int8_t scaleMap4[64] = { - 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, - 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, + 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, + 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 }; @@ -537,7 +545,7 @@ sb_doreset(sb_dsp_t *dsp) sb_commands[8] = 1; sb_commands[9] = 1; } else { - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) sb_commands[8] = 1; else sb_commands[8] = -1; @@ -1218,7 +1226,7 @@ sb_exec_command(sb_dsp_t *dsp) /* Update 8051 ram with the current DSP command. See https://github.com/joncampbell123/dosbox-x/issues/1044 */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_8051_ram[0x20] = dsp->sb_command; } @@ -1244,15 +1252,15 @@ sb_exec_command(sb_dsp_t *dsp) switch (dsp->sb_command) { case 0x01: /* ???? */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) dsp->asp_data_len = dsp->sb_data[0] + (dsp->sb_data[1] << 8) + 1; break; case 0x03: /* ASP status */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) sb_add_data(dsp, 0); break; case 0x04: /* ASP set mode register */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_asp_mode = dsp->sb_data[0]; if (dsp->sb_asp_mode & 4) dsp->sb_asp_ram_index = 0; @@ -1260,7 +1268,7 @@ sb_exec_command(sb_dsp_t *dsp) } /* else DSP Status (Obsolete) */ break; case 0x05: /* ASP set codec parameter */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_dsp_log("SB16 ASP unknown codec params %02X, %02X\n", dsp->sb_data[0], dsp->sb_data[1]); } break; @@ -1290,9 +1298,9 @@ sb_exec_command(sb_dsp_t *dsp) sb_dsp_log("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); /* 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen */ break; } - if (dsp->sb_type == SBAWE64) /* AWE64 has no ASP or a socket for it */ + if (dsp->sb_type == SBAWE64_DSP_416) /* AWE64 has no ASP or a socket for it */ sb_add_data(dsp, 0xFF); - else if (dsp->sb_type >= SB16) + else if (dsp->sb_type >= SB16_DSP_404) sb_add_data(dsp, 0x18); break; case 0x09: /* AZTECH mode set */ @@ -1308,7 +1316,7 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x0E: /* ASP set register */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory write */ @@ -1327,7 +1335,7 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x0F: /* ASP get register */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory read */ if (dsp->sb_asp_mode & 8) dsp->sb_asp_ram_index = 0; @@ -1371,11 +1379,11 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x1C: /* 8-bit autoinit DMA output */ - if (dsp->sb_type >= SB15) + if (dsp->sb_type >= SB_DSP_200) sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x1F: /* 2-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { + if (dsp->sb_type >= SB_DSP_200) { sb_start_dma(dsp, 1, 1, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); dsp->sb_8_length--; @@ -1400,7 +1408,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0x28: /* Direct ADC, 8-bit (Burst) */ break; case 0x2C: /* 8-bit autoinit DMA input */ - if (dsp->sb_type >= SB15) + if (dsp->sb_type >= SB_DSP_200) sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); break; case 0x30: /* MIDI Polling mode input */ @@ -1417,7 +1425,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0x33: /* MIDI Read Timestamp Interrupt */ break; case 0x34: /* MIDI In poll */ - if (dsp->sb_type < SB2) + if (dsp->sb_type < SB_DSP_200) break; sb_dsp_log("MIDI poll in\n"); dsp->midi_in_poll = 1; @@ -1425,7 +1433,7 @@ sb_exec_command(sb_dsp_t *dsp) dsp->uart_irq = 0; break; case 0x35: /* MIDI In irq */ - if (dsp->sb_type < SB2) + if (dsp->sb_type < SB_DSP_200) break; sb_dsp_log("MIDI irq in\n"); dsp->midi_in_poll = 0; @@ -1444,7 +1452,7 @@ sb_exec_command(sb_dsp_t *dsp) temp = 256 - dsp->sb_data[0]; temp = 1000000 / temp; sb_dsp_log("Sample rate - %ihz (%f)\n", temp, dsp->sblatcho); - if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16)) + if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16_DSP_404)) recalc_sb16_filter(0, temp); dsp->sb_freq = temp; if (IS_ESS(dsp)) { @@ -1453,7 +1461,7 @@ sb_exec_command(sb_dsp_t *dsp) break; case 0x41: /* Set output sampling rate */ case 0x42: /* Set input sampling rate */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sblatcho = (double) ((double) TIMER_USEC * (1000000.0 / (double) (dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); sb_dsp_log("Sample rate - %ihz (%f)\n", dsp->sb_data[1] + (dsp->sb_data[0] << 8), dsp->sblatcho); temp = dsp->sb_freq; @@ -1471,7 +1479,8 @@ sb_exec_command(sb_dsp_t *dsp) case 0x47: /* Continue Auto-Initialize DMA, 16-bit */ break; case 0x48: /* Set DSP block transfer size */ - dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); + if (dsp->sb_type >= SB_DSP_200) + dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); break; case 0x65: /* 4-bit ESPCM output with reference */ case 0x64: /* 4-bit ESPCM output */ @@ -1546,7 +1555,7 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x7D: /* 4-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { + if (dsp->sb_type >= SB_DSP_200) { sb_start_dma(dsp, 1, 1, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); dsp->sb_8_length--; @@ -1554,7 +1563,7 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x7F: /* 2.6-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { + if (dsp->sb_type >= SB_DSP_200) { sb_start_dma(dsp, 1, 1, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); dsp->sb_8_length--; @@ -1567,24 +1576,24 @@ sb_exec_command(sb_dsp_t *dsp) timer_set_delay_u64(&dsp->output_timer, (uint64_t) trunc(dsp->sblatcho)); break; case 0x90: /* High speed 8-bit autoinit DMA output */ - if (dsp->sb_type >= SB2) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x91: /* High speed 8-bit single cycle DMA output */ - if (dsp->sb_type >= SB2) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0x98: /* High speed 8-bit autoinit DMA input */ - if (dsp->sb_type >= SB2) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x99: /* High speed 8-bit single cycle DMA input */ - if (dsp->sb_type >= SB2) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0xA0: /* Set input mode to mono */ case 0xA8: /* Set input mode to stereo */ - if ((dsp->sb_type < SB2) || (dsp->sb_type > SBPRO2)) + if ((dsp->sb_type < SBPRO_DSP_300) || (dsp->sb_type > SBPRO2_DSP_302)) break; /* TODO: Implement. 3.xx-only command. */ break; @@ -1596,7 +1605,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0xB5: case 0xB6: case 0xB7: /* 16-bit DMA output */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); @@ -1610,7 +1619,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0xBD: case 0xBE: case 0xBF: /* 16-bit DMA input */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); @@ -1624,7 +1633,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0xC5: case 0xC6: case 0xC7: /* 8-bit DMA output */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); @@ -1638,7 +1647,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0xCD: case 0xCE: case 0xCF: /* 8-bit DMA input */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); @@ -1650,20 +1659,20 @@ sb_exec_command(sb_dsp_t *dsp) break; case 0xD1: /* Speaker on */ if (IS_NOT_ESS(dsp)) { - if (dsp->sb_type < SB15) { + if (dsp->sb_type < SB_DSP_200) { dsp->sb_8_pause = 1; sb_stop_dma(dsp); - } else if (dsp->sb_type < SB16) + } else if (dsp->sb_type < SB16_DSP_404) dsp->muted = 0; } dsp->sb_speaker = 1; break; case 0xD3: /* Speaker off */ if (IS_NOT_ESS(dsp)) { - if (dsp->sb_type < SB15) { + if (dsp->sb_type < SB_DSP_201) { dsp->sb_8_pause = 1; sb_stop_dma(dsp); - } else if (dsp->sb_type < SB16) + } else if (dsp->sb_type < SB16_DSP_404) dsp->muted = 1; } dsp->sb_speaker = 0; @@ -1673,26 +1682,28 @@ sb_exec_command(sb_dsp_t *dsp) sb_resume_dma(dsp, 1); break; case 0xD5: /* Pause 16-bit DMA */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_16_pause = 1; sb_stop_dma(dsp); } break; case 0xD6: /* Continue 16-bit DMA */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_16_pause = 0; sb_resume_dma(dsp, 1); } break; case 0xD8: /* Get speaker status */ - sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0); + if (dsp->sb_type >= SB_DSP_200) + sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0); break; case 0xD9: /* Exit 16-bit auto-init mode */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) dsp->sb_16_autoinit = 0; break; case 0xDA: /* Exit 8-bit auto-init mode */ - dsp->sb_8_autoinit = 0; + if (dsp->sb_type >= SB_DSP_200) + dsp->sb_8_autoinit = 0; break; case 0xE0: /* DSP identification */ sb_add_data(dsp, ~dsp->sb_data[0]); @@ -1733,7 +1744,7 @@ sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, dsp->sbe2); break; case 0xE3: /* DSP copyright */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { c = 0; while (sb16_copyright[c]) sb_add_data(dsp, sb16_copyright[c++]); @@ -1794,15 +1805,15 @@ sb_exec_command(sb_dsp_t *dsp) timer_set_delay_u64(&dsp->irq16_timer, (10ULL * TIMER_USEC)); break; case 0xF8: - if (dsp->sb_type < SB16) + if (dsp->sb_type < SB16_DSP_404) sb_add_data(dsp, 0); break; case 0xF9: /* SB16 8051 RAM read */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) sb_add_data(dsp, dsp->sb_8051_ram[dsp->sb_data[0]]); break; case 0xFA: /* SB16 8051 RAM write */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) dsp->sb_8051_ram[dsp->sb_data[0]] = dsp->sb_data[1]; break; case 0xFF: /* No, that's not how you program auto-init DMA */ @@ -1812,11 +1823,24 @@ sb_exec_command(sb_dsp_t *dsp) * http://the.earth.li/~tfm/oldpage/sb_dsp.html * http://www.synchrondata.com/pheaven/www/area19.htm * http://www.dcee.net/Files/Programm/Sound/ - * 0E3h DSP Copyright SBPro2??? - * 0F0h Sine Generator SB - * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 - * 0F2h IRQ Request, 8-bit SB + * https://github.com/schlae/sb-firmware/blob/master/sbv202.asm + * 008h Halt (Infinate Loop) SB2??? + * 018h DMA playback with auto init DMA. SB2??? + * 028h Auto-init direct ADC SB2??? + * 036h (Timestamp) SB??? + * 037h (Timestamp) SB??? + * 050h Stops playback of SRAM samples SB??? + * 051h Plays back samples stored in SRAM. SB??? + * 058h Load data into SRAM SB??? + * 059h Fetches the samples and then immediately plays them back. SB??? + * 078h Auto-init DMA ADPCM SB2??? + * 07Ah 2.6-bit ADPCM SB??? + * 0E3h DSP Copyright SBPro2??? (SBPRO2_DSP_302) + * 0F0h Sine Generator SB (SB_DSP_105, DSP20x) + * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 (DSP20x, SBPRO2_DSP_302) + * 0F2h IRQ Request, 8-bit SB (SB_DSP_105, DSP20x) * 0F3h IRQ Request, 16-bit SB16 + * 0F4h Perform ROM checksum SB (SB_DSP_105, DSP20x) * 0FBh DSP Status SB16 * 0FCh DSP Auxiliary Status SB16 * 0FDh DSP Command Status SB16 @@ -1829,7 +1853,7 @@ sb_exec_command(sb_dsp_t *dsp) /* Update 8051 ram with the last DSP command. See https://github.com/joncampbell123/dosbox-x/issues/1044 */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) dsp->sb_8051_ram[0x30] = dsp->sb_command; } @@ -1855,7 +1879,7 @@ sb_write(uint16_t addr, uint8_t val, void *priv) sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xE))) + if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xE))) addr &= 0xfffe; switch (addr & 0xF) { @@ -1938,7 +1962,7 @@ sb_read(uint16_t addr, void *priv) uint8_t ret = 0x00; /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xF))) + if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xF))) /* Exception: ESS AudioDrive does not alias port base+0xf */ addr &= 0xfffe; @@ -1980,7 +2004,7 @@ sb_read(uint16_t addr, void *priv) if (dsp->state == DSP_S_RESET_WAIT) dsp->state = DSP_S_NORMAL; if ((dsp->state == DSP_S_NORMAL) || IS_ESS(dsp)) { - if (dsp->sb_8_enable || dsp->sb_type >= SB16) + if (dsp->sb_8_enable || dsp->sb_type >= SB16_DSP_404) dsp->busy_count = (dsp->busy_count + 1) & 3; else dsp->busy_count = 0; @@ -2005,7 +2029,7 @@ sb_read(uint16_t addr, void *priv) ret = 0x80; } else { sb_dsp_log("SB Write Data Creative read 0xff\n"); - if ((dsp->sb_type >= SB2) && (dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp)) ret = 0xaa; else ret = 0xff; @@ -2015,7 +2039,7 @@ sb_read(uint16_t addr, void *priv) ret = 0x00; } else { sb_dsp_log("SB Write Data Creative read 0x7f\n"); - if ((dsp->sb_type >= SB2) && (dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp)) ret = 0x2a; else ret = 0x7f; @@ -2039,7 +2063,7 @@ sb_read(uint16_t addr, void *priv) ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80; } else { sb_dsp_log("SB Read Data Creative read %02X\n", (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff); - if ((dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + if ((dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp)) ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x2a : 0xaa; else ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; @@ -2150,11 +2174,11 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) /* Default values. Use sb_dsp_setxxx() methods to change. */ dsp->sb_irqnum = 7; dsp->sb_8_dmanum = 1; - if (type >= SB16) + if (type >= SB16_DSP_404) dsp->sb_16_dmanum = 5; else dsp->sb_16_dmanum = 0xff; - if ((type >= SB16) || IS_ESS(dsp)) + if ((type >= SB16_DSP_404) || IS_ESS(dsp)) dsp->sb_16_8_dmanum = 0x1; dsp->mpu = NULL; @@ -2186,7 +2210,7 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) a set frequency command is sent. */ recalc_sb16_filter(0, 3200 * 2); } - if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2)) { + if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2_DSP_302)) { /* OPL3 or dual OPL2 is stereo. */ if (dsp->sb_has_real_opl) recalc_opl_filter(FREQ_49716 * 2); From 9bc5f0dd0577899ac23600f31d1f773bf72edff0 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 9 Jan 2025 22:58:40 +0100 Subject: [PATCH 08/65] 8514/A and S3 changes of the late day (January 9th, 2025) S3: 1. Cleaned up the Short Stroke command processing. 2. Proceed calculating the error term only when it's equal or greater than the line length (Draw Line, Command 1 and also applies to Short Strokes, Command 0). 8514/A compatibles: 1. Reworked the polygon draw type A processing. 2. As with the S3, reworked the way error term is handled in the processing, and on Command 5 (Draw Polygon Boundary Line). --- src/include/86box/vid_8514a.h | 1 + src/video/vid_8514a.c | 142 ++++++++++++++++++++++++---------- src/video/vid_s3.c | 62 +++++++-------- 3 files changed, 128 insertions(+), 77 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 0e6e0965a..57e98cc44 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -138,6 +138,7 @@ typedef struct ibm8514_t { int output2; int ssv_len; + int ssv_len_back; uint8_t ssv_dir; uint8_t ssv_draw; int odd_in; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 810d403ab..0e51feae4 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -43,6 +43,11 @@ #include <86box/vid_ati_mach8.h> #include "cpu.h" +#ifdef CLAMP +# undef CLAMP +#endif + + #define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140_4k.BIN" static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv); @@ -68,6 +73,17 @@ ibm8514_log(const char *fmt, ...) # define ibm8514_log(fmt, ...) #endif +static int16_t +CLAMP(int16_t in, int16_t min, int16_t max) +{ + if (in < min) + return min; + if (in > max) + return max; + + return in; +} + #define WRITE8(addr, var, val) \ switch ((addr) & 1) { \ case 0: \ @@ -416,14 +432,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 2) { dev->accel.short_stroke = val; - dev->accel.cx = dev->accel.cur_x; - if (dev->accel.cur_x >= 0x600) - dev->accel.cx |= ~0x5ff; - - dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_y >= 0x600) - dev->accel.cy |= ~0x5ff; - if (dev->accel.cmd & 0x1000) { ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); @@ -969,6 +977,7 @@ ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t dev->accel.ssv_len = ssv & 0x0f; dev->accel.ssv_dir = ssv & 0xe0; dev->accel.ssv_draw = ssv & 0x10; + dev->accel.ssv_len_back = dev->accel.ssv_len; if (ibm8514_cpu_src(svga)) { dev->data_available = 0; @@ -1006,6 +1015,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat uint16_t bkgd_color = dev->accel.bkgd_color; uint32_t old_mix_dat; int and3 = dev->accel.cur_x & 3; + int poly_src; if (!dev->bpp) { compare &= 0xff; @@ -1121,13 +1131,24 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat old_mix_dat = mix_dat; + if (cmd == 5 || cmd == 1 || (cmd == 2 && (dev->accel.multifunc[0x0a] & 0x06))) + ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06); + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ - if (dev->accel.ssv_state == 0) + if (dev->accel.ssv_state == 0) { + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + + dev->accel.cy = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; break; + } if (dev->accel.cmd & 0x08) { while (count-- && dev->accel.ssv_len >= 0) { @@ -1289,7 +1310,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cy--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.ssv_len_back) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -1303,7 +1324,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cx--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.ssv_len_back) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x80) dev->accel.cy++; @@ -1454,6 +1475,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.sy) { dev->accel.cmd_back = 1; + if (!cpu_input) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } break; } @@ -1505,8 +1530,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sy--; } - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; dev->accel.x_count = 0; dev->accel.output = 0; } else { /*Bresenham Line*/ @@ -1580,7 +1603,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cy--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -1594,7 +1617,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cx--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x80) dev->accel.cy++; @@ -1673,6 +1696,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.sy) { dev->accel.cmd_back = 1; + if (!cpu_input) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } break; } @@ -1682,7 +1709,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cy--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -1696,7 +1723,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cx--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x80) dev->accel.cy++; @@ -1709,8 +1736,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sy--; } } - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; } break; @@ -2283,35 +2308,62 @@ skip_nibble_rect_write: } } } else if ((dev->accel.multifunc[0x0a] & 0x06) == 0x04) { /*Polygon Draw Type A*/ + ibm8514_log("Polygon Draw Type A: Clipping: L=%d, R=%d, T=%d, B=%d, C(%d,%d), sx=%d, sy=%d.\n", clip_l, clip_r, clip_t, clip_b, dev->accel.cx, dev->accel.cy, dev->accel.sx, dev->accel.sy); while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - READ(dev->accel.dest + dev->accel.cx, mix_dat); - if ((mix_dat & rd_mask_polygon) == rd_mask_polygon) + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.cx, poly_src); + if ((poly_src & rd_mask_polygon) == rd_mask_polygon) dev->accel.fill_state ^= 1; READ(dev->accel.dest + dev->accel.cx, dest_dat); + old_dest_dat = dest_dat; if (dev->accel.fill_state) { - if (!(rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) { - MIX(mix_dat ^ rd_mask_polygon, dest_dat, mix_dat); - ibm8514_log("Filling c(%d,%d) without bit 0 of rdmask=%02x, wrtmask=%02x, mixdat=%02x, dest=%02x, old=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, old_dest_dat); - dest_dat &= ~rd_mask_polygon; - } else if ((rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) { - ibm8514_log("Filling c(%d,%d) with bit 0 of rdmask=%02x, wrtmask=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask); - dest_dat &= ~(rd_mask_polygon & wrt_mask); + if (rd_mask_polygon & 0x01) { + if (wrt_mask & 0x01) { + dest_dat &= ~(rd_mask_polygon & wrt_mask); /*Fill State On, Write Mask 1, Read Mask 1.*/ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } else { + if (wrt_mask & 0x01) { + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat &= ~rd_mask_polygon; /*Fill State On, Write Mask 1, Read Mask 0.*/ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } } } else { - if (!(rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) - dest_dat &= ~rd_mask_polygon; - else if ((rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) - dest_dat &= ~(rd_mask_polygon & wrt_mask); + if (rd_mask_polygon & 0x01) { + if (wrt_mask & 0x01) { + dest_dat &= ~(rd_mask_polygon & wrt_mask); /*Fill State Off, Write Mask 1, Read Mask 1.*/ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } else { + if (wrt_mask & 0x01) { + dest_dat &= ~rd_mask_polygon; /*Fill State Off, Write Mask 1, Read Mask 0.*/ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } } - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || @@ -2322,7 +2374,11 @@ skip_nibble_rect_write: ibm8514_log("Results c(%d,%d):rdmask=%02x, wrtmask=%02x, mix=%02x, destdat=%02x, nowrite=%d.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, dev->accel.cx_back); WRITE(dev->accel.dest + dev->accel.cx, dest_dat); } - } + } else + ibm8514_log("Out of bounds DrawA C(%d,%d).\n", dev->accel.cx, dev->accel.cy); + + mix_dat <<= 1; + mix_dat |= 1; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -2356,6 +2412,8 @@ skip_nibble_rect_write: if (dev->accel.sy < 0) { ibm8514_log(".\n"); dev->accel.cmd_back = 1; + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; return; } } @@ -2468,7 +2526,7 @@ skip_nibble_rect_write: else dev->accel.oldcy = dev->accel.cy - 1; - ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.multifunc[2], dev->accel.multifunc[4], dev->accel.clip_top, clip_b, dev->accel.multifunc[0x0a]); + ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, clip_l, clip_r, clip_t, clip_b, dev->accel.multifunc[0x0a]); if (ibm8514_cpu_src(svga)) { dev->data_available = 0; @@ -2483,8 +2541,7 @@ skip_nibble_rect_write: if (dev->accel.cmd & 0x08) { /*Vectored Boundary Line*/ while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cx < clip_l) - dev->accel.cx = clip_l; + dev->accel.cx = CLAMP(dev->accel.cx, clip_l, clip_r); if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && @@ -2591,11 +2648,10 @@ skip_nibble_rect_write: } } else { /*Vectored Bresenham*/ while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cx < clip_l) - dev->accel.cx = clip_l; + dev->accel.cx = CLAMP(dev->accel.cx, clip_l, clip_r); if ((dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r) && + (dev->accel.cx < clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -2658,7 +2714,7 @@ skip_nibble_rect_write: else dev->accel.cy--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt_no_limit) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -2673,7 +2729,7 @@ skip_nibble_rect_write: dev->accel.cx--; dev->accel.oldcy = dev->accel.cy; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt_no_limit) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x80) dev->accel.cy++; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index abb2d70aa..bb5c283ad 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -273,6 +273,7 @@ typedef struct s3_t { int dat_count; int b2e8_pix, temp_cnt; int ssv_len; + int ssv_len_back; uint8_t ssv_dir; uint8_t ssv_draw; uint8_t dat_buf_16bit; @@ -511,7 +512,7 @@ s3_update_irqs(s3_t *s3) } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, void *priv); -void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv); +void s3_short_stroke_start(s3_t *s3, uint8_t ssv); static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define WRITE8(addr, var, val) \ @@ -922,15 +923,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); s3->accel.ssv_state = 1; - s3->accel.cx = s3->accel.cur_x & 0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cmd & 0x1000) { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); } else { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); } break; @@ -1787,15 +1785,12 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) s3->accel.short_stroke = val; s3->accel.ssv_state = 1; - s3->accel.cx = s3->accel.cur_x & 0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cmd & 0x1000) { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); } else { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); } } } @@ -7823,19 +7818,16 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) } void -s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) +s3_short_stroke_start(s3_t *s3, uint8_t ssv) { - if (!cpu_input) { - s3->accel.ssv_len = ssv & 0x0f; - s3->accel.ssv_dir = ssv & 0xe0; - s3->accel.ssv_draw = ssv & 0x10; + s3->accel.ssv_len = ssv & 0x0f; + s3->accel.ssv_dir = ssv & 0xe0; + s3->accel.ssv_draw = !!(ssv & 0x10); - if (s3_cpu_src(s3)) { - return; /*Wait for data from CPU*/ - } - } + if (s3_cpu_src(s3)) + return; /*Wait for data from CPU*/ - s3->accel_start(count, cpu_input, mix_dat, cpu_dat, s3); + s3->accel_start(-1, 0, -1, 0, s3); } void @@ -7978,11 +7970,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ - if (s3->accel.ssv_state == 0) + if (s3->accel.ssv_state == 0) { + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; break; + } - if (s3->accel.cmd & 0x08) /*Radial*/ - { + if (s3->accel.cmd & 0x08) { /*Radial*/ while (count-- && s3->accel.ssv_len >= 0) { if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -8036,8 +8030,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi else cpu_dat >>= 16; - if (!s3->accel.ssv_len) + if (!s3->accel.ssv_len) { + s3->accel.cur_x = s3->accel.cx & 0xfff; + s3->accel.cur_y = s3->accel.cy & 0xfff; break; + } switch (s3->accel.ssv_dir & 0xe0) { case 0x00: @@ -8077,9 +8074,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cx &= 0xfff; s3->accel.cy &= 0xfff; } - - s3->accel.cur_x = s3->accel.cx & 0xfff; - s3->accel.cur_y = s3->accel.cy & 0xfff; } break; @@ -8270,7 +8264,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi else s3->accel.cy--; - if (s3->accel.err_term >= 0) { + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { s3->accel.err_term += s3->accel.destx_distp; if (s3->accel.cmd & 0x20) s3->accel.cx++; @@ -8284,7 +8278,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi else s3->accel.cx--; - if (s3->accel.err_term >= 0) { + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { s3->accel.err_term += s3->accel.destx_distp; if (s3->accel.cmd & 0x80) s3->accel.cy++; From 3a22930c07f6f012381f41ede9021473b17a3f63 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 9 Jan 2025 23:24:58 +0100 Subject: [PATCH 09/65] And Cirrus per the previous commit. Improved the byte swap fix introduced time ago, this time by making it trigger on banked writes when needed. --- src/video/vid_cl54xx.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 4e7d1ac09..bc54d0d7c 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1361,7 +1361,7 @@ gd54xx_in(uint16_t addr, void *priv) 32-bit (Pre-5434)/64-bit (5434 and up) DRAM data bus width for 2M of memory */ - ret |= (gd54xx_is_5434(svga)) ? 0x98 : 0x18; + ret |= 0x18; break; case 4096: ret |= 0x98; /*64-bit (5434 and up) DRAM data bus width for 4M of memory*/ @@ -2281,6 +2281,9 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv) if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) + val = (val >> 8) | (val << 8); + gd54xx_write(addr, val, gd54xx); gd54xx_write(addr + 1, val >> 8, gd54xx); return; @@ -2308,6 +2311,9 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *priv) if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + gd54xx_write(addr, val, gd54xx); gd54xx_write(addr + 1, val >> 8, gd54xx); gd54xx_write(addr + 2, val >> 16, gd54xx); @@ -3661,9 +3667,6 @@ gd54xx_mem_sys_src(gd54xx_t *gd54xx, uint32_t cpu_dat, uint32_t count) mask_shift = 31 - byte_pos; if (!(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) cpu_dat >>= byte_pos; - else if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) - cpu_dat = ((cpu_dat & 0xff000000) >> 24) | ((cpu_dat & 0x00ff0000) >> 8) | - ((cpu_dat & 0x0000ff00) << 8) | ((cpu_dat & 0x000000ff) << 24); } else mask_shift = 7; From 738b80f1abcdf63a47ba10c16ea3d4e915ec53c9 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 9 Jan 2025 23:47:30 +0100 Subject: [PATCH 10/65] And DC390 for today. Restore the old way of identifying the chip id in the DC390. Fixes NT 4.0 booting from CD-ROM using said SCSI controller when its BIOS is enabled. --- src/scsi/scsi_pcscsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index 9aa5f391f..c2e5c9168 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -630,6 +630,7 @@ esp_hard_reset(esp_t *dev) fifo8_reset(&dev->fifo); fifo8_reset(&dev->cmdfifo); dev->dma = 0; + dev->tchi_written = 0; dev->rregs[ESP_CFG1] = dev->mca ? dev->HostID : 7; esp_log("ESP Reset\n"); @@ -1346,7 +1347,7 @@ esp_reg_read(esp_t *dev, uint32_t saddr) if (dev->mca) { ret = dev->rregs[ESP_TCHI]; } else { - if (dev->rregs[ESP_CFG2] & 0x40) + if (!dev->tchi_written) ret = TCHI_AM53C974; else ret = dev->rregs[ESP_TCHI]; @@ -1369,6 +1370,8 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) esp_log("Write reg %02x = %02x\n", saddr, val); switch (saddr) { case ESP_TCHI: + dev->tchi_written = 1; + fallthrough; case ESP_TCLO: case ESP_TCMID: esp_log("ESP TCW reg%02x = %02x.\n", saddr, val); From c627fa0dee5633e00bdcd2ed344723156259a507 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 9 Jan 2025 18:08:37 -0500 Subject: [PATCH 11/65] Missing todo for ataripc3 --- src/machine/m_xt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 62466bf91..c0d313c63 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -214,6 +214,7 @@ machine_xt_amixt_init(const machine_t *model) // TODO // Onboard EGA Graphics (NSI Logic EVC315-S on early boards STMicroelectronics EGA on later revisions) +// RTC // Adaptec ACB-2072 RLL Controller Card (Optional) // Atari PCM1 Mouse Support int From edfb344efa3a03334f278bad6ee68e5988766de7 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 9 Jan 2025 18:09:21 -0500 Subject: [PATCH 12/65] Update ataripc4 todo --- src/machine/m_at_286_386sx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 9c1eb817b..ead31c21c 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -214,7 +214,7 @@ machine_at_neat_ami_init(const machine_t *model) // TODO // Onboard Paradise PVGA1A-JK VGA Graphics -// Data Technology Corporation DTC7187 RLL Controller +// Data Technology Corporation DTC7187 RLL Controller (Optional) int machine_at_ataripc4_init(const machine_t *model) { From 1ab78eb48a7724606bd64ac74f7416fe8a925c31 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 6 Jan 2025 22:40:18 -0500 Subject: [PATCH 13/65] Cleanups in qt_settingsports --- src/qt/qt_settingsports.cpp | 4 +++- src/qt/qt_settingsports.hpp | 26 ++------------------------ 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 01d7d3f9f..9679c9e21 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -160,6 +160,7 @@ SettingsPorts::on_pushButtonSerialPassThru4_clicked() DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); } +#if 0 void SettingsPorts::on_pushButtonSerialPassThru5_clicked() { @@ -177,6 +178,7 @@ SettingsPorts::on_pushButtonSerialPassThru7_clicked() { DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast(Settings::settings)); } +#endif void SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked) @@ -220,4 +222,4 @@ SettingsPorts::on_checkBoxSerialPassThru7_clicked(bool checked) { ui->pushButtonSerialPassThru7->setEnabled(checked); } -#endif \ No newline at end of file +#endif diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index 1ecb051af..fb9cdb343 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -19,45 +19,23 @@ public: #if 0 private slots: void on_checkBoxSerialPassThru7_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru6_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru5_clicked(bool checked); #endif - -private slots: void on_checkBoxSerialPassThru4_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru3_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru2_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru1_clicked(bool checked); private slots: +#if 0 void on_pushButtonSerialPassThru7_clicked(); - -private slots: void on_pushButtonSerialPassThru6_clicked(); - -private slots: void on_pushButtonSerialPassThru5_clicked(); - -private slots: +#endif void on_pushButtonSerialPassThru4_clicked(); - -private slots: void on_pushButtonSerialPassThru3_clicked(); - -private slots: void on_pushButtonSerialPassThru2_clicked(); - -private slots: void on_pushButtonSerialPassThru1_clicked(); private slots: From 9b61651955866a2c388ee348850b08519c997f37 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 6 Jan 2025 19:44:15 -0500 Subject: [PATCH 14/65] Add other BIOS versions to ibmpc82 --- src/machine/m_xt.c | 81 ++++++++++++++++++++++++++++++++++--- src/machine/machine_table.c | 3 +- 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index c0d313c63..63ad6f4b3 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -65,15 +65,82 @@ machine_pc_init(const machine_t *model) return ret; } +static const device_config_t ibmpc82_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5150_1501476", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1501476 (10/27/82)", .internal_name = "ibm5150_1501476", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc82/BIOS_5150_27OCT82_1501476_U33.BIN", "" } }, + { .name = "5000024 (08/16/82)", .internal_name = "ibm5150_5000024", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc82/BIOS_5150_16AUG82_5000024_U33.BIN", "" } }, + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, + { .files_no = 0 } + }, + }, + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "enable_basic", + .description = "IBM Cassette Basic", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmpc82_device = { + .name = "IBM PC (1982) Devices", + .internal_name = "ibmpc82_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmpc82_config +}; + int machine_pc82_init(const machine_t *model) { - int ret; - int ret2; + int ret = 0; + int ret2; + uint8_t enable_5161; + uint8_t enable_basic; + const char* fn; - ret = bios_load_linear("roms/machines/ibmpc82/pc102782.bin", - 0x000fe000, 40960, 0); - if (ret) { + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + enable_basic = machine_get_config_int("enable_basic"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 40960, 0); + device_context_restore(); + + if (enable_basic && ret) { ret2 = bios_load_aux_linear("roms/machines/ibmpc82/ibm-basic-1.10.rom", 0x000f6000, 32768, 0); if (!ret2) { @@ -92,10 +159,12 @@ machine_pc82_init(const machine_t *model) return ret; device_add(&keyboard_pc82_device); - device_add(&ibm_5161_device); machine_xt_common_init(model, 0); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b60d35fd7..31642bfec 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -55,6 +55,7 @@ extern const device_t vid_device_sl; extern const device_t t1200_video_device; extern const device_t compaq_plasma_device; extern const device_t ps1_2011_device; +extern const device_t ibmpc82_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -282,7 +283,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmpc82_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, From 84a6dd9508268b33abfca8b52adde78cb85f1827 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 9 Jan 2025 20:13:55 -0500 Subject: [PATCH 15/65] Device customization for ibmpc, ibmxt & ibmxt86 --- src/machine/m_xt.c | 123 ++++++++++++++++++++++++++++++++++-- src/machine/machine_table.c | 9 ++- 2 files changed, 122 insertions(+), 10 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 63ad6f4b3..ece2e6578 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -37,14 +37,54 @@ machine_xt_common_init(const machine_t *model, int fixed_floppy) standalone_gameport_type = &gameport_device; } +static const device_config_t ibmpc_config[] = { + // clang-format off + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "enable_basic", + .description = "IBM Cassette Basic", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmpc_device = { + .name = "IBM PC (1981) Device", + .internal_name = "ibmpc_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmpc_config +}; + int machine_pc_init(const machine_t *model) { - int ret; + int ret; + uint8_t enable_5161; + uint8_t enable_basic; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + enable_basic = machine_get_config_int("enable_basic"); + device_context_restore(); ret = bios_load_linear("roms/machines/ibmpc/BIOS_5150_24APR81_U33.BIN", 0x000fe000, 40960, 0); - if (ret) { + + if (enable_basic && ret) { bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", 0x000f6000, 8192, 0); bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", @@ -62,6 +102,9 @@ machine_pc_init(const machine_t *model) machine_xt_common_init(model, 0); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } @@ -168,10 +211,42 @@ machine_pc82_init(const machine_t *model) return ret; } +static const device_config_t ibmxt_config[] = { + // clang-format off + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmxt_device = { + .name = "IBM XT (1982) Device", + .internal_name = "ibmxt_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt_config +}; + int machine_xt_init(const machine_t *model) { - int ret; + int ret; + uint8_t enable_5161; + uint8_t enable_basic; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + device_context_restore(); ret = bios_load_linear("roms/machines/ibmxt/xt.rom", 0x000f0000, 65536, 0); @@ -189,12 +264,13 @@ machine_xt_init(const machine_t *model) if (bios_only || !ret) return ret; - device_add(&keyboard_xt_device); - device_add(&ibm_5161_device); machine_xt_common_init(model, 0); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } @@ -216,10 +292,41 @@ machine_genxt_init(const machine_t *model) return ret; } +static const device_config_t ibmxt86_config[] = { + // clang-format off + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmxt86_device = { + .name = "IBM XT (1986) Device", + .internal_name = "ibmxt86_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt86_config +}; + int machine_xt86_init(const machine_t *model) { - int ret; + int ret; + uint8_t enable_5161; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + device_context_restore(); ret = bios_load_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", 0x000fe000, 65536, 0x6000); @@ -234,10 +341,12 @@ machine_xt86_init(const machine_t *model) return ret; device_add(&keyboard_xt86_device); - device_add(&ibm_5161_device); machine_xt_common_init(model, 0); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 31642bfec..1d67fae4c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -55,7 +55,10 @@ extern const device_t vid_device_sl; extern const device_t t1200_video_device; extern const device_t compaq_plasma_device; extern const device_t ps1_2011_device; +extern const device_t ibmpc_device; extern const device_t ibmpc82_device; +extern const device_t ibmxt_device; +extern const device_t ibmxt86_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -244,7 +247,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmpc_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -361,7 +364,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmxt_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -400,7 +403,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmxt86_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, From dfbd9be605bafb83c60bd2658ce62f2d5c8fef32 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 9 Jan 2025 20:40:43 -0500 Subject: [PATCH 16/65] Device customization for ibmat & ibmxt286 --- src/machine/m_at.c | 73 ++++++++++++++++++++++++++++++++++++- src/machine/machine_table.c | 6 ++- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 122c5cdef..089a73a10 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -53,6 +53,7 @@ #include <86box/fdc_ext.h> #include <86box/nvr.h> #include <86box/gameport.h> +#include <86box/ibm_5161.h> #include <86box/keyboard.h> #include <86box/lpt.h> #include <86box/rom.h> @@ -149,10 +150,41 @@ machine_at_ps2_ide_init(const machine_t *model) device_add(&ide_isa_device); } +static const device_config_t ibmat_config[] = { + // clang-format off + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmat_device = { + .name = " IBM AT Devices", + .internal_name = "ibmat_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmat_config +}; + int machine_at_ibm_init(const machine_t *model) { - int ret; + int ret; + uint8_t enable_5161; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + device_context_restore(); ret = bios_load_interleaved("roms/machines/ibmat/62x0820.u27", "roms/machines/ibmat/62x0821.u47", @@ -163,6 +195,9 @@ machine_at_ibm_init(const machine_t *model) machine_at_ibm_common_init(model); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } @@ -218,10 +253,41 @@ machine_at_ibmatpx_init(const machine_t *model) return ret; } +static const device_config_t ibmxt286_config[] = { + // clang-format off + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmxt286_device = { + .name = "IBM XT Model 286 Devices", + .internal_name = "ibmxt286_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt286_config +}; + int machine_at_ibmxt286_init(const machine_t *model) { - int ret; + int ret; + uint8_t enable_5161; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + device_context_restore(); ret = bios_load_interleaved("roms/machines/ibmxt286/bios_5162_21apr86_u34_78x7460_27256.bin", "roms/machines/ibmxt286/bios_5162_21apr86_u35_78x7461_27256.bin", @@ -232,6 +298,9 @@ machine_at_ibmxt286_init(const machine_t *model) machine_at_ibm_common_init(model); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 1d67fae4c..48a024e08 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -59,6 +59,8 @@ extern const device_t ibmpc_device; extern const device_t ibmpc82_device; extern const device_t ibmxt_device; extern const device_t ibmxt86_device; +extern const device_t ibmat_device; +extern const device_t ibmxt286_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -2677,7 +2679,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmat_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -2797,7 +2799,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmxt286_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, From ecaad9c41cef7356f5568a656d7ae7022f2c2a5f Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 9 Jan 2025 20:43:43 -0500 Subject: [PATCH 17/65] Update some copyrights --- src/machine/m_at.c | 3 ++- src/machine/m_xt.c | 22 ++++++++++++++++++++++ src/machine/machine_table.c | 2 ++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 089a73a10..fea87c8f6 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -13,10 +13,12 @@ * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, + * Jasmine Iwanek, * * Copyright 2017-2020 Fred N. van Kempen. * Copyright 2016-2020 Miran Grca. * Copyright 2008-2020 Sarah Walker. + * Copyright 2025 Jasmine Iwanek. * * 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,7 +38,6 @@ * Boston, MA 02111-1307 * USA. */ - #include #include #include diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index ece2e6578..db511c332 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -1,3 +1,25 @@ +/* + * 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. + * + * Standard PC/AT implementation. + * + * + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * Jasmine Iwanek, + * + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2025 Jasmine Iwanek. + */ #include #include #include diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 48a024e08..3fc3bcc8a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15,9 +15,11 @@ * * Authors: Miran Grca, * Fred N. van Kempen, + * Jasmine Iwanek, * * Copyright 2016-2020 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2025 Jasmine Iwanek. */ #include #include From 738087ae132c677735d2b277ab5cc3cdd4e6ce1c Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 6 Jan 2025 23:28:08 -0500 Subject: [PATCH 18/65] Cleanups in device --- src/device.c | 249 +++++++++++++++++++------------------ src/include/86box/device.h | 26 ++-- 2 files changed, 138 insertions(+), 137 deletions(-) diff --git a/src/device.c b/src/device.c index 9a904f550..5b733df46 100644 --- a/src/device.c +++ b/src/device.c @@ -19,7 +19,7 @@ * Copyright 2016-2019 Miran Grca. * Copyright 2008-2019 Sarah Walker. * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. * * 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 @@ -89,38 +89,38 @@ device_init(void) } void -device_set_context(device_context_t *c, const device_t *dev, int inst) +device_set_context(device_context_t *ctx, const device_t *dev, int inst) { - memset(c, 0, sizeof(device_context_t)); - c->dev = dev; - c->instance = inst; + memset(ctx, 0, sizeof(device_context_t)); + ctx->dev = dev; + ctx->instance = inst; if (inst) { - sprintf(c->name, "%s #%i", dev->name, inst); + sprintf(ctx->name, "%s #%i", dev->name, inst); /* If a numbered section is not present, but a non-numbered of the same name is, rename the non-numbered section to numbered. */ - const void *sec = config_find_section(c->name); + const void *sec = config_find_section(ctx->name); void * single_sec = config_find_section((char *) dev->name); if ((sec == NULL) && (single_sec != NULL)) - config_rename_section(single_sec, c->name); + config_rename_section(single_sec, ctx->name); } else if (!strcmp(dev->name, "PS/2 Mouse")) { - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); /* Migrate the old "Standard PS/2 Mouse" section */ - const void *sec = config_find_section(c->name); + const void *sec = config_find_section(ctx->name); void * old_sec = config_find_section("Standard PS/2 Mouse"); if ((sec == NULL) && (old_sec != NULL)) - config_rename_section(old_sec, c->name); + config_rename_section(old_sec, ctx->name); } else if (!strcmp(dev->name, "Microsoft RAMCard")) { - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); - /* Migrate the old "Standard PS/2 Mouse" section */ - const void *sec = config_find_section(c->name); + /* Migrate the old "Microsoft RAMCard for IBM PC" section */ + const void *sec = config_find_section(ctx->name); void * old_sec = config_find_section("Microsoft RAMCard for IBM PC"); if ((sec == NULL) && (old_sec != NULL)) - config_rename_section(old_sec, c->name); + config_rename_section(old_sec, ctx->name); } else - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); } static void @@ -153,7 +153,7 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) { device_t *init_dev = NULL; void *priv = NULL; - int c; + int16_t c; if (params != NULL) { init_dev = calloc(1, sizeof(device_t)); @@ -162,7 +162,7 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) } else init_dev = (device_t *) dev; - for (c = 0; c < 256; c++) { + for (c = 0; c < DEVICE_MAX; c++) { if (!inst && (devices[c] == dev)) { device_log("DEVICE: device already exists!\n"); return (NULL); @@ -244,6 +244,7 @@ void * device_add_linked(const device_t *dev, void *priv) { void *ret; + device_common_priv = priv; ret = device_add_common(dev, NULL, NULL, 0); device_common_priv = NULL; @@ -311,7 +312,8 @@ device_close_all(void) #endif if (devices[c]->close != NULL) devices[c]->close(device_priv[c]); - devices[c] = device_priv[c] = NULL; + devices[c] = NULL; + device_priv[c] = NULL; } } } @@ -372,7 +374,7 @@ device_available(const device_t *dev) if (dev != NULL) { config = dev->config; if (config != NULL) { - while (config->type != -1) { + while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { int roms_present = 0; @@ -414,7 +416,7 @@ device_get_bios_file(const device_t *dev, const char *internal_name, int file_no if (dev != NULL) { config = dev->config; if (config != NULL) { - while (config->type != -1) { + while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { bios = config->bios; @@ -452,7 +454,7 @@ device_has_config(const device_t *dev) config = dev->config; - while (config->type != -1) { + while (config->type != CONFIG_END) { c++; config++; } @@ -543,8 +545,7 @@ device_get_name(const device_t *dev, int bus, char *name) strcat(pbus, ")"); /* Allocate the temporary device name string and set it to all zeroes. */ - tname = (char *) malloc(strlen(dev->name) + 1); - memset(tname, 0x00, strlen(dev->name) + 1); + tname = (char *) calloc(1, strlen(dev->name) + 1); /* First strip the bus string with parentheses. */ fbus = strstr(dev->name, pbus); @@ -612,256 +613,256 @@ device_get_instance(void) } const char * -device_get_config_string(const char *s) +device_get_config_string(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_string((char *) device_current.name, (char *) s, (char *) c->default_string)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_string((char *) device_current.name, (char *) str, (char *) cfg->default_string)); - c++; + cfg++; } return (NULL); } int -device_get_config_int(const char *s) +device_get_config_int(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_int_ex(const char *s, int def) +device_get_config_int_ex(const char *str, int def) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) device_current.name, (char *) s, def)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) device_current.name, (char *) str, def)); - c++; + cfg++; } return def; } int -device_get_config_hex16(const char *s) +device_get_config_hex16(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_hex16((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_hex16((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_hex20(const char *s) +device_get_config_hex20(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_hex20((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_hex20((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_mac(const char *s, int def) +device_get_config_mac(const char *str, int def) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_mac((char *) device_current.name, (char *) s, def)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_mac((char *) device_current.name, (char *) str, def)); - c++; + cfg++; } return def; } void -device_set_config_int(const char *s, int val) +device_set_config_int(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_int((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_int((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_hex16(const char *s, int val) +device_set_config_hex16(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_hex16((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_hex16((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_hex20(const char *s, int val) +device_set_config_hex20(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_hex20((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_hex20((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_mac(const char *s, int val) +device_set_config_mac(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_mac((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_mac((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } int -device_is_valid(const device_t *device, int m) +device_is_valid(const device_t *device, int mch) { if (device == NULL) return 1; - if ((device->flags & DEVICE_PCJR) && !machine_has_bus(m, MACHINE_BUS_PCJR)) + if ((device->flags & DEVICE_PCJR) && !machine_has_bus(mch, MACHINE_BUS_PCJR)) return 0; - if ((device->flags & DEVICE_XTKBC) && machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC)) + if ((device->flags & DEVICE_XTKBC) && machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC)) return 0; - if ((device->flags & DEVICE_AT) && !machine_has_bus(m, MACHINE_BUS_ISA16)) + if ((device->flags & DEVICE_AT) && !machine_has_bus(mch, MACHINE_BUS_ISA16)) return 0; - if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC)) + if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC)) return 0; - if ((device->flags & DEVICE_PS2) && !machine_has_bus(m, MACHINE_BUS_PS2_PORTS)) + if ((device->flags & DEVICE_PS2) && !machine_has_bus(mch, MACHINE_BUS_PS2_PORTS)) return 0; - if ((device->flags & DEVICE_ISA) && !machine_has_bus(m, MACHINE_BUS_ISA)) + if ((device->flags & DEVICE_ISA) && !machine_has_bus(mch, MACHINE_BUS_ISA)) return 0; - if ((device->flags & DEVICE_CBUS) && !machine_has_bus(m, MACHINE_BUS_CBUS)) + if ((device->flags & DEVICE_CBUS) && !machine_has_bus(mch, MACHINE_BUS_CBUS)) return 0; - if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(m, MACHINE_BUS_PCMCIA) && !machine_has_bus(m, MACHINE_BUS_ISA)) + if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_ISA)) return 0; - if ((device->flags & DEVICE_MCA) && !machine_has_bus(m, MACHINE_BUS_MCA)) + if ((device->flags & DEVICE_MCA) && !machine_has_bus(mch, MACHINE_BUS_MCA)) return 0; - if ((device->flags & DEVICE_HIL) && !machine_has_bus(m, MACHINE_BUS_HIL)) + if ((device->flags & DEVICE_HIL) && !machine_has_bus(mch, MACHINE_BUS_HIL)) return 0; - if ((device->flags & DEVICE_EISA) && !machine_has_bus(m, MACHINE_BUS_EISA)) + if ((device->flags & DEVICE_EISA) && !machine_has_bus(mch, MACHINE_BUS_EISA)) return 0; - if ((device->flags & DEVICE_AT32) && !machine_has_bus(m, MACHINE_BUS_AT32)) + if ((device->flags & DEVICE_AT32) && !machine_has_bus(mch, MACHINE_BUS_AT32)) return 0; - if ((device->flags & DEVICE_OLB) && !machine_has_bus(m, MACHINE_BUS_OLB)) + if ((device->flags & DEVICE_OLB) && !machine_has_bus(mch, MACHINE_BUS_OLB)) return 0; - if ((device->flags & DEVICE_VLB) && !machine_has_bus(m, MACHINE_BUS_VLB)) + if ((device->flags & DEVICE_VLB) && !machine_has_bus(mch, MACHINE_BUS_VLB)) return 0; - if ((device->flags & DEVICE_PCI) && !machine_has_bus(m, MACHINE_BUS_PCI)) + if ((device->flags & DEVICE_PCI) && !machine_has_bus(mch, MACHINE_BUS_PCI)) return 0; - if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(m, MACHINE_BUS_CARDBUS) && !machine_has_bus(m, MACHINE_BUS_PCI)) + if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_PCI)) return 0; - if ((device->flags & DEVICE_USB) && !machine_has_bus(m, MACHINE_BUS_USB)) + if ((device->flags & DEVICE_USB) && !machine_has_bus(mch, MACHINE_BUS_USB)) return 0; - if ((device->flags & DEVICE_AGP) && !machine_has_bus(m, MACHINE_BUS_AGP)) + if ((device->flags & DEVICE_AGP) && !machine_has_bus(mch, MACHINE_BUS_AGP)) return 0; - if ((device->flags & DEVICE_AC97) && !machine_has_bus(m, MACHINE_BUS_AC97)) + if ((device->flags & DEVICE_AC97) && !machine_has_bus(mch, MACHINE_BUS_AC97)) return 0; return 1; } int -machine_get_config_int(char *s) +machine_get_config_int(char *str) { - const device_t *d = machine_get_device(machine); - const device_config_t *c; + const device_t *dev = machine_get_device(machine); + const device_config_t *cfg; - if (d == NULL) + if (dev == NULL) return 0; - c = d->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) d->name, s, c->default_int)); + cfg = dev->config; + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) dev->name, str, cfg->default_int)); - c++; + cfg++; } return 0; } char * -machine_get_config_string(char *s) +machine_get_config_string(char *str) { - const device_t *d = machine_get_device(machine); - const device_config_t *c; + const device_t *dev = machine_get_device(machine); + const device_config_t *cfg; - if (d == NULL) + if (dev == NULL) return 0; - c = d->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_string((char *) d->name, s, (char *) c->default_string)); + cfg = dev->config; + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_string((char *) dev->name, str, (char *) cfg->default_string)); - c++; + cfg++; } return NULL; @@ -881,7 +882,7 @@ const device_t device_none = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -895,7 +896,7 @@ const device_t device_internal = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 67a30b1c8..1c2ec5203 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -18,7 +18,7 @@ * Copyright 2016-2019 Miran Grca. * Copyright 2008-2019 Sarah Walker. * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. * * 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 @@ -197,12 +197,12 @@ extern "C" { #endif extern void device_init(void); -extern void device_set_context(device_context_t *c, const device_t *dev, int inst); +extern void device_set_context(device_context_t *ctx, const device_t *dev, int inst); extern void device_context(const device_t *dev); extern void device_context_inst(const device_t *dev, int inst); extern void device_context_restore(void); -extern void *device_add(const device_t *d); -extern void *device_add_linked(const device_t *d, void *priv); +extern void *device_add(const device_t *dev); +extern void *device_add_linked(const device_t *dev, void *priv); extern void *device_add_params(const device_t *dev, void *params); extern void device_add_ex(const device_t *dev, void *priv); extern void device_add_ex_params(const device_t *dev, void *priv, void *params); @@ -223,27 +223,27 @@ extern void device_get_name(const device_t *dev, int bus, char *name); extern int device_has_config(const device_t *dev); extern const char *device_get_bios_file(const device_t *dev, const char *internal_name, int file_no); -extern int device_is_valid(const device_t *, int m); +extern int device_is_valid(const device_t *, int mch); extern const device_t* device_context_get_device(void); extern int device_get_config_int(const char *name); -extern int device_get_config_int_ex(const char *s, int dflt_int); +extern int device_get_config_int_ex(const char *str, int def); extern int device_get_config_hex16(const char *name); extern int device_get_config_hex20(const char *name); -extern int device_get_config_mac(const char *name, int dflt_int); -extern void device_set_config_int(const char *s, int val); -extern void device_set_config_hex16(const char *s, int val); -extern void device_set_config_hex20(const char *s, int val); -extern void device_set_config_mac(const char *s, int val); +extern int device_get_config_mac(const char *name, int def); +extern void device_set_config_int(const char *str, int val); +extern void device_set_config_hex16(const char *str, int val); +extern void device_set_config_hex20(const char *str, int val); +extern void device_set_config_mac(const char *str, int val); extern const char *device_get_config_string(const char *name); extern int device_get_instance(void); #define device_get_config_bios device_get_config_string extern const char *device_get_internal_name(const device_t *dev); -extern int machine_get_config_int(char *s); -extern char *machine_get_config_string(char *s); +extern int machine_get_config_int(char *str); +extern char *machine_get_config_string(char *str); extern const device_t device_none; extern const device_t device_internal; From 1ee305d0f3979ab8b04ee777f2cc0a1d3da8e3ff Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 9 Jan 2025 23:22:00 -0500 Subject: [PATCH 19/65] devices -> midi_out_devices in sound/midi.c --- src/sound/midi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sound/midi.c b/src/sound/midi.c index 78794ef24..e9b4a82b6 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -71,7 +71,7 @@ typedef struct const device_t *device; } MIDI_OUT_DEVICE, MIDI_IN_DEVICE; -static const MIDI_OUT_DEVICE devices[] = { +static const MIDI_OUT_DEVICE midi_out_devices[] = { // clang-format off { &device_none }, #ifdef USE_FLUIDSYNTH @@ -106,8 +106,8 @@ static const MIDI_IN_DEVICE midi_in_devices[] = { int midi_out_device_available(int card) { - if (devices[card].device) - return device_available(devices[card].device); + if (midi_out_devices[card].device) + return device_available(midi_out_devices[card].device); return 1; } @@ -115,21 +115,21 @@ midi_out_device_available(int card) const device_t * midi_out_device_getdevice(int card) { - return devices[card].device; + return midi_out_devices[card].device; } int midi_out_device_has_config(int card) { - if (!devices[card].device) + if (!midi_out_devices[card].device) return 0; - return devices[card].device->config ? 1 : 0; + return midi_out_devices[card].device->config ? 1 : 0; } const char * midi_out_device_get_internal_name(int card) { - return device_get_internal_name(devices[card].device); + return device_get_internal_name(midi_out_devices[card].device); } int @@ -137,8 +137,8 @@ midi_out_device_get_from_internal_name(char *s) { int c = 0; - while (devices[c].device != NULL) { - if (!strcmp(devices[c].device->internal_name, s)) + while (midi_out_devices[c].device != NULL) { + if (!strcmp(midi_out_devices[c].device->internal_name, s)) return c; c++; } @@ -149,8 +149,8 @@ midi_out_device_get_from_internal_name(char *s) void midi_out_device_init(void) { - if ((midi_output_device_current > 0) && devices[midi_output_device_current].device) - device_add(devices[midi_output_device_current].device); + if ((midi_output_device_current > 0) && midi_out_devices[midi_output_device_current].device) + device_add(midi_out_devices[midi_output_device_current].device); midi_output_device_last = midi_output_device_current; } From cbbf91b790d585421b8b97697a442789f1a35674 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 01:09:09 -0500 Subject: [PATCH 20/65] Add other BIOS versions to ibmpc --- src/machine/m_xt.c | 60 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index db511c332..b31e58bdf 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -61,6 +61,29 @@ machine_xt_common_init(const machine_t *model, int fixed_floppy) static const device_config_t ibmpc_config[] = { // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5150_5700671", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "5700671 (10/19/81)", .internal_name = "ibm5150_5700671", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_19OCT81_5700671_U33.BIN", "" } }, + { .name = "5700051 (04/24/81)", .internal_name = "ibm5150_5700051", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_24APR81_5700051_U33.BIN", "" } }, + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, + { .files_no = 0 } + }, + }, { .name = "enable_5161", .description = "IBM 5161 Expansion Unit", @@ -94,27 +117,36 @@ const device_t ibmpc_device = { int machine_pc_init(const machine_t *model) { - int ret; - uint8_t enable_5161; - uint8_t enable_basic; + int ret = 0; + int ret2; + uint8_t enable_5161; + uint8_t enable_basic; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; device_context(model->device); enable_5161 = machine_get_config_int("enable_5161"); enable_basic = machine_get_config_int("enable_basic"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 40960, 0); device_context_restore(); - ret = bios_load_linear("roms/machines/ibmpc/BIOS_5150_24APR81_U33.BIN", - 0x000fe000, 40960, 0); - if (enable_basic && ret) { - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", - 0x000f6000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", - 0x000f8000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin", - 0x000fa000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin", - 0x000fc000, 8192, 0); + ret2 = bios_load_aux_linear("roms/machines/ibmpc/ibm-basic-1.00.rom", + 0x000f6000, 32768, 0); + if (!ret2) { + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", + 0x000f6000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", + 0x000f8000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin", + 0x000fa000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin", + 0x000fc000, 8192, 0); + } } if (bios_only || !ret) From 312536f51e14bc8f924521b71b2edb815e707c9b Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 01:09:27 -0500 Subject: [PATCH 21/65] A few updates to ibmpc82 --- src/machine/m_xt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index b31e58bdf..d38dd6bc6 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -224,7 +224,7 @@ machine_pc82_init(const machine_t *model) int ret2; uint8_t enable_5161; uint8_t enable_basic; - const char* fn; + const char *fn; /* No ROMs available. */ if (!device_available(model->device)) @@ -241,13 +241,13 @@ machine_pc82_init(const machine_t *model) ret2 = bios_load_aux_linear("roms/machines/ibmpc82/ibm-basic-1.10.rom", 0x000f6000, 32768, 0); if (!ret2) { - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f6", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U29 - 5000019.bin", 0x000f6000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f8", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U30 - 5000021.bin", 0x000f8000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fa", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U31 - 5000022.bin", 0x000fa000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fc", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U32 - 5000023.bin", 0x000fc000, 8192, 0); } } From c01022db46ec2a78ca9142798770ccc60dc09d31 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 02:33:13 -0500 Subject: [PATCH 22/65] Add other BIOS versions to ibmxt (82) --- src/machine/m_xt.c | 65 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index d38dd6bc6..9a56c4870 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -267,12 +267,45 @@ machine_pc82_init(const machine_t *model) static const device_config_t ibmxt_config[] = { // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5160_1501512_5000027", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1501512 (11/08/82)", .internal_name = "ibm5160_1501512_5000027", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } }, +#if 0 + { .name = "1501512 (11/08/82) (Alt)", .internal_name = "ibm5160_1501512_6359116", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } }, + { .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, +#endif + { .files_no = 0 } + }, + }, { .name = "enable_5161", .description = "IBM 5161 Expansion Unit", .type = CONFIG_BINARY, .default_int = 1 }, + { + .name = "enable_basic", + .description = "IBM Cassette Basic", + .type = CONFIG_BINARY, + .default_int = 1 + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -294,26 +327,28 @@ const device_t ibmxt_device = { int machine_xt_init(const machine_t *model) { - int ret; - uint8_t enable_5161; - uint8_t enable_basic; + int ret; + uint8_t enable_5161; + uint8_t enable_basic; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; device_context(model->device); enable_5161 = machine_get_config_int("enable_5161"); - device_context_restore(); + enable_basic = machine_get_config_int("enable_basic"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000); - ret = bios_load_linear("roms/machines/ibmxt/xt.rom", - 0x000f0000, 65536, 0); - if (!ret) { - ret = bios_load_linear("roms/machines/ibmxt/1501512.u18", - 0x000fe000, 65536, 0x6000); - if (ret) { - bios_load_aux_linear("roms/machines/ibmxt/1501512.u18", - 0x000f8000, 24576, 0); - bios_load_aux_linear("roms/machines/ibmxt/5000027.u19", - 0x000f0000, 32768, 0); - } + if (enable_basic && ret) { + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); + (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); } + device_context_restore(); if (bios_only || !ret) return ret; From a6b8f826fee27d55710c2e3019e68e550a8e17cc Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 03:24:12 -0500 Subject: [PATCH 23/65] Fixes --- src/machine/m_xt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 9a56c4870..1977c88df 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -278,11 +278,11 @@ static const device_config_t ibmxt_config[] = { .bios = { { .name = "1501512 (11/08/82)", .internal_name = "ibm5160_1501512_5000027", .bios_type = BIOS_NORMAL, .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } }, -#if 0 { .name = "1501512 (11/08/82) (Alt)", .internal_name = "ibm5160_1501512_6359116", .bios_type = BIOS_NORMAL, .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } }, { .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL, - .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, +#if 0 // The following are Diagnostic ROMs. { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, @@ -327,7 +327,7 @@ const device_t ibmxt_device = { int machine_xt_init(const machine_t *model) { - int ret; + int ret = 0; uint8_t enable_5161; uint8_t enable_basic; const char *fn; From 3ffaf21f605a00046af145d17bc40db238d8fd69 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 03:24:38 -0500 Subject: [PATCH 24/65] Add other BIOS versions to ibmxt (86) --- src/machine/m_xt.c | 50 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 1977c88df..7b59686d6 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -383,6 +383,33 @@ machine_genxt_init(const machine_t *model) static const device_config_t ibmxt86_config[] = { // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5160_050986", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1501512 (05/09/86)", .internal_name = "ibm5160_050986", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } }, + { .name = "5000026 (01/10/86)", .internal_name = "ibm5160_011086", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0851_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0854_27256_F000.BIN", "" } }, + { .name = "1501512 (01/10/86) (Alt)", .internal_name = "ibm5160_011086_alt", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" } }, +#if 0 + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, +#endif + { .files_no = 0 } + }, + }, { .name = "enable_5161", .description = "IBM 5161 Expansion Unit", @@ -410,21 +437,26 @@ const device_t ibmxt86_device = { int machine_xt86_init(const machine_t *model) { - int ret; - uint8_t enable_5161; + int ret = 0; + uint8_t enable_5161; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; device_context(model->device); enable_5161 = machine_get_config_int("enable_5161"); - device_context_restore(); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000); - ret = bios_load_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000fe000, 65536, 0x6000); if (ret) { - (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000f8000, 24576, 0); - (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", - 0x000f0000, 32768, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); + (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); } + device_context_restore(); if (bios_only || !ret) return ret; From 78a81b0d7fda7223400dc0eb424d54bab893e6d2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 10 Jan 2025 21:56:04 +0100 Subject: [PATCH 25/65] AT / PS/2 keyboard: It turns out a few other commands also cancel the pending command, fixes #4981. --- src/device/keyboard_at.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 882174e4e..af3d5d5fc 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1961,18 +1961,24 @@ keyboard_at_write(void *priv) } } else { if (dev->flags & FLAG_CTRLDAT) { - /* Special case - another command during another command that wants input - proceed + /* + Special case - another command during another command that wants input - proceed as normal but do not cancel the command (so keep waiting for input), unless the - command in progress is ED (Set/reset LEDs). */ - if (val == 0xed) { - keyboard_scan = 1; + command in progress is ED (Set/reset LEDs). + + It appears to also apply to command EE (Echo), F4 (Enable), F5 (Diable and Set + Default), and F6 (SetDefault). + */ + if ((val == 0xed) || (val == 0xee) || (val == 0xf4) || (val == 0xf5) || (val == 0xf6)) dev->flags &= ~FLAG_CTRLDAT; - } else + else dev->state = DEV_STATE_MAIN_WANT_IN; } switch (val) { case 0xed: /* set/reset LEDs */ + if ((dev->flags & FLAG_CTRLDAT) && (dev->command == 0xed)) + keyboard_scan = 1; dev->command = val; keyboard_at_log("%s: set/reset LEDs\n", dev->name); dev->flags |= FLAG_CTRLDAT; From f774618b1eb59df04a6b56b2053e65b3cd7db2f1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 10 Jan 2025 23:40:54 +0100 Subject: [PATCH 26/65] SiS 5513 PCI to ISA bridge: fix a typo in a revision check. --- src/chipset/sis_5513_p2i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c index ef9a6746d..4205db161 100644 --- a/src/chipset/sis_5513_p2i.c +++ b/src/chipset/sis_5513_p2i.c @@ -106,7 +106,7 @@ sis_5513_apc_reset(sis_5513_pci_to_isa_t *dev) { memset(dev->apc_regs, 0x00, sizeof(dev->apc_regs)); - if (dev->rev == 0b0) { + if (dev->rev == 0xb0) { dev->apc_regs[0x03] = 0x80; dev->apc_regs[0x04] = 0x38; dev->apc_regs[0x07] = 0x01; From 28c296fc753046b7455a97265ae58b4bf9bcbc4d Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2025 00:12:13 +0100 Subject: [PATCH 27/65] More case ranges in src/chipset/ali1531.c. --- src/chipset/ali1531.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index 9eb75f7cd..06d0a0a60 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -225,12 +225,8 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) ali1531_shadow_recalc(val, dev); break; - case 0x50: - case 0x51: - case 0x52: - case 0x54: - case 0x55: - case 0x56: + case 0x50 ... 0x52: + case 0x54 ... 0x56: dev->pci_conf[addr] = val; break; @@ -247,8 +243,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x86; break; - case 0x59: - case 0x5a: + case 0x59 ... 0x5a: case 0x5c: dev->pci_conf[addr] = val; break; @@ -270,8 +265,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); break; - case 0x70: - case 0x71: + case 0x70 ... 0x71: dev->pci_conf[addr] = val; break; @@ -283,8 +277,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x2b; break; - case 0x76: - case 0x77: + case 0x76 ... 0x77: dev->pci_conf[addr] = val; break; From 035b8deee2cf2b9ed6ad34d5ee0c220b6090a7fa Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 10 Jan 2025 22:53:52 -0500 Subject: [PATCH 28/65] Random warning fixes --- src/cdrom/cdrom_image_backend.c | 4 +-- src/cdrom/cdrom_mitsumi.c | 47 +++++++++++++++------------------ src/qt/dummy_cdrom_ioctl.c | 7 ++++- src/unix/dummy_cdrom_ioctl.c | 7 ++++- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 9d065a0cb..ad1756055 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -1195,7 +1195,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) for (int i = 0; i < 3; i++) { lead[i] = cdi->tracks_num; - (void *) cdi_insert_track(cdi, session, 0xa0 + i); + (void) cdi_insert_track(cdi, session, 0xa0 + i); } cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); @@ -1393,7 +1393,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) for (int i = 0; i < 3; i++) { lead[i] = cdi->tracks_num; - (void *) cdi_insert_track(cdi, session, 0xa0 + i); + (void) cdi_insert_track(cdi, session, 0xa0 + i); } cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); diff --git a/src/cdrom/cdrom_mitsumi.c b/src/cdrom/cdrom_mitsumi.c index 0cebfe7f6..c3c362b1b 100644 --- a/src/cdrom/cdrom_mitsumi.c +++ b/src/cdrom/cdrom_mitsumi.c @@ -156,9 +156,9 @@ mitsumi_cdrom_is_ready(const cdrom_t *dev) static void mitsumi_cdrom_reset(mcd_t *dev) { - cdrom_t cdrom; - - dev->stat = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | STAT_CHANGE) : 0; + cdrom_t *cdrom = calloc(1, sizeof(cdrom_t)); + + dev->stat = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | STAT_CHANGE) : 0; dev->cmdrd_count = 0; dev->cmdbuf_count = 0; dev->buf_count = 0; @@ -176,12 +176,12 @@ mitsumi_cdrom_reset(mcd_t *dev) static int mitsumi_cdrom_read_sector(mcd_t *dev, int first) { - cdrom_t cdrom; + cdrom_t *cdrom = calloc(1, sizeof(cdrom_t)); uint8_t status; - int ret; + int ret = 0; if (dev->drvmode == DRV_MODE_CDDA) { - status = cdrom_mitsumi_audio_play(&cdrom, dev->readmsf, dev->readcount); + status = cdrom_mitsumi_audio_play(cdrom, dev->readmsf, dev->readcount); if (status == 1) return status; else @@ -195,15 +195,15 @@ mitsumi_cdrom_read_sector(mcd_t *dev, int first) dev->data = 0; return 0; } - cdrom_stop(&cdrom); - ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0); + cdrom_stop(cdrom); + ret = cdrom_readsector_raw(cdrom, dev->buf, cdrom->seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0); if (ret <= 0) return 0; if (dev->mode & 0x40) { dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff); dev->buf[13] = CD_BCD((dev->readmsf >> 8) & 0xff); } - dev->readmsf = cdrom_lba_to_msf_accurate(cdrom.seek_pos + 1); + dev->readmsf = cdrom_lba_to_msf_accurate(cdrom->seek_pos + 1); dev->buf_count = dev->dmalen + 1; dev->buf_idx = 0; dev->data = 1; @@ -224,7 +224,7 @@ static uint8_t mitsumi_cdrom_in(uint16_t port, void *priv) { mcd_t *dev = (mcd_t *) priv; - uint8_t ret; + uint8_t ret = 0xff; pclog("Mitsumi CD-ROM IN=%03x\n", port); switch (port & 1) { @@ -259,14 +259,14 @@ mitsumi_cdrom_in(uint16_t port, void *priv) break; } - return 0xff; + return ret; } static void mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) { mcd_t *dev = (mcd_t *) priv; - cdrom_t cdrom; + cdrom_t *cdrom = calloc(1, sizeof(cdrom_t)); pclog("Mitsumi CD-ROM OUT=%03x, val=%02x\n", port, val); switch (port & 1) { @@ -348,19 +348,19 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) break; } if (!dev->cmdrd_count) - dev->stat = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; + dev->stat = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; return; } dev->cmd = val; dev->cmdbuf_idx = 0; dev->cmdrd_count = 0; dev->cmdbuf_count = 1; - dev->cmdbuf[0] = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; + dev->cmdbuf[0] = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; dev->data = 0; switch (val) { case CMD_GET_INFO: - if (mitsumi_cdrom_is_ready(&cdrom)) { - cdrom_get_track_buffer(&cdrom, &(dev->cmdbuf[1])); + if (mitsumi_cdrom_is_ready(cdrom)) { + cdrom_get_track_buffer(cdrom, &(dev->cmdbuf[1])); dev->cmdbuf_count = 10; dev->readcount = 0; } else { @@ -369,8 +369,8 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) } break; case CMD_GET_Q: - if (mitsumi_cdrom_is_ready(&cdrom)) { - cdrom_get_q(&cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC); + if (mitsumi_cdrom_is_ready(cdrom)) { + cdrom_get_q(cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC); dev->cmdbuf_count = 11; dev->readcount = 0; } else { @@ -386,7 +386,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) break; case CMD_STOPCDDA: case CMD_STOP: - cdrom_stop(&cdrom); + cdrom_stop(cdrom); dev->drvmode = DRV_MODE_STOP; dev->cur_toc_track = 0; break; @@ -395,7 +395,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) break; case CMD_READ1X: case CMD_READ2X: - if (mitsumi_cdrom_is_ready(&cdrom)) { + if (mitsumi_cdrom_is_ready(cdrom)) { dev->readcount = 0; dev->drvmode = (val == CMD_READ1X) ? DRV_MODE_CDDA : DRV_MODE_READ; dev->cmdrd_count = 6; @@ -411,7 +411,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) dev->cmdbuf_count = 3; break; case CMD_EJECT: - cdrom_stop(&cdrom); + cdrom_stop(cdrom); cdrom_eject(0); dev->readcount = 0; break; @@ -440,10 +440,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) static void * mitsumi_cdrom_init(UNUSED(const device_t *info)) { - mcd_t *dev; - - dev = malloc(sizeof(mcd_t)); - memset(dev, 0x00, sizeof(mcd_t)); + mcd_t *dev = calloc(1, sizeof(mcd_t)); dev->irq = MCD_DEFAULT_IRQ; dev->dma = MCD_DEFAULT_DMA; diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index 4ed0333a7..fb0224bc6 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -134,9 +134,14 @@ plat_cdrom_get_last_block(void *local) } int -plat_cdrom_ext_medium_changed(void *local) +plat_cdrom_ext_medium_changed(UNUSED(void *local)) { +#if 0 dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + + plat_cdrom_read_toc(ioctl); +#endif + int ret = 0; dummy_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret); diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index 4ed0333a7..fb0224bc6 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -134,9 +134,14 @@ plat_cdrom_get_last_block(void *local) } int -plat_cdrom_ext_medium_changed(void *local) +plat_cdrom_ext_medium_changed(UNUSED(void *local)) { +#if 0 dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; + + plat_cdrom_read_toc(ioctl); +#endif + int ret = 0; dummy_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret); From 0931e82bd195fd4b8fe0bc774f7ba27ad043e7e1 Mon Sep 17 00:00:00 2001 From: GetDizzy Date: Sat, 11 Jan 2025 00:10:38 -0500 Subject: [PATCH 29/65] Add BIOS selection to Packard Bell PB450. --- src/machine/m_at_386dx_486.c | 51 +++++++++++++++++++++++++++++++++--- src/machine/machine_table.c | 3 ++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 1c35d7290..2a4b6f3c6 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -684,20 +684,64 @@ machine_at_403tg_d_mr_init(const machine_t *model) return ret; } +static const device_config_t pb450_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "pci10a", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "PCI 1.0A", .internal_name = "pci10a", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/OPTI802.bin", "" } }, + { .name = "PNP 1.1A", .internal_name = "pnp11a", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/PNP11A.bin", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t pb450_device = { + .name = "Packard Bell PB450 Devices", + .internal_name = "pb450_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pb450_config +}; + int machine_at_pb450_init(const machine_t *model) { - int ret; + int ret = 0; + const char* fn; - ret = bios_load_linear("roms/machines/pb450/OPTI802.bin", - 0x000e0000, 131072, 0); + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + device_context(model->device); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); + if (bios_only || !ret) return ret; machine_at_common_init_ex(model, 2); device_add(&ide_vlb_2ch_device); + /* TODO: Detect if we're using the PNP and not the PCI ROM and don't add these? */ pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -713,6 +757,7 @@ machine_at_pb450_init(const machine_t *model) device_add(&fdc37c665_ide_device); device_add(&ide_opti611_vlb_sec_device); device_add(&intel_flash_bxt_device); + /* TODO: Detect if we're using the PNP and not the PCI ROM and don't add this? */ device_add(&phoenix_486_jumper_pci_device); return ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 3fc3bcc8a..06aea8597 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -63,6 +63,7 @@ extern const device_t ibmxt_device; extern const device_t ibmxt86_device; extern const device_t ibmat_device; extern const device_t ibmxt286_device; +extern const device_t pb450_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -6888,7 +6889,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &pb450_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = &gd5428_vlb_onboard_device, From 3b092bcdb2ec8e2b9194c4c509a99ac9fed4b607 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 01:31:57 -0500 Subject: [PATCH 30/65] Cleaning --- src/config.c | 100 ++++++++++++++---------------- src/game/joystick_standard.c | 21 +++---- src/game/joystick_sw_pad.c | 25 ++++---- src/qt/qt_settingsinput.cpp | 16 ++--- src/qt/sdl_joystick.c | 108 ++++++++++++++++----------------- src/qt/win_joystick_rawinput.c | 59 +++++++++--------- 6 files changed, 155 insertions(+), 174 deletions(-) diff --git a/src/config.c b/src/config.c index 2f1561f18..5119d45ff 100644 --- a/src/config.c +++ b/src/config.c @@ -475,8 +475,6 @@ load_input_devices(void) { ini_section_t cat = ini_find_section(config, "Input devices"); char temp[512]; - int c; - int d; char *p; p = ini_section_get_string(cat, "mouse_type", NULL); @@ -495,8 +493,8 @@ load_input_devices(void) /* Workaround for ini_section_get_int returning 0 on non-integer data */ joystick_type = joystick_get_from_internal_name("2axis_2button"); else { - c = ini_section_get_int(cat, "joystick_type", 8); - switch (c) { + int js = ini_section_get_int(cat, "joystick_type", 8); + switch (js) { case JS_TYPE_2AXIS_4BUTTON: joystick_type = joystick_get_from_internal_name("2axis_4button"); break; @@ -527,25 +525,25 @@ load_input_devices(void) } else joystick_type = JS_TYPE_NONE; - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - sprintf(temp, "joystick_%i_nr", c); - joystick_state[c].plat_joystick_nr = ini_section_get_int(cat, temp, 0); + for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { + sprintf(temp, "joystick_%i_nr", js); + joystick_state[js].plat_joystick_nr = ini_section_get_int(cat, temp, 0); - if (joystick_state[c].plat_joystick_nr) { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) { - sprintf(temp, "joystick_%i_axis_%i", c, d); - joystick_state[c].axis_mapping[d] = ini_section_get_int(cat, temp, d); + if (joystick_state[js].plat_joystick_nr) { + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) { + sprintf(temp, "joystick_%i_axis_%i", js, axis_nr); + joystick_state[js].axis_mapping[axis_nr] = ini_section_get_int(cat, temp, axis_nr); } - for (d = 0; d < joystick_get_button_count(joystick_type); d++) { - sprintf(temp, "joystick_%i_button_%i", c, d); - joystick_state[c].button_mapping[d] = ini_section_get_int(cat, temp, d); + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) { + sprintf(temp, "joystick_%i_button_%i", js, button_nr); + joystick_state[js].button_mapping[button_nr] = ini_section_get_int(cat, temp, button_nr); } - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { - sprintf(temp, "joystick_%i_pov_%i", c, d); + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { + sprintf(temp, "joystick_%i_pov_%i", js, pov_nr); p = ini_section_get_string(cat, temp, "0, 0"); - joystick_state[c].pov_mapping[d][0] = joystick_state[c].pov_mapping[d][1] = 0; - sscanf(p, "%i, %i", &joystick_state[c].pov_mapping[d][0], - &joystick_state[c].pov_mapping[d][1]); + joystick_state[js].pov_mapping[js][pov_nr] = joystick_state[js].pov_mapping[pov_nr][1] = 0; + sscanf(p, "%i, %i", &joystick_state[js].pov_mapping[pov_nr][0], + &joystick_state[js].pov_mapping[pov_nr][1]); } } } @@ -743,11 +741,9 @@ load_ports(void) ini_section_t cat = ini_find_section(config, "Ports (COM & LPT)"); char *p; char temp[512]; - int c; - memset(temp, 0, sizeof(temp)); - for (c = 0; c < SERIAL_MAX; c++) { + for (int c = 0; c < SERIAL_MAX; c++) { sprintf(temp, "serial%d_enabled", c + 1); com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1); @@ -758,7 +754,7 @@ load_ports(void) config_log("Serial Port %d: passthrough enabled.\n\n", c + 1); } - for (c = 0; c < PARALLEL_MAX; c++) { + for (int c = 0; c < PARALLEL_MAX; c++) { sprintf(temp, "lpt%d_enabled", c + 1); lpt_ports[c].enabled = !!ini_section_get_int(cat, temp, (c == 0) ? 1 : 0); @@ -776,11 +772,10 @@ load_storage_controllers(void) ini_section_t migration_cat; char *p; char temp[512]; - int c; int min = 0; int free_p = 0; - for (c = min; c < SCSI_CARD_MAX; c++) { + for (int c = min; c < SCSI_CARD_MAX; c++) { sprintf(temp, "scsicard_%d", c + 1); p = ini_section_get_string(cat, temp, NULL); @@ -932,7 +927,7 @@ load_storage_controllers(void) ini_section_delete_var(cat, "cassette_ui_writeprot"); } - for (c = 0; c < 2; c++) { + for (int c = 0; c < 2; c++) { sprintf(temp, "cartridge_%02i_fn", c + 1); p = ini_section_get_string(cat, temp, ""); @@ -2140,50 +2135,49 @@ save_input_devices(void) ini_section_t cat = ini_find_or_create_section(config, "Input devices"); char temp[512]; char tmp2[512]; - int c; - int d; ini_section_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type)); if (!joystick_type) { ini_section_delete_var(cat, "joystick_type"); - for (c = 0; c < 16; c++) { - sprintf(tmp2, "joystick_%i_nr", c); + for (int js = 0; js < MAX_PLAT_JOYSTICKS; js++) { + sprintf(tmp2, "joystick_%i_nr", js); ini_section_delete_var(cat, tmp2); - for (d = 0; d < 16; d++) { - sprintf(tmp2, "joystick_%i_axis_%i", c, d); + for (int axis_nr = 0; axis_nr < 16; axis_nr++) { + sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr); ini_section_delete_var(cat, tmp2); } - for (d = 0; d < 16; d++) { - sprintf(tmp2, "joystick_%i_button_%i", c, d); + for (int button_nr = 0; button_nr < 16; button_nr++) { + sprintf(tmp2, "joystick_%i_button_%i", js, button_nr); ini_section_delete_var(cat, tmp2); } - for (d = 0; d < 16; d++) { - sprintf(tmp2, "joystick_%i_pov_%i", c, d); + for (int pov_nr = 0; pov_nr < 16; pov_nr++) { + sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr); ini_section_delete_var(cat, tmp2); } } } else { ini_section_set_string(cat, "joystick_type", joystick_get_internal_name(joystick_type)); - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - sprintf(tmp2, "joystick_%i_nr", c); - ini_section_set_int(cat, tmp2, joystick_state[c].plat_joystick_nr); + for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { + sprintf(tmp2, "joystick_%i_nr", js); + ini_section_set_int(cat, tmp2, joystick_state[js].plat_joystick_nr); - if (joystick_state[c].plat_joystick_nr) { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) { - sprintf(tmp2, "joystick_%i_axis_%i", c, d); - ini_section_set_int(cat, tmp2, joystick_state[c].axis_mapping[d]); + if (joystick_state[js].plat_joystick_nr) { + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) { + sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr); + ini_section_set_int(cat, tmp2, joystick_state[js].axis_mapping[axis_nr]); } - for (d = 0; d < joystick_get_button_count(joystick_type); d++) { - sprintf(tmp2, "joystick_%i_button_%i", c, d); - ini_section_set_int(cat, tmp2, joystick_state[c].button_mapping[d]); + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) { + sprintf(tmp2, "joystick_%i_button_%i", js, button_nr); + ini_section_set_int(cat, tmp2, joystick_state[js].button_mapping[button_nr]); } - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { - sprintf(tmp2, "joystick_%i_pov_%i", c, d); - sprintf(temp, "%i, %i", joystick_state[c].pov_mapping[d][0], joystick_state[c].pov_mapping[d][1]); + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { + sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr); + sprintf(temp, "%i, %i", joystick_state[js].pov_mapping[pov_nr][0], + joystick_state[js].pov_mapping[pov_nr][1]); ini_section_set_string(cat, tmp2, temp); } } @@ -2341,10 +2335,8 @@ save_ports(void) { ini_section_t cat = ini_find_or_create_section(config, "Ports (COM & LPT)"); char temp[512]; - int c; - int d; - for (c = 0; c < SERIAL_MAX; c++) { + for (int c = 0; c < SERIAL_MAX; c++) { sprintf(temp, "serial%d_enabled", c + 1); if (((c < 2) && com_ports[c].enabled) || ((c >= 2) && !com_ports[c].enabled)) ini_section_delete_var(cat, temp); @@ -2358,9 +2350,9 @@ save_ports(void) ini_section_delete_var(cat, temp); } - for (c = 0; c < PARALLEL_MAX; c++) { + for (int c = 0; c < PARALLEL_MAX; c++) { sprintf(temp, "lpt%d_enabled", c + 1); - d = (c == 0) ? 1 : 0; + int d = (c == 0) ? 1 : 0; if (lpt_ports[c].enabled == d) ini_section_delete_var(cat, temp); else diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index 1d1568738..201574126 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -62,17 +62,13 @@ joystick_standard_read(UNUSED(void *priv)) { uint8_t ret = 0xf0; - if (JOYSTICK_PRESENT(0)) { - if (joystick_state[0].button[0]) - ret &= ~0x10; - if (joystick_state[0].button[1]) - ret &= ~0x20; - } - if (JOYSTICK_PRESENT(1)) { - if (joystick_state[1].button[0]) - ret &= ~0x40; - if (joystick_state[1].button[1]) - ret &= ~0x80; + for (int js = 0; js < 2; js++) { + if (JOYSTICK_PRESENT(js)) { + if (joystick_state[js].button[0]) + ret &= ~0x10; + if (joystick_state[js].button[1]) + ret &= ~0x20; + } } return ret; @@ -140,9 +136,7 @@ joystick_standard_read_axis_4button(UNUSED(void *priv), int axis) case 1: return joystick_state[0].axis[1]; case 2: - return 0; case 3: - return 0; default: return 0; } @@ -162,7 +156,6 @@ joystick_standard_read_axis_3axis(UNUSED(void *priv), int axis) case 2: return joystick_state[0].axis[2]; case 3: - return 0; default: return 0; } diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index cab008d0a..711a5fa1e 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -119,8 +119,7 @@ sw_parity(uint16_t data) static void * sw_init(void) { - sw_data *sw = (sw_data *) malloc(sizeof(sw_data)); - memset(sw, 0, sizeof(sw_data)); + sw_data *sw = (sw_data *) calloc(1, sizeof(sw_data)); timer_add(&sw->poll_timer, sw_timer_over, sw, 0); timer_add(&sw->trigger_timer, sw_trigger_timer_over, sw, 0); @@ -191,24 +190,24 @@ sw_write(void *priv) sw->poll_data = 1; } - for (uint8_t c = 0; c < 4; c++) { + for (uint8_t js = 0; js < MAX_JOYSTICKS; js++) { uint16_t data = 0x3fff; - if (!JOYSTICK_PRESENT(c)) + if (!JOYSTICK_PRESENT(js)) break; - if (joystick_state[c].axis[1] < -16383) + if (joystick_state[js].axis[1] < -16383) data &= ~1; - if (joystick_state[c].axis[1] > 16383) + if (joystick_state[js].axis[1] > 16383) data &= ~2; - if (joystick_state[c].axis[0] > 16383) + if (joystick_state[js].axis[0] > 16383) data &= ~4; - if (joystick_state[c].axis[0] < -16383) + if (joystick_state[js].axis[0] < -16383) data &= ~8; - for (uint8_t b = 0; b < 10; b++) { - if (joystick_state[c].button[b]) - data &= ~(1 << (b + 4)); + for (uint8_t button_nr = 0; button_nr < 10; button_nr++) { + if (joystick_state[js].button[button_nr]) + data &= ~(1 << (button_nr + 4)); } if (sw_parity(data)) @@ -216,10 +215,10 @@ sw_write(void *priv) if (sw->poll_mode) { sw->poll_left += 5; - sw->poll_data |= (data << (c * 15 + 3)); + sw->poll_data |= (data << (js * 15 + 3)); } else { sw->poll_left += 15; - sw->poll_data |= (data << (c * 15 + 1)); + sw->poll_data |= (data << (js * 15 + 1)); } } } diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 05e44c2c0..d7b69442c 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -178,15 +178,17 @@ updateJoystickConfig(int type, int joystick_nr, QWidget *parent) joystick_state[joystick_nr].plat_joystick_nr = jc.selectedDevice(); if (joystick_state[joystick_nr].plat_joystick_nr) { - for (int c = 0; c < joystick_get_axis_count(type); c++) { - joystick_state[joystick_nr].axis_mapping[c] = get_axis(jc, c, joystick_nr); + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(type); axis_nr++) { + joystick_state[joystick_nr].axis_mapping[axis_nr] = get_axis(jc, axis_nr, joystick_nr); } - for (int c = 0; c < joystick_get_button_count(type); c++) { - joystick_state[joystick_nr].button_mapping[c] = jc.selectedButton(c); + + for (int button_nr = 0; button_nr < joystick_get_button_count(type); button_nr++) { + joystick_state[joystick_nr].button_mapping[button_nr] = jc.selectedButton(button_nr); } - for (int c = 0; c < joystick_get_pov_count(type) * 2; c += 2) { - joystick_state[joystick_nr].pov_mapping[c][0] = get_pov(jc, c, joystick_nr); - joystick_state[joystick_nr].pov_mapping[c][1] = get_pov(jc, c + 1, joystick_nr); + + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(type) * 2; pov_nr += 2) { + joystick_state[joystick_nr].pov_mapping[pov_nr][0] = get_pov(jc, pov_nr, joystick_nr); + joystick_state[joystick_nr].pov_mapping[pov_nr][1] = get_pov(jc, pov_nr + 1, joystick_nr); } } } diff --git a/src/qt/sdl_joystick.c b/src/qt/sdl_joystick.c index d56612872..221e12078 100644 --- a/src/qt/sdl_joystick.c +++ b/src/qt/sdl_joystick.c @@ -54,28 +54,26 @@ joystick_init(void) joysticks_present = SDL_NumJoysticks(); memset(sdl_joy, 0, sizeof(sdl_joy)); - for (int c = 0; c < joysticks_present; c++) { - sdl_joy[c] = SDL_JoystickOpen(c); + for (int js = 0; js < joysticks_present; js++) { + sdl_joy[js] = SDL_JoystickOpen(js); - if (sdl_joy[c]) { - int d; + if (sdl_joy[js]) { + strncpy(plat_joystick_state[js].name, SDL_JoystickNameForIndex(js), 64); + plat_joystick_state[js].nr_axes = MIN(SDL_JoystickNumAxes(sdl_joy[js]), MAX_JOY_AXES); + plat_joystick_state[js].nr_buttons = MIN(SDL_JoystickNumButtons(sdl_joy[js]), MAX_JOY_BUTTONS); + plat_joystick_state[js].nr_povs = MIN(SDL_JoystickNumHats(sdl_joy[js]), MAX_JOY_POVS); - strncpy(plat_joystick_state[c].name, SDL_JoystickNameForIndex(c), 64); - plat_joystick_state[c].nr_axes = MIN(SDL_JoystickNumAxes(sdl_joy[c]), MAX_JOY_AXES); - plat_joystick_state[c].nr_buttons = MIN(SDL_JoystickNumButtons(sdl_joy[c]), MAX_JOY_BUTTONS); - plat_joystick_state[c].nr_povs = MIN(SDL_JoystickNumHats(sdl_joy[c]), MAX_JOY_POVS); - - for (d = 0; d < plat_joystick_state[c].nr_axes; d++) { - snprintf(plat_joystick_state[c].axis[d].name, sizeof(plat_joystick_state[c].axis[d].name), "Axis %i", d); - plat_joystick_state[c].axis[d].id = d; + for (int axis_nr = 0; axis_nr < plat_joystick_state[js].nr_axes; axis_nr++) { + snprintf(plat_joystick_state[js].axis[axis_nr].name, sizeof(plat_joystick_state[js].axis[axis_nr].name), "Axis %i", axis_nr); + plat_joystick_state[js].axis[axis_nr].id = axis_nr; } - for (d = 0; d < plat_joystick_state[c].nr_buttons; d++) { - snprintf(plat_joystick_state[c].button[d].name, sizeof(plat_joystick_state[c].button[d].name), "Button %i", d); - plat_joystick_state[c].button[d].id = d; + for (int buttons_nr = 0; buttons_nr < plat_joystick_state[js].nr_buttons; buttons_nr++) { + snprintf(plat_joystick_state[js].button[buttons_nr].name, sizeof(plat_joystick_state[js].button[buttons_nr].name), "Button %i", buttons_nr); + plat_joystick_state[js].button[buttons_nr].id = buttons_nr; } - for (d = 0; d < plat_joystick_state[c].nr_povs; d++) { - snprintf(plat_joystick_state[c].pov[d].name, sizeof(plat_joystick_state[c].pov[d].name), "POV %i", d); - plat_joystick_state[c].pov[d].id = d; + for (int pov_nr = 0; pov_nr < plat_joystick_state[js].nr_povs; pov_nr++) { + snprintf(plat_joystick_state[js].pov[pov_nr].name, sizeof(plat_joystick_state[js].pov[pov_nr].name), "POV %i", pov_nr); + plat_joystick_state[js].pov[pov_nr].id = pov_nr; } } } @@ -84,11 +82,9 @@ joystick_init(void) void joystick_close(void) { - int c; - - for (c = 0; c < joysticks_present; c++) { - if (sdl_joy[c]) - SDL_JoystickClose(sdl_joy[c]); + for (int js = 0; js < joysticks_present; js++) { + if (sdl_joy[js]) + SDL_JoystickClose(sdl_joy[js]); } } @@ -132,57 +128,55 @@ joystick_get_axis(int joystick_nr, int mapping) void joystick_process(void) { - int c; - int d; - if (!joystick_type) return; SDL_JoystickUpdate(); - for (c = 0; c < joysticks_present; c++) { - int b; + for (int js = 0; js < joysticks_present; js++) { + for (int axis_nr = 0; axis_nr < plat_joystick_state[js].nr_axes; axis_nr++) + plat_joystick_state[js].a[axis_nr] = SDL_JoystickGetAxis(sdl_joy[js], axis_nr); - for (b = 0; b < plat_joystick_state[c].nr_axes; b++) - plat_joystick_state[c].a[b] = SDL_JoystickGetAxis(sdl_joy[c], b); + for (int button_nr = 0; button_nr < plat_joystick_state[js].nr_buttons; button_nr++) + plat_joystick_state[js].b[button_nr] = SDL_JoystickGetButton(sdl_joy[js], button_nr); - for (b = 0; b < plat_joystick_state[c].nr_buttons; b++) - plat_joystick_state[c].b[b] = SDL_JoystickGetButton(sdl_joy[c], b); + for (int pov_nr = 0; pov_nr < plat_joystick_state[js].nr_povs; pov_nr++) + plat_joystick_state[js].p[pov_nr] = SDL_JoystickGetHat(sdl_joy[js], pov_nr); - for (b = 0; b < plat_joystick_state[c].nr_povs; b++) - plat_joystick_state[c].p[b] = SDL_JoystickGetHat(sdl_joy[c], b); - // pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); +#if 0 + pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", js, joystick_state[js].x, joystick_state[js].y, joystick_state[js].b[0], joystick_state[js].b[1], joysticks_present); +#endif } - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - if (joystick_state[c].plat_joystick_nr) { - int joystick_nr = joystick_state[c].plat_joystick_nr - 1; + for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { + if (joystick_state[js].plat_joystick_nr) { + int joystick_nr = joystick_state[js].plat_joystick_nr - 1; - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { - int x, y; - double angle, magnitude; + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) + joystick_state[js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[js].axis_mapping[axis_nr]); - x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); - y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) + joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]]; - angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); - magnitude = sqrt((double) x * (double) x + (double) y * (double) y); + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { + int x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); + int y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); + double angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + double magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) - joystick_state[c].pov[d] = -1; + joystick_state[js].pov[pov_nr] = -1; else - joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; + joystick_state[js].pov[pov_nr] = ((int) angle + 90 + 360) % 360; } } else { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = 0; - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = 0; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - joystick_state[c].pov[d] = -1; + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) + joystick_state[js].axis[axis_nr] = 0; + + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) + joystick_state[js].button[button_nr] = 0; + + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) + joystick_state[js].pov[pov_nr] = -1; } } } diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index bb05c3f5c..811425a98 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -412,7 +412,7 @@ win_joystick_handle(PRAWINPUT raw) /* Read buttons */ USAGE usage_list[128] = { 0 }; ULONG usage_length = plat_joystick_state[j].nr_buttons; - memset(plat_joystick_state[j].b, 0, 32 * sizeof(int)); + memset(plat_joystick_state[j].b, 0, MAX_JOY_BUTTONS * sizeof(int)); r = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usage_list, &usage_length, raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); @@ -425,8 +425,8 @@ win_joystick_handle(PRAWINPUT raw) } /* Read axes */ - for (int a = 0; a < plat_joystick_state[j].nr_axes; a++) { - const struct raw_axis_t *axis = &raw_joystick_state[j].axis[a]; + for (int axis_nr = 0; axis_nr < plat_joystick_state[j].nr_axes; axis_nr++) { + const struct raw_axis_t *axis = &raw_joystick_state[j].axis[axis_nr]; ULONG uvalue = 0; LONG value = 0; LONG center = (axis->max - axis->min + 1) / 2; @@ -453,15 +453,15 @@ win_joystick_handle(PRAWINPUT raw) value = value * 32768 / center; } - plat_joystick_state[j].a[a] = value; + plat_joystick_state[j].a[axis_nr] = value; #if 0 - joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); + joystick_log("%s %-06d ", plat_joystick_state[j].axis[axis_nr].name, plat_joystick_state[j].a[axis_nr]); #endif } /* read povs */ - for (int p = 0; p < plat_joystick_state[j].nr_povs; p++) { - const struct raw_pov_t *pov = &raw_joystick_state[j].pov[p]; + for (int pov_nr = 0; pov_nr < plat_joystick_state[j].nr_povs; pov_nr++) { + const struct raw_pov_t *pov = &raw_joystick_state[j].pov[pov_nr]; ULONG uvalue = 0; LONG value = -1; @@ -474,10 +474,10 @@ win_joystick_handle(PRAWINPUT raw) value %= 36000; } - plat_joystick_state[j].p[p] = value; + plat_joystick_state[j].p[pov_nr] = value; #if 0 - joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); + joystick_log("%s %-3d ", plat_joystick_state[j].pov[pov_nr].name, plat_joystick_state[j].p[pov_nr]); #endif } #if 0 @@ -508,44 +508,45 @@ joystick_get_axis(int joystick_nr, int mapping) void joystick_process(void) { - int d; - if (joystick_type == JS_TYPE_NONE) return; - for (int c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - if (joystick_state[c].plat_joystick_nr) { - int joystick_nr = joystick_state[c].plat_joystick_nr - 1; + for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) { + if (joystick_state[js].plat_joystick_nr) { + int joystick_nr = joystick_state[js].plat_joystick_nr - 1; - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) + joystick_state[js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[js].axis_mapping[axis_nr]); - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) + joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]]; + + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { int x; int y; double angle; double magnitude; - x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); - y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); + y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) - joystick_state[c].pov[d] = -1; + joystick_state[js].pov[pov_nr] = -1; else - joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; + joystick_state[js].pov[pov_nr] = ((int) angle + 90 + 360) % 360; } } else { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = 0; - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = 0; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - joystick_state[c].pov[d] = -1; + for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) + joystick_state[js].axis[axis_nr] = 0; + + for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) + joystick_state[js].button[button_nr] = 0; + + for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) + joystick_state[js].pov[pov_nr] = -1; } } } From 6ec9c33940bbe864fb58f670fb1925d28cc32241 Mon Sep 17 00:00:00 2001 From: GetDizzy Date: Sat, 11 Jan 2025 02:19:32 -0500 Subject: [PATCH 31/65] Formatting fixes. --- src/machine/m_at_386dx_486.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 2a4b6f3c6..43ba9a6d9 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -707,10 +707,10 @@ static const device_config_t pb450_config[] = { }; const device_t pb450_device = { - .name = "Packard Bell PB450 Devices", + .name = "Packard Bell PB450 Devices", .internal_name = "pb450_device", - .flags = 0, - .local = 0, + .flags = 0, + .local = 0, .init = NULL, .close = NULL, .reset = NULL, From 8cb220d84b249851202489ee3f69e7c12492d5ba Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 03:39:15 -0500 Subject: [PATCH 32/65] Corrections --- src/config.c | 8 ++++---- src/qt/sdl_joystick.c | 13 +++++++++---- src/qt/win_joystick_rawinput.c | 14 ++++---------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/config.c b/src/config.c index 5119d45ff..24efcf264 100644 --- a/src/config.c +++ b/src/config.c @@ -541,7 +541,7 @@ load_input_devices(void) for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { sprintf(temp, "joystick_%i_pov_%i", js, pov_nr); p = ini_section_get_string(cat, temp, "0, 0"); - joystick_state[js].pov_mapping[js][pov_nr] = joystick_state[js].pov_mapping[pov_nr][1] = 0; + joystick_state[js].pov_mapping[pov_nr][0] = joystick_state[js].pov_mapping[pov_nr][1] = 0; sscanf(p, "%i, %i", &joystick_state[js].pov_mapping[pov_nr][0], &joystick_state[js].pov_mapping[pov_nr][1]); } @@ -2145,15 +2145,15 @@ save_input_devices(void) sprintf(tmp2, "joystick_%i_nr", js); ini_section_delete_var(cat, tmp2); - for (int axis_nr = 0; axis_nr < 16; axis_nr++) { + for (int axis_nr = 0; axis_nr < MAX_JOY_AXES; axis_nr++) { sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr); ini_section_delete_var(cat, tmp2); } - for (int button_nr = 0; button_nr < 16; button_nr++) { + for (int button_nr = 0; button_nr < MAX_JOY_BUTTONS; button_nr++) { sprintf(tmp2, "joystick_%i_button_%i", js, button_nr); ini_section_delete_var(cat, tmp2); } - for (int pov_nr = 0; pov_nr < 16; pov_nr++) { + for (int pov_nr = 0; pov_nr < MAX_JOY_POVS; pov_nr++) { sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr); ini_section_delete_var(cat, tmp2); } diff --git a/src/qt/sdl_joystick.c b/src/qt/sdl_joystick.c index 221e12078..03159ba7f 100644 --- a/src/qt/sdl_joystick.c +++ b/src/qt/sdl_joystick.c @@ -67,9 +67,9 @@ joystick_init(void) snprintf(plat_joystick_state[js].axis[axis_nr].name, sizeof(plat_joystick_state[js].axis[axis_nr].name), "Axis %i", axis_nr); plat_joystick_state[js].axis[axis_nr].id = axis_nr; } - for (int buttons_nr = 0; buttons_nr < plat_joystick_state[js].nr_buttons; buttons_nr++) { - snprintf(plat_joystick_state[js].button[buttons_nr].name, sizeof(plat_joystick_state[js].button[buttons_nr].name), "Button %i", buttons_nr); - plat_joystick_state[js].button[buttons_nr].id = buttons_nr; + for (int button_nr = 0; button_nr < plat_joystick_state[js].nr_buttons; button_nr++) { + snprintf(plat_joystick_state[js].button[button_nr].name, sizeof(plat_joystick_state[js].button[button_nr].name), "Button %i", button_nr); + plat_joystick_state[js].button[button_nr].id = button_nr; } for (int pov_nr = 0; pov_nr < plat_joystick_state[js].nr_povs; pov_nr++) { snprintf(plat_joystick_state[js].pov[pov_nr].name, sizeof(plat_joystick_state[js].pov[pov_nr].name), "POV %i", pov_nr); @@ -143,7 +143,12 @@ joystick_process(void) plat_joystick_state[js].p[pov_nr] = SDL_JoystickGetHat(sdl_joy[js], pov_nr); #if 0 - pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", js, joystick_state[js].x, joystick_state[js].y, joystick_state[js].b[0], joystick_state[js].b[1], joysticks_present); + pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", js, + joystick_state[js].x, + joystick_state[js].y, + joystick_state[js].b[0], + joystick_state[js].b[1], + joysticks_present); #endif } diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index 811425a98..c293dcaca 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -522,16 +522,10 @@ joystick_process(void) joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]]; for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) { - int x; - int y; - double angle; - double magnitude; - - x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); - y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); - - angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); - magnitude = sqrt((double) x * (double) x + (double) y * (double) y); + int x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]); + int y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]); + double angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + double magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) joystick_state[js].pov[pov_nr] = -1; From f9ac37decd8cafc870a6927dd0a68ce1dd005872 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 04:04:39 -0500 Subject: [PATCH 33/65] Missed fix --- src/game/joystick_sw_pad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index 711a5fa1e..238e84d11 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -190,7 +190,7 @@ sw_write(void *priv) sw->poll_data = 1; } - for (uint8_t js = 0; js < MAX_JOYSTICKS; js++) { + for (uint8_t js = 0; js < 4; js++) { uint16_t data = 0x3fff; if (!JOYSTICK_PRESENT(js)) From 7d3d15853de68f8fbcb37844498cae3839b608c4 Mon Sep 17 00:00:00 2001 From: GetDizzy Date: Sat, 11 Jan 2025 04:11:54 -0500 Subject: [PATCH 34/65] Remove outdated TODOs. --- src/machine/m_at_386dx_486.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 43ba9a6d9..d3c7a21d2 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -741,7 +741,6 @@ machine_at_pb450_init(const machine_t *model) machine_at_common_init_ex(model, 2); device_add(&ide_vlb_2ch_device); - /* TODO: Detect if we're using the PNP and not the PCI ROM and don't add these? */ pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -757,7 +756,6 @@ machine_at_pb450_init(const machine_t *model) device_add(&fdc37c665_ide_device); device_add(&ide_opti611_vlb_sec_device); device_add(&intel_flash_bxt_device); - /* TODO: Detect if we're using the PNP and not the PCI ROM and don't add this? */ device_add(&phoenix_486_jumper_pci_device); return ret; From 49f5c358d85feb6850a5d656b23afcef809ceae8 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 04:37:18 -0500 Subject: [PATCH 35/65] Revert two fixes as batty has that covered --- src/cdrom/cdrom_image_backend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index ad1756055..9d065a0cb 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -1195,7 +1195,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) for (int i = 0; i < 3; i++) { lead[i] = cdi->tracks_num; - (void) cdi_insert_track(cdi, session, 0xa0 + i); + (void *) cdi_insert_track(cdi, session, 0xa0 + i); } cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); @@ -1393,7 +1393,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) for (int i = 0; i < 3; i++) { lead[i] = cdi->tracks_num; - (void) cdi_insert_track(cdi, session, 0xa0 + i); + (void *) cdi_insert_track(cdi, session, 0xa0 + i); } cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); From af12421a5baea3ac8d6448ee21bb8283279e94f7 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Sat, 11 Jan 2025 22:45:17 +0100 Subject: [PATCH 36/65] Update machine.h --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index ad8b47638..0cd3564ee 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -807,6 +807,7 @@ extern int machine_at_p2bls_init(const machine_t *); extern int machine_at_lgibmx7g_init(const machine_t *); extern int machine_at_p3bf_init(const machine_t *); extern int machine_at_bf6_init(const machine_t *); +extern int machine_at_bx6_init(const machine_t *); extern int machine_at_ax6bc_init(const machine_t *); extern int machine_at_atc6310bxii_init(const machine_t *); extern int machine_at_686bx_init(const machine_t *); From c64c5bcbcdf509b55e54c5ac0c06b653c681dccb Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Sat, 11 Jan 2025 23:04:17 +0100 Subject: [PATCH 37/65] Update m_at_slot1.c --- src/machine/m_at_slot1.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 415998364..a3ff921e3 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -359,6 +359,37 @@ machine_at_bf6_init(const machine_t *model) return ret; } +int +machine_at_bx6_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/bx6/BX6_EG.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977f_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + + return ret; +} + int machine_at_ax6bc_init(const machine_t *model) { From e00d7b8e1d1ad1044f0dbbc2803acf2c7ffec646 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Sat, 11 Jan 2025 23:18:49 +0100 Subject: [PATCH 38/65] Update machine_table.c --- src/machine/machine_table.c | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 06aea8597..4947b8898 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14632,6 +14632,47 @@ const machine_t machines[] = { }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ + +{ + .name = "[i440LX] ABIT BX6", + .internal_name = "bx6", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_bx6_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1500, + .max_voltage = 3500, + .min_multi = 2.0, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { .name = "[i440BX] ABIT BF6", .internal_name = "bf6", From fabe71150cb600ef7c290f93f5416c4b6c64e7d9 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 11 Jan 2025 18:13:56 -0500 Subject: [PATCH 39/65] Various improvements & Cleanups Some ported from ANightly's work --- src/device/CMakeLists.txt | 2 +- src/device/serial_passthrough.c | 8 ++--- src/device/unittester.c | 6 ++-- src/disk/hdc_xta.c | 8 ++--- src/disk/hdc_xtide.c | 4 +-- src/floppy/fdd_pcjs.c | 4 +++ src/include/86box/86box.h | 5 +++ src/machine/m_at_286_386sx.c | 4 --- src/machine/m_ps1.c | 2 +- src/network/CMakeLists.txt | 5 ++- src/network/net_rtl8139.c | 7 ++-- src/network/network.c | 2 ++ src/qt/qt_harddiskdialog.cpp | 12 +++++-- src/qt/qt_vulkanrenderer.cpp | 9 ++--- src/qt/qt_vulkanrenderer.hpp | 6 +++- src/qt/qt_vulkanwindowrenderer.cpp | 38 ++++++++++++++++++-- src/qt/qt_vulkanwindowrenderer.hpp | 2 +- src/qt/qt_winrawinputfilter.cpp | 40 ++++++++++++--------- src/qt/win_serial_passthrough.c | 2 +- src/scsi/scsi_aha154x.c | 2 +- src/scsi/scsi_ncr53c400.c | 2 +- src/sound/midi_fluidsynth.c | 33 ++++++----------- src/sound/resid-fp/siddefs-fp.h | 4 +++ src/sound/snd_opl2board.c | 4 +-- src/sound/snd_pas16.c | 1 + src/video/vid_et3000.c | 23 ++++++------ src/video/vid_et4000.c | 4 +-- src/video/vid_ht216.c | 57 +++++++++++------------------- src/video/vid_mga.c | 22 ++++-------- 29 files changed, 178 insertions(+), 140 deletions(-) diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index ae3fbf3f2..c9da627ef 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -57,7 +57,7 @@ add_library(dev OBJECT mouse_microtouch_touchscreen.c ) -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC) target_link_libraries(86Box atomic) endif() diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index eec9fa62a..ed5abe618 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -282,8 +282,8 @@ static const device_config_t serial_passthrough_config[] = { .type = CONFIG_SERPORT, .default_string = "", .file_filter = NULL, - .spinner = {}, - .selection = {} + .spinner = { 0 }, + .selection = { { 0 } } }, #ifdef _WIN32 { @@ -292,8 +292,8 @@ static const device_config_t serial_passthrough_config[] = { .type = CONFIG_STRING, .default_string = "\\\\.\\pipe\\86Box\\test", .file_filter = NULL, - .spinner = {}, - .selection = {} + .spinner = { 0 }, + .selection = { { 0 } } }, #endif { diff --git a/src/device/unittester.c b/src/device/unittester.c index e52f3b56f..614438fcb 100644 --- a/src/device/unittester.c +++ b/src/device/unittester.c @@ -104,8 +104,8 @@ struct unittester_state { /* 0x04: Exit */ uint8_t exit_code; }; -static struct unittester_state unittester; -static const struct unittester_state unittester_defaults = { +static struct unittester_state unittester; +static struct unittester_state unittester_defaults = { .trigger_port = 0x0080, .iobase_port = 0xFFFF, .fsm1 = UT_FSM1_WAIT_8, @@ -589,7 +589,7 @@ unittester_trigger_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv)) static void * unittester_init(UNUSED(const device_t *info)) { - unittester = (struct unittester_state) unittester_defaults; + unittester = unittester_defaults; unittester_exit_enabled = !!device_get_config_int("exit_enabled"); diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index a4ef45c43..a65ab5c69 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -1114,7 +1114,7 @@ static const device_config_t wdxt150_config[] = { .default_string = "", .default_int = 0x0320, .file_filter = "", - .spinner = { 0 }, /*W2*/ + .spinner = { 0 }, .selection = { { .description = "320H", .value = 0x0320 }, { .description = "324H", .value = 0x0324 }, @@ -1128,7 +1128,7 @@ static const device_config_t wdxt150_config[] = { .default_string = "", .default_int = 5, .file_filter = "", - .spinner = { 0 }, /*W3*/ + .spinner = { 0 }, .selection = { { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 4", .value = 4 }, @@ -1142,7 +1142,7 @@ static const device_config_t wdxt150_config[] = { .default_string = "", .default_int = 0xc8000, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CA00H", .value = 0xca000 }, @@ -1156,7 +1156,7 @@ static const device_config_t wdxt150_config[] = { .default_string = "rev_1", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Revision 1.0", .internal_name = "rev_1", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 8192, .files = { WD_REV_1_BIOS_FILE, "" } }, diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 9899e2a0f..b324b4d32 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -238,7 +238,7 @@ static const device_config_t xtide_config[] = { .default_string = "xt", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Regular XT", .internal_name = "xt", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XT, "" } }, @@ -260,7 +260,7 @@ static const device_config_t xtide_at_config[] = { .default_string = "at", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Regular AT", .internal_name = "at", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT, "" } }, diff --git a/src/floppy/fdd_pcjs.c b/src/floppy/fdd_pcjs.c index b7b3cc69d..76f8ca7dc 100644 --- a/src/floppy/fdd_pcjs.c +++ b/src/floppy/fdd_pcjs.c @@ -20,7 +20,11 @@ #include #include #include +#ifndef _MSC_VER #include +#else +#include +#endif #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index ffa670b7e..503518a2b 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -191,8 +191,13 @@ extern void pclog_ex(const char *fmt, va_list); extern void fatal_ex(const char *fmt, va_list); #endif extern void pclog_toggle_suppr(void); +#ifdef _MSC_VER +extern void pclog(const char *fmt, ...); +extern void fatal(const char *fmt, ...); +#else extern void pclog(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); extern void fatal(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +#endif extern void set_screen_size(int x, int y); extern void set_screen_size_monitor(int x, int y, int monitor_index); extern void reset_screen_size(void); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index ead31c21c..c3dc5c772 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -222,10 +222,6 @@ machine_at_ataripc4_init(const machine_t *model) ret = bios_load_interleaved("roms/machines/ataripc4/AMI_PC4X_1.7_EVEN.BIN", "roms/machines/ataripc4/AMI_PC4X_1.7_ODD.BIN", -#if 0 - ret = bios_load_interleaved("roms/machines/ataripc4/ami_pc4x_1.7_even.bin", - "roms/machines/ataripc4/ami_pc4x_1.7_odd.bin", -#endif 0x000f0000, 65536, 0); if (bios_only || !ret) diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 42bc49de2..3c9f1819f 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -252,7 +252,7 @@ static const device_config_t ps1_2011_config[] = { .default_string = "english_us", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "English (US)", .internal_name = "english_us", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/FC0000_US.BIN", "" } }, diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 0d42cbd8d..71f41f059 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -41,7 +41,10 @@ pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) target_link_libraries(86Box PkgConfig::SLIRP) if(WIN32) - target_link_libraries(PkgConfig::SLIRP INTERFACE wsock32 ws2_32 iphlpapi iconv) + target_link_libraries(PkgConfig::SLIRP INTERFACE wsock32 ws2_32 iphlpapi) + if (NOT MSVC) + target_link_libraries(PkgConfig::SLIRP INTERFACE iconv) + endif() if(STATIC_BUILD) add_compile_definitions(LIBSLIRP_STATIC) endif() diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index f04f9b7a3..0dac29a8c 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -28,6 +28,9 @@ #include #include #include +#ifdef _MVC_VER +#include +#endif #include #define HAVE_STDARG_H #include <86box/86box.h> @@ -531,14 +534,14 @@ rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) if (size > wrapped) { dma_bm_write(s->RxBuf + s->RxBufAddr, - buf, size - wrapped, 1); + (uint8_t *) buf, size - wrapped, 1); } /* reset buffer pointer */ s->RxBufAddr = 0; dma_bm_write(s->RxBuf + s->RxBufAddr, - buf + (size - wrapped), wrapped, 1); + (uint8_t *) buf + (size - wrapped), wrapped, 1); s->RxBufAddr = wrapped; diff --git a/src/network/network.c b/src/network/network.c index e60f50eb1..f4b03ee79 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -54,7 +54,9 @@ #include #include #include +#ifndef _MSC_VER #include +#endif #include #define HAVE_STDARG_H #include <86box/86box.h> diff --git a/src/qt/qt_harddiskdialog.cpp b/src/qt/qt_harddiskdialog.cpp index f2326ef8b..2acaaeacc 100644 --- a/src/qt/qt_harddiskdialog.cpp +++ b/src/qt/qt_harddiskdialog.cpp @@ -230,7 +230,11 @@ static HarddiskDialog *callbackPtr = nullptr; static MVHDGeom create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, uint8_t heads, uint8_t spt) { - MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; + MVHDGeom _86box_geometry = { + .cyl = cyl, + .heads = heads, + .spt = spt + }; MVHDGeom vhd_geometry; adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); @@ -256,7 +260,11 @@ create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, static MVHDGeom create_drive_vhd_dynamic(const QString &fileName, uint16_t cyl, uint8_t heads, uint8_t spt, int blocksize) { - MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; + MVHDGeom _86box_geometry = { + .cyl = cyl, + .heads = heads, + .spt = spt + }; MVHDGeom vhd_geometry; adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); int vhd_error = 0; diff --git a/src/qt/qt_vulkanrenderer.cpp b/src/qt/qt_vulkanrenderer.cpp index 9227cdcb3..13728b82e 100644 --- a/src/qt/qt_vulkanrenderer.cpp +++ b/src/qt/qt_vulkanrenderer.cpp @@ -30,10 +30,11 @@ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ +#include "qt_vulkanrenderer.hpp" #include #include -#include "qt_vulkanrenderer.hpp" + #if QT_CONFIG(vulkan) # include @@ -676,7 +677,7 @@ VulkanRenderer2::initResources() v_texcoord = texcoord; gl_Position = ubuf.mvp * position; } -#endif +#endif /* 0 */ VkShaderModule vertShaderModule = createShader(QStringLiteral(":/texture_vert.spv")); #if 0 #version 440 @@ -691,7 +692,7 @@ VulkanRenderer2::initResources() { fragColor = texture(tex, v_texcoord); } -#endif +#endif /* 0 */ VkShaderModule fragShaderModule = createShader(QStringLiteral(":/texture_frag.spv")); // Graphics pipeline @@ -1009,4 +1010,4 @@ VulkanRenderer2::startNextFrame() m_window->frameReady(); m_window->requestUpdate(); // render continuously, throttled by the presentation rate } -#endif +#endif /* QT_CONFIG(vulkan) */ diff --git a/src/qt/qt_vulkanrenderer.hpp b/src/qt/qt_vulkanrenderer.hpp index d4580d848..2c131e5d7 100644 --- a/src/qt/qt_vulkanrenderer.hpp +++ b/src/qt/qt_vulkanrenderer.hpp @@ -31,6 +31,8 @@ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ +#ifndef VULKANRENDERER_HPP +#define VULKANRENDERER_HPP #include #include @@ -90,4 +92,6 @@ private: QMatrix4x4 m_proj; }; -#endif +#endif // QT_CONFIG(vulkan) + +#endif // VULKANRENDERER_HPP diff --git a/src/qt/qt_vulkanwindowrenderer.cpp b/src/qt/qt_vulkanwindowrenderer.cpp index 60ad5be96..ab46b5961 100644 --- a/src/qt/qt_vulkanwindowrenderer.cpp +++ b/src/qt/qt_vulkanwindowrenderer.cpp @@ -1,3 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2022 Cacodemon345 +** Copyright (C) 2017 The Qt Company Ltd. +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * 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. +** * Neither the name of The Qt Company Ltd 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 +** OWNER 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 "qt_vulkanwindowrenderer.hpp" #include @@ -697,7 +729,7 @@ public: # if VK_HEADER_VERSION >= 135 && VK_HEADER_VERSION < 162 case VK_ERROR_INCOMPATIBLE_VERSION_KHR: return "VK_ERROR_INCOMPATIBLE_VERSION_KHR"; -# endif +# endif /* VK_HEADER_VERSION >= 135 && VK_HEADER_VERSION < 162 */ case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; case VK_ERROR_NOT_PERMITTED_EXT: @@ -788,7 +820,7 @@ public: m_devFuncs->vkDeviceWaitIdle(m_window->device()); } }; -# endif +# endif /* 0*/ VulkanWindowRenderer::VulkanWindowRenderer(QWidget *parent) : QVulkanWindow(parent->windowHandle()) @@ -851,4 +883,4 @@ VulkanWindowRenderer::getBuffers() { return std::vector { std::make_tuple((uint8_t *) renderer->mappedPtr, &this->buf_usage[0]) }; } -#endif +#endif /* QT_CONFIG(vulkan) */ diff --git a/src/qt/qt_vulkanwindowrenderer.hpp b/src/qt/qt_vulkanwindowrenderer.hpp index 828d091e6..de9f46b6f 100644 --- a/src/qt/qt_vulkanwindowrenderer.hpp +++ b/src/qt/qt_vulkanwindowrenderer.hpp @@ -35,6 +35,6 @@ private: VulkanRenderer2 *renderer; }; -#endif +#endif // QT_CONFIG(vulkan) #endif // VULKANWINDOWRENDERER_HPP diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index a1da0af61..73e8a2995 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -56,14 +56,18 @@ std::unique_ptr WindowsRawInputFilter::Register(MainWindow *window) { RAWINPUTDEVICE rid[2] = { - {.usUsagePage = 0x01, - .usUsage = 0x06, - .dwFlags = RIDEV_NOHOTKEYS, - .hwndTarget = nullptr}, - { .usUsagePage = 0x01, - .usUsage = 0x02, - .dwFlags = 0, - .hwndTarget = nullptr} + { + .usUsagePage = 0x01, + .usUsage = 0x06, + .dwFlags = RIDEV_NOHOTKEYS, + .hwndTarget = nullptr + }, + { + .usUsagePage = 0x01, + .usUsage = 0x02, + .dwFlags = 0, + .hwndTarget = nullptr + } }; if (hook_enabled && (RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])) == FALSE)) @@ -89,14 +93,18 @@ WindowsRawInputFilter::WindowsRawInputFilter(MainWindow *window) WindowsRawInputFilter::~WindowsRawInputFilter() { RAWINPUTDEVICE rid[2] = { - {.usUsagePage = 0x01, - .usUsage = 0x06, - .dwFlags = RIDEV_REMOVE, - .hwndTarget = NULL}, - { .usUsagePage = 0x01, - .usUsage = 0x02, - .dwFlags = RIDEV_REMOVE, - .hwndTarget = NULL} + { + .usUsagePage = 0x01, + .usUsage = 0x06, + .dwFlags = RIDEV_REMOVE, + .hwndTarget = NULL + }, + { + .usUsagePage = 0x01, + .usUsage = 0x02, + .dwFlags = RIDEV_REMOVE, + .hwndTarget = NULL + } }; if (hook_enabled) diff --git a/src/qt/win_serial_passthrough.c b/src/qt/win_serial_passthrough.c index 2b77bd219..c1802ce73 100644 --- a/src/qt/win_serial_passthrough.c +++ b/src/qt/win_serial_passthrough.c @@ -88,7 +88,7 @@ plat_serpt_set_params(void *priv) const serial_passthrough_t *dev = (serial_passthrough_t *) priv; if (dev->mode == SERPT_MODE_HOSTSER) { - DCB serialattr = {}; + DCB serialattr = { 0 }; GetCommState((HANDLE) dev->master_fd, &serialattr); #define BAUDRATE_RANGE(baud_rate, min, max) \ if (baud_rate >= min && baud_rate < max) { \ diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 58779e7ac..937213b85 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1421,7 +1421,7 @@ static const device_config_t aha_154xcp_config[] = { .default_string = "v1_02_en", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Version 1.02 (English)", .internal_name = "v1_02_en", .bios_type = BIOS_NORMAL, .files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/aha1542cp102.bin", diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index bea918660..6622ec59a 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -841,7 +841,7 @@ static const device_config_t rt1000b_config[] = { .default_string = "v8_10r", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Version 8.10R", .internal_name = "v8_10r", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 8192, .files = { RT1000B_810R_ROM, "" } }, diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index ccedb8c41..51383bdcf 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -330,8 +330,7 @@ static const device_config_t fluidsynth_config[] = { .name = "output_gain", .description = "Output Gain", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -347,8 +346,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_voices", .description = "Chorus Voices", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 99 }, @@ -358,8 +356,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_level", .description = "Chorus Level", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -369,8 +366,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_speed", .description = "Chorus Speed", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 10, .max = 500 }, @@ -380,8 +376,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_depth", .description = "Chorus Depth", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 2560 }, @@ -391,8 +386,7 @@ static const device_config_t fluidsynth_config[] = { .name = "chorus_waveform", .description = "Chorus Waveform", .type = CONFIG_SELECTION, - .selection = - { + .selection = { { .description = "Sine", .value = 0 @@ -414,8 +408,7 @@ static const device_config_t fluidsynth_config[] = { .name = "reverb_room_size", .description = "Reverb Room Size", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -425,8 +418,7 @@ static const device_config_t fluidsynth_config[] = { .name = "reverb_damping", .description = "Reverb Damping", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -436,8 +428,7 @@ static const device_config_t fluidsynth_config[] = { .name = "reverb_width", .description = "Reverb Width", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 1000 }, @@ -447,8 +438,7 @@ static const device_config_t fluidsynth_config[] = { .name = "reverb_level", .description = "Reverb Level", .type = CONFIG_SPINNER, - .spinner = - { + .spinner = { .min = 0, .max = 100 }, @@ -458,8 +448,7 @@ static const device_config_t fluidsynth_config[] = { .name = "interpolation", .description = "Interpolation Method", .type = CONFIG_SELECTION, - .selection = - { + .selection = { { .description = "None", .value = 0 diff --git a/src/sound/resid-fp/siddefs-fp.h b/src/sound/resid-fp/siddefs-fp.h index 9411b1694..22e40f4fb 100644 --- a/src/sound/resid-fp/siddefs-fp.h +++ b/src/sound/resid-fp/siddefs-fp.h @@ -24,7 +24,11 @@ #define RESID_BRANCH_HINTS true // Compiler specifics. +#ifndef _MSC_VER #define HAVE_BUILTIN_EXPECT true +#else +#define HAVE_BUILTIN_EXPECT false +#endif // Branch prediction macros, lifted off the Linux kernel. #if RESID_BRANCH_HINTS && HAVE_BUILTIN_EXPECT diff --git a/src/sound/snd_opl2board.c b/src/sound/snd_opl2board.c index dea7752d0..f1bda3398 100644 --- a/src/sound/snd_opl2board.c +++ b/src/sound/snd_opl2board.c @@ -173,8 +173,8 @@ static const device_config_t opl2board_config[] = { .type = CONFIG_SERPORT, .default_string = "", .file_filter = NULL, - .spinner = {}, - .selection = {} + .spinner = { 0 }, + .selection = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } }; diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index fab2a6a75..ed82afebf 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -86,6 +86,7 @@ * Copyright 2008-2024 Sarah Walker. * Copyright 2024 Miran Grca. */ +#define _USE_MATH_DEFINES #include #include #include diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c index a7d2a749f..45a2fc199 100644 --- a/src/video/vid_et3000.c +++ b/src/video/vid_et3000.c @@ -548,17 +548,20 @@ et3000_available(void) } static const device_config_t et3000_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { .description = "256 KB", - .value = 256 }, - { .description = "512 KB", - .value = 512 }, - { .description = "" } } }, + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + } + }, { .type = CONFIG_END } + // clang-format on }; const device_t et3000_isa_device = { diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index caf8d03c7..ad8cf5c46 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -972,7 +972,7 @@ static const device_config_t et4000_tc6058af_config[] = { .default_string = "v1_10", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Version 1.10", .internal_name = "v1_10", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 32768, .files = { TC6058AF_BIOS_ROM_PATH, "" } }, @@ -1019,7 +1019,7 @@ static const device_config_t et4000_bios_config[] = { .default_string = "v8_01", .default_int = 0, .file_filter = "", - .spinner = { 0 }, /*W1*/ + .spinner = { 0 }, .bios = { { .name = "Version 8.01", .internal_name = "v8_01", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 32768, .files = { BIOS_ROM_PATH, "" } }, diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index c1f5cbeaf..a249631ee 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1701,52 +1701,37 @@ ht216_force_redraw(void *priv) ht216->svga.fullchange = changeframecount; } +// clang-format off static const device_config_t v7_vga_1024i_config[] = { - { .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { .description = "256 KB", - .value = 256 }, - { .description = "512 KB", - .value = 512 }, - { .description = "" } } }, + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + } + }, { .type = CONFIG_END } }; -// clang-format off static const device_config_t ht216_32_standalone_config[] = { { - .name = "monitor_type", + .name = "monitor_type", .description = "Monitor type", - .type = CONFIG_SELECTION, + .type = CONFIG_SELECTION, .default_int = 0x18, - .selection = { - { - .description = "Mono Interlaced", - .value = 0x00 - }, - { - .description = "Mono Non-Interlaced", - .value = 0x08 - }, - { - .description = "Color Interlaced", - .value = 0x10 - }, - { - .description = "Color Non-Interlaced", - .value = 0x18 - }, - { - .description = "" - } + .selection = { + { .description = "Mono Interlaced", .value = 0x00 }, + { .description = "Mono Non-Interlaced", .value = 0x08 }, + { .description = "Color Interlaced", .value = 0x10 }, + { .description = "Color Non-Interlaced", .value = 0x18 }, + { .description = "" } } }, - { - .type = CONFIG_END - } + { .type = CONFIG_END } }; // clang-format on diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 1bdbecdf6..2b9e63af4 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -6851,8 +6851,7 @@ static const device_config_t mystique_config[] = { .name = "memory", .description = "Memory size", .type = CONFIG_SELECTION, - .selection = - { + .selection = { { .description = "2 MB", .value = 2 @@ -6865,15 +6864,11 @@ static const device_config_t mystique_config[] = { .description = "8 MB", .value = 8 }, - { - .description = "" - } + { .description = "" } }, .default_int = 8 }, - { - .type = CONFIG_END - } + { .type = CONFIG_END } // clang-format on }; @@ -6883,8 +6878,7 @@ static const device_config_t millennium_ii_config[] = { .name = "memory", .description = "Memory size", .type = CONFIG_SELECTION, - .selection = - { + .selection = { { .description = "4 MB", .value = 4 @@ -6897,15 +6891,11 @@ static const device_config_t millennium_ii_config[] = { .description = "16 MB", .value = 16 }, - { - .description = "" - } + { .description = "" } }, .default_int = 8 }, - { - .type = CONFIG_END - } + { .type = CONFIG_END } // clang-format on }; From abb066f6ef2efa9c83daad8ec50bcfb1fbcc29d8 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 21 Dec 2022 04:17:04 -0500 Subject: [PATCH 40/65] Initial Micro Solutions CompatiCard support --- src/floppy/CMakeLists.txt | 1 + src/floppy/fdc.c | 21 ++- src/floppy/fdc_compaticard.c | 355 +++++++++++++++++++++++++++++++++++ src/include/86box/fdc_ext.h | 4 + 4 files changed, 372 insertions(+), 9 deletions(-) create mode 100644 src/floppy/fdc_compaticard.c diff --git a/src/floppy/CMakeLists.txt b/src/floppy/CMakeLists.txt index d86ff4bc2..c16ca06f4 100644 --- a/src/floppy/CMakeLists.txt +++ b/src/floppy/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(fdd OBJECT fdd.c fdc.c + fdc_compaticard.c fdc_magitronic.c fdc_monster.c fdc_pii15xb.c diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 546174c57..4cb2a8491 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -103,15 +103,18 @@ typedef const struct { static fdc_cards_t fdc_cards[] = { // clang-format off - { &device_none }, - { &device_internal }, - { &fdc_xt_device }, - { &fdc_at_device }, - { &fdc_b215_device }, - { &fdc_pii151b_device }, - { &fdc_pii158b_device }, - { &fdc_monster_device }, - { NULL } + { &device_none }, + { &device_internal }, + { &fdc_b215_device }, + { &fdc_pii151b_device }, + { &fdc_pii158b_device }, + { &fdc_compaticard_i_device }, + { &fdc_compaticard_ii_device }, +#if 0 + { &fdc_compaticard_iv_device }, +#endif + { &fdc_monster_device }, + { NULL } // clang-format on }; diff --git a/src/floppy/fdc_compaticard.c b/src/floppy/fdc_compaticard.c new file mode 100644 index 000000000..a693c9cb2 --- /dev/null +++ b/src/floppy/fdc_compaticard.c @@ -0,0 +1,355 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of Micro Solutions CompatiCard I/II/IV. + * + * Authors: Jasmine Iwanek, + * + * Copyright 2022-2025 Jasmine Iwanek. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/machine.h> +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> + +#define DEVICE_COMPATICARD_I 0 +#define DEVICE_COMPATICARD_II 1 +#define DEVICE_COMPATICARD_IV 2 + +#define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) +#define ROM_COMPATICARD_IV "roms/floppy/compaticard/ccivbios1.05.bin" + +#define CR_2_MASK 0x2f /* 00101111b */ + +typedef struct compaticard_s { + rom_t bios_rom; + fdc_t *fdc; + /* + * 7 - Reserved - Set to 0 + * 6 - Reserved - Set to 0 + * 5 - Programmable Pin 2 Logic I sets Pin 2 low (TODO) + * 4 - Reserved - Set to 0 + * 3-0 - Data Transfer Rate Select (TODO) + * 0000---250 Kbps + * 0001-300 Kbps + * 1111-500 Kbps + */ + uint8_t cr_2; +} compaticard_t; + +static void +compaticard_out(uint16_t port, uint8_t val, void *priv) +{ + compaticard_t *dev = (compaticard_t *) priv; + + dev->cr_2 = (val & CR_2_MASK); +} + +static uint8_t +compaticard_in(uint16_t port, void *priv) +{ + compaticard_t *dev = (compaticard_t *) priv; + uint8_t ret = (dev->cr_2 &CR_2_MASK); + + return ret; +} + +static void +compaticard_close(void *priv) +{ + compaticard_t *dev = (compaticard_t *) priv; + + free(dev); +} + +static void * +compaticard_init(const device_t *info) +{ + compaticard_t *dev = calloc(1, sizeof(compaticard_t)); + uint16_t base_addr = device_get_config_hex16("base"); + uint8_t irq = 6; + uint8_t dma = 2; + uint16_t cr2_addr = 0x7f2; // Control Register 2 + + // CompatiCard II & IV have configurable IRQ and DMA + if (info->local >= DEVICE_COMPATICARD_II) { + irq = device_get_config_int("irq"); + dma = device_get_config_int("dma"); + } + + // Only on CompatiCard IV + if ((info->local == DEVICE_COMPATICARD_IV) && (BIOS_ADDR != 0)) + rom_init(&dev->bios_rom, ROM_COMPATICARD_IV, BIOS_ADDR, 0x2000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL); + + // TODO: Make this neater + switch (base_addr) { + case FDC_SECONDARY_ADDR: + cr2_addr = 0x772; + if (info->local == DEVICE_COMPATICARD_IV) + dev->fdc = device_add(&fdc_at_sec_device); + else + dev->fdc = device_add(&fdc_xt_sec_device); + break; + + case FDC_TERTIARY_ADDR: + cr2_addr = 0x762; + if (info->local == DEVICE_COMPATICARD_IV) + dev->fdc = device_add(&fdc_at_ter_device); + else + dev->fdc = device_add(&fdc_xt_ter_device); + break; + + case FDC_QUATERNARY_ADDR: + cr2_addr = 0x7e2; + if (info->local == DEVICE_COMPATICARD_IV) + dev->fdc = device_add(&fdc_at_qua_device); + else + dev->fdc = device_add(&fdc_xt_qua_device); + break; + + default: + if (info->local == DEVICE_COMPATICARD_IV) + dev->fdc = device_add(&fdc_at_device); + else + dev->fdc = device_add(&fdc_xt_device); + break; + } + + fdc_set_irq(dev->fdc, irq); + fdc_set_dma_ch(dev->fdc, dma); + + io_sethandler(cr2_addr, 0x0001, + compaticard_in, NULL, NULL, + compaticard_out, NULL, NULL, + dev); + + return dev; +} + +static int compaticard_iv_available(void) +{ + return rom_present(ROM_COMPATICARD_IV); +} + +static const device_config_t compaticard_i_config[] = { +// clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x3f0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x3f0", .value = 0x3f0 }, + { .description = "0x370", .value = 0x370 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + +static const device_config_t compaticard_ii_config[] = { +// clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x3f0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x3f0", .value = 0x3f0 }, + { .description = "0x370", .value = 0x370 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 6", .value = 6 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 2", .value = 2 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + +static const device_config_t compaticard_iv_config[] = { +// clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x3f0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x3f0", .value = 0x3f0 }, + { .description = "0x370", .value = 0x370 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 6", .value = 6 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 2", .value = 2 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + } + }, + { + .name = "bios_addr", + .description = "BIOS Address:", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xce000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "CE00H", .value = 0xce000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DE00H", .value = 0xde000 }, + { .description = "E000H", .value = 0xe0000 }, + { .description = "E800H", .value = 0xe8000 }, + { .description = "EE00H", .value = 0xee000 }, + { .description = "" } + } + }, +#if 0 + { + .name = "autoboot_enabled", + .description = "Enable Autoboot", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, +#endif + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + +const device_t fdc_compaticard_i_device = { + .name = "Micro Solutions CompatiCard I", + .internal_name = "compaticard_i", + .flags = DEVICE_ISA, + .local = 0, + .init = compaticard_init, + .close = compaticard_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = compaticard_i_config +}; + +const device_t fdc_compaticard_ii_device = { + .name = "Micro Solutions CompatiCard II", + .internal_name = "compaticard_ii", + .flags = DEVICE_ISA, + .local = 1, + .init = compaticard_init, + .close = compaticard_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = compaticard_ii_config +}; + +const device_t fdc_compaticard_iv_device = { + .name = "Micro Solutions CompatiCard IV", + .internal_name = "compaticard_iv", + .flags = DEVICE_ISA, + .local = 2, + .init = compaticard_init, + .close = compaticard_close, + .reset = NULL, + .available = compaticard_iv_available, + .speed_changed = NULL, + .force_redraw = NULL, + .config = compaticard_iv_config +}; diff --git a/src/include/86box/fdc_ext.h b/src/include/86box/fdc_ext.h index 4b33ed7a1..e6348139b 100644 --- a/src/include/86box/fdc_ext.h +++ b/src/include/86box/fdc_ext.h @@ -34,6 +34,10 @@ extern const device_t fdc_b215_device; extern const device_t fdc_pii151b_device; extern const device_t fdc_pii158b_device; +extern const device_t fdc_compaticard_i_device; +extern const device_t fdc_compaticard_ii_device; +extern const device_t fdc_compaticard_iv_device; + extern const device_t fdc_monster_device; extern void fdc_card_init(void); From 2d0f03a708d7ac4ba0f4b7ae719b56f82d8ac99e Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Sun, 12 Jan 2025 10:47:23 +0100 Subject: [PATCH 41/65] Fixed a BX6-related typo --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 4947b8898..330b7d52a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -14634,7 +14634,7 @@ const machine_t machines[] = { firmware. */ { - .name = "[i440LX] ABIT BX6", + .name = "[i440BX] ABIT BX6", .internal_name = "bx6", .type = MACHINE_TYPE_SLOT1, .chipset = MACHINE_CHIPSET_INTEL_440BX, From 204b24022f291ce7b4a5f3af9fee8d644f4f4c00 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 15:21:31 +0000 Subject: [PATCH 42/65] Implement the rivatimer and cyclical logging from my main NV3 branch so that we can get it reviewed and merged. --- src/86box.c | 152 ++++++++++++- src/include/86box/86box.h | 5 +- src/include/86box/nv/vid_nv_rivatimer.h | 84 ++++++++ src/video/nv/nv_rivatimer.c | 274 ++++++++++++++++++++++++ 4 files changed, 502 insertions(+), 13 deletions(-) create mode 100644 src/include/86box/nv/vid_nv_rivatimer.h create mode 100644 src/video/nv/nv_rivatimer.c diff --git a/src/86box.c b/src/86box.c index 8fa74fd4b..8450c8b6b 100644 --- a/src/86box.c +++ b/src/86box.c @@ -103,6 +103,7 @@ #include <86box/machine_status.h> #include <86box/apm.h> #include <86box/acpi.h> +#include <86box/nv/vid_nv_rivatimer.h> // Disable c99-designator to avoid the warnings about int ng #ifdef __clang__ @@ -252,12 +253,37 @@ static volatile atomic_int do_pause_ack = 0; static volatile atomic_int pause_ack = 0; #ifndef RELEASE_BUILD -static char buff[1024]; -static int seen = 0; + +#define LOG_SIZE_BUFFER 1024 /* Log size buffer */ +#define LOG_SIZE_BUFFER_CYCLIC_LINES 32 /* Cyclic log size buffer (number of lines that should be cehcked) */ +#define LOG_MINIMUM_REPEAT_ORDER 4 /* Minimum repeat size */ + +static char buff[LOG_SIZE_BUFFER]; +static char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; +static int32_t cyclic_last_line = 0; +static int32_t log_cycles = 0; + +static int seen = 0; static int suppr_seen = 1; #endif +/* + Ensures STDLOG is open for pclog_ex and pclog_ex_cyclic +*/ +void +pclog_ensure_stdlog_open() +{ + if (stdlog == NULL) { + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; + } +} + /* * Log something to the logfile or stdout. * @@ -269,19 +295,12 @@ void pclog_ex(const char *fmt, va_list ap) { #ifndef RELEASE_BUILD - char temp[1024]; + char temp[LOG_SIZE_BUFFER]; if (strcmp(fmt, "") == 0) return; - if (stdlog == NULL) { - if (log_path[0] != '\0') { - stdlog = plat_fopen(log_path, "w"); - if (stdlog == NULL) - stdlog = stdout; - } else - stdlog = stdout; - } + pclog_ensure_stdlog_open(); vsprintf(temp, fmt, ap); if (suppr_seen && !strcmp(buff, temp)) @@ -298,6 +317,114 @@ pclog_ex(const char *fmt, va_list ap) #endif } + +/* +Starfrost, 7-8 January 2025: + +For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found. + +Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm +*/ +void +pclog_ex_cyclic(const char* fmt, va_list ap) +{ +#ifndef RELEASE_BUILD + char temp[LOG_SIZE_BUFFER]; + + cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES; + + vsprintf(temp, fmt, ap); + + pclog_ensure_stdlog_open(); + + strncpy(cyclic_buff[cyclic_last_line], temp, LOG_SIZE_BUFFER); + + uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0}; + + // Random numbers + uint32_t base = 257; + uint32_t mod = 1000000007; + + uint32_t repeat_order = 0; + bool is_cycle = false; + + // compute the set of hashes for the current log buffer + for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++) + { + if (cyclic_buff[log_line][0] == '\0') + continue; // skip + + for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++) + { + hashes[log_line] = hashes[log_line] * base + cyclic_buff[log_line][log_line_char] % mod; + } + } + + + // Now see if there are real cycles... + // We implement a minimum repeat size. + for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++) + { + //TODO: Log what we need for cycle 1. + //TODO: Command line option that lets us turn off this behaviour. + for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++) + { + if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES]) + { + repeat_order = check_size; + break; + } + } + + is_cycle = (repeat_order != 0); + + // if there still is a cycle.. + if (is_cycle) + break; + + } + + if (is_cycle) + { + if (cyclic_last_line % repeat_order == 0) + { + log_cycles++; + + if (log_cycles == 1) + { + // 'Replay' the last few log entries so they actually show up + // Todo: is this right? + + for (uint32_t index = cyclic_last_line - 1; index > (cyclic_last_line - repeat_order); index--) + { + // *very important* to prevent out of bounds index + uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; + fprintf(stdlog, "%s", temp); + + } + + fprintf(stdlog, "%s", temp); // allow normal logging + } + + + if (log_cycles > 1 && log_cycles < 100) + fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log_cycles); + else if (log_cycles == 100) + fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n"); + } + } + else + { + log_cycles = 0; + fprintf(stdlog, "%s", temp); + } + + cyclic_last_line++; + +#endif + +} + void pclog_toggle_suppr(void) { @@ -1427,6 +1554,9 @@ pc_run(void) pc_reset_hard_init(); } + /* Update the guest-CPU independent timer for devices with independent clock speed */ + rivatimer_update_all(); + /* Run a block of code. */ startblit(); cpu_exec((int32_t) cpu_s->rspeed / 100); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 503518a2b..05c2a901e 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -187,8 +187,9 @@ extern int config_changed; /* config has changed */ /* Function prototypes. */ #ifdef HAVE_STDARG_H -extern void pclog_ex(const char *fmt, va_list); -extern void fatal_ex(const char *fmt, va_list); +extern void pclog_ex(const char *fmt, va_list ap); +extern void fatal_ex(const char *fmt, va_list ap); +extern void pclog_ex_cyclic(const char* fmt, va_list ap); #endif extern void pclog_toggle_suppr(void); #ifdef _MSC_VER diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h new file mode 100644 index 000000000..d5bb86b90 --- /dev/null +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -0,0 +1,84 @@ +/* + * 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. + * + * Fast, high-frequency, guest CPU-independent timer for Riva emulation. + * + * + * Authors: Connor Hyde, I need a better email address ;^) + * + * Copyright 2024-2025 starfrost + */ + +/* +RivaTimer + +This is a fast, high-frequency, guest CPU-independent timer. + +The main 86box timer is dependent on the TSC (time-stamp counter) register of the emulated CPU core. +This is fine for most purposes and has advantages in the fields of synchronisation and integrates neatly with +the clock dividers of the PC architecture, but in the case of the RIVA 128 it does not particularly suffice +(although it can be made to work with various techniques) since the clock source on the RIVA 128 is on the board itself +and the GPU has several different clocks that control different parts of the GPU (e.g., PTIMER runs on the memory clock but the core gpu is using the pixel clock). + +As faster graphics cards that offload more and more of the 3D graphics pipeline are emulated in the future, more and more work needs to be done by the emulator and +issues of synchronisation with a host CPU will simply make that work harder. Some features that are required for + +Architecture Brand Name 3D Features +NV1 (1995) NV1 Some weird URBS rectangle crap but feature set generally similar to nv3 but a bit worse +NV3 (1997) RIVA 128 (ZX) Triangle setup, edge-slope calculations, edge interpolation, span-slope calculations, span interpolation (Color-buffer, z-buffer, texture mapping, filtering) +NV4 (1998) RIVA TNT NV3 + 2x1 pixel pipelines + 32-bit colour + larger textures + trilinear + more ram (16mb) +NV5 (1999) RIVA TNT2 NV4 + higher clock speed +NV10 (1999) GeForce 256 NV5 + initial geometry transformation + lighting (8x lights) + MPEG-2 motion compensation + 4x1 pixel pipelines +NV15 (2000) GeForce 2 NV10 + First attempt at programmability + 4x2 pixel pipelines +NV20 (2001) GeForce 3 Programmable shaders! + +As you can see, the performance basically exponentially increases over a period of only 4 years. + +So I decided to create this timer that is completely separate from the CPU Core. +*/ + +#pragma once +#include +#include +#include +#include +#include <86Box\86box.h> + +#ifdef _WIN32 +#include +// Linux & MacOS should have the same API since OSX 10.12 +#else +#include +#endif + +typedef struct rivatimer_s +{ + struct rivatimer_s* prev; // Previous Rivatimer + double period; // Period in uS before firing + double value; // The current value of the rivatimer + bool running; // Is this RivaTimer running? + struct rivatimer_s* next; // Next RivaTimer + void (*callback)(); // Callback to call on fire + #ifdef _WIN32 + LARGE_INTEGER starting_time; // Starting time. + #else + struct timespec starting_time; // Starting time. + #endif + double time; // Accumulated time in uS. +} rivatimer_t; + +void rivatimer_init(); // Initialise the Rivatimer. +rivatimer_t* rivatimer_create(double period, void (*callback)(double real_time)); +void rivatimer_destroy(rivatimer_t* rivatimer_ptr); + +void rivatimer_update_all(); +void rivatimer_start(rivatimer_t* rivatimer_ptr); +void rivatimer_stop(rivatimer_t* rivatimer_ptr); +double rivatimer_get_time(rivatimer_t* rivatimer_ptr); +void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double real_time)); +void rivatimer_set_period(rivatimer_t* rivatimer_ptr, double period); diff --git a/src/video/nv/nv_rivatimer.c b/src/video/nv/nv_rivatimer.c new file mode 100644 index 000000000..343ec02ff --- /dev/null +++ b/src/video/nv/nv_rivatimer.c @@ -0,0 +1,274 @@ +/* + * 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. + * + * Fast, high-frequency, CPU-independent timer. + * + * + * + * Authors: Connor Hyde, I need a better email address ;^) + * + * Copyright 2024-2025 starfrost + */ + +/* See vid_nv_rivatimer.h comments for rationale behind not using the regular timer system + +Notes applicable to this file: +Since Windows XP, QueryPerformanceCounter and QueryPerformanceFrequency cannot fail so they are not checked. + +*/ + +#include <86Box/nv/vid_nv_rivatimer.h> + +#ifdef _WIN32 +LARGE_INTEGER performance_frequency; +#endif + +rivatimer_t* rivatimer_head; // The head of the rivatimer list. +rivatimer_t* rivatimer_tail; // The tail of the rivatimer list. + +/* Functions only used in this translation unit */ +bool rivatimer_really_exists(rivatimer_t* rivatimer); // Determine if a rivatimer really exists in the linked list. + +void rivatimer_init() +{ + // Destroy all the rivatimers. + rivatimer_t* rivatimer_ptr = rivatimer_head; + + if (!rivatimer_ptr) + return; + + while (rivatimer_ptr) + { + // since we are destroing it + rivatimer_t* old_next = rivatimer_ptr->next; + rivatimer_destroy(rivatimer_ptr); + + rivatimer_ptr = old_next; + } + + + #ifdef _WIN32 + // Query the performance frequency. + QueryPerformanceFrequency(&performance_frequency); + #endif +} + +// Creates a rivatimer. +rivatimer_t* rivatimer_create(double period, void (*callback)(double real_time)) +{ + rivatimer_t* new_rivatimer = NULL; + + // See i + if (period <= 0 + || !callback) + { + fatal("Invalid rivatimer_create call: period <= 0 or no callback"); + } + + // If there are no rivatimers, create one + if (!rivatimer_head) + { + rivatimer_head = calloc(1, sizeof(rivatimer_t)); + rivatimer_head->prev = NULL; // indicate this is the first in the list even if we don't strictly need to + rivatimer_tail = rivatimer_head; + new_rivatimer = rivatimer_head; + } + else // Otherwise add a new one to the list + { + rivatimer_tail->next = calloc(1, sizeof(rivatimer_t)); + rivatimer_tail = rivatimer_tail->next; + new_rivatimer = rivatimer_tail; + } + + // sanity check + if (new_rivatimer) + { + new_rivatimer->running = false; + new_rivatimer->period = period; + new_rivatimer->next = NULL; // indicate this is the last in the list + new_rivatimer->callback = callback; + } + + return new_rivatimer; +} + +// Determines if a rivatimer really exists. +bool rivatimer_really_exists(rivatimer_t* rivatimer) +{ + rivatimer_t* current = rivatimer_head; + + if (!current) + return false; + + while (current) + { + if (current == rivatimer) + return true; + + current = current->next; + } + + return false; +} + +// Destroy a rivatimer. +void rivatimer_destroy(rivatimer_t* rivatimer_ptr) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_destroy: The timer was already destroyed, or never existed in the first place. Punch starfrost in the face"); + + // Case: We are destroying the head + if (rivatimer_ptr == rivatimer_head) + { + // This is the only rivatimer + if (rivatimer_ptr->next == NULL) + { + rivatimer_head = NULL; + rivatimer_tail = NULL; + } + // This is not the only rivatimer + else + { + rivatimer_head = rivatimer_ptr->next; + rivatimer_head->prev = NULL; + // This is the only rivatimer and now there is only one + if (!rivatimer_head->next) + rivatimer_tail = rivatimer_head; + } + } + // Case: We are destroying the tail + else if (rivatimer_ptr == rivatimer_tail) + { + // We already covered the case where there is only one item above + rivatimer_tail = rivatimer_ptr->prev; + rivatimer_tail->next = NULL; + } + // Case: This is not the first or last rivatimer, so we don't need to set the head or tail + else + { + // Fix the break in the chain that this + if (rivatimer_ptr->next) + rivatimer_ptr->prev->next = rivatimer_ptr->next; + if (rivatimer_ptr->prev) + rivatimer_ptr->next->prev = rivatimer_ptr->prev; + } + + free(rivatimer_ptr); + rivatimer_ptr = NULL; //explicitly set to null +} + +void rivatimer_update_all() +{ + rivatimer_t* rivatimer_ptr = rivatimer_head; + + if (!rivatimer_ptr) + return; + + while (rivatimer_ptr) + { + // if it's not running skip it + if (!rivatimer_ptr->running) + { + rivatimer_ptr = rivatimer_ptr->next; + continue; + } + + #ifdef _WIN32 + LARGE_INTEGER current_time; + + QueryPerformanceCounter(¤t_time); + + double microseconds = ((double)current_time.QuadPart / 1000000.0) - (rivatimer_ptr->starting_time.QuadPart / 1000000.0); + #else + struct timespec current_time; + + clock_gettime(CLOCK_REALTIME, ¤t_time); + + double microseconds = ((double)current_time.tv_sec * 1000000.0) + ((double)current_time.tv_nsec / 1000.0); + #endif + + rivatimer_ptr->time += microseconds; + + // Reset the current time so we can actually restart + #ifdef _WIN32 + QueryPerformanceCounter(&rivatimer_ptr->starting_time); + #else + clock_gettime(CLOCK_REALTIME, &rivatimer_ptr->starting_time); + #endif + + // Time to fire + if (microseconds > rivatimer_ptr->period) + { + if (!rivatimer_ptr->callback) + { + pclog("Eh? No callback in RivaTimer?"); + continue; + } + + rivatimer_ptr->callback(microseconds); + } + + rivatimer_ptr = rivatimer_ptr->next; + } + +} + +void rivatimer_start(rivatimer_t* rivatimer_ptr) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_start: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + if (rivatimer_ptr->period <= 0) + fatal("rivatimer_start: Zero period!"); + + rivatimer_ptr->running = true; + + // Start off so rivatimer_update_all can actually update. + #ifdef _WIN32 + QueryPerformanceCounter(&rivatimer_ptr->starting_time); + #else + clock_gettime(CLOCK_REALTIME, &rivatimer_ptr->starting_time); + #endif +} + +void rivatimer_stop(rivatimer_t* rivatimer_ptr) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_stop: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + rivatimer_ptr->running = false; + rivatimer_ptr->time = 0; +} + +// Get the current time value of a rivatimer +double rivatimer_get_time(rivatimer_t* rivatimer_ptr) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_get_time: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + return rivatimer_ptr->time; +} + +void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double real_time)) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_set_callback: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + if (!callback) + fatal("rivatimer_set_callback: No callback!"); + + rivatimer_ptr->callback = callback; +} + +void rivatimer_set_period(rivatimer_t* rivatimer_ptr, double period) +{ + if (!rivatimer_really_exists(rivatimer_ptr)) + fatal("rivatimer_set_period: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + + rivatimer_ptr->period = period; +} \ No newline at end of file From 6eaec5b756fab78c94fcb861155acb7ed2c576fe Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 15:31:54 +0000 Subject: [PATCH 43/65] forgot to port over some parts --- src/timer.c | 4 ++++ src/video/CMakeLists.txt | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/timer.c b/src/timer.c index 6ddf8ebb5..2b92a1958 100644 --- a/src/timer.c +++ b/src/timer.c @@ -4,6 +4,7 @@ #include #include <86box/86box.h> #include <86box/timer.h> +#include <86Box/nv/vid_nv_rivatimer.h> uint64_t TIMER_USEC; uint32_t timer_target; @@ -168,6 +169,9 @@ timer_init(void) timer_target = 0ULL; tsc = 0; + /* Initialise the CPU-independent timer */ + rivatimer_init(); + timer_inited = 1; } diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index bbd329b7e..3d8e14c5e 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -27,7 +27,9 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c - vid_bochs_vbe.c) + vid_bochs_vbe.c + nv/nv_rivatimer.c + ) if(G100) target_compile_definitions(vid PRIVATE USE_G100) From 55f476617d67cc476f48c42cfe04554019afe82b Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 19:07:27 +0000 Subject: [PATCH 44/65] Don't punch me in the face, and also fix the compilation, and also fix a stupid bug in log replay. --- src/86box.c | 5 ++--- src/include/86box/nv/vid_nv_rivatimer.h | 6 +++--- src/video/nv/nv_rivatimer.c | 12 ++++++------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/86box.c b/src/86box.c index 8450c8b6b..b5a4de15e 100644 --- a/src/86box.c +++ b/src/86box.c @@ -271,8 +271,7 @@ static int suppr_seen = 1; /* Ensures STDLOG is open for pclog_ex and pclog_ex_cyclic */ -void -pclog_ensure_stdlog_open() +void pclog_ensure_stdlog_open() { if (stdlog == NULL) { if (log_path[0] != '\0') { @@ -399,7 +398,7 @@ pclog_ex_cyclic(const char* fmt, va_list ap) { // *very important* to prevent out of bounds index uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; - fprintf(stdlog, "%s", temp); + fprintf(stdlog, "%s", cyclic_buff[real_index]); } diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h index d5bb86b90..627bbcdcf 100644 --- a/src/include/86box/nv/vid_nv_rivatimer.h +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -63,7 +63,7 @@ typedef struct rivatimer_s double value; // The current value of the rivatimer bool running; // Is this RivaTimer running? struct rivatimer_s* next; // Next RivaTimer - void (*callback)(); // Callback to call on fire + void (*callback)(void); // Callback to call on fire #ifdef _WIN32 LARGE_INTEGER starting_time; // Starting time. #else @@ -72,11 +72,11 @@ typedef struct rivatimer_s double time; // Accumulated time in uS. } rivatimer_t; -void rivatimer_init(); // Initialise the Rivatimer. +void rivatimer_init(void); // Initialise the Rivatimer. rivatimer_t* rivatimer_create(double period, void (*callback)(double real_time)); void rivatimer_destroy(rivatimer_t* rivatimer_ptr); -void rivatimer_update_all(); +void rivatimer_update_all(void); void rivatimer_start(rivatimer_t* rivatimer_ptr); void rivatimer_stop(rivatimer_t* rivatimer_ptr); double rivatimer_get_time(rivatimer_t* rivatimer_ptr); diff --git a/src/video/nv/nv_rivatimer.c b/src/video/nv/nv_rivatimer.c index 343ec02ff..ee8c13916 100644 --- a/src/video/nv/nv_rivatimer.c +++ b/src/video/nv/nv_rivatimer.c @@ -120,7 +120,7 @@ bool rivatimer_really_exists(rivatimer_t* rivatimer) void rivatimer_destroy(rivatimer_t* rivatimer_ptr) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_destroy: The timer was already destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_destroy: The timer was already destroyed, or never existed in the first place."); // Case: We are destroying the head if (rivatimer_ptr == rivatimer_head) @@ -221,7 +221,7 @@ void rivatimer_update_all() void rivatimer_start(rivatimer_t* rivatimer_ptr) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_start: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_start: The timer has been destroyed, or never existed in the first place."); if (rivatimer_ptr->period <= 0) fatal("rivatimer_start: Zero period!"); @@ -239,7 +239,7 @@ void rivatimer_start(rivatimer_t* rivatimer_ptr) void rivatimer_stop(rivatimer_t* rivatimer_ptr) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_stop: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_stop: The timer has been destroyed, or never existed in the first place."); rivatimer_ptr->running = false; rivatimer_ptr->time = 0; @@ -249,7 +249,7 @@ void rivatimer_stop(rivatimer_t* rivatimer_ptr) double rivatimer_get_time(rivatimer_t* rivatimer_ptr) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_get_time: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_get_time: The timer has been destroyed, or never existed in the first place."); return rivatimer_ptr->time; } @@ -257,7 +257,7 @@ double rivatimer_get_time(rivatimer_t* rivatimer_ptr) void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double real_time)) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_set_callback: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_set_callback: The timer has been destroyed, or never existed in the first place."); if (!callback) fatal("rivatimer_set_callback: No callback!"); @@ -268,7 +268,7 @@ void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double void rivatimer_set_period(rivatimer_t* rivatimer_ptr, double period) { if (!rivatimer_really_exists(rivatimer_ptr)) - fatal("rivatimer_set_period: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face"); + fatal("rivatimer_set_period: The timer has been destroyed, or never existed in the first place."); rivatimer_ptr->period = period; } \ No newline at end of file From cbfeed7ea46acbc6d2481798b1dc920b8bcbc50d Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 19:09:35 +0000 Subject: [PATCH 45/65] Fix incorrect include --- src/include/86box/nv/vid_nv_rivatimer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h index 627bbcdcf..8ccc0f0df 100644 --- a/src/include/86box/nv/vid_nv_rivatimer.h +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -47,7 +47,7 @@ So I decided to create this timer that is completely separate from the CPU Core. #include #include #include -#include <86Box\86box.h> +#include <86Box/86box.h> #ifdef _WIN32 #include From 8c48478706d8b7c53fc6afe0ddc5498fcab8f1f1 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 19:11:20 +0000 Subject: [PATCH 46/65] fix the screwed up callbacks --- src/include/86box/nv/vid_nv_rivatimer.h | 2 +- src/video/nv/nv_rivatimer.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h index 8ccc0f0df..a4fe85e92 100644 --- a/src/include/86box/nv/vid_nv_rivatimer.h +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -63,7 +63,7 @@ typedef struct rivatimer_s double value; // The current value of the rivatimer bool running; // Is this RivaTimer running? struct rivatimer_s* next; // Next RivaTimer - void (*callback)(void); // Callback to call on fire + void (*callback)(double real_time); // Callback to call on fire #ifdef _WIN32 LARGE_INTEGER starting_time; // Starting time. #else diff --git a/src/video/nv/nv_rivatimer.c b/src/video/nv/nv_rivatimer.c index ee8c13916..44e5901d1 100644 --- a/src/video/nv/nv_rivatimer.c +++ b/src/video/nv/nv_rivatimer.c @@ -34,7 +34,7 @@ rivatimer_t* rivatimer_tail; // The tail of the rivatimer list. /* Functions only used in this translation unit */ bool rivatimer_really_exists(rivatimer_t* rivatimer); // Determine if a rivatimer really exists in the linked list. -void rivatimer_init() +void rivatimer_init(void) { // Destroy all the rivatimers. rivatimer_t* rivatimer_ptr = rivatimer_head; @@ -162,7 +162,7 @@ void rivatimer_destroy(rivatimer_t* rivatimer_ptr) rivatimer_ptr = NULL; //explicitly set to null } -void rivatimer_update_all() +void rivatimer_update_all(void) { rivatimer_t* rivatimer_ptr = rivatimer_head; From 8dc456cce5c2eb87e744ec1d82858a98f14ffec3 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 12 Jan 2025 20:37:50 +0100 Subject: [PATCH 47/65] NCR 5380-based changes of the day (January 12, 2025) 1. Sanity check for the SCSI temp_buffer if it's allocated or not. 2. Data reads and writes in non-DMA mode should be accessible only when DMA mode is Idle (as in, no DMA at all, whereas DMA mode will go to the SCSI controllers' callbacks). --- src/scsi/scsi_ncr5380.c | 47 ++++++++++++++++++++++++++------------- src/scsi/scsi_ncr53c400.c | 38 +++++++++++++++++++++++-------- src/scsi/scsi_t128.c | 2 ++ 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 527ff373f..092cc08e9 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -197,20 +197,29 @@ ncr5380_bus_read(ncr_t *ncr) phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); if (phase == SCSI_PHASE_DATA_IN) { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - ncr->state = STATE_DATAIN; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; + if (ncr->dma_mode == DMA_IDLE) { + ncr5380_log("Phase Data In.\n"); + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + + ncr->state = STATE_DATAIN; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; + } } else if (phase == SCSI_PHASE_DATA_OUT) { if (ncr->new_phase & BUS_IDLE) { ncr->state = STATE_IDLE; ncr->cur_bus &= ~BUS_BSY; - } else - ncr->state = STATE_DATAOUT; + } else { + if (ncr->dma_mode == DMA_IDLE) + ncr->state = STATE_DATAOUT; + } } else if (phase == SCSI_PHASE_STATUS) { + ncr5380_log("Phase Status.\n"); ncr->cur_bus |= BUS_REQ; ncr->state = STATE_STATUS; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; } else if (phase == SCSI_PHASE_MESSAGE_IN) { + ncr5380_log("Phase Message In.\n"); ncr->state = STATE_MESSAGEIN; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; } else if (phase == SCSI_PHASE_MESSAGE_OUT) { @@ -335,19 +344,22 @@ ncr5380_bus_update(ncr_t *ncr, int bus) if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { if (ncr->data_pos >= dev->buffer_length) { ncr->cur_bus &= ~BUS_REQ; + ncr5380_log("CMD Phase1 DataIn.\n"); scsi_device_command_phase1(dev); ncr->new_phase = SCSI_PHASE_STATUS; ncr->wait_data = 4; ncr->wait_complete = 8; } else { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/ ncr->data_wait |= 1; - ncr5380_log("DMA mode idle in\n"); + ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos); ncr->timer(ncr->priv, ncr->period); } else { - ncr5380_log("DMA mode IN.\n"); + ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos); ncr->clear_req = 3; } @@ -359,7 +371,8 @@ ncr5380_bus_update(ncr_t *ncr, int bus) case STATE_DATAOUT: dev = &scsi_devices[ncr->bus][ncr->target_id]; if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); + if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) + dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); if (ncr->data_pos >= dev->buffer_length) { ncr->cur_bus &= ~BUS_REQ; @@ -439,12 +452,12 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) switch (port & 7) { case 0: /* Output data register */ - ncr5380_log("Write: Output data register, val = %02x\n", val); + ncr5380_log("[%04X:%08X]: Write: Output data register, val=%02x\n", CS, cpu_state.pc, val); ncr->output_data = val; break; case 1: /* Initiator Command Register */ - ncr5380_log("Write: Initiator command register\n"); + ncr5380_log("[%04X:%08X]: Write: Initiator command register, val=%02x.\n", CS, cpu_state.pc, val); if ((val & 0x80) && !(ncr->icr & 0x80)) { ncr5380_log("Resetting the 5380\n"); ncr5380_reset(ncr); @@ -465,7 +478,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 3: /* Target Command Register */ - ncr5380_log("Write: Target Command register\n"); + ncr5380_log("Write: Target Command register, val=%02x.\n", val); ncr->tcr = val; break; @@ -482,7 +495,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 7: /* start DMA Initiator Receive */ - ncr5380_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA); + ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; if (ncr->dma_initiator_receive_ext) @@ -510,13 +523,13 @@ ncr5380_read(uint16_t port, ncr_t *ncr) ncr5380_log("Read: Current SCSI data register\n"); if (ncr->icr & ICR_DBP) { /*Return the data from the output register if on data bus phase from ICR*/ - ncr5380_log("Data Bus Phase, ret = %02x\n", ncr->output_data); ret = ncr->output_data; + ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x.\n", CS, cpu_state.pc, ret, ncr->clear_req, ncr->wait_data); } else { /*Return the data from the SCSI bus*/ ncr5380_bus_read(ncr); - ncr5380_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->cur_bus)); ret = BUS_GETDATA(ncr->cur_bus); + ncr5380_log("[%04X:%08X]: NCR Get SCSI bus data=%02x.\n", CS, cpu_state.pc, ret); } break; @@ -595,7 +608,9 @@ ncr5380_read(uint16_t port, ncr_t *ncr) break; case 6: - ret = ncr->tx_data; + ncr5380_log("Read: Input Data.\n"); + ncr5380_bus_read(ncr); + ret = BUS_GETDATA(ncr->cur_bus); break; case 7: /* reset Parity/Interrupt */ diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index 6622ec59a..997e8f152 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -148,6 +148,12 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) ncr400->busy = 1; if (!(ncr->mode & MODE_MONITOR_BUSY) && ((scsi_device_get_callback(dev) > 0.0))) timer_on_auto(&ncr400->timer, ncr->period / 250.0); + else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) { + if (scsi_device_get_callback(dev) > 0.0) + timer_on_auto(&ncr400->timer, 100.0); + else + timer_on_auto(&ncr400->timer, 40.0); + } } } break; @@ -181,13 +187,14 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { memset(ncr400->buffer, 0, MIN(128, dev->buffer_length)); if (ncr->mode & MODE_MONITOR_BUSY) - timer_on_auto(&ncr400->timer, ncr->period); + timer_on_auto(&ncr400->timer, (ncr->period / 4.0) * 3.0); else if (scsi_device_get_callback(dev) > 0.0) timer_on_auto(&ncr400->timer, 40.0); else timer_on_auto(&ncr400->timer, ncr->period); - ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); + ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", + ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); } break; @@ -244,6 +251,12 @@ ncr53c400_read(uint32_t addr, void *priv) ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl); if (!(ncr->mode & MODE_MONITOR_BUSY) && (scsi_device_get_callback(dev) > 0.0)) timer_on_auto(&ncr400->timer, ncr->period / 250.0); + else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) { + if (scsi_device_get_callback(dev) > 0.0) + timer_on_auto(&ncr400->timer, 100.0); + else + timer_on_auto(&ncr400->timer, 40.0); + } } } break; @@ -397,16 +410,20 @@ t130b_in(uint16_t port, void *priv) } static void -ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv)) +ncr53c400_dma_mode_ext(void *priv, void *ext_priv) { - ncr_t *ncr = (ncr_t *) priv; + ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv; + ncr_t *ncr = (ncr_t *) priv; /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - if (!(ncr->mode & MODE_DMA)) { - ncr53c400_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - ncr->dma_mode = DMA_IDLE; + ncr53c400_log("BlockCountLoaded=%d.\n", ncr400->block_count_loaded); + if (!ncr400->block_count_loaded) { + if (!(ncr->mode & MODE_DMA)) { + ncr53c400_log("No DMA mode\n"); + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + ncr->dma_mode = DMA_IDLE; + } } } @@ -474,6 +491,7 @@ ncr53c400_callback(void *priv) ncr400->block_count = (ncr400->block_count - 1) & 0xff; ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", ncr400->block_count); if (!ncr400->block_count) { + ncr->dma_mode = DMA_IDLE; ncr400->block_count_loaded = 0; ncr53c400_log("IO End of write transfer\n"); ncr->tcr |= TCR_LAST_BYTE_SENT; @@ -527,6 +545,7 @@ ncr53c400_callback(void *priv) ncr400->block_count = (ncr400->block_count - 1) & 0xff; ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count); if (!ncr400->block_count) { + ncr->dma_mode = DMA_IDLE; ncr400->block_count_loaded = 0; ncr53c400_log("IO End of read transfer\n"); ncr->isr |= STATUS_END_OF_DMA; @@ -544,6 +563,7 @@ ncr53c400_callback(void *priv) break; } + ncr53c400_log("Bus Read.\n"); ncr5380_bus_read(ncr); if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index c878bbb91..faad87052 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -287,6 +287,7 @@ write_again: t128->block_count = (t128->block_count - 1) & 0xff; t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); if (!t128->block_count) { + ncr->dma_mode = DMA_IDLE; t128->block_loaded = 0; t128_log("IO End of write transfer\n"); ncr->tcr |= TCR_LAST_BYTE_SENT; @@ -343,6 +344,7 @@ read_again: t128_log("T128 Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", t128->block_count, t128->status, dev->buffer_length, ncr->command[0]); if (!t128->block_count) { t128->block_loaded = 0; + ncr->dma_mode = DMA_IDLE; t128_log("IO End of read transfer\n"); ncr->isr |= STATUS_END_OF_DMA; timer_stop(&t128->timer); From 4f15889638cb38a51e790c49391535040e13d10a Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 23:09:03 +0000 Subject: [PATCH 48/65] fix compile by fixing capitalisation --- src/include/86box/nv/vid_nv_rivatimer.h | 2 +- src/timer.c | 2 +- src/video/nv/nv_rivatimer.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/86box/nv/vid_nv_rivatimer.h b/src/include/86box/nv/vid_nv_rivatimer.h index a4fe85e92..59f6cfebf 100644 --- a/src/include/86box/nv/vid_nv_rivatimer.h +++ b/src/include/86box/nv/vid_nv_rivatimer.h @@ -47,7 +47,7 @@ So I decided to create this timer that is completely separate from the CPU Core. #include #include #include -#include <86Box/86box.h> +#include <86box/86box.h> #ifdef _WIN32 #include diff --git a/src/timer.c b/src/timer.c index 2b92a1958..a3a7c9efb 100644 --- a/src/timer.c +++ b/src/timer.c @@ -4,7 +4,7 @@ #include #include <86box/86box.h> #include <86box/timer.h> -#include <86Box/nv/vid_nv_rivatimer.h> +#include <86box/nv/vid_nv_rivatimer.h> uint64_t TIMER_USEC; uint32_t timer_target; diff --git a/src/video/nv/nv_rivatimer.c b/src/video/nv/nv_rivatimer.c index 44e5901d1..12d40c026 100644 --- a/src/video/nv/nv_rivatimer.c +++ b/src/video/nv/nv_rivatimer.c @@ -22,7 +22,7 @@ Since Windows XP, QueryPerformanceCounter and QueryPerformanceFrequency cannot f */ -#include <86Box/nv/vid_nv_rivatimer.h> +#include <86box/nv/vid_nv_rivatimer.h> #ifdef _WIN32 LARGE_INTEGER performance_frequency; From 31207c98d656e2a68fd9c4b1d7d5c4774bdaa6a2 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 23:15:43 +0000 Subject: [PATCH 49/65] hopefully the final issue...fix missing prototype --- src/86box.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/86box.c b/src/86box.c index b5a4de15e..219535c84 100644 --- a/src/86box.c +++ b/src/86box.c @@ -266,6 +266,9 @@ static int32_t log_cycles = 0; static int seen = 0; static int suppr_seen = 1; + +// Functions only used in this translation unit +void pclog_ensure_stdlog_open(); #endif /* @@ -273,6 +276,7 @@ static int suppr_seen = 1; */ void pclog_ensure_stdlog_open() { +#ifndef RELEASE_BUILD if (stdlog == NULL) { if (log_path[0] != '\0') { stdlog = plat_fopen(log_path, "w"); @@ -281,6 +285,7 @@ void pclog_ensure_stdlog_open() } else stdlog = stdout; } +#endif } /* From fa3fb7ecccb0c73cb0c33f74865eb65621f911d8 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 12 Jan 2025 23:22:22 +0000 Subject: [PATCH 50/65] explicit void... --- src/86box.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/86box.c b/src/86box.c index 219535c84..85cbb9957 100644 --- a/src/86box.c +++ b/src/86box.c @@ -268,13 +268,13 @@ static int seen = 0; static int suppr_seen = 1; // Functions only used in this translation unit -void pclog_ensure_stdlog_open(); +void pclog_ensure_stdlog_open(void); #endif /* Ensures STDLOG is open for pclog_ex and pclog_ex_cyclic */ -void pclog_ensure_stdlog_open() +void pclog_ensure_stdlog_open(void) { #ifndef RELEASE_BUILD if (stdlog == NULL) { From be878ede582870a70532890b85fbd43e6f242e8d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 13 Jan 2025 00:56:04 +0100 Subject: [PATCH 51/65] Okay, maybe for the 53c400 only so. Based on my tests, the former 5380 commit will apply to the 53c400 only, for now... --- src/scsi/scsi_ncr5380.c | 4 ++-- src/scsi/scsi_t128.c | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 092cc08e9..0c3af9282 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -197,7 +197,7 @@ ncr5380_bus_read(ncr_t *ncr) phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); if (phase == SCSI_PHASE_DATA_IN) { - if (ncr->dma_mode == DMA_IDLE) { + if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext) { ncr5380_log("Phase Data In.\n"); if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; @@ -210,7 +210,7 @@ ncr5380_bus_read(ncr_t *ncr) ncr->state = STATE_IDLE; ncr->cur_bus &= ~BUS_BSY; } else { - if (ncr->dma_mode == DMA_IDLE) + if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext) ncr->state = STATE_DATAOUT; } } else if (phase == SCSI_PHASE_STATUS) { diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index faad87052..c878bbb91 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -287,7 +287,6 @@ write_again: t128->block_count = (t128->block_count - 1) & 0xff; t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); if (!t128->block_count) { - ncr->dma_mode = DMA_IDLE; t128->block_loaded = 0; t128_log("IO End of write transfer\n"); ncr->tcr |= TCR_LAST_BYTE_SENT; @@ -344,7 +343,6 @@ read_again: t128_log("T128 Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", t128->block_count, t128->status, dev->buffer_length, ncr->command[0]); if (!t128->block_count) { t128->block_loaded = 0; - ncr->dma_mode = DMA_IDLE; t128_log("IO End of read transfer\n"); ncr->isr |= STATUS_END_OF_DMA; timer_stop(&t128->timer); From f039fce49749779cf70d4f83545fd6d5da761f72 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 04:16:08 +0100 Subject: [PATCH 52/65] PIC: Signal to the CPU to end the block on IRR read, fixes stalls in waiting for IRQ, fixes #5108. --- src/pic.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pic.c b/src/pic.c index 82905261a..f8e83c40b 100644 --- a/src/pic.c +++ b/src/pic.c @@ -17,6 +17,7 @@ * Copyright 2015-2020 Andrew Jenner. * Copyright 2016-2020 Miran Grca. */ +#include #include #include #include @@ -491,12 +492,13 @@ pic_read(uint16_t addr, void *priv) else dev->data_bus = 0x00; #endif - } + } else + cpu_block_end = 1; /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, simply read whatever is currently on the data bus. */ } - pic_log("pic_read(%04X, %08X) = %02X\n", addr, priv, dev->data_bus); + pic_log("pic_read(%04X) = %02X\n", addr, dev->data_bus); return dev->data_bus; } From 123ff3b5e767864e8f1381ed18aeb3fa17966bbd Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 04:35:23 +0100 Subject: [PATCH 53/65] Fix NEC Vx0 INS*/OUS* timings calculation. --- src/cpu/808x.c | 53 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index d815551ae..0c1fb0f4d 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1634,28 +1634,55 @@ cpu_data_opff_rm(void) } } +uint8_t +cpu_inb(uint16_t port) +{ + uint8_t ret; + + wait(4, 0); + old_cycles = cycles; + + ret = inb(port); + + resub_cycles(); +} + uint16_t cpu_inw(uint16_t port) { - if (is8086 && !(port & 1)) { - wait(4, 0); - } else { - wait(8, 0); - } + uint16_t ret; - return inw(port); + if (is8086 && !(port & 1)) + wait(4, 0); + else + wait(8, 0); + + ret = inw(port); + + resub_cycles(); +} + +void +cpu_outb(uint16_t port, uint16_t val) +{ + wait(4, 0); + + outb(port, val); + + resub_cycles(); } void cpu_outw(uint16_t port, uint16_t val) { - if (is8086 && !(port & 1)) { + if (is8086 && !(port & 1)) wait(4, 0); - } else { + else wait(8, 0); - } - return outw(port, val); + outw(port, val); + + resub_cycles(); } /* Executes instructions up to the specified number of cycles. */ @@ -1804,8 +1831,7 @@ execx86(int cycs) writememw(es, DI, cpu_inw(DX)); DI += (cpu_state.flags & D_FLAG) ? -2 : 2; } else { - wait(4, 0); - writememb(es, DI, inb(DX)); + writememb(es, DI, cpu_inb(DX)); DI += (cpu_state.flags & D_FLAG) ? -1 : 1; } @@ -1833,8 +1859,7 @@ execx86(int cycs) cpu_outw(DX, readmemw(dest_seg, SI)); SI += (cpu_state.flags & D_FLAG) ? -2 : 2; } else { - wait(4, 0); - outb(DX, readmemb(dest_seg + SI)); + cpu_outb(DX, readmemb(dest_seg + SI)); SI += (cpu_state.flags & D_FLAG) ? -1 : 1; } if (in_rep == 0) From b1f94abc27131792c4b33be5588a736ac1f3c916 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 05:01:00 +0100 Subject: [PATCH 54/65] Fixed the fix. --- src/cpu/808x.c | 52 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 0c1fb0f4d..f37672a5c 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1637,52 +1637,72 @@ cpu_data_opff_rm(void) uint8_t cpu_inb(uint16_t port) { + int old_cycles = cycles; uint8_t ret; - wait(4, 0); + wait(is_mazovia ? 5 : 4, 1); old_cycles = cycles; ret = inb(port); - resub_cycles(); + resub_cycles(old_cycles); + + return ret; } uint16_t cpu_inw(uint16_t port) { + int old_cycles = cycles; uint16_t ret; - if (is8086 && !(port & 1)) - wait(4, 0); - else - wait(8, 0); + wait(is_mazovia ? 5 : 4, 1); + if (is8086 && !(port & 1)) { + old_cycles = cycles; + ret = inw(port); + } else { + wait(is_mazovia ? 5 : 4, 1); + old_cycles = cycles; + ret = inb(port++); + ret |= (inb(port) << 8); + } - ret = inw(port); + resub_cycles(old_cycles); - resub_cycles(); + return ret; } void cpu_outb(uint16_t port, uint16_t val) { - wait(4, 0); + int old_cycles = cycles; + + wait(is_mazovia ? 5 : 4, 1); + old_cycles = cycles; outb(port, val); - resub_cycles(); + resub_cycles(old_cycles); } void cpu_outw(uint16_t port, uint16_t val) { - if (is8086 && !(port & 1)) - wait(4, 0); - else - wait(8, 0); + int old_cycles = cycles; - outw(port, val); + wait(is_mazovia ? 5 : 4, 1); - resub_cycles(); + if (is8086 && !(port & 1)) { + old_cycles = cycles; + outw(port, val); + } else { + wait(is_mazovia ? 5 : 4, 1); + old_cycles = cycles; + outb(port++, val); + outb(port, val >> 8); + } + + resub_cycles(old_cycles); } /* Executes instructions up to the specified number of cycles. */ From ec175738ee48899770c7275179beb2746dc26312 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 05:38:10 +0100 Subject: [PATCH 55/65] FIX timings of SYSCALL/SYSRET/SYSENTER/SYSEXIT/FXSAVE/FXSTOR. --- src/cpu/x86_ops_amd.h | 12 ++---------- src/cpu/x86_ops_i686.h | 28 ++++++++++------------------ 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/cpu/x86_ops_amd.h b/src/cpu/x86_ops_amd.h index 9e6bcce55..54da4a79d 100644 --- a/src/cpu/x86_ops_amd.h +++ b/src/cpu/x86_ops_amd.h @@ -22,12 +22,8 @@ opSYSCALL(uint32_t fetchdat) ret = syscall_op(fetchdat); - if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); - PREFETCH_FLUSH(); + if (ret <= 1) CPU_BLOCK_END(); - } return ret; } @@ -41,12 +37,8 @@ opSYSRET(uint32_t fetchdat) ret = sysret(fetchdat); - if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); - PREFETCH_FLUSH(); + if (ret <= 1) CPU_BLOCK_END(); - } return ret; } diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index 5e5dc3c7c..a67571875 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -18,12 +18,8 @@ opSYSENTER(uint32_t fetchdat) { int ret = sysenter(fetchdat); - if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); - PREFETCH_FLUSH(); + if (ret <= 1) CPU_BLOCK_END(); - } return ret; } @@ -33,12 +29,8 @@ opSYSEXIT(uint32_t fetchdat) { int ret = sysexit(fetchdat); - if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); - PREFETCH_FLUSH(); + if (ret <= 1) CPU_BLOCK_END(); - } return ret; } @@ -118,7 +110,8 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward); } - CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + // CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + CLOCK_CYCLES(1); } else { /* FXSAVE */ writememw(easeg, cpu_state.eaaddr, i387_get_control_word()); @@ -163,7 +156,7 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.signExp); } - CLOCK_CYCLES((cr0 & 1) ? 56 : 67); + CLOCK_CYCLES(1); } return cpu_state.abrt; @@ -327,7 +320,8 @@ fx_save_stor_common(uint32_t fetchdat, int bits) } } - CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + // CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + CLOCK_CYCLES(1); } else { /* FXSAVE */ if ((twd & 0x0003) != 0x0003) @@ -372,7 +366,7 @@ fx_save_stor_common(uint32_t fetchdat, int bits) cpu_state.eaaddr = old_eaaddr; - CLOCK_CYCLES((cr0 & 1) ? 56 : 67); + CLOCK_CYCLES(1); } return cpu_state.abrt; @@ -400,8 +394,7 @@ static int opHINT_NOP_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + CLOCK_CYCLES(1); return 0; } @@ -409,7 +402,6 @@ static int opHINT_NOP_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + CLOCK_CYCLES(1); return 0; } From ad056b136c1413fdf371114d9524186312cde807 Mon Sep 17 00:00:00 2001 From: eddmanx Date: Mon, 13 Jan 2025 17:09:01 +0400 Subject: [PATCH 56/65] Update README.md - added the Avalonia86 manager --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ce38632e6..c01a852b5 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ It is also recommended to use a manager application with 86Box for easier handli * [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only) * [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia) +* [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux) * [sl86](https://github.com/DDXofficial/sl86) by [DDX](https://github.com/DDXofficial) (Command-line 86Box machine manager written in Python) * [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/Dungeonseeker/) (Linux focused, should work on Windows though untested) * [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only) From d39a8b9867cee2879c05cae606ff7715708223a2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 17:36:56 +0100 Subject: [PATCH 57/65] Reverted the PIC fix as it was apparently a red herring. --- src/pic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pic.c b/src/pic.c index f8e83c40b..fa7ff3662 100644 --- a/src/pic.c +++ b/src/pic.c @@ -492,8 +492,7 @@ pic_read(uint16_t addr, void *priv) else dev->data_bus = 0x00; #endif - } else - cpu_block_end = 1; + } /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, simply read whatever is currently on the data bus. */ } From 29ec9fa9ba5bb383dbda07716a9630e822442e55 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 13 Jan 2025 21:10:12 +0100 Subject: [PATCH 58/65] More NCR53c400 fixes (January 13th, 2025) Getting on my nerves, NCR 5380... --- src/include/86box/scsi_ncr5380.h | 1 + src/scsi/scsi_ncr5380.c | 9 +++++---- src/scsi/scsi_ncr53c400.c | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index 55692075b..09307fed6 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -104,6 +104,7 @@ typedef struct ncr_t { int state; int clear_req; int wait_data; + int wait_data_back; int wait_complete; int command_pos; int data_pos; diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 0c3af9282..c5fddc801 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -197,7 +197,7 @@ ncr5380_bus_read(ncr_t *ncr) phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); if (phase == SCSI_PHASE_DATA_IN) { - if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext) { + if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext || (ncr->wait_data_back == 1)) { ncr5380_log("Phase Data In.\n"); if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL)) ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; @@ -210,11 +210,12 @@ ncr5380_bus_read(ncr_t *ncr) ncr->state = STATE_IDLE; ncr->cur_bus &= ~BUS_BSY; } else { - if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext) + if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext || (ncr->wait_data_back == 1)) ncr->state = STATE_DATAOUT; } } else if (phase == SCSI_PHASE_STATUS) { ncr5380_log("Phase Status.\n"); + ncr->wait_data_back = 0; ncr->cur_bus |= BUS_REQ; ncr->state = STATE_STATUS; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; @@ -359,7 +360,7 @@ ncr5380_bus_update(ncr_t *ncr, int bus) ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos); ncr->timer(ncr->priv, ncr->period); } else { - ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos); + pclog("DMA mode IN=%d.\n", ncr->data_pos); ncr->clear_req = 3; } @@ -495,7 +496,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 7: /* start DMA Initiator Receive */ - ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); + pclog("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; if (ncr->dma_initiator_receive_ext) diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index 997e8f152..e028c7b42 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -193,6 +193,7 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) else timer_on_auto(&ncr400->timer, ncr->period); + ncr->wait_data_back = ncr->wait_data; ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); } From c9985798d3f785ef09c0ac053d25a554b95d15e1 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 13 Jan 2025 22:04:29 +0100 Subject: [PATCH 59/65] Remove excess logs. --- src/scsi/scsi_ncr5380.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index c5fddc801..e5dff88f8 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -360,7 +360,7 @@ ncr5380_bus_update(ncr_t *ncr, int bus) ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos); ncr->timer(ncr->priv, ncr->period); } else { - pclog("DMA mode IN=%d.\n", ncr->data_pos); + ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos); ncr->clear_req = 3; } @@ -496,7 +496,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) break; case 7: /* start DMA Initiator Receive */ - pclog("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); + ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; if (ncr->dma_initiator_receive_ext) From 40c52048a60057fcee0e31baa186ca7980881670 Mon Sep 17 00:00:00 2001 From: unreal9010 <84349460+unreal9010@users.noreply.github.com> Date: Mon, 13 Jan 2025 23:20:57 +0100 Subject: [PATCH 60/65] Added a couple of Quantum Fireball SE/EX drives --- src/disk/hdd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/disk/hdd.c b/src/disk/hdd.c index b861b5e50..5243f016b 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -448,9 +448,13 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-2] Quantum Fireball 640AT", .internal_name = "FB64A341", .model = "QUANTUM FIREBALL 640AT", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3.1, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Quantum Fireball TM1080AT", .internal_name = "TM10A462", .model = "QUANTUM FIREBALL TM1.0A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Quantum Fireball TM1.2AT", .internal_name = "TM12A012", .model = "QUANTUM FIREBALL TM1.2A", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 100, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 100, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 2, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, - { .name = "[ATA-2] Quantum Fireball EX5.1AT", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-2] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-2] Samsung PLS-31274A", .internal_name = "PLS31274A", .model = "SAMSUNG PLS-31274A", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 45, .track_seek_ms = 4.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 8 }, { .name = "[ATA-2] Samsung Winner-1", .internal_name = "WNR31601A", .model = "SAMSUNG WNR-31601A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Seagate Medalist (ST3780A)", .internal_name = "ST3780A", .model = "ST3780A", .zones = 8, .avg_spt = 120, .heads = 4, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 16 }, From 5b101aad81915c64b677c2e92cd5c60be809bd97 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2025 23:22:37 +0100 Subject: [PATCH 61/65] AT KBC: Fast track command AE (enable keyboard) because the LG MultiNet sends command A7 immediately after it, fixes keyboard lock-ups in its CMOS Setup. --- src/device/kbc_at.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 5c3c9ac6e..74be59017 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2127,6 +2127,13 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) } else if (fast_reset && ((val & 0xf0) == 0xf0)) { pulse_output(dev, val & 0x0f); + dev->state = STATE_MAIN_IBF; + return; + } else if (val == 0xae) { + /* Fast track it because of the LG MultiNet. */ + kbc_at_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + dev->state = STATE_MAIN_IBF; return; } From b1f54b9b84b0a653808fef789be987b34cfcbe03 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Tue, 14 Jan 2025 00:31:13 +0000 Subject: [PATCH 62/65] Move cyclical logging to the new logging system per obat feedback. --- src/86box.c | 113 +------------------------- src/include/86box/86box.h | 1 - src/include/86box/log.h | 7 ++ src/log.c | 167 +++++++++++++++++++++++++++++++++++--- 4 files changed, 162 insertions(+), 126 deletions(-) diff --git a/src/86box.c b/src/86box.c index 85cbb9957..97c211bee 100644 --- a/src/86box.c +++ b/src/86box.c @@ -254,14 +254,9 @@ static volatile atomic_int pause_ack = 0; #ifndef RELEASE_BUILD -#define LOG_SIZE_BUFFER 1024 /* Log size buffer */ -#define LOG_SIZE_BUFFER_CYCLIC_LINES 32 /* Cyclic log size buffer (number of lines that should be cehcked) */ -#define LOG_MINIMUM_REPEAT_ORDER 4 /* Minimum repeat size */ +#define LOG_SIZE_BUFFER 1024 /* Log size buffer */ static char buff[LOG_SIZE_BUFFER]; -static char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; -static int32_t cyclic_last_line = 0; -static int32_t log_cycles = 0; static int seen = 0; @@ -322,112 +317,6 @@ pclog_ex(const char *fmt, va_list ap) } -/* -Starfrost, 7-8 January 2025: - -For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found. - -Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm -*/ -void -pclog_ex_cyclic(const char* fmt, va_list ap) -{ -#ifndef RELEASE_BUILD - char temp[LOG_SIZE_BUFFER]; - - cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES; - - vsprintf(temp, fmt, ap); - - pclog_ensure_stdlog_open(); - - strncpy(cyclic_buff[cyclic_last_line], temp, LOG_SIZE_BUFFER); - - uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0}; - - // Random numbers - uint32_t base = 257; - uint32_t mod = 1000000007; - - uint32_t repeat_order = 0; - bool is_cycle = false; - - // compute the set of hashes for the current log buffer - for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++) - { - if (cyclic_buff[log_line][0] == '\0') - continue; // skip - - for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++) - { - hashes[log_line] = hashes[log_line] * base + cyclic_buff[log_line][log_line_char] % mod; - } - } - - - // Now see if there are real cycles... - // We implement a minimum repeat size. - for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++) - { - //TODO: Log what we need for cycle 1. - //TODO: Command line option that lets us turn off this behaviour. - for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++) - { - if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES]) - { - repeat_order = check_size; - break; - } - } - - is_cycle = (repeat_order != 0); - - // if there still is a cycle.. - if (is_cycle) - break; - - } - - if (is_cycle) - { - if (cyclic_last_line % repeat_order == 0) - { - log_cycles++; - - if (log_cycles == 1) - { - // 'Replay' the last few log entries so they actually show up - // Todo: is this right? - - for (uint32_t index = cyclic_last_line - 1; index > (cyclic_last_line - repeat_order); index--) - { - // *very important* to prevent out of bounds index - uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; - fprintf(stdlog, "%s", cyclic_buff[real_index]); - - } - - fprintf(stdlog, "%s", temp); // allow normal logging - } - - - if (log_cycles > 1 && log_cycles < 100) - fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log_cycles); - else if (log_cycles == 100) - fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n"); - } - } - else - { - log_cycles = 0; - fprintf(stdlog, "%s", temp); - } - - cyclic_last_line++; - -#endif - -} void pclog_toggle_suppr(void) diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 05c2a901e..96aeb645c 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -189,7 +189,6 @@ extern int config_changed; /* config has changed */ #ifdef HAVE_STDARG_H extern void pclog_ex(const char *fmt, va_list ap); extern void fatal_ex(const char *fmt, va_list ap); -extern void pclog_ex_cyclic(const char* fmt, va_list ap); #endif extern void pclog_toggle_suppr(void); #ifdef _MSC_VER diff --git a/src/include/86box/log.h b/src/include/86box/log.h index 9d3568069..7f0b96d60 100644 --- a/src/include/86box/log.h +++ b/src/include/86box/log.h @@ -12,9 +12,11 @@ * * Authors: Miran Grca, * Fred N. van Kempen, + * Connor Hyde * * Copyright 2021 Miran Grca. * Copyright 2021 Fred N. van Kempen. + * Copyright 2025 Connor Hyde. */ #ifndef EMU_LOG_H @@ -26,11 +28,16 @@ extern "C" { # endif +#define LOG_SIZE_BUFFER 1024 /* Log size buffer */ +#define LOG_SIZE_BUFFER_CYCLIC_LINES 32 /* Cyclic log size buffer (number of lines that should be cehcked) */ +#define LOG_MINIMUM_REPEAT_ORDER 4 /* Minimum repeat size */ + /* Function prototypes. */ extern void log_set_suppr_seen(void *priv, int suppr_seen); extern void log_set_dev_name(void *priv, char *dev_name); # ifdef HAVE_STDARG_H extern void log_out(void *priv, const char *fmt, va_list); +extern void log_out_cyclic(void* priv, const char *fmt, va_list); extern void log_fatal(void *priv, const char *fmt, ...); # endif extern void *log_open(char *dev_name); diff --git a/src/log.c b/src/log.c index b5267d70b..a4d84e616 100644 --- a/src/log.c +++ b/src/log.c @@ -12,12 +12,15 @@ * * Authors: Miran Grca, * Fred N. van Kempen, - * + * Connor Hyde + * * Copyright 2021 Miran Grca. * Copyright 2021 Fred N. van Kempen. + * Copyright 2025 Connor Hyde. */ #include #include +#include #include #include #include @@ -36,13 +39,31 @@ #ifndef RELEASE_BUILD typedef struct log_t { - char buff[1024]; - char *dev_name; - int seen; - int suppr_seen; + char buff[1024]; + char *dev_name; + int seen; + int suppr_seen; + char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; // Cyclical log buffer. This is 32kb, might calloc? + int32_t cyclic_last_line; + int32_t log_cycles; } log_t; extern FILE *stdlog; /* file to log output to */ +// Functions only used in this translation unit +void log_ensure_stdlog_open(void); + +void +log_ensure_stdlog_open(void) +{ + if (stdlog == NULL) { + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; + } +} void log_set_suppr_seen(void *priv, int suppr_seen) @@ -91,14 +112,7 @@ log_out(void *priv, const char *fmt, va_list ap) if (strcmp(fmt, "") == 0) return; - if (stdlog == NULL) { - if (log_path[0] != '\0') { - stdlog = plat_fopen(log_path, "w"); - if (stdlog == NULL) - stdlog = stdout; - } else - stdlog = stdout; - } + log_ensure_stdlog_open(); vsprintf(temp, fmt, ap); if (log->suppr_seen && !strcmp(log->buff, temp)) @@ -117,6 +131,131 @@ log_out(void *priv, const char *fmt, va_list ap) fflush(stdlog); } + +/* +Starfrost, 7-8 January 2025: + +For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found. + +Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm +*/ +void +log_out_cyclic(void* priv, const char* fmt, va_list ap) +{ +#ifndef RELEASE_BUILD + // get our new logging system instance. + log_t* log = (log_t*)priv; + + // does the log actually exist? + if (!log) + return; + + // is the string empty? + if (fmt[0] == '\0') + return; + + // ensure stdlog is open + log_ensure_stdlog_open(); + + char temp[LOG_SIZE_BUFFER] = {0}; + + log->cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES; + + vsprintf(temp, fmt, ap); + + log_copy(log, log->cyclic_buff[log->cyclic_last_line], temp, LOG_SIZE_BUFFER); + + uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0}; + + // Random numbers + uint32_t base = 257; + uint32_t mod = 1000000007; + + uint32_t repeat_order = 0; + bool is_cycle = false; + + // compute the set of hashes for the current log buffer + for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++) + { + if (log->cyclic_buff[log_line][0] == '\0') + continue; // skip + + for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++) + { + hashes[log_line] = hashes[log_line] * base + log->cyclic_buff[log_line][log_line_char] % mod; + } + } + + + // Now see if there are real cycles... + // We implement a minimum repeat size. + for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++) + { + //TODO: Log what we need for cycle 1. + //TODO: Command line option that lets us turn off this behaviour. + for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++) + { + if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES]) + { + repeat_order = check_size; + break; + } + } + + is_cycle = (repeat_order != 0); + + // if there still is a cycle.. + if (is_cycle) + break; + + } + + if (is_cycle) + { + if (log->cyclic_last_line % repeat_order == 0) + { + log->log_cycles++; + + if (log->log_cycles == 1) + { + // 'Replay' the last few log entries so they actually show up + // Todo: is this right? + + for (uint32_t index = log->cyclic_last_line - 1; index > (log->cyclic_last_line - repeat_order); index--) + { + // *very important* to prevent out of bounds index + uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES; + log_copy(log, temp, log->cyclic_buff[real_index], LOG_SIZE_BUFFER); + + fprintf(stdlog, "%s", log->cyclic_buff[real_index]); + + } + + // restore the original line + log_copy(log, temp, log->cyclic_buff[log->cyclic_last_line], LOG_SIZE_BUFFER); + + fprintf(stdlog, "%s", temp); // allow normal logging + } + + + if (log->log_cycles > 1 && log->log_cycles < 100) + fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log->log_cycles); + else if (log->log_cycles == 100) + fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n"); + } + } + else + { + log->log_cycles = 0; + fprintf(stdlog, "%s", temp); + } + + log->cyclic_last_line++; + +#endif + +} + void log_fatal(void *priv, const char *fmt, ...) { @@ -145,6 +284,8 @@ log_open(char *dev_name) log->dev_name = dev_name; log->suppr_seen = 1; + log->cyclic_last_line = 0; + log->log_cycles = 0; return (void *) log; } From 8fda1aca83241f04d02cea5efe2db78d76a539a8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2025 01:35:22 +0100 Subject: [PATCH 63/65] Acer V35N: Do not add the NVR - it is already added by the Super I/O chip. --- src/machine/m_at_socket7.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index f80d2d421..2dbb83684 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -58,10 +58,6 @@ machine_at_acerv35n_init(const machine_t *model) return ret; machine_at_common_init_ex(model, 2); - /* Yes, it's called amstrad_mega_pc_nvr_device, but it's basically the - standard AT NVR, just initialized to 0x00's (perhaps that should be the - default behavior?). */ - device_add(&amstrad_megapc_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); From efd5a6a47483e454d2cf496c87488aee939c2f34 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2025 02:38:44 +0100 Subject: [PATCH 64/65] SCAMP: Fixed EMS memory states, fixes #1966. --- src/chipset/scamp.c | 140 ++++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 52 deletions(-) diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c index 122318862..00f9798cb 100644 --- a/src/chipset/scamp.c +++ b/src/chipset/scamp.c @@ -101,6 +101,8 @@ typedef struct scamp_t { int ram_interleaved[2]; int ibank_shift[2]; + int ram_flags[24]; + port_92_t *port_92; } scamp_t; @@ -593,6 +595,35 @@ scamp_ems_write(uint32_t addr, uint8_t val, void *priv) ram[addr] = val; } +static void +scamp_mem_update_state(scamp_t *dev, uint32_t addr, uint32_t size) +{ + uint8_t flags; + + if ((addr >= 0x000a0000) && (addr < 0x00100000)) { + flags = dev->ram_flags[(addr - 0x000a0000) >> 14]; + + if (flags & 4) + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else switch (flags & 3) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; + } + } +} + static void recalc_ems(scamp_t *dev) { @@ -630,34 +661,48 @@ recalc_ems(scamp_t *dev) if (new_mappings[segment] < (mem_size * 1024)) { mem_mapping_set_exec(&dev->ems_mappings[segment], ram + dev->mappings[segment]); mem_mapping_enable(&dev->ems_mappings[segment]); - } else + dev->ram_flags[segment] |= 0x04; + } else { mem_mapping_disable(&dev->ems_mappings[segment]); + dev->ram_flags[segment] &= 0xfb; + } + + scamp_mem_update_state(dev, 0xa0000 + segment * 0x4000, 0x4000); } } + + flushmmucache_nopc(); } static void -shadow_control(uint32_t addr, uint32_t size, int state, int ems_enable) +shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state) { - if (ems_enable) - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - else - switch (state) { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - default: - break; - } + dev->ram_flags[(addr - 0x000a0000) >> 14] &= 0xfc; + dev->ram_flags[(addr - 0x000a0000) >> 14] |= state; + + if (size == 0x8000) { + dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] &= 0xfc; + dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] |= state; + } + + switch (state) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; + } + + scamp_mem_update_state(dev, addr, size); flushmmucache_nopc(); } @@ -669,47 +714,38 @@ shadow_recalc(scamp_t *dev) uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_CAXS]; uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_DAXS]; uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_FEAXS]; - uint32_t ems_enable; - - if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB) { - if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSMAP) /*Axxx/Bxxx/Dxxx*/ - ems_enable = (dev->cfg_regs[CFG_EMSEN2] & 0xf) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 4) | ((dev->cfg_regs[CFG_EMSEN2] & 0xf0) << 8); - else /*Cxxx/Dxxx/Exxx*/ - ems_enable = (dev->cfg_regs[CFG_EMSEN2] << 8) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 16); - } else - ems_enable = 0; /*Enabling remapping will disable all shadowing*/ if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) mem_remap_top(384); - shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00001); - shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00002); - shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00004); - shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00008); + shadow_control(dev, 0xa0000, 0x4000, abaxs & 3); + shadow_control(dev, 0xa0000, 0x4000, abaxs & 3); + shadow_control(dev, 0xa8000, 0x4000, (abaxs >> 2) & 3); + shadow_control(dev, 0xa8000, 0x4000, (abaxs >> 2) & 3); - shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00010); - shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00020); - shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00040); - shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00080); + shadow_control(dev, 0xb0000, 0x4000, (abaxs >> 4) & 3); + shadow_control(dev, 0xb0000, 0x4000, (abaxs >> 4) & 3); + shadow_control(dev, 0xb8000, 0x4000, (abaxs >> 6) & 3); + shadow_control(dev, 0xb8000, 0x4000, (abaxs >> 6) & 3); - shadow_control(0xc0000, 0x4000, caxs & 3, ems_enable & 0x00100); - shadow_control(0xc4000, 0x4000, (caxs >> 2) & 3, ems_enable & 0x00200); - shadow_control(0xc8000, 0x4000, (caxs >> 4) & 3, ems_enable & 0x00400); - shadow_control(0xcc000, 0x4000, (caxs >> 6) & 3, ems_enable & 0x00800); + shadow_control(dev, 0xc0000, 0x4000, caxs & 3); + shadow_control(dev, 0xc4000, 0x4000, (caxs >> 2) & 3); + shadow_control(dev, 0xc8000, 0x4000, (caxs >> 4) & 3); + shadow_control(dev, 0xcc000, 0x4000, (caxs >> 6) & 3); - shadow_control(0xd0000, 0x4000, daxs & 3, ems_enable & 0x01000); - shadow_control(0xd4000, 0x4000, (daxs >> 2) & 3, ems_enable & 0x02000); - shadow_control(0xd8000, 0x4000, (daxs >> 4) & 3, ems_enable & 0x04000); - shadow_control(0xdc000, 0x4000, (daxs >> 6) & 3, ems_enable & 0x08000); + shadow_control(dev, 0xd0000, 0x4000, daxs & 3); + shadow_control(dev, 0xd4000, 0x4000, (daxs >> 2) & 3); + shadow_control(dev, 0xd8000, 0x4000, (daxs >> 4) & 3); + shadow_control(dev, 0xdc000, 0x4000, (daxs >> 6) & 3); - shadow_control(0xe0000, 0x4000, feaxs & 3, ems_enable & 0x10000); - shadow_control(0xe4000, 0x4000, feaxs & 3, ems_enable & 0x20000); - shadow_control(0xe8000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x40000); - shadow_control(0xec000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x80000); + shadow_control(dev, 0xe0000, 0x4000, feaxs & 3); + shadow_control(dev, 0xe4000, 0x4000, feaxs & 3); + shadow_control(dev, 0xe8000, 0x4000, (feaxs >> 2) & 3); + shadow_control(dev, 0xec000, 0x4000, (feaxs >> 2) & 3); - shadow_control(0xf0000, 0x8000, (feaxs >> 4) & 3, 0); - shadow_control(0xf8000, 0x8000, (feaxs >> 6) & 3, 0); + shadow_control(dev, 0xf0000, 0x8000, (feaxs >> 4) & 3); + shadow_control(dev, 0xf8000, 0x8000, (feaxs >> 6) & 3); } static void From c36e6be6e248da16b2828a84a76dc57364e912d9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2025 06:27:41 +0100 Subject: [PATCH 65/65] NEAT: Fix EMS and implement Shadow RAM and top 128K of conventional memory on/off, closes #1375. --- src/chipset/neat.c | 367 +++++++++++++++++++++++++++++---------------- 1 file changed, 238 insertions(+), 129 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 97c4b8f1a..94f0d66e1 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -37,6 +37,9 @@ #define EMS_MAXPAGE 4 #define EMS_PGSIZE 16384 +#define EMS_PGMASK 16383 + +#define REG_MASK 0x0f /* CS8221 82C211 controller registers. */ #define REG_RA0 0x60 /* PROCCLK selector */ @@ -194,37 +197,47 @@ #define RB10_P0EXT 0xc0 /* page 0 extension */ #define RB10_P0EXT_SH 6 -#define REG_RB11 0x6f /* Miscellaneous */ -#define RB11_MASK 0xe6 /* 111R R11R */ -#define RB11_GA20 0x02 /* gate for A20 */ -#define RB11_RASTMO 0x04 /* enable RAS timeout counter */ -#define RB11_EMSLEN 0xe0 /* EMS memory chunk size */ -#define RB11_EMSLEN_SH 5 +#define REG_RB12 0x6f /* Miscellaneous */ +#define RB12_MASK 0xe6 /* 111R R11R */ +#define RB12_GA20 0x02 /* gate for A20 */ +#define RB12_RASTMO 0x04 /* enable RAS timeout counter */ +#define RB12_EMSLEN 0xe0 /* EMS memory chunk size */ +#define RB12_EMSLEN_SH 5 -typedef struct emspage_t { - int8_t enabled; /* 1=ENABLED */ +#define RAM_FLAG_EMS 0x08 +#define RAM_FLAG_ROMCS 0x04 +#define RAM_FLAG_SHREAD 0x02 +#define RAM_FLAG_SHWRITE 0x01 +#define RAM_FMASK_EMS 0x08 +#define RAM_FMASK_SHADOW 0x07 + +typedef struct ram_page_t { + int8_t enabled; /* 1=ENABLED */ char pad; - uint16_t page; /* selected page in EMS block */ - uint32_t start; /* start of EMS in RAM */ - uint8_t *addr; /* start addr in EMS RAM */ - mem_mapping_t mapping; /* mapping entry for page */ -} emspage_t; + uint32_t phys_base; + uint32_t virt_base; + mem_mapping_t mapping; /* mapping entry for page */ +} ram_page_t; typedef struct neat_t { - uint8_t regs[128]; /* all the CS8221 registers */ - uint8_t indx; /* programmed index into registers */ + uint8_t ram_flags[32]; + uint8_t regs[128]; /* all the CS8221 registers */ + uint8_t indx; /* programmed index into registers */ - char pad; + char pad; - uint16_t ems_base; /* configured base address */ - uint16_t ems_oldbase; - uint32_t ems_frame; /* configured frame address */ - uint32_t ems_oldframe; - uint16_t ems_size; /* EMS size in KB */ - uint16_t ems_pages; /* EMS size in pages */ - emspage_t ems[EMS_MAXPAGE]; /* EMS page registers */ + uint16_t ems_base; /* configured base address */ + uint32_t ems_frame; /* configured frame address */ + uint16_t ems_size; /* EMS size in KB */ + uint16_t ems_pages; /* EMS size in pages */ + + ram_page_t ems[EMS_MAXPAGE]; /* EMS page registers */ + ram_page_t shadow[32]; /* Shadow RAM pages */ } neat_t; +static uint8_t defaults[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 }; + #ifdef ENABLE_NEAT_LOG int neat_do_log = ENABLE_NEAT_LOG; @@ -247,11 +260,11 @@ neat_log(const char *fmt, ...) static uint8_t ems_readb(uint32_t addr, void *priv) { - neat_t *dev = (neat_t *) priv; - uint8_t ret = 0xff; + ram_page_t *dev = (ram_page_t *) priv; + uint8_t ret = 0xff; /* Grab the data. */ - ret = *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); + ret = *(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]); return ret; } @@ -260,11 +273,11 @@ ems_readb(uint32_t addr, void *priv) static uint16_t ems_readw(uint32_t addr, void *priv) { - neat_t *dev = (neat_t *) priv; - uint16_t ret = 0xffff; + ram_page_t *dev = (ram_page_t *) priv; + uint16_t ret = 0xffff; /* Grab the data. */ - ret = *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); + ret = *(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]); return ret; } @@ -273,40 +286,113 @@ ems_readw(uint32_t addr, void *priv) static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { - neat_t *dev = (neat_t *) priv; + ram_page_t *dev = (ram_page_t *) priv; /* Write the data. */ - *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; + *(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val; } /* Write one word to paged RAM. */ static void ems_writew(uint32_t addr, uint16_t val, void *priv) { - neat_t *dev = (neat_t *) priv; + ram_page_t *dev = (ram_page_t *) priv; /* Write the data. */ - *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; + *(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val; +} + +static void +neat_mem_update_state(neat_t *dev, uint32_t addr, uint32_t size, uint8_t new_flags, uint8_t mask) +{ + if ((addr >= 0x00080000) && (addr < 0x00100000) && + ((new_flags ^ dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]) & mask)) { + dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] &= ~mask; + dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] |= new_flags; + + new_flags = dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]; + + neat_log("neat_mem_update_state(): %08X-%08X: %02X\n", addr, addr + size - 1, new_flags); + + if (new_flags & RAM_FLAG_EMS) + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else if (new_flags & RAM_FLAG_ROMCS) + mem_set_mem_state(addr, size, MEM_READ_ROMCS | MEM_WRITE_ROMCS); + else switch (new_flags & (RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE)) { + 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_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; + } + } + + flushmmucache_nopc(); +} + +static void +shadow_recalc(neat_t *dev) +{ + for (uint8_t i = 8; i < 32; i++) { + int romcs = 0; + int write = 1; + int shadow_reg = REG_RB3 + ((i - 8) >> 3); + int shadow_bit = i & 7; + int ram_flags; + int read; + + if (i > 16) { + int rb1_romcs_bit = 7 - (i >> 2); + int rb1_write_bit = rb1_romcs_bit + 4; + + romcs = !(dev->regs[REG_RB1] & (1 << rb1_romcs_bit)); + write = !(dev->regs[REG_RB1] & (1 << rb1_write_bit)); + } else if (i <= 8) + shadow_bit ^= 4; + + read = dev->regs[shadow_reg] & (1 << shadow_bit); + write = write && read; + + ram_flags = romcs ? RAM_FLAG_ROMCS : 0x00; + ram_flags |= read ? RAM_FLAG_SHREAD : 0x00; + ram_flags |= write ? RAM_FLAG_SHWRITE : 0x00; + + if ((ram_flags > 0x00) && !(ram_flags & RAM_FLAG_ROMCS)) + mem_mapping_set_addr(&(dev->shadow[i].mapping), dev->shadow[i].virt_base, EMS_PGSIZE); + else + mem_mapping_disable(&(dev->shadow[i].mapping)); + + neat_mem_update_state(dev, dev->shadow[i].virt_base, EMS_PGSIZE, ram_flags, RAM_FMASK_SHADOW); + } } /* Re-calculate the active-page physical address. */ static void -ems_recalc(neat_t *dev, emspage_t *ems) +ems_recalc(neat_t *dev, ram_page_t *ems) { - if (ems->page >= dev->ems_pages) { - /* That page does not exist. */ - ems->enabled = 0; - } + uint32_t page = ems->phys_base / EMS_PGSIZE; - /* Pre-calculate the page address in EMS RAM. */ - ems->addr = ram + ems->start + (ems->page * EMS_PGSIZE); + if ((dev->regs[REG_RB7] & RB7_EMSEN) && ems->enabled && + (page >= 0x40) && (page < (0x40 + dev->ems_pages))) { + neat_log("ems_recalc(): %08X-%08X -> %08X-%08X\n", + ems->virt_base, ems->virt_base + EMS_PGSIZE - 1, + ems->phys_base, ems->phys_base + EMS_PGSIZE - 1); + mem_mapping_set_addr(&ems->mapping, ems->virt_base, EMS_PGSIZE); - if (ems->enabled) { /* Update the EMS RAM address for this page. */ - mem_mapping_set_exec(&ems->mapping, ems->addr); + mem_mapping_set_exec(&ems->mapping, ram + ems->phys_base); - /* Enable this page. */ - mem_mapping_enable(&ems->mapping); + if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000)) + neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, RAM_FLAG_EMS, RAM_FMASK_EMS); #if NEAT_DEBUG > 1 neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n", @@ -315,15 +401,18 @@ ems_recalc(neat_t *dev, emspage_t *ems) } else { /* Disable this page. */ mem_mapping_disable(&ems->mapping); + + if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000)) + neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, RAM_FMASK_EMS); } } static void ems_write(uint16_t port, uint8_t val, void *priv) { - neat_t *dev = (neat_t *) priv; - emspage_t *ems; - int vpage; + neat_t *dev = (neat_t *) priv; + ram_page_t *ems; + int vpage; #if NEAT_DEBUG > 1 neat_log("NEAT: ems_write(%04x, %02x)\n", port, val); @@ -337,8 +426,7 @@ ems_write(uint16_t port, uint8_t val, void *priv) case 0x0008: case 0x0009: ems->enabled = !!(val & 0x80); - ems->page &= 0x0180; /* clear lower bits */ - ems->page |= (val & 0x7f); /* add new bits */ + ems->phys_base = (ems->phys_base & 0xffe00000) | ((val & 0x7f) * EMS_PGSIZE); ems_recalc(dev, ems); break; default: @@ -358,7 +446,7 @@ ems_read(uint16_t port, void *priv) switch (port & 0x000f) { case 0x0008: /* page number register */ - ret = dev->ems[vpage].page & 0x7f; + ret = (dev->ems[vpage].phys_base / EMS_PGSIZE) & 0x7f; if (dev->ems[vpage].enabled) ret |= 0x80; break; @@ -373,68 +461,21 @@ ems_read(uint16_t port, void *priv) return ret; } -/* Initialize the EMS module. */ static void -ems_init(neat_t *dev, int en) +ems_update(neat_t *dev, int en) { - uint8_t j; - - /* Remove if needed. */ - if (!en) { - if (dev->ems_base > 0) - for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { - /* Disable for now. */ - mem_mapping_disable(&dev->ems[i].mapping); - - /* Remove I/O handler. */ - io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2, - ems_read, NULL, NULL, ems_write, NULL, NULL, dev); - } - -#ifdef ENABLE_NEAT_LOG - neat_log("NEAT: EMS disabled\n"); -#endif - - return; - } - - /* Get configured I/O address. */ - j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; - dev->ems_base = 0x0208 + (0x10 * j); - - /* Get configured frame address. */ - j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; - dev->ems_frame = 0xC0000 + (EMS_PGSIZE * j); - - /* - * For each supported page (we can have a maximum of 4), - * create, initialize and disable the mappings, and set - * up the I/O control handler. - */ for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { - /* Create and initialize a page mapping. */ - mem_mapping_add(&dev->ems[i].mapping, - dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE, - ems_readb, ems_readw, NULL, - ems_writeb, ems_writew, NULL, - ram, MEM_MAPPING_EXTERNAL, - dev); - - /* Disable for now. */ - mem_mapping_disable(&dev->ems[i].mapping); - /* Set up an I/O port handler. */ - io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2, - ems_read, NULL, NULL, ems_write, NULL, NULL, dev); + io_handler(en, dev->ems_base + (i * EMS_PGSIZE), 2, + ems_read, NULL, NULL, ems_write, NULL, NULL, dev); - /* - * TODO: update the 'high_mem' mapping to reflect that we now - * have NN MB less extended memory available.. - */ + if (en) + dev->ems[i].virt_base = dev->ems_frame + (i * EMS_PGSIZE); + + ems_recalc(dev, &(dev->ems[i])); } - neat_log("NEAT: EMS enabled, I/O=%04xH, Frame=%05XH\n", - dev->ems_base, dev->ems_frame); + flushmmucache_nopc(); } static void @@ -442,6 +483,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) { neat_t *dev = (neat_t *) priv; uint8_t xval; + uint8_t j; uint8_t *reg; int i; @@ -493,6 +535,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB1: val &= RB1_MASK; *reg = (*reg & ~RB1_MASK) | val; + shadow_recalc(dev); #if NEAT_DEBUG > 1 neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg); #endif @@ -501,6 +544,10 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB2: val &= RB2_MASK; *reg = (*reg & ~RB2_MASK) | val; + if (val & RB2_TOP128) + neat_mem_update_state(dev, 0x00080000, 0x00020000, RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE, RAM_FMASK_SHADOW); + else + neat_mem_update_state(dev, 0x00080000, 0x00020000, 0x00, RAM_FMASK_SHADOW); #if NEAT_DEBUG > 1 neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg); #endif @@ -509,6 +556,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB3: val &= RB3_MASK; *reg = (*reg & ~RB3_MASK) | val; + shadow_recalc(dev); #if NEAT_DEBUG > 1 neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg); #endif @@ -517,6 +565,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB4: val &= RB4_MASK; *reg = (*reg & ~RB4_MASK) | val; + shadow_recalc(dev); #if NEAT_DEBUG > 1 neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg); #endif @@ -525,6 +574,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB5: val &= RB5_MASK; *reg = (*reg & ~RB5_MASK) | val; + shadow_recalc(dev); #if NEAT_DEBUG > 1 neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg); #endif @@ -544,10 +594,9 @@ neat_write(uint16_t port, uint8_t val, void *priv) #if NEAT_DEBUG > 1 neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg); #endif - if (val & RB7_EMSEN) - ems_init(dev, 1); - else if (xval & RB7_EMSEN) - ems_init(dev, 0); + + if (xval & RB7_EMSEN) + ems_update(dev, !!(val & RB7_EMSEN)); if (xval & RB7_UMAREL) { if (val & RB7_UMAREL) @@ -571,10 +620,19 @@ neat_write(uint16_t port, uint8_t val, void *priv) #if NEAT_DEBUG > 1 neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg); #endif - if (dev->regs[REG_RB7] & RB7_EMSEN) { - ems_init(dev, 0); - ems_init(dev, 1); - } + + ems_update(dev, 0); + + /* Get configured I/O address. */ + j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; + dev->ems_base = 0x0208 + (0x10 * j); + + /* Get configured frame address. */ + j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; + dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j); + + if (dev->regs[REG_RB7] & RB7_EMSEN) + ems_update(dev, 1); break; case REG_RB10: @@ -584,23 +642,29 @@ neat_write(uint16_t port, uint8_t val, void *priv) neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg); #endif - dev->ems[3].start = ((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21; - dev->ems[2].start = ((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21; - dev->ems[1].start = ((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21; - dev->ems[0].start = ((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21; - for (i = 0; i < EMS_MAXPAGE; i++) - ems_recalc(dev, &dev->ems[i]); + dev->ems[3].phys_base = (dev->ems[3].phys_base & 0x001fffff) | + (((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21); + dev->ems[2].phys_base = (dev->ems[2].phys_base & 0x001fffff) | + (((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21); + dev->ems[1].phys_base = (dev->ems[1].phys_base & 0x001fffff) | + (((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21); + dev->ems[0].phys_base = (dev->ems[0].phys_base & 0x001fffff) | + (((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21); + + if (dev->regs[REG_RB7] & RB7_EMSEN) + for (i = 0; i < EMS_MAXPAGE; i++) + ems_recalc(dev, &dev->ems[i]); break; - case REG_RB11: - val &= RB11_MASK; - *reg = (*reg & ~RB11_MASK) | val; + case REG_RB12: + val &= RB12_MASK; + *reg = (*reg & ~RB12_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB11=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB12=%02x(%02x)\n", val, *reg); #endif - i = (val & RB11_EMSLEN) >> RB11_EMSLEN_SH; + i = (val & RB12_EMSLEN) >> RB12_EMSLEN_SH; switch (i) { - case 0: /* "less than 2MB" */ + case 0: /* "less than 1MB" */ dev->ems_size = 512; break; @@ -617,10 +681,18 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; } dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE; + + if (dev->regs[REG_RB7] & RB7_EMSEN) + for (i = 0; i < EMS_MAXPAGE; i++) + ems_recalc(dev, &dev->ems[i]); + if (dev->regs[REG_RB7] & RB7_EMSEN) { neat_log("NEAT: EMS %iKB (%i pages)\n", dev->ems_size, dev->ems_pages); } + + mem_a20_key = val & RB12_GA20; + mem_a20_recalc(); break; default: @@ -629,6 +701,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; } break; + default: break; } @@ -646,8 +719,10 @@ neat_read(uint16_t port, void *priv) break; case 0x23: - if ((dev->indx >= 0x60) && (dev->indx <= 0x6f)) + if ((dev->indx >= 0x60) && (dev->indx <= 0x6e)) ret = dev->regs[dev->indx]; + else if (dev->indx == 0x6f) + ret = (dev->regs[dev->indx] & 0xfd) | (mem_a20_key & 2); break; default: @@ -674,16 +749,50 @@ neat_init(UNUSED(const device_t *info)) { neat_t *dev; uint8_t dram_mode = 0; - uint8_t i; + uint8_t j; /* Create an instance. */ dev = (neat_t *) malloc(sizeof(neat_t)); memset(dev, 0x00, sizeof(neat_t)); + /* Get configured I/O address. */ + j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; + dev->ems_base = 0x0208 + (0x10 * j); + + /* Get configured frame address. */ + j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; + dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j); + + mem_mapping_disable(&ram_mid_mapping); + + /* + * For each supported page (we can have a maximum of 4), + * create, initialize and disable the mappings, and set + * up the I/O control handler. + */ + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + /* Create and initialize a page mapping. */ + mem_mapping_add(&dev->ems[i].mapping, + dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE, + ems_readb, ems_readw, NULL, + ems_writeb, ems_writew, NULL, + ram, MEM_MAPPING_INTERNAL, + &(dev->ems[i])); + + /* Disable for now. */ + mem_mapping_disable(&dev->ems[i].mapping); + } + + for (uint8_t i = 0; i < 32; i++) { + dev->shadow[i].virt_base = dev->shadow[i].phys_base = + (i * EMS_PGSIZE) + 0x00080000; + dev->shadow[i].enabled = 1; + } + /* Initialize some of the registers to specific defaults. */ - for (i = REG_RA0; i <= REG_RB11; i++) { + for (uint8_t i = REG_RA0; i <= REG_RB12; i++) { dev->indx = i; - neat_write(0x0023, 0x00, dev); + neat_write(0x0023, defaults[i & REG_MASK], dev); } /*