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 its 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