; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > $.Source.PMF.Buffer

; *****************************************************************************
;
;       NewInsV - Routine for InsVec
;
; in:   R0 = character to be inserted
;       R1 = buffer number
;
; out:  R0, R1, R3-R12 preserved
;       R2 undefined
;       C=1 <=> insertion failed
;

NewInsV ROUT
        CMP     R1, #NBuffers
        MOVCS   PC, R14                         ; not known about, pass it on

        Push    "R3-R5"
        MOV     R3, R1, LSL #2                  ; make index a word index
        ADR     R2, BuffParms
        ADD     R2, R2, R3, LSL #1
        LDMIA   R2, {R2, R5}                    ; get address, size

      [ ZeroPage <> 0
        LDR     R4, =ZeroPage
        ADD     R3, R3, R4
      ]

        LDR     R4, [R3, #BuffInPtrs]
        STRB    R0, [R2, R4]                    ; store byte anyway
        ADD     R4, R4, #1                      ; increment pointer

        TEQ     R4, R5
        MOVEQ   R4, #0

        LDR     R5, [R3, #BuffOutPtrs]          ; does inptr=outptr ?
        CMP     R4, R5                          ; C=1 <=> R4 >= R5
        CMPHI   R5, R4                          ; C=1 <=> R4 = R5
        STRCC   R4, [R3, #BuffInPtrs]           ; if not, then safe

        BCC     %FT10                           ; no event, cos not full
        TEQ     R1, #(Buff_Mouse :SHL: 2), 2    ; clear carry and test if mouse
        CMPNE   R1, #Buff_RS423Out              ; C=1 => output buffer
        BCS     %FT10                           ; no event, cos not input

        MOV     R2, R0                          ; put character in 'Y'
        MOV     R0, #Event_InputFull            ; event number
        BL      OSEVEN                          ; preserves R0-R3
        MOV     R0, R2                          ; restore character
        SEC                                     ; indicate buffer full
10
        Pull    "R3-R5,PC"                      ; claim call

; *****************************************************************************
;
;       NewRemV - Routine for RemVec
;
; in:   R1 = buffer number (0 => keyboard buffer)
;       V=0 => remove character
;       V=1 => examine only
;
; out:  R0 = R2 = next character for examine option or character removed
;       R1, R3-R12 preserved
;       C=1 <=> buffer was empty on entry
;

NewRemV ROUT
        BVS     Examine

        Push    R14
        MRS     R14, CPSR
        CMP     R1, #NBuffers
        BLO     %FT10
        MSR     CPSR_f, R14
        Pull    PC              ; not known about, pass it on (preserving V)
10
        ADD     R13, R13, #4

        Push    "R3-R5"

      [ ZeroPage <> 0
        LDR     R4, =ZeroPage
        ADD     R3, R4, R1, LSL #2
      |
        MOV     R3, R1, LSL #2
      ]

        LDR     R4, [R3, #BuffOutPtrs]
        LDR     R5, [R3, #BuffInPtrs]

        CMP     R4, R5
        CMPHI   R5, R4                          ; C=1 <=> (R4 = R5) ie empty
        BCS     RemVExit

        ADR     R2, BuffParms
        ADD     R2, R2, R1, LSL #3
        LDMIA   R2, {R2, R5}                    ; get address, size

        LDRB    R2, [R2, R4]                    ; get next byte to be read out
        MOV     R0, R2
        ADD     R4, R4, #1                      ; increment out pointer

        TEQ     R4, R5                          ; wrap pointer if necessary
        MOVEQ   R4, #0

        STR     R4, [R3, #BuffOutPtrs]          ; bugfix - was STRB
        TEQ     R1, #Buff_Mouse                 ; mouse => not output buffer
        BEQ     RemVExit                        ; exit (C=0) if not
        CMP     R1, #Buff_RS423Out              ; C=1 => output buffer
        BCC     RemVExit                        ; exit (C=0) if not

        LDR     R5, [R3, #BuffInPtrs]           ; reload in-ptr
        TEQ     R4, R5                          ; are ptrs same now ?
        BNE     RemVExitCLC                     ; no, then exit setting C=0

        Push    R0                              ; save character
        MOV     R0, #Event_OutputEmpty          ; output buffer empty event
        BL      OSEVEN                          ; generate event
        Pull    R0                              ; restore character

RemVExitCLC
        CLC                                     ; make sure carry clear

RemVExit
        Pull    "R3-R5,PC"

Examine
        Push    R14
        MRS     R14, CPSR
        CMP     R1, #NBuffers
        BLO     %FT10
        MSR     CPSR_f, R14
        Pull    PC              ; not known about, pass it on (preserving V)
10

        Push    "R3-R5"

        MOV     R3, R1, LSL #2
        ADR     R2, BuffParms

        LDR     R2, [R2, R3, LSL #1]            ; R2 -> buffer

      [ ZeroPage <> 0
        LDR     R4, =ZeroPage
        ADD     R3, R3, R4
      ]

        LDR     R4, [R3, #BuffOutPtrs]
        LDR     R5, [R3, #BuffInPtrs]

        CMP     R4, R5
        CMPHI   R5, R4                          ; C=1 <=> (R4 = R5) ie empty

        LDRCCB  R2, [R2, R4]                    ; if ok then examine byte
        MOVCC   R0, R2

        Pull    "R3-R5,PC"

; *****************************************************************************
;
;       NewCnpV - Routine for CnpVec
;
; in:   R1 = buffer number (0 => keyboard)
;       V=0, C=0 => count entries
;       V=0, C=1 => count spaces
;       V=1 => purge buffer
;
; out:  R0 undefined
;       (purge) R1-R12 preserved
;       (count) R1,R2 = count, R3-R12 preserved
;

NewCnpV
        Push    R14
        MRS     R14, CPSR
        CMP     R1, #NBuffers
        BLO     %FT10
        MSR     CPSR_f, R14
        Pull    "PC"            ; not known about, pass it on (preserving V)
10
        ADD     R13, R13, #4

        Push    "R3-R5"

        MSR     CPSR_f, R14             ; restore V and C

      [ ZeroPage <> 0
        LDR     R4, =ZeroPage
        ADD     R3, R4, R1, LSL #2
      |
        MOV     R3, R1, LSL #2
      ]

        LDR     R4, [R3, #BuffOutPtrs]

        STRVS   R4, [R3, #BuffInPtrs]   ; if purge, then make in=out
        Pull    "R3-R5,PC", VS          ; and return

        LDR     R5, [R3, #BuffInPtrs]
      [ ZeroPage <> 0
        MOV     R3, R1, LSL #2
      ]
        SUB     R1, R5, R4              ; in - out (don't stamp on carry)

        ADR     R5, BuffParms+4
        LDR     R5, [R5, R3, LSL #1]    ; get size

        TEQ     R1, #0                  ; don't stamp on carry
        ADDMI   R1, R1, R5              ; wrap number of chars if negative

        SUBCS   R1, R5, R1              ; C=1 => convert to spaces
        SUBCS   R1, R1, #1              ; one fewer spaces than BuffSizes

        MOV     R2, R1, LSR #8          ; make R2 = hi-byte
        AND     R1, R1, #&FF            ; and  R1 = lo-byte

        Pull    "R3-R5,PC"

; *****************************************************************************

BuffParms
        &       KeyBuff
        &       KeyBuffSize

        &       RS423InBuff
        &       RS423InBuffSize

        &       RS423OutBuff
        &       RS423OutBuffSize

        &       PrintBuff
        &       PrintBuffSize

        &       Sound0Buff
        &       Sound0BuffSize

        &       Sound1Buff
        &       Sound1BuffSize

        &       Sound2Buff
        &       Sound2BuffSize

        &       Sound3Buff
        &       Sound3BuffSize

        &       SpeechBuff
        &       SpeechBuffSize

        &       MouseBuff
        &       MouseBuffSize

; *****************************************************************************
;
;       DoInsertESC - Insert character into buffer, checking for escape
;
; in:   R1 = buffer id
;       R2 = character
;

DoInsertESC
        CMP     R1, #2                          ; if not keyboard or serial input
        BCS     INSERT                          ; then don't treat as special

        LDROSB  R0, RS423mode                   ; Z => simulate keyboard
        TST     R0, R1                          ; NZ => RS423 input and RS8Bit
        BNE     INSERT

        Push    R14

        LDROSB  R0, ESCch                       ; escape character
        TEQ     R2, R0                          ; if escape character
        LDROSB  R0, ESCaction, EQ
        TEQEQ   R0, #0                          ; and FX229,0
        BNE     CKESCY                          ; not escape or let it thru

; ESCAPE detected

        LDROSB  R0, ESCBREAK                    ; FX 200
        TST     R0, #1                          ; bit 0 set ?
        BNE     %FT10                           ; escape ignored

        MOV     R0, #Event_Escape
        BL      OSEVEN                          ; exits carry set if disabled
        BCC     %FT10                           ; [event enabled, so don't do
                                                ; normal escape action]
        Push    "R1, R12"
        BL      DoOsbyte7D                      ; generate escape condition
        Pull    "R1, R12"
10
        CLC                                     ; character inserted OK
        Pull    PC

CKESCY
        MOV     R0, #Event_CharInput
        BL      OSEVEN                          ; preserves R0-R2
        Pull    R14
INSERT
        MOV     R0, R2
INSRT
        Push    "R10,R12,R14"
        MOV     R10, #INSV
GoVec
        BL      GoVec2
        Pull    "R10,R12,PC"

GoVec2
        CallAVector

        LTORG

        END