; 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.VduCurSoft SlowCursorSpeed * 16 FastCursorSpeed * 8 OnFlashTime * 48 OffFlashTime * 16 ; InitCursor - initialise cursor shape and address InitCursor ROUT Push R14 LDR R6, [WsPtr, #CursorFlags] TST R6, #TeletextMode ; if teletext mode MOVNE R0, #&72 ; then start at 9 (slow flash) MOVEQ R0, #&67 ; else start at 7 (slow flash) BL ProgReg10AndCopy MOV R0, #1 ; set to flash immediately STR R0, [WsPtr, #CursorCounter] ; AFTER setting CursorSpeed ; in case VSYNC happens LDR R1, [WsPtr, #VduSprite] TEQ R1, #0 ; if outputting to sprite MOVNE R0, #&20 ; then turn cursor off BLNE ProgReg10AndCopy LDR R0, [WsPtr, #RowMult] ; 8 or 10 or 16 or 20 Pull R14 ; and drop thru to ... SetCursorBottom LDR R1, [WsPtr, #LineLength] MUL R2, R1, R0 STR R2, [WsPtr, #CursorEndOffset] MOV PC, R14 SetCursorTop LDR R1, [WsPtr, #LineLength] MUL R2, R1, R0 STR R2, [WsPtr, #CursorStartOffset] MOV PC, R14 ; ***************************************************************************** ; Cursors are split, so remove output cursor DoOutputCursor ROUT Push R14 LDR R1, [WsPtr, #LineLength] MOV R1, R1, LSL #3 ; and end after 8 rows LDR R0, [WsPtr, #ModeFlags] TST R0, #Flag_DoubleVertical ; if double vertical ADDNE R1, R1, R1 ; end after 16 rows MOV R0, #0 ; start on top line BL EORCursor LDR R2, [WsPtr, #InputCursorAddr] ; flashing cursor is at input Pull R14 B PreWC10 ; ***************************************************************************** ; ; PreWrchCursor - Remove cursors prior to Wrch ; ; out: R6 = new CursorFlags; R5,R7 preserved; others corrupted ; PreWrchCursor ; Need to disable IRQs here to stop Vsync modifying CursorFlags in between ; us reading it and writing it [ No26bitCode MRS R3, CPSR ORR R1, R3, #I32_bit MSR CPSR_c, R1 | SETPSR I_bit, R1 ] LDR R6, [WsPtr, #CursorFlags] MOVS R0, R6, LSL #(32-InWrchBitPosn) ; CS => was already off ORRCC R6, R6, #InWrchBit ; protect against vsyncs STRCC R6, [WsPtr, #CursorFlags] LDR R0, [WsPtr, #CursorStack] MOV R0, R0, RRX ; shift down + put current ; state in top bit STR R0, [WsPtr, #CursorStack] MOV R2,R14 LDR R14, [WsPtr, #HALVideoFeatures] TST R14, #2 BLEQ RemovePointer MOV R14,R2 [ No26bitCode MSR CPSR_c, R3 ; restore old I bit MOVCS PC, R14 ; already off, so exit | MOVCSS PC, R14 ; already off, so exit ; (restoring I_bit) TEQP R14, #0 ; restore old I_bit ] LDR R2, [WsPtr, #CursorAddr] ; point to output TST R6, #CursorsSplit BNE DoOutputCursor PreWC10 TST R6, #ActualState MOVEQ PC, R14 ; flash cursor is off anyway BIC R6, R6, #ActualState STR R6, [WsPtr, #CursorFlags] ; and drop thru to EORFlashCursor ; ***************************************************************************** ; ; EORCursor - Exclusive-OR cursor with screen ; ; in: R0 = Start offset from top of cursor ; R1 = End+1 offset ; R2 = Screen address of appropriate cursor ; R6 = CursorFlags ; ; out: R5-R7 preserved; R0-R4, R8-R11 corrupted ; EORFlashCursor ASSERT CursorEndOffset-CursorStartOffset=4 ADD R0, WsPtr, #CursorStartOffset LDMIA R0, {R0,R1} EORCursor CMP R0, R1 MOVCS PC, R14 ; top >= bottom, so nowt ADD R1, R1, R2 LDR R3, [WsPtr, #LineLength] ASSERT CursorNbit = CursorFill +4 ADD R4, WsPtr, #CursorFill LDMIA R4, {R4, PC} ; load CursorFill and CursorNbit Cursor1bit LDRB R8, [R0, R2]! EOR R8, R8, R4 STRB R8, [R0], R3 TEQ R0, R1 MOVEQ PC, R14 Cursor1loop LDRB R8, [R0] EOR R8, R8, R4 STRB R8, [R0], R3 TEQ R0, R1 BNE Cursor1loop MOV PC, R14 Cursor2bit ADD R0, R0, R2 Cursor2loop LDRB R8, [R0, #1] EOR R8, R8, R4 STRB R8, [R0, #1] LDRB R8, [R0] EOR R8, R8, R4 STRB R8, [R0], R3 TEQ R0, R1 BNE Cursor2loop MOV PC, R14 CursorTeletext [ TTX256 ASSERT HiResTTX Push "R0, R1, R14" ADD R0, R0, #320*1024 ; go to other screen ADD R1, R1, #320*1024 BL Cursor16bit Pull "R0, R1, R14" B Cursor16bit | [ HiResTTX Push "R0, R1, R14" ADD R0, R0, #160*1024 ; go to other screen ADD R1, R1, #160*1024 BL Cursor8bit Pull "R0, R1, R14" B Cursor8bit | Push "R0, R1, R14" ADD R0, R0, #40*1024 ; go to other screen ADD R1, R1, #40*1024 BL Cursor4bit Pull "R0, R1, R14" ; and drop thru to ... ] ] Cursor4bit LDR R8, [R0, R2]! EOR R8, R8, R4 STR R8, [R0], R3 TEQ R0, R1 MOVEQ PC, R14 Cursor4loop LDR R8, [R0] EOR R8, R8, R4 STR R8, [R0], R3 TEQ R0, R1 BNE Cursor4loop MOV PC, R14 Cursor8bit ADD R0, R0, R2 Cursor8loop LDMIA R0, {R8,R9} EOR R8, R8, R4 EOR R9, R9, R4 STMIA R0, {R8,R9} ADD R0, R0, R3 TEQ R0, R1 BNE Cursor8loop MOV PC, R14 Cursor16bit ADD R0, R0, R2 Cursor16loop LDMIA R0, {R8-R11} EOR R8, R8, R4 EOR R9, R9, R4 EOR R10, R10, R4 EOR R11, R11, R4 STMIA R0, {R8-R11} ADD R0, R0, R3 TEQ R0, R1 BNE Cursor16loop MOV PC, R14 Cursor32bit ADD R0, R0, R2 SUB R3, R3, #32 Cursor32loop LDMIA R0, {R8-R11} EOR R8, R8, R4 EOR R9, R9, R4 EOR R10, R10, R4 EOR R11, R11, R4 STMIA R0!, {R8-R11} LDMIA R0, {R8-R11} EOR R8, R8, R4 EOR R9, R9, R4 EOR R10, R10, R4 EOR R11, R11, R4 STMIA R0!, {R8-R11} ADD R0, R0, R3 TEQ R0, R1 BNE Cursor32loop MOV PC, R14 ; ***************************************************************************** ; ; PostWrchCursor - Put back cursors after Wrch ; ; out: R6 = new CursorFlags, R5,R7 preserved, all others undefined ; PostWrchCursor ROUT MOV R6,R14 LDR R14,[WsPtr, #HALVideoFeatures] TST R14,#2 BNE %FT10 MRS R4,CPSR ORR R3,R4,#I32_bit MSR CPSR_c,R3 BL RestorePointer MSR CPSR_c,R4 10 MOV R14,R6 LDR R6, [WsPtr, #CursorFlags] LDR R0, [WsPtr, #CursorStack] MOVS R0, R0, LSL #1 STR R0, [WsPtr, #CursorStack] MOVCS PC, R14 ; we're still off, so do nowt Push R14 [ ForceMark LDR R0, [WsPtr, #CursorCounter] TEQ R0, #0 ; are we flashing LDRNE R0, [WsPtr, #CursorSpeed] ; force to start of mark state STRNE R0, [WsPtr, #CursorCounter] MOVNE R0, #ActualState STRNE R0, [WsPtr, #CursorDesiredState] ] [ RePlot LDR R1, [WsPtr, #CursorDesiredState] EOR R1, R1, R6 ; EOR of desired and actual ANDS R1, R1, #ActualState ; just get that bit BEQ PWC10 ; same, then go home EOR R6, R1, R6 ; EOR actual bit TST R6, #CursorsSplit LDRNE R2, [WsPtr, #InputCursorAddr] LDREQ R2, [WsPtr, #CursorAddr] BL EORFlashCursor PWC10 ] BIC R6, R6, #InWrchBit ; coming out of wrch now TST R6, #CursorsSplit STREQ R6, [WsPtr, #CursorFlags] Pull PC, EQ ; return if no output cursor LDR R2, [WsPtr, #CursorAddr] LDR R1, [WsPtr, #LineLength] MOV R1, R1, LSL #3 ; and end after 8 rows LDR R0, [WsPtr, #ModeFlags] TST R0, #Flag_DoubleVertical ; if double vertical ADDNE R1, R1, R1 ; end after 16 rows MOV R0, #0 ; start on top line BL EORCursor STR R6, [WsPtr, #CursorFlags] ; only clear it now ? Pull PC ; ***************************************************************************** VsyncCall ROUT Push "R0-R11,R14" [ AssemblePointerV BL PollPointer ] BL UpdatePointer LDR R6, [WsPtr, #CursorFlags] TST R6, #TeletextMode BLNE TeletextFlashTest ; if TTX, do other stuff VsyncReturn LDR R1, [WsPtr, #CursorDesiredState] LDR R0, [WsPtr, #CursorCounter] SUBS R0, R0, #1 LDREQ R0, [WsPtr, #CursorSpeed] ; if is zero, reload EOREQ R1, R1, #ActualState ; and toggle desired state STREQ R1, [WsPtr, #CursorDesiredState] STRCS R0, [WsPtr, #CursorCounter] ; store back unless was frozen TST R6, #InWrchBit Pull "R0-R11,PC", NE ; in wrch, so don't touch screen ; or modify CursorFlags EOR R1, R1, R6 ; EOR of desired and actual ANDS R1, R1, #ActualState ; just get that bit Pull "R0-R11,PC", EQ ; same, then go home EOR R6, R1, R6 ; EOR actual bit STR R6, [WsPtr, #CursorFlags] TST R6, #CursorsSplit LDRNE R2, [WsPtr, #InputCursorAddr] LDREQ R2, [WsPtr, #CursorAddr] BL EORFlashCursor Pull "R0-R11,PC" ; ***************************************************************************** TeletextFlashTest ROUT LDR R3, [WsPtr, #TeletextCount] SUBS R3, R3, #1 BNE %FT20 ; count not expired LDR R1, [WsPtr, #TeletextOffset] [ TTX256 ASSERT HiResTTX EORS R1, R1, #320*1024 ; switch to other flash bank | [ HiResTTX EORS R1, R1, #160*1024 ; switch to other flash bank | EORS R1, R1, #40*1024 ; switch to other flash bank ] ] STR R1, [WsPtr, #TeletextOffset] MOVEQ R3, #OnFlashTime MOVNE R3, #OffFlashTime LDR R0, [WsPtr, #DisplayStart] BL SetVinit ; preserves R3 20 STR R3, [WsPtr, #TeletextCount] B VsyncReturn ; ***************************************************************************** ; ; Vdu23_0_10 - Program cursor start, flash/steady, on/off ; Vdu23_0_10 LDRB R0, [WsPtr, #QQ+2] ; get parameter ProgReg10AndCopy STR R0, [WsPtr, #Reg10Copy] ; and drop thru to ... ProgReg10 AND R1, R0, #&60 CMP R1, #&40 BCS IsFlashing MOV R2, #0 STR R2, [WsPtr, #CursorCounter] ; freeze the flashing TST R1, #&20 MOVEQ R2, #ActualState ; steady cursor STR R2, [WsPtr, #CursorDesiredState] B PR1010 IsFlashing TST R1, #&20 MOVEQ R2, #FastCursorSpeed MOVNE R2, #SlowCursorSpeed STR R2, [WsPtr, #CursorSpeed] LDR R2, [WsPtr, #CursorCounter] TEQ R2, #0 ; was flashing frozen ? ; if not, don't perturb flash MOVEQ R2, #1 ; set to flash immediately STREQ R2, [WsPtr, #CursorCounter] PR1010 AND R0, R0, #&1F ; get start position bits TST R6, #TeletextMode ; if teletext mode MOVNE R0, R0, LSR #1 ; then divide by 2 LDR R1, [WsPtr, #ModeFlags] TST R1, #Flag_DoubleVertical ; if double vertical MOVNE R0, R0, LSL #1 ; then double cursor value LDR R1, [WsPtr, #RowMult] CMP R0, R1 ; is it > rowmult ? MOVHI R0, R1 ; set to rowmult if so B SetCursorTop ; ***************************************************************************** ; ; Vdu23_0_11 - Program cursor end ; Vdu23_0_11 LDRB R0, [WsPtr, #QQ+2] ; get parameter TST R6, #TeletextMode ; if teletext MOVNE R0, R0, LSR #1 ; then divide by 2 ADD R0, R0, #1 ; get end line +1 LDR R1, [WsPtr, #ModeFlags] TST R1, #Flag_DoubleVertical ; if double vertical MOVNE R0, R0, LSL #1 ; then double cursor value LDR R1, [WsPtr, #RowMult] CMP R0, R1 MOVHI R0, R1 ; if > rowmult, set to rowmult B SetCursorBottom ; ***************************************************************************** ; ; Vdu23_1 - Program cursor ; Vdu23_1 LDR R0, [WsPtr, #CursorFlags] TST R0, #Vdu5Bit MOVNE PC, R14 ; none of this nonsense in VDU5 mode LDRB R1, [WsPtr, #QQ+1] ; get parameter CursorOnOff CMP R1, #1 MOVCC R0, #&20 ; 0 -> just turn off LDRCS R0, [WsPtr, #Reg10Copy] ; 1,2,3 -> read old state BLS ProgReg10 ; 0,1 -> program hardware TEQ R1, #2 BICEQ R0, R0, #&60 ; 2 -> steady ORRNE R0, R0, #&60 ; 3 -> slow flashing STR R0, [WsPtr, #Reg10Copy] ; save in copy B ProgReg10 ; ***************************************************************************** ; ; DoCursorEdit ; ; in: R0 = &87 => COPY ; &88 => cursor left ; &89 => cursor right ; &8A => cursor down ; &8B => cursor up ; ; out: C=0 => doing COPY and valid character ; C=1 otherwise ; DoCursorEdit LDR R6, [WsPtr, #CursorFlags] TEQ R0, #&87 BNE IsCursorMove ; COPY character under cursor Push R14 TST R6, #CursorsSplit BEQ BadCopyExit ; cursors not split so don't copy TST R6, #Vdu5Bit BNE BadCopyExit ; can't copy in VDU5 mode BL ReadCharacter TEQ R0, #0 BEQ BadCopyExit BL VDUBE ; is a cursor movement valid ? BNE DoCE10 Push R0 BL PreWrchCursor BL InputCursorHT BL PostWrchCursor Pull R0 DoCE10 CLC Pull PC BadCopyExit BL BEL ; make bell sound SEC Pull PC ; ***************************************************************************** ; ; VDUBE - Check if valid to move cursor ; ; out: R0 preserved ; R1 = 0 => OK, R1<>0 => OK ; R6 = CursorFlags ; Z => OK, NZ => not OK ; C = 1 VDUBE LDR R6, [WsPtr, #CursorFlags] LDROSB R1, VDUqueueItems ; zero if not buffering TEQ R1, #0 ANDEQS R1, R6, #Vdu5Bit ; zero if not in VDU 5 mode ; insert check for vdu disabled here CMP R1, #0 ; set Z on R1, C:=1 MOV PC, R14 ; ***************************************************************************** IsCursorMove Push R14 BL VDUBE Pull PC, NE Push R0 BL PreWrchCursor ; remove both cursors Pull R0 BL ICM10 BL PostWrchCursor SEC Pull PC ICM10 TST R6, #CursorsSplit BNE AlreadySplit Push R0 LDR R0, [WsPtr, #Reg10Copy] AND R0, R0, #&DF ; use double flash rate BSR ProgReg10 LDR R0, [WsPtr, #CursorX] ; copy parameters STR R0, [WsPtr, #InputCursorX] LDR R0, [WsPtr, #CursorY] STR R0, [WsPtr, #InputCursorY] LDR R0, [WsPtr, #CursorAddr] STR R0, [WsPtr, #InputCursorAddr] ORR R6, R6, #CursorsSplit STR R6, [WsPtr, #CursorFlags] Pull R0 AlreadySplit CMP R0, #&89 BCC InputCursorLeft ; &88 BEQ InputCursorRight ; &89 CMP R0, #&8B BCC InputCursorDown ; &8A ; and drop thru to ... InputCursorUp LDR R1, [WsPtr, #InputCursorY] LDR R2, [WsPtr, #InputCursorAddr] LDR R3, [WsPtr, #RowLength] LDR R4, [WsPtr, #TWTRow] SUB R1, R1, #1 SUB R2, R2, R3 CMP R1, R4 LDRLT R1, [WsPtr, #TWBRow] STR R1, [WsPtr, #InputCursorY] ; need signed comparison STRGE R2, [WsPtr, #InputCursorAddr] ; in case Y went -ve MOVGE PC, R14 B AddressInputCursor InputCursorDown LDR R1, [WsPtr, #InputCursorY] LDR R2, [WsPtr, #InputCursorAddr] LDR R3, [WsPtr, #RowLength] LDR R4, [WsPtr, #TWBRow] ADD R1, R1, #1 ADD R2, R2, R3 CMP R1, R4 LDRHI R1, [WsPtr, #TWTRow] STR R1, [WsPtr, #InputCursorY] STRLS R2, [WsPtr, #InputCursorAddr] MOVLS PC, R14 ; and drop thru to ... AddressInputCursor Push R14 LDR R0, [WsPtr, #InputCursorX] LDR R1, [WsPtr, #InputCursorY] BL AddressR0R1 STR R2, [WsPtr, #InputCursorAddr] Pull PC AddressCursors LDR R6, [WsPtr, #CursorFlags] TST R6, #CursorsSplit BEQ AddressCursor BSR AddressInputCursor B AddressCursor InputCursorLeft LDR R0, [WsPtr, #InputCursorX] LDR R2, [WsPtr, #InputCursorAddr] [ HiResTTX LDR R3, [WsPtr, #CharWidth] | LDR R3, [WsPtr, #BytesPerChar] ] LDR R4, [WsPtr, #TWLCol] SUB R0, R0, #1 SUB R2, R2, R3 CMP R0, R4 LDRLT R0, [WsPtr, #TWRCol] STR R0, [WsPtr, #InputCursorX] STRGE R2, [WsPtr, #InputCursorAddr] ; I do mean GE ! MOVGE PC, R14 BSR AddressInputCursor B InputCursorUp InputCursorRight LDR R0, [WsPtr, #InputCursorX] LDR R2, [WsPtr, #InputCursorAddr] [ HiResTTX LDR R3, [WsPtr, #CharWidth] | LDR R3, [WsPtr, #BytesPerChar] ] LDR R4, [WsPtr, #TWRCol] ADD R0, R0, #1 ADD R2, R2, R3 CMP R0, R4 LDRHI R0, [WsPtr, #TWLCol] STR R0, [WsPtr, #InputCursorX] STRLS R2, [WsPtr, #InputCursorAddr] MOVLS PC, R14 BSR AddressInputCursor B InputCursorDown ; ***************************************************************************** ; ; InputCursorHT - move input cursor "right" after copying ; InputCursorHT Push R14 LDR R6, [WsPtr, #CursorFlags] BL InputCursorMove BCC ICHTExit BL InputCursorB0 BL AddressInputCursor EOR R6, R6, #8 BL InputCursorMove BLCS InputCursorB0 ICHTExit Pull R14 B AddressInputCursor END