Rems: 0AC3 PO FILL no leading space after TAB command 0B6A PO CHAR 2 no leading space if space just printed 0C44 PO STEP checks inverted characters in message table 1865 OUT LINE1 prints line number with leading spaces 187D OUT LINE2 zero flag: leading space allowed 192B OUT SP 1 check for leading spaces 1A1B OUT NUM 1 no leading spaces 1A2B OUT NUM 2 print with leading spaces P OPEN 1AFC see 1A7A syntax offset table PO QUEST 0A69 (09F4 PRINT OUT) Jumps from: 09F4 PRINT OUT (twice) PO RIGHT subroutine 0A3D See 09F4 PRINT OUT. Called from: 09F4 PRINT OUT through 0A11 control character table with code 09. ports The function of the input from and output to the ports is set by the hardware, and cannot be changed even by m/c programs; so although any port may be input or output from BASICor machine code, the use of such instructions is limited. See page 159-60 of the old Spectrum handbook, and page 138-139 of the Plus 2 handbook. For some reason the index of the latter book gives page 197 as the reference for "ports": this isn't helpful. See also the ZX printer handbook page 4. Port addresses are 2-byte integers, but usually only bits zero to 4 of the lo byte are significant, and only one of these should be set to zero for a meaningful result; which meansthere are only five ports for most purposes. The keyboard uses port FE, but also uses the hi byte to multiply the number of ports used. More detail is given below, but the uses of the five main ports may be summarized as follows. _Zero_in_bit_zero: port 11111110b/FEh/254d - input from keyboard - input from EAR socket - output to loudspeaker - output to border - input/output of Microdrives etc, see page 139 of the Plus 2 handbook _Zero_in_bit_one: port 11111101b/FDh/253d - used by the 3-channel sound chip, RS232, keypad and MIDI of the Plus, see pages 139 and 166 of the Plus 2 handbook - 7FFD is used for the extra memory of the Plus, see pages 139 and 147 of the Plus 2 handbook _Zero_in_bit_2: port 11111011b/FBh/251d - input from ZX printer - output to ZX printer _Zero_in_bit_3: port 11110111b/F7h/247d - used by Microdrives etc, see page 139 of the Plus 2 handbook _Zero_in_bit_4: port 11101111b/EFh/239d - used by Microdrives etc, see page 139 of the Plus 2 handbook Keyboard ports In the case of the keyboard, the hi byte of the port address is also significant; see the tables in NB 1 under KEYBOARD SCANNING. The byte read in from port FE indicates whichkey, if any, in the half-row is being pressed. The BREAK key, SPACE with CAPS SHIFT, is considered pressed when there is input with zero in bit zero from FEFE (CAPS SHIFT) and also zero in bit zero from 7FFE (SPACE). See 1F54 BREAK KEY. Inputs: 0296 KEY LINE read FEFE, FDFE, FBFE, F7FE, EFFE, DFFE, BFFE, 7FFE in succession 053F SA/LD RET and 05ED LD SAMPLE check BREAK/SPACE key - bit 0 of 7FFE only 1F54 BREAK KEY check BREAK key, bit 0 of 7FFE and FEFE Rems: 028E KEY SCAN successive port addresses in BC EAR/MIC port: EAR input, MIC, loudspeaker and border colour output All port FE: the same port outputs to the MIC socket, the loudspeaker and the border, so a single OUT eg in the SAVE routines controls all three. Inputs: - bit 6 is zero if there is an incoming pulse from the EAR socket _0556_LD_BYTES read EAR state in bit 6, move it to bit 5 and save with 010 RED in bits 2 -> zero _05ED_LD_SAMPLE read EAR state in bit 6, move it to bit 5 and check for edge Output: - bit 4 set sends a pulse to the loudspeaker - bit 3 zero turns on the MIC socket - bits 2, 1 and zero set the border colour 03D6 BE H&L LP bit 4 on turns speaker on, zero turns it off, border colour unchanged 04D8 SA LEADER, 04EA SA SYNC 1 and 04F2 SA SYNC 2 alternate 00000010b/00001101b turns MIC on & border RED, MIC off & border CYAN 051C SA OUT alternate 00000001b/00001110b turns MIC on & border YELLOW, MIC off & border BLUE 053F SA/LD RET bits 2, 1 and 0 restore border colour 0556 LD BYTES 00001111b for MIC off and border WHITE 05ED LD/SAMPLE set bit 3 to turn off MIC and change border colour 2294 BORDER bits 2, 1 and 0 set new border colour Rems: 03B5 BEEPER 00001000b turns off MIC 04D0 SA FLAG 00000010b signals MIC on and RED 04F2 SA SYNC 2 00001110 signals MIC off and YELLOW 0507 SA START 00000001b signals MIC on and BLUE 0511 SA BIT 2 00001110 signals MIC off and YELLOW ZX printer ports Port FB inputs and outputs to the ZX printer: see page 160 of the old Spectrum handbook and the ZX printer's own handbook. The printer port FB isn't mentioned in the Plus 2 handbook, nor is the ZX printer, but port FB is certainly used for printer output in the older Spectrum Plus, see page 65 underOUT in the Spectrum Plus handbook, and the ZX printer can be used with it in 48K mode, see the Introductory handbook to the Spectrum Plus. The_stylus is the "pen" which marks the paper; actually there are two of them in the ZX printer. The_encoder is a synchronizing device which takes 256d bits, one pixel line, fromthe printer buffer and feeds them to the stylus at a controlled rate. Input: - bit 7: set when the stylus is in contact with the paper, ie ready, and stays set till an output received - bit 6: set if printer connected, otherwise zero - bit 0: set when the encoder is ready, and stays set till an output received 0F0C COPY L 2 check bits 6 (on if printer connected) and 7 (on if stylus ready) 0F1E COPY L 5 check bit 0 (on if encoder ready) Output: - bit 7: one produces a dot from the stylus - bit 2: zero starts the motor one stops the motor - bit 1: one slows the motor, unless bit 2 is also one 0EDA COPY END stop the motor with 00000100b 0EF4 COPY LINE slow motor with 00000010b 0EFD COPY L 1 stop the motor with 00000100b 0F1E COPY L 5 send bit to printer, one if bit 7 set PO SAVE subroutine 0C3B see also scrolling Used to print a single character_recursively, ie from within the 0010 PRINT A 1 sequence, eg when expanding token codes. The PRINT A 1 sequence operates with the alternate register set from 15F2 PRINT A 2, switching them back at the endof 15F7 CALL SUB, so as to save the main registers: if it was simply called from within itself they would be switched back andthe main registers would be corrupted. PO SAVE corrects this. Input parameters: A holds the character code - the alternate registers are in use. Action: stack DE' - exchange the main registers - call 0010 PRINT A 1 - restore the registers and DE'. Exit: RET. Output parameters: main registers and DE' are preserved. Called from: 0AD0 PO SPACE 0C14 PO TABLE 0C22 PO EACH PO SCR subroutine 0C55 Checks whether the next print to screen will require scrolling; if so scrolls it. In automatic listing, which scrolls the upper screen without prompts till the line marked as current is on screen, the whole screen is scrolled up one line; but if the current line indicator in 5C67 BREG is zero, indicating the current lineis already on screen, a complete return from the 1795 AUTO LIST routine is made. In ordinary listing of the upper screen, again the wholescreen is scrolled up one line; but if the scroll counter in 5C8C SCR CT indicates that a full screen has been scrolled, the "scroll?" message is printed and scrolling doesn't proceed till a key is pressed. See also TV FLAG bit 4. In scrolling the lower screen, if there is room between upper and lower screens only the lower screen is scrolled, otherwise both are scrolled: scrolling is usually only by one line, but in the case of an INPUT ... AT input the lower screen may need to be scrolled several times. Input parameters: the alternate registers are in use; this subroutine is part of the 0010 PRINT A 1 output sequence, all executed in the alternate registers - BC' holds the current print position, see DISPLAY AREA; B' is the line number, from 18h/24d at the top of either upper or lower screen downwards. C' isn't used. Action: if bit 1 of FLAGS is set return immediately; the ZX printer flag. If it is set output is being made to the printer - stack a return address 0DD9 CL SET; all RETs will be to there - if bit zero of TV FLAG is set jump on to PO SCR 4; the"lower screen flag". If it is set printing is in the lower screen [the notes say INPUT ... AT, but the jump will be made for any editing or input if a line end is reached] - (scrolling the upper screen; it can be assumed that the lower screen is blank) check the new print position line number against the number in 5C6B DF SZ; this is the current number of lines in the lower screen, so also the line number of the top blank line in the lower screen - if the line number is_less than 5C6B DF SZ report "Outof screen"; something has gone wrong, the top display is overlapping the bottom - if it is_more than 5C6B DF SZ return; there are still spare lines in the upper screen - (scrolling is needed) if bit 4 of TV FLAG is zero jumpon to PO SCR 2; the "auto listing" flag, ordinary listing - (auto listing) decrement the current line indicator from 5C67 BREG - if it was 01 jump on to PO SCR 3; the current line isn't yet on screen, scrolling is necessary - (5C67 BREG holds zero, the current line is on screen already) call 1601 CHAN OPEN with stream zero to open the keyboard channel - put the address from 5C3F LIST SP in the stack pointer - zero bit 4 of TV FLAG; signalling ordinary listing - return; the return address at 5C3F LIST SP to which the stack pointer now points was set as the return address for the whole routine in 1795 AUTO LIST, so the LIST command routineis now terminated. _0C88_PO_SCR_2 (ordinary listing): decrement the scroll counter in 5C8C SCR CT - if it doesn't reach zero jump on to PO SCR 3; more lines can be scrolled before prompting "scroll?" - (a whole screen has been scrolled) set 5C8C SCR CT back to 18h/24d less the current line; this is the number of lines in the upper screen - stack the attributes from 5C8F ATTR T/MASK T and P FLAG; the permanent ones will be copied to the temporary ones for the time being - call 0601 CHAN OPEN with stream minus 3 to open the keyboard channel; output to the lower screen - call 0C0A PO MSG to print message number zero from 0CF8, the "scroll?" message - set bit 5 of TV FLAG; "clear the lower screen after this keystroke" - set bit 3 of FLAGS; "L mode". K mode would interpret eg "N" as NEXT - zero bit 5 of FLAGS; "waiting for a key" - switch back into the main registers, to avoid a doubleEXX into the main registers [however there seems no need to stack DE' as suggested by the notes: this was done in 0C3B PO SAVE where DE' carries an important pointer, but here DE' is only pointing to the last byte of "scroll?"] - call 15D4 WAIT KEY; it waits till a key is pressed, then clears the lower screen and returns with the final key codein A - switch the registers back to the alternates - if the key code is 20h BREAK/SPACE report "BREAK - CONT repeats" - if it is E2 STOP the same - OR the code with 00100000b/20h, setting bit 5 to make it lower-case - if it was upper or lower case "N" make the report - (no BREAK; continue scrolling) call 1601 CHAN OPEN again with stream minus 2 to open the upper screen output channel - recover ATTR T/MASK T and P FLAG from the stack and restore the temporary attributes. _0CD2_PO_SCR_3 (scroll the screen by one line, automatic or ordinary listing): call 0DFE CL SC ALL to scroll the whole screen by one line; a blank line is added at the bottom of the lower screen - make a new print position at the left margin, always column 21h, of the line one above 5C6B DF SZ; DF SZ marked the top of the lower screen before the scroll, so this position is on the blank line at the top of the lower screen - stack this print position - call 0E9B CL ADDR to find the address in the display area of the print position; this blank line used to belong to the lower screen, and its attributes have been scrolled up, so they must be changed to upper screen attributes - convert the display address to the corresponding attribute address; the seven instructions after the subroutine call, which do this conversion, duplicate exactly the first seven of 0BDB PO ATTR - a very unusual duplication in the ROM - and are explained under PO ATTR - make the address 5AE0; this is the address of the attributes of the first position in the bottom screen line, which is in the lower screen but was given upper-screen attributes when it was cleared, by the last part of 0E4D CL LINE2, because TV FLAG bit zero was zero for "upper screen" - get the upper screen attributes from the bottom line and the lower screen attributes from the print position address just found - set a counter to 20h for the number of characters in the line. _0CF0_PO_SCR_3A: step along the lines putting the attributes from the bottom line in the new upper screen line andvice versa - recover the position values and return. _0D02_PO_SCR_4 (scrolling the lower screen): if the printposition line number is zero or one report "Out of screen"; remember it is counted from 18h/24d at the top of the lower screen. The lower screen is never allowed to grow beyond 17h/23dlines, leaving one for the upper screen - add the line number to the number in 5C6B DF SZ and subtract 19h - if there is no carry, return; 5C6B DF SZ records the number of lines available in the lower screen, and the number oflines being used down to the present line number (L, say) is 19h/25d - L. If this is no bigger than 5C6B DF SZ (D, say), there is no need to scroll. So add the line number to 5C6B DF SZand subtract 19h: D + L - 19h = D - (19h - L)