VOGONS


SBVGM (DOS) VGM Player

Topic actions

Reply 100 of 530, by Scali

User metadata
Rank l33t
Rank
l33t
NewRisingSun wrote:

The reason that manipulating port 0x61 directly is bad is that on the Tandy 1000 TX and TL, which don't need the activation via multiplexer, the relevant bits of port 0x61 control the keyboard clock line, which you should not mess around with unneccessarily.

The same goes for a 5160 (and probably most later PCs and clones).
It's an extra thing to take care of with the Tandy sound clone card we have, and the patches we're trying to do to games to enable Tandy/PCjr audio on non-Tandy/PCjr systems.
My own VGM player originally was made only for PCjr, and I found that running it on my 5160 messed it up (which is why I suggested OPLx to use a machine check to make sure you're running on a PCjr before trying to mess with it).
I didn't know there was an int routine for it on Tandy/PCjr though.
Thanks for pointing that out, I'll include it in my player as well.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 101 of 530, by NewRisingSun

User metadata
Rank Oldbie
Rank
Oldbie

@OPLx: The pitch is too low when playing back SAA1099-writes containing VGM files.

Apparently you are correcting for vanilla DOSBox getting the SAA1099 base clock wrong. That however makes it sound wrong on DOSBox builds that have this corrected, and has the additonal effect of playing .VGM files that were captured from within DOSBox (for example using my .VGM logging patch which captures OPL2/OPL3/SAA1099/SN7689/PC Speakear/SB DAC/Tandy DAC, not publicly released so far) differently than how they originally sounded even in the same emulator. Generally, software should not be written around emulator bugs, or at least make it optional.

Attached file is captured from Creative's "The music revolution is here" demo and plays back at the correct pitch in VGMplay/in_vgm. The full capture of the song amounts to 900 KB, or 600 kB after running vgm_cmp (which makes the file sound wrong), and thus will not load in SBVGM, which I do consider a severe limitation.

Also, the first few notes of attached BRUCELEE.VGM are played incorrectly, even after taking the pitch shift into account. Since this is my own player and arrangement of the song (the original game only supports the TI chip and sounds like crap, high-pitched shrieking without any note envelopes), one might be tempted to blame me and my original player routine, but the original routine sounds fine in DOSBox, and the captured .VGM file also plays correctly in other players. Maybe it's a computation error in your base block adjustment routine?

Attachments

  • Filename
    BRUCELEE.zip
    File size
    4.86 KiB
    Downloads
    108 downloads
    File license
    Fair use/fair dealing exception
  • Filename
    APLAY.zip
    File size
    18.64 KiB
    Downloads
    117 downloads
    File license
    Fair use/fair dealing exception

Reply 102 of 530, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie
NewRisingSun wrote:

@OPLx: The pitch is too low when playing back SAA1099-writes containing VGM files.

Apparently you are correcting for vanilla DOSBox getting the SAA1099 base clock wrong. That however makes it sound wrong on DOSBox builds that have this corrected, and has the additonal effect of playing .VGM files that were captured from within DOSBox (for example using my .VGM logging patch which captures OPL2/OPL3/SAA1099/SN7689/PC Speakear/SB DAC/Tandy DAC, not publicly released so far) differently than how they originally sounded even in the same emulator. Generally, software should not be written around emulator bugs, or at least make it optional.

Gameblaster emulation is not usually so important if it appears to work. At least the pitch is now fixed in ScummVM.
DosBox still assumes the SAA chips run at emulated 31250 Hz sampling rate, but in reality it's about 27965 Hz.
So tone number 3 on octave 4 is closest to 440Hz A4 reference tone, about 440.4 Hz 😀
I believe it does not properly mix noise + tone, but it appears no game uses it so there's no material.

I have toyed with the idea of writing a more correct emulator, but it would be so obscure no one would use it and there's still no material to play 😀
And it would contain the same resampling problem than with PIT emulation, except SAA chips tone generators may work at 3.579 MHz internally, but it would require further research.
Also, the SAA chip output is analog, so reverse engineering is not so simple than with chips that have digital output.

Reply 103 of 530, by OPLx

User metadata
Rank Member
Rank
Member
NewRisingSun wrote:
@OPLx: The pitch is too low when playing back SAA1099-writes containing VGM files. […]
Show full quote

@OPLx: The pitch is too low when playing back SAA1099-writes containing VGM files.

Apparently you are correcting for vanilla DOSBox getting the SAA1099 base clock wrong. That however makes it sound wrong on DOSBox builds that have this corrected, and has the additonal effect of playing .VGM files that were captured from within DOSBox (for example using my .VGM logging patch which captures OPL2/OPL3/SAA1099/SN7689/PC Speakear/SB DAC/Tandy DAC, not publicly released so far) differently than how they originally sounded even in the same emulator. Generally, software should not be written around emulator bugs, or at least make it optional.

Attached file is captured from Creative's "The music revolution is here" demo and plays back at the correct pitch in VGMplay/in_vgm. The full capture of the song amounts to 900 KB, or 600 kB after running vgm_cmp (which makes the file sound wrong), and thus will not load in SBVGM, which I do consider a severe limitation.

Also, the first few notes of attached BRUCELEE.VGM are played incorrectly, even after taking the pitch shift into account. Since this is my own player and arrangement of the song (the original game only supports the TI chip and sounds like crap, high-pitched shrieking without any note envelopes), one might be tempted to blame me and my original player routine, but the original routine sounds fine in DOSBox, and the captured .VGM file also plays correctly in other players. Maybe it's a computation error in your base block adjustment routine?

I actually asked about this issue a while back on the thread here. I worked around the issue in DOSBox 0.74 because I didn't want to see more incorrect pitched Gameblaster music on YouTube. 😀 If you change the "DOSBox FakeBIOS v1.0" string in your build to something else, the current version of the player will work. The player works properly on actual hardware so I need to take a look and see what's wrong with the pitch correction as this could be a bug that could affect SAA1099 VGM files that were captured with an 8 MHz base clock rather than the 7.15909 MHz used by the Gameblaster.

The player should be able to handle VGMs of large size if XMS support available and the -x command line option is specified. If it still does not work, is there a place where I can get the 900 KB VGM do debug with? The link to VGMRips forum requires logging in. Is there another location that the TI file is at?

Reply 104 of 530, by NewRisingSun

User metadata
Rank Oldbie
Rank
Oldbie

Here is the 900K VGM file from that Creative demo. The TI file from Bruce Lee is not actually relevant to the SAA emulation (I was talking about the VGM of my SAA1099 recreation of the music), but I have attached the pack nonetheless.

Attachments

Reply 105 of 530, by OPLx

User metadata
Rank Member
Rank
Member
NewRisingSun wrote:

Here is the 900K VGM file from that Creative demo. The TI file from Bruce Lee is not actually relevant to the SAA emulation (I was talking about the VGM of my SAA1099 recreation of the music), but I have attached the pack nonetheless.

Thank you for the files! I'll go ahead see where the problems are. 😀

Reply 106 of 530, by OPLx

User metadata
Rank Member
Rank
Member
Jepael wrote:
Gameblaster emulation is not usually so important if it appears to work. At least the pitch is now fixed in ScummVM. DosBox stil […]
Show full quote

Gameblaster emulation is not usually so important if it appears to work. At least the pitch is now fixed in ScummVM.
DosBox still assumes the SAA chips run at emulated 31250 Hz sampling rate, but in reality it's about 27965 Hz.
So tone number 3 on octave 4 is closest to 440Hz A4 reference tone, about 440.4 Hz 😀
I believe it does not properly mix noise + tone, but it appears no game uses it so there's no material.

I have toyed with the idea of writing a more correct emulator, but it would be so obscure no one would use it and there's still no material to play 😀
And it would contain the same resampling problem than with PIT emulation, except SAA chips tone generators may work at 3.579 MHz internally, but it would require further research.
Also, the SAA chip output is analog, so reverse engineering is not so simple than with chips that have digital output.

I haven't looked at the emulator code, but there some issues how the envelope generators are emulated (it is there, but there's a bug with how they are activated). Have you seen SAASound? It's a very accurate SAA1099 emulator, albeit tied to an 8MHz base clock. If you have the time (and of course the desire!), I would ask you to please consider making a more accurate one as there may come be programs in the future that end up using the "hidden" features on the Gameblaster. SBVGM emulates the NES' APU chip by taking advantage of the envelope generators on the SAA1099 so it's possible to hear NES VGMs on the SAA1099.

Reply 107 of 530, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie
OPLx wrote:

I haven't looked at the emulator code, but there some issues how the envelope generators are emulated (it is there, but there's a bug with how they are activated). Have you seen SAASound? It's a very accurate SAA1099 emulator, albeit tied to an 8MHz base clock. If you have the time (and of course the desire!), I would ask you to please consider making a more accurate one as there may come be programs in the future that end up using the "hidden" features on the Gameblaster. SBVGM emulates the NES' APU chip by taking advantage of the envelope generators on the SAA1099 so it's possible to hear NES VGMs on the SAA1099.

I recall there was some improvement in progress for DosBox Gameblaster emulation, but I don't know the details.

@NewRisingSun: Since you seem to have the tool, could you capture Monkey Island Gameblaster music? Because I would have to do it non-realtime (includes hacking sound driver to output stuff to parallel port, and capturing that on another PC with logic analyzer...)

Reply 109 of 530, by OPLx

User metadata
Rank Member
Rank
Member
NewRisingSun wrote:

Also, the first few notes of attached BRUCELEE.VGM are played incorrectly, even after taking the pitch shift into account. Since this is my own player and arrangement of the song (the original game only supports the TI chip and sounds like crap, high-pitched shrieking without any note envelopes), one might be tempted to blame me and my original player routine, but the original routine sounds fine in DOSBox, and the captured .VGM file also plays correctly in other players. Maybe it's a computation error in your base block adjustment routine?

@NewRisingSun: Your player is correct. I've found and fixed that bug SAA1099 frequency adjustment octave cache. I'll take a look at the memory issue next.

Reply 110 of 530, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie
NewRisingSun wrote:

I have made DOSBox-VGM available, so you now have the ability to capture it yourself.

Well, there's always something.
This time, the latest compiler available from binary packages is g++-4.8 which does not support -std=gnu++14 yet.
But otherwise this was simple, everything went well and I was able to compile DoxBox SVN rev 4000 just fine, managed to compile it with debugger, and even added your patches successfully.

May I ask if there's a simple way to port this to some earlier standard?

Reply 111 of 530, by NewRisingSun

User metadata
Rank Oldbie
Rank
Oldbie

What platform are you compiling for? Because mingw32, which I am using, currently comes with g++ 5.3.0.

I use a smart pointer for the VGMCapture object to make sure it is properly released, and the .VGM file is written, regardless of how DOSBox exits. You need at least -std=gnu++11 for this, otherwise the changes are going to be more involved.

One C++14 feature I use is make_unique in dosbox.cpp, which I'm told can be added manually to C++11 using

template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

Then there's

for (auto& prev: previousPCMs) {

in vgmcapture.cpp, which I *think* (without having tried to compile it) must be rewritten as

for(std::vector<struct previousPCM>::iterator prev = previousPCMs.begin(); prev!= previousPCMs.end(); prev++) {

You're getting the idea of why I find C++14 rather attractive.

Reply 112 of 530, by OPLx

User metadata
Rank Member
Rank
Member

v1.11 is released here. @NewRisingSun: I took into consideration your suggestion about not working around the SAA1099 frequency bug in DOSBox 0.74 and went ahead and removed the functionality all together. Hopefully there will be a DOSBox update in the near future as I had pointed out that bug over two years ago.

Reply 113 of 530, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie
NewRisingSun wrote:
What platform are you compiling for? Because mingw32, which I am using, currently comes with g++ 5.3.0. […]
Show full quote

What platform are you compiling for? Because mingw32, which I am using, currently comes with g++ 5.3.0.

I use a smart pointer for the VGMCapture object to make sure it is properly released, and the .VGM file is written, regardless of how DOSBox exits. You need at least -std=gnu++11 for this, otherwise the changes are going to be more involved.

One C++14 feature I use is make_unique in dosbox.cpp, which I'm told can be added manually to C++11 using

template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

Then there's

for (auto& prev: previousPCMs) {

in vgmcapture.cpp, which I *think* (without having tried to compile it) must be rewritten as

for(std::vector<struct previousPCM>::iterator prev = previousPCMs.begin(); prev!= previousPCMs.end(); prev++) {

You're getting the idea of why I find C++14 rather attractive.

No, sorry I don't 😁 Well, I do see the point, but I rarely use C++ anyway, so it took some time for me to even dig out what's this make_unique about. At first I had crashing issues so I just changed all those to just pointers to object and used plain old new and delete, but it still kept crashing, see below.

I have Linux 64-bit, using Linux Mint 17.3, it's stock compiler is 4.4.8 that I am using now. The latest compiler packages I tried were 4.8.4, from stock software repositories, but it compiles just fine now with 4.4.8.

I tried those modifications (the auto& makes an instance you can use directly as prev.something but the prev iterator is a pointer to instance so those needed to be changed to prev->something).

And, finally, it always crashed. The

strcpy(header.id, "Vgm ");

line caused it to crash with a buffer overflow. I did not see the compiler warning at first but after debugging for some hours I did, it said it will always cause a buffer overflow. Fixing that, I have a VGM file now!

Thanks for your support on this, I really do appreciate it. Now this will enable me to get forward to experiment with some Gameblaster emulation.

Reply 114 of 530, by NewRisingSun

User metadata
Rank Oldbie
Rank
Oldbie

Why would that line crash with a buffer overflow? There is the implicit fifth byte ('\0') after the "Vgm ", which will overwrite the first byte of header.rofsEOF, but that is okay since rofsEOF is filled with actual information immediately afterwards. Unless you are enabling some hyper-aggressive bounds-checking in the compiler which does not take that into consideration. Does "crash" mean the compilation stopped with an error message, or the built file exited with a protection fault when run?

In any case, I am replacing it with

memcpy(header.id, "Vgm ", 4);

which should humor any bounds-checking compiler.

At first I had crashing issues so I just changed all those to just pointers to object and used plain old new and delete, but it still kept crashing, see below.

Then you might need to make sure to always press Ctrl-Alt-F7 again to stop VGM logging, otherwise the file might not get actually written, or you must manually call delete at any point where DOSBox may quit.

Last edited by NewRisingSun on 2017-01-07, 14:41. Edited 1 time in total.

Reply 115 of 530, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

Crash the built file with buffer overflow error, right when stopping the capture. The compiled did warn about it beforehand, but I just did not see it from all the rest of the build messages.

I am not enabling any extra checks myself, it's whatever comes with the 64-bit OS and dosbox build environment.
Yeah, I also don't see why it does that even if the fifth byte does overwrite the next member and the struct is packed.

Reply 116 of 530, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

If you are having envelope issues while playing SAA chip VGMs, I think I figured out why.

VGM is a register dump format just like many others, i.e. it only tracks when register data is written to some register index, and for each data write event to chip there is always a register and data pair.

For SAA chips, when envelopes are in external triggered mode, the external triggering is performed just by writing the register index (0x18 or 0x19) to index port.
So imagine a program that only wants to generate triangle wave in software by writing register index port only, it never writes register data port so it does not get logged into VGM file.

OK, i thought a workaround would be to log a register write into VGM file with previous data when registers 0x18 and 0x19 are accessed.
Except that when logging, we cannot know if a program is only triggering the envelope by writing 0x18 or 0x19 to register index port, or will it next write the register data port as well, so in the VGM file there would be a double write to this register, and this will trigger the envelope twice.

Sure, the complete solution would be to add SAA envelope triggering commands to VGM file, that would end up as single write to register index port only (0x18 and 0x19), and VGM file logging should cache any writes to register index ports with values 0x18 and 0x19 to know if next write is another register index write (it was envelope trigger only) or register data write (it was really writing new data to register 0x18 or 0x19 as well).

I don't know if any other chip behaves like this as well, but some programs that play PCM by writing only to OPL chip data register have a similar issue as well, there is also a register and data pair logged for each data port write in VGM file, and it's up to the VGM file player to rewrite the register index port unnecessarily or if it knows it can skip writing register index, so it can only concentrate on writing the data port.

Reply 117 of 530, by OPLx

User metadata
Rank Member
Rank
Member

The present SAA1099 emulator used by DOSBox, VGMPlay (from VGMRips.net), and likely MAME doesn't support proper envelope generator emulation. It is kind of there, but I believe there is a bug in it's implementation (on how it gets activated). Once the envelope generator is enabled, the two ways to it either to use the internal envelope clock (setting bit 5 of registers 0x18 or 0x19 at 0) or via an external clock (bit 5 set to 1) as you mentioned above.

How to control the envelope generators is a bit different from most other chips as the usage effectively uses two channels (1&2 or 3&4) to control the envelope generator. One then has the option (via the mixer) and volume controls to mix in the square waveform on top of the envelope generator. Looking at the data sheet, first two waveforms seem useless, but actually can be used creatively in conjunction with the normal square waveform or the other envelope generator waveforms.

If you download Super Mario Bros. and play any of the VGMs with SBVGM on real hardware, you will hear the triangle waveform.

To my knowledge there aren't any arcade VGMs or Gameblaster games that use the envelope generators or play back PCM samples on the SAA1099. Many of the music found on the Sam Coupe platform use the envelope generators or play back samples, but (so far) there aren't any VGMs captured from that platform.

Here are the register settings to enable the envelope generator (using the internal clock). The assumption is that the SAA1099 starts out with all it's registers cleared to 0.

REG : VALUE
0x1C: 0x01 ; sound enable
0x02: 0xFF ; set channel 2 amplitude
0x09: 0x3A ; set channel 1 frequency
0x10: 0x50 ; set channel 1 octave
0x18: 0x9A ; enable envelope generator 0, with internal clock & repeating triangle waveform with 3 bits for envelope control

The values above will activate envelope generator 0 and with only the triangle waveform audible. Frequency control of the envelope generators are done via channels 1 and 4 (for envelope generators 0 and 1 respectively).

Unfortunately with the present DOSBox SAA1099 emulator has a bug that the frequency enable bit for channel 2 or channel 5 have to be set in order for the envelope generator output to be audible ... which is not how the real hardware actually behaves. Enabling the frequency output on top of the envelope generator output naturally mixes the selected envelope generator waveform with the square waveform and one won't hear what one is initially expecting.

I'm really surprised that Creative Labs didn't document this feature in the C/MS programming manual. There are so many interesting things that can be done with the chip. At least the Sam Coupe scene managed to tap into some of it's power. 😀

I have not had a chance to examine the source code, but if I find the problem spot before someone else does, I will let you know.

Last edited by OPLx on 2017-01-08, 11:20. Edited 1 time in total.

Reply 118 of 530, by ElBrunzy

User metadata
Rank Oldbie
Rank
Oldbie

I see you chat alot about coding asm and C, did you decided to release you source code? What do you use to compile it ? djgpp ? I'm eager to read your source code, I prefer to do that rather then read a book. I'm in my bed now under my curtain now, but I look forward to use your software tomorrow on my free day!

Reply 119 of 530, by OPLx

User metadata
Rank Member
Rank
Member
ElBrunzy wrote:

I see you chat alot about coding asm and C, did you decided to release you source code? What do you use to compile it ? djgpp ? I'm eager to read your source code, I prefer to do that rather then read a book. I'm in my bed now under my curtain now, but I look forward to use your software tomorrow on my free day!

I haven't released the player source yet (I still need to make time to clean up some of it). Most of the programming conversation is about work that NewRisingSun did to add VGM capture to his build of DOSBox. The compiler that I am using is the DOS version of Open Watcom v1.9.

I wouldn't think of the source code as a means to learn how to program, but suppose the source code could be used as a means to just see one approach to how to implement a VGM player. Because it is written mostly in C, it is far from being optimal, but it ends up requiring less time.