; 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 => MoreSWIs ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SubstituteArgs ; in: R0 -> arglist (space delimited args, terminated by 10,13,0) ; R1 -> buffer ; R2 = bufflen ; R3 -> string to mangle ; R4 = no of chars in $R3 ; out: R2 = no of chars in buffer XOS_SubstituteArgs_code Push "r5,lr" MOV r5, #0 SWI XOS_SubstituteArgs32 Pull "r5,lr" B SLVK_TestV ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SubstituteArgs32 ; in: R0 -> arglist (space delimited args, terminated by 10,13,0) ; R1 -> buffer ; R2 = bufflen ; R3 -> string to mangle ; R4 = no of chars in $R3 ; R5 = flags ; top bit set => don't append unused part of line ; out: R2 = no of chars in buffer XOS_SubstituteArgs32_code ROUT WritePSRc SVC_mode, R12 ; enable IRQs NOP Push "R0-R8, lr" ADD R8, R4, R3 ; try and get parameter positions. ; Items starting with " can have spaces in MOV R6, #0 ; parameter number LDR R12, =MacExStartPtrs LDR R4, =MacExEndPtrs 35 LDRB R5, [R0], #1 CMP R5, #" " BEQ %BT35 MOV R2, #" " CMP R5, #"""" MOVEQ R2, #"""" ; quoted param CMP r6, #10 ; "rest of line" item? MOVEQ r2, #-1 ; terminate on EOL only SUB R0, R0, #1 STR R0, [R12, R6, LSL #2] CMP r5, #"""" ADDEQ R0, R0, #1 36 LDRB R5, [R0], #1 BL suba_chktrm CMPNE R5, R2 BNE %BT36 CMP R5, #"""" LDREQB R5, [R0] CMPEQ R5, #"""" ; check for "" in string ADDEQ R0, R0, #1 BEQ %BT36 CMP R2, #"""" SUBNE R0, R0, #1 STR R0, [R4, R6, LSL #2] ADD R6, R6, #1 CMP R6, #11 ; Parameters 0-9 and a "rest" set. BNE %BT35 ; Keep track of highest param used, so can tack any unused stuff on end. ; R3 points at string to get chars from ; R12 at start ptrs ; R4 at end ptrs MOV R6, #0 ; count. MOV R7, #0 ; highest param used. LDR R2, [stack, #4*2] 37 BL suba_getchar BEQ %FT41 CMP R5, #"%" BEQ %FT44 38 BL suba_addchar B %BT37 PCnotparm ADD R5, R5, #"0" MOV R11, R5 MOV R5, #"%" BL suba_addchar MOV R5, R11 B %BT38 44 BL suba_getchar MOVEQ R5, #"%" BEQ %FT40 CMP R5, #"%" BEQ %BT38 CMP R5, #"*" BEQ DoStarParams SUBS R5, R5, #"0" BMI PCnotparm CMP R5, #9 BGT PCnotparm ; itsa parameter! Get ptrs from R12, R4 CMP R5, R7 ADDGE R7, R5, #1 LDR R11, [R4, R5, LSL #2] CopyToR11FromParamR5 LDR R10, [R12, R5, LSL #2] ; start ptr 39 LDRB R5, [R10], #1 CMP R10, R11 BGT %BT37 BL suba_addchar B %BT39 DoStarParams ; had %* : find limits to copy between BL suba_getchar BEQ PCStarTerminates SUBS R5, R5, #"0" BMI PCStarNoDigit CMP R5, #9 MOVLE R7, #11 ; flag * used LDRLE R11, [R4, #10*4] ; always to EOL BLE CopyToR11FromParamR5 PCStarNoDigit ADD R5, R5, #"0" MOV R11, R5 MOV R5, #"%" BL suba_addchar MOV R5, #"*" BL suba_addchar MOV R5, R11 B %BT38 PCStarTerminates MOV R5, #"%" BL suba_addchar MOV R5, #"*" 40 BL suba_addchar 41 CMP r7, #11 LDREQ r12, [r4, #10*4] ; no more to copy BEQ %FT42 LDR r0, [stack, #4*5] CMP r0, #0 LDRPL R12, [R12, R7, LSL #2] ; ptr to rest of command line : copy LDRMI r12, [r4, #10*4] ; caller wants no appending. 42 LDRB R5, [R12], #1 BL suba_addchar BL suba_chktrm BNE %BT42 STR R6, [stack, #4*2] Pull "R0-R8, lr" ExitSWIHandler suba_addchar EntryS ADD R6, R6, #1 CMP R6, R2 STRNEB R5, [R1], #1 EXITS NE PullEnv ADRL R0, ErrorBlock_BuffOverflow [ International BL TranslateError ] STR R0, [stack] Pull "R0-R8, lr" B SLVK_SetV suba_getchar CMP R3, R8 LDRNEB R5, [R3], #1 MOV PC, lr suba_chktrm CMP R5, #13 CMPNE R5, #10 CMPNE R5, #0 MOV PC, lr LTORG ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Take R0 as pointer to null-terminated string, print it ; with line breaks before words that won't fit on the current line. ; CR forces a newline. TAB=tab to next column of 8. CHR$31 = hard space ; <27,n> => substitute nth dictionary entry: ; dictionary is pointed at by r1, consists of a list of null-terminated ; strings, with preceding length bytes. ; 0th dictentry => use string at r2. XOS_PrettyPrint_code ROUT ; Inside here, r1 is the current string pointer ; R3 is the linelength to format to ; R4 is the current position in the line. ; r6 is the return addr in word counting ; r7 is the r1 restore value in reading word length ; r8 is used in dictionary selection in getbytepp ; r9 is the stack restoration level for exiting. ; r11 is the dictionary pointer (0 means use MOS dict) ; r12 is the special token pointer WritePSRc SVC_mode, r11 Push "r0-r9, lr" BL ReadWindowWidth ; read linelength MOV R3, R0 MOV R0, #165 ; read output cursor SWI XOS_Byte ORR R4, R1, #&80000000 ; no leading space even if in line. LDMFD stack, {r1, r11, r12} ; reload strptr, dictptr, tokptr CMP r11, #0 ADREQL r11, MOSdictionary MOV r9, stack ; loop over all words 01 BL getwordlength CMP R2, #0 BNE %FT03 BL getbytepp B %FT21 ; null word - test for done 03 CMP R4, #0 ADDGT R2, R2, #1 ; allow for separator ADD R0, R2, R4 BIC R0, R0, #&80000000 ; clear R4 flag CMP R0, R3 BLE %FT10 CMP R4, #0 SUBGT R2, R2, #1 ; remove leading space length MOV R4, #0 ; if word too long to fit, do newline SWI XOS_NewLine BVS exitpp 10 CMP R4, #0 BIC R4, R4, #&80000000 ; clear "no leading space" flag ADD R4, R4, R2 SUBGT R2, R2, #1 SWIGT XOS_WriteI+" " ; output separator if not 1st on line BVS exitpp 04 BL getbytepp CMP R0, #31 ; hard space? MOVEQ R0, #" " SWI XOS_WriteC BVS exitpp SUBS R2, R2, #1 BNE %BT04 21 CMP R0, #13 MOVEQ R4, #0 SWIEQ XOS_NewLine BVS exitpp CMP R0, #TAB BEQ %FT20 CMP R0, #0 BNE %BT01 exitpp MOV stack, r9 STRVS r0, [stack] Pull "r0-r9,lr" B SLVK_TestV ; TAB had: align to next multiple of 8 20 BIC R4, R4, #&80000000 ; first want to get next word length, to see if it's worth doing ADD R5, R4, #8 BIC R5, R5, #7 SUB R5, R5, R4 ; spaces for this tab 24 BL getwordlength CMP R2, #0 BNE %FT23 ; got the word BL getbytepp CMP R0, #13 BEQ %BT21 ; TAB, CR - whalley! CMP R0, #TAB SUBNE R5, R5, #1 ; leading spaces, junk ignored ADDEQ R5, R5, #8 ; multiple tabs OK tho. CMP r0, #0 ; terminator? BNE %BT24 ; only case to allow zero-length word SUB r1, r1, #1 ; we know this rewinds OK 23 ADD R0, R4, R5 ADD R0, R0, R2 CMP R0, R3 MOVGT R0, #13 ; next tab stop too far : newline BGT %BT21 22 SWI XOS_WriteI+" " BVS exitpp ADD R4, R4, #1 SUBS r5, r5, #1 BNE %BT22 ORR R4, R4, #&80000000 ; set top bit to disable leading space B %BT01 getwordlength MOV r6, lr MOV r10, r9 ; first copy context MOV r2, stack MOV r7, r1 copycontextpp CMP r9, r2 LDRNE r0, [r9, #-4]! Push r0, NE BNE copycontextpp MOV r2, #0 ; word length 02 BL getbytepp CMP R0, #31 CMPNE R0, #" "+1 ADDGE r2, r2, #1 BGE %BT02 MOV r1, r7 MOV stack, r9 MOV r9, r10 MOV pc, r6 getbytepp LDRB r0, [r1], #1 CMP r0, #TokenEscapeChar BEQ gettokenpp CMP r0, #0 MOVNE pc, lr CMP stack, r9 MOVHS pc, lr Pull r1 ; back to previous token B getbytepp gettokenpp LDRB r0, [r1], #1 ; tokno Push r1 ; save context CMP r0, #0 MOVEQ r1, r12 BEQ getbytepp MOV r1, r11 gtoklp SUBS r0, r0, #1 LDRNEB r8, [r1] ADDNE r1, r1, r8 BNE gtoklp ADD r1, r1, #1 B getbytepp ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ReadWindowWidth ROUT ; read "number of chars printable after Newline ; before we're on the next line" MOV R0, #VduExt_WindowWidth ReadVduVarForSam Push "R0, R1, lr" ; R1 reserves space MOV R0, #-1 STR R0, [stack, #4] ; overwrite R1 value MOV R0, sp MOV R1, sp SWI XOS_ReadVduVariables LDR R0, [sp], #8 LDR pc, [sp], #4 ;***************************************************************************** ; R0 -> envstring, R1 -> 5 byte time WriteEnv_SWICode ROUT ; for debugger use CMP R0, #0 BEQ %FT01 LDR R10, =EnvString MOV R11, R0 02 LDRB R12, [R11], #1 CMP R12, #" " MOVLT R12, #0 STRB R12, [R10], #1 BGE %BT02 01 CMP R1, #0 ExitSWIHandler EQ LDR R10, =ZeroPage+EnvTime MOV R11, #4 03 LDRB R12, [R1, R11] STRB R12, [R10, R11] SUBS R11, R11, #1 BPL %BT03 ExitSWIHandler ;***************************************************************************** ; LET RdArgs() BE ; R0 ptr to key defn string ; R1 ptr to command line to decode ; R2 ptr to workspace ; R3 size of workspace ; Returns R3 size left ; Flags used in initial args decoding AFlag * 1:SHL:8 ; flags shifted up a byte; avoid looking like chars. KFlag * 1:SHL:9 SFlag * 1:SHL:10 EFlag * 1:SHL:11 GFlag * 1:SHL:12 UnsetBase * &FF000000 ; only if all bits set (cannot be RAM address) PresentFlag * &7FFFFFFF AbsentFlag * 0 ; Type flags EndType * 0 FlagType * 1 KeywordType * 2 ItemType * 3 RdArgs_SWICode ROUT WritePSRc SVC_mode, R10 Push "R4, R8, R9, lr" MOV R10, R2 ; R10 points at next available word MOV R12, R0 01 MOV R11, #UnsetBase SUBS R3, R3, #4 BMI %FT99 ; insufficient space STR R11, [R10], #4 02 LDRB R11, [R12], #1 CMP R11, #"/" BNE %FT03 LDRB R11, [R12], #1 UpperCase R11, R9 CMP R11, #"A" MOVEQ R11, #AFlag CMP R11, #"K" MOVEQ R11, #KFlag CMP R11, #"S" MOVEQ R11, #SFlag CMP R11, #"E" MOVEQ R11, #EFlag CMP R11, #"G" MOVEQ R11, #GFlag CMP R11, #256 LDRGE R9, [R10, #-4] ORRGE R9, R11, R9 STRGE R9, [R10, #-4] 03 CMP R11, #"," BEQ %BT01 CMP R11, #" " BGE %BT02 ; Initialisation complete: all flags set, R10 implies number of args. MOV R8, R10 10 BL RdItem BVS %FT90 CMP R12, #KeywordType BNE %FT11 ADD R11, R2, R4, LSL #2 ; keyword ptr BL RdItem BVS %FT90 CMP R12, #ItemType BNE %FT98 BL SetKeyword BVS %FT90 B %BT10 11 CMP R12, #ItemType BNE %FT12 ; next positional arg := itemptr MOV R11, R2 20 CMP R11, R8 BEQ %FT98 ; no more positional args LDR R12, [R11], #4 CMP R12, #UnsetBase BLO %BT20 TST R12, #KFlag :OR: SFlag BNE %BT20 SUB R11, R11, #4 BL SetKeyword BVS %FT90 B %BT10 12 CMP R12, #EndType BNE %BT10 ; postscan to check all /a args set. MOV R12, R2 30 CMP R12, R8 BEQ %FT31 LDR R11, [R12], #4 CMP R11, #UnsetBase BLO %BT30 TST R11, #AFlag BNE %FT98 ; bum args error MOV R11, #AbsentFlag STR R11, [R12, #-4] ; force "not present" B %BT30 31 Pull "R4, R8, R9, lr" ExitSWIHandler 98 ADR R0, ErrorBlock_BadParameters [ International BL TranslateError ] B %FT90 99 ADRL R0, ErrorBlock_BuffOverflow [ International BL TranslateError ] 90 Pull "R4, R8, R9, lr" B SLVK_SetV EXPORT ErrorBlock_BadParameters MakeErrorBlock BadParameters MakeErrorBlock ArgRepeated ALIGN ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; RdItem: strips next item from command line ; In: R1 -> cmd line ; Out: R1 updated ; R12 contains type ; R4 contains ptr for Item, argno for Flag/Keyword ; VS means buffer full ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ RdItem ROUT Push "R1, R7, R8, lr" MOV R8, #0 ; not demanding new arg 01 LDRB R12, [R1], #1 CMP R12, #" " BEQ %BT01 BGE %FT33 MOV R12, #EndType CLRV Pull "R1, R7, R8, PC" 33 CMP R12, #"""" BEQ ohnoitsquotedargumentsagain CMP R12, #"-" ; options? BNE %FT02 ; nope - boring item 05 BL GetArg LDRVS R1, [stack] BVS %FT02 ; not recognised - boring item STR R1, [stack] ; new restore value. MRS R12, CPSR Push R12 ; save EQ/NE LDR R12, [R2, R4, LSL #2] CMP R12, #UnsetBase BHS %FT34 ADR R0, ErrorBlock_ArgRepeated [ International BL TranslateError | SETV ] ADD stack, stack, #4 ; discard PSR Pull "R1, R7, R8, PC" 34 ANDS R12, R12, #SFlag BNE %FT35 MOV R12, #KeywordType ADD stack, stack, #4 ; discard PSR CLRV Pull "R1, R7, R8, PC" 35 MOV R12, #PresentFlag STR R12, [R2, R4, LSL #2] ; now deal with flag elision: if nextchar valid keyword char, rescan Pull R12 TST R12, #Z_bit BEQ %FT20 ; GetArg returned NE, so not single char abbr Push "R2, R3" LDRB R2, [R1] BL CheckR2OKChar Pull "R2, R3" MOVEQ R8, #1 ; MUST get another arg BEQ %BT05 20 MOV R12, #FlagType CLRV Pull "R1, R7, R8, PC" 02 CMP R8, #0 BEQ %FT39 ADR R0, ErrorBlock_BadParameters [ International BL TranslateError | SETV ] Pull "R1, R7, R8, PC" 39 ; copy arg until <" " MOV R7, #" " SUB R1, R1, #1 06 MOV R4, R10 03 LDRB R12, [R1], #1 CMP R12, R7 CMPNE R12, #" "-1 BLE %FT04 10 SUBS R3, R3, #1 STRPLB R12, [R10], #1 BPL %BT03 23 ADRL R0, ErrorBlock_BuffOverflow [ International BL TranslateError | SETV ] Pull "R1, R7, R8, PC" 04 CMP R7, #"""" BNE %FT07 CMP R12, #"""" BNE %FT08 LDRB R12, [R1], #1 CMP R12, #"""" BEQ %BT10 07 MOV R12, #0 ; terminate SUBS R3, R3, #1 BMI %BT23 STRB R12, [R10], #1 MOV R12, #ItemType SUB R1, R1, #1 STR R1, [stack] CLRV Pull "R1, R7, R8, PC" ohnoitsquotedargumentsagain MOV R7, #"""" B %BT06 08 ADRL R0, ErrorBlock_BadString [ International BL TranslateError | SETV ] Pull "R1, R7, R8, PC" ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; GetArg ; Look through keys: allow only full match on first pass, then ; single char abbreviation on second pass ; Return V set if not key, EQ if single letter abbreviation ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ GetArg ROUT ; In: R0 ptr to keystring ; R1 ptr to potential option. ; Out: VS if nomatch or ; R1 updated ; R4 argument number Push "R0-R3, R5-R6, lr" MOV R6, #-1 ; pass number 20 MOV R4, #0 01 LDRB R2, [R0], #1 CMP R2, #" " BEQ %BT01 02 BL CheckR2OKChar BNE %FT03 ; matched in full LDRB R3, [R1], #1 UpperCase R2, R5 UpperCase R3, R5 CMP R2, R3 LDREQB R2, [R0], #1 BEQ %BT02 CMP R6, #0 BLT %FT04 ; 2nd pass: allow abbreviation ; IF single char abbreviation THEN success ELSE skip LDR R2, [stack, #4] SUB R2, R1, R2 ; length of match+1 CMP R2, #2 SUBEQ R1, R1, #1 BEQ %FT13 ; success ; skip to next keyword 04 LDRB R2, [R0], #1 CMP R2, #" " BLT %FT05 CMP R2, #"," ADDEQ R4, R4, #1 CMPNE R2, #"=" BNE %BT04 LDR R1, [stack, #4] B %BT01 03 ; NE on first pass: check input string terminated OK LDRB R2, [R1] ; check for end of input word BL CheckR2OKChar BNE %FT13 ; yaay! full & correct match SUB R0, R0, #1 B %BT04 05 ADDS R6, R6, #1 LDMLEFD stack, {R0, R1} BLE %BT20 SETV Pull "R0-R3, R5-R6, PC" ; back with failure 13 STR R1, [stack, #4] CLRPSR V_bit, R0 ; clrV (just) Pull "R0-R3, R5-R6, PC" ; back with success CheckR2OKChar ROUT CMP R2, #"A" RSBGES R3, R2, #"Z" BGE %FT50 CMP R2, #"a" RSBGES R3, R2, #"z" BGE %FT50 CMP R2, #"0" RSBGES R3, R2, #"9" BGE %FT50 CMP R2, #"_" MOV PC, lr 50 CMP R0, R0 ; set EQ MOV PC, lr ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SetKeyword ROUT ; R11 ptr at keyword flags ; R4 ptr to value Push "R0-R2, R5, R6, lr" LDR R0, [R11] TST R0, #EFlag :OR: GFlag STR R4, [R11] ; result will always be here anyway BEQ %FT01 SUB R5, R10, R4 ; length of value ADD R3, R3, R5 ; increase free space ADD R2, R5, #11 ; round up to nearest word, then 1 BIC R2, R2, #3 MOV R6, stack ; STR stack, [stack, -R2]! is unpredictable STR R6, [stack, -R2]! ; reserve stack frame ADD R2, stack, #4 ; input value ptr 03 LDRB R6, [R4, R5] STRB R6, [R2, R5] SUBS R5, R5, #1 BPL %BT03 ; copy the value TST R0, #EFlag MOV R0, R2 BNE %FT02 ADD R1, R4, #2 ; free space pointer SUBS R3, R3, #2 MOV R2, R3 BMI %FT04 ORR R2, R2, #1:SHL:31 SWI XOS_GSTrans 05 SUB R3, R3, R2 ADD R10, R1, R2 ; update freespace pointer STRB R2, [R1, #-2] MOV R2, R2, LSR #8 STRB R2, [R1, #-1] BCS %FT04 90 LDR stack, [stack, #0] ; unwind frame (and don't let AAsm use STRVS R0, [stack] ; postindexed!!!) Pull "R0-R2, R5, R6,PC" 04 ADRL R0, ErrorBlock_BuffOverflow [ International BL TranslateError | SETV ] B %BT90 02 ADD R1, R4, #3 ; free space pointer SUBS R3, R3, #3 ; adjust for type (1 byte) + length (2 bytes) BMI %BT04 MOV R2, R3 SWI XOS_EvaluateExpression BVS %BT90 TEQ R1, #0, 2 ; if non-zero, then string, so update length MOVNE R14, #1 ; set type byte to definitely non-zero STRNEB R14, [R4] BNE %BT05 ; (C=0 so no buffer overflow, V=0 from SWI) STRB R1, [R4] ; set type byte to zero (=> integer) SUBS R3, R3, #5 BMI %BT04 STRB R2, [R4, #1] MOV R2, R2, LSR #8 STRB R2, [R4, #2] MOV R2, R2, LSR #8 STRB R2, [R4, #3] MOV R2, R2, LSR #8 STRB R2, [R4, #4] ADD R10, R4, #5 B %BT90 01 CLRV Pull "R0-R2, R5, R6,PC" ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ReadRAMFSLimits ; Return R0 start, R1 end (i.e. 1st byte out of area) ReadRAMFSLimits_Code ROUT Push "lr" MOV r0, #ChangeDyn_RamFS SWI XOS_ReadDynamicArea ; out: r0 = base, r1 = current size Pull "lr" ADDVC r1, r1, r0 ; if no error, make r1 -> after end ORRVS lr, lr, #V_bit ; if error, then set V_bit on return ExitSWIHandler ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ExitAndDie ; r0-r2 parameters for Exit ; r3 pointer to module name TerminateAndSodOff ROUT Push "r0-r2" LDR r10, =ZeroPage [ ZeroPage = 0 STR r10, [r10, #Curr_Active_Object] | MOV r14, #0 STR r14, [r10, #Curr_Active_Object] ] MOV r1, r3 MOV r0, #ModHandReason_Delete SWI XOS_Module Pull "r0-r2" SWI XOS_Exit ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; AddCallBack entry to callback vector ; r0 address to call ; r1 workspace ptr AddCallBack_Code ROUT Push "r0-r3, lr" [ ChocolateSysHeap ASSERT ChocolateCBBlocks = ChocolateBlockArrays + 0 LDR r3,=ZeroPage+ChocolateBlockArrays LDR r3,[r3,#0] BL ClaimChocolateBlock MOVVS r3, #12 BLVS ClaimSysHeapNode | MOV r3, #12 BL ClaimSysHeapNode ] BVS %FT99 Pull "r0, r1" LDR r10, =ZeroPage WritePSRc SVC_mode+I_bit, r3 ; IRQs off while holding context. LDR r3, [r10, #CallBack_Vector] [ {TRUE} STR r3, [r2, #0] STMIB r2, {r0, r1} STR r2, [r10, #CallBack_Vector] Pull "r2, r3, lr" | STR r3, [r2], #4 STMIA r2, {r0, r1} SUB r2, r2, #4 STR r2, [r10, #CallBack_Vector] Pull "r2, r3, lr" MOV r10, #0 ] LDRB r11, [r10, #CallBack_Flag] ORR r11, r11, #CBack_VectorReq STRB r11, [r10, #CallBack_Flag] B SLVK 99 STR r0, [stack] Pull "r0-r3, lr" B SLVK_SetV ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; RemoveCallBack - Entry for SWI OS_RemoveCallBack ; ; Removes an entry on the callback vector before it has been called ; ; in: r0 = address that would have been called ; r1 = workspace ptr ; ; out: - ; RemoveCallBack ROUT Push "r2-r4" SavePSR r10 ; save old I bit 10 WritePSRc SVC_mode+I_bit, r11 ; disable IRQs while looking at list LDR r11, =ZeroPage LDR r2, [r11, #CallBack_Vector]! ; r11 -> prev, r2 -> this 20 TEQ r2, #0 Pull "r2-r4", EQ ExitSWIHandler EQ LDMIA r2, {r3,r4,r12} ; r3 -> next, r4 = addr, r12 = ws TEQ r4, r0 ; check if correct address TEQEQ r12, r1 ; and correct ws ptr MOVNE r11, r2 ; if not, then prev:=this MOVNE r2, r3 ; and this:=next BNE %BT20 ; and loop STR r3, [r11] ; prev.link := next RestPSR r10 ; safe now to restore IRQ status Push "r0, r1, lr" ; now free this node [ ChocolateSysHeap ASSERT ChocolateCBBlocks = ChocolateBlockArrays + 0 LDR r1,=ZeroPage+ChocolateBlockArrays LDR r1,[r1,#0] BL FreeChocolateBlock BLVS FreeSysHeapNode | BL FreeSysHeapNode ; and then start again (NB we must ; restart from head of list again, as ; enabling IRQs could have changed list ] STRVS r0, [sp, #0] Pull "r0, r1, lr" BVC %BT10 Pull "r2-r4" ; had an error while releasing block ORR lr, lr, #V_bit ExitSWIHandler ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; SWI OS_Confirm ; If pointer visible, change pointer shape and look at mouse keys too. ; Flush mouse buffer first. ; Wait until key pressed. ; Returns: (lowercased) character in r0 (if mouse scanned, LH button = 'y', ; other buttons = 'n') ; C set for Escape condition ; EQ set if r0 = 'y' [ International confirm_yn DCB "YesNo:yn",0 ; Token to lookup message for Yes/No | confirm_yn DCB "yn" ] ptr_confirm DCB "ptr_confirm",0 ; Wimp's confirm pointer sprite shape confirm_scale DCD 1,1,1,1 ; Scaling factor for sprite op Confirm_Code ROUT WritePSRc SVC_mode, r10 ; enable IRQs Push "r0-r7, lr" ; Lookup the symbols for Y/N ADR r0, confirm_yn [ International BL FindToken ; Lookup in messages, use default if error ] LDRB r1, [r0], #1 ; Y character LDRB r2, [r0], #1 ; N character ORR r1, r1, r2, LSL #8 Push "r1" ; Y=[sp], N=[sp+1] ; Save current pointer selected MOV r0, #106 MOV r1, #255 ; read pointer state SWI XOS_Byte BVS confirm_error BIC r2, r1, #&80 MOV r10, r1 TST r10, #15 ; Pointer enabled? BEQ confirm_waitloop ; Jump if not ; Find Wimp's "ptr_confirm" sprite, searching first RMA then ROM SWI XWimp_BaseOfSprites MOVVS r10, #0 ; If error then don't use mouse BVS confirm_waitloop ; And jump to poll keyboard MOV r11, r0 ; Save -> ROM sprites, r1 -> RMA sprites ADR r2, ptr_confirm ; -> sprite name MOV r0, #&128 ; Read sprite info SWI XOS_SpriteOp BVC %FT10 ; Jump if sprite in RMA ADR r2, ptr_confirm ; -> sprite name MOV r1, r11 ; -> ROM sprites MOV r0, #&128 ; Read sprite info SWI XOS_SpriteOp MOVVS r10, #0 ; If error then don't use mouse BVS confirm_waitloop ; And jump to poll keyboard ; Set pointer shape from the sprite area found (r1) 10 MOV r7, #0 ; No pixel translation ADR r6, confirm_scale ; pointer scaling factor (1:1) MOV r5, #0 ; y hot spot offset MOV r4, #0 ; x hot spot offset MOV r3, #&23 ; No palette, shape 3 ADR r2, ptr_confirm ; -> sprite name MOV r0, #&124 ; Set pointer shape SWI XOS_SpriteOp ; Ignore errors MOV r0, #21 MOV r1, #9 SWI XOS_Byte ; flush mouse buffer MOV r0, #&C4 MOV r1, #0 MOV r2, #255 SWI XOS_Byte ; read current repeat rate. LDR r0, =ZeroPage LDR r0, [r0, #MetroGnome] ADD r11, r1, r0 ; time to wait for confirm_mouserepeat SWI XOS_Mouse CMP r2, #0 ; any buttons down? BEQ confirm_waitloop CMP r3, r11 BMI confirm_mouserepeat confirm_waitloop MOV r0, #129 MOV r1, #1 MOV r2, #0 SWI XOS_Byte ; scan for key BVS confirm_error CMP r2, #255 BNE confirm_gotkey TST r10, #15 BEQ confirm_waitloop ; no mouse scan wanted. SWI XOS_Mouse BVS confirm_error CMP r2, #0 BEQ confirm_waitloop TST r2, #4 ; LH button? LDRNEB r1, [sp] ; Yes LDREQB r1, [sp, #1] ; No confirm_gotkey CMP r2, #&1B ; ESCAPE or normal char read ? ORREQ r11, r1, #&100 MOVNE r11, r1 LowerCase r11, r1 TSTS r10, #15 ; Was pointer changed? MOV r1, r10 MOV r0, #106 SWINE XOS_Byte ; Yes then restore shape Pull "r10" ; r10=YN AND r10, r10, #&ff ; Retain Y byte Pull "r0-r7, lr" BIC lr, lr, #C_bit :OR: Z_bit ; SKS. Punter lr has VClear AND r0, r11, #&FF TST r11, #&100 ; ESCAPE condition ? (SKS) ORRNE lr, lr, #C_bit CMP r0, r10 ORREQ lr, lr, #Z_bit B SLVK confirm_error ADD sp, sp, #4 ; Drop YN STR r0, [stack] Pull "r0-r7, lr" B SLVK_SetV ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; In r0 = continuation crc (0 to start) ; r1 -> start of core ; r2 -> end of core ; r3 = increment (typically 1, 2 or 4), but can be -ve ; Out r0 = crc so far CRC_Code ROUT [ {TRUE} WritePSRc SVC_mode, r10 ; Could take a long time Push "r3, r14" TEQ r3, #0 ; is increment 0? - if so, it's silly BEQ %FT80 ; so return error, rather than going on forever MOV r10, r1 MOV r12, #&A000 ; CRC EOR pattern = &A001 ORR r12, r12, #&0001 10 CMP r10, r2 ; Finished ? BEQ %FA90 ; Must be exact end, allows -ve offset LDRB r14, [r10], r3 EOR r0, r0, r14 ; EOR the data with current crc lo CMP r10, r2 ; length might be odd so check again MOVEQ r11, #8 ; if equal then only do 8 bits BEQ %FT20 LDRB r14, [r10], r3 EOR r0, r0, r14, LSL #8 ; EOR the data with current crc hi MOV r11, #16 ; do 16 bits 20 MOVS r0, r0, LSR #1 ; acc >>= 1; CS/CC EORCS r0, r0, r12 ; CS -> eor, CC -> ok SUBS r11, r11, #1 ; 8 bits per byte BNE %BT20 B %BT10 80 ADRL r0, ErrorBlock_BadParameters ; return "Bad parameters" error [ International BL TranslateError ] Pull "r3, r14" B SLVK_SetV 90 Pull "r3, r14" ExitSWIHandler | WritePSRc SVC_mode, r10 ; Could take a long time Push "r3, r4, lr" MOV r10, r1 MOV r12, #&A000 ; CRC EOR pattern = &A001 ORR r12, r12, #&0001 MOV r14, #1 ; A single bit to be shifted 10 CMP r10, r2 ; Finished ? BEQ %FA90 ; Must be exact end, allows -ve offset LDRB r4, [r10], r3 MOV r11, #0 ; Go round the bits 20 TST r4, r14, LSL r11 ; Is data bit = carry ?; NE/EQ BEQ %FT30 MOVS r0, r0, LSR #1 ; acc >>= 1; CS/CC EORCC r0, r0, r12 ; NE, CC -> eor, NE, CS -> ok B %FT40 30 MOVS r0, r0, LSR #1 ; acc >>= 1; CS/CC EORCS r0, r0, r12 ; EQ, CS -> eor, EQ, CC -> ok 40 ADD r11, r11, #1 ; 8 bits per byte CMP r11, #8 BLO %BT20 B %BT10 90 Pull "r3, r4, lr" ExitSWIHandler ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ END