2CCF DEC RPT C integer part zero for "proper fractions" 2D3B INT TO FP returns integer part of FP number 2DD5 FP TO A checks integer part not more than 255d 2E01 PF LOOP number split into parts 2E6F PF MEDIUM store integer part 2ECF PF FRACTN store fractional part 2EEF PF FR EXX integer part after multiplying by ten is the digit to be stored 2F4A PF E SBRN fractional part handled separately 2F8B CA=10*A+C returns integer part of 10 * fraction 36AF int returns integer part as last value INTEGER TO FLOATING POINT subroutine see 2D3B INT TO FP INTEGER TRUNCATION TOWARDS ZERO SUBROUTINE see 3214 truncate interpreter (BASIC) see BASIC INTERPRETER, 1B8A LINE RUN, 24FB SCANNING interrupts The non-maskable interrupt mode zero of the Z80 chip isn't used in the Spectrum ROM. There is provision for its use by m/c programmers, but an unfortunate mistake in ROM at 0066 RESET makes it impossible to do anything with it except jump to 0000 START. The maskable interrupt mode 1 calls 0038 MASK INT fifty times a second to work the clock and to read the keyboard, except during BEEPs, COPY and cassette operation. The maskable interrupt mode 2 isn't used by ROM and is freely available to programmers. mode 1 disabled in: 0000 START 03B5 BEEPER 04D0 S FLAG 0556 LD BYTES 0EAC COPY 0ECD COPY BUFF 11B7 NEW mode 1 enabled in: 0048 KEY INT 03F6 BE END 053F SA/LD RET 0EDA COPY END 0EFD COPY L 1 1219 RAM SET Rems: Introduction keyboard scanned 50d times per second 0038 MASK INT clock and keyboard on every interrupt 02BF KEYBOARD called by every interrupt 1303 MAIN 4 must be enabled for HALT 1F3A PAUSE counts maskable interrupts 1F3D PAUSE 1 "halts" on each interrupt inter-statement marker see ":" (code 3A) at end of alphabet INT EXP1 subroutine 2ACC Reads a BASIC expression, which is the specification of an array dimension or subscript, see arrays. Checks it against the_limit_value supplied, the maximum value which can be accepted as the result: when a dimension is specified it is set at FF00, so effectively there is no limit except available memory, when a subscript is being read it is set to the dimension size. _Out_of_range_errors aren't reported, but recorded in an_error_register: if it remains zero, no error has occurred. When the subroutine is called from the 2A52 SLICING loop, it carries the error register forward from one call to another, using 2ACD INT EXP2 as entry point so as not to reset it, and reports an error only after both parameters have been collected.The purpose of this isn't at all clear. Input parameters: HL holds the limit value - the BASIC pointer in 5C5D CH ADD is on the first character of an expression specifying a dimension or subscript. Action: make an error register set to zero. _2ACD_INT_EXP2: call 1C82 EXPT 1NUM to evaluate the expression and put it on the stack - if checking syntax jump on to I RESTORE - (run time) call 1E99 FIND INT2 to get the value of theexpression; FIND INT2 will report an error if the expression is negative or more than FFFFh/65535d - if it is zero jump on with carry to I CARRY - check it against the limit value. _2AE8_I_CARRY (the carry is set if there has been a "zero" or "over the limit" error): if carry is set, SBC 00 decrements the error register. _2AEB_I_RESTORE: clear the machine stack and return. Exit: RET, from 2AEB I RESTORE. Output parameters: BC holds the value of the subscript ordimension - A is zero if the value is within the range specified, otherwise FF or less - DE and HL are unchanged. Called from: 29FB SV MULT 2C2E D NO LOOP Rems: 2A52 SL LINE 2A81 SL SECOND save up the error register till slicing completed 2A94 SL DEFINE test error register after slicing done 2AE8 I CARRY INT EXP2 subroutine 2ACD (2ACC INT EXP1) Called from: 2A52 SLICING 2A81 SL SECOND INT FETCH subroutine 2D7F Copies a small integer FP number X into a register, and subtracts it from 10000h/65536d to make an absolute value if it is marked as negative - which is indicated by a flag on return. X isn't necessarily on the calculator stack, though often it is. There is no check that X is in small integer format; if it isn't, the number returned will be rubbish. The mechanism for producing the value of negative X works like this: - XOR the lo byte of X with the sign byte FF; the result is FF minus X lo, with no carry - subtract the sign byte; this_increments the result by one and sets the carry flag, except only if the original lo bytewas zero. The result is now from zero: zero without carry from anything else: 100h - lo with carry - add the sign byte FF to X hi with any carry from the lobyte operations; this has no effect unless the lo byte was zero,when it decrements X hi to X hi - 1 - XOR this result with the sign byte FF; it makes if X lo was zero: 100h - X hi if X lo was anything else: FF - X hi The overall result is: X zero: both bytes remain zero X lo zero: X lo unchanged, X hi becomes 100h - X hi otherwise: X lo becomes 100h - X lo, X hi becomes FF - X hi which are the correct values required for the absolute value. None of these operations have any effect if the number is positive, since then its sign byte is zero. Cf 2DA2 FP TO BC and 1E99 FIND INT2, which - can only get numbers from the calculator stack, and delete them from the stack in doing so; INT FETCH doesn't - can read numbers which aren't integers, or not in smallinteger format, and round them to integers if necessary - signal negative numbers and out-of-range numbers; by flags in the case of FP TO BC, by error reports in the case of FIND INT2 - don't negate negative numbers to their absolute value. Input parameters: HL holds the address of the first byte of the number; the exponent byte, always zero for numbers in small integer format. Action: read the sign from the second byte; 00 for positive, FF for negative - read the value from the third byte; X lo - XOR with the sign byte and subtract the sign byte - read the fourth byte; X hi - add the sign byte with carry - XOR the result with the sign byte. Exit: RET. Output parameters: DE holds the value required - C holds the sign byte, 00 or FF - HL addresses the fourth byte of the FP number - B unchanged - always returns with NC. Called from: 2DAD FP DELETE 2E01 PF LOOP 30CA multiply (twice) 3297 re-stack 3483 INT CASE Rems: 2D8E INT STORE uses same mechanism to negate INT STORE subroutine 2D8E Puts the number X from a register holding ABS X into "small integer" FP format, positive or negative according to a flag. X is usually but not necessarily loaded on to the calculator stack. If X is flagged as negative, it is subtracted from 10000h/65536d before being loaded; the mechanism employed is thesame as that described above under 2D7F INT FETCH. The entry point 2D8C P INT STO can be used without the flag if X can be assumed positive; never used from the ROM. Cf: 2D2B STACK BC, which always puts X on the calculator stack, and always as a positive number. 2AB6 STK STORE, which also loads a number to any address HL, but it must already be in FP format in AEDCB, not necessarily a small integer. 33C0 MOVE FP, which merely moves a FP number from one location to another. 22B4 STACK NUM the same, but the destination is alwaysthe calculator stack. Input parameters: DE holds the absolute value of X - HL the address of the first of the five bytes intendedto hold it - C holds zero if X is positive, FF if negative. Action: put zero in byte 1; small integer - put C in byte 2; sign byte - XOR the lo byte with the sign flag; for this and the next few operations see the explanation of INT FETCH above - subtract the sign flag from the result - put this in byte 3 - add the sign flag to the hi byte with the carry - XOR the result with the sign flag - put this in byte 4 - put zero in byte 5. Exit: RET. Output parameters: BC, DE and HL unchanged - X in the five bytes starting at HL. Called from: 30EA MULT RSLT 3267 T STORE 3483 INT CASE 3492 sgn INT TO FP subroutine 2D3B Reads a decimal integer from BASIC and puts it on the calculator stack in FP form. Input parameters: A holds the character code of the firstdigit, already read from the address at the BASIC pointer in 5C5D CH ADD. Action: use the calculator to put zero on the stack for an accumulator. _24D0_NXT_DGT_2: call 2D22 STK DIGIT to put the value of the digit on the calculator stack - if it returns with carry return; no more digits - (digit read) multiply the accumulator by ten and add the new digit - move on the BASIC pointer - loop back to NXT DGT 2. Exit: RET from NXT DGT 2 when all digits have been read. Output parameters: the number is added to the calculator stack as last value - the C flag is set - the BASIC pointer in 5C5D CH ADD is on the code after the number. Called from: 19FB E LINE NO 2CBB NOT BIN 2CFF ST E PART IN VAR 1 213A (2089 INPUT) There are no direct calls of or jumps to this label, butit sets itself as error address for variable assignments in the INPUT command routine; any errors in variable assignment merely recopy the input BASIC to the lower screen with a flashing errorcursor. The error address is reset in 2174 IN VAR 5. 2148 IN VAR 2 return to if not OK 2174 IN VAR 5 address dropped IN VAR 2 2148 (2089 INPUT) Jumps from: 213A IN VAR 1 IN VAR 3 215E (2089 INPUT) Jumps from: 2129 IN PR 3 IN VAR 4 2161 (2089 INPUT) Jumps from: 2148 IN VAR 2 IN VAR 5 2174 (2089 INPUT) Misprinted IN VARS 5. Jumps from: 2161 IN VAR 4 IN VAR 6 219B (2089 INPUT) Misprinted IN VARS 6. Jumps from: 2174 IN VAR 5 INVERSE key (DD) see also colours, KEYBOARD SCANNING, extended mode key table (c) The M key in E mode with either shift produces the tokenINVERSE. INVERSE can be used either as a BASIC command or as a print control item within a PRINT etc statement. In either case it must be followed by a parameter: one for "on", which reverses the PAPER and INK colours inany new printing position on the screen zero for "off", which restores the position to normal. INVERSE 8 isn't accepted. As a command, it is read by 1B29 STMT L 1 referring through the syntax offset table 1A48 to the syntax parameter table 1A7A. 1AEF P INVERSE causes a jump to 1C96 CLASS 07 (PERMS), the executive routine for all the colour item commands INK to OVER. As a print control item, execution is from within the PRINT executive routine 1FCD PRINT; each new expression following the PRINT command is checked by a call to 1FFC PR ITEM1 from 1FE5 PRINT 3. If it is INVERSE, this in turn calls 21F2 CO TEMP 3, from 2024 PR ITEM 3; here the token code DD is converted to the "embedded" control code 14h, which is then sentthrough the output routine followed by the parameter. The way this works when printing on screen can be seen at 09F4 PRINT OUT; indexing with 14h for INVERSE into the control character table at 0A11 produces an indirect jump to 0A7A (0A1F + 5B) PO 1 OPER. See the index description of this subroutine for the rather tricky way in which it collects the parameter and sends execution to 0A87 PO CONT, which finally executes the INVERSE command. inverse character (pixel), inverse status Terms used only in notes on the SCREEN$ function: in comparing the character on screen with the character set, it still counts as a match even if the character is printed in INVERSE VIDEO. 254F S SCRN LP test with mask 00 and mask FF 255A S SC MTCH save mask to match seven remaining bytes INVERSE control code (14h) and OVER control code (15h) On the original Spectrum, the INVERSE control codes wereproduced as follows: "INVERSE on" - 4 key with caps shift "INVERSE off" - 3 key with caps shift