From 2b347047295c3bc001f9bd39ade8e42ec449299d Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sun, 25 Jul 2021 20:49:27 +0500 Subject: [PATCH 01/16] Add the Sound Blaster AWE64 Gold --- src/include/86box/snd_sb.h | 5 +- src/include/86box/sound.h | 1 + src/sound/snd_sb.c | 155 ++++++++++++++++++++++++++++++++++++- src/sound/snd_sb_dsp.c | 4 +- src/sound/sound.c | 1 + 5 files changed, 158 insertions(+), 8 deletions(-) diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 7889380f5..cb850584c 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -30,9 +30,8 @@ #define SBPRO 5 /* DSP v3.00 */ #define SBPRO2 6 /* DSP v3.02 + OPL3 */ #define SB16 7 /* DSP v4.05 + OPL3 */ -#define SADGOLD 8 /* AdLib Gold */ -#define SND_WSS 9 /* Windows Sound System */ -#define SND_PAS16 10 /* Pro Audio Spectrum 16 */ +#define SBAWE32 8 /* DSP v4.13 + OPL3 */ +#define SBAWE64 9 /* DSP v4.16 + OPL3 */ /* SB 2.0 CD version */ typedef struct sb_ct1335_mixer_t diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index b15724cdd..93339d6c6 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -116,6 +116,7 @@ extern const device_t sb_16_pnp_device; extern const device_t sb_32_pnp_device; extern const device_t sb_awe32_device; extern const device_t sb_awe32_pnp_device; +extern const device_t sb_awe64_gold_device; /* Innovation SSI-2001 */ extern const device_t ssi2001_device; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 8e1ea61a4..3d8e51806 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -244,6 +244,81 @@ static uint8_t sb_awe32_pnp_rom[] = { 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ }; +static uint8_t sb_awe64_gold_pnp_rom[] = { + 0x0e, 0x8c, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL009E, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x20, /* PnP version 1.0, vendor version 2.0 */ + 0x82, 0x16, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', ' ', 'A', 'W', 'E', '6', '4', ' ', 'G', 'o', 'l', 'd', /* ANSI identifier */ + + 0x16, 0x0e, 0x8c, 0x00, 0x44, 0x00, 0xa9, /* logical device CTL0044, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */ + 0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x22, 0x20, 0x00, /* IRQ 5 */ + 0x2a, 0x02, 0x0c, /* DMA 1, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0x20, 0x16, /* DMA 5, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x01, 0x10, /* I/O 0x220, decodes 16-bit, 1-byte alignment, 16 addresses */ + 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x01, 0x02, /* I/O 0x330, decodes 16-bit, 1-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x01, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x01, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x01, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x31, 0x02, /* start dependent functions, sub-optimal */ + 0x22, 0xa0, 0x06, /* IRQ 5/7/9/10 */ + 0x2a, 0x0b, 0x0c, /* DMA 0/1/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0xe0, 0x16, /* DMA 5/6/7, compatibility, count by word, no count by byte, is bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x94, 0x03, 0x04, 0x04, /* I/O 0x388-0x394, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x38, /* end dependent functions */ + + 0x15, 0x0e, 0x8c, 0x70, 0x02, 0x00, /* logical device CTL7002 */ + 0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */ + 0x82, 0x04, 0x00, 'G', 'a', 'm', 'e', /* ANSI identifier */ + 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x01, 0x08, /* I/O 0x200, decodes 16-bit, 1-byte alignment, 8 addresses */ + + 0x16, 0x0e, 0x8c, 0x00, 0x23, 0x00, 0xa9, /* logical device CTL0023, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */ + 0x82, 0x09, 0x00, 'W', 'a', 'v', 'e', 'T', 'a', 'b', 'l', 'e', /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x47, 0x01, 0x20, 0x06, 0x20, 0x06, 0x01, 0x04, /* I/O 0x620, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x0a, 0x20, 0x0a, 0x01, 0x04, /* I/O 0xA20, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x0e, 0x20, 0x0e, 0x01, 0x04, /* I/O 0xE20, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x20, 0x06, 0x80, 0x06, 0x20, 0x04, /* I/O 0x620-0x680, decodes 16-bit, 32-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x0a, 0x80, 0x0a, 0x20, 0x04, /* I/O 0xA20-0xA80, decodes 16-bit, 32-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x0e, 0x80, 0x0e, 0x20, 0x04, /* I/O 0xE20-0xE80, decodes 16-bit, 32-byte alignment, 4 addresses */ + 0x38, /* end dependent functions */ + + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ +}; #ifdef ENABLE_SB_LOG @@ -1301,6 +1376,27 @@ sb_awe32_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pr } +static void +sb_awe64_gold_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + sb_t *sb = (sb_t *) priv; + + switch (ld) { + case 0: /* Audio */ + sb_16_pnp_config_changed(0, config, sb); + break; + + case 1: /* Game */ + sb_16_pnp_config_changed(1, config, sb); + break; + + case 2: /* WaveTable */ + emu8k_change_addr(&sb->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + break; + } +} + + void * sb_1_init(const device_t *info) { @@ -1753,7 +1849,7 @@ sb_awe32_init(const device_t *info) if (sb->opl_enabled) opl3_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBAWE32, 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")); @@ -1803,7 +1899,7 @@ sb_awe32_pnp_init(const device_t *info) sb->opl_enabled = 1; opl3_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, ((info->local == 2) ? SBAWE64 : SBAWE32), SB_SUBTYPE_DEFAULT, sb); sb_ct1745_mixer_reset(sb); sb->mixer_enabled = 1; @@ -1822,7 +1918,9 @@ sb_awe32_pnp_init(const device_t *info) sb->gameport = gameport_add(&gameport_pnp_device); - if (info->local == 1) + if (info->local == 2) + isapnp_add_card(sb_awe64_gold_pnp_rom, sizeof(sb_awe64_gold_pnp_rom), sb_awe64_gold_pnp_config_changed, NULL, NULL, NULL, sb); + else if (info->local == 1) isapnp_add_card(sb_32_pnp_rom, sizeof(sb_32_pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb); else isapnp_add_card(sb_awe32_pnp_rom, sizeof(sb_awe32_pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb); @@ -2457,6 +2555,45 @@ static const device_config_t sb_awe32_pnp_config[] = } }; +static const device_config_t sb_awe64_gold_config[] = +{ + { + "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 4096, "", { 0 }, + { + { + "None", 0 + }, + { + "512 KB", 512 + }, + { + "2 MB", 2048 + }, + { + "4 MB", 4096 + }, + { + "8 MB", 8192 + }, + { + "28 MB", 28*1024 + }, + { + "" + } + } + }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 + }, + { + "", "", -1 + } +}; + const device_t sb_1_device = { "Sound Blaster v1.0", @@ -2603,3 +2740,15 @@ const device_t sb_awe32_pnp_device = NULL, sb_awe32_pnp_config }; + +const device_t sb_awe64_gold_device = +{ + "Sound Blaster AWE64 Gold", + DEVICE_ISA | DEVICE_AT, + 2, + sb_awe32_pnp_init, sb_awe32_close, NULL, + { sb_awe32_available }, + sb_speed_changed, + NULL, + sb_awe64_gold_config +}; diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 6203def85..ede51d576 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -66,7 +66,7 @@ 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, 0x40d}; +uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d, 0x410}; /*These tables were 'borrowed' from DOSBox*/ @@ -314,7 +314,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->sb_type < SBAWE64)) sb_commands[8] = 1; else sb_commands[8] = -1; diff --git a/src/sound/sound.c b/src/sound/sound.c index 851ccc92a..cddd83359 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -99,6 +99,7 @@ static const SOUND_CARD sound_cards[] = { "sb32_pnp", &sb_32_pnp_device }, { "sbawe32", &sb_awe32_device }, { "sbawe32_pnp", &sb_awe32_pnp_device }, + { "sbawe64_gold", &sb_awe64_gold_device }, #if defined(DEV_BRANCH) && defined(USE_PAS16) { "pas16", &pas16_device }, #endif From e864aa2edcdb25162b360312e89d1b6b6a7c0e75 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 26 Jul 2021 05:02:40 +0200 Subject: [PATCH 02/16] PIIX IDE non-bus master BAR's are now only writable on the SMSC Victory/66. --- src/chipset/intel_piix.c | 48 ++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 2c3e0fa89..57f5091c8 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -613,36 +613,52 @@ piix_write(int func, int addr, uint8_t val, void *priv) fregs[0x0d] = val & 0xf0; break; case 0x10: - fregs[0x10] = (val & 0xf8) | 1; - piix_ide_handlers(dev, 0x01); + if (dev->type == 5) { + fregs[0x10] = (val & 0xf8) | 1; + piix_ide_handlers(dev, 0x01); + } break; case 0x11: - fregs[0x11] = val; - piix_ide_handlers(dev, 0x01); + if (dev->type == 5) { + fregs[0x11] = val; + piix_ide_handlers(dev, 0x01); + } break; case 0x14: - fregs[0x14] = (val & 0xfc) | 1; - piix_ide_handlers(dev, 0x01); + if (dev->type == 5) { + fregs[0x14] = (val & 0xfc) | 1; + piix_ide_handlers(dev, 0x01); + } break; case 0x15: - fregs[0x15] = val; - piix_ide_handlers(dev, 0x01); + if (dev->type == 5) { + fregs[0x15] = val; + piix_ide_handlers(dev, 0x01); + } break; case 0x18: - fregs[0x18] = (val & 0xf8) | 1; - piix_ide_handlers(dev, 0x02); + if (dev->type == 5) { + fregs[0x18] = (val & 0xf8) | 1; + piix_ide_handlers(dev, 0x02); + } break; case 0x19: - fregs[0x19] = val; - piix_ide_handlers(dev, 0x02); + if (dev->type == 5) { + fregs[0x19] = val; + piix_ide_handlers(dev, 0x02); + } break; case 0x1c: - fregs[0x1c] = (val & 0xfc) | 1; - piix_ide_handlers(dev, 0x02); + if (dev->type == 5) { + fregs[0x1c] = (val & 0xfc) | 1; + piix_ide_handlers(dev, 0x02); + } break; case 0x1d: - fregs[0x1d] = val; - piix_ide_handlers(dev, 0x02); + if (dev->type == 5) { + fregs[0x1d] = val; + piix_ide_handlers(dev, 0x02); + } break; case 0x20: fregs[0x20] = (val & 0xf0) | 1; From 2d376b45845b70c63f098d8660233a2aab2ae6b1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 26 Jul 2021 05:07:13 +0200 Subject: [PATCH 03/16] The legacy SCSI configuration option is now always removed on config save, fixes #1561 . --- src/config.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index f9347a0a4..9f06262b8 100644 --- a/src/config.c +++ b/src/config.c @@ -2439,14 +2439,16 @@ save_storage_controllers(void) char temp[512]; int c; + config_delete_var(cat, "scsicard"); + for (c = 0; c < SCSI_BUS_MAX; c++) { sprintf(temp, "scsicard_%d", c + 1); if (scsi_card_current[c] == 0) config_delete_var(cat, temp); else - config_set_string(cat, temp, - scsi_card_get_internal_name(scsi_card_current[c])); + config_set_string(cat, temp, + scsi_card_get_internal_name(scsi_card_current[c])); } if (fdc_type == FDC_INTERNAL) From f79b11cd9a3be500f2397c259d1aa65918c4657c Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jul 2021 03:42:56 +0200 Subject: [PATCH 04/16] PIIX3 fixes. --- src/chipset/intel_piix.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 57f5091c8..a865e045a 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -589,18 +589,13 @@ piix_write(int func, int addr, uint8_t val, void *priv) } else if (func == 1) switch(addr) { /* IDE */ case 0x04: fregs[0x04] = (val & 5); - if (dev->type < 3) + if (dev->type <= 3) fregs[0x04] |= 0x02; piix_ide_handlers(dev, 0x03); piix_ide_bm_handlers(dev); break; case 0x07: - if (val & 0x20) - fregs[0x07] &= 0xdf; - if (val & 0x10) - fregs[0x07] &= 0xef; - if (val & 0x08) - fregs[0x07] &= 0xf7; + fregs[0x07] &= ~(val & 0x38); break; case 0x09: if (dev->type == 5) { @@ -669,7 +664,8 @@ piix_write(int func, int addr, uint8_t val, void *priv) piix_ide_bm_handlers(dev); break; case 0x3c: - fregs[0x3c] = val; + if (dev->type == 5) + fregs[0x3c] = val; break; case 0x3d: if (dev->type == 5) @@ -706,6 +702,8 @@ piix_write(int func, int addr, uint8_t val, void *priv) if (dev->type > 4) fregs[addr] = val; break; + default: + break; } else if (func == 2) switch(addr) { /* USB */ case 0x04: if (dev->type > 4) { @@ -1051,6 +1049,8 @@ piix_reset_hard(piix_t *dev) /* Function 1: IDE */ fregs = (uint8_t *) dev->regs[1]; piix_log("PIIX Function 1: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); + if (dev->type < 4) + fregs[0x04] = 0x02; fregs[0x06] = 0x80; fregs[0x07] = 0x02; if (dev->type == 4) fregs[0x08] = dev->rev & 0x07; From 827065c0bc3a7408925b89841454b695fd470304 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jul 2021 06:12:09 +0200 Subject: [PATCH 05/16] Ported the cassette emulation from PCE, closes #835. --- src/config.c | 56 +++ src/device/CMakeLists.txt | 2 +- src/device/cassette.c | 715 +++++++++++++++++++++++++++++++++++ src/device/keyboard_xt.c | 22 +- src/floppy/fdd.c | 4 +- src/include/86box/cassette.h | 173 +++++++++ src/include/86box/language.h | 4 +- src/include/86box/plat.h | 2 + src/include/86box/resource.h | 48 ++- src/include/86box/ui.h | 17 +- src/include/86box/win.h | 3 + src/machine/machine.c | 4 + src/pit.c | 4 + src/win/86Box.rc | 23 +- src/win/Makefile.mingw | 2 +- src/win/win_cdrom.c | 31 ++ src/win/win_media_menu.c | 130 ++++++- src/win/win_settings.c | 64 ++-- src/win/win_stbar.c | 45 +++ 19 files changed, 1274 insertions(+), 75 deletions(-) create mode 100644 src/device/cassette.c create mode 100644 src/include/86box/cassette.h diff --git a/src/config.c b/src/config.c index 9f06262b8..a85be31ca 100644 --- a/src/config.c +++ b/src/config.c @@ -37,6 +37,7 @@ #include "cpu.h" #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> #include <86box/nvr.h> #include <86box/config.h> #include <86box/isamem.h> @@ -1093,6 +1094,18 @@ load_storage_controllers(void) ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0); ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0); + + cassette_enable = !!config_get_int(cat, "cassette_enabled", 1); + p = config_get_string(cat, "cassette_file", ""); + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511\n"); + else + strncpy(cassette_fname, p, strlen(p) + 1); + cassette_mode = config_get_string(cat, "cassette_mode", "load"); + cassette_pos = config_get_int(cat, "cassette_position", 0); + cassette_srate = config_get_int(cat, "cassette_srate", 44100); + cassette_append = !!config_get_int(cat, "cassette_append", 0); + cassette_pcm = config_get_int(cat, "cassette_pcm", 0); } @@ -1954,6 +1967,14 @@ config_load(void) for (i = 0; i < ISAMEM_MAX; i++) isamem_type[i] = 0; + cassette_enable = 1; + memset(cassette_fname, 0x00, sizeof(cassette_fname)); + cassette_mode = "load"; + cassette_pos = 0; + cassette_srate = 44100; + cassette_append = 0; + cassette_pcm = 0; + config_log("Config file not present or invalid!\n"); return; } @@ -2471,6 +2492,41 @@ save_storage_controllers(void) config_set_int(cat, "ide_qua", ide_qua_enabled); delete_section_if_empty(cat); + + if (cassette_enable == 1) + config_delete_var(cat, "cassette_enabled"); + else + config_set_int(cat, "cassette_enabled", cassette_enable); + + if (cassette_fname == NULL) + config_delete_var(cat, "cassette_file"); + else + config_set_string(cat, "cassette_file", cassette_fname); + + if (cassette_mode == NULL) + config_delete_var(cat, "cassette_mode"); + else + config_set_string(cat, "cassette_mode", cassette_mode); + + if (cassette_pos == 0) + config_delete_var(cat, "cassette_position"); + else + config_set_int(cat, "cassette_position", cassette_pos); + + if (cassette_srate == 44100) + config_delete_var(cat, "cassette_srate"); + else + config_set_int(cat, "cassette_srate", cassette_srate); + + if (cassette_append == 0) + config_delete_var(cat, "cassette_append"); + else + config_set_int(cat, "cassette_append", cassette_append); + + if (cassette_pcm == 0) + config_delete_var(cat, "cassette_pcm"); + else + config_set_int(cat, "cassette_pcm", cassette_pcm); } diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index ae8cd867d..cecb241a5 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -13,7 +13,7 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(dev OBJECT bugger.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c +add_library(dev OBJECT bugger.c cassette.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c postcard.c serial.c vpc2007.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c smbus_piix4.c keyboard.c keyboard_xt.c keyboard_at.c mouse.c mouse_bus.c diff --git a/src/device/cassette.c b/src/device/cassette.c new file mode 100644 index 000000000..a849a4fb1 --- /dev/null +++ b/src/device/cassette.c @@ -0,0 +1,715 @@ +/***************************************************************************** + * pce * + *****************************************************************************/ + +/***************************************************************************** + * File name: src/arch/ibmpc/cassette.c * + * Created: 2008-11-25 by Hampa Hug * + * Copyright: (C) 2008-2019 Hampa Hug * + *****************************************************************************/ + +/***************************************************************************** + * This program is free software. You can redistribute it and / or modify it * + * under the terms of the GNU General Public License version 2 as published * + * by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY, without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * + * Public License for more details. * + *****************************************************************************/ + + +#include +#include +#include +#include +#include +#include + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include "cpu.h" +#include <86box/machine.h> +#include <86box/plat.h> +#include <86box/ui.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/cassette.h> + +// #include + + +#define CAS_CLK 1193182 + + +pc_cassette_t * cassette; + +char cassette_fname[512]; +char * cassette_mode; +unsigned long cassette_pos, cassette_srate; +int cassette_enable; +int cassette_append, cassette_pcm; +int cassette_ui_writeprot; + + +static int cassette_cycles = -1; + + +static void pc_cas_reset (pc_cassette_t *cas); + + +#ifdef ENABLE_CASSETTE_LOG +int cassette_do_log = ENABLE_CASSETTE_LOG; + + +static void +cassette_log(const char *fmt, ...) +{ + va_list ap; + + if (cassette_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define cassette_log(fmt, ...) +#endif + + +void pc_cas_init (pc_cassette_t *cas) +{ + cas->save = 0; + cas->pcm = 0; + + cas->motor = 0; + ui_sb_update_icon(SB_CASSETTE, 0); + + cas->position = 0; + + cas->position_save = 0; + cas->position_load = 0; + + cas->data_out = 0; + cas->data_inp = 0; + + cas->pcm_out_vol = 64; + cas->pcm_out_val = 0; + + cas->cas_out_cnt = 0; + cas->cas_out_buf = 0; + + cas->cas_inp_cnt = 0; + cas->cas_inp_buf = 0; + cas->cas_inp_bit = 0; + + cas->clk = 0; + + cas->clk_pcm = 0; + + cas->clk_out = 0; + cas->clk_inp = 0; + + cas->srate = 44100; + + cas->close = 0; + cas->fname = NULL; + cas->fp = NULL; + + pc_cas_reset (cas); +} + +void pc_cas_free (pc_cassette_t *cas) +{ + free (cas->fname); + + if (cas->close) { + fclose (cas->fp); + } +} + +pc_cassette_t *pc_cas_new (void) +{ + pc_cassette_t *cas; + + cas = malloc (sizeof (pc_cassette_t)); + + if (cas == NULL) { + return (NULL); + } + + pc_cas_init (cas); + + return (cas); +} + +void pc_cas_del (pc_cassette_t *cas) +{ + if (cas != NULL) { + pc_cas_free (cas); + free (cas); + } +} + +int pc_cas_set_fname (pc_cassette_t *cas, const char *fname) +{ + unsigned n; + const char * ext; + + if (cas->close) + fclose (cas->fp); + + cas->close = 0; + cas->fp = NULL; + + free (cas->fname); + cas->fname = NULL; + + cas->position = 0; + + cas->position_save = 0; + cas->position_load = 0; + + if (fname == NULL) { + ui_sb_update_icon_state(SB_CASSETTE, 1); + return (0); + } + + cas->fp = plat_fopen (fname, "r+b"); + + if (cas->fp == NULL) + cas->fp = plat_fopen (fname, "w+b"); + + if (cas->fp == NULL) { + ui_sb_update_icon_state(SB_CASSETTE, 1); + return (1); + } + + cas->close = 1; + + pc_cas_append (cas); + + cas->position_save = cas->position; + + if (cas->save == 0) + pc_cas_set_position (cas, 0); + + n = strlen (fname); + + cas->fname = malloc ((n + 1) * sizeof(char)); + + if (cas->fname != NULL) + memcpy (cas->fname, fname, (n + 1) * sizeof(char)); + + if (n > 4) { + ext = fname + (n - 4); + + /* Has to be 44.1 kHz, mono, 8-bit. */ + if (stricmp (ext, ".pcm") == 0) + pc_cas_set_pcm (cas, 1); + else if (stricmp (ext, ".raw") == 0) + pc_cas_set_pcm (cas, 1); + else if (stricmp (ext, ".wav") == 0) + pc_cas_set_pcm (cas, 1); + else if (stricmp (ext, ".cas") == 0) + pc_cas_set_pcm (cas, 0); + } + + return (0); +} + +static +void pc_cas_reset (pc_cassette_t *cas) +{ + unsigned i; + + cas->clk_pcm = 0; + + cas->clk_out = cas->clk; + cas->clk_inp = 0; + + cas->pcm_out_val = 0; + + cas->cas_out_cnt = 0; + cas->cas_out_buf = 0; + + cas->cas_inp_cnt = 0; + cas->cas_inp_buf = 0; + cas->cas_inp_bit = 0; + + for (i = 0; i < 3; i++) { + cas->pcm_inp_fir[i] = 0; + } +} + +int pc_cas_get_mode (const pc_cassette_t *cas) +{ + return (cas->save); +} + +void pc_cas_set_mode (pc_cassette_t *cas, int save) +{ + save = (save != 0); + + if (cas->save == save) { + return; + } + + if (cas->save) { + cas->position_save = cas->position; + cas->position = cas->position_load; + } + else { + cas->position_load = cas->position; + cas->position = cas->position_save; + } + + cas->save = save; + + if (cas->fp != NULL) { + fflush (cas->fp); + + pc_cas_set_position (cas, cas->position); + } + + pc_cas_reset (cas); +} + +int pc_cas_get_pcm (const pc_cassette_t *cas) +{ + return (cas->pcm); +} + +void pc_cas_set_pcm (pc_cassette_t *cas, int pcm) +{ + cas->pcm = (pcm != 0); + + cassette_pcm = (pcm != 0); + + pc_cas_reset (cas); +} + +unsigned long pc_cas_get_srate (const pc_cassette_t *cas) +{ + return (cas->srate); +} + +void pc_cas_set_srate (pc_cassette_t *cas, unsigned long srate) +{ + cas->srate = srate; + + pc_cas_reset (cas); +} + +void pc_cas_rewind (pc_cassette_t *cas) +{ + if (cas->fp != NULL) { + rewind (cas->fp); + cas->position = 0; + } + + pc_cas_reset (cas); +} + +void pc_cas_append (pc_cassette_t *cas) +{ + if (cas->fp != NULL) { + fseek (cas->fp, 0, SEEK_END); + cas->position = ftell (cas->fp); + } + + pc_cas_reset (cas); +} + +unsigned long pc_cas_get_position (const pc_cassette_t *cas) +{ + return (cas->position); +} + +int pc_cas_set_position (pc_cassette_t *cas, unsigned long pos) +{ + if (cas->fp == NULL) { + return (1); + } + + if (fseek (cas->fp, pos, SEEK_SET) != 0) { + return (1); + } + + cas->position = pos; + + pc_cas_reset (cas); + + return (0); +} + +static +void pc_cas_read_bit (pc_cassette_t *cas) +{ + int val; + + if (cas->cas_inp_cnt == 0) { + if (cas->fp == NULL) { + return; + } + + if (feof (cas->fp)) { + return; + } + + val = fgetc (cas->fp); + + if (val == EOF) { + cassette_log ("cassette EOF at %lu\n", cas->position); + return; + } + + cas->position += 1; + + cas->cas_inp_cnt = 8; + cas->cas_inp_buf = val; + } + + cas->cas_inp_bit = ((cas->cas_inp_buf & 0x80) != 0); + + cas->cas_inp_buf = (cas->cas_inp_buf << 1) & 0xff; + cas->cas_inp_cnt -= 1; +} + +static +int pc_cas_read_smp (pc_cassette_t *cas) +{ + int smp, *fir; + + if (feof (cas->fp)) { + return (0); + } + + smp = fgetc (cas->fp); + + if (smp == EOF) { + cassette_log ("cassette EOF at %lu\n", cas->position); + return (0); + } + + cas->position += 1; + + fir = cas->pcm_inp_fir; + + fir[0] = fir[1]; + fir[1] = fir[2]; + fir[2] = (smp & 0x80) ? (smp - 256) : smp; + + smp = (fir[0] + 2 * fir[1] + fir[2]) / 4; + + return (smp); +} + +static +void pc_cas_write_bit (pc_cassette_t *cas, unsigned char val) +{ + if (val) { + cas->cas_out_buf |= (0x80 >> cas->cas_out_cnt); + } + + cas->cas_out_cnt += 1; + + if (cas->cas_out_cnt >= 8) { + if (cas->fp != NULL) { + fputc (cas->cas_out_buf, cas->fp); + cas->position += 1; + } + + cas->cas_out_buf = 0; + cas->cas_out_cnt = 0; + } +} + +static +void pc_cas_write_smp (pc_cassette_t *cas, int val) +{ + unsigned char smp; + + if (val < 0) { + smp = (val < -127) ? 0x80 : (val + 256); + } + else { + smp = (val > 127) ? 0x7f : val; + } + + fputc (smp, cas->fp); + + cas->position += 1; +} + +void pc_cas_set_motor (pc_cassette_t *cas, unsigned char val) +{ + unsigned i; + + val = (val != 0); + + if (val == cas->motor) { + return; + } + + if ((val == 0) && cas->save && cas->pcm) { + for (i = 0; i < (cas->srate / 16); i++) { + pc_cas_write_smp (cas, 0); + } + } + + cassette_log ("cassette %S at %lu motor %s\n", (cas->fname != NULL) ? cas->fname : "", cas->position, val ? "on" : "off"); + + cas->motor = val; + + if (cas->fp != NULL) { + fflush (cas->fp); + + pc_cas_set_position (cas, cas->position); + } + + pc_cas_reset (cas); + + if (cas->motor) + timer_set_delay_u64(&cas->timer, 8ULL * PITCONST); + else + timer_disable(&cas->timer); + + ui_sb_update_icon(SB_CASSETTE, !!val); +} + +unsigned char pc_cas_get_inp (const pc_cassette_t *cas) +{ + return (cas->data_inp); +} + +void pc_cas_set_out (pc_cassette_t *cas, unsigned char val) +{ + unsigned long clk; + + val = (val != 0); + + if (cas->motor == 0) { + cas->data_inp = val; + return; + } + + if (cas->data_out == val) { + return; + } + + cas->data_out = val; + + if (cas->pcm) { + cas->pcm_out_val = val ? -cas->pcm_out_vol : cas->pcm_out_vol; + return; + } + + if (cas->save == 0) { + return; + } + + if (val == 0) { + return; + } + + clk = cas->clk - cas->clk_out; + cas->clk_out = cas->clk; + + if (clk < (CAS_CLK / 4000)) { + ; + } + else if (clk < ((3 * CAS_CLK) / 4000)) { + pc_cas_write_bit (cas, 0); + } + else if (clk < ((5 * CAS_CLK) / 4000)) { + pc_cas_write_bit (cas, 1); + } +} + +void pc_cas_print_state (const pc_cassette_t *cas) +{ + cassette_log ("%s %s %lu %s %lu\n", (cas->fname != NULL) ? cas->fname : "", cas->pcm ? "pcm" : "cas", cas->srate, cas->save ? "save" : "load", cas->position); +} + +static +void pc_cas_clock_pcm (pc_cassette_t *cas, unsigned long cnt) +{ + unsigned long i, n; + int v = 0; + + n = cas->srate * cnt + cas->clk_pcm; + + cas->clk_pcm = n % CAS_CLK; + + n = n / CAS_CLK; + + if (n == 0) { + return; + } + + if (cas->save) { + for (i = 0; i < n; i++) { + pc_cas_write_smp (cas, cas->pcm_out_val); + } + } + else { + for (i = 0; i < n; i++) { + v = pc_cas_read_smp (cas); + } + + cas->data_inp = (v < 0) ? 0 : 1; + } +} + +void pc_cas_clock (pc_cassette_t *cas, unsigned long cnt) +{ + cas->clk += cnt; + + if (cas->motor == 0) { + return; + } + + if (cas->pcm) { + pc_cas_clock_pcm (cas, cnt); + return; + } + + if (cas->save) { + return; + } + + if (cas->clk_inp > cnt) { + cas->clk_inp -= cnt; + return; + } + + cnt -= cas->clk_inp; + + cas->data_inp = !cas->data_inp; + + if (cas->data_inp) { + pc_cas_read_bit (cas); + } + + if (cas->cas_inp_bit) { + cas->clk_inp = CAS_CLK / 2000; + } + else { + cas->clk_inp = CAS_CLK / 4000; + } + + if (cas->clk_inp > cnt) { + cas->clk_inp -= cnt; + } +} + + +void pc_cas_advance (pc_cassette_t *cas) +{ + int ticks; + cpu_s = (CPU *) &cpu_f->cpus[cpu_effective]; + + if (cas->motor == 0) + return; + + if (cassette_cycles == -1) + cassette_cycles = cycles; + if (cycles <= cassette_cycles) + ticks = (cassette_cycles - cycles); + else + ticks = (cassette_cycles + (cpu_s->rspeed / 100) - cycles); + cassette_cycles = cycles; + + pc_cas_clock(cas, ticks); +} + + +static void +cassette_close(void *p) +{ + if (cassette != NULL) { + free(cassette); + cassette = NULL; + } +} + + +static void +cassette_callback(void *p) +{ + pc_cassette_t *cas = (pc_cassette_t *) p; + + pc_cas_clock (cas, 8); + + if (cas->motor) + ui_sb_update_icon(SB_CASSETTE, 1); + + timer_advance_u64(&cas->timer, 8ULL * PITCONST); +} + + +static void * +cassette_init(const device_t *info) +{ + cassette = NULL; + + if (cassette_pcm == 1) + cassette_pcm = -1; + + cassette_log("CASSETTE: file=%s mode=%s pcm=%d srate=%lu pos=%lu append=%d\n", + (cassette_fname != NULL) ? cassette_fname : "", cassette_mode, cassette_pcm, cassette_srate, cassette_pos, cassette_append); + + cassette = pc_cas_new(); + + if (cassette == NULL) { + cassette_log("ERROR: *** alloc failed\n"); + return NULL; + } + + if (strlen(cassette_fname) == 0) { + if (pc_cas_set_fname (cassette, NULL)) { + cassette_log("ERROR: *** opening file failed (%s)\n", cassette_fname); + } + } else { + if (pc_cas_set_fname (cassette, cassette_fname)) { + cassette_log("ERROR: *** opening file failed (%s)\n", cassette_fname); + } + } + + if (strcmp (cassette_mode, "load") == 0) + pc_cas_set_mode (cassette, 0); + else if (strcmp (cassette_mode, "save") == 0) + pc_cas_set_mode (cassette, 1); + else { + cassette_log ("ERROR: *** unknown cassette mode (%s)\n", cassette_mode); + } + + if (cassette_append) + pc_cas_append (cassette); + else + pc_cas_set_position (cassette, cassette_pos); + + if (cassette_pcm >= 0) + pc_cas_set_pcm (cassette, cassette_pcm); + + pc_cas_set_srate (cassette, cassette_srate); + + timer_add(&cassette->timer, cassette_callback, cassette, 0); + + return cassette; +} + + +const device_t cassette_device = { + "IBM PC/PCjr Cassette Device", + 0, + 0, + cassette_init, cassette_close, NULL, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index e68718c68..f090ff202 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -33,6 +33,7 @@ #include <86box/fdd.h> #include <86box/machine.h> #include <86box/m_xt_t1000.h> +#include <86box/cassette.h> #include <86box/io.h> #include <86box/pic.h> #include <86box/pit.h> @@ -515,13 +516,14 @@ kbd_write(uint16_t port, uint8_t val, void *priv) timer_process(); + if (kbd->type <= 1) + pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0); + speaker_update(); - if ((kbd->type <= 1) && !(kbd->pb & 0x08)) - speaker_gated = speaker_enable = 1; - else { - speaker_gated = val & 1; - speaker_enable = val & 2; - } + + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) was_speaker_enable = 1; pit_ctr_set_gate(&pit->counters[2], val & 1); @@ -622,8 +624,12 @@ kbd_read(uint16_t port, void *priv) /* This is needed to avoid error 131 (cassette error). This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */ - if (kbd->type <= 1) - ret |= (ppispeakon ? 0x10 : 0); + if (kbd->type <= 1) { + if (cassette == NULL) + ret |= (ppispeakon ? 0x10 : 0); + else + ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0); + } if (kbd->type == 5) ret |= (tandy1k_eeprom_read() ? 0x10 : 0); diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index e7484aebf..c4439c7b4 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -512,7 +512,7 @@ fdd_load(int drive, char *fn) drive_empty[drive] = 1; fdd_set_head(drive, 0); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - ui_sb_update_icon_state(drive, 1); + ui_sb_update_icon_state(SB_FLOPPY | drive, 1); } @@ -538,7 +538,7 @@ fdd_close(int drive) drives[drive].byteperiod = NULL; drives[drive].stop = NULL; d86f_destroy(drive); - ui_sb_update_icon_state(drive, 1); + ui_sb_update_icon_state(SB_FLOPPY | drive, 1); } diff --git a/src/include/86box/cassette.h b/src/include/86box/cassette.h new file mode 100644 index 000000000..6f8f92693 --- /dev/null +++ b/src/include/86box/cassette.h @@ -0,0 +1,173 @@ +/***************************************************************************** + * pce * + *****************************************************************************/ + +/***************************************************************************** + * File name: src/ibmpc/cassette.h * + * Created: 2008-11-25 by Hampa Hug * + * Copyright: (C) 2008-2019 Hampa Hug * + *****************************************************************************/ + +/***************************************************************************** + * This program is free software. You can redistribute it and / or modify it * + * under the terms of the GNU General Public License version 2 as published * + * by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY, without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * + * Public License for more details. * + *****************************************************************************/ + + +#ifndef PCE_IBMPC_CASSETTE_H +#define PCE_IBMPC_CASSETTE_H 1 + + +#include + + +typedef struct { + char save; + char pcm; + + unsigned char motor; + + unsigned long position; + + unsigned long position_save; + unsigned long position_load; + + unsigned char data_out; + unsigned char data_inp; + + int pcm_out_vol; + int pcm_out_val; + + unsigned cas_out_cnt; + unsigned char cas_out_buf; + + unsigned cas_inp_cnt; + unsigned char cas_inp_buf; + unsigned char cas_inp_bit; + + int pcm_inp_fir[3]; + + unsigned long clk; + + unsigned long clk_pcm; + + unsigned long clk_out; + unsigned long clk_inp; + + unsigned long srate; + + char close; + char *fname; + FILE *fp; + pc_timer_t timer; +} pc_cassette_t; + + +void pc_cas_init (pc_cassette_t *cas); +void pc_cas_free (pc_cassette_t *cas); + +pc_cassette_t *pc_cas_new (void); +void pc_cas_del (pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the cassette file + * @return True on error, false otherwise + *****************************************************************************/ +int pc_cas_set_fname (pc_cassette_t *cas, const char *fname); + +/*!*************************************************************************** + * @short Get the cassette mode + * @return True if in save mode, false if in load mode + *****************************************************************************/ +int pc_cas_get_mode (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the cassette mode + * @param save If true set save mode, otherwise set load mode + *****************************************************************************/ +void pc_cas_set_mode (pc_cassette_t *cas, int save); + +/*!*************************************************************************** + * @short Get the cassette pcm mode + * @return True if in pcm mode, false if in binary mode + *****************************************************************************/ +int pc_cas_get_pcm (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the cassette pcm mode + * @param pcm If true set pcm mode, otherwise set binary mode + *****************************************************************************/ +void pc_cas_set_pcm (pc_cassette_t *cas, int pcm); + +/*!*************************************************************************** + * @short Get the pcm sample rate + * @return The sample rate in Hz + *****************************************************************************/ +unsigned long pc_cas_get_srate (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the pcm sample rate + * @param pcm The sample rate in Hz + *****************************************************************************/ +void pc_cas_set_srate (pc_cassette_t *cas, unsigned long srate); + +/*!*************************************************************************** + * @short Rewind the cassette + *****************************************************************************/ +void pc_cas_rewind (pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Fast forward to the end of the cassette + *****************************************************************************/ +void pc_cas_append (pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Get the current load/save position + *****************************************************************************/ +unsigned long pc_cas_get_position (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the current load/save position + *****************************************************************************/ +int pc_cas_set_position (pc_cassette_t *cas, unsigned long pos); + +/*!*************************************************************************** + * @short Set the cassette motor status + *****************************************************************************/ +void pc_cas_set_motor (pc_cassette_t *cas, unsigned char val); + +/*!*************************************************************************** + * @short Get the current input from the cassette + *****************************************************************************/ +unsigned char pc_cas_get_inp (const pc_cassette_t *cas); + +/*!*************************************************************************** + * @short Set the current output to the cassette + *****************************************************************************/ +void pc_cas_set_out (pc_cassette_t *cas, unsigned char val); + +void pc_cas_print_state (const pc_cassette_t *cas); + +void pc_cas_clock (pc_cassette_t *cas, unsigned long cnt); +void pc_cas_advance (pc_cassette_t *cas); + + +extern pc_cassette_t * cassette; + +extern char cassette_fname[512]; +extern char * cassette_mode; +extern unsigned long cassette_pos, cassette_srate; +extern int cassette_enable; +extern int cassette_append, cassette_pcm; +extern int cassette_ui_writeprot; + +extern const device_t cassette_device; + + +#endif diff --git a/src/include/86box/language.h b/src/include/86box/language.h index b791f27c8..ec4b8d721 100644 --- a/src/include/86box/language.h +++ b/src/include/86box/language.h @@ -121,6 +121,8 @@ #define IDS_2145 2145 // "You are loading an unsupported..." #define IDS_2146 2146 // "CPU type filtering based on..." #define IDS_2147 2147 // "Continue" +#define IDS_2148 2148 // "Continue" +#define IDS_2149 2149 // "Continue" #define IDS_4096 4096 // "Hard disk (%s)" #define IDS_4097 4097 // "%01i:%01i" @@ -229,7 +231,7 @@ #define IDS_LANG_ENUS IDS_7168 -#define STR_NUM_2048 100 +#define STR_NUM_2048 102 #define STR_NUM_3072 11 #define STR_NUM_4096 40 #define STR_NUM_4352 6 diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 14f6db2db..9f16e149f 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -131,6 +131,8 @@ extern void plat_power_off(void); /* Platform-specific device support. */ +extern void cassette_mount(char *fn, uint8_t wp); +extern void cassette_eject(void); extern void floppy_mount(uint8_t id, char *fn, uint8_t wp); extern void floppy_eject(uint8_t id); extern void cdrom_mount(uint8_t id, char *fn); diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index 0cd8d1423..03b797fea 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -195,6 +195,7 @@ #define IDC_CONFIGURE_SCSI_2 1093 #define IDC_CONFIGURE_SCSI_3 1094 #define IDC_CONFIGURE_SCSI_4 1095 +#define IDC_CHECK_CASSETTE 1096 #define IDC_HARD_DISKS 1100 /* hard disks config */ #define IDC_LIST_HARD_DISKS 1101 @@ -379,29 +380,36 @@ * and 5 bits for Removable Disks (5 bits for ID), so we use an * 8bit (256 entries) space for these devices. */ -#define IDM_FLOPPY_IMAGE_NEW 0x1200 -#define IDM_FLOPPY_IMAGE_EXISTING 0x1300 -#define IDM_FLOPPY_IMAGE_EXISTING_WP 0x1400 -#define IDM_FLOPPY_EXPORT_TO_86F 0x1500 -#define IDM_FLOPPY_EJECT 0x1600 +#define IDM_CASSETTE_IMAGE_NEW 0x1200 +#define IDM_CASSETTE_IMAGE_EXISTING 0x1300 +#define IDM_CASSETTE_IMAGE_EXISTING_WP 0x1400 +#define IDM_CASSETTE_REWIND 0x1500 +#define IDM_CASSETTE_FAST_FORWARD 0x1600 +#define IDM_CASSETTE_EJECT 0x1700 -#define IDM_CDROM_MUTE 0x2200 -#define IDM_CDROM_EMPTY 0x2300 -#define IDM_CDROM_RELOAD 0x2400 -#define IDM_CDROM_IMAGE 0x2500 -#define IDM_CDROM_HOST_DRIVE 0x2600 +#define IDM_FLOPPY_IMAGE_NEW 0x2200 +#define IDM_FLOPPY_IMAGE_EXISTING 0x2300 +#define IDM_FLOPPY_IMAGE_EXISTING_WP 0x2400 +#define IDM_FLOPPY_EXPORT_TO_86F 0x2500 +#define IDM_FLOPPY_EJECT 0x2600 -#define IDM_ZIP_IMAGE_NEW 0x3200 -#define IDM_ZIP_IMAGE_EXISTING 0x3300 -#define IDM_ZIP_IMAGE_EXISTING_WP 0x3400 -#define IDM_ZIP_EJECT 0x3500 -#define IDM_ZIP_RELOAD 0x3600 +#define IDM_CDROM_MUTE 0x3200 +#define IDM_CDROM_EMPTY 0x3300 +#define IDM_CDROM_RELOAD 0x3400 +#define IDM_CDROM_IMAGE 0x3500 +#define IDM_CDROM_HOST_DRIVE 0x3600 -#define IDM_MO_IMAGE_NEW 0x4200 -#define IDM_MO_IMAGE_EXISTING 0x4300 -#define IDM_MO_IMAGE_EXISTING_WP 0x4400 -#define IDM_MO_EJECT 0x4500 -#define IDM_MO_RELOAD 0x4600 +#define IDM_ZIP_IMAGE_NEW 0x4200 +#define IDM_ZIP_IMAGE_EXISTING 0x4300 +#define IDM_ZIP_IMAGE_EXISTING_WP 0x4400 +#define IDM_ZIP_EJECT 0x4500 +#define IDM_ZIP_RELOAD 0x4600 + +#define IDM_MO_IMAGE_NEW 0x5200 +#define IDM_MO_IMAGE_EXISTING 0x5300 +#define IDM_MO_IMAGE_EXISTING_WP 0x5400 +#define IDM_MO_EJECT 0x5500 +#define IDM_MO_RELOAD 0x5600 /* Next default values for new objects */ diff --git a/src/include/86box/ui.h b/src/include/86box/ui.h index 15950c6e6..09bd29b24 100644 --- a/src/include/86box/ui.h +++ b/src/include/86box/ui.h @@ -50,14 +50,15 @@ extern void ui_check_menu_item(int id, int checked); /* Status Bar functions. */ #define SB_ICON_WIDTH 24 -#define SB_FLOPPY 0x00 -#define SB_CDROM 0x10 -#define SB_ZIP 0x20 -#define SB_MO 0x30 -#define SB_HDD 0x40 -#define SB_NETWORK 0x50 -#define SB_SOUND 0x60 -#define SB_TEXT 0x70 +#define SB_CASSETTE 0x00 +#define SB_FLOPPY 0x10 +#define SB_CDROM 0x20 +#define SB_ZIP 0x30 +#define SB_MO 0x40 +#define SB_HDD 0x50 +#define SB_NETWORK 0x60 +#define SB_SOUND 0x70 +#define SB_TEXT 0x80 extern wchar_t *ui_window_title(wchar_t *s); extern void ui_status_update(void); diff --git a/src/include/86box/win.h b/src/include/86box/win.h index 087387a36..affbe2cc4 100644 --- a/src/include/86box/win.h +++ b/src/include/86box/win.h @@ -58,6 +58,7 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); #define SDL_CLASS_NAME L"86BoxSDLWnd" #define SDL_SUB_CLASS_NAME L"86BoxSDLSubWnd" +#define CASSETTE_SUBMENU_NAME L"CassetteSubmenu" #define FLOPPY_SUBMENU_NAME L"FloppySubmenu" #define CDROM_SUBMENU_NAME L"CdromSubmenu" #define ZIP_SUBMENU_NAME L"ZIPSubmenu" @@ -220,10 +221,12 @@ extern wchar_t *BrowseFolder(wchar_t *saved_path, wchar_t *title); extern void media_menu_init(); extern void media_menu_reset(); extern int media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +extern HMENU media_menu_get_cassette(void); extern HMENU media_menu_get_floppy(int id); extern HMENU media_menu_get_cdrom(int id); extern HMENU media_menu_get_zip(int id); extern HMENU media_menu_get_mo(int id); +extern void media_menu_update_cassette(void); extern void media_menu_update_floppy(int id); extern void media_menu_update_cdrom(int id); extern void media_menu_update_zip(int id); diff --git a/src/machine/machine.c b/src/machine/machine.c index 6c453812c..565e9f038 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -27,6 +27,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> #include <86box/dma.h> #include <86box/pic.h> #include <86box/pit.h> @@ -90,6 +91,9 @@ machine_init_ex(int m) smbase = is_am486dxl ? 0x00060000 : 0x00030000; lpt_init(); + + if (cassette_enable) + device_add(&cassette_device); } /* All good, boot the machine! */ diff --git a/src/pit.c b/src/pit.c index 9db4c45dd..dd4613d76 100644 --- a/src/pit.c +++ b/src/pit.c @@ -27,6 +27,7 @@ #include "cpu.h" #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> #include <86box/dma.h> #include <86box/io.h> #include <86box/nmi.h> @@ -734,6 +735,9 @@ pit_speaker_timer(int new_out, int old_out) { int l; + if (cassette != NULL) + pc_cas_set_out(cassette, new_out); + speaker_update(); l = pit->counters[2].l ? pit->counters[2].l : 0x10000; diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 658b7868b..aefca42e9 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -187,6 +187,22 @@ BEGIN MENUITEM SEPARATOR END +CassetteSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&New image...", IDM_CASSETTE_IMAGE_NEW + MENUITEM SEPARATOR + MENUITEM "&Existing image...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM SEPARATOR + MENUITEM "&Rewind to the beginning", IDM_CASSETTE_REWIND + MENUITEM "&Fast forward to the end", IDM_CASSETTE_FAST_FORWARD + MENUITEM SEPARATOR + MENUITEM "E&ject", IDM_CASSETTE_EJECT + END +END + FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" @@ -549,7 +565,7 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,7,118,94,10 END -DLG_CFG_STORAGE DIALOG DISCARDABLE 107, 0, 267, 211 +DLG_CFG_STORAGE DIALOG DISCARDABLE 107, 0, 267, 203 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -588,6 +604,9 @@ BEGIN COMBOBOX IDC_COMBO_SCSI_4,73,157,137,120, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI_4,213,157,38,12 + + CONTROL "Cassette",IDC_CHECK_CASSETTE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,185,94,10 END DLG_CFG_HARD_DISKS DIALOG DISCARDABLE 107, 0, 267, 154 @@ -1121,6 +1140,8 @@ BEGIN IDS_2145 "You are loading an unsupported configuration" IDS_2146 "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." IDS_2147 "Continue" + IDS_2148 "Cassette: %s" + IDS_2149 "Cassette images (*.CAS;*.PCM)\0*.CAS;*.PCM\0All files (*.*)\0*.*\0" END STRINGTABLE DISCARDABLE diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 3fa401f1e..a7fa1286d 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -636,7 +636,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ m_at_misc.o -DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ +DEVOBJ := bugger.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ vpc2007.o clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_piix4.o \ diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index b6fea8e34..f68e81fbb 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -27,8 +27,11 @@ #include #include #include +#include <86box/86box.h> #include <86box/config.h> #include <86box/timer.h> +#include <86box/device.h> +#include <86box/cassette.h> #include <86box/fdd.h> #include <86box/hdd.h> #include <86box/scsi_device.h> @@ -41,6 +44,33 @@ #include <86box/win.h> +void +cassette_mount(char *fn, uint8_t wp) +{ + pc_cas_set_fname(cassette, NULL); + memset(cassette_fname, 0, sizeof(cassette_fname)); + cassette_ui_writeprot = wp; + pc_cas_set_fname(cassette, fn); + if (fn != NULL) + memcpy(cassette_fname, fn, MIN(511, strlen(fn))); + ui_sb_update_icon_state(SB_CASSETTE, (fn == NULL) ? 1 : 0); + media_menu_update_cassette(); + ui_sb_update_tip(SB_CASSETTE); + config_save(); +} + + +void +cassette_eject(void) +{ + pc_cas_set_fname(cassette, NULL); + ui_sb_update_icon_state(SB_CASSETTE, 1); + media_menu_update_cassette(); + ui_sb_update_tip(SB_CASSETTE); + config_save(); +} + + void floppy_mount(uint8_t id, char *fn, uint8_t wp) { @@ -53,6 +83,7 @@ floppy_mount(uint8_t id, char *fn, uint8_t wp) config_save(); } + void floppy_eject(uint8_t id) { diff --git a/src/win/win_media_menu.c b/src/win/win_media_menu.c index 1d4e16327..b01cf376a 100644 --- a/src/win/win_media_menu.c +++ b/src/win/win_media_menu.c @@ -8,6 +8,7 @@ #include <86box/config.h> #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> #include <86box/fdd.h> #include <86box/fdd_86f.h> #include <86box/hdc.h> @@ -22,18 +23,22 @@ #include <86box/zip.h> #include <86box/win.h> -#define MACHINE_HAS_IDE (machines[machine].flags & MACHINE_IDE_QUAD) +#define MACHINE_HAS_IDE (machines[machine].flags & MACHINE_IDE_QUAD) #define MACHINE_HAS_SCSI (machines[machine].flags & MACHINE_SCSI_DUAL) -#define FDD_FIRST 0 -#define CDROM_FIRST FDD_FIRST + FDD_NUM -#define ZIP_FIRST CDROM_FIRST + CDROM_NUM -#define MO_FIRST ZIP_FIRST + ZIP_NUM +#define CASSETTE_FIRST 0 +#define FDD_FIRST 1 +#define CDROM_FIRST FDD_FIRST + FDD_NUM +#define ZIP_FIRST CDROM_FIRST + CDROM_NUM +#define MO_FIRST ZIP_FIRST + ZIP_NUM + static HMENU media_menu, stbar_menu; static HMENU menus[FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; + static char index_map[255]; + static void media_menu_set_ids(HMENU hMenu, int id) { @@ -51,6 +56,7 @@ media_menu_set_ids(HMENU hMenu, int id) } } + /* Loads the submenu from resource by name */ static HMENU media_menu_load_resource(wchar_t *lpName) @@ -67,6 +73,28 @@ media_menu_load_resource(wchar_t *lpName) return actual; } + +static void +media_menu_set_name_cassette(void) +{ + wchar_t name[512], fn[512]; + MENUITEMINFO mii = { 0 }; + + if (strlen(cassette_fname) == 0) + _swprintf(name, plat_get_string(IDS_2148), plat_get_string(IDS_2057)); + else { + mbstoc16s(fn, cassette_fname, sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2148), fn); + } + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; + mii.dwTypeData = name; + + SetMenuItemInfo(media_menu, (UINT_PTR)menus[CASSETTE_FIRST], FALSE, &mii); +} + + static void media_menu_set_name_floppy(int drive) { @@ -91,6 +119,7 @@ media_menu_set_name_floppy(int drive) SetMenuItemInfo(media_menu, (UINT_PTR)menus[FDD_FIRST + drive], FALSE, &mii); } + static void media_menu_set_name_cdrom(int drive) { @@ -121,6 +150,7 @@ media_menu_set_name_cdrom(int drive) SetMenuItemInfo(media_menu, (UINT_PTR)menus[CDROM_FIRST + drive], FALSE, &mii); } + static void media_menu_set_name_zip(int drive) { @@ -150,6 +180,7 @@ media_menu_set_name_zip(int drive) SetMenuItemInfo(media_menu, (UINT_PTR)menus[ZIP_FIRST + drive], FALSE, &mii); } + static void media_menu_set_name_mo(int drive) { @@ -177,6 +208,26 @@ media_menu_set_name_mo(int drive) SetMenuItemInfo(media_menu, (UINT_PTR)menus[MO_FIRST + drive], FALSE, &mii); } + +void +media_menu_update_cassette(void) +{ + int i = CASSETTE_FIRST; + + if (strlen(cassette_fname) == 0) { + EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_GRAYED); + } else { + EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_ENABLED); + } + + media_menu_set_name_cassette(); +} + + void media_menu_update_floppy(int id) { @@ -193,6 +244,7 @@ media_menu_update_floppy(int id) media_menu_set_name_floppy(id); } + void media_menu_update_cdrom(int id) { @@ -220,6 +272,7 @@ media_menu_update_cdrom(int id) media_menu_set_name_cdrom(id); } + void media_menu_update_zip(int id) { @@ -238,6 +291,7 @@ media_menu_update_zip(int id) media_menu_set_name_zip(id); } + void media_menu_update_mo(int id) { @@ -256,6 +310,7 @@ media_menu_update_mo(int id) media_menu_set_name_mo(id); } + static void media_menu_load_submenus() { @@ -263,6 +318,9 @@ media_menu_load_submenus() int curr = 0; + menus[curr] = media_menu_load_resource(CASSETTE_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], 0); + for(int i = 0; i < FDD_NUM; i++) { menus[curr] = media_menu_load_resource(FLOPPY_SUBMENU_NAME); media_menu_set_ids(menus[curr++], i); @@ -284,12 +342,14 @@ media_menu_load_submenus() } } + static inline int is_valid_fdd(int i) { return fdd_get_type(i) != 0; } + static inline int is_valid_cdrom(int i) { @@ -302,6 +362,7 @@ is_valid_cdrom(int i) return cdrom[i].bus_type != 0; } + static inline int is_valid_zip(int i) { @@ -314,6 +375,7 @@ is_valid_zip(int i) return zip_drives[i].bus_type != 0; } + static inline int is_valid_mo(int i) { @@ -326,6 +388,7 @@ is_valid_mo(int i) return mo_drives[i].bus_type != 0; } + void media_menu_reset() { @@ -338,6 +401,12 @@ media_menu_reset() /* Add new ones. */ int curr = 0; + if(cassette_enable) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); + media_menu_update_cassette(); + } + curr++; + for(int i = 0; i < FDD_NUM; i++) { if(is_valid_fdd(i)) { AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); @@ -371,6 +440,7 @@ media_menu_reset() } } + /* Initializes the Media menu in the main menu bar. */ static void media_menu_main_init() @@ -394,6 +464,7 @@ media_menu_main_init() free(lpMenuName); } + void media_menu_init() { @@ -411,6 +482,7 @@ media_menu_init() media_menu_reset(); } + int media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -419,6 +491,40 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) id = LOWORD(wParam) & 0x00ff; switch (LOWORD(wParam) & 0xff00) { + case IDM_CASSETTE_IMAGE_NEW: + ret = file_dlg_st(hwnd, IDS_2149, "", NULL, 1); + if (! ret) { + if (strlen(openfilestring) == 0) + cassette_mount(NULL, wp); + else + cassette_mount(openfilestring, wp); + } + break; + + case IDM_CASSETTE_REWIND: + pc_cas_rewind(cassette); + break; + case IDM_CASSETTE_FAST_FORWARD: + pc_cas_append(cassette); + break; + + case IDM_CASSETTE_IMAGE_EXISTING_WP: + wp = 1; + /* FALLTHROUGH */ + case IDM_CASSETTE_IMAGE_EXISTING: + ret = file_dlg_st(hwnd, IDS_2149, cassette_fname, NULL, 0); + if (! ret) { + if (strlen(openfilestring) == 0) + cassette_mount(NULL, wp); + else + cassette_mount(openfilestring, wp); + } + break; + + case IDM_CASSETTE_EJECT: + cassette_eject(); + break; + case IDM_FLOPPY_IMAGE_NEW: NewFloppyDialogCreate(hwnd, id, 0); break; @@ -428,9 +534,8 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* FALLTHROUGH */ case IDM_FLOPPY_IMAGE_EXISTING: ret = file_dlg_st(hwnd, IDS_2109, floppyfns[id], NULL, 0); - if (! ret) { + if (! ret) floppy_mount(id, openfilestring, wp); - } break; case IDM_FLOPPY_EJECT: @@ -518,24 +623,35 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return(1); } + +HMENU +media_menu_get_cassette(void) +{ + return menus[CASSETTE_FIRST]; +} + + HMENU media_menu_get_floppy(int id) { return menus[FDD_FIRST + id]; } + HMENU media_menu_get_cdrom(int id) { return menus[CDROM_FIRST + id]; } + HMENU media_menu_get_zip(int id) { return menus[ZIP_FIRST + id]; } + HMENU media_menu_get_mo(int id) { diff --git a/src/win/win_settings.c b/src/win/win_settings.c index f0a00c6c5..edba0f0b1 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -38,6 +38,7 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/timer.h> +#include <86box/cassette.h> #include <86box/nvr.h> #include <86box/machine.h> #include <86box/gameport.h> @@ -103,7 +104,7 @@ static int temp_lpt_devices[3]; static int temp_serial[4], temp_lpt[3]; /* Other peripherals category */ -static int temp_fdc_card, temp_hdc, temp_ide_ter, temp_ide_qua; +static int temp_fdc_card, temp_hdc, temp_ide_ter, temp_ide_qua, temp_cassette; static int temp_scsi_card[SCSI_BUS_MAX]; static int temp_bugger; static int temp_postcard; @@ -369,23 +370,17 @@ win_settings_init(void) for (i = 0; i < 4; i++) temp_serial[i] = serial_enabled[i]; - /* Other peripherals category */ + /* Storage devices category */ for (i = 0; i < SCSI_BUS_MAX; i++) temp_scsi_card[i] = scsi_card_current[i]; temp_fdc_card = fdc_type; temp_hdc = hdc_current; temp_ide_ter = ide_ter_enabled; temp_ide_qua = ide_qua_enabled; - temp_bugger = bugger_enabled; - temp_postcard = postcard_enabled; - temp_isartc = isartc_type; - - /* ISA memory boards. */ - for (i = 0; i < ISAMEM_MAX; i++) - temp_isamem[i] = isamem_type[i]; + temp_cassette = cassette_enable; mfm_tracking = xta_tracking = esdi_tracking = ide_tracking = 0; - for (i = 0; i < 2; i++) + for (i = 0; i < 8; i++) scsi_tracking[i] = 0; /* Hard disks category */ @@ -433,6 +428,15 @@ win_settings_init(void) scsi_tracking[mo_drives[i].scsi_device_id >> 3] |= (1 << ((mo_drives[i].scsi_device_id & 0x07) << 3)); } + /* Other peripherals category */ + temp_bugger = bugger_enabled; + temp_postcard = postcard_enabled; + temp_isartc = isartc_type; + + /* ISA memory boards. */ + for (i = 0; i < ISAMEM_MAX; i++) + temp_isamem[i] = isamem_type[i]; + temp_deviceconfig = 0; } @@ -486,20 +490,14 @@ win_settings_changed(void) for (j = 0; j < 4; j++) i = i || (temp_serial[j] != serial_enabled[j]); - /* Peripherals category */ + /* Storage devices category */ for (j = 0; j < SCSI_BUS_MAX; j++) i = i || (temp_scsi_card[j] != scsi_card_current[j]); i = i || (fdc_type != temp_fdc_card); i = i || (hdc_current != temp_hdc); i = i || (temp_ide_ter != ide_ter_enabled); i = i || (temp_ide_qua != ide_qua_enabled); - i = i || (temp_bugger != bugger_enabled); - i = i || (temp_postcard != postcard_enabled); - i = i || (temp_isartc != isartc_type); - - /* ISA memory boards. */ - for (j = 0; j < ISAMEM_MAX; j++) - i = i || (temp_isamem[j] != isamem_type[j]); + i = i || (temp_cassette != cassette_enable); /* Hard disks category */ i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); @@ -516,6 +514,15 @@ win_settings_changed(void) i = i || memcmp(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); i = i || memcmp(mo_drives, temp_mo_drives, MO_NUM * sizeof(mo_drive_t)); + /* Other peripherals category */ + i = i || (temp_bugger != bugger_enabled); + i = i || (temp_postcard != postcard_enabled); + i = i || (temp_isartc != isartc_type); + + /* ISA memory boards. */ + for (j = 0; j < ISAMEM_MAX; j++) + i = i || (temp_isamem[j] != isamem_type[j]); + i = i || !!temp_deviceconfig; return i; @@ -574,20 +581,14 @@ win_settings_save(void) for (i = 0; i < 4; i++) serial_enabled[i] = temp_serial[i]; - /* Peripherals category */ + /* Storage devices category */ for (i = 0; i < SCSI_BUS_MAX; i++) scsi_card_current[i] = temp_scsi_card[i]; hdc_current = temp_hdc; fdc_type = temp_fdc_card; ide_ter_enabled = temp_ide_ter; ide_qua_enabled = temp_ide_qua; - bugger_enabled = temp_bugger; - postcard_enabled = temp_postcard; - isartc_type = temp_isartc; - - /* ISA memory boards. */ - for (i = 0; i < ISAMEM_MAX; i++) - isamem_type[i] = temp_isamem[i]; + cassette_enable = temp_cassette; /* Hard disks category */ memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); @@ -624,6 +625,15 @@ win_settings_save(void) mo_drives[i].priv = NULL; } + /* Other peripherals category */ + bugger_enabled = temp_bugger; + postcard_enabled = temp_postcard; + isartc_type = temp_isartc; + + /* ISA memory boards. */ + for (i = 0; i < ISAMEM_MAX; i++) + isamem_type[i] = temp_isamem[i]; + /* Mark configuration as changed. */ config_changed = 2; @@ -1656,6 +1666,7 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) settings_enable_window(hdlg, IDC_BUTTON_IDE_QUA, is_at && temp_ide_qua); settings_set_check(hdlg, IDC_CHECK_IDE_TER, temp_ide_ter); settings_set_check(hdlg, IDC_CHECK_IDE_QUA, temp_ide_qua); + settings_set_check(hdlg, IDC_CHECK_CASSETTE, temp_cassette); free(stransi); free(lptsTemp); @@ -1723,6 +1734,7 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; temp_ide_ter = settings_get_check(hdlg, IDC_CHECK_IDE_TER); temp_ide_qua = settings_get_check(hdlg, IDC_CHECK_IDE_QUA); + temp_cassette = settings_get_check(hdlg, IDC_CHECK_CASSETTE); default: return FALSE; diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index 7dc1d0785..893c9c63d 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -34,6 +34,7 @@ #include <86box/device.h> #include <86box/machine.h> #include <86box/timer.h> +#include <86box/cassette.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/fdd.h> @@ -177,6 +178,28 @@ ui_sb_update_icon_state(int tag, int state) } +static void +StatusBarCreateCassetteTip(int part) +{ + WCHAR tempTip[512]; + WCHAR fn[512]; + + if (strlen(cassette_fname) == 0) + _swprintf(tempTip, plat_get_string(IDS_2148), plat_get_string(IDS_2057)); + else { + mbstoc16s(fn, cassette_fname, sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2148), fn); + } + + if (sbTips[part] != NULL) { + free(sbTips[part]); + sbTips[part] = NULL; + } + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + static void StatusBarCreateFloppyTip(int part) { @@ -364,6 +387,10 @@ ui_sb_update_tip(int meaning) if (part != 0xff) { switch(meaning & 0xf0) { + case SB_CASSETTE: + StatusBarCreateCassetteTip(part); + break; + case SB_FLOPPY: StatusBarCreateFloppyTip(part); break; @@ -492,6 +519,8 @@ ui_sb_update_panes(void) memset(sb_map, 0xff, sizeof(sb_map)); sb_parts = 0; + if (cassette_enable) + sb_parts++; for (i=0; i Date: Tue, 27 Jul 2021 06:17:54 +0200 Subject: [PATCH 06/16] Added cassette support to the IBM PCjr. --- src/machine/m_pcjr.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 5b468d2f6..7a2fda607 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -29,6 +29,8 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/timer.h> +#include <86box/device.h> +#include <86box/cassette.h> #include <86box/io.h> #include <86box/nmi.h> #include <86box/pic.h> @@ -614,6 +616,10 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0x61: pcjr->pb = val; + timer_process(); + + pc_cas_set_motor(cassette, (pcjr->pb & 0x08) == 0); + speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; @@ -657,10 +663,14 @@ kbd_read(uint16_t port, void *priv) case 0x61: ret = pcjr->pb; break; - + case 0x62: ret = (pcjr->latched ? 1 : 0); ret |= 0x02; /*Modem card not installed*/ + if ((pcjr->pb & 0x08) || (cassette == NULL)) + ret |= (ppispeakon ? 0x10 : 0); + else + ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0); ret |= (ppispeakon ? 0x10 : 0); ret |= (ppispeakon ? 0x20 : 0); ret |= (pcjr->data ? 0x40: 0); From 24a6d5051c512ebc39626ebb4ad94004e29683b7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jul 2021 06:20:19 +0200 Subject: [PATCH 07/16] .WAV and .RAW are now recognized cassette file types, equivalent to .PCM, must be 44.1 kHz, 8-bit, mono. --- src/win/86Box.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/86Box.rc b/src/win/86Box.rc index aefca42e9..683a697eb 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -1141,7 +1141,7 @@ BEGIN IDS_2146 "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." IDS_2147 "Continue" IDS_2148 "Cassette: %s" - IDS_2149 "Cassette images (*.CAS;*.PCM)\0*.CAS;*.PCM\0All files (*.*)\0*.*\0" + IDS_2149 "Cassette images (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" END STRINGTABLE DISCARDABLE From 45b3e13450c1f2bb4069bc810c5eef52bb0dea53 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jul 2021 00:58:19 +0200 Subject: [PATCH 08/16] Cassette improvements and fixes. --- src/config.c | 28 ++++++++++++++++++++++++---- src/device/cassette.c | 8 +++++++- src/include/86box/cassette.h | 2 +- src/include/86box/resource.h | 8 +++++--- src/win/86Box.rc | 2 ++ src/win/win_media_menu.c | 21 ++++++++++++++++++++- 6 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/config.c b/src/config.c index a85be31ca..299bd8dd5 100644 --- a/src/config.c +++ b/src/config.c @@ -808,6 +808,10 @@ load_machine(void) /* Remove this after a while.. */ config_delete_var(cat, "nvr_path"); config_delete_var(cat, "enable_sync"); + + /* Set up the architecture flags. */ + AT = IS_AT(machine); + PCI = IS_ARCH(machine, MACHINE_BUS_PCI); } @@ -1095,17 +1099,22 @@ load_storage_controllers(void) ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0); ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0); - cassette_enable = !!config_get_int(cat, "cassette_enabled", 1); + cassette_enable = !!config_get_int(cat, "cassette_enabled", AT ? 0 : 1); p = config_get_string(cat, "cassette_file", ""); if (strlen(p) > 511) fatal("load_storage_controllers(): strlen(p) > 511\n"); else strncpy(cassette_fname, p, strlen(p) + 1); - cassette_mode = config_get_string(cat, "cassette_mode", "load"); + p = config_get_string(cat, "cassette_mode", ""); + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511\n"); + else + strncpy(cassette_mode, p, strlen(p) + 1); cassette_pos = config_get_int(cat, "cassette_position", 0); cassette_srate = config_get_int(cat, "cassette_srate", 44100); cassette_append = !!config_get_int(cat, "cassette_append", 0); cassette_pcm = config_get_int(cat, "cassette_pcm", 0); + cassette_ui_writeprot = !!config_get_int(cat, "cassette_writeprot", 0); } @@ -1937,6 +1946,11 @@ config_load(void) kbd_req_capture = 0; scale = 1; machine = machine_get_machine_from_internal_name("ibmpc"); + + /* Set up the architecture flags. */ + AT = IS_AT(machine); + PCI = IS_ARCH(machine, MACHINE_BUS_PCI); + fpu_type = fpu_get_type(cpu_f, cpu, "none"); gfxcard = video_get_video_from_internal_name("cga"); vid_api = plat_vidapi("default"); @@ -1967,13 +1981,14 @@ config_load(void) for (i = 0; i < ISAMEM_MAX; i++) isamem_type[i] = 0; - cassette_enable = 1; + cassette_enable = AT ? 0 : 1; memset(cassette_fname, 0x00, sizeof(cassette_fname)); - cassette_mode = "load"; + memcpy(cassette_mode, "load", strlen("load") + 1); cassette_pos = 0; cassette_srate = 44100; cassette_append = 0; cassette_pcm = 0; + cassette_ui_writeprot = 0; config_log("Config file not present or invalid!\n"); return; @@ -2527,6 +2542,11 @@ save_storage_controllers(void) config_delete_var(cat, "cassette_pcm"); else config_set_int(cat, "cassette_pcm", cassette_pcm); + + if (cassette_ui_writeprot == 0) + config_delete_var(cat, "cassette_writeprot"); + else + config_set_int(cat, "cassette_writeprot", cassette_ui_writeprot); } diff --git a/src/device/cassette.c b/src/device/cassette.c index a849a4fb1..b3cf65029 100644 --- a/src/device/cassette.c +++ b/src/device/cassette.c @@ -47,7 +47,7 @@ pc_cassette_t * cassette; char cassette_fname[512]; -char * cassette_mode; +char cassette_mode[512]; unsigned long cassette_pos, cassette_srate; int cassette_enable; int cassette_append, cassette_pcm; @@ -270,6 +270,12 @@ void pc_cas_set_mode (pc_cassette_t *cas, int save) cas->save = save; + memset(cassette_mode, 0x00, sizeof(cassette_mode)); + if (save) + memcpy(cassette_mode, "save", strlen("save") + 1); + else + memcpy(cassette_mode, "load", strlen("load") + 1); + if (cas->fp != NULL) { fflush (cas->fp); diff --git a/src/include/86box/cassette.h b/src/include/86box/cassette.h index 6f8f92693..a22b4c41f 100644 --- a/src/include/86box/cassette.h +++ b/src/include/86box/cassette.h @@ -161,7 +161,7 @@ void pc_cas_advance (pc_cassette_t *cas); extern pc_cassette_t * cassette; extern char cassette_fname[512]; -extern char * cassette_mode; +extern char cassette_mode[512]; extern unsigned long cassette_pos, cassette_srate; extern int cassette_enable; extern int cassette_append, cassette_pcm; diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index 03b797fea..50e35ab91 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -383,9 +383,11 @@ #define IDM_CASSETTE_IMAGE_NEW 0x1200 #define IDM_CASSETTE_IMAGE_EXISTING 0x1300 #define IDM_CASSETTE_IMAGE_EXISTING_WP 0x1400 -#define IDM_CASSETTE_REWIND 0x1500 -#define IDM_CASSETTE_FAST_FORWARD 0x1600 -#define IDM_CASSETTE_EJECT 0x1700 +#define IDM_CASSETTE_RECORD 0x1500 +#define IDM_CASSETTE_PLAY 0x1600 +#define IDM_CASSETTE_REWIND 0x1700 +#define IDM_CASSETTE_FAST_FORWARD 0x1800 +#define IDM_CASSETTE_EJECT 0x1900 #define IDM_FLOPPY_IMAGE_NEW 0x2200 #define IDM_FLOPPY_IMAGE_EXISTING 0x2300 diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 683a697eb..601afe4f9 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -196,6 +196,8 @@ BEGIN MENUITEM "&Existing image...", IDM_CASSETTE_IMAGE_EXISTING MENUITEM "Existing image (&Write-protected)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR + MENUITEM "&Record", IDM_CASSETTE_RECORD + MENUITEM "&Play", IDM_CASSETTE_PLAY MENUITEM "&Rewind to the beginning", IDM_CASSETTE_REWIND MENUITEM "&Fast forward to the end", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR diff --git a/src/win/win_media_menu.c b/src/win/win_media_menu.c index b01cf376a..14778e513 100644 --- a/src/win/win_media_menu.c +++ b/src/win/win_media_menu.c @@ -34,7 +34,7 @@ static HMENU media_menu, stbar_menu; -static HMENU menus[FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; +static HMENU menus[1 + FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; static char index_map[255]; @@ -216,10 +216,23 @@ media_menu_update_cassette(void) if (strlen(cassette_fname) == 0) { EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_GRAYED); + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_GRAYED); } else { EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_ENABLED); + if (strcmp(cassette_mode, "save") == 0) { + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); + } else { + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); + } EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_ENABLED); } @@ -501,6 +514,12 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; + case IDM_CASSETTE_RECORD: + pc_cas_set_mode(cassette, 1); + break; + case IDM_CASSETTE_PLAY: + pc_cas_set_mode(cassette, 0); + break; case IDM_CASSETTE_REWIND: pc_cas_rewind(cassette); break; From 6cad6cc7848f25f498a445313a4ddad209512455 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jul 2021 00:59:11 +0200 Subject: [PATCH 09/16] One thing I forgot. --- src/win/win_media_menu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/win/win_media_menu.c b/src/win/win_media_menu.c index 14778e513..c9901d890 100644 --- a/src/win/win_media_menu.c +++ b/src/win/win_media_menu.c @@ -516,9 +516,13 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_CASSETTE_RECORD: pc_cas_set_mode(cassette, 1); + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); break; case IDM_CASSETTE_PLAY: pc_cas_set_mode(cassette, 0); + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); break; case IDM_CASSETTE_REWIND: pc_cas_rewind(cassette); From ca6863540ca992662b796d958c730fa37740d7a7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jul 2021 03:29:14 +0200 Subject: [PATCH 10/16] Some fixes. --- src/win/win_media_menu.c | 8 ++++---- src/win/win_ui.c | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/win/win_media_menu.c b/src/win/win_media_menu.c index c9901d890..7b7aae788 100644 --- a/src/win/win_media_menu.c +++ b/src/win/win_media_menu.c @@ -516,13 +516,13 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_CASSETTE_RECORD: pc_cas_set_mode(cassette, 1); - CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); - CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); break; case IDM_CASSETTE_PLAY: pc_cas_set_mode(cassette, 0); - CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); break; case IDM_CASSETTE_REWIND: pc_cas_rewind(cassette); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 92e790dd3..237324d0b 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -176,6 +176,7 @@ video_toggle_option(HMENU h, int *val, int id) device_force_redraw(); } +#if defined(DEV_BRANCH) && defined(USE_OPENGL) /* Recursively finds and deletes target submenu */ static int delete_submenu(HMENU parent, HMENU target) @@ -203,6 +204,7 @@ delete_submenu(HMENU parent, HMENU target) return 0; } +#endif static void show_render_options_menu() From f52a68871375ccdd068d4eb6f9c026d060b63986 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jul 2021 05:12:35 +0200 Subject: [PATCH 11/16] Hercules fixes (and implemented undocumented behavior where with page 1 set in text mode, characters are read from page 1 and attributes from page 0), closes #1562. --- src/video/vid_hercules.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 94faf3fea..05f126110 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -138,21 +138,21 @@ hercules_out(uint16_t addr, uint8_t val, void *priv) case 0x03b8: old = dev->ctrl; - if (!(dev->ctrl2 & 0x01) && !(val & 0x02)) - val = (val & 0xfd) | (dev->ctrl & 0x02); - if (!(dev->ctrl2 & 0x02) && !(val & 0x80)) - val = (val & 0x7f) | (dev->ctrl & 0x80); + /* Prevent settings of bits if they are disabled in CTRL2. */ + if (!(dev->ctrl2 & 0x01) && (val & 0x02)) + val &= 0xfd; + if (!(dev->ctrl2 & 0x02) && (val & 0x80)) + val &= 0x7f; dev->ctrl = val; if (old ^ val) recalc_timings(dev); break; case 0x03bf: + old = dev->ctrl2; dev->ctrl2 = val; - if (val & 0x02) - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); + if (old ^ val) + recalc_timings(dev); break; default: @@ -250,6 +250,7 @@ hercules_poll(void *priv) hercules_t *dev = (hercules_t *)priv; uint8_t chr, attr; uint16_t ca, dat; + uint16_t pa; int oldsc, blink; int x, c, oldvc; int drawcursor; @@ -272,16 +273,13 @@ hercules_poll(void *priv) } dev->lastline = dev->displine; - // if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { - if (dev->ctrl & 2) { + if ((dev->ctrl & 0x02) && (dev->ctrl2 & 0x01)) { ca = (dev->sc & 3) * 0x2000; - // if ((dev->ctrl & 0x80) && (dev->ctrl2 & 2)) - if (dev->ctrl & 0x80) + if ((dev->ctrl & 0x80) && (dev->ctrl2 & 0x02)) ca += 0x8000; for (x = 0; x < dev->crtc[1]; x++) { if (dev->ctrl & 8) - // dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; else dat = 0; @@ -292,9 +290,12 @@ hercules_poll(void *priv) video_blend((x << 4) + c, dev->displine); } } else { + pa = ((dev->ctrl & 0x80) && (dev->ctrl2 & 0x02)) ? 0x8000 : 0x0000; for (x = 0; x < dev->crtc[1]; x++) { if (dev->ctrl & 8) { - chr = dev->vram[(dev->ma << 1) & 0xfff]; + /* Undocumented behavior: page 1 in text mode means characters are read + from page 1 and attributes from page 0. */ + chr = dev->vram[((dev->ma << 1) & 0xfff) + pa]; attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; } else chr = attr = 0; From 026bed4e531dd40d3c95fc2348217ef8051b08bc Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 29 Jul 2021 05:36:10 +0200 Subject: [PATCH 12/16] Fixed cassette ejecting and made write protection actually work, closes #1564. --- src/device/cassette.c | 8 +++++--- src/win/win_cdrom.c | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/device/cassette.c b/src/device/cassette.c index b3cf65029..c613b278b 100644 --- a/src/device/cassette.c +++ b/src/device/cassette.c @@ -418,7 +418,7 @@ int pc_cas_read_smp (pc_cassette_t *cas) static void pc_cas_write_bit (pc_cassette_t *cas, unsigned char val) { - if (val) { + if (val && !cassette_ui_writeprot) { cas->cas_out_buf |= (0x80 >> cas->cas_out_cnt); } @@ -426,7 +426,8 @@ void pc_cas_write_bit (pc_cassette_t *cas, unsigned char val) if (cas->cas_out_cnt >= 8) { if (cas->fp != NULL) { - fputc (cas->cas_out_buf, cas->fp); + if (!cassette_ui_writeprot) + fputc (cas->cas_out_buf, cas->fp); cas->position += 1; } @@ -447,7 +448,8 @@ void pc_cas_write_smp (pc_cassette_t *cas, int val) smp = (val > 127) ? 0x7f : val; } - fputc (smp, cas->fp); + if (!cassette_ui_writeprot) + fputc (smp, cas->fp); cas->position += 1; } diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index f68e81fbb..a743ad14a 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -64,6 +64,7 @@ void cassette_eject(void) { pc_cas_set_fname(cassette, NULL); + memset(cassette_fname, 0x00, sizeof(cassette_fname)); ui_sb_update_icon_state(SB_CASSETTE, 1); media_menu_update_cassette(); ui_sb_update_tip(SB_CASSETTE); From 14f6eaca391743ac8a5c7ec8f951a5a2dc8dfcc7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 29 Jul 2021 18:17:09 +0200 Subject: [PATCH 13/16] Added some cassette-related sanity checks, closes #1567. --- src/device/keyboard_xt.c | 2 +- src/machine/m_pcjr.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index f090ff202..d10c8bf1f 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -516,7 +516,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) timer_process(); - if (kbd->type <= 1) + if ((kbd->type <= 1) && (cassette != NULL)) pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0); speaker_update(); diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 7a2fda607..c51dbf03a 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -618,7 +618,8 @@ kbd_write(uint16_t port, uint8_t val, void *priv) timer_process(); - pc_cas_set_motor(cassette, (pcjr->pb & 0x08) == 0); + if (cassette != NULL) + pc_cas_set_motor(cassette, (pcjr->pb & 0x08) == 0); speaker_update(); speaker_gated = val & 1; From 949dea352417a37b098a1d85a553956572b02c32 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 29 Jul 2021 20:34:55 +0200 Subject: [PATCH 14/16] Added IBM PCjr cartridge support. --- src/config.c | 36 ++++++ src/device/CMakeLists.txt | 2 +- src/device/cartridge.c | 208 ++++++++++++++++++++++++++++++++++ src/floppy/fdd.c | 34 +++--- src/include/86box/cartridge.h | 40 +++++++ src/include/86box/language.h | 8 +- src/include/86box/machine.h | 1 + src/include/86box/plat.h | 2 + src/include/86box/resource.h | 43 +++---- src/include/86box/ui.h | 17 +-- src/include/86box/win.h | 3 + src/machine/machine.c | 3 + src/machine/machine_table.c | 2 +- src/win/86Box.rc | 14 +++ src/win/Makefile.mingw | 3 +- src/win/win_cdrom.c | 24 ++++ src/win/win_media_menu.c | 80 ++++++++++++- src/win/win_stbar.c | 57 +++++++++- 18 files changed, 523 insertions(+), 54 deletions(-) create mode 100644 src/device/cartridge.c create mode 100644 src/include/86box/cartridge.h diff --git a/src/config.c b/src/config.c index 299bd8dd5..08969bc3f 100644 --- a/src/config.c +++ b/src/config.c @@ -38,6 +38,7 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/nvr.h> #include <86box/config.h> #include <86box/isamem.h> @@ -1115,6 +1116,33 @@ load_storage_controllers(void) cassette_append = !!config_get_int(cat, "cassette_append", 0); cassette_pcm = config_get_int(cat, "cassette_pcm", 0); cassette_ui_writeprot = !!config_get_int(cat, "cassette_writeprot", 0); + + for (c=0; c<2; c++) { + sprintf(temp, "cartridge_%02i_fn", c + 1); + p = config_get_string(cat, temp, ""); + +#if 0 + /* + * NOTE: + * Temporary hack to remove the absolute + * path currently saved in most config + * files. We should remove this before + * finalizing this release! --FvK + */ + if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { + /* + * Yep, its absolute and prefixed + * with the EXE path. Just strip + * that off for now... + */ + wcsncpy(floppyfns[c], &wp[wcslen(usr_path)], sizeof_w(cart_fns[c])); + } else +#endif + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511\n"); + else + strncpy(cart_fns[c], p, strlen(p) + 1); + } } @@ -2547,6 +2575,14 @@ save_storage_controllers(void) config_delete_var(cat, "cassette_writeprot"); else config_set_int(cat, "cassette_writeprot", cassette_ui_writeprot); + + for (c=0; c<2; c++) { + sprintf(temp, "cartridge_%02i_fn", c+1); + if (strlen(cart_fns[c]) == 0) + config_delete_var(cat, temp); + else + config_set_string(cat, temp, cart_fns[c]); + } } diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index cecb241a5..7e78d752f 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -13,7 +13,7 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(dev OBJECT bugger.c cassette.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c +add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c postcard.c serial.c vpc2007.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c smbus_piix4.c keyboard.c keyboard_xt.c keyboard_at.c mouse.c mouse_bus.c diff --git a/src/device/cartridge.c b/src/device/cartridge.c new file mode 100644 index 000000000..894262aa3 --- /dev/null +++ b/src/device/cartridge.c @@ -0,0 +1,208 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the PCjr cartridge emulation. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/plat.h> +#include <86box/ui.h> +#include <86box/mem.h> +#include <86box/machine.h> +#include <86box/cartridge.h> + + +typedef struct +{ + uint8_t * buf; + uint32_t base; +} cart_t; + + +char cart_fns[2][512]; + + +static cart_t carts[2]; + +static mem_mapping_t cart_mappings[2]; + + +#ifdef ENABLE_CARTRIDGE_LOG +int cartridge_do_log = ENABLE_CARTRIDGE_LOG; + + +static void +cartridge_log(const char *fmt, ...) +{ + va_list ap; + + if (cartridge_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define cartridge_log(fmt, ...) +#endif + + +static uint8_t +cart_read(uint32_t addr, void *priv) +{ + cart_t *dev = (cart_t *) priv; + + return dev->buf[addr - dev->base]; +} + + +static void +cart_load_error(int drive, char *fn) +{ + cartridge_log("Cartridge: could not load '%s'\n",fn); + memset(cart_fns[drive], 0, sizeof(cart_fns[drive])); + ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1); +} + + +static void +cart_image_close(int drive) +{ + if (carts[drive].buf != NULL) { + free(carts[drive].buf); + carts[drive].buf = NULL; + } + + carts[drive].base = 0x00000000; + + mem_mapping_disable(&cart_mappings[drive]); +} + + +static void +cart_image_load(int drive, char *fn) +{ + FILE *f; + uint32_t size; + uint32_t base = 0x00000000; + + cart_image_close(drive); + + f = fopen(fn, "rb"); + if (fseek(f, 0, SEEK_END) == -1) + fatal("cart_image_load(): Error seeking to the end of the file\n"); + size = ftell(f); + if (size < 0x1200) { + cartridge_log("cart_image_load(): File size %i is too small\n", size); + cart_load_error(drive, fn); + return; + } + if (size & 0x00000fff) { + size -= 0x00000200; + fseek(f, 0x000001ce, SEEK_SET); + fread(&base, 1, 2, f); + base <<= 4; + fseek(f, 0x00000200, SEEK_SET); + carts[drive].buf = (uint8_t *) malloc(size); + memset(carts[drive].buf, 0x00, size); + fread(carts[drive].buf, 1, size, f); + fclose(f); + } else { + base = drive ? 0xe0000 : 0xd0000; + fseek(f, 0x00000000, SEEK_SET); + carts[drive].buf = (uint8_t *) malloc(size); + memset(carts[drive].buf, 0x00, size); + fread(carts[drive].buf, 1, size, f); + fclose(f); + } + + cartridge_log("cart_image_load(): %s at %08X-%08X\n", fn, base, base + size - 1); + carts[drive].base = base; + mem_mapping_set_addr(&cart_mappings[drive], base, size); + mem_mapping_set_exec(&cart_mappings[drive], carts[drive].buf); + mem_mapping_set_p(&cart_mappings[drive], &(carts[drive])); +} + + +static void +cart_load_common(int drive, char *fn, uint8_t hard_reset) +{ + FILE *f; + + cartridge_log("Cartridge: loading drive %d with '%s'\n", drive, fn); + + if (!fn) + return; + f = plat_fopen(fn, "rb"); + if (f) { + fclose(f); + strcpy(cart_fns[drive], fn); + cart_image_load(drive, cart_fns[drive]); + /* On the real PCjr, inserting a cartridge causes a reset + in order to boot from the cartridge. */ + if (!hard_reset) + resetx86(); + } else + cart_load_error(drive, fn); +} + + +void +cart_load(int drive, char *fn) +{ + cart_load_common(drive, fn, 0); +} + + +void +cart_close(int drive) +{ + cartridge_log("Cartridge: closing drive %d\n", drive); + + cart_image_close(drive); + cart_fns[drive][0] = 0; + ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1); +} + + +void +cart_reset(void) +{ + int i; + + cart_image_close(1); + cart_image_close(0); + + if (!(machines[machine].flags & MACHINE_CARTRIDGE)) + return; + + for (i = 0; i < 2; i++) { + mem_mapping_add(&cart_mappings[i], 0x000d0000, 0x00002000, + cart_read,NULL,NULL, + NULL,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, NULL); + mem_mapping_disable(&cart_mappings[i]); + } + + cart_load_common(0, cart_fns[0], 1); + cart_load_common(1, cart_fns[1], 1); +} diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index c4439c7b4..f8016793a 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -489,24 +489,24 @@ fdd_load(int drive, char *fn) if (!p) return; f = plat_fopen(fn, "rb"); - if (!f) - return; - if (fseek(f, -1, SEEK_END) == -1) - fatal("fdd_load(): Error seeking to the end of the file\n"); - size = ftell(f) + 1; - fclose(f); - while (loaders[c].ext) { - if (!strcasecmp(p, (char *) loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) { - driveloaders[drive] = c; - strcpy(floppyfns[drive], fn); - d86f_setup(drive); - loaders[c].load(drive, floppyfns[drive]); - drive_empty[drive] = 0; - fdd_forced_seek(drive, 0); - fdd_changed[drive] = 1; - return; + if (f) { + if (fseek(f, -1, SEEK_END) == -1) + fatal("fdd_load(): Error seeking to the end of the file\n"); + size = ftell(f) + 1; + fclose(f); + while (loaders[c].ext) { + if (!strcasecmp(p, (char *) loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) { + driveloaders[drive] = c; + strcpy(floppyfns[drive], fn); + d86f_setup(drive); + loaders[c].load(drive, floppyfns[drive]); + drive_empty[drive] = 0; + fdd_forced_seek(drive, 0); + fdd_changed[drive] = 1; + return; + } + c++; } - c++; } fdd_log("FDD: could not load '%s' %s\n",fn,p); drive_empty[drive] = 1; diff --git a/src/include/86box/cartridge.h b/src/include/86box/cartridge.h new file mode 100644 index 000000000..390604e79 --- /dev/null +++ b/src/include/86box/cartridge.h @@ -0,0 +1,40 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for the PCjr cartridge emulation. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#ifndef EMU_CARTRIDGE_H +# define EMU_CARTRIDGE_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern char cart_fns[2][512]; + + +extern void cart_load(int drive, char *fn); +extern void cart_close(int drive); + +extern void cart_reset(void); + + +#ifdef __cplusplus +} +#endif + + +#endif /*EMU_CARTRIDGE_H*/ diff --git a/src/include/86box/language.h b/src/include/86box/language.h index ec4b8d721..7e096fbf4 100644 --- a/src/include/86box/language.h +++ b/src/include/86box/language.h @@ -121,8 +121,10 @@ #define IDS_2145 2145 // "You are loading an unsupported..." #define IDS_2146 2146 // "CPU type filtering based on..." #define IDS_2147 2147 // "Continue" -#define IDS_2148 2148 // "Continue" -#define IDS_2149 2149 // "Continue" +#define IDS_2148 2148 // "Cassette: %s" +#define IDS_2149 2149 // "Cassette images (*.PCM;*.RAW;*..." +#define IDS_2150 2150 // "Cartridge %i: %ls" +#define IDS_2151 2151 // "Cartridge images (*.JRC)\0*.JRC\0..." #define IDS_4096 4096 // "Hard disk (%s)" #define IDS_4097 4097 // "%01i:%01i" @@ -231,7 +233,7 @@ #define IDS_LANG_ENUS IDS_7168 -#define STR_NUM_2048 102 +#define STR_NUM_2048 104 #define STR_NUM_3072 11 #define STR_NUM_4096 40 #define STR_NUM_4352 6 diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index f40745a05..2996133dc 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -82,6 +82,7 @@ #define MACHINE_IDE_QUAD 0x07800000 /* sys has int quad IDE/ATAPI - mark as dual + both ter and and qua IDE/ATAPI */ #define MACHINE_SCSI 0x08000000 /* sys has int single SCSI - mark as pri SCSI */ #define MACHINE_SCSI_DUAL 0x18000000 /* sys has int dual SCSI - mark as both pri and sec SCSI */ +#define MACHINE_CARTRIDGE 0x20000000 /* sys has two cartridge bays */ #define IS_ARCH(m, a) (machines[m].flags & (a)) ? 1 : 0; #define IS_AT(m) ((machines[m].flags & 0x00000FC8) && !(machines[m].flags & MACHINE_PC98)) ? 1 : 0; diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 9f16e149f..208d7d3bd 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -133,6 +133,8 @@ extern void plat_power_off(void); /* Platform-specific device support. */ extern void cassette_mount(char *fn, uint8_t wp); extern void cassette_eject(void); +extern void cartridge_mount(uint8_t id, char *fn, uint8_t wp); +extern void cartridge_eject(uint8_t id); extern void floppy_mount(uint8_t id, char *fn, uint8_t wp); extern void floppy_eject(uint8_t id); extern void cdrom_mount(uint8_t id, char *fn); diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index 50e35ab91..91291dfd8 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -389,29 +389,32 @@ #define IDM_CASSETTE_FAST_FORWARD 0x1800 #define IDM_CASSETTE_EJECT 0x1900 -#define IDM_FLOPPY_IMAGE_NEW 0x2200 -#define IDM_FLOPPY_IMAGE_EXISTING 0x2300 -#define IDM_FLOPPY_IMAGE_EXISTING_WP 0x2400 -#define IDM_FLOPPY_EXPORT_TO_86F 0x2500 -#define IDM_FLOPPY_EJECT 0x2600 +#define IDM_CARTRIDGE_IMAGE 0x2200 +#define IDM_CARTRIDGE_EJECT 0x2300 -#define IDM_CDROM_MUTE 0x3200 -#define IDM_CDROM_EMPTY 0x3300 -#define IDM_CDROM_RELOAD 0x3400 -#define IDM_CDROM_IMAGE 0x3500 -#define IDM_CDROM_HOST_DRIVE 0x3600 +#define IDM_FLOPPY_IMAGE_NEW 0x3200 +#define IDM_FLOPPY_IMAGE_EXISTING 0x3300 +#define IDM_FLOPPY_IMAGE_EXISTING_WP 0x3400 +#define IDM_FLOPPY_EXPORT_TO_86F 0x3500 +#define IDM_FLOPPY_EJECT 0x3600 -#define IDM_ZIP_IMAGE_NEW 0x4200 -#define IDM_ZIP_IMAGE_EXISTING 0x4300 -#define IDM_ZIP_IMAGE_EXISTING_WP 0x4400 -#define IDM_ZIP_EJECT 0x4500 -#define IDM_ZIP_RELOAD 0x4600 +#define IDM_CDROM_MUTE 0x4200 +#define IDM_CDROM_EMPTY 0x4300 +#define IDM_CDROM_RELOAD 0x4400 +#define IDM_CDROM_IMAGE 0x4500 +#define IDM_CDROM_HOST_DRIVE 0x4600 -#define IDM_MO_IMAGE_NEW 0x5200 -#define IDM_MO_IMAGE_EXISTING 0x5300 -#define IDM_MO_IMAGE_EXISTING_WP 0x5400 -#define IDM_MO_EJECT 0x5500 -#define IDM_MO_RELOAD 0x5600 +#define IDM_ZIP_IMAGE_NEW 0x5200 +#define IDM_ZIP_IMAGE_EXISTING 0x5300 +#define IDM_ZIP_IMAGE_EXISTING_WP 0x5400 +#define IDM_ZIP_EJECT 0x5500 +#define IDM_ZIP_RELOAD 0x5600 + +#define IDM_MO_IMAGE_NEW 0x6200 +#define IDM_MO_IMAGE_EXISTING 0x6300 +#define IDM_MO_IMAGE_EXISTING_WP 0x6400 +#define IDM_MO_EJECT 0x6500 +#define IDM_MO_RELOAD 0x6600 /* Next default values for new objects */ diff --git a/src/include/86box/ui.h b/src/include/86box/ui.h index 09bd29b24..8b4e77fcd 100644 --- a/src/include/86box/ui.h +++ b/src/include/86box/ui.h @@ -51,14 +51,15 @@ extern void ui_check_menu_item(int id, int checked); /* Status Bar functions. */ #define SB_ICON_WIDTH 24 #define SB_CASSETTE 0x00 -#define SB_FLOPPY 0x10 -#define SB_CDROM 0x20 -#define SB_ZIP 0x30 -#define SB_MO 0x40 -#define SB_HDD 0x50 -#define SB_NETWORK 0x60 -#define SB_SOUND 0x70 -#define SB_TEXT 0x80 +#define SB_CARTRIDGE 0x10 +#define SB_FLOPPY 0x20 +#define SB_CDROM 0x30 +#define SB_ZIP 0x40 +#define SB_MO 0x50 +#define SB_HDD 0x60 +#define SB_NETWORK 0x70 +#define SB_SOUND 0x80 +#define SB_TEXT 0x90 extern wchar_t *ui_window_title(wchar_t *s); extern void ui_status_update(void); diff --git a/src/include/86box/win.h b/src/include/86box/win.h index affbe2cc4..079463214 100644 --- a/src/include/86box/win.h +++ b/src/include/86box/win.h @@ -59,6 +59,7 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); #define SDL_SUB_CLASS_NAME L"86BoxSDLSubWnd" #define CASSETTE_SUBMENU_NAME L"CassetteSubmenu" +#define CARTRIDGE_SUBMENU_NAME L"CartridgeSubmenu" #define FLOPPY_SUBMENU_NAME L"FloppySubmenu" #define CDROM_SUBMENU_NAME L"CdromSubmenu" #define ZIP_SUBMENU_NAME L"ZIPSubmenu" @@ -222,11 +223,13 @@ extern void media_menu_init(); extern void media_menu_reset(); extern int media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); extern HMENU media_menu_get_cassette(void); +extern HMENU media_menu_get_cartridge(int id); extern HMENU media_menu_get_floppy(int id); extern HMENU media_menu_get_cdrom(int id); extern HMENU media_menu_get_zip(int id); extern HMENU media_menu_get_mo(int id); extern void media_menu_update_cassette(void); +extern void media_menu_update_cartridge(int id); extern void media_menu_update_floppy(int id); extern void media_menu_update_cdrom(int id); extern void media_menu_update_zip(int id); diff --git a/src/machine/machine.c b/src/machine/machine.c index 565e9f038..afa79b02c 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -28,6 +28,7 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/dma.h> #include <86box/pic.h> #include <86box/pit.h> @@ -94,6 +95,8 @@ machine_init_ex(int m) if (cassette_enable) device_add(&cassette_device); + + cart_reset(); } /* All good, boot the machine! */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 0fd1ebcca..936f94281 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -62,7 +62,7 @@ const machine_t machines[] = { /* 8088 Machines */ { "[8088] IBM PC (1981)", "ibmpc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 16, 64, 16, 0, machine_pc_init, NULL }, { "[8088] IBM PC (1982)", "ibmpc82", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 256, 256, 0, machine_pc82_init, NULL }, - { "[8088] IBM PCjr", "ibmpcjr", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 4772728, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, + { "[8088] IBM PCjr", "ibmpcjr", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 4772728, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_CARTRIDGE, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, { "[8088] IBM XT (1982)", "ibmxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 256, 64, 0, machine_xt_init, NULL }, { "[8088] IBM XT (1986)", "ibmxt86", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 64, 0, machine_xt86_init, NULL }, { "[8088] American XT Computer", "americxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_americxt_init, NULL }, diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 601afe4f9..c5205f85f 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -205,6 +205,16 @@ BEGIN END END +CartridgeSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE + MENUITEM SEPARATOR + MENUITEM "E&ject", IDM_CARTRIDGE_EJECT + END +END + FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" @@ -831,6 +841,7 @@ END 81 ICON DISCARDABLE ICON_PATH "icons/hard_disk_active.ico" 96 ICON DISCARDABLE ICON_PATH "icons/network.ico" 97 ICON DISCARDABLE ICON_PATH "icons/network_active.ico" +104 ICON DISCARDABLE ICON_PATH "icons/cartridge.ico" 144 ICON DISCARDABLE ICON_PATH "icons/floppy_525_empty.ico" 145 ICON DISCARDABLE ICON_PATH "icons/floppy_525_empty_active.ico" 152 ICON DISCARDABLE ICON_PATH "icons/floppy_35_empty.ico" @@ -843,6 +854,7 @@ END 185 ICON DISCARDABLE ICON_PATH "icons/mo_empty_active.ico" 192 ICON DISCARDABLE ICON_PATH "icons/cassette_empty.ico" 193 ICON DISCARDABLE ICON_PATH "icons/cassette_empty_active.ico" +232 ICON DISCARDABLE ICON_PATH "icons/cartridge_empty.ico" 240 ICON DISCARDABLE ICON_PATH "icons/machine.ico" 241 ICON DISCARDABLE ICON_PATH "icons/display.ico" 242 ICON DISCARDABLE ICON_PATH "icons/input_devices.ico" @@ -1144,6 +1156,8 @@ BEGIN IDS_2147 "Continue" IDS_2148 "Cassette: %s" IDS_2149 "Cassette images (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" + IDS_2150 "Cartridge %i: %ls" + IDS_2151 "Cartridge images (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0All files (*.*)\0*.*\0" END STRINGTABLE DISCARDABLE diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index a7fa1286d..29de899d7 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -636,7 +636,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ m_at_misc.o -DEVOBJ := bugger.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ +DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ vpc2007.o clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_piix4.o \ @@ -760,6 +760,7 @@ VIDOBJ := video.o \ vid_ht216.o \ vid_oak_oti.o \ vid_paradise.o \ + vid_rage128pro.o \ vid_rtg310x.o \ vid_ti_cf62011.o \ vid_tvga.o \ diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index a743ad14a..8a32df295 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -32,6 +32,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/fdd.h> #include <86box/hdd.h> #include <86box/scsi_device.h> @@ -72,6 +73,29 @@ cassette_eject(void) } +void +cartridge_mount(uint8_t id, char *fn, uint8_t wp) +{ + cart_close(id); + cart_load(id, fn); + ui_sb_update_icon_state(SB_CARTRIDGE | id, strlen(cart_fns[id]) ? 0 : 1); + media_menu_update_cartridge(id); + ui_sb_update_tip(SB_CARTRIDGE | id); + config_save(); +} + + +void +cartridge_eject(uint8_t id) +{ + cart_close(id); + ui_sb_update_icon_state(SB_CARTRIDGE | id, 1); + media_menu_update_cartridge(id); + ui_sb_update_tip(SB_CARTRIDGE | id); + config_save(); +} + + void floppy_mount(uint8_t id, char *fn, uint8_t wp) { diff --git a/src/win/win_media_menu.c b/src/win/win_media_menu.c index 7b7aae788..f72c2aae1 100644 --- a/src/win/win_media_menu.c +++ b/src/win/win_media_menu.c @@ -9,6 +9,7 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/fdd.h> #include <86box/fdd_86f.h> #include <86box/hdc.h> @@ -27,14 +28,15 @@ #define MACHINE_HAS_SCSI (machines[machine].flags & MACHINE_SCSI_DUAL) #define CASSETTE_FIRST 0 -#define FDD_FIRST 1 +#define CARTRIDGE_FIRST CASSETTE_FIRST + 1 +#define FDD_FIRST CARTRIDGE_FIRST + 2 #define CDROM_FIRST FDD_FIRST + FDD_NUM #define ZIP_FIRST CDROM_FIRST + CDROM_NUM #define MO_FIRST ZIP_FIRST + ZIP_NUM static HMENU media_menu, stbar_menu; -static HMENU menus[1 + FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; +static HMENU menus[1 + 2 + FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; static char index_map[255]; @@ -95,6 +97,29 @@ media_menu_set_name_cassette(void) } +static void +media_menu_set_name_cartridge(int drive) +{ + wchar_t name[512], fn[512]; + MENUITEMINFO mii = { 0 }; + + if (strlen(floppyfns[drive]) == 0) { + _swprintf(name, plat_get_string(IDS_2150), + drive + 1, plat_get_string(IDS_2057)); + } else { + mbstoc16s(fn, floppyfns[drive], sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2150), + drive + 1, fn); + } + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; + mii.dwTypeData = name; + + SetMenuItemInfo(media_menu, (UINT_PTR)menus[CARTRIDGE_FIRST + drive], FALSE, &mii); +} + + static void media_menu_set_name_floppy(int drive) { @@ -241,6 +266,20 @@ media_menu_update_cassette(void) } +void +media_menu_update_cartridge(int id) +{ + int i = CARTRIDGE_FIRST + id; + + if (strlen(cart_fns[id]) == 0) + EnableMenuItem(menus[i], IDM_CARTRIDGE_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + else + EnableMenuItem(menus[i], IDM_CARTRIDGE_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + + media_menu_set_name_cartridge(id); +} + + void media_menu_update_floppy(int id) { @@ -334,6 +373,11 @@ media_menu_load_submenus() menus[curr] = media_menu_load_resource(CASSETTE_SUBMENU_NAME); media_menu_set_ids(menus[curr++], 0); + for(int i = 0; i < 2; i++) { + menus[curr] = media_menu_load_resource(CARTRIDGE_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], i); + } + for(int i = 0; i < FDD_NUM; i++) { menus[curr] = media_menu_load_resource(FLOPPY_SUBMENU_NAME); media_menu_set_ids(menus[curr++], i); @@ -356,6 +400,13 @@ media_menu_load_submenus() } +static inline int +is_valid_cartridge(void) +{ + return ((machines[machine].flags & MACHINE_CARTRIDGE) ? 1 : 0); +} + + static inline int is_valid_fdd(int i) { @@ -420,6 +471,14 @@ media_menu_reset() } curr++; + for(int i = 0; i < 2; i++) { + if(is_valid_cartridge()) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); + media_menu_update_cartridge(i); + } + curr++; + } + for(int i = 0; i < FDD_NUM; i++) { if(is_valid_fdd(i)) { AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); @@ -548,6 +607,16 @@ media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) cassette_eject(); break; + case IDM_CARTRIDGE_IMAGE: + ret = file_dlg_st(hwnd, IDS_2151, floppyfns[id], NULL, 0); + if (! ret) + cartridge_mount(id, openfilestring, wp); + break; + + case IDM_CARTRIDGE_EJECT: + cartridge_eject(id); + break; + case IDM_FLOPPY_IMAGE_NEW: NewFloppyDialogCreate(hwnd, id, 0); break; @@ -654,6 +723,13 @@ media_menu_get_cassette(void) } +HMENU +media_menu_get_cartridge(int id) +{ + return menus[CARTRIDGE_FIRST + id]; +} + + HMENU media_menu_get_floppy(int id) { diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index 893c9c63d..6d37e54f0 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -35,6 +35,7 @@ #include <86box/machine.h> #include <86box/timer.h> #include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/fdd.h> @@ -200,6 +201,33 @@ StatusBarCreateCassetteTip(int part) } +static void +StatusBarCreateCartridgeTip(int part) +{ + WCHAR tempTip[512]; + WCHAR fn[512]; + int drive = sb_part_meanings[part] & 0xf; + + int type = zip_drives[drive].is_250 ? 250 : 100; + + if (strlen(cart_fns[drive]) == 0) { + _swprintf(tempTip, plat_get_string(IDS_2150), + drive+1, plat_get_string(IDS_2057)); + } else { + mbstoc16s(fn, cart_fns[drive], sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2150), + drive+1, fn); + } + + if (sbTips[part] != NULL) { + free(sbTips[part]); + sbTips[part] = NULL; + } + sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + wcscpy(sbTips[part], tempTip); +} + + static void StatusBarCreateFloppyTip(int part) { @@ -391,6 +419,10 @@ ui_sb_update_tip(int meaning) StatusBarCreateCassetteTip(part); break; + case SB_CARTRIDGE: + StatusBarCreateCartridgeTip(part); + break; + case SB_FLOPPY: StatusBarCreateFloppyTip(part); break; @@ -467,7 +499,7 @@ void ui_sb_update_panes(void) { int i, id; - int mfm_int, xta_int, esdi_int, ide_int, scsi_int; + int cart_int, mfm_int, xta_int, esdi_int, ide_int, scsi_int; int edge = 0; int c_mfm, c_esdi, c_xta; int c_ide, c_scsi; @@ -481,6 +513,7 @@ ui_sb_update_panes(void) sb_ready = 0; } + cart_int = (machines[machine].flags & MACHINE_CARTRIDGE) ? 1 : 0; mfm_int = (machines[machine].flags & MACHINE_MFM) ? 1 : 0; xta_int = (machines[machine].flags & MACHINE_XTA) ? 1 : 0; esdi_int = (machines[machine].flags & MACHINE_ESDI) ? 1 : 0; @@ -521,6 +554,8 @@ ui_sb_update_panes(void) sb_parts = 0; if (cassette_enable) sb_parts++; + if (cart_int) + sb_parts += 2; for (i=0; i Date: Thu, 29 Jul 2021 20:42:06 +0200 Subject: [PATCH 15/16] Removed from the makefile that, which was not supposed to be there. --- src/win/Makefile.mingw | 1 - 1 file changed, 1 deletion(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 29de899d7..c00cde83b 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -760,7 +760,6 @@ VIDOBJ := video.o \ vid_ht216.o \ vid_oak_oti.o \ vid_paradise.o \ - vid_rage128pro.o \ vid_rtg310x.o \ vid_ti_cf62011.o \ vid_tvga.o \ From 347a8fa011345479f75189f8e7fe8b6ef8e4ca8c Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Jul 2021 00:41:05 +0200 Subject: [PATCH 16/16] Fixed win_stbar.c warning reported by lemondrops and committed the icons. --- src/win/icons/cartridge.ico | Bin 0 -> 1150 bytes src/win/icons/cartridge_empty.ico | Bin 0 -> 1150 bytes src/win/win_stbar.c | 2 -- 3 files changed, 2 deletions(-) create mode 100644 src/win/icons/cartridge.ico create mode 100644 src/win/icons/cartridge_empty.ico diff --git a/src/win/icons/cartridge.ico b/src/win/icons/cartridge.ico new file mode 100644 index 0000000000000000000000000000000000000000..1edb05a8b69ec1b7e2ab1ddc0fbabff957235ab1 GIT binary patch literal 1150 zcmbu8OK;Oa6orl82XsSXkDb`##BV!^ouqj{X{mT50fo*oqO$b?u=)wX}9>>*wFazXdmxrT20fmkg&wcy3U~O@ZP_!$&(l8 zP-lue3V|H zG>Wn}b5lq}K~*ogHq)?64CN!J7aokOd8qz^^S8{K=P&u*Ow)!Xh(W#b;kZ4-YRdg8@9vbwp zOh(IR?(;nKD*9-+1;=hdl6CYr_Fxk!V@M}vJ%TF}WISKj_dlKNqUDBYy8&YWuN85u z^02IX?F@>*@1fV-tmupFS$Qr(FUFb#fk*rVK4Zu|i+GM>?o&}z&;Mk;hrwtY!|5(Y zTaPf=dWtcb(6@{aW*pBky8oEp&%H|j*}D@wf4RW^Vu@FWOT2!6hJz#WVMQ33@3a1F zZ-JeM^NRk>>H=?%S2$XpM+Q*!+28x9Un{_20<2L6XX DcBEAo literal 0 HcmV?d00001 diff --git a/src/win/icons/cartridge_empty.ico b/src/win/icons/cartridge_empty.ico new file mode 100644 index 0000000000000000000000000000000000000000..28efc04a4fd43caf0a153cb4bcb3c508edba3362 GIT binary patch literal 1150 zcmbu8OK;Oa6orl82Xw`n4XQ1V<;3zhiXZYTQS2m5ltL*~JX(PSQd=mX7TQI1lr)G% zp@;<%<cEw>0gxrfE81iIqj2K}-1C zzplyCm*^B@L`e@}+(Voch|`jJ7YS=o)Il6~(Jw|A^vAgBQ;ye>bq7ePNz*>kjO5I- z5=p%9O49;GIYLnkYx=Ceiae)A>9Yay&Ilcnr(rpS4|v@2IO*+9#S(Dp*c z5PmD>TIEqy_uDxXVbDXbyHeAa>zmcNi2MW#QiMJUQUr_<-&xFaobWxBW&Qk5wstTW ztz)>lfzjGyOxB)ZOeXZL;)6}Dw=lZ@g#Vv=wf>v$kMUxAAG`Zgygr!X&4&~09g>f8 z!pMA=_2)bLc=%|mrhhv>!@Hw74yUI${`?)&(;t|9`H9)rbDW(0BIlTqqfg(kcX0ey L|NG{}#sBaJ6wxIZ literal 0 HcmV?d00001 diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index 6d37e54f0..b89bcafed 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -208,8 +208,6 @@ StatusBarCreateCartridgeTip(int part) WCHAR fn[512]; int drive = sb_part_meanings[part] & 0xf; - int type = zip_drives[drive].is_250 ? 250 : 100; - if (strlen(cart_fns[drive]) == 0) { _swprintf(tempTip, plat_get_string(IDS_2150), drive+1, plat_get_string(IDS_2057));