Spoiler - recursive solution

Here my own solution. A recursive solution. I had to add a second parameter which I set to 0 at first call of the method.

public static List<int> ScoreFrames (List<int> rolls, int frameSize)
{
    //This solution takes the first two scores and call itself to calculate the next points

    List<int> frameList = new List<int>();
    // The rolls list dimension
    int count = rolls.Count;
    // The actual point
    int points = 0;

    //Teh frameSize is used to exclude points after 20 frame (see T21StrikeInLastFrame Test) (the base case of recursion)
    if (frameSize >= 10)
        return frameList;

    // If the rolls list dimension is less or equal than one, there are no points (the base case of recursion)
    if (count <= 1)
        return frameList;

    if(count >= 2) // A set of rules that reduce all other cases toward the base case
    {
        
        points = rolls[0] + rolls[1]; // Sum of the points in a frame
        if (points < 10) frameList.Add(points); // if points are less than 10 create a list with first result of frame
        if (count == 2) return frameList; // ... and if the list dimension is equal 2 returns the points

        if(points >= 10) // Strike or spare
        {
            frameList.Add(points + rolls[2]); // sum the third point 
            if(points > 10 || (rolls[0] == 0 || rolls[1] == 0)) // if the points are more than 10 or the first or second scores are equal to 0
                return frameList.Concat(ScoreFrames(rolls.GetRange(1, count - 1), ++frameSize)).ToList<int>();  // Concat the actual points with the list [1] -> [the end of list] - After a STRIKE
        }
    
        return frameList.Concat(ScoreFrames(rolls.GetRange(2, count - 2), ++frameSize)).ToList<int>(); // Concat the actual points with the list [2] -> [the end of list] // After a SPARE
    }
     
    return frameList;// (the base case of recursion)
}