Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yamaha YMF724/YMF744/YMF754 (DS-XG) driver with hardware FM/MPU-401 port remapping #81

Merged
merged 50 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
10f84fd
MPU-401 support
jiyunomegami Jan 3, 2024
521b55d
fix /MCOM usage message
jiyunomegami Jan 3, 2024
c2c42d6
PIO option
jiyunomegami Jan 6, 2024
561422d
Messy X-Fi changes (WARNING: does not work yet)
jiyunomegami Jan 8, 2024
b83d5fd
Intel HDA: read back CORBCTL value when enabling DMA, add fallback to…
jiyunomegami Jan 8, 2024
3f2959c
cleanup PIO fallback patch
jiyunomegami Jan 10, 2024
3f543fb
get COM port addresses from the BIOS Data Area (BDA)
jiyunomegami Jan 10, 2024
5d48cc0
check /MCOM and /DBG arguments for typos
jiyunomegami Jan 10, 2024
a0c3ce1
Remove /PIO option
jiyunomegami Jan 13, 2024
41d5abd
Merge remote-tracking branch 'upstream/main'
jiyunomegami Jan 13, 2024
744876d
Cleanup serial code
jiyunomegami Jan 13, 2024
0ced005
working CMI driver
jiyunomegami Jan 14, 2024
cd1ca34
Merge remote-tracking branch 'upstream/main'
jiyunomegami Jan 14, 2024
8af01e6
Merge remote-tracking branch 'upstream/main'
jiyunomegami Jan 15, 2024
a464267
Intel HDA: Fix assertion
jiyunomegami Jan 16, 2024
0af4b6b
Merge remote-tracking branch 'upstream/main'
jiyunomegami Jan 16, 2024
64c3a64
Fix invalid serial port message
jiyunomegami Jan 18, 2024
2090648
Revert "Fix invalid serial port message"
jiyunomegami Jan 18, 2024
255b478
Fix Invalid COM port message
jiyunomegami Jan 18, 2024
107d18e
Revert "Fix Invalid COM port message"
jiyunomegami Jan 18, 2024
ab69650
Fix Invalid COM port message
jiyunomegami Jan 18, 2024
e1bf818
Add pcibios_enable_memmap_set_master_all and fix pcibios_enable_*
jiyunomegami Jan 18, 2024
19f29bd
Fix pcibios_enable_memmap_set_master PCI command register width
jiyunomegami Jan 18, 2024
bb78cee
Add fallback to the NULL driver
jiyunomegami Jan 18, 2024
95d63f6
HW MIDI only option /MCOM9
jiyunomegami Jan 18, 2024
835718e
Add YMF driver
jiyunomegami Jan 18, 2024
233e984
Merge remote-tracking branch 'upstream/main'
jiyunomegami Jan 19, 2024
f8d6705
CMI: remove sbpro mixer as the datasheet is misleading. add log for b…
crazii Jan 21, 2024
be5aedf
CMI: remove SBPro mixer from SB16; add log for mixer reads/writes.
crazii Jan 21, 2024
0d2aa03
CMI: remove problematic unmuting FM/PCM, fix log.
crazii Jan 21, 2024
54c87df
CMI: fix logs.
crazii Jan 21, 2024
3278b3e
CMI: remove more mixers.
crazii Jan 21, 2024
9487d7d
CMI: remove logs.
crazii Jan 21, 2024
5af070f
CMI: fix typo.
crazii Jan 21, 2024
9c67330
CMI WIP.
crazii Jan 21, 2024
6c03f98
(1) Now the S/PDIF status bits are set correctly. The copyright bit i…
jiyunomegami Jan 21, 2024
62b5234
Merge remote-tracking branch 'upstream/main'
jiyunomegami Jan 21, 2024
6d1daae
YMF SB (PCM) driver without mixer support
jiyunomegami Jan 23, 2024
b224a10
Merge remote-tracking branch 'upstream/main'
jiyunomegami Jan 23, 2024
dbfd272
Merge remote-tracking branch 'upstream/main' into forupstream2
jiyunomegami Jan 23, 2024
62cf0c1
merge from upstream
jiyunomegami Jan 23, 2024
1e34fe0
Merge remote-tracking branch 'upstream/main' into forupstream2
jiyunomegami Jan 25, 2024
e05ad3a
Change FM/MPU-401 startup message when using hardware
jiyunomegami Jan 25, 2024
9e5e4b6
Merge remote-tracking branch 'upstream/main'
jiyunomegami Jan 25, 2024
e85e207
YMF724 support and YMF754 workarounds
jiyunomegami Jan 27, 2024
dff737f
Use DBG_Logi for MDBG output
jiyunomegami Jan 27, 2024
d831094
Merge branch 'main' into forupstream2
jiyunomegami Jan 27, 2024
6dcd31e
merge upstream CMI changes
jiyunomegami Jan 27, 2024
5267146
YMF driver cleanup
jiyunomegami Jan 27, 2024
268bc96
Place au_cards_fallback_to_null within #ifdef SBEMU blocks
jiyunomegami Feb 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 75 additions & 15 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,61 @@ static const char MAIN_ISR_DOSID_String[] = "Crazii SBEMU Sound Blaster emula
static void MAIN_TSR_InstallationCheck();
static void MAIN_TSR_Interrupt();

uint16_t main_hw_fmport = 0;
#define hw_fm_outb(reg,data) outp(main_hw_fmport+reg,data)
#define hw_fm_inb(reg) inp(main_hw_fmport+reg)

uint16_t main_hw_mpuport = 0;
#define hw_mpu_outb(reg,data) outp(main_hw_mpuport+reg,data)
#define hw_mpu_inb(reg) inp(main_hw_mpuport+reg)

static uint32_t MAIN_OPL3_388(uint32_t port, uint32_t val, uint32_t out)
{
return out ? OPL3EMU_PrimaryWriteIndex(val) : OPL3EMU_PrimaryRead(val);
if (main_hw_fmport) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can determine main_hw_fmport before initialization and install a totally different handler (i.e. MAIN_OPL3_388_HWREMAP() ) to avoid check main_hw_fmport in runtime every time.

Also it will be better if main_hw_fmport is put in mpxplay_audioout_info_s struct, and the init routine will check it and use another trap handler (aka MAIN_OPL3_388_HWREMAP).

In such a way we decouple main from YMF driver, YMF driver only depend on mpxplay/au_cards module, not an extern defined in main.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it a problem for some slow machines if you check main_hw_fmport every time?
I think it is OK to commit it as is now, and improve it later.

There needs to be a way to have two or more cards selected. For example YMF for FM/MIDI and NULL or HDA for sound effects.
You could have options like /SC for sound effects, /FC for FM, /MC for MIDI.

Copy link
Owner

@crazii crazii Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it a problem for some slow machines if you check main_hw_fmport every time?

No, it is not.
As previously mentioned, That is A MONIOR SUGGESTION, and is not required do modify it right now.

But I'll be much better if dependency of main_hw_fmport is removed from main.c. The idea is to treat mpxplay/au_cards as a standalone library, and it should be SELF CONTAINED, WITHOUT ANY INCLUDE/LINKAGE dependencies.
Think about this: if anyone, by any chance, want to use mpxplay/au_cards, he need to define a variable name main_hw_fmport to make the linker pass, which he might no even care; Or he need to modify the source code to remove anything involving main_hw_fmport. Either way it is not a good portable code.

This is already encountered when porting mpxplay into SBEMU. you can find dummy variables in au_base.c line 30:

//dummy symbol to keep original code unmodified
#ifdef __DOS__
#include <dos.h>
void (__far *oldint08_handler)();
volatile unsigned long int08counter;
unsigned long mpxplay_signal_events;
#endif

and au_cards.c, line 146

#ifdef SBEMU
struct mpxplay_audioout_info_s au_infos;
unsigned int playcontrol,outmode = OUTMODE_TYPE_AUDIO;
unsigned int intsoundconfig=INTSOUND_NOINT08|INTSOUND_NOBUSYWAIT,intsoundcontrol;
unsigned long allcpuusage,allcputime;
unsigned int is_lfn_support,uselfn,iswin9x;
#endif

It's understandable that the author of mpxplay didn't predict that his code will be used others, but we can avoid the same problem for SBEMU.
Also please be noted that still it is a minor suggestion and you don't have to change it now, or for yourself, but please confirm if you want change it now.

There needs to be a way to have two or more cards selected. For example YMF for FM/MIDI and NULL or HDA for sound effects.

Yes for now it is. I will be glad if you wanna add this, or if not, I can do that later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Naturally I think you would add some routines card_fm_read, card_fm_write etc. to struct one_sndcard_info.
I can do this later, but I want to clean up the Linux drivers first.
It would be easier for me to merge to/from my fork if this YMF patch gets merged first.

Before this I didn't have any experience with DOS.
I thought since this is a TSR it needs to be fast/simple, and, looking at main.c, thought that a global variable (main_hw_fmport) was OK.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, we can leave it for later. I'm really sorry for keep you waiting so long, I was digging into the doom crash problem and now still be. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the problem with doom? With which card?

Copy link
Owner

@crazii crazii Feb 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the problem with doom? With which card?

The onboard HDA that @hjnijlunsing has, it's a compatibility problem not quite related to the soundcard driver as opl3 works.

Discussed here #13 (comment)

if (out) {
hw_fm_outb(0, val & 0xff);
return val;
} else {
return hw_fm_inb(0);
}
}
return out ? OPL3EMU_PrimaryWriteIndex(val) : OPL3EMU_PrimaryRead(val);
}
static uint32_t MAIN_OPL3_389(uint32_t port, uint32_t val, uint32_t out)
{
return out ? OPL3EMU_PrimaryWriteData(val) : OPL3EMU_PrimaryRead(val);
if (main_hw_fmport) {
if (out) {
hw_fm_outb(1, val & 0xff);
return val;
} else {
return hw_fm_inb(1);
}
}
return out ? OPL3EMU_PrimaryWriteData(val) : OPL3EMU_PrimaryRead(val);
}
static uint32_t MAIN_OPL3_38A(uint32_t port, uint32_t val, uint32_t out)
{
return out ? OPL3EMU_SecondaryWriteIndex(val) : OPL3EMU_SecondaryRead(val);
if (main_hw_fmport) {
if (out) {
hw_fm_outb(2, val & 0xff);
return val;
} else {
return hw_fm_inb(2);
}
}
return out ? OPL3EMU_SecondaryWriteIndex(val) : OPL3EMU_SecondaryRead(val);
}
static uint32_t MAIN_OPL3_38B(uint32_t port, uint32_t val, uint32_t out)
{
return out ? OPL3EMU_SecondaryWriteData(val) : OPL3EMU_SecondaryRead(val);
if (main_hw_fmport) {
if (out) {
hw_fm_outb(3, val & 0xff);
return val;
} else {
return hw_fm_inb(3);
}
}
return out ? OPL3EMU_SecondaryWriteData(val) : OPL3EMU_SecondaryRead(val);
}

static uint32_t MAIN_DMA(uint32_t port, uint32_t val, uint32_t out)
Expand Down Expand Up @@ -144,43 +184,57 @@ static uint32_t MAIN_MPU_330(uint32_t port, uint32_t val, uint32_t out)
c = '\n';
mpu_dbg_ctr = 0;
}
DBG_Log("%02x%c", val, c);
DBG_Logi("%02x%c", val, c);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DBG_Log/DBG_Logi will output log for release builds. do your need a debug log but without the source file/line information?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a hex dump of the raw MIDI data. I think it is a nice feature.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I understand. So it is NOT needed for release builds?
You can add one more specific macro like _LOG() but without file/lines, which will be disabled in release build. Or I can add that and you may use it, we can do that later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It IS intended for release builds.
if you use the option /MDBG2 you can output the MIDI data over the debug serial port at 115200 baud, 3 times the MIDI serial rate of 38400 baud (different from normal MIDI which is 31500 baud.)
You can dump the actual MIDI data that games are using while the music actually being played, without having to intercept it physically.

Copy link
Owner

@crazii crazii Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, cool :)
EDIT: but be ware that when /MDB or /DBG is not specified, it will probably print on the screen, please confirm whether it is expected.
EDIT2: I overlooked the context, you've guarded it with defines, and has variables switches too, it is OK, sorry for that :).

Copy link
Contributor Author

@jiyunomegami jiyunomegami Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is OK to print to the screen if /MDBG is specified but /DBG is not.
BTW, the hexdump uses 3 characters for each MIDI data byte, two for the MIDI data byte, and one more for the space or newline. Ignoring the LF to CRLF conversion in serial.c.
EDIT: That is why you need 3 times the MIDI baud rate.

BTW, is there a good reason to have the LF to CRLF conversion and the baud rate set to 9600?
In my builds I remove the LF to CRLF conversion, since in my Linux terminal using cat or minicom I get extra blank lines with CRLF.
And 9600 is just too slow so I set it to 115200.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might depend on the terminal, for me it needs CRLF to properly turn to next line.
I don't know why the baud rate is set, you may ask @thp who should know about this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably fine to have 115200 and LF only. As @jiyunomegami mentioned, it's up to the terminal on the other side to be configured properly.

}
} else {
DBG_Log("r%x\n", mpu_state);
DBG_Logi("r%x\n", mpu_state);
}
}
#endif
if (out) {
if (main_hw_mpuport) {
hw_mpu_outb(0, (unsigned char)(val & 0xff));
}
ser_putbyte((int)(val & 0xff));
return 0;
} else {
uint8_t val, hwval;
if (main_hw_mpuport) {
hwval = hw_mpu_inb(0);
}
if (mpu_state == 1) {
mpu_state = 0;
return 0xfe;
val = 0xfe;
} else if (mpu_state == 2) {
mpu_state = 4;
return 0xfe;
val = 0xfe;
} else {
return 0;
val = 0;
}
if (main_hw_mpuport) {
val = hwval;
}
return val;
}
}
static uint32_t MAIN_MPU_331(uint32_t port, uint32_t val, uint32_t out)
{
#if MPU_DEBUG
if (mpu_debug) {
if (out) {
DBG_Log("s%x\n", val);
DBG_Logi("s%x\n", val);
} else {
if (mpu_dbg_ctr < 10 && mpu_state <= 2) {
DBG_Log("sr%x\n", mpu_state);
DBG_Logi("sr%x\n", mpu_state);
mpu_dbg_ctr++;
}
}
}
#endif
if (out) {
if (main_hw_mpuport) {
hw_mpu_outb(1, (unsigned char)(val & 0xff));
}
if (val == 0xff) { // Reset
#if MPU_DEBUG
mpu_dbg_ctr = 0;
Expand All @@ -194,6 +248,10 @@ static uint32_t MAIN_MPU_331(uint32_t port, uint32_t val, uint32_t out)
}
return 0;
}
if (main_hw_mpuport) {
uint8_t hwval = hw_mpu_inb(1);
return hwval;
}
if ((mpu_state & 3) == 0) {
return 0x80;
} else {
Expand Down Expand Up @@ -335,7 +393,7 @@ struct MAIN_OPT
"/SC", "Select sound card index in list (/SCL)", 0, MAIN_SETCMD_HIDDEN,
"/R", "Reset sound card driver", 0, MAIN_SETCMD_HIDDEN,
"/P", "UART mode MPU-401 IO address (default 330) [*]", 0x330, 0,
"/MCOM", "UART mode MPU-401 COM port (1=COM1, 2=COM2, 3=COM3, 4=COM4, otherwise base address)", 0, 0,
"/MCOM", "UART mode MPU-401 COM port (1=COM1, 2=COM2, 3=COM3, 4=COM4, 9:HW MPU only, otherwise base address)", 0, 0,
"/COML", "List installed COM ports", 0, MAIN_SETCMD_HIDDEN,
#if MPU_DEBUG
"/MDBG", "Enable MPU-401 debugging (0 to disable, 1 or 2 to enable)", 0, 0,
Expand Down Expand Up @@ -744,7 +802,8 @@ int main(int argc, char* argv[])
}

//OPL3EMU_Init(aui.freq_card);
printf("OPL3 emulation at port 388: ");
char *emutype = (main_hw_fmport != 0) ? "hardware" : "emulation";
printf("OPL3 %s at port 388: ", emutype);
MAIN_Print_Enabled_Newline(true);
}

Expand All @@ -762,8 +821,9 @@ int main(int argc, char* argv[])
return 1;
}

printf("MPU-401 UART emulation at address %x: ",
MAIN_Options[OPT_MPUADDR].value);
char *emutype = (main_hw_mpuport != 0) ? "hardware" : "emulation";
printf("MPU-401 UART %s at address %x: ",
emutype, MAIN_Options[OPT_MPUADDR].value);
MAIN_Print_Enabled_Newline(true);
}

Expand Down
2 changes: 2 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ CARDS_SRC := mpxplay/au_cards/ac97_def.c \
mpxplay/au_cards/sc_sbliv.c \
mpxplay/au_cards/sc_via82.c \
mpxplay/au_cards/sc_sbxfi.c \
mpxplay/au_cards/sc_null.c \
mpxplay/au_cards/sc_ymf.c \

SBEMU_SRC := sbemu/dbopl.cpp \
sbemu/opl3emu.cpp \
Expand Down
28 changes: 25 additions & 3 deletions mpxplay/au_cards/au_cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ extern one_sndcard_info VIA82XX_sndcard_info;
extern one_sndcard_info SBLIVE_sndcard_info;
extern one_sndcard_info CMI8X38_sndcard_info;
extern one_sndcard_info EMU20KX_sndcard_info;
extern one_sndcard_info YMF_sndcard_info;
extern one_sndcard_info YMFSB_sndcard_info;
#ifndef SBEMU
extern one_sndcard_info ESS_sndcard_info;
extern one_sndcard_info WSS_sndcard_info;
Expand All @@ -71,14 +73,20 @@ extern one_sndcard_info WINDSOUND_sndcard_info;
extern one_sndcard_info WINWAVOUT_sndcard_info;
#endif

extern one_sndcard_info NON_sndcard_info;
#ifndef SBEMU
extern one_sndcard_info WAV_sndcard_info;
extern one_sndcard_info NON_sndcard_info;
extern one_sndcard_info TST_sndcard_info;
extern one_sndcard_info NUL_sndcard_info;
#endif

static one_sndcard_info *all_sndcard_info[]={
#ifdef AU_CARDS_LINK_YMF
&YMFSB_sndcard_info,
#endif
#ifdef AU_CARDS_LINK_YMF
&YMF_sndcard_info,
#endif
#ifdef AU_CARDS_LINK_SB16
&SB16_sndcard_info,
#endif
Expand Down Expand Up @@ -149,6 +157,7 @@ unsigned int playcontrol,outmode = OUTMODE_TYPE_AUDIO;
unsigned int intsoundconfig=INTSOUND_NOINT08|INTSOUND_NOBUSYWAIT,intsoundcontrol;
unsigned long allcpuusage,allcputime;
unsigned int is_lfn_support,uselfn,iswin9x;
unsigned char au_cards_fallback_to_null = 0;
#endif

static aucards_writedata_t aucards_writedata_func;
Expand Down Expand Up @@ -341,8 +350,21 @@ void AU_init(struct mpxplay_audioout_info_s *aui)
goto err_out_auinit;
}
if(!aui->card_handler && !(aui->card_controlbits&AUINFOS_CARDCNTRLBIT_SILENT)){
pds_textdisplay_printf("No supported soundcard found!");
goto err_out_auinit;
#ifdef SBEMU
if (au_cards_fallback_to_null) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good to use SBEMU on au_cards_fallback_to_null in au_cards.h in my perspective, if it is guarded in the header, it probably need a SBEMU switch in au_cards.c too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this commit:
commit 268bc96
Place au_cards_fallback_to_null within #ifdef SBEMU blocks

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, thanks

static one_sndcard_info *no_sndcard_info[]={&NON_sndcard_info};
asip=&no_sndcard_info[0];
aui->card_handler=*asip;
aui->card_test_index = 1;
carddetect(aui,0);
pds_textdisplay_printf("Using NULL driver");
} else {
#endif
pds_textdisplay_printf("No supported soundcard found!");
goto err_out_auinit;
#ifdef SBEMU
}
#endif
}
}

Expand Down
6 changes: 6 additions & 0 deletions mpxplay/au_cards/au_cards.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ typedef struct au_cardconfig_v0154_s{
#define AU_CARDS_LINK_IHD 1
#define AU_CARDS_LINK_SBLIVE 1
#define AU_CARDS_LINK_VIA82XX 1
#define AU_CARDS_LINK_YMF 1
#endif
#ifdef AU_CARDS_LINK_WIN
#define AU_CARDS_LINK_WINDSOUND 1
Expand All @@ -187,6 +188,7 @@ typedef struct au_cardconfig_v0154_s{
#define AU_CARDS_LINK_IHD 1
#define AU_CARDS_LINK_SBLIVE 1
#define AU_CARDS_LINK_VIA82XX 1
#define AU_CARDS_LINK_YMF 1
#endif
#endif

Expand Down Expand Up @@ -293,6 +295,10 @@ extern unsigned int AU_cardbuf_space(struct mpxplay_audioout_info_s *aui);
#endif
extern int AU_writedata(struct mpxplay_audioout_info_s *);

#ifdef SBEMU
extern unsigned char au_cards_fallback_to_null;
#endif

#ifdef __cplusplus
}
#endif
Expand Down
Loading
Loading