;****************************************************************************
; ReadPitchArg
;
; Reads a pitch argument for SONA_KEYON_* and SONA_PITCH_* stream events,
; processes it and stores the new pitch value.
;----------------------------------------------------------------------------
; input c ..... current stream bank
; input hl .... current stream address
; input de .... pointer to current pitch
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
; output de ... pointer to current pitch (intact)
;----------------------------------------------------------------------------
; modifies .... a,bc,hl,a'
;----------------------------------------------------------------------------
; notes: pitch value must NOT cross a page boundary.
;****************************************************************************
ReadPitchArg:
ReadArgByte ; Read first byte
ld a, b
cp $70
jr c, ReadShortPitchArg ; Short-form absolute pitch?
cp $80
jr c, ReadLongPitchArg ; Long-form absolute pitch?
ret z ; No-op?
cp $F0
jr c, ReadShortRelPitchArg ; Short-form relative pitch?
jr ReadLongRelPitchArg ; Long-form relative pitch?
;----------------------------------------------------------------------------
; Absolute pitch format, short-form
;----------------------------------------------------------------------------
; 0yyyyxxx where xxx = octave (0..7)
; yyyy = semitone (0..11)
;----------------------------------------------------------------------------
ReadShortPitchArg:
ld a, b ; Isolate octave and store it
and $07
ld (de), a
inc e
ld a, b ; Isolate semitone and store it
add a, a
and $F0
ld (de), a
dec e ; Restore pointer
ret ; End of subroutine
;----------------------------------------------------------------------------
; Absolute pitch format, long-form
;----------------------------------------------------------------------------
; 0111zzzz 0yyyyxxx where xxx = octave (0..7)
; yyyy = semitone (0..11)
; zzzz = fraction (0..15)
;----------------------------------------------------------------------------
ReadLongPitchArg:
and $0F ; Isolate fraction and keep
ex af, af' ; it for later
ReadArgByte ; Read second byte
ld a, b ; Isolate octave and store it
and $07
ld (de), a
inc e
ld a, b ; Isolate semitone
add a, a
and $F0
ld b, a ; Merge semitone with fraction
ex af, af' ; and store them
or b
ld (de), a
dec e ; Restore pointer
ret ; End of subroutine
;----------------------------------------------------------------------------
; Relative pitch format, short-form
;----------------------------------------------------------------------------
; 1yyyydxx where xx = octave (0..3)
; yyyy = semitone (0..11)
; d = direction (0 = up, 1 = down)
;----------------------------------------------------------------------------
ReadShortRelPitchArg:
PollPcm
push bc ; Save registers
push hl ; We need to clobber C and HL
ld a, b ; Isolate direction
and $04
ex af, af'
ld a, b ; Convert pitch to long form
add a, a ;
and $F0 ; B = octave
ld c, a ; C = semitone+fraction
ld a, b
and $03
ld b, a
jr ReadRelPitchCommon
;----------------------------------------------------------------------------
; Relative pitch format, long-form
;----------------------------------------------------------------------------
; 1111zzzz dyyyyxxx where xxx = octave (0..7)
; yyyy = semitone (0..11)
; zzzz = fraction (0..15)
; d = direction (0 = up, 1 = down)
;----------------------------------------------------------------------------
ReadLongRelPitchArg:
PollPcm
ld a, b ; Isolate fraction
and $0F
ex af, af'
ReadArgByte ; Read second byte
push bc ; Save registers
push hl ; We need to clobber C and HL
ld a, b ; Isolate semitone and put it
add a, a ; together with the fraction
and $F0
ld c, a
ex af, af'
or c
ld c, a
ld a, b ; Isolate direction
and $80
ex af, af'
ld a, b ; Isolate octave
and $07
ld b, a
; fallthrough to ReadRelPitchCommon...
;----------------------------------------------------------------------------
; Common code to both short and long form relative pitch
; notes: BC and HL have been pushed onto the stack by this point
;----------------------------------------------------------------------------
ReadRelPitchCommon:
PollPcm
; b = pitch to add/substract (octave)
; c = pitch to add/substract (semitone+fraction)
; de = pointer to original pitch
; a' = direction (0 = add, else substract)
ex de, hl ; Read original pitch
ld d, (hl)
inc l
ld e, (hl)
ex de, hl
ex af, af' ; Do the addition
call AddOrSubPitch
PollPcm
ex de, hl ; Store new pitch
ld (hl), e
dec l
ld (hl), d
ex de, hl
pop hl ; Restore registers
pop bc
ret ; End of subroutine