rscustom / rocksmith-custom-song-toolkit

Custom song toolkit for Rocksmith and Rocksmith 2014
http://www.rscustom.net/
343 stars 80 forks source link

Issue in SNG writer regarding linknext #297

Closed iminashi closed 6 years ago

iminashi commented 7 years ago

The relevant code is lines 1141 - 1186 in Sg2014FileWriter.

Currently the algorithm assumes that the parent note in a linknext is always the previous note of the child note, but that is not always the case:

EOF Linknext

RS Linknext

The CHILD mask gets applied to the G string note and the note is not drawn. And while the mask is not applied to the A string note with the slide out, it still works out and that note is not drawn either, so it would seem that RS does its own thing instead of following the SNG file to the letter.

L0FKA commented 7 years ago

Test case would be nice. it has filter for //check to see if we are looking at the same string so I may be something bigger, gotta check this with sample xml tonight

iminashi commented 7 years ago

That check for same string is made only for notes on the same time (split chord).

I tried rewriting that part of the code and here is what I've currently got. This should fix the issues and be more accurate, but changes to how chords with linkNext are exported to the XML would be needed on the EOF side too, otherwise some things will break.

            // Connect parent notes with child notes (linkNext)
            for (int j = 0; j < a.Notes.Notes.Length; j++)
            {
                // Look for notes with PARENT mask (linkNext=1)
                var n = a.Notes.Notes[j];
                if ((n.NoteMask & CON.NOTE_MASK_PARENT) != 0)
                {
                    if(n.ChordId == -1) // Single note
                    {
                        // Find the next note on the same string
                        int x = j + 1;
                        while(x < a.Notes.Notes.Length)
                        {
                            if(a.Notes.Notes[x].StringIndex == n.StringIndex)
                            {
                                a.Notes.Notes[x].ParentPrevNote = (short)(n.NextIterNote - 1);
                                a.Notes.Notes[x].NoteMask |= CON.NOTE_MASK_CHILD;

                                break;
                            }
                            x++;
                        }
                        if(x == a.Notes.Notes.Length)
                        {
                            // Ran out of notes in the difficulty level without finding a child note
                            // Possible to end up here due to badly placed sections or due to DDC moving sections
                            // Throw exception / show error message?
                        }
                    } else // Chord
                    {
                        // Chordnotes should always be present
                        // Should probably add a check for n.ChordNotesId == -1?
                        var chordnotes = cns[n.ChordNotesId];

                        // Check which chordNotes have linknext
                        for(int cnString = 0; cnString < 6; cnString++)
                        {
                            if ((chordnotes.NoteMask[cnString] & CON.NOTE_MASK_PARENT) != 0)
                            {
                                // Find the next note on the same string
                                int x = j + 1;
                                while (x < a.Notes.Notes.Length)
                                {
                                    if (a.Notes.Notes[x].StringIndex == cnString)
                                    {
                                        a.Notes.Notes[x].ParentPrevNote = (short)(n.NextIterNote - 1);
                                        a.Notes.Notes[x].NoteMask |= CON.NOTE_MASK_CHILD;

                                        break;
                                    }
                                    x++;
                                }
                                if (x == a.Notes.Notes.Length)
                                {
                                    // Ran out of notes in the difficulty level without finding a child note
                                    // Throw exception / show error message?
                                }
                            }
                        }
                    }
                }
            }
iminashi commented 7 years ago

Here are some test cases.

The "fail" arrangement has two cases where the Toolkit currently produces wrong results. The second one is pretty unlikely to happen. The "tests" arrangement has some additional artificial tests.