OSBYTE 123, 156; OSWRCH entry point; Econet / User printer routines; Flush buffers; Count or purge buffer (CNPV); Append to buffer - 362 bytes (2.2%)
- §1. OSWRCH - write character
- §2. On Entry:
- §3. openPrinterChannel
- §4. checkForSerialPrinter
- §5. OSBYTE 156 - Update ACIA Control Register and OS Copy
- §6. userPrinter
- §7. OSBYTE 123 - Warn OS about printer going dormant
- §8. printerServiceCallIfNotEmpty
- §9. printerServiceCall
- §10. Flushes the given buffer
- §11. Count or Purge Buffer (CNPV) - Default Entry Point
- §12. Adds a byte to a buffer.
This is the main entry point for writing characters to the display and/or to other devices such as ECONET, a printer, RS-423 or to a file. Note: the .characterDestinationsAvailableFlags has the following bits: bit 0 - enable RS-423 driver bit 1 - disable VDU driver bit 2 - disable printer driver bit 3 - enable printer, independent of VDU 2/3 (=CTRL B/C) bit 4 - disable SPOOLed output bit 5 - not used, zero bit 6 - disable printer driver (unless preceded by VDU 1) bit 7 - not used, zero On Entry: A = character to write On Exit: A, X, Y are preserved
.oswrchEntryPoint = $e0a4 PHA } TXA } PHA } store A,X,Y registers TYA } PHA } TSX X = stack pointer LDA .stackPage + 3,X peek into stack to get A value back PHA push A again BIT .econetWriteCharacterInterceptionFlag check OSWRCH interception flag BPL .skipEconetProcessing if (not set) then branch (skip Econet) TAY pass character to Y LDA #4 A=4 for OSWRCH service call JSR .netvJumper call NETV code BCS .oswrchFinishUp if (claimed) then branch (finish up and exit) .skipEconetProcessing = $e0bb CLC prepare to not send this to printer LDA #2 check output destination BIT .characterDestinationsAvailableFlags is VDU driver disabled? BNE .skipVDUOutput yes, skip past VDU driver PLA pull character PHA push character JSR .vduChrEntryPoint call VDU driver on exit, C=1 if character to be sent to printer .skipVDUOutput = $e0c8 LDA #8 check output destination BIT .characterDestinationsAvailableFlags is printer separately enabled? BNE .printerEnabled yes, jump to call printer driver BCC .printerDisabled carry clear, don't sent to printer .printerEnabled = $e0d1 PLA pull character PHA push character JSR .sendCharacterToPrinter call printer driver .printerDisabled = $e0d6 LDA .characterDestinationsAvailableFlags check output destination ROR check RS-423 output bit BCC .skipRS423Output if (RS-423 output is disabled) then branch (skip past serial output) Check for timeout LDY .rs423TimeoutCounter get RS-423 timout counter DEY decrease counter BPL .skipRS423Output if (timed out) then branch (skip past serial code) RS-423 output PLA pull character PHA push character PHP save IRQs SEI disable IRQs LDX #.bufferNumberRS423Output X=RS-423 output buffer PHA save character JSR .osbyte152EntryPoint examine RS-423 output buffer to see if it's empty BCC + buffer is not empty, jump to send character JSR .clearBusyFlagAndSetRS423Active set RS-423 Active + PLA get character LDX #.bufferNumberRS423Output X=RS-423 output buffer JSR .addByteToBuffer send character to RS-423 output buffer PLP restore IRQs .skipRS423Output = $e0f7 LDA #$10 check output destination BIT .characterDestinationsAvailableFlags check SPOOL output BNE .oswrchFinishUp if (SPOOL output disabled) then branch (skip past SPOOL output) LDY .spoolFileHandle get SPOOL file handle BEQ .oswrchFinishUp if (not open) then branch (skip past SPOOL output) PLA pull character PHA push character SEC } ROR .tapeCritical } Set tape critical flag JSR .OSBPUT write character to SPOOL channel (A=character to write, Y=file handle) LSR .tapeCritical clear tape critical flag .oswrchFinishUp = $e10d PLA PLA } TAY } PLA } restore A,X,Y registers TAX } PLA } RTS
A=character to print
.sendCharacterToPrinter = $e114 BIT .characterDestinationsAvailableFlags check for bit 6 set BVS .exit16 if (printer is disabled) then branch (exit) CMP .printerIgnoreCharacter compare character against printer ignore character BEQ .exit16 if (the same) then branch (exit) .sendValidByteToPrinter = $e11e PHP save flags (including IRQ flag) SEI disable interrupts TAX store byte to send in X LDA #%00000100 } BIT .characterDestinationsAvailableFlags } check bit 2 'disable printer } driver' BNE .pullAndExit14 if (printer is disabled) then branch (pull flags and exit) TXA restore byte to send to A LDX #.bufferNumberPrinter X=printer buffer number JSR .addByteToBuffer put character in printer buffer BCS .pullAndExit14 if (carry set, i.e. unsuccessful) then branch (pull flags and exit) BIT .printerBufferEmptyFlag check buffer empty flag BPL .pullAndExit14 if (printer buffer is not empty) then branch (pull flags and exit) JSR .openPrinterChannel open printer channel .pullAndExit14 = $e138 PLP restore flags (including IRQ flag) .exit16 = $e139 RTS
.openPrinterChannel = $e13a LDA .printerDestination check printer destination BEQ .flushBufferX if (zero) then branch (clear printer buffer and exit) CMP #1 } BNE .checkForSerialPrinter } if (parallel printer not selected) } then branch (check for serial } printer) deal with parallel printer JSR .osbyte145EntryPoint read a byte from the printer buffer ROR .printerBufferEmptyFlag rotate carry into bit 7 of the printer buffer empty flag BMI .exit17 if (printer buffer empty) then branch (return) To send data to the parallel printer: 1. Enable the User VIA interrupt '1'. The printer will trigger an IRQ when it is ready for another character. 2. Write the byte to send to .userVIARegisterA 3. Set bits 1-3 of the userVIAPeripheralControlRegister to %110 4. Set bits 1-3 of the userVIAPeripheralControlRegister to %111 This sends a 'STROBE' signal to advise the printer that valid data is waiting. LDY #%10000010 enable interrupt 1 of the user VIA STY .userVIAInterruptEnableRegister this is triggered by the printer when it is ready to receive a new character STA .userVIARegisterA pass byte to the Centronics port LDA .userVIAPeripheralControlRegister } AND #%11110001 } ORA #%00001100 } pulse CA2 line to generate STA .userVIAPeripheralControlRegister } STROBE signal to advise printer ORA #%00001110 } that valid data is waiting STA .userVIAPeripheralControlRegister } BNE .exit17 ALWAYS branch (return) [this could just be an RTS, saving one byte]
.checkForSerialPrinter = $e164 CMP #2 } BNE .userPrinter } if (serial printer is NOT } selected) then branch (check for } user printer) deal with serial printer LDY .rs423TimeoutCounter } DEY } BPL .flushBufferX } if (timeout counter is timed out) } then branch (to flush the buffer) LSR .printerBufferEmptyFlag clear printer buffer empty flag .clearBusyFlagAndSetRS423Active = $e170 LSR .rs423ReadyFlag clear RS-423 busy flag .setRS423Active = $e173 JSR .getRS423InputBufferFreeBytes } BCC .exit17 } if (free space in buffer is low) } then branch (return) LDX #%00100000 set bit 5 on ACIA control register set 'Request To Send' low (meaning Active) .writeToACIARequestToSend = $e17a LDY #%10011111 Mask for setting bits 5 and 6 This writes the 'Request To Send' value. fall through...
§5. OSBYTE 156 - Update ACIA Control Register and OS Copy.
write (current value AND Y) EOR X Preserves Y and flags
.osbyte156EntryPoint = $e17c PHP push flags SEI disable interrupts TYA A=Y STX .tempStoreFA .tempStoreFA=X AND .rs423ControlRegisterCopy A=old value AND Y EOR X EOR .tempStoreFA LDX .rs423ControlRegisterCopy get old value in X .storeACIAAndPull = $e189 STA .rs423ControlRegisterCopy put new value in STA .acia6850ControlRegister and store to ACIA control register PLP get back flags .exit17 = $e190 RTS
.userPrinter = $e191 CLC clear carry LDA #1 A = 1 JSR .printerServiceCall fall through...
§7. OSBYTE 123 - Warn OS about printer going dormant.
This call is used by the User Print Routine to indicate to the MOS that it has finished its task (The User Print Routine is selected by *FX 5,3).
.osbyte123EntryPoint = $e197 ROR .printerBufferEmptyFlag mark printer buffer empty (clear top bit) - RTS
§8. printerServiceCallIfNotEmpty.
Signal to the printer that there's at least one character in the printer buffer, at a rate of 100Hz until the printer driver deals with it.
.printerServiceCallIfNotEmpty = $e19b BIT .printerBufferEmptyFlag check printer buffer empty flag BMI - if (buffer is empty) then branch (exit) LDA #0 A=0 (100Hz update when printer is active and buffer is not empty) fall through...
Econet / User printer routines See NAUG Section 24.2.4, Page 424 for more detail on reason codes On Entry: A = reason code 0 means 100Hz update 1 means become active, since printer buffer is no longer empty 2 means VDU 2 happened (disable printer output) 3 means VDU 3 happened (enable printer output) 5 means select new printer driver (entry via OSBYTE 5 to .selectPrinterType)
.printerServiceCall = $e1a2 LDX #.bufferNumberPrinter X=printer buffer number .selectPrinterType = $e1a4 LDY .printerDestination Y=printer destination (*FX 5 value) JSR .netvJumper let network have a look (should respond if Y=4 for net printer) JMP (.vectorUPTV) let user printer routine have a look (can respond if Y=3, or 5-255 for user printer)
§10. Flushes the given buffer.
For buffer numbers, see .bufferNumberKeyboard. On Entry: X=buffer number
.flushBufferX = $e1ad CLC clear carry .flushSoundBufferX = $e1ae PHA save A PHP save flags SEI disable interrupts BCS .flushNonSoundBufferX if (carry set on entry) then branch LDA .bufferTypeAndSerialBaudRatesTable,X carry clear so get byte from table BPL .flushNonSoundBufferX if (not sound buffer) then branch JSR .clearSoundChannelBuffer clear sound buffer .flushNonSoundBufferX = $e1bb SEC set carry ROR .bufferEmptyFlags,X rotate buffer flag to show buffer empty CPX #2 BCS .skipInputBufferHandling if (X > 1) then branch (it's not an input buffer) LDA #0 this is an input buffer STA .softKeyStringLength reset length of the *KEY string currently being decoded (to stop decoding a soft key, which would otherwise add more characters into the input buffer) STA .twosComplimentOfNumberOfBytesInVDUQueue reset length of VDU queue .skipInputBufferHandling = $e1cb JSR .purgeBuffer purge buffer PLP restore flags PLA restore A RTS
§11. Count or Purge Buffer (CNPV) - Default Entry Point.
On Entry: X = buffer to access if V set then purge buffer (else count buffer) for count buffer: if C set then get bytes free else get bytes used
.cnpEntryPoint = $e1d1 BVC .countBuffer if (V clear) then branch (count buffer) LDA .bufferStartIndices,X purge buffer by setting STA .bufferEndIndices,X end of buffer = start of buffer RTS .countBuffer = $e1da PHP push flags SEI disable interrupts PHP push flags SEC set carry LDA .bufferEndIndices,X get end of buffer SBC .bufferStartIndices,X subtract start of buffer BCS + if (carry set) then branch SEC set carry SBC .emptyBufferStartOffset,X subtract buffer start offset (i.e. add buffer length) + PLP pull flags BCC + if (carry clear) then branch (to tidy up and exit) CLC clear carry ADC .emptyBufferStartOffset,X adc to get bytes used EOR #$FF and invert to get space left + LDY #0 Y=0 TAX X=A PLP get back flags RTS
§12. Adds a byte to a buffer..
On failure (e.g. the buffer is full), flash the keyboard lights and keep trying On Entry: A = byte to write X = buffer to write into On Exit: Carry clear if successful
.addByteToBuffer = $e1f8 SEI prevent interrupts JSR .insJumper enter a byte in buffer X BCC .exit18 if (successful) then branch (exit) JSR .turnOnKeyboardLightsAndTestEscape switch on both keyboard lights PHP push flags PHA push A JSR .keyboardIndicators switch off unselected LEDs PLA recall A PLP recall flags BMI .exit18 if (return is -ve, i.e. Escape pressed) then branch (exit) CLI allow interrupts BCS .addByteToBuffer if (byte didn't enter buffer) then branch (go back and try again) .exit18 = $e20d RTS