Weirdness, wtf? [solved]

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Weirdness, wtf? [solved]
by on (#209328)
I have a rom where there is a default sound driver. If certain songs are selected a flag is set to unload the default sound driver. Once the dault sound driver is unloaded than a flag is set to indicate the non-default driver is currently loaded. If the next song that is called does not request the non-default sound driver than that driver is unloaded and the default driver is restored.

I had this working 100% at one point, and I'm not sure how or why it has stopped working. To simplify I'm no longer switching drivers at any point. All my cuurent tests are loading either driver A or B.

Currently, this is what happens:

load sound driver A: sound driver doesn't work (sound doesn't work but the menu screen is operational, so not stuck in any loops waiting on the spc)
load sound driver B: sound driver works

I have one file has the spc code for both sound drivers in such a fashion:

Code:
.export SOUND_DRIVER_A, SOUND_DRIVER_A_END, SOUND_DRIVER_B, SOUND_DRIVER_B_END
 
.segment "DRIVER"

SOUND_DRIVER_A:
(sound driver A data)
SOUND_DRIVER_A_END:

SOUND_DRIVER_B:
(sound driver B data)
SOUND_DRIVER_B_END:


the code to load a driver is just

Code:
SPC_BOOT = 0380h ; all sound drivers being tested are using this address
;**********************************************************************
;* upload driver
;*
;* disable time consuming interrupts during this function
;**********************************************************************
spcBootDriverA:         
;----------------------------------------------------------------------
:   ldx   REG_APUIO0   ; wait for 'ready signal from SPC
   cpx   #0BBAAh      ;
   bne   :-      ;--------------------------------------
   stx   REG_APUIO1   ; start transfer:
   ldx   #SPC_BOOT   ; port1 = !0
   stx   REG_APUIO2   ; port2,3 = transfer address
   lda   #0CCh      ; port0 = 0CCh
   sta   REG_APUIO0   ;--------------------------------------
:   cmp   REG_APUIO0   ; wait for SPC
   bne   :-      ;
;----------------------------------------------------------------------
; ready to transfer
;----------------------------------------------------------------------
   lda   f:SOUND_DRIVER_A   ; read first byte
   xba         ;
   lda   #0      ;
   ldx   #1      ;
   bra   sb_start   ;
;----------------------------------------------------------------------
; transfer data
;----------------------------------------------------------------------
sb_send:
;----------------------------------------------------------------------
   xba         ; swap DATA into A
   lda   f:SOUND_DRIVER_A, x; read next byte
   inx         ; swap DATA into B
   xba         ;--------------------------------------
:   cmp   REG_APUIO0   ; wait for SPC
   bne   :-      ;--------------------------------------
   ina         ; increment counter (port0 data)
;----------------------------------------------------------------------
sb_start:
;----------------------------------------------------------------------
   rep   #20h      ; write port0+port1 data
   sta   REG_APUIO0   ;
   sep   #20h      ;--------------------------------------
   cpx   #SOUND_DRIVER_A-SOUND_DRIVER_A   ; loop until all bytes transferred
   bcc   sb_send            ;
;----------------------------------------------------------------------
; all bytes transferred
;----------------------------------------------------------------------
:   cmp   REG_APUIO0   ; wait for SPC
   bne   :-      ;--------------------------------------
   ina         ; add 2 or so...
   ina         ;--------------------------------------
            ; mask data so invalid 80h message wont get sent
   stz   REG_APUIO1   ; port1=0
   ldx   #SPC_BOOT   ; port2,3 = entry point
   stx   REG_APUIO2   ;
   sta   REG_APUIO0   ; write P0 data
            ;--------------------------------------
:   cmp   REG_APUIO0   ; final sync
   bne   :-      ;--------------------------------------
   stz   REG_APUIO0
   
   stz   spc_v      ; reset V
   stz   spc_q      ; reset Q
   stz   spc_fwrite   ; reset command fifo
   stz   spc_fread   ;
   stz   spc_sfx_next   ;
   
   stz   spc_pr+0
   stz   spc_pr+1
   stz   spc_pr+2
   stz   spc_pr+3
;----------------------------------------------------------------------
; driver installation successful
;----------------------------------------------------------------------
   rts         ; return
;----------------------------------------------------------------------



There is a copy of the code that is the same except for local labels and uses SOUND_DRIVER_B and is called spcBootDriverB. While assembeld (ca65) the output is the same for both routines except for the driver address and number of bytes to transfer. Everything here is correct.

Right now there is no way I can get SOUND_DRIVER_A to work.

If I go back to the version which only has the ability to load one sound driver and I only include one sound driver (no matter which sound driver I include) then it will always work. I'm not sure why including the code for a second driver, and including the data for a second sound driver would cause any weirdness.

If I use SOUND_DRIVER_B data for both SOUND_DRIVER_B and SOUND_DRIVER_A than "A" works.

It looks like when I use SOUND_DRIVER_A the last thing written to $f2 is $17 which is gain, and the last value written to $f3 is $9e (%10011110, custom gain and gain rate). This shows me it's not processing pattern data because it's not cycling through the channels. The only thing being updated are the spc timers. I know what code would produce this value and it's the exact same code in SOUND_DRIVER_B. Most of the code between the sound drivers is the same, everything that handles the it pattern data is the same, as is everything which handles volume and such.

If I use the original snesmod code and only include 1 driver than it works no matter which driver I use. I do not understand why SOUND_DRIVER_A would "magically" (that word rather implies some sort of bug some where doesn't it?) work.

The only changes to snesmod.asm was having two different spcBoot routines (which are the same except for the data they read and the number of bytes they transfer), and sm_spc where I'm including two sound drivers instead of one.

Anyway I posted this because I thought if I wrote it out something might jump out at me and possibly somebody might have some ideas of things to check.
Re: Weirdness, wtf?
by on (#209336)
A few things:

- Instead of two identical routines for uploading different drivers, you should consider having one routine for uploading whatever data you are pointing to via index register or variable in RAM.
- What is the use case for having two sound drivers via SNESmod? I can imagine having multiple sound drivers for SNESGSS since the soundbanks don't seem readily interchangeable.
- It sounds like there are some issues with your changes to SNESmod, but unless you provide those code changes it will be hard to determine what went wrong.
Re: Weirdness, wtf?
by on (#209350)
HihiDanni wrote:
- Instead of two identical routines for uploading different drivers, you should consider having one routine for uploading whatever data you are pointing to via index register or variable in RAM.

Yeah, the working version used that feature, I changed it to this for testing, not that it made a difference.

Quote:
- What is the use case for having two sound drivers via SNESmod? I can imagine having multiple sound drivers for SNESGSS since the soundbanks don't seem readily interchangeable.

When I perform live I have a rom which has over 100 songs and most of them use an older version of the driver, but a few use the newer version. Besides additional features, some of the commands have changed. Rather than go back and edit the old songs for use with the new driver, this seemed like it would be less time consuming.

It could also be useful for putting together something which has songs made with different drivers which is how the idea came about in the beginning.

(Side question, are there any trackers that let you search for a specific command used in a song? It would be handy to do a search for all uses of a single command)

Quote:
- It sounds like there are some issues with your changes to SNESmod, but unless you provide those code changes it will be hard to determine what went wrong.

It does seem like it would have to be something with the driver, but it's really weird that there is never any issue loading the driver in the circumstance of only having one sound driver.

When I was mucking about with the driver earlier I managed to arrive at the opposite situation. Sound driver A would work and sound driver B would not work. I still cannot arrive back at a situation where loading both drivers works correctly, or where Sound driver B works as it did back when I first posted about this. What I did was change the segments the sound drivers were located in. But they have always been in banks that requried far addressing and the boot code accounts for that.

I've attached one of the sound drivers in question (the one which was working this morning but now no longer works, even though no driver code was changed)

I also did another test using only the snesmod driver and snesmod w/ pitch modulation and ran into the same problem. Only the snesmod w/ pitch mod would work, not the original snesmod sound driver. And again, each of those sound drivers work fine on their own, and the code is structred in the same way.
Re: Weirdness, wtf?
by on (#209353)
Oh, so whatever is the second driver you include doesn't work? This does seems like it might be related to upload issues, and possibly ROM layout as well? I'd try to dump the SPC memory just after the upload finishes, and check that it matches up byte for byte with what you are trying to upload. If there's a mismatch, we know that the upload process is the culprit.

Edit: Another idea that popped into my head: If this issue happens after replacing a previously uploaded driver with a new one, I wonder if it has anything to do with stale data that's confusing the new driver?

Very cool that you perform live!
Re: Weirdness, wtf?
by on (#209364)
I should have thought of this earlier, and I won't be able to verify until tomorrow, but when it seemed like a sound driver was failing it was likely because the song was from a soundbank compiled for the other sound driver. This would explain the flip flop effect because when I was messing around with it I'm sure I switched the driver in the makefile at some point. I overlooked that detail from when I first set up that system. Man that thing in my head that let's me think thoughts, whatever it is, I think it's starting to fail.
Re: Weirdness, wtf?
by on (#209409)
Augustus Blackheart wrote:
When I perform live I have a rom which has over 100 songs and most of them use an older version of the driver, but a few use the newer version. Besides additional features, some of the commands have changed. Rather than go back and edit the old songs for use with the new driver, this seemed like it would be less time consuming.

That's part of why I haven't changed anything in Pently sequence data. Drums changed from 1 byte to 2 in Pently 3 (Thwaite) to allow for Tim Follin-style sharing of the triangle between drum and bass, and instruments changed from 4 bytes to 5 in Pently 4 (RHDE) to accommodate a pointer used by a FamiTracker-style envelope in the attack phase. But all changes to conductor and pattern data have been additive to support new effects. Even the (stalled) Super NES port of Pently uses the same sequence data format.

Augustus Blackheart wrote:
It could also be useful for putting together something which has songs made with different drivers which is how the idea came about in the beginning.

Or if someone makes a multicart with multiple competition entries, each with a different driver.

Augustus Blackheart wrote:
(Side question, are there any trackers that let you search for a specific command used in a song? It would be handy to do a search for all uses of a single command)

HertzDevil's 0CC-FamiTracker has find and replace. I'm not aware of any sample-based trackers (those targeting .it and its predecessors) that do.
Re: Weirdness, wtf?
by on (#209626)
...and it's fixed, I should have looked more closely at the Makefile earlier.

tepples wrote:
That's part of why I haven't changed anything in Pently sequence data. Drums changed from 1 byte to 2 in Pently 3 (Thwaite) to allow for Tim Follin-style sharing of the triangle between drum and bass, and instruments changed from 4 bytes to 5 in Pently 4 (RHDE) to accommodate a pointer used by a FamiTracker-style envelope in the attack phase. But all changes to conductor and pattern data have been additive to support new effects. Even the (stalled) Super NES port of Pently uses the same sequence data format.

I made the choice to convert the songs even when I wasn't sure I had the commands set the way I wanted. SNESMod uses higher numbers for the default and lower numbers to turn something on... I flipped that around for one group of commands, and when I noticed, I had the opportunity to go back and fix this in many songs but I decided it wasn't worth the effort. In the future I will give more thought to things like this, but for me it didn't matter because it wasn't for public release, and I fixed the issue for the public version.

I'm glad you implemented the TF sharing, when I was making NES songs I always used mml which was rather tedious for that sort of thing.

Quote:
HertzDevil's 0CC-FamiTracker has find and replace. I'm not aware of any sample-based trackers (those targeting .it and its predecessors) that do.

It seems like such an obvious feature I'm surprised that it didn't happen much sooner. Every once in awhile it's possible to end up with a stray command somewhere and than it's so much fun to hunt down exactly where it is, as I usually use commands on every line of most columns.
Re: Weirdness, wtf?
by on (#209656)
OpenMPT has had find and replace for quite a long time (possibly pretty much always?)
Re: Weirdness, wtf?
by on (#209681)
I actually got a thought myself on why the converted modules are not compatible between different versions of the sound drivers...

Are your pointers regarding patterns and instruments consistent between both copies? Memory locations for the modules could be another major cause of module files failing to play back on the other sound driver since it requires a specific memory location.
Re: Weirdness, wtf?
by on (#209812)
Revenant wrote:
OpenMPT has had find and replace for quite a long time (possibly pretty much always?)

Thanks, I figured somebody, somewhere, must have done this a long time ago.

KungFuFurby wrote:
I actually got a thought myself on why the converted modules are not compatible between different versions of the sound drivers...
Are your pointers regarding patterns and instruments consistent between both copies? Memory locations for the modules could be another major cause of module files failing to play back on the other sound driver since it requires a specific memory location.

I fixed it earlier this week. In the Makefile I was using I didn't set the flags for one of the soundbanks to use the 2nd sound driver. In addition, on the SNES side, something in this particular project was writing to an area of RAM reserved for the sound driver. This explains why either sound driver would work in any other project, but not in this one.

edit: I updated the subject to make it clear that the issue has been resolved.