
VirtualC64 3.4: 🙈

On how to detect a second SID
https://csdb.dk/forums/index.php?roomid=14&topicid=99181&showallposts=1
On the end of this blog is a detection program and its source code
For reference: Some demos using 2 SIDs (in case we decide to support this feature):

@mithrendal Thanks for searching
This turned out not to be a bug. It's just that the demo expects a second SID and does not find one. The good news is that it shouldn't be too difficult to support multiple SIDs in VirtualC64.
TODOs
Screenshot from vAmiga:

Some planning before coding...
Requirements:
There are two approaches to map additional SIDs. The first one maps the auxiliary chips into the SID memory range ($D400 - $D7FF). The second one maps them into the cartridge memory range ($DE00 - $DFFF). VICE supports both. Since the latter case requires some additional checks inside the emulator (accesses to the cartridge port have to be rerouted if a SID is mapped into this area), we should try to find out how important this mapping area is. If it turns out that most demos expect the additional chips in the SID memory range, we should keep our hands away from the IO1 and IO2 space.
Architecture:
The implementation is pretty much straight forward:
Preparation:
Before adding new code…
what about an auto detection of the attacked memory space ?
UserStory:
a program pokes into $d420 adress space .... to play a tune on a stereo sid
Action:
Sidbridge automatically activates an additional SID at $d420 without asking the User to do this via settings ....
what about an auto detection of the attacked memory space ?
Such approaches usually don't work reliably for the C64, because games and demos do all kind of "irregular" stuff. In the case of SID, the relevant memory address space is mirrored every 32 bytes, because only the lower 5 address bits are evaluated. This means that standard SID can be acceseed at a variety of different memory locations (in multi-SID mods, some addresses that would normally address the build-in SID are simply rerouted to the additional chips). As a result, additional SIDs could be auto-activated by "normal" programs, too.
I've got a prototype working that pretends to have two SIDs. It works in the sense that the demo thinks there is a second SID on board (I am using the old version of the demo which terminates if no second SID is found):

My second SID does not contribute to the final audio stream yet. In other words: Only the primary SID is audible. The audio stream sounds strange, though. There are some pops in the background that I don't know where they come from. What I noticed is that the demo makes heavy use of the audio filter and model-specific SID properties. On the 6xxx, sound is very different from the 8xxx, and so it is when the audio filter is disabled. Maybe the pops would disappear if the audio filter is parameterized in a certain way (VICE allows setting filter parameters, VirtualC64 does not).
It'll be interesting to find out how the primary SID sounds like in VICE if the second SID is muted.
The cracking noise problem is solved (I think). It was just a missing else that caused all reads and writes that were supposed to be routed to the secondary SID to be routed to the primary SID, too. Now, I have a prototype working that produces and combines two audio streams. I tried to compare my audio output with the one produced by VICE, but for some reason I can't get the demo to work there.
@mithrendal: How did you run the demo in VICE?
I tried with the following settings:

But it still complains that I only have one SID:

@mithrendal: Thanks for advising me to use the no-sid-check-version in VICE:
http://csdb.dk/getinternalfile.php/206430/to_norah_nosidcheck.prg
VICE sounds exactly the same as the experimentally patched version of VirtualC64 which means we've successfully passed the "proof of concept" phase. Next step will be to decently integrate the new feature into the existing software architecture and GUI.
It seems many entries in csdb are tagged with 2sid 3sid but that doesn’t mean demos without it have only 1sid (to nora is an example)
https://csdb.dk/search/?seinsel=all&search=2sid
https://csdb.dk/search/?seinsel=all&search=3sid
Searching for 4sid results in empty list. Are there no 4sid music demos ? Why?
2sids = 6 voices, 3 sids = 9voices, 4 sids = 12 voices
Maybe 12 simultaneously voices is not so popular for electronic synthesizer music?
Here a top chart list ... many 2sids are inside
https://csdb.dk/toplist.php?type=release&subtype=%287%29&submit=Check%C2%A0chart
for comparison there is a deepsid direct start link ...
https://deepsid.chordian.net/?file=SID%20Happens/To_Norah_2SID.sid

by clicking on the 1 or 2 we can disable one sid and listen ...
I've added the necessary SID options to the hardware panel:

It looks a bit cluttered. Maybe I should move the drive and port stuff to a separate Peripherals panel (as in vAmiga). 🤔
by clicking on the 1 or 2 we can disable one sid and listen ...
Very cool site 😎. Never heard about it before.

The project is pretty much done.
All four SID channels can be mixed freely, just the same way as the four audio channels in vAmiga:

The SID inspector has been adjusted, too. It allows to examine an arbitrary SID now:

Last, but not least, the hardware panel has been simplified:

The drive and control port settings reside on a separate tab now ("Peripherals" which also exists in vAmiga).
@mithrendal: If you wish to incorporate multi-SID support in the web version, the following API calls are key:
C64::configure(OPT_SID_ENABLE, <sid nr>, <bool>)
C64::configure(OPT_SID_ADDRESS, <sid nr>, <address>)
To make Norah sing, set <address> to 0xD420 and enable the second SID (<sid nr> = 1).
VirtualC64 supports "SID hot plugging" which means you can add or remove SIDs any time (assuming there are no bugs, because this wasn't that easy to implement).
when compiling the latest code from master to WASM (which is 32Bit) the emcc compiler complains again ... do you have an idea what it is complaining about ?
In file included from Emulator/C64.cpp:10:
In file included from Emulator/C64.h:45:
Emulator/SID/SIDBridge.h:239:9: error: invalid operands to binary expression ('SerReader' and 'long')
& config.volL
^ ~~~~~~~~~~~
Emulator/SID/SIDBridge.h:256:41: note: in instantiation of function template specialization 'SIDBridge::applyToPersistentItems<SerReader>' requested here
size_t _load(u8 *buffer) override { LOAD_SNAPSHOT_ITEMS }
^
Emulator/Foundation/HardwareComponent.h:266:27: note: expanded from macro 'LOAD_SNAPSHOT_ITEMS'
SerReader reader(buffer); \
^
/Users/familie/projects/emsdk/upstream/emscripten/system/include/libcxx/cstddef:78:17: note: candidate function not viable: no known conversion from 'SerReader' to 'std::byte' for 1st argument
constexpr byte operator& (byte __lhs, byte __rhs) noexcept
^
Emulator/Foundation/Serialization.h:203:5: note: candidate function not viable: no known conversion from 'long' to 'bool &' for 1st argument
DESERIALIZE8(bool)
^
Emulator/Foundation/Serialization.h:186:63: note: expanded from macro 'DESERIALIZE8'
when I look for the variable volL which the emcc compiler is comlaining about ... it is definded as a long in SIDTypes.h but in SIDBridge.h it is a float ...
I've changed the datatype in the config struct to
// Input channel volumes and pan settings
i64 vol[4];
i64 pan[4];
// Output channel volumes
i64 volL;
i64 volR;
The code is on the dev branch.
it is definded as a long in SIDTypes.h but in SIDBridge.h it is a float ...
It's two different variables. config.volis the config parameter which is always an integer (because it is channeled through the configure() API). vol is the internal scaling factor applied to sound samples. It is computed out of config.vol by some sophisticated scaling formula to take the logarithmic aspect of our ear into account.
Ah I see ... now with i64 the new Core with multiSID compiles now completely ... very good
Compiler stops now at the WASm SDL2 wrapper
mainsdl.cpp:310:14: error: no member named 'readMonoSamples' in 'SIDBridge'
c64->sid.readMonoSamples((float *)stream, n);
~~~~~~~~ ^
mainsdl.cpp:713:21: error: no matching member function for call to 'configure'
wrapper->c64->configure(DRIVE8, OPT_DRIVE_CONNECT,1);
~~~~~~~~~~~~~~^~~~~~~~~
Emulator/C64.h:237:10: note: candidate function not viable: no known conversion from 'DriveID' to 'ConfigOption' for 1st argument
bool configure(ConfigOption option, long id, long value);
^
Emulator/C64.h:236:10: note: candidate function not viable: requires 2 arguments, but 3 were provided
bool configure(ConfigOption option, long value);
^
Emulator/C64.h:240:10: note: candidate function not viable: requires single argument 'model', but 3 arguments were provided
void configure(C64Model model);
^
2 errors generated.
definitily due to some API changes ... I will have a look for the replacements
The operand order has been cleaned up. Instead of
wrapper->c64->configure(DRIVE8, OPT_DRIVE_CONNECT,1);
use
wrapper->c64->configure(OPT_DRIVE_CONNECT, DRIVE8, 1);
Now, the config option types always comes first.
and readMonoSamples changed to copyMono ...
void MyAudioCallback(void* thisC64,
Uint8* stream,
int len)
{
C64 *c64 = (C64 *)thisC64;
int n = len / sizeof(float);
//c64->sid.readMonoSamples((float *)stream, n);
c64->sid.copyMono((float *)stream, n);
sum_samples += n;
}
now it completely compiled ... lets just ship it ..
Ok virtual64web starts up
but there is no sound at all ... when changing SID Chip Version an assertion says it is not running ...
I guess now its time to enable them ...
lets first try this
c64->configure(OPT_SID_ENABLE, 1);
c64->configure(OPT_SID_ADDRESS, 1, 0x400);
when changing SID Chip Version an assertion says it is not running ...
😱 What exactly does it say?
c64->configure(OPT_SID_ADDRESS, 1, 0x400);
Must be
c64->configure(OPT_SID_ADDRESS, 1, 0xD400);
it says
[0] ( 0, 1) 0000 SIDBridge: WARNING: Invalid SID address: 400
haha I missed the d ... hang on
no complains from the bridge anymore captain...
SIDBridge says ... SIDBridge: config.address[1] = 161ae42
but no sound ... and when I change SID Chip Revision it still complains "not running"
Assertion failed: !isRunning(), at: Emulator/SID/ReSID.cpp,130,setRevision
I have to start up the engine somehow, don't I ?
Assertion failed: !isRunning(), at: Emulator/SID/ReSID.cpp,130,setRevision
You need to embed the call in a suspend() / resume() block
SIDBridge says ... SIDBridge: config.address[1] = 161ae42
It should report 0xD420 🤔
BTW, SID 1 is the "second SID". The built in SID is SID 0. You only need to configure SID 1. Hence, set the address to 0xD420 which is the address where Nora is looking for it.
two SIDs are working fine in vc64web ... thanks dirk
Most helpful comment
I've got a prototype working that pretends to have two SIDs. It works in the sense that the demo thinks there is a second SID on board (I am using the old version of the demo which terminates if no second SID is found):
My second SID does not contribute to the final audio stream yet. In other words: Only the primary SID is audible. The audio stream sounds strange, though. There are some pops in the background that I don't know where they come from. What I noticed is that the demo makes heavy use of the audio filter and model-specific SID properties. On the 6xxx, sound is very different from the 8xxx, and so it is when the audio filter is disabled. Maybe the pops would disappear if the audio filter is parameterized in a certain way (VICE allows setting filter parameters, VirtualC64 does not).
It'll be interesting to find out how the primary SID sounds like in VICE if the second SID is muted.