diff --git a/main.c b/main.c index 6d1f2f4d..15c7c86d 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) { @@ -195,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; @@ -207,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; @@ -243,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 { @@ -765,7 +772,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_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); diff --git a/mpxplay/au_cards/au_cards.h b/mpxplay/au_cards/au_cards.h index 78de6edf..cab2296e 100644 --- a/mpxplay/au_cards/au_cards.h +++ b/mpxplay/au_cards/au_cards.h @@ -228,15 +228,15 @@ 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; 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) diff --git a/mpxplay/au_cards/ioport.c b/mpxplay/au_cards/ioport.c index 5b5f79d6..43326e49 100644 --- a/mpxplay/au_cards/ioport.c +++ b/mpxplay/au_cards/ioport.c @@ -23,5 +23,16 @@ 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->mpu401_softread) { + int timeout = 10000; // 100ms + do { + uint8_t st = hw_mpu_inb(1); + if (!(st & 0x40)) break; + // still full + pds_delay_10us(1); + } while (--timeout); + } +#endif hw_mpu_outb(idx, data); } 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<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; + } + } + } + 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); return 1; @@ -920,18 +960,26 @@ 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 ( 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 (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; } if(status&CM_MCBINT) //Abort conditions occur during PCI Bus Target/Master Access { //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) @@ -965,6 +1013,36 @@ static aucards_allmixerchan_s cmi8x38_mixerset[]={ NULL }; +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); +} + +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, @@ -990,7 +1068,12 @@ one_sndcard_info CMI8X38_sndcard_info={ &CMI8X38_writeMIXER, &CMI8X38_readMIXER, - &cmi8x38_mixerset[0] + &cmi8x38_mixerset[0], + + &ioport_fm_write, + &ioport_fm_read, + &cmi8x38_mpu401_write, + &cmi8x38_mpu401_read, }; #endif 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);