I think subdump's logic is better/best, but it takes subdump very long time to dump the sub, so I can't use it. (In the first place, I don't know the subdump's logic because this is not open-source.)
How should the subs error correction work, IMO:
1. You define 9 variables: SubRereadNum, CurrentSubReadNum, CurrentSectorNum, FixLevel, QCurrentSector, QNextSector, QGenSector, QEAN, QISRC.
2. From commandline args you read FixLevel (should be between 0 and 96) and SubRereadNum (0 or larger)
3. You read a sector with the LBA = CurrentSectorNum (0 by default) and put its Q-channel into QCurrentSector.
3.1. If QNextSector is null: you read a sector with LBA = CurrentSectorNum + 1, check its Mode (should be 0x01) and Q-CRC and put its Q-channel into QNextSector.
If Q-CRC is bad or Mode != 1, you read a sector with LBA = CurrentSectorNum + 2, check its Mode and Q-CRC, if both are fine, you substract 1 frame from MSF and AMSF (MSF - 1 and AMSF - 1), fix Q-CRC and write that into Q-NextSector.
If Q-CRC is bad again or Mode != 1, you read a sector with LBA = CurrentSectorNum + 3, etc.
4. If Q-CRC of QCurrentSector matches, go to p.5.
4.1. If Q-CRC of QCurrentSector doesn't match: QGenSector = QNextSector - 1 frame (MSF - 1, AMSF - 1, fix Q-CRC).
4.2. You do a binary compare (96 bits vs 96 bits) between QCurrentSector and QGenSector and count a number of bits that differ. If their count is <= FixLevel: QCurrentSector = QGenSector and go to p.5.
4.3. If QEAN != null, you do a binary compare between QCurrentSector and QEAN and count a number of bits that differ. If their count is <= FixLevel: QCurrentSector = QEAN and go to p.5.
4.4. If QISRC != null, you do a binary compare between QCurrentSector and QISRC and count a number bits that differ. If their count is <= FixLevel: QCurrentSector = QISRC and go to p.5.
4.5. If still not matched and CurrentSubReadNum < SubRereadNum: clear the drive's cache and go to p.3
5. Write QCurrentSector to the .sub
5.1. If Q-CRC is bad: QNextSector = QNextSector + 1 frame (add + 1 to MSF, add + 1 to AMSF, fix Q-CRC)
5.2. If Q-CRC is good and QCurrentSector mode = 0x01: QNextSector = QCurrentSector + 1 frame
5.3. If Q-CRC is good and QCurrentSector mode = 0x02 (EAN): QEAN = QCurrentSector and QNextSector = QNextSector + 1 frame
5.4. If Q-CRC is good and QCurrentSector mode = 0x03 (ISRC): QISRC = QCurrentSector and QNextSector = QNextSector + 1 frame
5.5. CurrentSectorNum = CurrentSectorNum + 1, CurrentSubReadNum = 0
This way you let users to decide, how many bits are fine to be fixed and how many times it's ok to reread. Don't forget to clear the drive's cache before each rereading, otherwise, you may get the same results every time.