Sona 0.50 Source

Sona 0.50/src-z80/pitch_parse.z80

;****************************************************************************
; 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