BBC Operation System OS 1.20 VDU Main Routines ************************************************************************** ************************************************************************** ** ** ** OSWRCH MAIN ROUTINE entry from E0C5 ** ** ** ** output a byte via the VDU stream ** ** ** ************************************************************************** ************************************************************************** ;This routine takes up over 40% of the operating system ROM ;Entry points are variable, as are the results achieved. ;Tracing any particular path is relatively easy but generalising for ;commenting is not. For clarity comments will not be as detailed as ;for later parts of the Operating System. C4C0 LDX &026A ;get number of items in VDU queue C4C3 BNE &C512 ;if parameters needed then C512 C4C5 BIT &D0 ;else check status byte C4C7 BVC &C4D8 ;if cursor editing enabled two cursors exist C4C9 JSR &C568 ;swap values C4CC JSR &CD6A ;then set up write cursor C4CF BMI &C4D8 ;if display disabled C4D8 C4D1 CMP #&0D ;else if character in A=RETURN teminate edit C4D3 BNE &C4D8 ;else C4D8 C4D5 JSR &D918 ;terminate edit C4D8 CMP #&7F ;is character DELETE ? C4DA BEQ &C4ED ;if so C4ED C4DC CMP #&20 ;is it less than space? (i.e. VDU control code) C4DE BCC &C4EF ;if so C4EF C4E0 BIT &D0 ;else check VDU byte ahain C4E2 BMI &C4EA ;if screen disabled C4EA C4E4 JSR &CFB7 ;else display a character C4E7 JSR &C664 ;and cursor right C4EA JMP &C55E ; ********* read link addresses and number of parameters ***************** C4ED LDA #&20 ;to replace delete character ********* read link addresses and number of parameters ***************** C4EF TAY ;Y=A C4F0 LDA &C333,Y ;get lo byte of link address C4F3 STA &035D ;store it in jump vector C4F6 LDA &C354,Y ;get hi byte C4F9 BMI &C545 ;if negative (as it will be if a direct address) ;there are no parameters needed ;so C545 C4FB TAX ;else X=A C4FC ORA #&F0 ;set up negated parameter count C4FE STA &026A ;store it as number of items in VDU queue C501 TXA ;get back A C502 LSR ;A=A/16 C503 LSR ; C504 LSR ; C505 LSR ; C506 CLC ;clear carry C507 ADC #&C3 ;add &C3 to get hi byte of link address C509 STA &035E ; C50C BIT &D0 ;check if cursor editing enabled C50E BVS &C52F ;if so re-exchange pointers C510 CLC ;clear carry C511 RTS ;and exit ;return with carry clear indicates that printer action not required. ; ********** parameters are outstanding *********************************** X=&26A = 2 complement of number of parameters X=&FF for 1, FE for 2 etc. C512 STA &0224,X ;store parameter in queue C515 INX ;increment X C516 STX &026A ;store it as VDU queue C519 BNE &C532 ;if not 0 C532 as more parameters are needed C51B BIT &D0 ;get VDU status byte C51D BMI &C534 ;if screen disabled C534 C51F BVS &C526 ;else if cursor editing C526 C521 JSR &CCF5 ;execute required function C524 CLC ;clear carry C525 RTS ;and exit ; C526 JSR &C568 ;swap values of cursors C529 JSR &CD6A ;set up write cursor C52C JSR &CCF5 ;execute required function C52F JSR &C565 ;re-exchange pointers C532 CLC ;carry clear C533 RTS ;exit ************************************************************************* * * * VDU 1 - SEND NEXT CHARACTER TO PRINTER * * * * 1 parameter required * * * ************************************************************************* ; C534 LDY &035E ;if upper byte of link address not &C5 C537 CPY #&C5 ;printer is not interested C539 BNE &C532 ;so C532 C53B TAX ;else X=A C53C LDA &D0 ;A=VDU status byte C53E LSR ;get bit 0 into carry C53F BCC &C511 ;if printer not enabled exit C541 TXA ;restore A C542 JMP &E11E ;else send byte in A (next byte) to printer *********** if explicit link address found, no parameters *************** C545 STA &035E ;upper byte of link address C548 TYA ;restore A C549 CMP #&08 ;is it 7 or less? C54B BCC &C553 ;if so C553 C54D EOR #&FF ;invert it C54F CMP #&F2 ;c is set if A >&0D C551 EOR #&FF ;re invert C553 BIT &D0 ;VDU status byte C555 BMI &C580 ;if display disabled C580 C557 PHP ;push processor flags C558 JSR &CCF5 ;execute required function C55B PLP ;get back flags C55C BCC &C561 ;if carry clear (from C54B/F) **************** main exit routine ************************************** C55E LDA &D0 ;VDU status byte C560 LSR ;Carry is set if printer is enabled C561 BIT &D0 ;VDU status byte C563 BVC &C511 ;if no cursor editing C511 to exit ***************** cursor editing routines ******************************* C565 JSR &CD7A ;restore normal write cursor C568 PHP ;save flags and C569 PHA ;A C56A LDX #&18 ;X=&18 C56C LDY #&64 ;Y=&64 C56E JSR &CDDE ;exchange &300/1+X with &300/1+Y C571 JSR &CF06 ;set up display address C574 JSR &CA02 ;set cursor position C577 LDA &D0 ;VDU status byte C579 EOR #&02 ;invert bit 1 to allow or bar scrolling C57B STA &D0 ;VDU status byte C57D PLA ;restore flags and A C57E PLP ; C57F RTS ;and exit ; C580 EOR #&06 ;if A<>6 C582 BNE &C58C ;return via C58C C584 LDA #&7F ;A=&7F C586 BCC &C5A8 ;and goto C5A8 ALWAYS!! ******************* check text cursor in use *************************** C588 LDA &D0 ;VDU status byte C58A AND #&20 ;set A from bit 5 of status byte C58C RTS ;and exit A=0 if text cursor, &20 if graphics ************************************************************************* * * * VDU 14 - SET PAGED MODE * * * ************************************************************************* ; C58D LDY #&00 ;Y=0 C58F STY &0269 ;paged mode counter C592 LDA #&04 ;A=04 C594 BNE &C59D ;jump to C59D ************************************************************************* * * * VDU 2 - PRINTER ON (START PRINT JOB) * * * ************************************************************************* C596 JSR &E1A2 ;select printer buffer and output character C599 LDA #&94 ;A=&94 ;when inverted at C59B this becomes =&01 ************************************************************************* * * * VDU 21 - DISABLE DISPLAY * * * ************************************************************************* C59B EOR #&95 ;if A=&15 A now =&80: if A=&94 A now =1 C59D ORA &D0 ;VDU status byte set bit 0 or bit 7 C59F BNE &C5AA ;branch forward to store ************************************************************************* * * * VDU 3 - PRINTER OFF (END PRINT JOB) * * * ************************************************************************* C5A1 JSR &E1A2 ;select printer buffer and output character C5A4 LDA #&0A ;A=10 to clear status bits below... ************************************************************************* * * * VDU 15 - PAGED MODE OFF * * * ************************************************************************* ; A=&F or &A C5A6 EOR #&F4 ;convert to &FB or &FE C5A8 AND &D0 ;VDU status byte clear bit 0 or bit 2 of status C5AA STA &D0 ;VDU status byte C5AC RTS ;exit ************************************************************************* * * * VDU 4 - OUTPUT AT TEXT CURSOR * * * ************************************************************************* ; C5AD LDA &0361 ;pixels per byte C5B0 BEQ &C5AC ;if no graphics in current mode C5AC C5B2 JSR &C951 ;set CRT controller for text cursor C5B5 LDA #&DF ;this to clear bit 5 of status byte C5B7 BNE &C5A8 ;via C5A8 exit ************************************************************************* * * * VDU 5 - OUTPUT AT GRAPHICS CURSOR * * * ************************************************************************* C5B9 LDA &0361 ;pixels per byte C5BC BEQ &C5AC ;if none this is text mode so exit C5BE LDA #&20 ;set up graphics cursor C5C0 JSR &C954 ;via C954 C5C3 BNE &C59D ;set bit 5 via exit C59D ************************************************************************* * * * VDU 8 - CURSOR LEFT * * * ************************************************************************* C5C5 JSR &C588 ;A=0 if text cursor A=&20 if graphics cursor C5C8 BNE &C61F ;move cursor left 8 pixels if graphics C5CA DEC &0318 ;else decrement text column C5CD LDX &0318 ;store new text column C5D0 CPX &0308 ;if it is less than text window left C5D3 BMI &C5EE ;do wraparound cursor to rt of screen 1 line up C5D5 LDA &034A ;text cursor 6845 address C5D8 SEC ;subtract C5D9 SBC &034F ;bytes per character C5DC TAX ;put in X C5DD LDA &034B ;get text cursor 6845 address C5E0 SBC #&00 ;subtract 0 C5E2 CMP &034E ;compare with hi byte of screen RAM address C5E5 BCS &C5EA ;if = or greater C5E7 ADC &0354 ;add screen RAM size hi byte to wrap around C5EA TAY ;Y=A C5EB JMP &C9F6 ;Y hi and X lo byte of cursor position ***************** execute wraparound left-up***************************** C5EE LDA &030A ;text window right C5F1 STA &0318 ;text column *************** cursor up *********************************************** C5F4 DEC &0269 ;paged mode counter C5F7 BPL &C5FC ;if still greater than 0 skip next instruction C5F9 INC &0269 ;paged mode counter to restore X=0 C5FC LDX &0319 ;current text line C5FF CPX &030B ;top of text window C602 BEQ &C60A ;if it's at top of window C60A C604 DEC &0319 ;else decrement current text line C607 JMP &C6AF ;and carry on moving cursor ******** cursor at top of window **************************************** C60A CLC ;clear carry C60B JSR &CD3F ;check for window violatations C60E LDA #&08 ;A=8 to check for software scrolling C610 BIT &D0 ;compare against VDU status byte C612 BNE &C619 ;if not enabled C619 C614 JSR &C994 ;set screen start register and adjust RAM C617 BNE &C61C ;jump C61C C619 JSR &CDA4 ;soft scroll 1 line C61C JMP &C6AC ;and exit **********cursor left and down with graphics cursor in use ************** C61F LDX #&00 ;X=0 to select horizontal parameters ********** cursor down with graphics in use ***************************** ;X=2 for vertical or 0 for horizontal C621 STX &DB ;store X C623 JSR &D10D ;check for window violations C626 LDX &DB ;restore X C628 SEC ;set carry C629 LDA &0324,X ;current graphics cursor X>1=vertical C62C SBC #&08 ;subtract 8 to move back 1 character C62E STA &0324,X ;store in current graphics cursor X>1=verticaal C631 BCS &C636 ;if carry set skip next C633 DEC &0325,X ;current graphics cursor hi -1 C636 LDA &DA ;&DA=0 if no violation else 1 if vert violation ;2 if horizontal violation C638 BNE &C658 ;if violation C658 C63A JSR &D10D ;check for window violations C63D BEQ &C658 ;if none C658 C63F LDX &DB ;else get back X C641 LDA &0304,X ;graphics window rt X=0 top X=2 C644 CPX #&01 ;is X=0 C646 BCS &C64A ;if not C64A C648 SBC #&06 ;else subtract 7 C64A STA &0324,X ;current graphics cursor X>1=vertical C64D LDA &0305,X ;graphics window hi rt X=0 top X=2 C650 SBC #&00 ;subtract carry C652 STA &0325,X ;current graphics cursor X<2=horizontal else vertical C655 TXA ;A=X C656 BEQ &C660 ;cursor up C658 JMP &D1B8 ;set up external coordinates for graphics ************************************************************************* * * * VDU 11 - CURSOR UP * * * ************************************************************************* C65B JSR &C588 ;A=0 if text cursor A=&20 if graphics cursor C65E BEQ &C5F4 ;if text cursor then C5F4 C660 LDX #&02 ;else X=2 C662 BNE &C6B6 ;goto C6B6 ************************************************************************* * * * VDU 9 - CURSOR RIGHT * * * ************************************************************************* C664 LDA &D0 ;VDU status byte C666 AND #&20 ;check bit 5 C668 BNE &C6B4 ;if set then graphics cursor in use so C6B4 C66A LDX &0318 ;text column C66D CPX &030A ;text window right C670 BCS &C684 ;if X exceeds window right then C684 C672 INC &0318 ;text column C675 LDA &034A ;text cursor 6845 address C678 ADC &034F ;add bytes per character C67B TAX ;X=A C67C LDA &034B ;text cursor 6845 address C67F ADC #&00 ;add carry if set C681 JMP &C9F6 ;use X and Y to set new cursor address ********: text cursor down and right ************************************* C684 LDA &0308 ;text window left C687 STA &0318 ;text column ********: text cursor down ************************************* C68A CLC ;clear carry C68B JSR &CAE3 ;check bottom margin, X=line count C68E LDX &0319 ;current text line C691 CPX &0309 ;bottom margin C694 BCS &C69B ;if X=>current bottom margin C69B C696 INC &0319 ;else increment current text line C699 BCC &C6AF ; C69B JSR &CD3F ;check for window violations C69E LDA #&08 ;check bit 3 C6A0 BIT &D0 ;VDU status byte C6A2 BNE &C6A9 ;if software scrolling enabled C6A9 C6A4 JSR &C9A4 ;perform hardware scroll C6A7 BNE &C6AC ; C6A9 JSR &CDFF ;execute upward scroll C6AC JSR &CEAC ;clear a line C6AF JSR &CF06 ;set up display address C6B2 BCC &C732 ; *********** graphic cursor right **************************************** C6B4 LDX #&00 ; ************** graphic cursor up (X=2) ********************************** C6B6 STX &DB ;store X C6B8 JSR &D10D ;check for window violations C6BB LDX &DB ;get back X C6BD CLC ;clear carry C6BE LDA &0324,X ;current graphics cursor X>1=vertical C6C1 ADC #&08 ;Add 8 pixels C6C3 STA &0324,X ;current graphics cursor X>1=vertical C6C6 BCC &C6CB ; C6C8 INC &0325,X ;current graphics cursor X<2=horizontal else vertical C6CB LDA &DA ;A=0 no window violations 1 or 2 indicates violation C6CD BNE &C658 ;if outside window C658 C6CF JSR &D10D ;check for window violations C6D2 BEQ &C658 ;if no violations C658 C6D4 LDX &DB ;get back X C6D6 LDA &0300,X ;graphics window X<2 =left else bottom C6D9 CPX #&01 ;If X=0 C6DB BCC &C6DF ;C6DF C6DD ADC #&06 ;else add 7 C6DF STA &0324,X ;current graphics cursor X>1=vertical C6E2 LDA &0301,X ;graphics window hi X<2 =left else bottom C6E5 ADC #&00 ;add anny carry C6E7 STA &0325,X ;current graphics cursor X<2=horizontal else vertical C6EA TXA ;A=X C6EB BEQ &C6F5 ;if X=0 C6F5 cursor down C6ED JMP &D1B8 ;set up external coordinates for graphics ************************************************************************* * * * VDU 10 - CURSOR DOWN * * * ************************************************************************* C6F0 JSR &C588 ;A=0 if text cursor A=&20 if graphics cursor C6F3 BEQ &C68A ;if text cursor back to C68A C6F5 LDX #&02 ;else X=2 to indicate vertical movement C6F7 JMP &C621 ;move graphics cursor down ************************************************************************* * * * VDU 28 - DEFINE TEXT WINDOW * * * * 4 parameters * * * ************************************************************************* ;parameters are set up thus ;0320 P1 left margin ;0321 P2 bottom margin ;0322 P3 right margin ;0323 P4 top margin ;Note that last parameter is always in 0323 C6FA LDX &0355 ;screen mode C6FD LDA &0321 ;get bottom margin C700 CMP &0323 ;compare with top margin C703 BCC &C758 ;if bottom margin exceeds top return C705 CMP &C3E7,X ;text window bottom margin maximum C708 BEQ &C70C ;if equal then its OK C70A BCS &C758 ;else exit C70C LDA &0322 ;get right margin C70F TAY ;put it in Y C710 CMP C3EF,X ;text window right hand margin maximum C713 BEQ &C717 ;if equal then OK C715 BCS &C758 ;if greater than maximum exit C717 SEC ;set carry to subtract C718 SBC &0320 ;left margin C71B BMI &C758 ;if left greater than right exit C71D TAY ;else A=Y (window width) C71E JSR &CA88 ;calculate number of bytes in a line C721 LDA #&08 ;A=8 to set bit of &D0 C723 JSR &C59D ;indicating that text window is defined C726 LDX #&20 ;point to parameters C728 LDY #&08 ;point to text window margins C72A JSR &D48A ;(&300/3+Y)=(&300/3+X) C72D JSR &CEE8 ;set up screen address C730 BCS &C779 ;home cursor within window C732 JMP &CA02 ;set cursor position