; 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.
;
        TTL     => MoreComms

Error_Code ROUT
        ; Use MessageTrans to construct an error block by substituting the error text into
        ; an error

        Push    "r7,r8,lr"

        ASSERT  ?Error_CodeTag <= 8
        ADR     lr, Error_CodeTag
        LDMIA   lr, {r1,r2}
        Push    "r1,r2"

        MOV     r1, r0          ; pointer
        MOV     r0, #0          ; base
        SWI     XOS_ReadUnsigned
        Push    "r2"

        MOV     r0, sp          ; Error block
 [ :LNOT:International
        ; Haven't got any alternate code, but at least it'll assemble
 |
        BL      TranslateError_VClear
 ]

        ; If error number's changed don't substitute
        LDR     r3, [r0]
        TEQ     r3, r2
        BNE     %FT90

        ; GSTrans the text into the error buffer
        MOV     r3, r0
        MOV     r0, r1
        ADD     r1, r3, #4
        MOV     r2, #252
        SWI     XOS_GSTrans

        ; Ensure 0-terminated
        MOV     r0, #0
        CMP     r2, #251
        MOVHI   r2, #251
        STRB    r0, [r1, r2]

        MOV     r0, r3
90
        ADD     sp, sp, #12
        SETV
        Pull    "r7,r8,pc"

Error_CodeTag DCB "ErrSub", 0

        LTORG

Eval_Code ROUT
             Push  "lr"
             LDR    R1, =GeneralMOSBuffer
             MOV    R2, #LongCLISize
             SWI    XOS_EvaluateExpression
             Pull  "PC", VS
           [ :LNOT: International
             SWI    XOS_WriteS
             =     "Result is a",0
             ALIGN
             Pull  "PC", VS
             CMP    R1, #0
             ADREQ  R0, %FT01
             ADRNE  R0, %FT02
             SWI    XOS_Write0
             Pull  "PC", VS
             SWI    XOS_WriteS
             =     ", value : ",0
             ALIGN
             Pull  "PC", VS
           |
             Push   "r4"
             CMP    R1, #0
             ADREQ  R0, %FT01
             ADRNE  R0, %FT02
             BL     FindToken
             MOV    R4,R0
             BL     WriteS_Translated_UseR4
             =      "Result:Result is %0, value :",0
             ALIGN
             SWI    XOS_WriteI + " "
             Pull   "r4"

           ]
             LDREQ  R1, =GeneralMOSBuffer
             MOVEQ  R0, R2
             MOVEQ  R2, #256
             SWIEQ  XOS_BinaryToDecimal
             MOV    R5, #-1
03           ADD    R5, R5, #1
             CMP    R5, R2
             BEQ    %FT04
             LDRB   R0, [R1, R5]
             CMP    R0, #&7F
             MOVEQ  R0, #"?"-"@"   ; preversion!!
             CMP    R0, #31
             ADDLE  R0, R0, #"@"
             SWILE  XOS_WriteI+"|"
             Pull  "PC", VS
             CMP    R0, #"|"
             CMPNE  R0, #""""
             CMPNE  R0, #"<"
             SWIEQ  XOS_WriteI+"|"
             SWIVC  XOS_WriteC
             BVC    %BT03

04           SWIVC  XOS_NewLine
             Pull  "PC"

        [ International
01
    =    "Integer:an integer",0
02
    =    "String:a string",0
        |
01
    =    "n integer",0
02
    =    " string",0
        ]

    ALIGN

;****************************************************************************
; Coupla utility commands

Time_Code    ROUT
     Push   "lr"
     SUB     R13, R13, #8
     MOV     R1, R13
     MOV     R0, #3
     STRB    R0, [R1]
     MOV     R0, #14
     SWI     XOS_Word
     BVS     %FT01
     MOV     R0, #-1
     MOV     R1, R13
     LDR     R2, =GeneralMOSBuffer
     MOV     R3, #256
     ADRL    R4, TimeFormat
     SWI     XTerritory_ConvertDateAndTime
01   ADD     R13, R13, #8
     SWIVC   XOS_Write0
     SWIVC   XOS_NewLine
     Pull   "PC"

Cache_Code   ROUT
     Push    "lr"
     TEQ     r1, #0
     BNE     %FT05

     ; Report
     MOV     r0, #MMUCReason_ModifyControl
     MOV     r1, #0             ; EOR mask
     MOV     r2, #-1            ; AND mask (ie don't modify)
     SWI     XOS_MMUControl
     Pull    "PC", VS

     SWI     XOS_WriteS
     DCB     "Cache ", 0
     ALIGN
     Pull    "PC", VS

     TST     r1, #MMUC_C
     ADRNE   r0, %FT02
     ADREQ   r0, %FT03
     SWI     XOS_Write0
     SWIVC   XOS_NewLine
     Pull    "PC"
02
     DCB     "On", 0            ; Not internationalised because the
03                              ; command expects english 'On' or 'Off'
     DCB     "Off", 0           ; to set it so should report in english
     ALIGN
05
     ; Set
     BL      Cache_Opt_Parse
     MOVS    r1, r1
     BPL     %FT07
     ADRL    r0, ErrorBlock_BadParameters
   [ International
     BL      TranslateError
   |
     SETV
   ]
07
     LDR     r2, =:NOT: (MMUC_I + MMUC_C + MMUC_W)
     LDRNE   r1, =0
     LDREQ   r1, =MMUC_I + MMUC_C + MMUC_W
     MOVVC   r0, #MMUCReason_ModifyControl
     SWIVC   XOS_MMUControl
     Pull    "PC"

Cache_Opt_Parse
     ; => R0 -> control terminated string
     ; <= R1 = 0, 1, or -ve for error
     LDRB    r2, [r0], #1
     TEQ     r2, #'O'
     TEQNE   r2, #'o'
     BNE     %FT15
     LDRB    r2, [r0], #1
     TEQ     r2, #'N'
     TEQNE   r2, #'n'
     BEQ     %FT12
     TEQ     r2, #'F'
     TEQNE   r2, #'f'
     BNE     %FT15
     LDRB    r2, [r0], #1
     TEQ     r2, #'F'
     TEQNE   r2, #'f'
     BNE     %FT15
     ; Off
     MOVS    r1, #1
12
     ; On
     MOVEQ   r1, #0
13
     ; Check for trailing text
     LDRB    r2, [r0], #1
     CMP     r2, #' '
     BEQ     %BT13
     MOVCC   pc, lr
15
     ; Error
     SETV
     MOV     r1, #-1
     MOV     pc, lr

Ignore_Code  ROUT
     Push   "lr"
     MOVS    R4, R1
     MOV     R1, R0
     MOV     R0, #10+ (1:SHL:30)
     SWINE   XOS_ReadUnsigned
     Pull   "PC", VS
     MOV     R6, R2        ; maybe number
     BL      CheckEOL
     BNE     %FT01

     CMP     R4, #0
     MOV     R0, #&B6
     MOVEQ   R1, #255
     MOVNE   R1, #0
     MOV     R2, #0
     SWI     XOS_Byte
     MOV     R0, #6
     MOV     R1, R6
     SWINE   XOS_Byte
     Pull   "PC"

01   ADRL    R0, ErrorBlock_BadNumb
   [ International
     BL      TranslateError
   |
     SETV
   ]
     Pull   "PC"

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

ROMModules_Code Entry
      [ International
        BL      GSWriteS_Translated
        =       "ROMMTitle:No. Position|IModule Name|I|IVersion|IStatus|M|J",0
        EXIT    VS
      |
        ADRL    r0, romm_helpstr
        MOV     r1, #0
        SWI     XOS_PrettyPrint
        EXIT    VS
      ]
        MOV     r1, #0
        MOV     r2, #-1
01
        SWI     XOS_ReadEscapeState
        PullEnv CS
        BCS     AckEscape
        MOV     r0, #ModHandReason_EnumerateROM_ModulesWithInfo
        SWI     XOS_Module
        BVC     %FT08
        CLRV
        EXIT                                            ; exit V clear

; R1 = module number +1
; R2 = podule number
; R3 -> name
; R4 = status (-1 unplugged, 0 dormant, 1 active, 2 running)
; R5 = chunk number
; R6 = version number

; Copy info into buffer and prettyprint
08
        MOV     r5, r1                                  ; save r1 and r2 for next call to OS_Module
        MOV     r10, r2
        MOV     r0, r1
        MOV     r2, #4
        SUB     sp, sp, #4
        MOV     r1, sp
        SWI     XOS_ConvertCardinal2
        ADD     sp, sp, #4
        SUB     r12, r1, r0
        LDR     r1, =GeneralMOSBuffer
        MOV     r2, #256
        MOV     r0, #31
        RSBS    r12, r12, #3
15      BLNE    %FT20
        SUBS    r12, r12, #1
        BPL     %BT15
        MOV     r0, r5
        SWI     XOS_ConvertCardinal2
        MOV     r0, #" "
        BL      %FT20                                   ; add space
        CMP     r10, #-1
      [ International
        ADREQL  r0, rommpossysrom
        ADRLTL  r0, rommposextrom
        ADRGTL  r0, rommpospodule
        BL      FindToken
      |
        ADREQL  r0, rommpossr
        ADRLTL  r0, rommposer
        ADRGTL  r0, rommposp
      ]
        BL      %FT21                                   ; add string
        MOV     r0, #" "
        BL      %FT20                                   ; add space
        MOVGT   r0, r10                                 ; if normal podule then use plain number (flags still set from CMP)
        MVNLT   r0, r10                                 ; if extension ROM then NOT it (-2 => 1, -3 => 2 etc)
        SWINE   XOS_ConvertCardinal1
        MOV     r0, #TAB
        BL      %FT20                                   ; tab to col. 16
        MOV     r0, r3
        BL      %FT21                                   ; copy name in
        MOV     r3, r0                                  ; string length
        MOV     r0, #TAB
03
        CMP     r3, #24
        ADDCC   r3, r3, #8
        BLCC    %FT20
        BCC     %BT03
04
        MOV     r11, #"0"
        TST     r6, #&F0000000                          ; 1st digit of integer part
        ORRNE   r0, r11, r6, LSR #28
        BLNE    %FT20
        MOV     r6, r6, LSL #4
        TSTEQ   r6, #&F0000000                          ; 2nd digit of integer part
        ORRNE   r0, r11, r6, LSR #28
        BLNE    %FT20
        MOV     r6, r6, LSL #4
        TSTEQ   r6, #&F0000000                          ; 3rd digit of integer part
        ORRNE   r0, r11, r6, LSR #28
        BLNE    %FT20
        MOV     r6, r6, LSL #4
        ORR     r0, r11, r6, LSR #28                    ; 4th digit of integer part
        BL      %FT20
        MOV     r0, #"."
        BL      %FT20
        MOV     r6, r6, LSL #4
        ORR     r0, r11, r6, LSR #28                    ; 1st digit of decimal part
        BL      %FT20
        MOV     r6, r6, LSL #4
        ORR     r0, r11, r6, LSR #28                    ; 2nd digit of decimal part
        BL      %FT20
        MOVS    r6, r6, LSL #4                          ; only print 3rd and 4th digits of decimal part if non-zero
        ORRNE   r0, r11, r6, LSR #28
        BLNE    %FT20
        MOVS    r6, r6, LSL #4
        ORRNE   r0, r11, r6, LSR #28
        BLNE    %FT20
        MOV     r0, #TAB
        BL      %FT20

        CMP     r4, #0
      [ International
        ADRMIL  r0, rommstatu
        ADREQL  r0, rommstatd
        ADRGTL  r0, rommstata
        BL      FindToken
      |
        ADRMIL  r0, rommstu
        ADREQL  r0, rommstd
        ADRGTL  r0, rommsta
      ]
        CMP     r4, #2
      [ International
        ADREQL  r0, rommstatr
        BLEQ    FindToken
      |
        ADREQL  r0, rommstr
      ]
        BL      %FT21
        MOV     r0, #13
        BL      %FT20
        MOV     r0, #0
        BL      %FT20
        LDR     r0, =GeneralMOSBuffer
        MOV     r1, #0
        SWI     XOS_PrettyPrint
        EXIT    VS
        MOV     r1, r5
        MOV     r2, r10
        B       %BT01

; R1 buffer ptr, R2 bufflen left

20
        EntryS
        SUBS    r2, r2, #1
        STRPLB  r0, [r1], #1
        EXITS
21
        EntryS
        Push    "r0"
        MOV     r12, r0
22
        LDRB    r0, [r12], #1
        CMP     r0, #TokenEscapeChar
        BEQ     %FT23
        CMP     r0, #0
      [ International
        CMPNE   r0, #10
      ]
        BLNE    %BT20
        BNE     %BT22
        Pull    "r0"
        SUB     r0, r12, r0       ; length of string
        SUB     r0, r0, #1
        EXITS

23
        BL      %BT20
        LDRB    r0, [r12], #1
        BL      %BT20
        B       %BT22

      [ International
rommpossysrom
     =   "SYSROM:System ROM", 0
rommposextrom
     =   "EXTROM:Extn ROM", 0
rommpospodule
     =   "PODROM:Podule", 0

rommstata
     =   "Active:Active", 0

rommstatd
     =   "Dormant:Dormant", 0

rommstatu
     =   "Unplugged:Unplugged", 0

rommstatr
     =   "Running:Running",0

     ALIGN
      |
romm_helpstr
     =   "No. Position",9,"Module Name",9,9,"Version",9,"Status",10,13,0
rommpossr
     =   "System ROM", 0
rommstu
     =   "Unplugged", 0
rommstd
     =   "Dormant", 0
rommsta
     =   "Active", 0
rommstr
     =   "Running", 0

     ALIGN
      ]
     LTORG

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

RMEnsure_Code Entry "r0, r1"
        MOV     r1, r0                          ; name pointer
        MOV     r0, #ModHandReason_LookupName
        SWI     XOS_Module
        MOVVS   r10, r0                         ; module handler will build a nice error
        BVS     RMEDoCommand                    ; module not found
        LDR     r0, [stack]                     ; now find version number
01
        LDRB    r6, [r0], #1
        CMP     r6, #" "
        BNE     %BT01
        BL      RMEGetVerNo
        MOV     r6, r1
        LDR     r0, [r3, #Module_HelpStr]
        TEQ     r0, #0
        BEQ     RMEDoCommand                    ; no help string, so do command
        ADD     r0, r0, r3
        BL      GetVerNoFromHelpString
        CMP     r1, r6
        EXIT    GE
        MOV     r10, #0
RMEDoCommand
        Pull    "r0, r1"
        CMP     r1, #2
        BEQ     BuildRMEnsureError
04
        LDRB    r1, [r0], #1
        CMP     r1, #" "
        BNE     %BT04
05
        LDRB    r1, [r0], #1
        CMP     r1, #" "
        BEQ     %BT05
06
        LDRB    r1, [r0], #1
        CMP     r1, #" "
        BNE     %BT06
        SUB     r0, r0, #1
03
        SWI     XOS_CLI
        Pull    PC

BuildRMEnsureError
        MOVS    r0, r10
        BEQ     %FT10
        SETV
        Pull    pc
10      ADR     r0, ErrorBlock_ModuleTooOld
      [ International
        LDR     r4,[r3, #Module_TitleStr]
        ADD     r4,r4,r3
        BL      TranslateError_UseR4            ; => V set
        Pull    pc
      |
        BL      GetOscliBuffer
        MOV     r10, r5
        LDR     r2, [r0], #4
        STR     r2, [r5], #4
        BL      rmecopystr
        MOV     r6, r0

        LDR     r2, [r3, #Module_TitleStr]      ; r3 still module pointer
        ADD     r0, r2, r3
        BL      rmecopystr
        MOV     r0, r6
        BL      rmecopystr
        STRB    r2, [r5]                        ; terminate
        B       BuildRMEnsureError
      ]

rmecopystr
        LDRB    r2, [r0], #1
        CMP     r2, #32
        STRGEB  r2, [r5], #1
        BGE     rmecopystr
        MOV     pc, lr

        MakeErrorBlock ModuleTooOld

; *************************************************************************
;
;       RMEGetVerNo - Read version number from a string
;
; in:   R0 -> string
;
; out:  R0, R4, R5, R12 corrupted
;       R1 = version number in BCD with the decimal point between bits 15 and 16
;            eg "2.34" => &00023400, "5.6789" => &00056789, "17" => &00170000
;            only the last 4 digits of the integer part, and the first 4 decimal places are stored
;

RMEGetVerNo Entry
        MOV     r1, #0
10
        LDRB    r12, [r0], #1
        CMP     r12, #" "
        BEQ     %BT10
11
        SUB     r12, r12, #"0"
        CMP     r12, #9
        ORRLS   r1, r12, r1, LSL #4             ; just keep nibbles - we only need the
        LDRLSB  r12, [r0], #1                   ; result to be ordered, not continous
        BLS     %BT11
        MOV     r5, #0
        CMP     r12, #"."-"0"
        BNE     %FT13
        MOV     r4, #16
12
        SUBS    r4, r4, #4
        BMI     %FT13
        LDRB    r12, [r0], #1
        SUB     r12, r12, #"0"
        CMP     r12, #9
        ORRLS   r5, r5, r12, LSL r4
        BLS     %BT12
13
        ORR     r1, r5, r1, LSL #16
        EXIT

; *************************************************************************
;
;       GetVerNoFromHelpString - Read version number from a module help string
;
; in:   R0 -> module help string
;
; out:  R1 = version number in BCD with the decimal point between bits 15 and 16
;            eg "2.34" => &00023400, "5.6789" => &00056789, "17" => &00170000
;            only the last 4 digits of the integer part, and the first 4 decimal places are stored
;       All other registers preserved
;

GetVerNoFromHelpString Entry "r0, r4, r5, r12"
        MOV     r5, #0                          ; char count
10
        LDRB    r1, [r0], #1
        CMP     r1, #0                          ; check character
        EXIT    EQ                              ; if end of string then no version number so return zero
        ADD     r5, r5, #1
        CMP     r1, #TAB
        ADDEQ   r5, r5, #7
        BICEQ   r5, r5, #7
        CMP     r5, #16                         ; hit verno col yet?
        BLT     %BT10
20
        LDRB    r1, [r0], #1
        CMP     r1, #TAB
        CMPNE   r1, #31                         ; if a control character (except TAB)
        MOVLT   r1, #0                          ; then no version number so return zero
        EXIT    LT
        SUB     r1, r1, #"0"
        CMP     r1, #9                          ; if not a digit
        BHI     %BT20                           ; then try next character
        SUB     r0, r0, #1                      ; was a digit so go back to it
        BL      RMEGetVerNo                     ; read version number from here
        EXIT

        END