; 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.osbyte ; New version of OSBYTE which claims the ByteV(ector) properly ; PMF 18/9/86 ; Updates: ; Kernel ; Version Date Who Why ; 2.01 15-June-90 JSR Change OS_Byte 124/125/126 to update the CallBack_Flag byte ; correctly, rather than setting it to 1. The bug caused vector ; callbacks to be delayed over much when escape was pressed. ; ???? 08-Feb-95 WT Change OS_Byte 106 to support the new cursor storage method ; introduced for Stork LCD support. OsbyteLowLimit * &6A ; osbytes lower than this get Y set to 0 OsbyteVeryLow * &1A ; osbytes lower than this are all recognised OsbyteKeyStatus * &CA ; only OS_Byte variable which isn't pure any more! ; ***************************************************************************** MACRO MyOsbyte $cond B$cond GoMyOsbyte MEND MACRO MyOsWord $cond B$cond GoMyOsword MEND MACRO Unused $cond MOV$cond PC, R14 ; just return and let the next person have a go MEND MACRO ByteReturnV $cond ASSERT "$cond"="" :LOR: "$cond"="VS" [ "$cond"="" LDRVC R0,[R13] ] ADD$cond R13,R13,#4 LDR$cond R3,[R13],#8 ; pull r3, junk r14 LDR$cond PC,[R13],#4 MEND ; Main OSbyte entry point ; R0,R1,R2 are parameters OsByte Push "R0, R3, R14" BL OsByteGo ; Call the subsid entry pt. Pull "R0,R3" Push "R0-R4" LDMIA R13, {R2-R4} ; R2=A, R3=X, R4=Y MOV R1, #Service_UKByte ; osbyte service reason BL Issue_Service TEQ R1, #0 STMEQIA R13, {R2-R4} ; if claimed, then update ; returned R0-R2 CLRPSR V_bit, R3 ; clear V flag Pull R0 ADRNE R0, ErrorBlock_BadCommand ; not claimed, R0 -> error [ International BLNE TranslateError ] SWINE XOS_GenerateError ; set V if not claimed Pull "R1-R4" ADD SP,SP,#4 Pull "PC" MakeErrorBlock BadCommand GoMyOsbyte CLRPSR V_bit, R3 Pull "R0,R3" ; pull the world AND the PC to return ADD SP,SP,#4 Pull "PC" ; ***************************************************************************** OsByteGo ROUT AND R0, R0, #&FF ; no funny business! SUBS R3, R0, #OsbyteLowLimit ; is it a low one ? BCS HiOsbyte MOV R2, #0 ; lo one, so set Y to 0 CMP R0, #OsbyteVeryLow ; is it one we recognise ? 10 ADDCC PC, PC, R0, LSL #2 ; then go thru despatch table B TryInternational ; else issue unknown osbyte service 20 ASSERT %BT20-%BT10 = 8 BAL Osbyte00 BAL Osbyte01 BAL Osbyte02 BAL Osbyte03 BAL Osbyte04 BAL Osbyte05 BAL Osbyte06 BAL Osbyte07 BAL Osbyte08 BAL Osbyte09 BAL Osbyte0A BAL Osbyte0B BAL Osbyte0C BAL Osbyte0D BAL Osbyte0E BAL Osbyte0F BAL Osbyte10 BAL Osbyte11 BAL Osbyte12 BAL Osbyte13 BAL Osbyte14 BAL Osbyte15 BAL Osbyte16 BAL Osbyte17 BAL Osbyte18 BAL Osbyte19 HiOsbyte CMP R0, #OsByte_BaseOfROMVectorTable ; is it a variable ? 30 ADDCC PC, PC, R3, LSL #2 B DoOsbyteVar ; yes, then do variable mangling 40 ASSERT %BT40-%BT30=8 BAL Osbyte6A BAL Osbyte6B BAL Osbyte6C BAL Osbyte6D BAL Osbyte6E BAL Osbyte6F BAL Osbyte70 BAL Osbyte71 BAL Osbyte72 BAL Osbyte73 BAL Osbyte74 BAL Osbyte75 BAL Osbyte76 BAL Osbyte77 BAL Osbyte78 BAL Osbyte79 BAL Osbyte7A BAL Osbyte7B BAL Osbyte7C BAL Osbyte7D BAL Osbyte7E BAL Osbyte7F BAL Osbyte80 BAL Osbyte81 BAL Osbyte82 BAL Osbyte83 BAL Osbyte84 BAL Osbyte85 BAL Osbyte86 BAL Osbyte87 BAL Osbyte88 BAL Osbyte89 BAL Osbyte8A BAL Osbyte8B BAL Osbyte8C BAL Osbyte8D BAL Osbyte8E BAL Osbyte8F BAL Osbyte90 BAL Osbyte91 BAL Osbyte92 BAL Osbyte93 BAL Osbyte94 BAL Osbyte95 BAL Osbyte96 BAL Osbyte97 BAL Osbyte98 BAL Osbyte99 BAL Osbyte9A BAL Osbyte9B BAL Osbyte9C BAL Osbyte9D BAL Osbyte9E BAL Osbyte9F BAL OsbyteA0 BAL OsbyteA1 BAL OsbyteA2 BAL OsbyteA3 BAL OsbyteA4 BAL OsbyteA5 BAL OsbyteA6 BAL OsbyteA7 TryInternational ; special ones in the middle TEQ R0, #OsByte_Country BEQ DoOsbyteSetCountry TEQ R0, #OsByte_Alphabet BEQ DoOsbyteSetAlphKey MOV PC, R14 ; ***************************************************************************** ; The Osbyte routines themselves ; Mos version number and title string ; R1 = 0 -> give an error with and string MosTitle ; R1 <>0 -> RETURN with R1 = MosVer ; R2 is Preserved ; MosVer values clients might expect to read are as follows: ; (ref: http://beebwiki.mdfs.net/OSBYTE_%2600 ) ; Volume Directory Extension ; Electron 0 \ ; BBC A/B 1 | ; BBC B+ 2 | ; Master 128 3 | :d. . / ; Master ET 4 | ; Master Compact 5 | ; Arthur/RISC OS 6 | ; Springboard 7 / ; Unix 8 \ ; 6809/6309 9 | N/A / . ; Mac OS X 10 / ; 6809/6309 17 :d. . / ; Commodore 64/128 28 \ ; TI calculator 29 | d: N/A . ; Amstrad CPC 30 | ; Sinclair ZX Spectrum 31 / ; DOS/Windows 32 \ d:\ \ . ; 6809/6309 39 / Osbyte00 ROUT TEQ R1, #0 MOVNE R1, #MosVer MyOsbyte NE [ UseNewFX0Error LDR R0, =NewFX0Error LDR LR, [R0] CMP LR, #0 ADREQ R0, FX0Error ; Fall back to hardcoded string if new one isn't ready yet | ADR R0, FX0Error ] SWI XOS_GenerateError ByteReturnV [ UseNewFX0Error InitNewFX0Error ROUT Push "r0-r4,lr" MOV r0, #ExtROMFooter_BuildDate BL ExtendedROMFooter_FindTag CMP r0, #0 BEQ %FT10 MOV r1, r0 MOV r0, #-1 LDR r2, =NewFX0Error+4 MOV r3, #?NewFX0Error - 4 ADR r4, NewFX0ErrorFormat SWI XTerritory_ConvertDateAndTime ; Fill in error number on success LDRVC r2, =NewFX0Error MOVVC r3, #ErrorNumber_FX0 STRVC r3, [r2] 10 Pull "r0-r4,pc" ] FX0Error & ErrorNumber_FX0 = "$SystemName $VersionNo",0 [ UseNewFX0Error NewFX0ErrorFormat = "$SystemName $VString (%dy %m3 %ce%yr)",0 ] ALIGN ; ***************************************************************************** ; Write User Flag Osbyte01 V2B156 ADD R0, R0, #&F0 ; convert 1,5,6 to &F1,&F5,&F6 B DoOsbyteVar ; Select input stream Osbyte02 ROUT AND R0, R1, #1 ; new buffer id TEQ R1, #0 ; 0 => disable RXI Push "r0" BNE %FT10 ; [enabling serial] ; disable serial by closing stream LDRB r1, SerialInHandle TEQ r1, #0 MOVNE r0, #0 ; close file if handle non-zero STRNEB r0, SerialInHandle ; zero handle first SWINE XOS_Find B %FT20 ; enable serial by opening stream 10 LDRB r0, SerialInHandle TEQ r0, #0 ; if a stream open already BNE %FT20 ; then skip SUB sp, sp, #64 MOV r3, sp ADR r1, SerialInFilename 12 LDRB r0, [r1], #1 CMP r0, #0 STRNEB r0, [r3], #1 BNE %BT12 MOV r0, #SerialOp_GetDeviceName SWI XOS_SerialOp ; r1 should now be correct device name or preserved on error ; i.e. left pointing at our default name ADD lr, sp, #63 14 SUBS r0, r1, lr ; Basic buffer overflow check LDRNEB r0, [r1], #1 CMPNE r0, #0 STRB r0, [r3], #1 BNE %BT14 MOV r0, #open_read + open_mustopen MOV r1, sp ; open serial stream for input SWI XOS_Find STRVCB r0, SerialInHandle ; if did open then store handle ; (may store same value if already open, but who cares?) ADD sp, sp, #64 20 Pull "r0" LDRB R1, InputStream ; old input stream STRB R0, InputStream MyOsbyte LTORG SerialInFilename = "Devices#Buffer1:$.", 0, "Serial", 0 ALIGN ; Select output stream Osbyte03 Osbyte04 ; select cursor keys actions V2B34 ADD R0, R0, #&E9 ; convert 3,4 to &EC,&ED B DoOsbyteVar ; Write Printer driver type Osbyte05 ROUT BL MakePrinterDormant ; for netprint SavePSR R14 ; for restoring I afterwards 10 CLRPSR I_bit, R3 [ InterruptDelay NOP NOP NOP NOP NOP ] RestPSR R14 ; restore old I LDR R3, =ZeroPage LDRB R3, [R3, #ESC_Status] TST R3, #&40 MyOsbyte NE ; ESCAPE, so don't change LDR R3, PrinterActive TEQ R3, #0 BNE %BT10 ; still active, then loop ; insert code here to notify UPTVEC of change B V2B156 ; R0 = 5, update variable ; Write Printer Ignore Character Osbyte06 STRB R2, NoIgnore ; (R2=0) allow chars to be ignored B V2B156 ; Write RS423 receive rate ; Write RS432 transmit rate Osbyte07 Osbyte08 SUB r0, r0, #2 ; 7 -> 5; 8 -> 6 SWI XOS_SerialOp MyOsbyte ; Write First Flash Time Osbyte09 MOV R2, #1 ; and drop thru to ... ; Write Second Flash Time Osbyte0A ; (R2=0) Osbyte910 [ ZeroPage <> 0 LDR R0, =ZeroPage ADD R2, R2, R0 ] MOV R0, R1 ; new period LDRB R1, [R2, #OsbyteVars + :INDEX: SpacPeriod] ; get old state STRB R0, [R2, #OsbyteVars + :INDEX: SpacPeriod] ; store new LDRB R3, FlashCount TEQ R3, #0 ; are we frozen ? MyOsbyte NE ; no, then finish STRB R0, FlashCount ; kick the counter ASSERT (ZeroPage :AND: 255) = 0 STRB R2, FlashState ; force new state VDWS WsPtr TEQ R2, #0 BEQ ForceSecondState Push "R1,R2" BL DoFirstFlash Pull "R1,R2" MyOsbyte ForceSecondState Push "R1,R2" BL DoSecondFlash Pull "R1,R2" MyOsbyte ; Write Keyboard Delay Osbyte0B V2BBC ADD R0, R0, #(&C4-&0B) B DoOsbyteVar ; Write Keyboard Rate Osbyte0C TEQ R1, #0 BNE V2BBC CLRPSR I_bit, R0 ; this may take some time BL ReadKeyDefaults MyOsbyte ; ***************************************************************************** ; Disable / Enable Events ; R1 = Event number. Decrement/Increment semaphore for this event Osbyte0D ROUT Osbyte0E ROUT CMP R1, #32 ; if illegal event number MOVCS R2, #&FF ; then return + say was enabled BCS %FT10 ADD R3, WsPtr, #:INDEX: EventSemaphores LDRB R2, [R3, R1] ; get semaphore for this event CMP R0, #13 ; 13 => disable, 14 => enable SUBEQ R0, R2, #1 ; decrement semaphore ADDNE R0, R2, #1 ; increment semaphore CMP R2, #&FF ; Z=1 => already saturated, so don't store back STRNEB R0, [R3, R1] 10 MOV R1, R2 ; R1 = R2 = old semaphore MyOsbyte ; ***************************************************************************** ; Flush Buffer Osbyte0F ROUT TEQ R1, #0 BNE FlushInput BL FlushAll MyOsbyte ; flush all buffers FlushAll Push R14 MOV R1, #(NBuffers-1) 10 BL FlushThis SUBS R1, R1, #1 BPL %BT10 Pull PC ; flush input buffer FlushInput LDROSB R1, InputStream ; get buffer id of input stream BL FlushThis MyOsbyte ; ***************************************************************************** ; Clear out the softkeys Osbyte12 ROUT MOV R0, #0 STRB R0, SoftKeyLen ; purge current expansion LDR R11, =ZeroPage+KeyWorkSpace ; can corrupt R11 Push R4 MOV R1, #15 10 MOV R3, R1 BL SetupKeyName ; exits with R0 -> SoftKeyName MOV R2, #-1 ; destroy variable MOV R3, #0 ; context pointer 0 MOV R4, #0 ; type irrelevant SWI XOS_SetVarVal ; V will be set if not present SUBS R1, R1, #1 BPL %BT10 Pull R4 MyOsbyte ; ***************************************************************************** ; Wait for Vsync Osbyte13 ROUT ; Bail immediately if we're in an IRQ handler. ; (it's bad form for IRQ handlers to take too much time, and ; depending on various factors, it may be impossible for us to ; receive VSync IRQs from within a handler) ; https://www.riscosopen.org/tracker/tickets/424 LDR R3, =ZeroPage+IRQsema LDR R3, [R3] CMP R3, #0 MyOsbyte NE MRS R3, CPSR ; Interrupts disabled at the moment LDRB R2, CFStime 10 ; bug fix for MED-03165. Having a DPMS-blanked screen stopped printing. ; The reason is that HSyncs stop and VSyncs stop as a consequence, ; but the Hourglass module uses this call to wait for the next VSync ; before animating the hourglass. ; When the screen is DPMS-blanked this osbyte will now return ; immediately. This is equivalent to the operation of the DPMSUtils ; module shipped with OS 3.50. ; For RISC OS 5, we've now extended it to also skip the wait if DPMS ; has turned off VSyncs, since it's plausible that hardware/drivers ; won't generate VSync interrupts in that state either. VDWS LR LDRB R0, [LR,#ScreenBlankFlag] LDRB R1, [LR,#ScreenBlankDPMSState] TEQ R0, #0 ; NE => blanked TSTNE R1, #3 ; NE => blanked and DPMS turned off HSync or VSync MyOsbyte NE ; if true exit immediately ; Also, exit now if we don't have a driver active, or there's no ; mode programmed LDR R0, [LR,#CurrentGraphicsVDriver] CMP R0, #GraphicsVInvalid CMPEQ R1, #255 MyOsbyte EQ ; It is actually better to call Idle with interrupts disabled as it stops the interrupt ; going off on the way through the SWI dispatch and accidentally waiting for the next ; interrupt... The Idle will return when an interrupt is pending - it will be handled below LDR R0, =ZeroPage LDRB R0, [R0, #PortableFlags] TST R0, #PortableFeature_Idle SWINE XPortable_Idle BIC R1, R3, #I32_bit MSR CPSR_c, R1 ; CLI ;StrongARM core will not see interrupt unless disable is cleared for at least 5 cycles, ;in order to fill synchroniser pipe [ InterruptDelay NOP NOP NOP NOP NOP ] MSR CPSR_c, R3 ; SEI LDRB R1, CFStime TEQ R1, R2 MyOsbyte NE B %BT10 ; ***************************************************************************** ; Restore font definitions Osbyte14 MOV R1, #1 ; start at character 1*32 MOV R2, #3 ; do 3 pages B ResetPartFont ; ***************************************************************************** ; Flush Selected Buffer Osbyte15 ROUT ; ; TMD 24-Apr-92: Don't check buffer number, as this prevents the flushing ; of buffer manager buffers. ; ; CMP R1, #NBuffers ; BCS %FT10 ; invalid buffer number BL FlushThis ;10 MyOsbyte FlushThis ; code inserted here to zero PrinterActive iff you are flushing the printer ; buffer and the print destination is not a stream one CMP R1, #Buff_RS423Out ; is it an input buffer ? (not mouse) BCS %FT20 ; no, then branch MOV R0, #0 STRB R0, SoftKeyLen ; kill soft key expansion STRB R0, VDUqueueItems ; flush VDU queue 20 SETV ; indicate purge not count B CnpEntry ; Reset Group of font definitions Osbyte19 ROUT CMP R1, #8 MyOsbyte CS ; not in range 0..7, ignore TEQ R1, #0 MOVEQ R1, #1 ; if 0 then start at 1*32, do 7 pages MOVEQ R2, #7 MOVNE R2, #1 ; else start at n*32, do 1 page ResetPartFont ; first offer to International module Push "R1, R2, R4, R5" MOV R4, R1, LSL #5 ; R4 = start character ADD R5, R4, R2, LSL #5 ; R5 = end character+1 SUB R5, R5, #1 ; R5 = end character LDRB R3, Alphabet MOV R2, #Inter_Define BL OfferInternationalService Pull "R1, R2, R4, R5" MyOsbyte EQ ; if claimed, don't use hard font ByteToNosbod DoResetFont MyOsbyte ; ***************************************************************************** ; Set country number ; in: R1 = country number DoOsbyteSetCountry ROUT TEQ R1, #&7F ; if 127, just read country LDREQB R1, Country MyOsbyte EQ BL GetCountry Push R4 BL ConvertCNoToANo ; convert country no. to alphabet no. Pull R4, NE MOVNE R1, #0 ; if not claimed, return with X=0 MyOsbyte NE ; was claimed, so have country number in R1 and R3, alphabet no. in R4 LDRB R1, Country ; save old country STRB R3, Country ; store new country STRB R4, Alphabet ; and new alphabet BL NewKeyboard ; R3=new keyboard, R4=alphabet for it BL SetAlphabet Pull R4 MyOsbyte SetAlphabet Push "R1,R5,R14" MOV R2, #Inter_Define ; now redefine the chars MOV R3, R4 MOV R4, #32 MOV R5, #255 BL OfferInternationalService Pull "R1,R5,PC" ConvertCNoToANo MOV R3, R1 ; put country no. in R3 MOV R2, #Inter_CNoToANo OfferInternationalService Push R14 MOV R1, #Service_International BL Issue_Service TEQ R1, #0 ; set Z flag if claimed Pull PC ; Notify keyboard handler of new keyboard NewKeyboard Push "R1,R4,R14" STRB R3, Keyboard STRB R4, KeyAlphabet MOV R2, #Inter_Keyboard BL OfferInternationalService Pull "R1,R4,PC" ; ***************************************************************************** ; Set keyboard/alphabet for a particular country DoOsbyteSetAlphKey ROUT TST R1, #&80 ; if set then setting keyboard BNE %FT10 ; [setting keyboard] ; setting alphabet TEQ R1, #&7F ; 127 => just read alphabet LDREQB R1, Alphabet MyOsbyte EQ ; 20/8/87 added code to do setting of default alphabet BL GetCountry Push R4 BL ConvertCNoToANo ; try to convert R1 to alphabet number MOVNE R4, R3 ; if failed, try without converting BL SetAlphabet ; try to set this alphabet Pull R4 MOVNE R1, #0 ; if not claimed, return with X=0 MyOsbyte NE LDRB R1, Alphabet STRB R3, Alphabet MyOsbyte ; setting keyboard 10 AND R1, R1, #&7F TEQ R1, #&7F ; 127 => just read keyboard LDREQB R1, Keyboard MyOsbyte EQ BL GetCountry Push R4 BL ConvertCNoToANo ; validating country no. Pull R4, NE MOVNE R1, #0 ; if not claimed, return with X=0 MyOsbyte NE LDRB R1, Keyboard ; load old keyboard BL NewKeyboard ; R3=new keyboard, R4=alphabet for it Pull R4 MyOsbyte ; ***************************************************************************** ; All osbytes from &1A to &69 are unused (apart from international ones!) ; End of unused block ; Write pointer shape number, mouse linkage ; ; R1 = 0 => pointer off ; R1 = 1..4 => use pointer shape 1..4, linked to mouse ; R1 = &81..&84 => use pointer shape 1..4, unlinked ; Osbyte6A VDWS R0 LDRB R3, [R0, #PointerShapeNumber] ; get old shape number AND R2, R1, #&7F ; allow 0..4, &80..&84 CMP R2, #4 BHI %FT90 ; ignore change if too high TEQ R1, R3 BEQ %FT90 ; same as old STRB R1, [R0, #PointerShapeNumber] ; will take effect on next vsync (UpdatePointer) 90 MOV R1, R3 MyOsbyte ; Set vdu driver's screen number Osbyte70 ByteToNosbod DoSetDriverBank MyOsbyte ; Set displayed screen number Osbyte71 ByteToNosbod DoSetDisplayBank MyOsbyte ; *SHADOW Osbyte72 MOV R0, #&EF ; redirect to shadow variable MOV R2, #0 B DoOsbyteVar ; ***************************************************************************** ; Read VDU Status Osbyte75 Push R2 ByteToNosbod DoReadVDUStatus Pull R2 MyOsbyte ; Reflect Keyboard Status In LEDs Osbyte76 LDR R11, =ZeroPage+KeyWorkSpace BL UpdateLEDs MyOsbyte ; Write Keys Pressed Info Osbyte78 BL WriteKeysDown MyOsbyte ; Perform Keyboard Scan from 15 Osbyte7A MOV R1, #&0F ; and drop thru to ... ; Perform Keyboard Scan Osbyte79 BL BBCScanKeys MyOsbyte ; Inform OS Printer Driver going Dormant Osbyte7B BL MakePrinterDormant ByteReturnV ; Clear Escape Condition Osbyte7C BL DoOsbyte7C MyOsbyte ; Set Escape Condition Osbyte7D BL DoOsbyte7D MyOsbyte DoOsbyte7C Push "R11, R14" MOV R11, #0 B Osbyte7C7D DoOsbyte7D Push "R11, R14" MOV R11, #&FF Osbyte7C7D LDR R12, =ZeroPage+EscHan_ws STRB R11, [R12, #ESC_Status-EscHan_ws] ; set escape flag MOV R14, PC LDMIA R12, {R12, PC} Exit7D TEQ R12, #1 Pull "R11, PC", NE MRS R11, CPSR ; Preserve old processor state ORR R12, R11, #SVC_mode ; Switch to SVC mode preserving IRQ_bit MSR CPSR_c, R12 Push R14 ; Preserve SVC_R14 SWI XOS_SetCallBack Pull R14 ; Restore SVC_R14 MSR CPSR_c, R11 ; Switch back to original mode, with V_bit intact from SWI Pull "R11, PC" ; Acknowledge ESCAPE Osbyte7E ROUT LDR R3, =ZeroPage LDRB R3, [R3, #ESC_Status] TST R3, #&40 BEQ NoESCToAck ; escape flag clear LDRB R0, ESCeffect TEQ R0, #0 BNE NoESCToAck ; escape effects disabled CLRPSR I_bit, R0 ; enable interrupts (doing SOUNDs and ; closing files may take some time!) SWI XSound_QInit BVS %FT99 ; no noises anyway! LDR R0, =&01010008 ; channel 8, amplitude &101 MOV R1, #&00010000 ; pitch 0, duration 1 10 SWI XSound_ControlPacked BVS %FT99 ; (R0 would be corrupted) SUB R0, R0, #1 ; decrement channel TST R0, #&FF ; if channel <> 0 then loop BNE %BT10 99 MOV R0, #0 STRB R0, PageModeLineCount ; zero line count LDRB R1, ExecFileH CMP R1, #0 ; is EXEC file open (and V:=0) STRNEB R0, ExecFileH ; if so, zero handle and close ; (will enable IRQs for me) SWINE XOS_Find ; (R0=0, R1=handle) ByteReturnV VS ; if error then bomb out BL FlushAll NoESCToAck BL DoOsbyte7C ANDS R1, R3, #&40 ; set R1 to 0 if wasn't escape, MOVNE R1, #&FF ; &FF if was MyOsbyte ; Check for EOF Osbyte7F MOV R0, #OSArgs_EOFCheck SWI XOS_Args ; result comes back in R2 MOV R1, R2 ByteReturnV ; ***************************************************************************** ; Read ADC or buffer status Osbyte80 AND R1, R1, #&FF ; no funny business TST R1, #&80 ; is it ADVAL(-n) BEQ AdvalPositive ; no, then do adval(+ve) EOR R1, R1, #&FF ; convert to buffer number CLC ; (C:=0 and V:=0) TEQ R1, #Buff_Mouse ; is it mouse (only input buf >= 2) ? CMPNE R1, #Buff_RS423Out ; C=1 <=> output buffer, so count spaces ; V=0, so will do count not purge ADR R14, MyOsbyte80 CnpEntry Push "R10,R12,R14" MOV R10, #CNPV B GoVec MyOsbyte80 MyOsbyte AdvalPositive ROUT TEQ R1, #7 TEQNE R1, #8 Unused NE Push R11 MOV R11, R1 ; save adval number SWI XOS_Mouse Pull R11, VS ByteReturnV VS TEQ R11, #7 MOVEQ R1, R0 ; R1 is required value MOV R2, R1, LSR #8 ; put lo in R1, hi in R2 AND R1, R1, #&FF AND R2, R2, #&FF Pull R11 MyOsbyte ; ***************************************************************************** ; Perform INKEY operation ; OSVersionID values clients might expect to read include the following: ; (ref: http://beebwiki.mdfs.net/OSBYTE_%2681 ) ; Arthur 1.20 &A0 ; RISC OS 2.00 &A1 ; RISC OS 2.01 &A2 ; RISC OS 3.0x &A3 ; RISC OS 3.1x &A4 ; RISC OS 3.50 &A5 ; RISC OS 3.60 &A6 ; RISC OS 3.7x &A7 ; RISC OS 4.0x &A8 ; RISC OS 4.3x &A9 ; RISC OS 5.xx &AA ; Pyromaniac &AE ; Springboard &AF Osbyte81 ROUT TST R2, #&80 ; is it negative inkey ? BEQ %FT10 ; no, then not INKEY-256 ANDS R1, R1, #&FF ; zero => INKEY(-256) MOVEQ R1, #OSVersionID ; then X := OS version number MOVEQ R2, #0 ; and Y := 0 MyOsbyte EQ ; if was INKEY-256 then claim 10 Push R14 ; save return address for if passing on ADR R14, My81 Push R14 ; stack 'claiming' return address BL DoInkeyOp ; R14 = 'passing on' return address NotMy81 ; DoInkeyOp passed it on Pull "R3,R14" ; Throw away 'claiming' return address ; and restore real passing on return address Unused ; else pass it on still My81 Pull R14 ; throw away real passing on address ByteReturnV ; ***************************************************************************** ; Read Machine High Order Address Osbyte82 MOV R1, #&FF ; Pretend we're an I/O processor ! MOV R2, #&FF MyOsbyte ; ***************************************************************************** ; Read OSHWM Osbyte83 LDRB R2, OSHWM ; Read from silly variable MOV R1, #0 ; lo-byte is 0 MyOsbyte ; ***************************************************************************** ; Read Text Cursor Position (input cursor if split) Osbyte86 ByteToNosbod DoReadPOSVPOSI ; Results in R1, R2 (i.e. POS, VPOS) MyOsbyte ; ***************************************************************************** ; Read Screen Mode and Character at text cursor position Osbyte87 [ {FALSE} ; The user's PSR is no longer there. In fact, it never was (or hasn't been ; for a long time), because the return address passed to the vector always ; had the I bit set. LDR R3, [R13, #StackOffset] ; get user's psr ANDS R3, R3, #I_bit ; EQ => irqs were on CLRPSR I_bit, R3, EQ ; so clear I_bit now ] ; However, the SPSR _should_ have the user's interrupt state. If he had ; IRQs off, we will not have turned them back on, so neither we nor an ; interrupt routine will have called a a SWI, so SPSR will still be the ; SPSR from the original OS_Byte, with I set. ; ; If someone else is on ByteV, and passed it on, the rules say that they ; mustn't have enabled interrupts either, in which case any corrupted SPSR ; must still have I set. ; ; If the caller had interrupts enabled, an interrupt may have corrupted SPSR ; the worst effect of this is that we may not enable interrupts. So... MRS R3, SPSR TST R3, #I32_bit ; EQ => IRQs were on MSREQ CPSR_c, #SVC2632 ; so turn them on ByteToNosbod DoOSBYTE87 ; Results in R1, R2 (i.e. char, mode) MyOsbyte ; ***************************************************************************** ; Insert Character Into Buffer Osbyte8A BL INSERT MyOsbyte ; ***************************************************************************** ; Write Filing System Options : *OPT Osbyte8B MOV R0, #FSControl_Opt SWI XOS_FSControl ByteReturnV ; ***************************************************************************** ; Issue Paged ROM Service Request Osbyte8F BL Issue_Service MyOsbyte ; ***************************************************************************** ; Select vertical screen shift and interlace option :*TV Osbyte90 LDRB R0, TVVertical STRB R1, TVVertical MOV R1, R0 ; old vertical in R1 AND R0, R2, #1 LDRB R2, TVInterlace ; old interlace in R2 STRB R0, TVInterlace MyOsbyte ; ***************************************************************************** ; Get Character From Buffer Osbyte91 CLRV ; remove not examine RemVEntry ADR R14, MyOsbyte80 REMOVE Push "R10,R12,R14" MOV R10, #REMV B GoVec ; ***************************************************************************** ; Examine Buffer Status Osbyte98 SETV ; examine not remove B RemVEntry ; ***************************************************************************** ; Insert Character Code Into buffer checking for ESCAPE Osbyte99 BL DoInsertESC MyOsbyte ; ***************************************************************************** ; Update pseudo 6850 control register and soft copy Osbyte9C MOV r0, #SerialOp_Modify6850 ; OS_SerialOp to modify 6850 control register SWI XOS_SerialOp MyOsbyte ; ***************************************************************************** ; 'Fast TUBE BPUT' Osbyte9D MOV R0, R1 ; R0 := character MOV R1, R2 ; R1 := handle SWI XOS_BPut ByteReturnV ; ***************************************************************************** ; Read VDU Variable (0..15 implemented) OsbyteA0 ByteToNosbod DoReadVDUVariable MyOsbyte ; ***************************************************************************** ; Read CMOS RAM OsbyteA1 ; R1 = address , R2 = result CLRPSR I_bit, R0 ; this may take some time MOV R0, R1 BL Read ; Read CMOS ram at address <R0> MOV R2, R0 ; Result in R0, return in R2 MyOsbyte ; Write CMOS RAM OsbyteA2 CLRPSR I_bit, R0 ; this may take some time MOVS R0, R1 [ ProtectStationID ASSERT NetStnCMOS = 0 MyOsbyte EQ ] MOV R1, R2 BL Write MOV R1, R0 ; R1 is supposed to be preserved MyOsbyte ; ***************************************************************************** ; OsByte 163,... applications call OsbyteA3 ROUT TEQ R1, #242 Unused NE ; not 242 - pass it on BL %FT10 MyOsbyte ; if come to here, has been claimed 10 Push R14 ByteToNosbod DoOsbyte163_242 Pull R14 ; if come to here, wasn't claimed Unused ; ***************************************************************************** ; Read Output cursor Position OsbyteA5 ByteToNosbod DoReadPOSVPOSO ; Result in R1,R2 (Horiz,vert) MyOsbyte ; Read OsbyteVars location. Legacy DoOsbyteVar API extended for 32bit high ; zero page address, and fixed to treat ByteVars as read-only (RISC OS has ; probably never supported modifying the value at runtime) OsbyteA6 MOV R1,#(ZeroPage+OsbyteVars-&A6) :AND: 255 LDR R2,=(ZeroPage+OsbyteVars-&A6) :SHR: 8 MyOsbyte OsbyteA7 LDR R1,=(ZeroPage+OsbyteVars-&A6) :SHR: 8 LDRB R2, [WsPtr, #2] ; "next location", OS_Byte &A8 R1 value MyOsbyte ; ***************************************************************************** ; ; All calls &A8 to &FF are implemented together. ; <NEW VALUE> = (<OLD VALUE> AND R2 ) EOR R1 ; The old value is returned in R1 and the next location is returned in R2 ; ; ***************************************************************************** DoOsbyteVar SUB R0, R0, #OsByte_BaseOfOSByteVarTable LDRB R3, [WsPtr, R0] ; Load the byte AND R11, R3, R2 ; Mangle it as required by the law EOR R11, R11, R1 ; ................................ MOV R1, R3 ; Return old value in R1 TEQ R0, #OsbyteKeyStatus - OsByte_BaseOfOSByteVarTable BEQ DoOsbyteKeyStatus ; sorry - it's not pure any more, mea culpa. KJB. STRB R11, [R0, WsPtr]! ; R0 +:= WsPtr LDRB R2, [R0, #1] ; Return contents of next loc in R2 MyOsbyte ; Keyboard status (OS_Byte 202). ; on entry: R0 = OsbyteKeyStatus - OsByte_BaseOfOSByteVarTable ; R1 = old value ; R11 = new value DoOsbyteKeyStatus ROUT Push "R0-R3,R10" MOV R10,#UpCallV ; (Can't use OS_UpCall - it enables IRQs and we're documented as not doing so) MOV R3,R11 ; R3 = new value MOV R2,R1 ; R2 = old value MOV R1,#0 ; pre-change MOV R0,#UpCall_KeyboardStatus BL CallVector ; go on then, interfere (Corrupts R10 & WsPtr) LDR R0, [R13] ; get back original R0 [ ZeroPage = 0 STRB R3, [R0, #OsbyteVars]! ; R0 +:= WsPtr | LDR R14, =ZeroPage+OsbyteVars STRB R3, [R0, R14]! ; R0 +:= WsPtr ] LDRB R14, [R0, #1] ; Return contents of next loc in R2 STR R14, [R13, #8] ; by popping it on the stack TEQ R2, R3 ; don't bother with UpCall if it didn't change... MOVNE R10,#UpCallV MOVNE R1,#1 ; post-change MOVNE R0,#UpCall_KeyboardStatus BLNE CallVector ; can't do anything about it now... Pull "R0-R3,R10" MyOsbyte LTORG ; All the unused OS_Byte calls ; ADC stuff Osbyte10 ROUT Osbyte11 ROUT ; Incr/Decr Polling Int Osbyte16 Osbyte17 ; Unused Osbyte18 ; Write 1MHz bus selection Osbyte6B ; Write Usage of Shadow memory for normal access Osbyte6C ; Make temporary filing system permanent Osbyte6D ; &6E and &6F are reserved by 3rd parties Osbyte6E Osbyte6F ; &73 and &74 reserved for Electron Osbyte73 Osbyte74 ; Close SPOOL(ON) & EXEC files Osbyte77 ; Read top of USER RAM Osbyte84 ; Read top of user RAM for given mode Osbyte85 ; *CODE Osbyte88 ; *MOTOR Osbyte89 ; *TAPE Osbyte8C ; *ROM Osbyte8D ; Enter Language ROM Osbyte8E ; Access Mem.Map.IO &92..&97 Osbyte92 Osbyte93 Osbyte94 Osbyte95 Osbyte96 Osbyte97 ; Write to VidULA & COPY Osbyte9A Osbyte9B ; Old Style Speech Osbyte9E Osbyte9F ; Check Processor Type OsbyteA4 Unused ; ***************************************************************************** ; ; GetCountry - Read country ; ; in: R1 = country number or alphabet number ; ; out: IF R1=0 THEN ; R1:=Configured Country ; IF R1=0 THEN ; R1:=LastKbId ; IF R1>=&20 THEN R1:=0 ; ENDIF ; ENDIF ; ; R0 undefined ; GetCountry ROUT TEQ R1, #0 ; if not setting default, exit MOVNE PC, R14 Push R14 MOV R0, #CountryCMOS ; read configured country BL Read MOVS R1, R0 ; if not Country Default, exit Pull PC, NE LDR R0, =ZeroPage+KeyWorkSpace LDRB R1, [R0, #:INDEX: LastKbId] ; read last valid keyboard id CMP R1, #&20 ; if <&20 then use this MOVCS R1, #0 ; else set to 0 Pull PC END