Some backstory:
- In [#45](https://github.com/vivaria/tja2fumen/pull/45), I reworked the
header parsing code to make sure every header value was correctly
identified.
- In [#46](https://github.com/vivaria/tja2fumen/pull/46), I changed how
the "branch point" header bytes were set by checking if a song contained
only drumroll branching conditions. This fixed drumroll-only songs like
BATTLE NO. 1, Shoutoku Taiko, etc.
However, I missed a corner case in #46 -- songs with `#BRANCHSTART
p,0,0` should still be considered "drumroll only". As well, I neglected
to consider the "percentage only" songs. So, I fixed the header bytes
there, too.
Then, to confirm that my changes do in fact produce correct headers, I
enabled the check for `branch_points` for (most) of the songs in the
test suite. The tests pass. :)
This PR updates the behavior for songs with drumroll branching
conditions (`#BRANCHSTART r`)
The changes include:
- Correctly setting the `branchInfo` bytes for branching conditions that
occur _after_ the first condition.
- Correctly setting the `branch_points` bytes in the header when there
are only drumroll conditions.
- Correctly setting the `branch_ratio` bytes in the header when total
notes differ between branches.
- Correctly handling #SECTION commands for a number of different corner
cases:
1. #SECTION occurs on its own without a #BRANCHSTART
2. #BRANCHSTART occurs with a #SECTION command
3. #BRANCHSTART occurs without a #SECTION command (and is first branch
condition)
4. #BRANCHSTART occurs without a #SECTION command (and is NOT first
branch condition)
Note: I've added `shoto9` to the test suite, but the TJA file is
structured in a way that the number of measures doesn't match the number
of fumen measures. The TJA needs to be reworked, but that's okay,
because its purpose was just to check that the branching bytes were
correct.
Fixes#40.
Previously, I had to reverse engineer many of the bytes in a valid fumen
header. This meant that I was often working with literal byte values, as
well as guessing at what things meant, calling them "padding" or
"unknown".
However, thanks to #44, I now have a TON of knowledge about the correct
purpose of each byte in the header. This lets me properly document each
value's purpose, and it also lets me parse 4-byte groups as ints, rather
than dealing with individual raw bytes.
In summary, the changes in this PR are:
- Create a new `FumenHeader` class with individual (correctly-named!)
attributes for each 4-byte integer.
- Parse and write the fumen header as one big 520-byte chunk, instead of
handling the header in smaller increments.
- Remove a bunch of dead lines of code that were hardcoding specific
byte values, and replace them with proper integer values.
- Vastly simplify the test for valid headers by removing checks against
individual bytes..
Necessary for #40.
Fixes#44.
This PR adds `genpe.tja` to the test suite, a song that currently fails
due to how `tja2fumen` handles `#SECTION` commands.
We fix the problems with branching commands in
8ad2102f0a. (Making sure that any #SECTION
commands that occur before the first #BRANCHSTART are properly handled.)
This PR also contains a few refactoring commits to improve the clarity
of how the branching logic works, to make further debugging of branching
songs easier.
Fixes#33.
This PR adds a new chart to the test suite (`imcanz.tja`) that uses
`p,0,0`, `p,999,999` _and_ `#SECTION` commands:
- `p,0,0`: Forces the chart into the Master branch (since it's
impossible to fail a 0% accuracy requirement)
- `p,999,999`: Forces the chart into the Normal branch (since it's
impossible to pass a 999% accuracy requirement)
- `#SECTION`: Resets accuracy values for notes and drumrolls on the next
measure. (In practice, this just means that the branch condition is
repeated on the next measure, at least according to the official fumen I
have.)
Note: Only the Oni and Hard difficulties have actually been added to the
test suite. The Normal and Easy charts were too broken to easily match
the official fumens. They will need a lot of work to fix charting
errors, so I'm leaving them commented out for now.
Fixes#27.
Before:
- If there was a #BPMCHANGE, tana's adjustment would be applied to _the current measure's duration_. This would result in very strange looking, impossible durations (e.g. negative)
- Additionally, this method required us to look ahead to the _next_ measure to determine the adjustment.
- Finally, it required us to keep track of two different durations: measureDurationBase (unadjusted) and measureDuration (adjusted)
After:
- Instead, we now leave the measureDuration as purely as "unadjusted".
- Then, we apply the "BPMCHANGE adjustment" _only_ when computing the fumenOffset start of the next measure.
- This requires us to keep track of both the start *and* end fumenOffset (where end = start + duration)
- However, this greatly simplifies and clarifies the code, since we:
- No longer need to "look ahead" to the next measure to compute the offset adjustment.
- No longer need to keep track of two different measureDurations (adjusted/unadjusted)
- Only need to work with a single pair of measures at a time (measureFumen, measureFumenPrev)
- The measure duration (and fumenOffsetEnd) times are now more comprehensible, since any negative offsets are only applied to the fumenOffsetStart value of the next measure.
After: