SPECTRUM 48k ROM ROUTINES ========================= Notes: * The notation $xxxx.nnn refers to ROM address $xxxx and page nnn in The Complete Spectrum ROM Disassembly by Ian Logan & Frank O'Hara. A '.' separator means the routine is in the 48K BASIC ROM on the 128k. This is ROM.1 on the +128k/+2 and ROM.3 on the +2A/+3. A 'E' separator means the routine is in the Editor ROM.0 on the 128k. A 'S' separator means the routine is in the Syntax ROM.1 on the 128k +2A/+3. * The notation {nnn} refers to footnote nnn. * The term "last value" refers to the top entry on the calculator stack; ie. the 5 bytes before (STKEND). If the result of a routine is not stored in the registers then it will be in "last value". * The term "stack the number" means "convert to 5-byte FP form and store as "last value" on the calculator stack". * For a thorough explanation of the use of the calculator stack refer to Toni Baker's excellent ZX Computing series "Machine Code Calculator": http://www.users.globalnet.co.uk/~jg27paw4/type-ins/zx-comp/mccalc.zip $0000. 1 START (RST $00) the start $0008. 1 ERROR_1 (RST $08) the error restart $0010. 1 PRINT_A_1 (RST $10) print A (BC,DE,HL preserved) $0028. 1 FP_CALC (RST $28) start the FP calculator (DEFB $38 stops) $0030. 1 BC_SPACES (RST $30) make BC bytes of space at the end of (WORKSP) $0038. 1 MASK_INT (RST $38) increment (FRAMES) and scan the keyboard $028e. 5 KEY_SCAN {001} the keyboard scanning subroutine $0145 S $03b5. 11 BEEPER {002} play note length DE (f*t), pitch HL (T/4) $03f8. 11 BEEP {002} play note length "last-1 value", pitch "last value" $04c2. 15 SA_BYTES save DE header(A=$00)/data(A=$ff) bytes from IX $0828 S $0556. 17 LD_BYTES {003} load DE header(A=$00)/data(A=$ff) bytes to IX $0884 S $09f4. 33 PRINT_OUT print A (BC,DE,HL not preserved) $0adc. 36 PO_STORE store row,col,address for current output file $0b03. 36 PO_FETCH set B,C=row,col, HL=address for current output file $0b24. 36 PO_ANY print A at B,C=row,col, HL=address $0bdb. 39 PO_ATTR set the attributes for the current character $0c0a. 39 PO_MSG print message entry A from table at DE $0c10. 39 PO_TOKENS print token entry A from table at DE $0c41. 40 PO_SEARCH {004} search for Ath entry in table at DE, returns in DE $0c55. 40 PO_SCR test for scroll on line B $0d4d. 43 TEMPS set temporary colours $0d6b. 44 CLS the CLS command routine $0d6e. 44 CLS_LOWER clear the lower screen $0daf. 44 CL_ALL clear the whole display area $21ef E $22c7 S $0dd9. 45 CL_SET set HL=address in current output file of row,col B,C $0e00. 45 CL_SCROLL scroll up B lines from bottom (1-23) $0e44. 46 CL_LINE clear bottom B lines of display file $0e88. 48 CL_ATTR set DE=atttribute address for display address HL $0e9b. 48 CL_ADDR set HL=display address for line B $0eac. 48 COPY the COPY command routine $21a7 E $20ce S $0ecd. 49 COPY_BUFF copy the printer buffer to the printer $0edf. 49 CLEAR_PRB clear the printer buffer $0ef4. 49 COPY_LINE copy pixel line B from address HL to the printer $0f2c. 50 EDITOR enter characters into the current EDIT/INPUT line $1097. 55 CLEAR_SP reclaim the work area addressed by HL $10a8. 55 KEY_INPUT input a character to A from channel "K" $111d. 56 ED_COPY copy the EDIT/INPUT line to the lower screen $1190. 57 SET_HL set HL/DE=first/last address of (E_LINE) or (WORKSP) $1195. 58 SET_DE set DE= last address of (E_LINE) or (WORKSP) $11b7. 59 NEW the NEW command routine $21aa E $2280 S $12a2. 61 MAIN_EXEC the main execution loop $155d. 64 MAIN_ADD add a new line to the BASIC program area $15d4. 65 WAIT_KEY wait for a character to A from channel (CURCHL) $15e6. 66 INPUT_AD input a character to A from channel (CURCHL) $1601. 66 CHAN_OPEN open a channel to stream A $1652. 67 ONE_SPACE make room for 1 byte at HL $1655. 67 MAKE_ROOM make room for BC bytes at HL $1664. 68 POINTERS update pointers by BC bytes made/reclaimed after HL $1695. 69 LINE_NO get a 16-bit line number from (HL) or (DE) $16b0. 69 SET_MIN reclaim E_LINE, WORKSP, STKBOT/END areas $16bf. 69 SET_WORK reclaim WORKSP, STKBOT/END areas $16c5. 70 SET_STK reclaim STKBOT/END area $16d4. 70 REC_EDIT {018} reclaim E_LINE area $16e5. 70 CLOSE CLOSE stream "last value" $1736. 71 OPEN OPEN channel "last value" for stream "last-1 value" $1793. 73 CAT_ETC the CAT/ERASE/FORMAT/MOVE commands routine $1be5 E CAT $1c0c E ERASE $0641 E FORMAT $1af0 E MOVE $17f5. 74 LLIST the LLIST command routine $1b71 E $17f9. 74 LIST the LIST command routine $1b75 E $1855. 75 OUT_LINE print a BASIC line from HL $196e. 79 LINE_ADDR set HL=line HL address, DE=previous line address $1980. 79 CP_LINES set Carry if line (HL) less than line BC $198b. 80 EACH_STMT find statement #D or token #E starting from HL $19b8. 80 NEXT_ONE {005} find next line in (PROG) or next variable in (VARS) $19e5. 81 RECLAIM_1 reclaim from HL to DE-1 $19e8. 81 RECLAIM_2 reclaim BC bytes from HL $19fb. 82 E_LINE_NO set BC=line number in E_LINE area (0 if none) $1a1b. 82 OUT_NUM_1 print number 0-9999 from BC, no padding $1a28. 82 OUT_NUM_2 print number 0-9999 from (HL), space padded $1b17. 86 LINE_SCAN {006} check syntax of EDIT (E_LINE) line $17af E $0fbf S $1b76. 88 STMT_RET return point after correct statement interpretation $1821 E $1031 S $1b8a. 88 LINE_RUN run the EDIT (E_LINE) line $1838 E $1048 S $1c1f. 91 CLASS_01 prepare LET,READ,INPUT $18f9 E $110c S $1c7a. 93 EXPT_2NUM Scanning CLASS_08, expect 2 numeric expressions $190a E $1c82. 93 EXPT_1NUM Scanning CLASS_06, expect 1 numeric expression $190e E $1c8c. 93 EXPT_EXP Scanning CLASS_0A, expect 1 string expression $1916 E $1c96. 93 PERMS set permanent colours from temporary colours $191a E $112d S $1cde. 94 FETCH_NUM {007} evaluate a numeric "next expression" at (CH_ADD) $1cf0. 95 IF the IF command routine $1967 E $1d86. 97 LOOK_PROG {008} search for token E starting at address HL $1ded. 99 READ the READ command routine $19ab E $1e27.100 DATA the DATA command routine $19eb E $1e85.101 TWO_PARAM {009} set A="last value" and BC="last-1 value" $1e94.101 FIND_INT1 set A ="last value"; quit with report B if too big $1e99.101 FIND_INT2 set BC="last value"; quit with report B if too big $1ea1.102 RUN the RUN command routine $1A02 E $1eac.102 CLEAR the CLEAR command routine $1204 S $1eed.103 GO_SUB the GO SUB command routine $1a53 E $1f05.103 TEST_ROOM check for sufficient free RAM; report 4 if not $1f1a.103 FREE_MEM {010} set BC=amount of memory in use $1f23.104 RETURN the RETURN command routine $1a6f E $1d03. 95 FOR the FOR command routine $1981 E $1f3a.104 PAUSE {011} pause "last value" 1/50ths seconds (or until key) $1f3d.104 PAUSE_1 {011} pause BC 1/50ths seconds (or until key) $1f54.104 BREAK_KEY reset Carry if BREAK pressed, set otherwise $162a S $1f60.105 DEF_FN the DEF FN command routine $1a8c E $1fc9.106 LPRINT the LPRINT command routine $2174 E $1bb2. 89 REM the REM command routine $1862 E $1fcd.106 PRINT the PRINT command routine $2178 E $203c.108 PR_STRING print BC characters from DE $2089.109 INPUT the INPUT command routine $218c E $2294.115 BORDER the BORDER command routine; BORDER="last value" $22aa.115 PIXEL_ADD set HL=address and A=bit# of pixel at B,C=y,x $22b0.115 PIXEL_ADD+6 same as PIXEL_ADD but avoids check on y coord $22cb.116 POINT return POINT "last val" row,col as "last val" 0/1 $22dc.116 PLOT PLOT "last value" $22e5.116 PLOT_SUB PLOT B,C=y,x $2307.117 STK_TO_BC {012} set B="last value", C="last-1 value" $2314.117 STK_TO_A {012} set A="last value", C=sign of "last value" $2320.117 CIRCLE at x="last-2 val", y="last-1 val ", r="last value" $21ae E $2286 S $2382.119 DRAW {013} draw a line from (COORDS) to offset "last value" $21be E $2296 S $2477.123 LINE_DRAW draw a line from (COORDS) to offset "last value" $24b7.124 DRAW_LINE same as LINE_DRAW but doesn't exit via TEMPS $24fb.127 SCANNING evaluate the "next expression" at (CH_ADD) $2535.128 S_SCRN$_S evaluate SCREEN$ at "last value" row,col $254f.128 S_SCRN_LP evaluate SCREEN$ at DE for B chars in set at HL $2580.129 S_ATTR_S evaluate ATTR at "last value" row,col $28b2.141 LOOK_VARS {014} find the variable addressed by (CH_ADD) $2ab1.150 STK_ST_0 stack AEDCB as string array/slice (A=0) $2ab2.150 STK_ST_$ stack AEDCB as any string $2ab6.150 STK_STORE stack AEDCB $2aee.151 DE,(DE+1) performs the action "LD DE,(DE+1)" $2aff.151 LET {015} assign a variable from LET, READ or INPUT $2b59.153 L_NUMERIC copy "last value" to HL-5 $2bf1.157 STK_FETCH fetch "last value" to AEDCB $2c02.156 DIM the DIM command routine $21d5 E $2c88.159 ALPHANUM set Carry if A is alphanumeric $2c8d.159 ALPHA set Carry if A is alphabetic $2c9b.160 DEC_TO_FP {016} stack the decimal number at (CH_ADD) $2d1b.161 NUMERIC reset Carry if A is a digit $30-$39, else set Carry $2d22.162 STK_DIGIT stack the number in A if it is a digit $2d28.162 STACK_A stack the number in A $2d2b.162 STACK_BC stack the number in BC $2d3b.162 INT_TO_FP stack the decimal integer at (CH_ADD) $2da2.166 FP_TO_BC fetch "last value" to BC $2dd5.167 FP_TO_A fetch "last value" to A $2de3.167 PRINT_FP print "last value" as a number $30a9.179 HL=HL*DE set HL=HL*DE $33b4.194 STACK_NUM stack the 5-byte FP form number addressed at HL $35de.207 VAL/VAL$ {017} evaluate VAL/VAL$ "last value", return "last value" $361f.208 STR$ evaluate STR$ "last value", return "last value" $028e. 5 KEY_SCAN {001} the keyboard scanning subroutine On returning from $028e KEY_SCAN the DE register and the Zero flag indicate which keys are being pressed. . The Zero flag is reset if pressing more than two keys, or pressing two keys and neither is a shift key; DE identifies two of the keys. . The Zero flag is set otherwise, and DE identifies the keys. . If pressing just the two shift keys then DE = $2718. . If pressing one shift key and one other key, then D identifies the shift key and E identifies the other key. . If pressing any one key, then D=$ff and E identifies the key. . If pressing no key, then DE=$ffff. The key codes returned by KEY_SCAN are shown below. KEY_SCAN key codes: hex, decimal, binary ? hh dd bbbbbbbb ? hh dd bbbbbbbb ? hh dd bbbbbbbb ? hh dd bbbbbbbb 1 24 36 00100011 Q 25 37 00100101 A 26 38 00100110 CS 27 39 00100111 2 1c 28 00011100 W 1d 29 00011101 S 1e 30 00011110 Z 1f 31 00011111 3 14 20 00010100 E 15 21 00010101 D 16 22 00010110 X 17 23 00010111 4 0c 12 00001100 R 0d 13 00001101 F 0e 14 00001110 C 0f 15 00001111 5 04 4 00000100 T 05 5 00000101 G 06 6 00000110 V 07 7 00000111 6 03 3 00000011 Y 02 2 00000010 H 01 1 00000001 B 00 0 00000000 7 0b 11 00001011 U 0a 10 00001010 J 09 9 00001001 N 08 8 00001000 8 13 19 00010011 I 12 18 00010010 K 11 17 00010001 M 10 16 00010000 9 1b 27 00011011 O 1a 26 00011010 L 19 25 00011001 SS 18 24 00011000 0 23 35 00100011 P 22 34 00100010 EN 21 33 00100001 SP 20 32 00100000 $03b5. 11 BEEPER {002} play note length DE (f*t) with pitch HL (T/4) This subroutine is entered with the DE register pair holding the value 'f*t', where a note of given frequency 'f' is to have a duration of 't' seconds, and the HL register pair holding a value equal to the number of T states in the "timing loop" divided by '4'; eg. for "middle C" to be produced for one second DE holds $0105 (INT(261.3*1)) and HL holds +066A (derived from 6689/4-30.125). $0556. 17 LD_BYTES {003} load DE header(A=$00)/data(A=$ff) bytes to IX Set Carry for LOAD, reset Carry for VERIFY. $0c41. 40 PO_SEARCH {004} search for Ath entry in table at DE, returns in DE Resets Carry if initial character is a letter, sets Carry otherwise. $19b8. 80 NEXT_ONE {005} find next line in (PROG) or next variable in (VARS) Searches from line/variable at HL and returns next address in HL. $1b17. 86 LINE_SCAN {006} check syntax of EDIT (E_LINE) line The parsing routine of the BASIC interpreter is entered at LINE-SCAN when syntax is being checked, and at LINE-RUN when a BASIC program of one or more statements is to be executed. Each statement is considered in turn and the system variable CH-ADD is used to point to each code of the statement as it occurs in the program area or the editing area. $1cde. 94 FETCH_NUM {007} evaluate a numeric "next expression" at (CH_ADD) Result is stored as "last value"; zero if no following expression. $1d86. 97 LOOK_PROG {008} search for token E starting at address HL Used to search for DATA, DEF FN and NEXT statements. $1e85.101 TWO_PARAM {009} set A="last value" and BC="last-1 value" The topmost parameter on the calculator stack must be compressible into a single register. It is two's complemented if it is negative. The second parameter must be compressible into a register pair. $1f1a.103 FREE_MEM {010} set BC=amount of memory in use The expression "65536-USR 7962" (7962=$1f1a) gives the amount of free RAM. $1f3a.104 PAUSE {011} pause "last value" 1/50ths seconds (or until key) $1f3d.104 PAUSE_1 {011} pause BC 1/50ths seconds (or until key) System variable FLAGS (23611) bit 5 set if a key has been pressed. $2307.117 STK_TO_BC {012} set B="last value", C="last-1 value" $2314.117 STK_TO_A {012} set A="last value", C=sign of "last value" Quit with report B if too big. $2382.119 DRAW {013} draw a line from (COORDS) to offset "last value" Gets a third (optional) angle parameter by a call to $1c82 EXPT_1NUM. $28b2.141 LOOK_VARS {014} find the variable addressed by (CH_ADD) Called whenever a search of the variables area or of the arguments of a DEF FN statement is required. Entered with (CH-ADD) pointing to the first letter of the name of the variable whose location is being sought. The exit parameters are: * (CH-ADD) points to the first location after the name of the variable as it occurs in the BASIC line. * When "variable not found": . Carry is set. . Zero is set only when the search was for an array variable. . HL points to the first letter of the name of the variable as it occurs in the BASIC line. * When "variable found": . Carry is reset. . Zero is set for both simple string variables and all array variables. . HL points to the letter of a short name, or the last character of a long name, of the existing entry that was found in the variables area. In all cases C bits 5 & 6 indicate the type of variable being handled. Bit 7 is the complement of the SYNTAX/RUN flag, but only when the subroutine is used in runtime will bits 0 to 4 hold the code of the variable's letter. In syntax time the return is always made with Carry reset. Zero is set for arrays and reset for all other variables. $2aff.151 LET {015} assign a variable from LET, READ or INPUT When the destination variable is a newly declared variable then DEST will point to the first letter of the variable's name as it occurs in the BASIC line. Bit 1 of FLAGX will be set. However if the destination variable exists already then bit 1 of FLAGX will be reset and DEST will point for a numeric variable to the location before the five bytes of the old number and for a string variable to the first location of the old string. Bit 0 of FLAGX is set if the destination variable is a complete simple string variable. $2c9b.160 DEC_TO_FP {016} stack the decimal number at (CH_ADD) Also handles BIN numbers. $35de.207 VAL/VAL$ {017} evaluate VAL/VAL$ "last value", return "last value" Set B=$1d for VAL, B=$18 for VAL$. $16d4. 70 REC_EDIT {018} reclaim E_LINE area Not used by the 48k ROM; probably left over from the ZX80/81. 48k ROM ERROR REPORTS ===================== Do a JP to the given address to return to BASIC with the indicated error report. 0 - OK $1bb0 1 - NEXT without FOR $1dd8 2 - Variable not found $0670, $1c2e 3 - Subscript wrong $2a20 4 - Out of memory $1f15 5 - Out of screen $0c86 6 - Number too big $31ad, $3703 7 - RETURN without GOSUB $1f36 8 - End of file $15e4 9 - STOP statement $1cee A - Invalid argument $34e7, $371a B - Integer out of range $046c, $1e9f, $24f9, $35dc C - Nonsense in BASIC $1c8a, $21ce D - BREAK - CONT repeats $0d00 E - Out of DATA $1e08 F - Invalid file name $0642, $1765 G - No room for line $1555 H - STOP in INPUT $21d4 I - FOR without NEXT $1d84 J - Invalid I/O device $15c4 K - Invalid colour $2244 L - BREAK into program $1b7b M - RAMTOP no good $1eda N - Statement lost $1bec O - Invalid stream $160e, $1725 P - FN without DEF $2812 Q - Parameter error $288b R - Tape loading error $0806