dosbox-staging:kc/opl-dc-bias-1

Last commit made on 2024-01-09
Get this branch:
git clone -b kc/opl-dc-bias-1 https://git.launchpad.net/dosbox-staging

Branch merges

Branch information

Name:
kc/opl-dc-bias-1
Repository:
lp:dosbox-staging

Recent commits

89ee923... by kcgen <email address hidden>

Remove the OPL DC bias using a forward-looking average

The algorithm works by:

1. Maintaining a queue of N samples when the
   stream is above a bias threshold. The queue is
   cleared otherwise.

2. Maintaining a running average of the DC offset
   based on the queue.

3. Deducting the running average from the head of
   the queue.

3d75cd3... by kcgen <email address hidden>

Remove OPL DC bias using a simple running average

Some games like Golden Eagle (1991), Wizardry 6 (1990), and
Wizardry 7 (1992) can be configured to play PCM effects and
music using the Adlib's OPL channels by rapidly changing the
volume in very crude steps, similar to RealSound with the PC
Speaker or using an LPT DAC.

In these cases, the games use large DC bias that can often
pop either at the start or end of the effect sequences.

The algorithm works by:
1. Maintaining a running average of the DC offset that
   starts from zero.
2. Computing the averge across the last N samples.
3. Deducting the running average from the current sample.

We could parameterize the settings if more games can be served by
this, and if they benefit from other settings. For now, let's not
over-engineer it until we need to.

Vogons has a thread that lists some (all?) of these games:

https://www.vogons.org/viewtopic.php?f=7&t=50525

e170b4e... by kcgen <email address hidden>

Use a bit_view to de-magic the SB DSP buffer status IO call result

153f3c6... by kcgen <email address hidden>

Replace part of the SB 8-on/8-off buffer status with DMA buffer state

The eight on/off logic is split:
1. The off part is kept; we now report available room every 8th call.
2. The on part is replaced with an actual check of the DMA buffer state.

Previously, the SB's write buffer status could report "we're full,
we can't accept data" eight consecutive times, even when when the
DSP and DMA and totally idle. This behaviour causes SimLife and
the Crystal Dream demo to eventually give up on setting up their
DMA transfers.

So this replaces the "we're busy, we're busy, we're busy, ..." with
an actual check of the DMA status.. and if DMA isn't running or
at the minimum (about to run dry), then we say "we're available".

---

More notes from the PR review:

I created this based on logging what these games were doing (just
a bunch of LOGs in SB) combined with reading about the buffer
write check (in the ref'd docs).

86Box and DOSBox-X both calculate the playback rate of the current
DMA transfer and then steadily draining down that time until it
nears completion.

In this implementation, fortunately we've already got the dma.left
and dma.min values to see how close we are to the end of the
transfer.

One of the nuances is that games can change the playback rate as
well as switch from mono to stereo; so the drain down rate can
vary: and indeed, 86Box does this extra bookkeeping.

In our case, these rate changes are already taken care of by the
existing code, and it just happens that this threshold (dma.left
vs dma.min) will happen sooner if the rates are faster.

Scali had a through discussion about Sound Blaster seamless
playback using all the different DMA methods (autoinit, signle
init, and hacked methods)
https://www.vogons.org/viewtopic.php?t=52806. He wrote a nice
seamless playback tool, too (tested this PR with it, and it's
fine).

948123d... by kcgen <email address hidden>

Move the Sound Blaster write buffer status to a function

This is functionally identical.

It uses a self-documenting function name and adds comments about
the logic behind why we might consider the buffer at capacity or not.

89c6e3d... by kcgen <email address hidden>

Apply clang format to the Sound Blaster read routine (whitespace-only)

74e89c1... by Cameron Kaiser

Don't sign extend 16-bit immediates to 32-bit in ppc dynrec, fixes #2846

Signed-off-by: kcgen <email address hidden>

a4fe121... by kcgen <email address hidden>

Accommodate a larger count size in the full core

0a6c3f1... by kcgen <email address hidden>

Fix an undefined behaviour in the 32-bit signed multiplier

DIMULD ("double word integer multiplied with double word integer")
multiplies signed 32-bit values (op2 and op3), and stores the result
in op1, also a signed 32-bit variable.

The result of the multiplication is allowed to overflow the capacity
of op1; if so, then the carry and overflow bits are set.

Ref: https://docs.oracle.com/cd/E19455-01/806-3773/instructionset-39/index.html

The issue is that operands were being cast straight from their
incoming uint32_t register types up to signed 64-bit values, instead
of first being cast to signed 32-bit values.

This was caught while testing Frontier - First Encounter with a
position independent UBSAN build:

meson setup --buildtype=debug \
             -Db_sanitize=undefined \
             -Db_pie=true \
             -Db_staticpic=true build/ubsan

runtime error: signed integer overflow: 4294934784 * 4294950322
               cannot be represented in type 'long long'

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
         ../../src/cpu/core_normal/prefix_66_0f.h:236:4 in

dbd2307... by Daniel Bomar

Fix DOS_DeviceHasName function to correctly check string lengths