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

Conversation

jiyunomegami
Copy link
Contributor

No description provided.

jiyunomegami and others added 30 commits January 4, 2024 04:54
…ufpos, should print continually on screen after TSR for DEBUG build.
@crazii
Copy link
Owner

crazii commented Jan 27, 2024

It's really great! please wait while I have a simple review.

@crazii
Copy link
Owner

crazii commented Jan 31, 2024

Thanks for your great work!
There're some minor suggestions and please confirm whether you like to change them.
if you're not suitable to do it, will you agree that I slightly modify it after merge?

@jiyunomegami
Copy link
Contributor Author

Please let me know your suggestions.
There are some other changes that I made, related to the other Linux drivers, so it may be best if I do it.

@crazii
Copy link
Owner

crazii commented Feb 1, 2024

Please let me know your suggestions.

I added some review comments on your change, can you check it?

EDIT: it's not related to linux drivers but to main_hw_fmport .

@jiyunomegami
Copy link
Contributor Author

I looked all over but I can't find your comments.
Please tell me where/how to view them.

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)

@@ -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.

@@ -341,8 +350,17 @@ 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;
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

@crazii
Copy link
Owner

crazii commented Feb 1, 2024

I looked all over but I can't find your comments. Please tell me where/how to view them.

Sorry :), I forget submitting the reviews, now you can see it.

@crazii
Copy link
Owner

crazii commented Feb 1, 2024

BTW are you located in Japan? I guessed by your id, if you are, I think we share a similar time zone which is convenient for both of us :).

@jiyunomegami
Copy link
Contributor Author

Yes, Japan. I had some free time to work on this over the new year holidays (around Jan. 1st here.)
I see your comments now, will respond later.

I have a question:
The Trident 4D wave card cannot use DMA addresses above 0x40000000 (over 30 bits.)
For example, I saw that the address gotten from pds_xms_alloc was 0xD97DD000.
With that address, all you get is noise.
When I use himemx /MAX=32768 I got a lower address 0x00511000, and proper sound.

Is there a way to get a lower address without limiting it with himemx options etc?
I know that the Yamaha DSDMA has problems on modern systems if you don't use /MAX=32768 so this might be a related issue.

@crazii
Copy link
Owner

crazii commented Feb 1, 2024

I remember there's a himemex2 wich allocates memory from low address. It comes with himemex in the original release, can you check that?

@crazii crazii merged commit c5397ce into crazii:main Feb 2, 2024
1 check passed
@jiyunomegami
Copy link
Contributor Author

Thanks. I do get lower addresses with himemx2.
I was using a 4GB stick of RAM. Now with 1GB I don't get anything over 0x40000000.

On this machine it is possible to allocate multiple times until you get a good address. I don't know if the BIOS has anything to do with it.

with over 4GB of RAM it goes something like this:
DMA buffer physical address: D9821000
retrying DMA buffer physical address: 00111000
retrying DMA buffer physical address: 2022C000
retrying DMA buffer physical address: 42800000
retrying DMA buffer physical address: D9825000
retrying DMA buffer physical address: 00115000
retrying DMA buffer physical address: 20230000
retrying DMA buffer physical address: 42804000
retrying DMA buffer physical address: D9829000
retrying DMA buffer physical address: 00119000
retrying DMA buffer physical address: 20234000
retrying DMA buffer physical address: 42808000
retrying DMA buffer physical address: D982D000
retrying DMA buffer physical address: 0011D000
retrying DMA buffer physical address: 20238000
retrying DMA buffer physical address: 4280C000
retrying DMA buffer physical address: D9831000
retrying DMA buffer physical address: 00121000
retrying DMA buffer physical address: 2023C000
retrying DMA buffer physical address: 42810000

@jiyunomegami
Copy link
Contributor Author

jiyunomegami commented Feb 2, 2024

For the retry logic, I had to add MDma_alloc_cardmem_noexit, since MDma_alloc_cardmem calls exit when the allocation fails.
Is there a reason for that? Can we just remove the exit call and have it return NULL?

@crazii
Copy link
Owner

crazii commented Feb 2, 2024

Have you freed the previously allocated memory before retry? If not, then it will finally get more lower, but will leak/waste memories. If yes, I don't know why it behaves that way, it's weird. you might read the readme of himemex to know more about its allocation strategy.

The original routine assume that if one allocation failed, there's something wrong with memory allocation or not enough memory, so it simply exists.

I think you can return NULL but for other drivers it sill need exist from outside because the program is unable to run.
or you can add one address limit parameter, somthing like MDma_alloc_cardmem_with_base_limit which performs the retry in it, and exit if retry failed, and MDma_alloc_cardmem calls to MDma_alloc_cardmem_with_base_limit with a max limit of 0xFFFFFFFF.

@jiyunomegami
Copy link
Contributor Author

jiyunomegami commented Feb 2, 2024

OK. I will add a new function. I think it is OK to simply add a function that returns NULL on failure, since that is what the Linux drivers expect.
You can't free the allocated memory until you get a good address. Since the addresses of freed memory get reused.
When testing how many allocations are possible, I could only allocate 40-50 times until it failed.
I was only allocating 1 page (4096 bytes) at a time so I guess it is some limitation of XMS.

@crazii
Copy link
Owner

crazii commented Feb 2, 2024

You can't free the allocated memory until you get a good address. Since the addresses of freed memory get reused.

Agreed. By the way of the retry, the memory cannot be freed before you get a valid address, but it will better to free them all after you get one.
BTW you can allocate large blocks in multiple pages if the base limit is far slow from returned, anyway the retry logic is under your control and the retry functions is only used by Trident for now ( might be needed by more cards, let's wait and see)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants