From 1e045e702867f589fc186ac8810ef196793fcf24 Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sat, 17 Feb 2024 18:34:52 +0900 Subject: [PATCH 1/8] Squash compiler warnings --- main.c | 9 +++++---- mpxplay/au_cards/au_cards.h | 4 ++-- mpxplay/au_cards/pcibios.c | 2 +- mpxplay/au_cards/sc_cmi.c | 4 ++-- mpxplay/au_cards/sc_ymf.c | 12 ++++++------ 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/main.c b/main.c index 6d1f2f4d..1510eecf 100644 --- a/main.c +++ b/main.c @@ -85,10 +85,11 @@ static void MAIN_TSR_Interrupt(); } \ } else { \ if (fm_aui.card_handler->card_fm_read) \ - return fm_aui.card_handler->card_fm_read(&fm_aui, n); \ + return fm_aui.card_handler->card_fm_read(&fm_aui, n); \ } \ - return 0; \ - } } while (0) + } \ + return 0; \ + } while (0) static uint32_t MAIN_OPL3_388(uint32_t port, uint32_t val, uint32_t out) { @@ -765,7 +766,7 @@ int main(int argc, char* argv[]) { printf("Invalid Sound card IRQ: "); MAIN_CPrintf(RED, "%d", aui.card_irq); - printf(", Trying to assign a valid IRQ...\n", aui.card_irq); + printf(", Trying to assign a valid IRQ...\n"); aui.card_irq = pcibios_AssignIRQ(aui.card_pci_dev); if(aui.card_irq == 0xFF) { diff --git a/mpxplay/au_cards/au_cards.h b/mpxplay/au_cards/au_cards.h index 78de6edf..82625dcd 100644 --- a/mpxplay/au_cards/au_cards.h +++ b/mpxplay/au_cards/au_cards.h @@ -228,10 +228,10 @@ typedef struct mpxplay_audioout_info_s{ char *card_selectname; // select card by name - NOT used by SBEMU #ifdef SBEMU - int card_test_index; //current test index for main card + int card_test_index; //current test index int card_select_index; //user selection for main card int card_select_index_fm; //user selection for FM(OPL) card - int card_select_index_mpu401; //user selection via MPU-401 card + int card_select_index_mpu401; //user selection for MPU-401 card int card_samples_per_int; //samples per interrupt struct pci_config_s* card_pci_dev; uint16_t fm_port; diff --git a/mpxplay/au_cards/pcibios.c b/mpxplay/au_cards/pcibios.c index 0f41e4eb..b9fff008 100644 --- a/mpxplay/au_cards/pcibios.c +++ b/mpxplay/au_cards/pcibios.c @@ -715,7 +715,7 @@ uint8_t pcibios_AssignIRQ(pci_config_s* ppkey) if(intpin-1 == j) { linkedIRQ = pcibios_ReadConfig_Byte(&cfg, PCIR_INTR_LN); - assert(linkedIRQ == 0xFF || ((1<card_private_data; int status = snd_cmipci_read_32(card, CM_REG_INT_STATUS); //read only reg (R) while(status == -1) snd_cmipci_read_32(card, CM_REG_INT_STATUS); - if ( card->chip_version > 37 && !(status&CM_INTR) || - card->chip_version <= 37 && !(status & CM_INTR_MASK)) { //the summary bit is incorrect for PCI-SX, the interrupt be chained to other shared IRQ device with invalid interrupts + if ((card->chip_version > 37 && !(status&CM_INTR)) || + (card->chip_version <= 37 && !(status & CM_INTR_MASK))) { //the summary bit is incorrect for PCI-SX, the interrupt be chained to other shared IRQ device with invalid interrupts return 0; } if(status&CM_MCBINT) //Abort conditions occur during PCI Bus Target/Master Access diff --git a/mpxplay/au_cards/sc_ymf.c b/mpxplay/au_cards/sc_ymf.c index a6764157..54b21359 100644 --- a/mpxplay/au_cards/sc_ymf.c +++ b/mpxplay/au_cards/sc_ymf.c @@ -869,10 +869,10 @@ static int snd_ymfpci_memalloc (struct mpxplay_audioout_info_s *aui) return -1; memset(card->dm->linearptr, 0, size); - ptr = card->dm->linearptr; + ptr = (uint8_t *)card->dm->linearptr; ptr_addr = (dma_addr_t)ptr; - ptr = (char *)ALIGN((unsigned long)ptr, 0x100); + ptr = (uint8_t *)ALIGN((unsigned long)ptr, 0x100); ptr_addr = ALIGN(ptr_addr, 0x100); card->bank_base_playback = ptr; @@ -892,7 +892,7 @@ static int snd_ymfpci_memalloc (struct mpxplay_audioout_info_s *aui) ptr_addr += card->bank_size_playback; } } - ptr = (char *)ALIGN((unsigned long)ptr, 0x100); + ptr = (uint8_t *)ALIGN((unsigned long)ptr, 0x100); ptr_addr = ALIGN(ptr_addr, 0x100); card->bank_base_capture = ptr; card->bank_base_capture_addr = (uint32_t)pds_cardmem_physicalptr(card->dm, ptr_addr); @@ -903,7 +903,7 @@ static int snd_ymfpci_memalloc (struct mpxplay_audioout_info_s *aui) ptr_addr += card->bank_size_capture; } } - ptr = (char *)ALIGN((unsigned long)ptr, 0x100); + ptr = (uint8_t *)ALIGN((unsigned long)ptr, 0x100); ptr_addr = ALIGN(ptr_addr, 0x100); card->bank_base_effect = ptr; card->bank_base_effect_addr = (uint32_t)pds_cardmem_physicalptr(card->dm, ptr_addr); @@ -914,14 +914,14 @@ static int snd_ymfpci_memalloc (struct mpxplay_audioout_info_s *aui) ptr_addr += card->bank_size_effect; } } - ptr = (char *)ALIGN((unsigned long)ptr, 0x100); + ptr = (uint8_t *)ALIGN((unsigned long)ptr, 0x100); ptr_addr = ALIGN(ptr_addr, 0x100); card->work_base = ptr; card->work_base_addr = (uint32_t)pds_cardmem_physicalptr(card->dm, ptr_addr); card->pcmout_buffer = card->work_base + card->work_size; card->pcmout_buffer_physaddr = (uint32_t)pds_cardmem_physicalptr(card->dm, card->pcmout_buffer); - aui->card_DMABUFF = card->pcmout_buffer; + aui->card_DMABUFF = (char *)card->pcmout_buffer; #if YMF_DEBUG DBG_Logi("playback base: %8.8X\n", card->bank_base_playback_addr); From 90f8e7abc5422eb8c6124404e0f1f11c625baa6c Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sat, 17 Feb 2024 21:17:32 +0900 Subject: [PATCH 2/8] Disable interrupts when setting __djgpp_selector_limit --- mpxplay/au_cards/au_base.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mpxplay/au_cards/au_base.c b/mpxplay/au_cards/au_base.c index 8f8cfe5a..a00f77b3 100644 --- a/mpxplay/au_cards/au_base.c +++ b/mpxplay/au_cards/au_base.c @@ -331,9 +331,11 @@ int pds_dpmi_xms_allocmem(xmsmem_t * mem,unsigned int size) unsigned long newlimit = info.address + size - base - 1; newlimit = ((newlimit+1+0xFFF)&~0xFFF) - 1;//__dpmi_set_segment_limit must be page aligned //printf("addr: %08x, limit: %08x\n",mem->linearptr, newlimit); + int intr = disable(); __dpmi_set_segment_limit(_my_ds(), max(limit, newlimit)); __dpmi_set_segment_limit(__djgpp_ds_alias, max(limit, newlimit)); __djgpp_selector_limit = max(limit, newlimit); + if (intr) enable(); return 1; } }while(0); From c590c9931c932cf2fca2a729375afa0be4b9f725 Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sat, 17 Feb 2024 21:17:54 +0900 Subject: [PATCH 3/8] CMI8738 hardware OPL3 support. Must be enabled using /SCFM option. --- mpxplay/au_cards/sc_cmi.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/mpxplay/au_cards/sc_cmi.c b/mpxplay/au_cards/sc_cmi.c index 7d9a084e..f111be71 100644 --- a/mpxplay/au_cards/sc_cmi.c +++ b/mpxplay/au_cards/sc_cmi.c @@ -448,7 +448,7 @@ static void snd_cmipci_ch_reset(cmi8x38_card *cm, int ch) //reset channel ch int reset = CM_RST_CH0 << ch; int adcch = CM_CHADC0 << ch; snd_cmipci_write_32(cm, CM_REG_FUNCTRL0, adcch|reset); - do {pds_delay_10us(10); printf("%x\n",snd_cmipci_read_32(cm,CM_REG_FUNCTRL0));} while(!(snd_cmipci_read_32(cm,CM_REG_FUNCTRL0)&reset)); + do {pds_delay_10us(10); uint32_t x = snd_cmipci_read_32(cm,CM_REG_FUNCTRL0);} while(!(snd_cmipci_read_32(cm,CM_REG_FUNCTRL0)&reset)); snd_cmipci_write_32(cm, CM_REG_FUNCTRL0, adcch&(~reset)); do {pds_delay_10us(10);} while((snd_cmipci_read_32(cm,CM_REG_FUNCTRL0)&reset)); pds_mdelay(5); @@ -684,6 +684,34 @@ static int CMI8X38_adetect(struct mpxplay_audioout_info_s *aui) // init chip cmi8x38_chip_init(card); + uint16_t fmport = card->iobase + CM_REG_FM_PCI; + if (aui->card_select_index_fm && aui->card_select_index_fm == aui->card_test_index) { +#define OPL_write(reg, val) do { outp(fmport, reg); pds_delay_10us(1); outp(fmport+1, val); pds_delay_10us(3); } while (0) +#define OPL_status() (inp(fmport) & 0xe0) + OPL_write(0x04, 0x60); // Reset Timer 1 and Timer 2 + OPL_write(0x04, 0x80); // Reset the IRQ + uint8_t fmsts1 = OPL_status(); + //printf("fmsts1: %x\n", fmsts1); + OPL_write(0x02, 0xff); // Set Timer 1 to ff + OPL_write(0x04, 0x21); // Unmask and start Timer 1 + pds_delay_10us(8); // Delay at least 80us + uint8_t fmsts2 = OPL_status(); + OPL_write(0x04, 0x60); // Reset Timer 1 and Timer 2 + OPL_write(0x04, 0x80); // Reset the IRQ + //printf("fmsts2: %x\n", fmsts2); + if (!(fmsts1 == 0 && fmsts2 == 0xc0)) { + printf("CMI: No OPL detected\n"); + } else { + uint8_t fmsts3 = inp(fmport) & 0x06; + //printf("fmsts3: %x\n", fmsts3); + if (fmsts3 == 0) { + //printf("CMI: OPL3 detected\n"); + aui->fm_port = fmport; + aui->fm = 1; + } + } + } + mpxplay_debugf(CMI_DEBUG_OUTPUT, "did init, IRQ: %d, iobase: %x", card->irq, card->iobase); return 1; @@ -990,7 +1018,12 @@ one_sndcard_info CMI8X38_sndcard_info={ &CMI8X38_writeMIXER, &CMI8X38_readMIXER, - &cmi8x38_mixerset[0] + &cmi8x38_mixerset[0], + + &ioport_fm_write, + &ioport_fm_read, + &ioport_mpu401_write, + &ioport_mpu401_read, }; #endif From a827648957b9fd9bab4b26274aa8a5336b04a67b Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sat, 17 Feb 2024 23:12:28 +0900 Subject: [PATCH 4/8] Add mpu401_softread flag for CMI8738/Duke Nukem 3D --- main.c | 16 +++++++++++----- mpxplay/au_cards/au_cards.h | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index 1510eecf..15c7c86d 100644 --- a/main.c +++ b/main.c @@ -196,9 +196,12 @@ static uint32_t MAIN_MPU_330(uint32_t port, uint32_t val, uint32_t out) ser_putbyte((int)(val & 0xff)); return 0; } else { - uint8_t val, hwval; - if (mpu401_aui.mpu401 && mpu401_aui.card_handler->card_mpu401_read) + uint8_t val, hwval, hwval_valid = 0; + if (mpu401_aui.mpu401 && mpu401_aui.card_handler->card_mpu401_read) { hwval = mpu401_aui.card_handler->card_mpu401_read(&mpu401_aui, 0); + if (!mpu401_aui.mpu401_softread) + hwval_valid = 1; + } if (mpu_state == 1) { mpu_state = 0; val = 0xfe; @@ -208,7 +211,7 @@ static uint32_t MAIN_MPU_330(uint32_t port, uint32_t val, uint32_t out) } else { val = 0; } - if (mpu401_aui.mpu401 && mpu401_aui.card_handler->card_mpu401_read) + if (hwval_valid) return hwval; else return val; @@ -244,8 +247,11 @@ static uint32_t MAIN_MPU_331(uint32_t port, uint32_t val, uint32_t out) } return 0; } - if (mpu401_aui.mpu401 && mpu401_aui.card_handler->card_mpu401_read) - return mpu401_aui.card_handler->card_mpu401_read(&mpu401_aui, 1); + if (mpu401_aui.mpu401 && mpu401_aui.card_handler->card_mpu401_read) { + uint8_t hwval = mpu401_aui.card_handler->card_mpu401_read(&mpu401_aui, 1); + if (!mpu401_aui.mpu401_softread) + return hwval; + } if ((mpu_state & 3) == 0) { return 0x80; } else { diff --git a/mpxplay/au_cards/au_cards.h b/mpxplay/au_cards/au_cards.h index 82625dcd..cab2296e 100644 --- a/mpxplay/au_cards/au_cards.h +++ b/mpxplay/au_cards/au_cards.h @@ -236,7 +236,7 @@ typedef struct mpxplay_audioout_info_s{ struct pci_config_s* card_pci_dev; uint16_t fm_port; uint16_t mpu401_port; - unsigned int pcm: 1, fm: 1, mpu401: 1; + unsigned int pcm: 1, fm: 1, mpu401: 1, mpu401_softread; #endif struct one_sndcard_info *card_handler; // function structure of the card void *card_private_data; // extra private datas can be pointed here (with malloc) From c05a297685075460b599bc6e20e0e5649bf2c49d Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sat, 17 Feb 2024 23:13:05 +0900 Subject: [PATCH 5/8] Check if the MPU-401 UART is ready for writing, needed for CMI8738 --- mpxplay/au_cards/ioport.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mpxplay/au_cards/ioport.c b/mpxplay/au_cards/ioport.c index 5b5f79d6..84c8dec9 100644 --- a/mpxplay/au_cards/ioport.c +++ b/mpxplay/au_cards/ioport.c @@ -23,5 +23,14 @@ uint8_t ioport_mpu401_read (struct mpxplay_audioout_info_s *aui, unsigned int id void ioport_mpu401_write (struct mpxplay_audioout_info_s *aui, unsigned int idx, uint8_t data) { + if (idx == 0) { + int timeout = 10000; // 100ms + do { + uint8_t st = hw_mpu_inb(1); + if (!(st & 0x40)) break; + // still full + pds_delay_10us(1); + } while (--timeout); + } hw_mpu_outb(idx, data); } From f0d22356d68f365e73acba98815326cb02d956e9 Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sat, 17 Feb 2024 23:17:00 +0900 Subject: [PATCH 6/8] Hardware FM and MPU-401 support for CMI8738 --- mpxplay/au_cards/sc_cmi.c | 61 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/mpxplay/au_cards/sc_cmi.c b/mpxplay/au_cards/sc_cmi.c index f111be71..d1450afe 100644 --- a/mpxplay/au_cards/sc_cmi.c +++ b/mpxplay/au_cards/sc_cmi.c @@ -378,6 +378,8 @@ typedef struct cmi8x38_card int shift; //int ac3_shift; /* extra shift: 1 on soft ac3 mode */ + uint8_t midi_in_data; + uint8_t midi_in_data_valid:1; }cmi8x38_card; extern unsigned int intsoundconfig,intsoundcontrol; @@ -711,6 +713,16 @@ static int CMI8X38_adetect(struct mpxplay_audioout_info_s *aui) } } } + uint16_t mpuport = card->iobase + CM_REG_MPU_PCI; + if (card->chip_version >= 39) { + uint8_t val = inp(card->iobase + CM_REG_MPU_PCI + 1); + if (val != 0x00 && val != 0xff) { + //printf("CMI: MPU-401 detected\n"); + aui->mpu401_port = mpuport; + aui->mpu401 = 1; + aui->mpu401_softread = 1; // Needed for Duke Nukem 3D + } + } mpxplay_debugf(CMI_DEBUG_OUTPUT, "did init, IRQ: %d, iobase: %x", card->irq, card->iobase); @@ -948,7 +960,13 @@ static int CMI8X38_IRQRoutine(mpxplay_audioout_info_s* aui) { cmi8x38_card *card=aui->card_private_data; int status = snd_cmipci_read_32(card, CM_REG_INT_STATUS); //read only reg (R) - while(status == -1) snd_cmipci_read_32(card, CM_REG_INT_STATUS); + if (status == -1) { + int timeout = 2000; + do { + status = snd_cmipci_read_32(card, CM_REG_INT_STATUS); + if (status != -1) break; + } while (--timeout); + } if ((card->chip_version > 37 && !(status&CM_INTR)) || (card->chip_version <= 37 && !(status & CM_INTR_MASK))) { //the summary bit is incorrect for PCI-SX, the interrupt be chained to other shared IRQ device with invalid interrupts return 0; @@ -957,9 +975,11 @@ static int CMI8X38_IRQRoutine(mpxplay_audioout_info_s* aui) { //nothing we can do } - if(status&CM_UARTINT) + if(status&CM_UARTINT && aui->mpu401_port) { - + card->midi_in_data = inp(aui->mpu401_port); + card->midi_in_data_valid = 1; + //DBG_Logi("uartint %x\n", card->midi_in_data); } unsigned int mask = 0; if (status & CM_CHINT0) @@ -993,6 +1013,38 @@ static aucards_allmixerchan_s cmi8x38_mixerset[]={ NULL }; +#if 0 // use ioport_mpu401_write +static void cmi8x38_mpu401_write (struct mpxplay_audioout_info_s *aui, unsigned int idx, uint8_t data) +{ + if (idx == 0) { + int timeout = 10000; // 100ms + do { + uint8_t st = inp(aui->mpu401_port+1); + if (!(st & 0x40)) break; + // still full + pds_delay_10us(1); + } while (--timeout); + } + outp(aui->mpu401_port+idx, data); +} +#endif + +static uint8_t cmi8x38_mpu401_read (struct mpxplay_audioout_info_s *aui, unsigned int idx) +{ + struct cmi8x38_card *card=aui->card_private_data; + if (idx == 0) { + //uint8_t midi_in_data = inp(aui->mpu401_port); + uint8_t midi_in_data = card->midi_in_data_valid ? card->midi_in_data : inp(aui->mpu401_port); + card->midi_in_data_valid = 0; + //DBG_Logi(" r %u %2.2X\n", idx, midi_in_data); + return midi_in_data; + } else { + uint8_t data = inp(aui->mpu401_port+idx); + //if (data != 0xbf) DBG_Logi(" r %u %2.2X\n", idx, data); + return data; + } +} + one_sndcard_info CMI8X38_sndcard_info={ "CMI 8338/8738", SNDCARD_LOWLEVELHAND|SNDCARD_INT08_ALLOWED, @@ -1022,8 +1074,9 @@ one_sndcard_info CMI8X38_sndcard_info={ &ioport_fm_write, &ioport_fm_read, + //&cmi8x38_mpu401_write, &ioport_mpu401_write, - &ioport_mpu401_read, + &cmi8x38_mpu401_read, }; #endif From 8060a78663c479a07a6e54b625f498aa6e48ebde Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sun, 18 Feb 2024 00:29:34 +0900 Subject: [PATCH 7/8] Only check if the MPU-401 UART is ready for writing in the CMI driver --- mpxplay/au_cards/ioport.c | 4 +++- mpxplay/au_cards/sc_cmi.c | 5 +---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mpxplay/au_cards/ioport.c b/mpxplay/au_cards/ioport.c index 84c8dec9..61744a17 100644 --- a/mpxplay/au_cards/ioport.c +++ b/mpxplay/au_cards/ioport.c @@ -23,7 +23,8 @@ uint8_t ioport_mpu401_read (struct mpxplay_audioout_info_s *aui, unsigned int id void ioport_mpu401_write (struct mpxplay_audioout_info_s *aui, unsigned int idx, uint8_t data) { - if (idx == 0) { +#if 0 // shouldn't DOS programs be doing this themselves if it was really necessary? + if (idx == 0 && aui->) { int timeout = 10000; // 100ms do { uint8_t st = hw_mpu_inb(1); @@ -32,5 +33,6 @@ void ioport_mpu401_write (struct mpxplay_audioout_info_s *aui, unsigned int idx, pds_delay_10us(1); } while (--timeout); } +#endif hw_mpu_outb(idx, data); } diff --git a/mpxplay/au_cards/sc_cmi.c b/mpxplay/au_cards/sc_cmi.c index d1450afe..7731baba 100644 --- a/mpxplay/au_cards/sc_cmi.c +++ b/mpxplay/au_cards/sc_cmi.c @@ -1013,7 +1013,6 @@ static aucards_allmixerchan_s cmi8x38_mixerset[]={ NULL }; -#if 0 // use ioport_mpu401_write static void cmi8x38_mpu401_write (struct mpxplay_audioout_info_s *aui, unsigned int idx, uint8_t data) { if (idx == 0) { @@ -1027,7 +1026,6 @@ static void cmi8x38_mpu401_write (struct mpxplay_audioout_info_s *aui, unsigned } outp(aui->mpu401_port+idx, data); } -#endif static uint8_t cmi8x38_mpu401_read (struct mpxplay_audioout_info_s *aui, unsigned int idx) { @@ -1074,8 +1072,7 @@ one_sndcard_info CMI8X38_sndcard_info={ &ioport_fm_write, &ioport_fm_read, - //&cmi8x38_mpu401_write, - &ioport_mpu401_write, + &cmi8x38_mpu401_write, &cmi8x38_mpu401_read, }; From 6d7b38253d97267f25f74eb98f3a36e9db57cbe7 Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sun, 18 Feb 2024 00:34:10 +0900 Subject: [PATCH 8/8] Fix typo in ioport.c --- mpxplay/au_cards/ioport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpxplay/au_cards/ioport.c b/mpxplay/au_cards/ioport.c index 61744a17..43326e49 100644 --- a/mpxplay/au_cards/ioport.c +++ b/mpxplay/au_cards/ioport.c @@ -24,7 +24,7 @@ uint8_t ioport_mpu401_read (struct mpxplay_audioout_info_s *aui, unsigned int id void ioport_mpu401_write (struct mpxplay_audioout_info_s *aui, unsigned int idx, uint8_t data) { #if 0 // shouldn't DOS programs be doing this themselves if it was really necessary? - if (idx == 0 && aui->) { + if (idx == 0 && aui->mpu401_softread) { int timeout = 10000; // 100ms do { uint8_t st = hw_mpu_inb(1);