I finally got this thing working and cleaned up the source and comments. It's complete, and almost ready for release (I just have to relocate some code). I've removed all the swearing from the comments but I hope my sense of frustration is still imbued in the code. :P
With this, and the nonstandard battle endings updating the Morph supply, I think my Morph mega-fix is mostly complete. I still have to follow that lead on the Revert queueing bit from Assassin for a possible improvement to the main bugfix, but unless anyone knows of some other oddities with Morph, I will compile all the fixes into one .asm file in the coming week and produce some IPS patches. God, I dread writing the documentation for this.

On a side note, does xkas support calling or branching to straight addresses instead of labels? I keep declaring my labels using "org $address" and then put nothing but my label in there, just so I can jump or branch to that address. If I'm just making a call and not inserting code, can't I just type in the address? I can never get that to work but maybe I'm doing it wrong. :/
Quick description: I modify C2/0B01 so it can be called upon to either initialize Morph or to just update the Morph decrementor, which now factors in the ATB multiplier. Then I hook the ATB recalculation call to a tiny new function that tells the end-of-turn function at C2/083F to update all Morph-related stuff whenever the ATB variables are recalculated (when Haste/Slow status is changed, for example).
Or, well, that's what it will do when it's completely finished. For now, it does something kind of hackish and silly instead.

;Morph timer affected by Haste and Slow, v2
;This sets the Morph decrementor in init_morph, then calls init_morph
;every time ATB variables are recalculated (When Haste and Stop is
;set or removed, for example.
hirom
;header
!freespace = $C2A65A
;Change Haste multiplier for testing
org $C209E3
db $80 ;(Haste multiplier = 2x speed)
;Can't be too careful...
!phaxyp = "PHA : PHX : PHY : PHP"
!plpyxa = "PLP : PLY : PLX : PLA"
;hook
org $C2089D
JSR newfunc
;freespace
org !freespace
newfunc:
JSR recalc_atb
!phaxyp ;Preserve all the registers
CPX $3EE2 ;Exit if target isn't Morphed
BNE end
;The proper way
;LDA #$80
;ORA $3204,X
;STA $3204,X ;Always call C2/0AA8 after setting ATB variables
;So, at battle start and whenever Haste/Slow changes and maybe
;some other times
;To use this, we need to modify init_morph to set 16-bit A both in set_morpher
;and update_decrementor, but there's no room for an extra "REP #$20" without
;relocating parts of that function.
;The silly way
;BRA end ;(ignore this; used for testing the above)
REP #$20 ;We need to set 16-bit A so update_decrementor works,
;but init_morph loads $3EE2, expecting it to be 8-bit
;What do...?
SEP #$10
LDY $3EE3 ;(Commandeer Y to preserve $3EE3 briefly)
TDC
STA $3EE2 ;We only care about the n flag being clear, so zero $3EE3
JSR init_morph ;Now init_morph won't reset the Morph timer
STY $3EE3 ;Restore $3EE3
end:
!plpyxa
RTS
;Start Morph timer and establish amount to decrement it
org $C20B01
init_morph:
PHX
PHP
LDA $3EE2
;(New code, 2 bytes added)
BMI set_morpher ;If no one is morphed, set morpher, init timer, and set decrementor
;(Modified code)
BRA set_decrementor ;If somone is, only update decrementor
;(End of new and modified code)
;Unchanged code, for reference)
set_morpher:
LDA $3EBB
LSR
LSR
ROR
BCS exit ;(Exit function if bit 2 of $3EBB is set..
; Set for just Phunbaba battle #4 [i.e. Terra's
; second Phunbaba encounter])
ASL ;(Put Bit 1 into Carry)
STX $3EE2 ;(store target in X as Morphed character)
TDC
REP #$20 ;(Set 16-bit Accumulator)
DEC ;(A is $FFFF)
STA $3F30 ;(Morph timer = 65535)
;(End of unchanged code)
;(New code, adds 9 bytes [total: 11 bytes])
set_decrementor:
;REP #$20 ;This should be here, but my silly code handles it for now
LDA #$FF00
ORA $3ADD,X ;Low byte holds ATB multiplier, high byte holds FFh
JSR multiply16 ;(16-bit A = FFh * ATB multiplier)
;INC #2 ;(Division is a bit inaccurate, would this help?
;(End of new code)
;(Shifted code)
LDX $1CF6 ;(Morph supply)
JSR divide ;((ATB Multiplier * 255) / Morph supply) (16-bit A / 8-bit X)
BCC upgrade ;(Branch if bit 1 of $3EBB not set.
; This bit is set in Terra's 2nd Phunbaba battle
; [i.e. Phunbaba #4], and lasts afterward. So
; Terra gains some resolve here. ^__^)
LSR ;(A = (255 * ATB multiplier + 2 / Morph supply) / 2 [pre-Phunbaba])
upgrade:
LSR ;(A = (255 * ATB multiplier + 2 / Morph supply) / 4 [post-Phunbaba])
;(End of shifted code)
;(Removed code, for reference. Removes 11 bytes)
;LSR
;LSR
;CMP #$0800
;BCC nocap
;LDA #$07FF ;(this will cap amount to decrement morph time
; ; counter at 2048)
; ;
; ;Removed for space. Morph is disabled unless Morph
; ;supply is at least 16, in which case amount to decrement
; ;will be at most 512 (old), or 2033 (new).
; ;Old: (65535 / 16) / 8 + 1 = 512)
; ;New: ([255 * 255 + 1] / 16) / 2 + 1 = 2033
; ;That's with the Haste multiplier being maxed.
;nocap:
;INC ;Sacrificed to make that extra branch, for now
;(End of removed code)
;(Unchanged code, for reference)
STA $3F32 ;(Amount to decrement morph time counter)
exit:
PLP
PLX
RTS
;(End of unchanged code)
;Called addresses (for labeling)
;Multiplies low byte of A * high byte of A. Stores result in 16-bit A.
org $C24781
multiply16:
;Divides 16-bit A / 8-bit X
;Stores answer in 16-bit A. Stores remainder in 8-bit X.
org $C24792
divide:
;Recalculate ATB
org $C209D2
recalc_atb:
;Notes:
;$3EE2 is set in init_morph unless its already set
;(and only ever in init_morph)
;init_morph is called whenever C2/0AA8 discovers Morph status on target
;C2/0AA8 is called once whenever bit 1 of 3204,X has been set
;bit 1 of 3204,X is set whenever C2/23ED detects target is morphed (via $3EE2)
;So it goes:
;if C2/23ED detects target is morphed, set bit
;if bit is set, clear it and call C2/0AA8
;(always update menu)
;if target has Morph status, call init_morph
; if $3EE2 is clear
; set $3EE2, and set timer and decrementor
; if $3EE2 is set
; set decrementor only
;if no Morph status
; clear $3EE2, timer, and gauge, and update supply