; 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.oseven

; *****************************************************************************
;
;       SWIPrintChar - Entry for SWI OS_PrintChar
;
; in:   R0 = character

SWIPrintChar ROUT
        Push    "R0-R9, R14"            ; save registers
        BYTEWS  WsPtr
        CLRV                            ; R14 on entry must have V=0
        BL      SWIPrintCharEntry
        STRVS   R0, [R13, #0]           ; if error then poke R0 to stack
        Pull    "R0-R9, R14"
        B       SLVK_TestV              ; return appropriately

; *****************************************************************************
;
;       MOSDoPrint - Print a character via VDU 1
;
; in:   R0 = character
;
; out:  V=0 => printed OK
;       V=1 => error, R0 -> error block
;

MOSDoPrint ROUT
        Push    "R12,R14"
        BYTEWS  WsPtr
        BL      MOSDoPrintWS
        Pull    "R12,PC"

MOSDoPrintWS                                    ; entry point when R12-> BYTEWS
        CLRV
        LDRB    R1, WrchDest
        TST     R1, #4                          ; is 'printer disabled' bit set ?
        MOVNE   PC, R14                         ; yes, then return with V clear
SWIPrintCharEntry
        LDRB    R1, PrinterDrivType             ; get the stream type
        B       FudgePrinterInsert

; *****************************************************************************
;
;       WRITE - Insert character into buffer
;       Retries until successful or ESCAPE condition
;
; in:   R0 = character
;       R1 = buffer number
;

WRITE   ROUT
        Push    R14
10
        BL      INSRT
        Pull    PC, CC

; insert code here to turn LEDs on

        LDR     R2, =ZeroPage
        LDRB    R2, [R2, #ESC_Status]
        MOVS    R2, R2, LSL #(32-6)
        Pull    PC, CS                  ; escape

        MRS     R14, CPSR
        BIC     R2, R14, #I32_bit
        MSR     CPSR_c, R2              ; CLI
      [ InterruptDelay
        NOP
        NOP
        NOP
        NOP
        NOP
      ]
        MSR     CPSR_c, R14             ; restore I
        B       %BT10

; *****************************************************************************
;
;       FudgePrinterInsert - Write byte to printer stream
;
; in:   R0 = character to send
;       R1 = printer type (3..255)
;       R12 -> BYTEWS
;       R14 has V_bit clear
;
; out:  V=0 => printed OK
;       V=1 => error, R0 -> error block
;

FudgePrinterInsert ROUT
        Push    R14

        LDR     R2, PrinterActive               ; R1=handle for printer stream
        TEQ     R2, #0
        MOVNE   R1, R2                          ; already have handle, so can
        BNE     %FT10                           ; corrupt R1

        Push    R0                              ; save character
        ADR     R0, PrinterTypeString
        ADR     R2, PrinterTypeName
05
        LDRB    R3, [R0], #1                    ; copy string from ROM to RAM
        TEQ     R3, #0
        STRNEB  R3, [R2], #1
        BNE     %BT05

        BL      OutputDecimalR1ToR2

        MOV     R0, #0                          ; terminate with 0
        STRB    R0, [R2]
        ADR     R0, PrinterTypeName+1           ; pointer to variable name
        MOV     R1, R2                  ; dummy expansion pointer
                                        ; (saving ptr to end of string!)
        MOV     R2, #-1                         ; don't accept chars
        MOV     R3, #0                          ; no wildcarding
        MOV     R4, #VarType_Expanded
        SWI     XOS_ReadVarVal                  ; on exit, R2=0 => no such var
        CMP     R2, #0
        Pull    "R0,PC", EQ                     ; so ignore this stream (V:=0)

        MOV     R0, #">"                        ; now stick ">",13 on end
        STRB    R0, [R1], #1
        MOV     R0, #13
        STRB    R0, [R1]

        ADR     R1, PrinterTypeName             ; point to "<PrinterType$nnn>"
        MOV     R0, #(open_write + open_mustopen + open_nodir)
        SWI     XOS_Find
        BLVS    StopPrinting                    ; stop printing
        Pull    "R1, PC", VS                    ; exit V set, not corrupting R0

        MOV     R1, R0                          ; will always be non-zero
        Pull    R0                              ; restore character

        STR     R1, PrinterActive               ; store new handle
10
        SWI     XOS_BPut                        ; R0 = byte to send
        Pull    PC, VC                          ; no error, so exit

        BL      StopPrinting                    ; preserves R0,R1
        Push    R0                              ; save error pointer
        MOV     R0, #0                          ; CLOSE reason code
        STR     R0, PrinterActive               ; zero handle
        SWI     XOS_Find                        ; close channel
        SETV
        Pull    "R0,PC"                         ; return V set


PrinterTypeString
        =       "<",PrinterPrefix,0
        ALIGN

MakePrinterDormant
        LDR     R3, PrinterActive               ; printer handle
        CMP     R3, #0                          ; no active handle if 0 (also clears V if zero)
        MOVEQ   PC, R14
        Push    "R0,R1,R14"
        MOV     R1, R3                          ; R1 = handle
        MOV     R0, #0                          ; close reason code
        STR     R0, PrinterActive               ; zero handle
        SWI     XOS_Find
        BLVS    StopPrinting
        Pull    R0, VC                          ; if no error, preserve R0
        ADDVS   R13, R13, #4                    ; else junk R0
        Pull    "R1,PC"

; *****************************************************************************
;
;       StopPrinting - Clear bits 3 and 5 of FX3, bit 0 of VduStatus
;
;       Preserves all registers (including status)
;

StopPrinting ROUT
        Push    "R0,R1"                         ; don't corrupt the flags!
        LDRB    R0, WrchDest
        BIC     R0, R0, #(1:SHL:3) :OR: (1:SHL:5)
        STRB    R0, WrchDest
        VDWS    R1
        LDR     R0, [R1, #VduStatus]
        BIC     R0, R0, #1                      ; clear VDU 2 bit
        STR     R0, [R1, #VduStatus]
        Pull    "R0,R1"
        MOV     PC, R14                         ; returning preserving flags

; *****************************************************************************
;
;       OutputDecimalR1ToR2 - Output a decimal byte
;
; in:   R1 = number to output
;       R2 = buffer to accept chars
;
; out:  R0, R3 corrupt

OutputDecimalR1ToR2 ROUT
        MOV     R0, #100                        ; do hundreds first
10
        MOV     R3, #"0"
20
        SUBS    R1, R1, R0
        ADDCS   R3, R3, #1
        BCS     %BT20
        ADD     R1, R1, R0
        CMP     R3, #"0"                        ; if digit non-zero
        STRNEB  R3, [R2], #1                    ; then output
        TEQ     R0, #10
        MOVNE   R0, #10                         ; then do tens digit
        BNE     %BT10

        ORR     R1, R1, #"0"
        STRB    R1, [R2], #1                    ; output units digit
        MOV     PC, R14


        END