VOGONS


First post, by NewRisingSun

User metadata
Rank Oldbie
Rank
Oldbie

I noticed a possible mistake in adlib.cpp. Registers 0xB0..0xB8 are not captured in the initial register dump, possibly to not include any notes that are already sounding when capturing begins. If a game initializes registers 0xB6..0xB8 only once and then turns percussion notes on and off by writing to 0xBD without reinitializing 0xB6..0xB8, the high bits of the frequency number will not be played back properly. Zeliard is one such game, and as expected, .DRO captures from that game sound wrong in all playback programs; some drum notes will be inaudible.

Zeliard captures correctly after the following source patch:

--- adlib.cpp.old	2013-01-15 12:10:04 +0000
+++ adlib.cpp 2014-01-19 19:54:06 +0000
@@ -227,10 +227,10 @@
Bitu i, val;
/* Check the registers to add */
for (i=0;i<256;i++) {
- //Skip the note on entries
- if (i>=0xb0 && i<=0xb8)
- continue;
val = (*cache)[ i ];
+ //Silence the note on entries
+ if (i>=0xb0 && i<=0xb8)
+ val &= ~0x20;
if (val) {
AddWrite( i, val );
}

This silences any notes that were active before capturing was started while preserving the upper bits of the frequency number.

Reply 1 of 4, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Moving to patches part.
It's an interesting problem that you are touching.

Water flows down the stream
How to ask questions the smart way!

Reply 2 of 4, by Malvineous

User metadata
Rank Oldbie
Rank
Oldbie

This is a good fix, it should help correct a few capture problems. I think however you should also zero out register 0xBD, bits 0-4 (i.e. val &= 0x1f) as well. This will prevent extra notes from sounding at the beginning of the capture in the event that rhythm mode is enabled, and rhythm notes are active at the moment the capture begins.

Reply 3 of 4, by NewRisingSun

User metadata
Rank Oldbie
Rank
Oldbie

Added the silencing of percussion notes, the silencing of second register set notes, plus the clearing of the register cache upon initialization. Commander Keen 4-6 would not capture properly without this additional memset command (the second register set is filled with garbage data), though I have no idea why it has never been an issue with other games.

--- adlib.cpp.old	2013-01-15 12:10:04 +0000
+++ adlib.cpp 2014-04-03 18:05:11 +0000
@@ -227,14 +227,17 @@
Bitu i, val;
/* Check the registers to add */
for (i=0;i<256;i++) {
- //Skip the note on entries
- if (i>=0xb0 && i<=0xb8)
- continue;
val = (*cache)[ i ];
+ //Silence the note on entries
+ if (i>=0xb0 && i<=0xb8)
+ val &= ~0x20;
+ if (i==0xbd) val &= ~0x1f;
if (val) {
AddWrite( i, val );
}
val = (*cache)[ 0x100 + i ];
+ if (i>=0xb0 && i<=0xb8)
+ val &= ~0x20;
if (val) {
AddWrite( 0x100 + i, val );
}
@@ -525,6 +528,7 @@

void Module::Init( Mode m ) {
mode = m;
+ memset(cache, 0, 0x200);
switch ( mode ) {
case MODE_OPL3:
case MODE_OPL2: