OSBYTE 132, 133, 135; Cursor editing mode routines - 382 bytes (2.3%)
- §1. OSBYTE 135 - Read character at text cursor position
- §2. nonMODE7ReadCharacter
- §3. Read character from screen pixels
- §4. Read pixel
- §5. Check the graphics point on the VDU queue is within the graphics window
- §6. Check the given point is within the graphics window
- §7. splitIntoTwoCursors
- §8. readCharacterFromScreenAndCursorRight
- §9. terminateEdit
- §10. OSBYTE 132 - Read HIMEM (start of screen memory)
- §11. OSBYTE 133 - Read start of screen memory for given MODE
§1. OSBYTE 135 - Read character at text cursor position.
.osbyte135EntryPoint = $d7c2 LDY .vduNumberOfLogicalColoursMinusOne get number of logical colours for current MODE BNE .nonMODE7ReadCharacter if (MODE is not 7) then branch LDA (.vduWriteCursorScreenAddressLow),Y read MODE 7 character from screen LDY #2 Y=2 - CMP .teletextCharacterConversionTable + 1,Y compare with conversion table BNE + if (not equal) then branch LDA .teletextCharacterConversionTable,Y get previous byte from table DEY Y=Y-1 + DEY Y=Y-1 BPL - if (+ve) then branch (loop back and do it again) .finishUpFX135 = $d7d7 LDY .vduCurrentScreenMODE Y = current screen MODE TAX X = character RTS
.nonMODE7ReadCharacter = $d7dc JSR .readCharacterDefinitionMaskFromScreen read from screen, making a one bit mask of 8 bytes to match against each character, in workspaceA-H LDX #.charSPACE Start with the space character (loop counter) .readCharLoop = $d7e1 TXA Loop through each character in turn looking to see if it matches workspaceA-H PHA Save character JSR .getCharacterDefinitionAddress get character definition address for character A PLA recall character TAX move to X - LDY #7 Y=7 -- LDA .vduWorkspaceA,Y get byte in workspaceA-H copy CMP (.vduTempStoreDE),Y check against character definition BNE + if (not the same) then branch (to skip to next character) DEY Y-- BPL -- if (still non-negative) then branch (back to loop eight times, to check each row of the character) TXA At this point the character matches CPX #.charDELETE but if it's the DELETE character then pretend we didn't match and carry on BNE .finishUpFX135 if (we are NOT the DELETE character) then branch (to finish up) + INX no match on this character so increment to next character LDA .vduTempStoreDE } CLC } Add 8 to address of character } definition to move on to the next } character ADC #8 } Affects low byte only as we check } one page of characters at a time STA .vduTempStoreDE } BNE - if (we have not reached the end of the page) then branch (back to check the character) TXA A=X BNE .readCharLoop if (character number not zero) then branch (loop back) BEQ .finishUpFX135 ALWAYS branch (finish up)
§3. Read character from screen pixels.
Reads 8x8 cell of pixels from the screen. This will be compared against each of the character definitions to determine which character is on screen. This is for the cursor editing mode feature.
.readCharacterDefinitionMaskFromScreen = $d808 LDY #7 Y=7 .setupPatternLoop = $d80a STY .vduTempStoreDA .vduTempStoreDA=Y (loop counter) LDA #1 A=1 STA .vduTempStoreDB .vduTempStoreDB=A -- LDA .vduColourMaskLeft A=left colour mask STA .vduTempStoreDC store in .vduTempStoreDC LDA (.vduWriteCursorScreenAddressLow),Y get a byte from current text character EOR .vduBackgroundTextColour EOR with text background colour CLC clear carry - BIT .vduTempStoreDC and check bits of colour mask BEQ + if (result = 0) then branch (this becomes a zero bit in our mask) SEC set carry. This becomes a one bit in our mask + ROL .vduTempStoreDB Rotate left and add the carry in the low bit BCS + if (carry now set; bit 7 originally set) then branch (because we are done: the initial value of 1 has rotated through the 8 bits and into the carry) LSR .vduTempStoreDC shift mask right one place for the next pixel BCC - if (carry clear; nothing shifted off the left) then branch (loop back) TYA } ADC #7 } Y = Y + 8 (Carry is set, so adding } 7 + carry = 8) TAY } BCC -- if (no overflow from the add) then branch (loop back, move on to the next cell to read from) + LDY .vduTempStoreDA read modified values into Y and A LDA .vduTempStoreDB STA .vduWorkspaceA,Y store copy DEY and do it again BPL .setupPatternLoop until 8 bytes copied RTS
On Entry: A = VDU variable offset for the graphics coordinates to use. On Exit: A = current colour at the coordinate specified OR A = $FF if coordinate is out of bounds
.readPixel = $d839 PHA store A TAX X=A JSR .plotConvertExternalAbsoluteCoordinatesToPixels set up positional data PLA get back A TAX X=A JSR .checkPointXInBoundsAndSetScreenAddresses set a screen address after checking for window bounds BNE ++ if (out of bounds) then branch (exit with A=$FF) LDA (.vduScreenAddressOfGraphicsCursorCellLow),Y get row of current graphics cell - ASL A=A*2, Carry=bit 7 ROL .vduTempStoreDA .vduTempStoreDA=.vduTempStoreDA+2 +Carry, Carry=bit 7 of .vduTempStoreDA ASL .vduCurrentPlotByteMask byte mask=byte mask*2 + Carry PHP save flags BCS + if (carry set) then branch LSR .vduTempStoreDA restore .vduTempStoreDA with bit 7=0 + PLP pull flags BNE - if (Z set) then branch LDA .vduTempStoreDA A=.vduTempStoreDA AND number of colours in current MODE -1 AND .vduNumberOfLogicalColoursMinusOne RTS ++ LDA #$FF A=$FF - RTS
§5. Check the graphics point on the VDU queue is within the graphics window.
.checkParameterInBoundsAndSetScreenAddresses = $d85d LDX #.vdu25ParameterXLow - .vduVariablesStart X is the offset to the desired parameter for the point in graphics coordinates fall through...
§6. Check the given point is within the graphics window.
Takes the graphics coordinates pointed to by X, checks whether they are in the bounds of the graphics window, and if so sets up screen addresses. On Entry: X is the vdu variables offset to the graphics point to check On Exit: .vduScreenAddressOfGraphicsCursorCellLow/High is the screen address Y is the vertical offset within the character cell (0-7) Z is clear (i.e. BNE will branch) if coordinates are outside the graphics area
.checkPointXInBoundsAndSetScreenAddresses = $d85f JSR .checkPointXIsWithinGraphicsWindow BNE - if (point is not in graphics window) then branch (exit) .setScreenAddress = $d864 LDA .vduGraphicsWindowPixelsBottomLow,X read low byte of Y coordinate EOR #$FF Flip the coordinates to be from the top of the screen TAY Remember in Y AND #7 A = row within a character cell STA .vduGraphicsCursorVerticalOffsetInCell store row (0-7) TYA A=Y LSR } LSR } LSR } divide by 8 ASL Multiply by two to give the offset in the multiplication table TAY Y = offset into multiplication table LDA (.vduMultiplicationTableLow),Y Get high byte of offset from screen RAM start STA .vduTempStoreDA store it INY Y=Y+1 LDA (.vduMultiplicationTableLow),Y get low byte LDY .vduCurrentScreenMODEGroup check MODE group BEQ + if (zero, i.e. MODEs 0,1,2) then branch (skip this next bit) LSR .vduTempStoreDA } divide the offset by two ROR } + ADC .vduScreenTopLeftAddressLow add the screen top left address (low) STA .vduScreenAddressOfGraphicsCursorCellLow store it LDA .vduTempStoreDA get high byte ADC .vduScreenTopLeftAddressHigh add with carry the screen top left address (high) STA .vduScreenAddressOfGraphicsCursorCellHigh store it LDA .vduGraphicsWindowPixelsLeftHigh,X STA .vduTempStoreDA store x coordinate of point (high) LDA .vduGraphicsWindowPixelsLeftLow,X get x coordinate of point (low) PHA remember it AND .vduPixelsPerByteMinusOne get the horizontal X offset within the range of pixelsPerByte ADC .vduPixelsPerByteMinusOne add the pixels per byte minus one, which offsets to (one more than) the start of the MODE mask table for the current MODE TAY Y=A LDA .sixteenColourMODEMaskTable - 1,Y read byte mask STA .vduCurrentPlotByteMask store it PLA get back A LDY .vduPixelsPerByteMinusOne Y=number of pixels per byte minus one CPY #3 compare with 3 BEQ + if (MODE 1 or 5) then branch forward BCS ++ if (MODE 0 or 4) then branch forward ASL } ROL .vduTempStoreDA } (A,.vduTempStoreDA) *= 2 + ASL } ROL .vduTempStoreDA } (A,.vduTempStoreDA) *= 2 ++ AND #$F8 clear bits 0-2 CLC clear carry ADC .vduScreenAddressOfGraphicsCursorCellLow add A/.vduTempStoreDA to screen address STA .vduScreenAddressOfGraphicsCursorCellLow LDA .vduTempStoreDA ADC .vduScreenAddressOfGraphicsCursorCellHigh BPL + if (result +ve) then branch SEC set carry SBC .vduScreenSizeHighByte and subtract screen memory size making it wrap round + STA .vduScreenAddressOfGraphicsCursorCellHigh store it LDY .vduGraphicsCursorVerticalOffsetInCell get line in graphics cell containing current graphics .zeroAReturn = $d8cb LDA #0 A=0 to set Z flag (valid result) RTS
.splitIntoTwoCursors = $d8ce PHA Push A LDA #$A0 A=$A0 LDX .twosComplimentOfNumberOfBytesInVDUQueue X=number of items in VDU queue BNE .pullAndReturn2 if (not 0) then branch BIT .vduStatusByte check VDU status byte BNE .pullAndReturn2 if (either VDU is disabled, or plot to graphics cursor enabled) then branch (exit) BVS + if (cursor editing mode enabled) then branch LDA .vduLastCursorStartRegisterValue get CRTC register start setting AND #%10011111 clear bits 5 and 6 ORA #%01000000 set bit 6 to modify last cursor size setting JSR .setCursorOnOrOff change cursor format LDX #.vduTextCursorXPosition - .vduVariablesStart source = text cursor LDY #.vduTextInputCursorXCoordinate - .vduVariablesStart destination = text input cursor JSR .copyTwoBytesWithinVDUVariables set text input cursor from text output cursor JSR .restoreWriteCursor modify character at cursor position LDA #2 JSR .setVDUStatusByteFlags bit 1 of VDU status is set to bar scrolling + LDA #%10111111 JSR .clearVDUStatusByteFlags bit 6 of VDU status (separated cursors) is set to zero PLA Pull A AND #%01111111 clear high bit (7) JSR .vduChrEntryPoint call VDU routine LDA #%01000000 set bit six (separate cursors) JMP .setVDUStatusByteFlags set separated cursors and return
§8. readCharacterFromScreenAndCursorRight.
.readCharacterFromScreenAndCursorRight = $d905 LDA #%00100000 A=$20 BIT .vduStatusByte BVC .zeroAReturn if (bit 6 clear; not in cursor editing mode) then branch (exit) BNE .zeroAReturn if (bit 5 set; graphics cursor enabled) then branch (exit) JSR .osbyte135EntryPoint read a character from the screen BEQ .exit12 if (A = 0, i.e. failed to read) then branch (exit) PHA store A JSR .vdu9EntryPoint perform cursor right .pullAndReturn2 = $d916 PLA restore A .exit12 = $d917 RTS
When editing a line with two cursors, pressing return terminates the edit. This clears the VDU status flags and restores the text cursor to normal.
.terminateEdit = $d918 LDA #%10111101 } JSR .clearVDUStatusByteFlags } clear bits 2 and 6 of VDU status } (page scrolling; separated cursors) JSR .setTextCursor set text cursor (CRTC hardware) LDA #.charRETURN continue processing as a RETURN character RTS
§10. OSBYTE 132 - Read HIMEM (start of screen memory).
.osbyte132EntryPoint = $d923 LDX .vduCurrentScreenMODE get current screen MODE fall through...
§11. OSBYTE 133 - Read start of screen memory for given MODE.
.osbyte133EntryPoint = $d926 TXA X=MODE number AND #7 keep it in range 0-7 TAY Y=MODE number LDX .screenDisplayMemoryIndexTable,Y X = get screen RAM size index LDA .screenMemoryStartHigh,X A = high byte of start address LDX #0 X = 0 (low byte of result) BIT .systemAvailableRAM get available RAM BMI .returnTheScreenAddress if (32k available) then branch AND #$3F AND A with $3F to bring into memory range for a 16K BBC Micro CPY #4 BCS .returnTheScreenAddress if (MODE number >= 4) then branch (to return the value) TXA return zero (Model A can't display MODEs 0-3) .returnTheScreenAddress = $d93e TAY Y = high byte of screen address RTS