As documented, FH is:
Horizontal scan interrupt flag. Is set if VDP scans line specified in register R#19. If IE1 is set, interrupt is generated. FH is reset when S#1 is read
That would appear to establish that FH is completely independent of IE1 — it will be set if the VDP scans the R#19 line, it will be reset when S#1 is read. Oh, and by the way, if IE1 is set, the current status of FH will also be used to trigger interrupts.
However, I notice that many programs assume that they can read S#1 and use bit 0 to determine the current source of an interrupt. E.g. in Space Manbow the interrupt response code looks essentially like:
interrupt: if (S#1 & 1) { wait for end of horizontal blank OTIR list of relevant VDP updates } else { ... other things ... }
But the title screen does not enable IE1 and does not prepare a list of VDP updates — not even an empty list. So if FH is left to behave exactly as per the documentation then, through an uninitialised pointer, Space Manbow ends up blasting the start of the BIOS at the VDP upon every end-of-frame interrupt, which it mistakes for a line interrupt.
Empirically and based on the inherently-limited scope of my disassemblies, maintaining an internal FH as described but exposing it in S#1 only when IE1 is enabled seems to give correct execution. But that puts me into the sphere of guesswork so: is there any detailed third-party documentation of the Yamaha VDPs? Or a thread here somewhere that I've just failed to uncover? Or anybody who is willing to say a few words?