When the current address is xxxxxxxf, after doing the standard ADPCM
decoding and incrementing the current address as usual to get the
next address, the DSP will update the predscale register by reading
2 bytes from memory, and add two to get the next address.
This means xxxxxx10 cannot be a current address, as the DSP goes
from 0f to 12 directly.
A more serious issue with the old code is that if the start address
is 16-byte aligned, some samples will always be skipped, even when
that should not be the case.
An easy way to test whether this behaviour is correct is to check
the current address register and the predscale after each read.
Old code:
...
ACCA=00000002, predscale=<value>
ACCA=00000003, predscale=<value>
...
ACCA=0000000f, predscale=<value>
ACCA=00000010, predscale=<another value>
ACCA=00000013, predscale=<another value>
ACCA=00000014, predscale=<another value>
...
New code (and console):
...
ACCA=00000002, predscale=<value>
ACCA=00000003, predscale=<value>
...
ACCA=0000000f, predscale=<value>
ACCA=00000012, predscale=<another value>
ACCA=00000013, predscale=<another value>
...
Slightly cleaner, allows DSP accelerator behaviour to be
added to both HLE and LLE pretty easily, and makes the accelerator
easier to unit test.
I chose to include all accelerator state as private members, and
to expose state that is accessible via registers with getters/setters.
It's more verbose, yes, but it makes it very clear what is part of
the accelerator state and what isn't (e.g. coefs).
This works quite well for registers, since the accelerator can do
whatever it wants internally. For example, the start/end/current
addresses are masked -- having a getter/setter makes it easier to
enforce the mask.
This adds a test ucode that can be used to check the accelerator loop
behaviour with various start/end addresses.
It's actually more of a test template than a ready to use test.
const char[1] and wxString() can both be converted to multiple common
types, so this results in an ambiguous conditional expression
compilation error (C2445)
These rely on instance state, or are used within instance-based class
member functions, so they should belong to the instance itself instead
of being file statics.
The logic is entirely the same; only the inputs and outputs are
different, so deduplicating makes sense.
This will make fixing accelerator issues easier.