Skip to content

DOSBox-VGM

Technical discussion about the VGM format, and all the software you need to handle VGM files.

Moderator: Staff

DOSBox-VGM

Post by NewRisingSun2 »

Attached find my patch to DOSBox which directly logs to .VGM files instead of .DRO files. The program logs writes to the Tandy 1000/PCjr's SN76496 chip, the Game Blaster (SAA1099), the OPL2/Dual OPL2/OPL3 chip, the PC speaker (via an AY-3-8910), and the Sound Blaster and Tandy SL/TL/RL DACs (via an YM2612). DAC and PC speaker are only logged if "capturepcm" and "capturespeaker" in the [dosbox] section of DOSBox.conf are set to "true", respectively; they are "false" by default, and can only be changed from the config file, not within a DOSBox session from the command line. I have only added PC speaker support for that one game (4D Boxing) that uses it as a fourth PSG channel, but theoretically one could also use it to create a .VGM pack of scratchy sound effects from Commander Keen episodes 1-3. Similarly, I have added DAC logging only for the few games that use it for drums; therefore, it only works with single-cycle 8-bit transfers when the whole sample in memory at the time that the DMA transfer is started (i.e. no double-buffering).

The source code diff also incorporates my correction to the Game Blaster base clock, my patch adding support for Tandy 1000 direct DAC writes, and my patch correcting the interpretation of SN76496 frequency register value 0. As mentioned in one of these discussion threads, when using the Tandy DAC, "sbtype=" should be set to "none" in the [sblaster] section of DOSBox.conf. The source code diff is against SVN r4000, as revisions r4002 and r4003 from two days ago made some changes to the mixer code that break my Tandy DAC code. Just download SVN r4003 and replace mixer.cpp and mixer.h with those from r4000. As I am using a few C++14 features, before compiling, you need to re-run "configure" with the CPPFLAGS="-std=gnu++14" option, e.g.

Code: Select all

./configure --enable-core-inline LDFLAGS="-static-libgcc -static-libstdc++ -s" CPPFLAGS="-std=gnu++14"
The default key to start capturing is still Ctrl+Alt+F7; even the name in the key bindings ("mapper") file is still "hand_caprawopl", so I wouldn't have to change my key binding file. I tried to start logging in the middle of a 4-OP FM song, and the playback still seemed correct, so I hope I did the register cache business correctly, and I have taken care that no OPL register writes are filtered (i.e. no implicit vgm_cmp).
Attachments
DOSBox-VGM build.zip
Win32 build of DOSBox-VGM
(1.57 MiB) Downloaded 1072 times
r4000-vgmcapture.zip
Source diff against DOSBox SVN r4000
(15.45 KiB) Downloaded 735 times
  • User avatar
  • MaliceX Offline
  • Posts: 226
  • Joined: 2012-09-29, 11:45:48
  • Location: Australia
  • Contact:

Post by MaliceX »

beastly work. i will have a look at this when i have some free time to do some tests. :) thanks for your efforts!
-dj.tuBIG/MaliceX
  • Tom Offline
  • Ragequit Member
    Ragequit Member
  • Posts: 496
  • Joined: 2011-11-30, 17:26:44
  • Location: Italy
  • Contact:

Post by Tom »

Awesome work, now we only need someone to rip the Tandy version of Thexder's main music so I'll have something to listen on infinite loop.

I still think the PC Speaker should be logged properly into a separate chip with dedicated commands instead of using a workaround, though, just like I'm not sure if using the YM2612 only for its DAC is a good idea, how hard would it be to add a generic "PCM stream" chip to be used in such cases?
Also known as nineko.

Post by NewRisingSun2 »

Tom wrote:Awesome work, now we only need someone to rip the Tandy version of Thexder's main music so I'll have something to listen on infinite loop.
Done.
Tom wrote:I still think the PC Speaker should be logged properly into a separate chip with dedicated commands instead of using a workaround,
For PC speaker logging, that would require the following commands for writing period and mode to Programmable Interval Timer counters 0 and 2 (command numbers are hypothetical):
  • 0x30 xx: Write byte xx to 8254 Programmable Interval Timer (PIT) Counter 0 Register (I/O address 0x40)
  • 0x31 xx: Write byte xx to 8255 Programmable Peripherial Interface (PPI) System Control Port (I/O address 0x61, only bits 0 and 1 are relevant)
  • 0x32 xx: Write byte xx to 8254 Programmable Interval Timer (PIT) Counter 2 Register (I/O address 0x42)
  • 0x33 xx: Write byte xx to 8254 Programmable Interval Timer (PIT) Control Word Register (I/O address 0x43)
Counter 0 is necessary when a program uses the PC speaker for sample playback using Pulse Width Modulation.

The bigger problem is that for programs that do Pulse Width Modulation manually without the PIT by waiting for a small number of CPU cycles between I/O address 0x61 writes (Ultima II Sierra On-Line version), one would need to have sub-sample timing accuracy. Another solution for that issue would be to indeed just add a generic PCM command as you proposed, including one for generic 16 bit PCM, and then I could simply use Blip_Buffer to convert those high-frequency PC Speaker writes directly into samples. I had done that at one point, but removed it since any gain in quality compared to the current code was lost by reducing the result to 8 bits for the YM2612 DAC. How about (command numbers are hypothetical):
  • 0x3F xx: Generic 8-bit unsigned PCM write
  • 0x40 ll mm: Generic 16-bit signed PCM write (ll: LSB, mm: MSB)
  • User avatar
  • kyusawamura Offline
  • Posts: 33
  • Joined: 2015-06-08, 20:42:22
  • Location: Argentina
  • Contact:

Post by kyusawamura »

Thank you so much for this! I'll give it a try!

By the way, would it be too much trouble to give the user the option to log PC speaker notes into standard OPL2 MIDI-like notes, like the Life & Death II - The Brain music pack?
(Although I'm not sure if that one had an OPL2 mode already in the game as opposed to being 'converted' from PC speaker to FM...)

Post by NewRisingSun2 »

The game plays Adlib music that just sounds like PC speaker music.

VGM, as I understand it, is supposed to play back music as it originally sounded. By that standard, OPL2 cannot be used to capture PC speaker sounds because it has no square waveform.
  • User avatar
  • kyusawamura Offline
  • Posts: 33
  • Joined: 2015-06-08, 20:42:22
  • Location: Argentina
  • Contact:

Post by kyusawamura »

That's why I suggested transcribing the notes to like a standard piano-like instrument or something of the sort... I didn't mean having the PC speaker square waves play on the OPL2.

Post by NewRisingSun2 »

DOSBox-VGM captures. It does not transcribe. If transcription/conversion from one chip to another is desired, it should be done by an external utility, not by a VGM-producing emulator.
  • User avatar
  • kyusawamura Offline
  • Posts: 33
  • Joined: 2015-06-08, 20:42:22
  • Location: Argentina
  • Contact:

Post by kyusawamura »

Okay, got it. I'll add this to my list of things to code for when I can program competently. :P Thanks for the feedback!
  • User avatar
  • Soniccis96 Offline
  • Posts: 22
  • Joined: 2018-08-26, 14:21:16
  • Location: Burgas, Bulgaria
  • Contact:

Post by Soniccis96 »

How about MIDI capturing? I can't rip MT-32 soundtrack from Speed Racer: The Challenge of Racer X.
  • User avatar
  • ValleyBell Offline
  • Posts: 4937
  • Joined: 2011-12-01, 20:20:07
  • Location: Germany

Post by ValleyBell »

MIDI capturing has been part of DOSBox for ages.
  • nlflint Offline
  • Posts: 4
  • Joined: 2020-07-20, 1:27:17

Buffer overflow fix

Post by nlflint »

Hello all,
I tried to use this patch on linux (Ubuntu 20.04), and was getting a buffer overflow. Attached is an updated patch file that fixes the buffer overflow error below.

Repro:
0. Start DosBox
1. Start a game that plays OPL music
2. Press shortcut to start capturing VGM (for some reason left alt doesn't work as a modifier on my machine either?)
3. Press shortcut to end capture

Expected: VGM file created that plays in a VGM player.
Actual: Error message "*** buffer overflow detected ***: terminated" it output to stdout and dosbox crashes. VGM capture file is empty (0kb).

The problem was a strcpy of the Vgm header text. Changed to strncpy with len 4 and it works fine now.
Attachments
r4000-vgmcapture-overflow-fix.zip
(15.86 KiB) Downloaded 331 times
  • andlabs Offline
  • Posts: 189
  • Joined: 2011-12-04, 22:00:12

Post by andlabs »

Looks like that last patch wasn't enough for me on macOS 10.12 with Xcode 9.2, as I got errors about C++11 narrowing rules being broken (which I could bypass by disabling a warning, but I'll make them explicit C-style casts below instead) and using > 0 to check if pointers were nonnull instead of != 0 (which I couldn't). Since the errors are in files not touched by the patches, I assume the first patch wouldn't be enough either.

What I had to do (sorry but for various reasons I can't make this a real patch, just instructions):
  • In src/dos/dos_programs.cpp on line 78, change 'A'+d to (char)('A'+d)
  • In src/gui/sdlmain.cpp on lines 1316, 1317, and 1318, change the > 0 comparison after the strstr() calls to != 0
  • In src/hardware/vga_other.cpp on lines 283, 284, and 285, wrap the entire expression on each line inside a cast to Bitu (so for instance line 283 would read something like (Bitu)(2 + ... : 0),)
And then I could

Code: Select all

$ ./autogen.sh
$ ./configure --enable-core-inline CXXFLAGS="-std=gnu++14"
$ make
Note the use of CXXFLAGS and not CPPFLAGS like in the original post; CPPFLAGS refers to the C preprocessor and not C++ and therefore it gets applied to the C compiler as well, and clang doesn't like it when you specify a C++ language for a C file.

(And in case anyone else was wondering like I was, the last patch is supposed to be used instead of the original one, not in addition to it. It contains all the changes in the original patch plus the previous poster's fixes.)
  • andlabs Offline
  • Posts: 189
  • Joined: 2011-12-04, 22:00:12

Post by andlabs »

And it turns out this STILL wasn't enough, because this old version of dosbox expects the linker to see libpng as -lpng and with a header of png.h. macOS does come with a libpng that the linker can see with -lpng but does not include the headers (even in Xcode!), and libpng available from third-party package managers (I use MacPorts) is visible to the linker with a version suffix instead (such as -lpng16).

Fixing this is harder, and the "correct" fix would require significant changes beyond my time or understanding, so what I did was, before running ./autogen.sh:
  • Run pkg-config --libs libpng
  • Read the -l flag from the output, which in my case was -lpng16
  • In configure.ac, replace all instances of -lpng with -lpng16
  • Also on line 367, change AC_CHECK_LIB(png to AC_CHECK_LIB(png16 (in your case, replacing png16 with whatever the library flag is without the -l)
Then, I re-run autogen.sh and configure as so:

Code: Select all

$ ./autogen.sh
$ ./configure --enable-core-inline CXXFLAGS="-std=gnu++14 $(pkg-config --cflags libpng)" CFLAGS="$(pkg-config --cflags libpng)" LDFLAGS="$(pkg-config --libs libpng)"
$ make
And now I can save screenshots.
  • User avatar
  • Corak Offline
  • Posts: 14
  • Joined: 2015-11-04, 11:39:36
  • Location: Cimmeria, Simferopol
  • Contact:

Post by Corak »

Hi! Do you plan to update your Dosbox vgm mod to Dosbox-X?
There is much better dealing with fm synth.
I compared capturing to .dro with dosbox original and dosbox-x. X versions much better... Also there is 2 very important features added:
1 - Savestates. (helps to go directly to point before music starts)
2 - Pause with interrupts enabled (Helps alot to capture Full FM music tune without Sfx or conditional Stops.)

Opened suggest feature to github:
https://github.com/joncampbell123/dosbox-x/issues/4504
Post Reply