zx81-rom

ZX81 rom source mirror
git clone http://frotz.net/git/zx81-rom.git
Log | Files | Refs

zx81dual.html (386998B)


      1 ; ===========================================================
      2 ; An Assembly Listing of the Operating System of the ZX81 ROM
      3 ; ===========================================================
      4 ------------------------------------------------------------------------
      5 
      6 ; Last updated: 13-DEC-2004
      7 ; 2011		Updated to remove -, +, /, *, &, 
      8 ;		characters from labels (which confuse assemblers)
      9 ;
     10 ; 2011		Updated for conditional assembly of ORIGINAL or "Shoulders of Giants" ROM
     11 ;
     12 ; 2014-08-01	Updated to add CHARS_PER_LINE_WINDOW  which is normally 32.
     13 ;
     14 ;	The ideal pixel rates for square pixels on a PAL system are
     15 ;	14.75  MHz (interlaced) and
     16 ;	 7.375 MHz (non-interlaced, which the ZX80/ZX81 are).
     17 ;	These are not commonly available but fortunately one can buy
     18 ;	baud-rate generator frequencies such as
     19 ;	14.7456 and 7.3728 MHz that are only 0.03% low
     20 ;	which is more than close enough.
     21 ;
     22 ;	ZX video normally has 6.5 MHz pixel rate,
     23 ;	so 32 characters take 256 pixels in 39.4 microseconds.
     24 ;	A 7.3728 MHz clock and 40 characters produces 
     25 ;	320 pixels in 43.4 microseconds.
     26 ;
     27 ;	ZX80 video generation is software defined so it is
     28 ;	easy to get square pixels simply by subtracting 8 from the bytes
     29 ;	at hex addresses 287, 2AA and 2B8.
     30 ;	The video will appear to the left of the screen but
     31 ;	the characters will be square and a diagonal graphic line
     32 ;	will be at 45 degrees.
     33 ;
     34 ;	ZX81 video generation in fast mode exactly the same as the ZX80.
     35 ;
     36 ;	ZX81 video generation in slow mode is problematic, in that
     37 ;	the NMI generator expects a 3.25 MHz CPU clock 
     38 ;	(3.25MHz / 208 = 15.625 kHz = 64 microsecond line period)
     39 ;	It is inside the ULA where it cannot be modified.
     40 ;
     41 ;	Simply fitting a 7.3728 MHz crystal would reduce the line period to
     42 ;	57.3 microseconds. Slow mode would require the CPU clock to be
     43 ;	divided by 236.
     44 ;
     45 ;	Square pixels on NTSC requires 11+3/11 = 11.272... MHz (interlaced)
     46 ;	or 5.63.. non-interlaced which is slower than the original 6.5 MHz.
     47 ;	The NTSC line period is still 64 microseconds, so 256 pixels
     48 ;	stretch over 45 microseconds, and 320 pixels over 56 microseconds.
     49 ;	Thus it is possible to get square pixels on an NTSC display,
     50 ;	it is not possible to get 40 column text as well.
     51 ;	That would require the PAL clock, but pixels would not be square.
     52 ;
     53 ;	The ZX printer is fixed in hardware.
     54 ;	It will not work in 40-column mode.
     55 ;
     56 ;
     57 ;
     58 ;	PIXEL_CLOCK	equ	7372500
     59 ;
     60 ; on-line assembler complains about the line above
     61 ;
     62 ; CHARS_PER_LINE_WINDOW always 32 for 6.5   MHz pixel rate
     63 ;                       always 40 for 7.375 MHz PAL square pixel rate
     64 ;
     65 CHARS_PER_LINE_WINDOW	equ	40	; 32	originally
     66 ;
     67 ; CHARS_PER_LINE always 32 for 6.5 MHz pixel rate
     68 ;                but 32 or 40 if using PAL square pixel rate
     69 ;
     70 CHARS_HORIZONTAL	equ	40	; 32	originally
     71 CHARS_VERTICAL		equ	24
     72 ;
     73 ; 2014-08-01
     74 ; Largely working but some bugs remain.
     75 ; Working:
     76 ; You can type text and it takes 40 characters before new line.
     77 ; 40 characters are nicely centred in the screen.
     78 ; PLOT X,Y accepts X from 0 to 79.
     79 ; Faulty:
     80 ; System crashing in an authentic ZX81 fashion,
     81 ; I don't know if this is due to software bugs
     82 ; or socket joint disturbance from key presses.
     83 ; 
     84 ;
     85 ; 2018-01-09 add org
     86 ; Assembles using on-line assembler "zasm" at:
     87 ;
     88 ; http://k1.spdns.de/cgi-bin/zasm.cgi
     89 ;
     90 	org	0
     91 	
     92 FALSE		equ	0
     93 
     94 ORIGINAL	equ	0
     95 NOT_BODGED	equ	1
     96 
     97 ; 2018-02-09 CHARS_HORIZONTAL placed in SCROLL routine.
     98 ;		Thanks to Adam Klotblixt for testing code and spotting this bug.
     99 ;	Also added to some G007 routines.
    100 ;
    101 
    102 ------------------------------------------------------------------------
    103 
    104 ;
    105 ; Work in progress.
    106 ; This file will cross-assemble an original version of the "Improved"
    107 ; ZX81 ROM.
    108 ; The file can be modified to change the behaviour of the ROM
    109 ; when used in emulators although there is no spare space available.
    110 ;
    111 ; The documentation is incomplete and if you can find a copy
    112 ; of "The Complete Spectrum ROM Disassembly" then many routines
    113 ; such as POINTERS and most of the mathematical routines are
    114 ; similar and often identical.
    115 ;
    116 ; I've used the labels from the above book in this file and also
    117 ; some from the more elusive Complete ZX81 ROM Disassembly
    118 ; by the same publishers, Melbourne House.
    119 
    120 #if 0
    121 ; zasm does not understand these:
    122 #define DEFB .BYTE	; TASM cross-assembler definitions
    123 #define DEFW .WORD
    124 #define EQU	.EQU
    125 #endif
    126 
    127 ; define stuff sensibly:
    128 ;
    129 ; I/O locations:
    130 ;
    131 IO_PORT_TAPE		equ	$FF	; write
    132 IO_PORT_SCREEN		equ	$FF	; write
    133 
    134 IO_PORT_KEYBOARD_RD	equ	$FE	; A0 low
    135 IO_PORT_NMI_GEN_ON	equ	$FE	; A0 low
    136 IO_PORT_NMI_GEN_OFF	equ	$FD	; A1 low
    137 IO_PORT_PRINTER		equ	$FB	; A2 low
    138 ------------------------------------------------------------------------
    139 
    140 ;
    141 ; System variables:
    142 ;
    143 RAMBASE		equ	$4000
    144 ERR_NR		equ	$4000		; The report code. Incremented before printing.
    145 FLAGS		equ	$4001		; Bit 0: Suppression of leading space.
    146 					; Bit 1: Control Flag for the printer.
    147 					; Bit 2: Selects K or F mode; or, F or G
    148 					; Bit 6: FP no. or string parameters.
    149 					; Bit 7: Reset during syntax checking."
    150 ERR_SP		equ	$4002		; Pointer to the GOSUB stack.
    151 RAMTOP		equ	$4004		; The top of available RAM, or as specified.
    152 MODE		equ	$4006		; Holds the code for K or F
    153 PPC		equ	$4007		; Line number of the current statement.
    154 PPC_hi		equ	PPC+1
    155 VERSN		equ	$4009		; Marks the start of the RAM that is saved.
    156 E_PPC		equ	$400A		; The BASIC line with the cursor
    157 D_FILE		equ	$400C		; Pointer to Display file
    158 DF_CC		equ	$400E		; Address for PRINT AT position
    159 VARS		equ	$4010		; Pointer to variable area
    160 DEST		equ	$4012		; Address of current variable in program area
    161 E_LINE		equ	$4014		; Pointer to workspace
    162 E_LINE_hi	equ	E_LINE+1
    163 CH_ADD		equ	$4016		; Pointer for scanning a line, in program or workspace
    164 X_PTR		equ	$4018		; Pointer to syntax error.
    165 X_PTR_lo	equ	X_PTR
    166 X_PTR_hi	equ	X_PTR+1
    167 STKBOT		equ	$401A		; Pointer to calculator stack bottom.
    168 STKEND		equ	$401C		; Pointer to calculator stack end.
    169 BERG		equ	$401E		; Used for many different counting purposes
    170 MEM		equ	$401F		; Pointer to base of table of fp. nos, either in calc. stack or variable area.
    171 ;					; Unused by ZX BASIC. Or FLAG Y for G007
    172 DF_SZ		equ	$4022		; Number of lines in the lower screen
    173 S_TOP		equ	$4023		; Current line number of automatic listing
    174 LAST_K		equ	$4025		; Last Key pressed
    175 DEBOUNCE_VAR	equ	$4027		; The de-bounce status
    176 MARGIN		equ	$4028		; Adjusts for differing TV standards
    177 NXTLIN		equ	$4029		; Next BASIC line to be interpreted
    178 OLDPPC		equ	$402B		; Last line number, in case needed.
    179 FLAGX		equ	$402D		; Bit 0: Reset indicates an arrayed variable
    180 					; Bit 1: Reset indicates a given variable exists
    181 					; Bit 5: Set during INPUT mode
    182 					; Bit 7: Set when INPUT is to be numeric
    183 STRLEN		equ	$402E		; Length of a string, or a BASIC line
    184 STRLEN_lo	equ	STRLEN		; 
    185 T_ADDR		equ	$4030		; Pointer to parameter table. & distinguishes between PLOT & UNPLOT
    186 SEED		equ	$4032		; For RANDOM function
    187 FRAMES		equ	$4034		; Frame counter
    188 FRAMES_hi	equ	FRAMES+1	; 
    189 COORDS		equ	$4036		; X & Y for PLOT
    190 COORDS_x	equ	COORDS		; 
    191 PR_CC		equ	$4038		; Print buffer counter
    192 S_POSN		equ	$4039		; Line & Column for PRINT AT
    193 S_POSN_x	equ	$4039		; 
    194 S_POSN_y	equ	$403A		; 
    195 CDFLAG		equ	$403B		; Bit 6 = the true fast/slow flag
    196 					; Bit 7 = copy of the fast/slow flag. RESET when FAST needed
    197 PRBUFF		equ	$403C		; Printer buffer
    198 PRBUFF_END	equ	$405C		; 
    199 MEM_0_1st	equ	$405D		; room for 5 floating point numbers (meme_0 to mem_ 5???)
    200 ;			$407B		; unused. Or RESTART to G007
    201 ;			$407D		; The BASIC program starts here
    202 ;		equ	$40
    203 ;		equ	$40
    204 ;		equ	$40
    205 ; First byte after system variables:
    206 USER_RAM	equ	$407D
    207 MAX_RAM		equ	$7FFF
    208 ------------------------------------------------------------------------
    209 
    210 ;===============================
    211 ; ZX81 constants:
    212 ;===============================
    213 ; ZX characters (not the same as ASCII)
    214 ;-------------------------------
    215 ZX_SPACE	equ	$00
    216 ;	ZX_graphic		equ	$01	
    217 ;	ZX_graphic		equ	$02	
    218 ;	ZX_graphic		equ	$03	
    219 ;	ZX_graphic		equ	$04	
    220 ;	ZX_graphic		equ	$05	
    221 ;	ZX_graphic		equ	$06	
    222 ;	ZX_graphic		equ	$07	
    223 ;	ZX_graphic		equ	$08	
    224 ;	ZX_graphic		equ	$09	
    225 ;	ZX_graphic		equ	$0A	
    226 ZX_QUOTE		equ	$0B
    227 ZX_POUND		equ	$0C
    228 ZX_DOLLAR		equ	$0D
    229 ZX_COLON		equ	$0E
    230 ZX_QUERY		equ	$0F
    231 ZX_BRACKET_LEFT		equ	$10
    232 ZX_BRACKET_RIGHT	equ	$11
    233 ZX_GREATER_THAN		equ	$12
    234 ZX_LESS_THAN		equ	$13
    235 ZX_EQUAL		equ	$14
    236 ZX_PLUS			equ	$15
    237 ZX_MINUS		equ	$16
    238 ZX_STAR			equ	$17
    239 ZX_SLASH		equ	$18
    240 ZX_SEMICOLON		equ	$19
    241 ZX_COMMA		equ	$1A
    242 ZX_PERIOD		equ	$1B
    243 ZX_0		equ	$1C
    244 ZX_1		equ	$1D
    245 ZX_2		equ	$1E
    246 ZX_3		equ	$1F
    247 ZX_4		equ	$20
    248 ZX_5		equ	$21
    249 ZX_6		equ	$22
    250 ZX_7		equ	$23
    251 ZX_8		equ	$24
    252 ZX_9		equ	$25
    253 ZX_A		equ	$26
    254 ZX_B		equ	$27
    255 ZX_C		equ	$28
    256 ZX_D		equ	$29
    257 ZX_E		equ	$2A
    258 ZX_F		equ	$2B
    259 ZX_G		equ	$2C
    260 ZX_H		equ	$2D
    261 ZX_I		equ	$2E
    262 ZX_J		equ	$2F
    263 ZX_K		equ	$30
    264 ZX_L		equ	$31
    265 ZX_M		equ	$32
    266 ZX_N		equ	$33
    267 ZX_O		equ	$34
    268 ZX_P		equ	$35
    269 ZX_Q		equ	$36
    270 ZX_R		equ	$37
    271 ZX_S		equ	$38
    272 ZX_T		equ	$39
    273 ZX_U		equ	$3A
    274 ZX_V		equ	$3B
    275 ZX_W		equ	$3C
    276 ZX_X		equ	$3D
    277 ZX_Y		equ	$3E
    278 ZX_Z		equ	$3F
    279 ZX_RND			equ	$40
    280 ZX_INKEY_STR		equ	$41
    281 ZX_PI			equ	$42
    282 ;
    283 ; $43 to $6F not used
    284 ;
    285 ZX_cursor_up		equ	$70
    286 ZX_cursor_down		equ	$71
    287 ZX_cursor_left		equ	$72
    288 ZX_cursor_right		equ	$73
    289 
    290 ZX_GRAPHICS		equ	$74
    291 ZX_EDIT			equ	$75
    292 ZX_NEWLINE		equ	$76
    293 ZX_RUBOUT		equ	$77
    294 ZX_KL			equ	$78
    295 ZX_FUNCTION		equ	$79
    296 ;
    297 ; $7A to $7F not used
    298 ;
    299 ZX_CURSOR		equ	$7F
    300 ;
    301 ; $80 to $BF are inverses of $00 to $3F
    302 ;
    303 ;	ZX_graphic		equ	$80	 ; inverse space
    304 ;	ZX_graphic		equ	$81	
    305 ;	ZX_graphic		equ	$82	
    306 ;	ZX_graphic		equ	$83	
    307 ;	ZX_graphic		equ	$84	
    308 ;	ZX_graphic		equ	$85	
    309 ;	ZX_graphic		equ	$86	
    310 ;	ZX_graphic		equ	$87	
    311 ;	ZX_graphic		equ	$88	
    312 ;	ZX_graphic		equ	$89	
    313 ;	ZX_graphic		equ	$8A	
    314 ZX_INV_QUOTE		equ	$8B
    315 ZX_INV_POUND		equ	$8C
    316 ZX_INV_DOLLAR		equ	$8D
    317 ZX_INV_COLON		equ	$8E
    318 ZX_INV_QUERY		equ	$8F
    319 ZX_INV_BRACKET_RIGHT	equ	$90
    320 ZX_INV_BRACKET_LEFT	equ	$91
    321 ZX_INV_GT		equ	$92
    322 
    323 ZX_INV_PLUS		equ	$95
    324 ZX_INV_MINUS		equ	$96
    325 
    326 ZX_INV_K		equ	$B0
    327 ZX_INV_S		equ	$B8
    328 
    329 ZX_DOUBLE_QUOTE		equ	$C0
    330 ZX_AT			equ	$C1
    331 ZX_TAB			equ	$C2
    332 ; not used		equ	$C3
    333 ZX_CODE			equ	$C4
    334 ZX_VAL			equ	$C5
    335 ZX_LEN			equ	$C6
    336 ZX_SIN			equ	$C7
    337 ZX_COS			equ	$C8
    338 ZX_TAN			equ	$C9
    339 ZX_ASN			equ	$CA
    340 ZX_ACS			equ	$CB
    341 ZX_ATN			equ	$CC
    342 ZX_LN			equ	$CD
    343 ZX_EXP			equ	$CE
    344 ZX_INT			equ	$CF
    345 
    346 ZX_SQR			equ	$D0
    347 ZX_SGN			equ	$D1
    348 ZX_ABS			equ	$D2
    349 ZX_PEEK			equ	$D3
    350 ZX_USR			equ	$D4
    351 ZX_STR_STR		equ	$D5		; STR$
    352 ZX_CHR_STR		equ	$D6		; CHR$
    353 ZX_NOT			equ	$D7
    354 ZX_POWER		equ	$D8
    355 ZX_OR			equ	$D9
    356 ZX_AND			equ	$DA
    357 ZX_LESS_OR_EQUAL	equ	$DB
    358 ZX_GREATER_OR_EQUAL	equ	$DC
    359 ZX_NOT_EQUAL		equ	$DD
    360 ZX_THEN			equ	$DE
    361 ZX_TO			equ	$DF
    362 
    363 ZX_STEP			equ	$E0
    364 ZX_LPRINT		equ	$E1
    365 ZX_LLIST		equ	$E2
    366 ZX_STOP			equ	$E3
    367 ZX_SLOW			equ	$E4
    368 ZX_FAST			equ	$E5
    369 ZX_NEW			equ	$E6
    370 ZX_SCROLL		equ	$E7
    371 ZX_CONT			equ	$E8
    372 ZX_DIM			equ	$E9
    373 ZX_REM			equ	$EA
    374 ZX_FOR			equ	$EB
    375 ZX_GOTO			equ	$EC
    376 ZX_GOSUB		equ	$ED
    377 ZX_INPUT		equ	$EE
    378 ZX_LOAD			equ	$EF
    379 
    380 ZX_LIST			equ	$F0
    381 ZX_LET			equ	$F1
    382 ZX_PAUSE		equ	$F2
    383 ZX_NEXT			equ	$F3
    384 ZX_POKE			equ	$F4
    385 ZX_PRINT		equ	$F5
    386 ZX_PLOT			equ	$F6
    387 ZX_RUN			equ	$F7
    388 ZX_SAVE			equ	$F8
    389 ZX_RAND			equ	$F9
    390 ZX_IF			equ	$FA
    391 ZX_CLS			equ	$FB
    392 ZX_UNPLOT		equ	$FC
    393 ZX_CLEAR		equ	$FD
    394 ZX_RETURN		equ	$FE
    395 ZX_COPY			equ	$FF
    396 ------------------------------------------------------------------------
    397 
    398 
    399 ;
    400 _CLASS_00	equ	0
    401 _CLASS_01	equ	1
    402 _CLASS_02	equ	2
    403 _CLASS_03	equ	3
    404 _CLASS_04	equ	4
    405 _CLASS_05	equ	5
    406 _CLASS_06	equ	6
    407 ------------------------------------------------------------------------
    408 
    409 
    410 
    411 ; These values taken from BASIC manual
    412 ; 
    413 ;
    414 ERROR_CODE_SUCCESS			equ	0
    415 ERROR_CODE_CONTROL_VARIABLE		equ	1
    416 ERROR_CODE_UNDEFINED_VARIABLE		equ	2
    417 ERROR_CODE_SUBSCRIPT_OUT_OF_RANGE	equ	3
    418 ERROR_CODE_NOT_ENOUGH_MEMORY		equ	4
    419 ERROR_CODE_NO_ROOM_ON_SCREEN		equ	5
    420 ERROR_CODE_ARITHMETIC_OVERFLOW		equ	6
    421 ERROR_CODE_RETURN_WITHOUT_GOSUB		equ	7
    422 ERROR_CODE_INPUT_AS_A_COMMAND		equ	8
    423 ERROR_CODE_STOP				equ	9
    424 ERROR_CODE_INVALID_ARGUMENT		equ	10
    425 
    426 ERROR_CODE_INTEGER_OUT_OF_RANGE		equ	11
    427 ERROR_CODE_VAL_STRING_INVALID		equ	12
    428 ERROR_CODE_BREAK			equ	13
    429 
    430 ERROR_CODE_EMPTY_PROGRAM_NAME		equ	15
    431 ------------------------------------------------------------------------
    432 
    433 ;
    434 ; codes for Forth-like calculator
    435 ;
    436 __jump_true		equ	$00
    437 __exchange		equ	$01
    438 __delete		equ	$02
    439 __subtract		equ	$03
    440 __multiply		equ	$04
    441 __division		equ	$05
    442 __to_power		equ	$06
    443 __or			equ	$07
    444 __boolean_num_and_num	equ	$08
    445 __num_l_eql		equ	$09
    446 __num_gr_eql		equ	$0A
    447 __nums_neql		equ	$0B
    448 __num_grtr		equ	$0C
    449 __num_less		equ	$0D
    450 __nums_eql		equ	$0E
    451 __addition		equ	$0F
    452 __strs_and_num		equ	$10
    453 __str_l_eql		equ	$11
    454 __str_gr_eql		equ	$12
    455 __strs_neql		equ	$13
    456 __str_grtr		equ	$14
    457 __str_less		equ	$15
    458 __strs_eql		equ	$16
    459 __strs_add		equ	$17
    460 __negate		equ	$18
    461 __code			equ	$19
    462 __val			equ	$1A 
    463 __len			equ	$1B 
    464 __sin			equ	$1C
    465 __cos			equ	$1D
    466 __tan			equ	$1E
    467 __asn			equ	$1F
    468 __acs			equ	$20
    469 __atn			equ	$21
    470 __ln			equ	$22
    471 __exp			equ	$23
    472 __int			equ	$24
    473 __sqr			equ	$25
    474 __sgn			equ	$26
    475 __abs			equ	$27
    476 __peek			equ	$28
    477 __usr_num		equ	$29
    478 __str_dollar		equ	$2A
    479 __chr_dollar		equ	$2B
    480 __not			equ	$2C
    481 __duplicate		equ	$2D
    482 __n_mod_m		equ	$2E
    483 __jump			equ	$2F
    484 __stk_data		equ	$30
    485 __dec_jr_nz		equ	$31
    486 __less_0		equ	$32
    487 __greater_0		equ	$33
    488 __end_calc		equ	$34
    489 __get_argt		equ	$35
    490 __truncate		equ	$36
    491 __fp_calc_2		equ	$37
    492 __e_to_fp		equ	$38
    493 
    494 ;
    495 ; __series_xx			equ	$39 : $80__$9F.
    496 ; tells the stack machine to push 
    497 ; 0 to 31 floating-point values on the stack.
    498 ;
    499 __series_06		equ	$86
    500 __series_08		equ	$88
    501 __series_0C		equ	$8C
    502 ;	__stk_const_xx			equ	$3A : $A0__$BF.
    503 ;	__st_mem_xx			equ	$3B : $C0__$DF.
    504 ;	__get_mem_xx			equ	$3C : $E0__$FF.
    505 
    506 __st_mem_0			equ	$C0
    507 __st_mem_1			equ	$C1
    508 __st_mem_2			equ	$C2
    509 __st_mem_3			equ	$C3
    510 __st_mem_4			equ	$C4
    511 __st_mem_5			equ	$C5
    512 __st_mem_6			equ	$C6
    513 __st_mem_7			equ	$C7
    514 
    515 
    516 __get_mem_0			equ	$E0
    517 __get_mem_1			equ	$E1
    518 __get_mem_2			equ	$E2
    519 __get_mem_3			equ	$E3
    520 __get_mem_4			equ	$E4
    521 
    522 
    523 __stk_zero			equ	$A0
    524 __stk_one			equ	$A1
    525 __stk_half			equ	$A2
    526 __stk_half_pi			equ	$A3
    527 __stk_ten			equ	$A4
    528 ------------------------------------------------------------------------
    529 
    530 ;*****************************************
    531 ;** Part 1. RESTART ROUTINES AND TABLES **
    532 ;*****************************************
    533 
    534 ------------------------------------------------------------------------
    535 
    536 ; THE *'START'*
    537 ------------------------------------------------------------------------
    538 
    539 ; All Z80 chips start at location zero.
    540 ; At start-up the Interrupt Mode is 0, ZX computers use Interrupt Mode 1.
    541 ; Interrupts are disabled .
    542 
    543 mark_0000:
    544 *START:*
    545 	OUT	(IO_PORT_NMI_GEN_OFF),A	; Turn off the NMI generator if this ROM is 
    546 				; running in ZX81 hardware. This does nothing 
    547 				; if this ROM is running within an upgraded
    548 				; ZX80.
    549 	LD	BC,MAX_RAM	; Set BC to the top of possible RAM.
    550 				; The higher unpopulated addresses are used for
    551 				; video generation.
    552 	JP	RAM_CHECK <#RAM_CHECK>	; Jump forward to RAM_CHECK.
    553 
    554 ------------------------------------------------------------------------
    555 
    556 ; THE *'ERROR'* RESTART
    557 ------------------------------------------------------------------------
    558 
    559 ; The error restart deals immediately with an error.
    560 ; ZX computers execute the same code in runtime as when checking syntax.
    561 ; If the error occurred while running a program
    562 ; then a brief report is produced.
    563 ; If the error occurred while entering a BASIC line or in input etc., 
    564 ; then the error marker indicates the exact point at which the error lies.
    565 
    566 mark_0008:
    567 *ERROR_1:*
    568 	LD	HL,(CH_ADD)	; fetch character address from CH_ADD.
    569 	LD	(X_PTR),HL	; and set the error pointer X_PTR.
    570 	JR	ERROR_2 <#ERROR_2>		; forward to continue at ERROR_2.
    571 
    572 ------------------------------------------------------------------------
    573 
    574 ; THE *'PRINT A CHARACTER'* RESTART
    575 ------------------------------------------------------------------------
    576 
    577 ; This restart prints the character in the accumulator using the alternate
    578 ; register set so there is no requirement to save the main registers.
    579 ; There is sufficient room available to separate a space (zero) from other
    580 ; characters as leading spaces need not be considered with a space.
    581 
    582 mark_0010:
    583 *PRINT_A:*
    584 	AND	A		; test for zero - space.
    585 	JP	NZ,PRINT_CH <#PRINT_CH>	; jump forward if not to PRINT_CH.
    586 
    587 	JP	PRINT_SP <#PRINT_SP>	; jump forward to PRINT_SP.
    588 
    589 ; ___
    590 #if ORIGINAL
    591 	DEFB	$FF		; unused location.
    592 #else
    593 	DEFB	$01		;+ unused location. Version. PRINT PEEK 23
    594 #endif
    595 
    596 ------------------------------------------------------------------------
    597 
    598 ; THE *'COLLECT A CHARACTER'* RESTART
    599 ------------------------------------------------------------------------
    600 
    601 ; The character addressed by the system variable CH_ADD is fetched and if it
    602 ; is a non-space, non-cursor character it is returned else CH_ADD is 
    603 ; incremented and the new addressed character tested until it is not a space.
    604 
    605 mark_0018:
    606 *GET_CHAR:*
    607 	LD	HL,(CH_ADD)	; set HL to character address CH_ADD.
    608 	LD	A,(HL)		; fetch addressed character to A.
    609 
    610 *TEST_SP:*
    611 	AND	A		; test for space.
    612 	RET	NZ		; return if not a space
    613 
    614 	NOP			; else trickle through
    615 	NOP			; to the next routine.
    616 
    617 ------------------------------------------------------------------------
    618 
    619 ; THE *'COLLECT NEXT CHARACTER'* RESTART
    620 ------------------------------------------------------------------------
    621 
    622 ; The character address is incremented and the new addressed character is 
    623 ; returned if not a space, or cursor, else the process is repeated.
    624 
    625 mark_0020:
    626 *NEXT_CHAR:*
    627 	CALL	CH_ADD_PLUS_1 <#CH_ADD_PLUS_1>	; gets next immediate
    628 				; character.
    629 	JR	TEST_SP <#TEST_SP>		; back
    630 ; ___
    631 
    632 	DEFB	$FF, $FF, $FF	; unused locations.
    633 
    634 ------------------------------------------------------------------------
    635 
    636 ; THE *'FLOATING POINT CALCULATOR'* RESTART
    637 ------------------------------------------------------------------------
    638 
    639 ; this restart jumps to the recursive floating-point calculator.
    640 ; the ZX81's internal, FORTH-like, stack-based language.
    641 ;
    642 ; In the five remaining bytes there is, appropriately, enough room for the
    643 ; end-calc literal - the instruction which exits the calculator.
    644 
    645 mark_0028:
    646 *FP_CALC:*
    647 #if ORIGINAL
    648 	JP	CALCULATE <#CALCULATE>	; jump immediately to the CALCULATE routine.
    649 #else
    650 
    651 	JP	CALCULATE <#CALCULATE>	;+ jump to the NEW calculate routine address.
    652 #endif
    653 
    654 mark_002B:
    655 *end_calc:*
    656 	POP	AF		; drop the calculator return address RE_ENTRY
    657 	EXX			; switch to the other set.
    658 
    659 	EX	(SP),HL		; transfer H'L' to machine stack for the
    660 				; return address.
    661 				; when exiting recursion then the previous
    662 				; pointer is transferred to H'L'.
    663 
    664 	EXX			; back to main set.
    665 	RET			; return.
    666 
    667 
    668 ------------------------------------------------------------------------
    669 
    670 ; THE *'MAKE BC SPACES'* RESTART
    671 ------------------------------------------------------------------------
    672 
    673 ; This restart is used eight times to create, in workspace, the number of
    674 ; spaces passed in the BC register.
    675 
    676 mark_0030:
    677 *BC_SPACES:*
    678 	PUSH	BC		; push number of spaces on stack.
    679 	LD	HL,(E_LINE)	; fetch edit line location from E_LINE.
    680 	PUSH	HL		; save this value on stack.
    681 	JP	RESERVE <#RESERVE>		; jump forward to continue at RESERVE.
    682 
    683 
    684 ------------------------------------------------------------------------
    685 
    686 _START		equ	$00
    687 _ERROR_1	equ	$08
    688 _PRINT_A	equ	$10
    689 _GET_CHAR	equ	$18
    690 _NEXT_CHAR	equ	$20
    691 _FP_CALC	equ	$28
    692 _BC_SPACES	equ	$30
    693 ------------------------------------------------------------------------
    694 
    695 ; THE *'INTERRUPT'* RESTART
    696 ------------------------------------------------------------------------
    697 
    698 ;	The Mode 1 Interrupt routine is concerned solely with generating the central
    699 ;	television picture.
    700 ;	On the ZX81 interrupts are enabled only during the interrupt routine, 
    701 ;	although the interrupt 
    702 ;
    703 ;	This Interrupt Service Routine automatically disables interrupts at the 
    704 ;	outset and the last interrupt in a cascade exits before the interrupts are
    705 ;	enabled.
    706 ;
    707 ;	There is no DI instruction in the ZX81 ROM.
    708 ;
    709 ;	A maskable interrupt is triggered when bit 6 of the Z80's Refresh register
    710 ;	changes from set to reset.
    711 ;
    712 ;	The Z80 will always be executing a HALT (NEWLINE) when the interrupt occurs.
    713 ;	A HALT instruction repeatedly executes NOPS but the seven lower bits
    714 ;	of the Refresh register are incremented each time as they are when any 
    715 ;	simple instruction is executed. (The lower 7 bits are incremented twice for
    716 ;	a prefixed instruction)
    717 ;
    718 ;	This is controlled by the Sinclair Computer Logic Chip - manufactured from 
    719 ;	a Ferranti Uncommitted Logic Array.
    720 ;
    721 ;	When a Mode 1 Interrupt occurs the Program Counter, which is the address in
    722 ;	the upper echo display following the NEWLINE/HALT instruction, goes on the 
    723 ;	machine stack.	193 interrupts are required to generate the last part of
    724 ;	the 56th border line and then the 192 lines of the central TV picture and, 
    725 ;	although each interrupt interrupts the previous one, there are no stack 
    726 ;	problems as the 'return address' is discarded each time.
    727 ;
    728 ;	The scan line counter in C counts down from 8 to 1 within the generation of
    729 ;	each text line. For the first interrupt in a cascade the initial value of 
    730 ;	C is set to 1 for the last border line.
    731 ;	Timing is of the utmost importance as the RH border, horizontal retrace
    732 ;	and LH border are mostly generated in the 58 clock cycles this routine 
    733 ;	takes .
    734 
    735 
    736 ------------------------------------------------------------------------
    737 
    738 MARK_0038:
    739 *INTERRUPT:*
    740 	DEC	C		; (4)	decrement C - the scan line counter.
    741 	JP	NZ,SCAN_LINE <#SCAN_LINE>	; (10/10) JUMP forward if not zero to SCAN_LINE
    742 
    743 	POP	HL		; (10) point to start of next row in display 
    744 				;	file.
    745 
    746 	DEC	B		; (4)	decrement the row counter. (4)
    747 	RET	Z		; (11/5) return when picture complete to R_IX_1_LAST_NEWLINE
    748 				;	with interrupts disabled.
    749 
    750 	SET	3,C		; (8)	Load the scan line counter with eight.
    751 				;	Note. LD C,$08 is 7 clock cycles which 
    752 				;	is way too fast.
    753 
    754 ; ->
    755 
    756 mark_0041:
    757 *WAIT_INT:*
    758 ;
    759 ; NB $DD is for 32-column display
    760 ;
    761 	LD	R,A		; (9) Load R with initial rising value $DD.
    762 
    763 	EI			; (4) Enable Interrupts.	[ R is now $DE ].
    764 
    765 	JP	(HL)		; (4) jump to the echo display file in upper
    766 				;	memory and execute characters $00 - $3F 
    767 				;	as NOP instructions.	The video hardware 
    768 				;	is able to read these characters and, 
    769 				;	with the I register is able to convert 
    770 				;	the character bitmaps in this ROM into a 
    771 				;	line of bytes. Eventually the NEWLINE/HALT
    772 				;	will be encountered before R reaches $FF. 
    773 				;	It is however the transition from $FF to 
    774 				;	$80 that triggers the next interrupt.
    775 				;	[ The Refresh register is now $DF ]
    776 
    777 ; ___
    778 
    779 mark_0045:
    780 *SCAN_LINE:*
    781 	POP	DE		; (10) discard the address after NEWLINE as the 
    782 				;	same text line has to be done again
    783 				;	eight times. 
    784 
    785 	RET	Z		; (5)	Harmless Nonsensical Timing.
    786 				;	(condition never met)
    787 
    788 	JR	WAIT_INT <#WAIT_INT>	; (12) back to WAIT_INT
    789 
    790 ;	Note. that a computer with less than 4K or RAM will have a collapsed
    791 ;	display file and the above mechanism deals with both types of display.
    792 ;
    793 ;	With a full display, the 32 characters in the line are treated as NOPS
    794 ;	and the Refresh register rises from $E0 to $FF and, at the next instruction 
    795 ;	- HALT, the interrupt occurs.
    796 ;	With a collapsed display and an initial NEWLINE/HALT, it is the NOPs 
    797 ;	generated by the HALT that cause the Refresh value to rise from $E0 to $FF,
    798 ;	triggering an Interrupt on the next transition.
    799 ;	This works happily for all display lines between these extremes and the 
    800 ;	generation of the 32 character, 1 pixel high, line will always take 128 
    801 ;	clock cycles.
    802 
    803 ------------------------------------------------------------------------
    804 
    805 ; THE *'INCREMENT CH_ADD'* SUBROUTINE
    806 ------------------------------------------------------------------------
    807 
    808 ; This is the subroutine that increments the character address system variable
    809 ; and returns if it is not the cursor character. The ZX81 has an actual 
    810 ; character at the cursor position rather than a pointer system variable
    811 ; as is the case with prior and subsequent ZX computers.
    812 
    813 mark_0049:
    814 CH_ADD_PLUS_1:
    815 	LD	HL,(CH_ADD)	; fetch character address to CH_ADD.
    816 
    817 mark_004C:
    818 *TEMP_PTR1:*
    819 	INC	HL		; address next immediate location.
    820 
    821 mark_004D:
    822 *TEMP_PTR2:*
    823 	LD	(CH_ADD),HL	; update system variable CH_ADD.
    824 
    825 	LD	A,(HL)		; fetch the character.
    826 	CP	ZX_CURSOR	; compare to cursor character.
    827 	RET	NZ		; return if not the cursor.
    828 
    829 	JR	TEMP_PTR1 <#TEMP_PTR1>	; back for next character to TEMP_PTR1.
    830 
    831 ------------------------------------------------------------------------
    832 
    833 ; THE *'ERROR_2'* BRANCH
    834 ------------------------------------------------------------------------
    835 
    836 ; This is a continuation of the error restart.
    837 ; If the error occurred in runtime then the error stack pointer will probably
    838 ; lead to an error report being printed unless it occurred during input.
    839 ; If the error occurred when checking syntax then the error stack pointer
    840 ; will be an editing routine and the position of the error will be shown
    841 ; when the lower screen is reprinted.
    842 
    843 mark_0056:
    844 *ERROR_2:*
    845 	POP	HL		; pop the return address which points to the
    846 				; DEFB, error code, after the RST 08.
    847 	LD	L,(HL)		; load L with the error code. HL is not needed
    848 				; anymore.
    849 
    850 mark_0058:
    851 *ERROR_3:*
    852 	LD	(IY+ERR_NR-RAMBASE),L	; place error code in system variable ERR_NR
    853 	LD	SP,(ERR_SP)	; set the stack pointer from ERR_SP
    854 	CALL	SLOW_FAST <#SLOW_FAST>	; selects slow mode.
    855 	JP	SET_MIN <#SET_MIN>		; exit to address on stack via routine SET_MIN.
    856 
    857 ; ___
    858 
    859 	DEFB	$FF		; unused.
    860 
    861 ------------------------------------------------------------------------
    862 
    863 ; THE *'NON MASKABLE INTERRUPT'* ROUTINE
    864 ------------------------------------------------------------------------
    865 
    866 ;	Jim Westwood's technical dodge using Non-Maskable Interrupts solved the
    867 ;	flicker problem of the ZX80 and gave the ZX81 a multi-tasking SLOW mode 
    868 ;	with a steady display.	Note that the AF' register is reserved for this 
    869 ;	function and its interaction with the display routines.	When counting 
    870 ;	TV lines, the NMI makes no use of the main registers.
    871 ;	The circuitry for the NMI generator is contained within the SCL (Sinclair 
    872 ;	Computer Logic) chip. 
    873 ;	( It takes 32 clock cycles while incrementing towards zero ). 
    874 
    875 mark_0066:
    876 *NMI:*
    877 	EX	AF,AF'		; (4) switch in the NMI's copy of the 
    878 				;	accumulator.
    879 	INC	A		; (4) increment.
    880 	JP	M,NMI_RET <#NMI_RET>	; (10/10) jump, if minus, to NMI_RET as this is
    881 				;	part of a test to see if the NMI 
    882 				;	generation is working or an intermediate 
    883 				;	value for the ascending negated blank 
    884 				;	line counter.
    885 
    886 	JR	Z,NMI_CONT <#NMI_CONT>	; (12) forward to NMI_CONT
    887 				;	when line count has incremented to zero.
    888 
    889 ; Note. the synchronizing NMI when A increments from zero to one takes this
    890 ; 7 clock cycle route making 39 clock cycles in all.
    891 
    892 mark_006D:
    893 *NMI_RET:*
    894 	EX	AF,AF'		; (4)	switch out the incremented line counter
    895 				;	or test result $80
    896 	RET			; (10) return to User application for a while.
    897 
    898 ; ___
    899 
    900 ;	This branch is taken when the 55 (or 31) lines have been drawn.
    901 
    902 mark_006F:
    903 *NMI_CONT:*
    904 	EX	AF,AF'		; (4) restore the main accumulator.
    905 
    906 	PUSH	AF		; (11) *		Save Main Registers
    907 	PUSH	BC		; (11) **
    908 	PUSH	DE		; (11) ***
    909 	PUSH	HL		; (11) ****
    910 
    911 ;	the next set-up procedure is only really applicable when the top set of 
    912 ;	blank lines have been generated.
    913 
    914 	LD	HL,(D_FILE)	; (16) fetch start of Display File from D_FILE
    915 				;      points to the HALT at beginning.
    916 	SET	7,H		; (8)  point to upper 32K 'echo display file'
    917 
    918 	HALT			; (1)  HALT synchronizes with NMI.
    919 				;      Used with special hardware connected to the
    920 				;      Z80 HALT and WAIT lines to take 1 clock cycle.
    921 
    922 ------------------------------------------------------------------------
    923 
    924 ;	the NMI has been generated - start counting.
    925 ;	The cathode ray is at the RH side of the TV.
    926 ;
    927 ;	First the NMI servicing, similar to CALL		=	17 clock cycles.
    928 ;	Then the time taken by the NMI for zero-to-one path	=	39 cycles
    929 ;	The HALT above						=	01 cycles.
    930 ;	The two instructions below				=	19 cycles.
    931 ;	The code at R_IX_1 <#R_IX_1> up to and including the CALL		=	43 cycles.
    932 ;	The Called routine at DISPLAY_5 <#DISPLAY_5>				=	24 cycles.
    933 ;	--------------------------------------				---
    934 ;	Total Z80 instructions					=	143 cycles.
    935 ;
    936 ;	Meanwhile in TV world,
    937 ;	Horizontal retrace					=	15 cycles.
    938 ;	Left blanking border 8 character positions		=	32 cycles
    939 ;	Generation of 75% scanline from the first NEWLINE	=	96 cycles
    940 ;	---------------------------------------				---
    941 ;								=	143 cycles
    942 ;
    943 ;	Since at the time the first JP (HL) is encountered to execute the echo
    944 ;	display another 8 character positions have to be put out, then the
    945 ;	Refresh register need to hold $F8. Working back and counteracting 
    946 ;	the fact that every instruction increments the Refresh register then
    947 ;	the value that is loaded into R needs to be $F5.	:-)
    948 ;
    949 ;
    950 	OUT	(IO_PORT_NMI_GEN_OFF),A		; (11) Stop the NMI generator.
    951 
    952 	JP	(IX)				; (8) forward to R_IX_1 (after top) or R_IX_2
    953 
    954 ; ****************
    955 ; ** KEY TABLES **
    956 ; ****************
    957 
    958 ------------------------------------------------------------------------
    959 
    960 ; THE *'UNSHIFTED'* CHARACTER CODES
    961 ------------------------------------------------------------------------
    962 
    963 
    964 mark_007E:
    965 *K_UNSHIFT*:
    966 	DEFB	ZX_Z
    967 	DEFB	ZX_X
    968 	DEFB	ZX_C
    969 	DEFB	ZX_V
    970 
    971 	DEFB	ZX_A
    972 	DEFB	ZX_S
    973 	DEFB	ZX_D
    974 	DEFB	ZX_F
    975 	DEFB	ZX_G
    976 
    977 	DEFB	ZX_Q
    978 	DEFB	ZX_W
    979 	DEFB	ZX_E
    980 	DEFB	ZX_R
    981 	DEFB	ZX_T
    982 
    983 	DEFB	ZX_1
    984 	DEFB	ZX_2
    985 	DEFB	ZX_3
    986 	DEFB	ZX_4
    987 	DEFB	ZX_5
    988 
    989 	DEFB	ZX_0
    990 	DEFB	ZX_9
    991 	DEFB	ZX_8
    992 	DEFB	ZX_7
    993 	DEFB	ZX_6
    994 
    995 	DEFB	ZX_P
    996 	DEFB	ZX_O
    997 	DEFB	ZX_I
    998 	DEFB	ZX_U
    999 	DEFB	ZX_Y
   1000 
   1001 	DEFB	ZX_NEWLINE
   1002 	DEFB	ZX_L
   1003 	DEFB	ZX_K
   1004 	DEFB	ZX_J
   1005 	DEFB	ZX_H
   1006 
   1007 	DEFB	ZX_SPACE
   1008 	DEFB	ZX_PERIOD
   1009 	DEFB	ZX_M
   1010 	DEFB	ZX_N
   1011 	DEFB	ZX_B
   1012 
   1013 
   1014 ------------------------------------------------------------------------
   1015 
   1016 ; THE *'SHIFTED'* CHARACTER CODES
   1017 ------------------------------------------------------------------------
   1018 
   1019 
   1020 
   1021 mark_00A5:
   1022 K_SHIFT:
   1023 	DEFB	ZX_COLON	; :
   1024 	DEFB	ZX_SEMICOLON	; ;
   1025 	DEFB	ZX_QUERY	; ?
   1026 	DEFB	ZX_SLASH	; /
   1027 	DEFB	ZX_STOP
   1028 	DEFB	ZX_LPRINT
   1029 	DEFB	ZX_SLOW
   1030 	DEFB	ZX_FAST
   1031 	DEFB	ZX_LLIST
   1032 	DEFB	$C0		; ""
   1033 	DEFB	ZX_OR
   1034 	DEFB	ZX_STEP
   1035 	DEFB	$DB		; <=
   1036 	DEFB	$DD		; <>
   1037 	DEFB	ZX_EDIT
   1038 	DEFB	ZX_AND
   1039 	DEFB	ZX_THEN
   1040 	DEFB	ZX_TO
   1041 	DEFB	$72		; cursor-left
   1042 	DEFB	ZX_RUBOUT
   1043 	DEFB	ZX_GRAPHICS
   1044 	DEFB	$73		; cursor-right
   1045 	DEFB	$70		; cursor-up
   1046 	DEFB	$71		; cursor-down
   1047 	DEFB	ZX_QUOTE	; "
   1048 	DEFB	$11		; )
   1049 	DEFB	$10		; (
   1050 	DEFB	ZX_DOLLAR	; $
   1051 	DEFB	$DC		; >=
   1052 	DEFB	ZX_FUNCTION
   1053 	DEFB	ZX_EQUAL
   1054 	DEFB	ZX_PLUS
   1055 	DEFB	ZX_MINUS
   1056 	DEFB	ZX_POWER	; **
   1057 	DEFB	ZX_POUND	; £ 
   1058 	DEFB	ZX_COMMA	; ,
   1059 	DEFB	ZX_GREATER_THAN	; >
   1060 	DEFB	ZX_LESS_THAN	; <
   1061 	DEFB	ZX_STAR		; *
   1062 
   1063 ------------------------------------------------------------------------
   1064 
   1065 ; THE *'FUNCTION'* CHARACTER CODES
   1066 ------------------------------------------------------------------------
   1067 
   1068 
   1069 
   1070 mark_00CC:
   1071 *K_FUNCT:*
   1072 	DEFB	ZX_LN
   1073 	DEFB	ZX_EXP
   1074 	DEFB	ZX_AT
   1075 	DEFB	ZX_KL
   1076 	DEFB	ZX_ASN
   1077 	DEFB	ZX_ACS
   1078 	DEFB	ZX_ATN
   1079 	DEFB	ZX_SGN
   1080 	DEFB	ZX_ABS
   1081 	DEFB	ZX_SIN
   1082 	DEFB	ZX_COS
   1083 	DEFB	ZX_TAN
   1084 	DEFB	ZX_INT
   1085 	DEFB	ZX_RND
   1086 	DEFB	ZX_KL
   1087 	DEFB	ZX_KL
   1088 	DEFB	ZX_KL
   1089 	DEFB	ZX_KL
   1090 	DEFB	ZX_KL
   1091 	DEFB	ZX_KL
   1092 	DEFB	ZX_KL
   1093 	DEFB	ZX_KL
   1094 	DEFB	ZX_KL
   1095 	DEFB	ZX_KL
   1096 	DEFB	ZX_TAB
   1097 	DEFB	ZX_PEEK
   1098 	DEFB	ZX_CODE
   1099 	DEFB	ZX_CHR_STR	;	CHR$
   1100 	DEFB	ZX_STR_STR	;	STR$
   1101 	DEFB	ZX_KL
   1102 	DEFB	ZX_USR
   1103 	DEFB	ZX_LEN
   1104 	DEFB	ZX_VAL
   1105 	DEFB	ZX_SQR
   1106 	DEFB	ZX_KL
   1107 	DEFB	ZX_KL
   1108 	DEFB	ZX_PI
   1109 	DEFB	ZX_NOT
   1110 	DEFB	ZX_INKEY_STR
   1111 
   1112 
   1113 ------------------------------------------------------------------------
   1114 
   1115 ; THE *'GRAPHIC'* CHARACTER CODES
   1116 ------------------------------------------------------------------------
   1117 
   1118 
   1119 
   1120 mark_00F3:
   1121 *K_GRAPH:*
   1122 	DEFB	$08		; graphic
   1123 	DEFB	$0A		; graphic
   1124 	DEFB	$09		; graphic
   1125 	DEFB	$8A		; graphic
   1126 	DEFB	$89		; graphic
   1127 
   1128 	DEFB	$81		; graphic
   1129 	DEFB	$82		; graphic
   1130 	DEFB	$07		; graphic
   1131 	DEFB	$84		; graphic
   1132 	DEFB	$06		; graphic
   1133 
   1134 	DEFB	$01		; graphic
   1135 	DEFB	$02		; graphic
   1136 	DEFB	$87		; graphic
   1137 	DEFB	$04		; graphic
   1138 	DEFB	$05		; graphic
   1139 
   1140 	DEFB	ZX_RUBOUT
   1141 	DEFB	ZX_KL
   1142 	DEFB	$85		; graphic
   1143 	DEFB	$03		; graphic
   1144 	DEFB	$83		; graphic
   1145 
   1146 	DEFB	$8B		; graphic
   1147 	DEFB	$91		; inverse )
   1148 	DEFB	$90		; inverse (
   1149 	DEFB	$8D		; inverse $
   1150 	DEFB	$86		; graphic
   1151 
   1152 	DEFB	ZX_KL
   1153 	DEFB	$92		; inverse >
   1154 	DEFB	$95		; inverse +
   1155 	DEFB	$96		; inverse -
   1156 	DEFB	$88		; graphic
   1157 
   1158 ------------------------------------------------------------------------
   1159 
   1160 ; THE *'TOKEN'* TABLES
   1161 ------------------------------------------------------------------------
   1162 
   1163 
   1164 
   1165 mark_0111:
   1166 *TOKEN_TABLE:*
   1167 	DEFB	ZX_QUERY						+$80; '?'
   1168 	DEFB	ZX_QUOTE,	ZX_QUOTE				+$80; ""
   1169 	DEFB	ZX_A,	ZX_T						+$80; AT
   1170 	DEFB	ZX_T,	ZX_A,	ZX_B					+$80; TAB
   1171 	DEFB	ZX_QUERY						+$80; '?'
   1172 	DEFB	ZX_C,	ZX_O,	ZX_D,	ZX_E				+$80; CODE
   1173 	DEFB	ZX_V,	ZX_A,	ZX_L					+$80; VAL
   1174 	DEFB	ZX_L,	ZX_E,	ZX_N					+$80; LEN
   1175 	DEFB	ZX_S,	ZX_I,	ZX_N					+$80; SIN
   1176 	DEFB	ZX_C,	ZX_O,	ZX_S					+$80; COS
   1177 	DEFB	ZX_T,	ZX_A,	ZX_N					+$80; TAN
   1178 	DEFB	ZX_A,	ZX_S,	ZX_N					+$80; ASN
   1179 	DEFB	ZX_A,	ZX_C,	ZX_S					+$80; ACS
   1180 	DEFB	ZX_A,	ZX_T,	ZX_N					+$80; ATN
   1181 	DEFB	ZX_L,	ZX_N						+$80; LN
   1182 	DEFB	ZX_E,	ZX_X,	ZX_P					+$80; EXP
   1183 	DEFB	ZX_I,	ZX_N,	ZX_T					+$80; INT
   1184 	DEFB	ZX_S,	ZX_Q,	ZX_R					+$80; SQR
   1185 	DEFB	ZX_S,	ZX_G,	ZX_N					+$80; SGN
   1186 	DEFB	ZX_A,	ZX_B,	ZX_S					+$80; ABS
   1187 	DEFB	ZX_P,	ZX_E,	ZX_E,	ZX_K				+$80; PEEK
   1188 	DEFB	ZX_U,	ZX_S,	ZX_R					+$80; USR
   1189 	DEFB	ZX_S,	ZX_T,	ZX_R,	ZX_DOLLAR			+$80; STR$
   1190 	DEFB	ZX_C,	ZX_H,	ZX_R,	ZX_DOLLAR			+$80; CHR$
   1191 	DEFB	ZX_N,	ZX_O,	ZX_T					+$80; NOT
   1192 	DEFB	ZX_STAR,	ZX_STAR					+$80; **
   1193 	DEFB	ZX_O,	ZX_R						+$80; OR
   1194 	DEFB	ZX_A,	ZX_N,	ZX_D					+$80; AND
   1195 	DEFB	ZX_LESS_THAN,		ZX_EQUAL			+$80; >=
   1196 	DEFB	ZX_GREATER_THAN,	ZX_EQUAL			+$80; <=
   1197 	DEFB	ZX_LESS_THAN,		ZX_GREATER_THAN			+$80; ><
   1198 	DEFB	ZX_T,	ZX_H,	ZX_E,	ZX_N				+$80; THEN
   1199 	DEFB	ZX_T,	ZX_O						+$80; TO
   1200 	DEFB	ZX_S,	ZX_T,	ZX_E,	ZX_P				+$80; STEP
   1201 	DEFB	ZX_L,	ZX_P,	ZX_R,	ZX_I,	ZX_N,	ZX_T		+$80; LPRINT
   1202 	DEFB	ZX_L,	ZX_L,	ZX_I,	ZX_S,	ZX_T			+$80; LLIST
   1203 	DEFB	ZX_S,	ZX_T,	ZX_O,	ZX_P				+$80; STOP
   1204 	DEFB	ZX_S,	ZX_L,	ZX_O,	ZX_W				+$80; SLOW
   1205 	DEFB	ZX_F,	ZX_A,	ZX_S,	ZX_T				+$80; FAST
   1206 	DEFB	ZX_N,	ZX_E,	ZX_W					+$80; NEW
   1207 	DEFB	ZX_S,	ZX_C,	ZX_R,	ZX_O,	ZX_L,	ZX_L		+$80; SCROLL
   1208 	DEFB	ZX_C,	ZX_O,	ZX_N,	ZX_T				+$80; CONT
   1209 	DEFB	ZX_D,	ZX_I,	ZX_M					+$80; DIM
   1210 	DEFB	ZX_R,	ZX_E,	ZX_M					+$80; REM
   1211 	DEFB	ZX_F,	ZX_O,	ZX_R					+$80; FOR
   1212 	DEFB	ZX_G,	ZX_O,	ZX_T,	ZX_O				+$80; GOTO
   1213 	DEFB	ZX_G,	ZX_O,	ZX_S,	ZX_U,	ZX_B			+$80; GOSUB
   1214 	DEFB	ZX_I,	ZX_N,	ZX_P,	ZX_U,	ZX_T			+$80; INPUT
   1215 	DEFB	ZX_L,	ZX_O,	ZX_A,	ZX_D				+$80; LOAD
   1216 	DEFB	ZX_L,	ZX_I,	ZX_S,	ZX_T				+$80; LIST
   1217 	DEFB	ZX_L,	ZX_E,	ZX_T					+$80; LET
   1218 	DEFB	ZX_P,	ZX_A,	ZX_U,	ZX_S,	ZX_E			+$80; PAUSE
   1219 	DEFB	ZX_N,	ZX_E,	ZX_X,	ZX_T				+$80; NEXT
   1220 	DEFB	ZX_P,	ZX_O,	ZX_K,	ZX_E				+$80; POKE
   1221 	DEFB	ZX_P,	ZX_R,	ZX_I,	ZX_N,	ZX_T			+$80; PRINT
   1222 	DEFB	ZX_P,	ZX_L,	ZX_O,	ZX_T				+$80; PLOT
   1223 	DEFB	ZX_R,	ZX_U,	ZX_N					+$80; RUN
   1224 	DEFB	ZX_S,	ZX_A,	ZX_V,	ZX_E				+$80; SAVE
   1225 	DEFB	ZX_R,	ZX_A,	ZX_N,	ZX_D				+$80; RAND
   1226 	DEFB	ZX_I,	ZX_F						+$80; IF
   1227 	DEFB	ZX_C,	ZX_L,	ZX_S					+$80; CLS
   1228 	DEFB	ZX_U,	ZX_N,	ZX_P,	ZX_L,	ZX_O,	ZX_T		+$80; UNPLOT
   1229 	DEFB	ZX_C,	ZX_L,	ZX_E,	ZX_A,	ZX_R			+$80; CLEAR
   1230 	DEFB	ZX_R,	ZX_E,	ZX_T,	ZX_U,	ZX_R,	ZX_N		+$80; RETURN
   1231 	DEFB	ZX_C,	ZX_O,	ZX_P,	ZX_Y				+$80; COPY
   1232 	DEFB	ZX_R,	ZX_N,	ZX_D					+$80; RND
   1233 	DEFB	ZX_I,	ZX_N,	ZX_K,	ZX_E,	ZX_Y,	ZX_DOLLAR	+$80; INKEY$
   1234 	DEFB	ZX_P,	ZX_I						+$80; PI
   1235 
   1236 ------------------------------------------------------------------------
   1237 
   1238 ; THE *'LOAD_SAVE UPDATE'* ROUTINE
   1239 ------------------------------------------------------------------------
   1240 
   1241 ;
   1242 ;
   1243 
   1244 mark_01FC:
   1245 *LOAD_SAVE:*
   1246 	INC	HL		;
   1247 	EX	DE,HL		;
   1248 	LD	HL,(E_LINE)	; system variable edit line E_LINE.
   1249 	SCF			; set carry flag
   1250 	SBC	HL,DE		;
   1251 	EX	DE,HL		;
   1252 	RET	NC		; return if more bytes to LOAD_SAVE.
   1253 
   1254 	POP	HL		; else drop return address
   1255 
   1256 ------------------------------------------------------------------------
   1257 
   1258 ; THE *'DISPLAY'* ROUTINES
   1259 ------------------------------------------------------------------------
   1260 
   1261 ;
   1262 ;
   1263 
   1264 mark_0207:
   1265 *SLOW_FAST:*
   1266 	LD	HL,CDFLAG	; Address the system variable CDFLAG.
   1267 	LD	A,(HL)		; Load value to the accumulator.
   1268 	RLA			; rotate bit 6 to position 7.
   1269 	XOR	(HL)		; exclusive or with original bit 7.
   1270 	RLA			; rotate result out to carry.
   1271 	RET	NC		; return if both bits were the same.
   1272 
   1273 ;	Now test if this really is a ZX81 or a ZX80 running the upgraded ROM.
   1274 ;	The standard ZX80 did not have an NMI generator.
   1275 
   1276 	LD	A,$7F		; Load accumulator with %011111111
   1277 	EX	AF,AF'		; save in AF'
   1278 
   1279 	LD	B,17		; A counter within which an NMI should occur
   1280 				; if this is a ZX81.
   1281 	OUT	(IO_PORT_NMI_GEN_ON),A	; start the NMI generator.
   1282 
   1283 ;	Note that if this is a ZX81 then the NMI will increment AF'.
   1284 
   1285 mark_0216:
   1286 *LOOP_11:*
   1287 
   1288 	DJNZ	LOOP_11 <#LOOP_11>		; self loop to give the NMI a chance to kick in.
   1289 				; = 16*13 clock cycles + 8 = 216 clock cycles.
   1290 
   1291 	OUT	(IO_PORT_NMI_GEN_OFF),A	; Turn off the NMI generator.
   1292 	EX	AF,AF'		; bring back the AF' value.
   1293 	RLA			; test bit 7.
   1294 	JR	NC,NO_SLOW <#NO_SLOW>	; forward, if bit 7 is still reset, to NO_SLOW.
   1295 
   1296 ;	If the AF' was incremented then the NMI generator works and SLOW mode can
   1297 ;	be set.
   1298 
   1299 	SET	7,(HL)		; Indicate SLOW mode - Compute and Display.
   1300 
   1301 	PUSH	AF		; *		Save Main Registers
   1302 	PUSH	BC		; **
   1303 	PUSH	DE		; ***
   1304 	PUSH	HL		; ****
   1305 
   1306 	JR	DISPLAY_1 <#DISPLAY_1>	; skip forward - to DISPLAY_1.
   1307 
   1308 ; ___
   1309 
   1310 mark_0226:
   1311 *NO_SLOW:*
   1312 	RES	6,(HL)		; reset bit 6 of CDFLAG.
   1313 	RET			; return.
   1314 
   1315 ------------------------------------------------------------------------
   1316 
   1317 ; THE *'MAIN DISPLAY'* LOOP
   1318 ------------------------------------------------------------------------
   1319 
   1320 ; This routine is executed once for every frame displayed.
   1321 
   1322 mark_0229:
   1323 *DISPLAY_1:*
   1324 
   1325 	LD	HL,(FRAMES)	; fetch two-byte system variable FRAMES.
   1326 	DEC	HL		; decrement frames counter.
   1327 mark_022D:
   1328 *DISPLAY_P:*
   1329 	LD	A,$7F		; prepare a mask
   1330 	AND	H		; pick up bits 6-0 of H.
   1331 	OR	L		; and any bits of L.
   1332 	LD	A,H		; reload A with all bits of H for PAUSE test.
   1333 
   1334 ;	Note both branches must take the same time.
   1335 
   1336 	JR	NZ,ANOTHER <#ANOTHER>	; (12/7) forward if bits 14-0 are not zero 
   1337 				; to ANOTHER
   1338 
   1339 	RLA			; (4) test bit 15 of FRAMES.
   1340 	JR	OVER_NC <#OVER_NC>		; (12) forward with result to OVER_NC
   1341 
   1342 ; ___
   1343 
   1344 mark_0237:
   1345 *ANOTHER:*
   1346 	LD	B,(HL)		; (7) Note. Harmless Nonsensical Timing weight.
   1347 	SCF			; (4) Set Carry Flag.
   1348 
   1349 ; Note. the branch to here takes either (12)(7)(4) cyles or (7)(4)(12) cycles.
   1350 
   1351 mark_0239:
   1352 *OVER_NC:*
   1353 	LD	H,A		; (4)	set H to zero
   1354 	LD	(FRAMES),HL	; (16) update system variable FRAMES 
   1355 	RET	NC		; (11/5) return if FRAMES is in use by PAUSE 
   1356 				; command.
   1357 
   1358 mark_023E:
   1359 *DISPLAY_2:*
   1360 	CALL	KEYBOARD <#KEYBOARD>	; gets the key row in H and the column in L. 
   1361 				; Reading the ports also starts
   1362 				; the TV frame synchronization pulse. (VSYNC)
   1363 
   1364 	LD	BC,(LAST_K)	; fetch the last key values
   1365 	LD	(LAST_K),HL	; update LAST_K with new values.
   1366 
   1367 	LD	A,B		; load A with previous column - will be $FF if
   1368 				; there was no key.
   1369 	ADD	A,2		; adding two will set carry if no previous key.
   1370 
   1371 	SBC	HL,BC		; subtract with the carry the two key values.
   1372 
   1373 ; If the same key value has been returned twice then HL will be zero.
   1374 
   1375 	LD	A,(DEBOUNCE_VAR)
   1376 	OR	H		; and OR with both bytes of the difference
   1377 	OR	L		; setting the zero flag for the upcoming branch.
   1378 
   1379 	LD	E,B		; transfer the column value to E
   1380 	LD	B,11		; and load B with eleven 
   1381 
   1382 	LD	HL,CDFLAG	; address system variable CDFLAG
   1383 	RES	0,(HL)		; reset the rightmost bit of CDFLAG
   1384 	JR	NZ,NO_KEY <#NO_KEY>	; skip forward if debounce/diff >0 to NO_KEY
   1385 
   1386 	BIT	7,(HL)		; test compute and display bit of CDFLAG
   1387 	SET	0,(HL)		; set the rightmost bit of CDFLAG.
   1388 	RET	Z		; return if bit 7 indicated fast mode.
   1389 
   1390 	DEC	B		; (4) decrement the counter.
   1391 	NOP			; (4) Timing - 4 clock cycles. ??
   1392 	SCF			; (4) Set Carry Flag
   1393 
   1394 mark_0264:
   1395 *NO_KEY:*
   1396 
   1397 	LD	HL,DEBOUNCE_VAR	;
   1398 	CCF			; Complement Carry Flag
   1399 	RL	B		; rotate left B picking up carry
   1400 				;	C<-76543210<-C
   1401 
   1402 
   1403 
   1404 
   1405 
   1406 
   1407 mark_026A:
   1408 *LOOP_B:*
   1409 
   1410 	DJNZ	LOOP_B <#LOOP_B>		; self-loop while B>0 to LOOP_B
   1411 
   1412 	LD	B,(HL)		; fetch value of DEBOUNCE_VAR to B
   1413 	LD	A,E		; transfer column value
   1414 	CP	$FE		;
   1415 	SBC	A,A		; A = A-A-C = 0-Carry
   1416 #if 1
   1417 ; I think this truncating DEBOUNCE_VAR 
   1418 ; which would explain why the VSYNC time didn't match
   1419 ; my calculations that assumed debouncing for 255 loops.
   1420 ;
   1421 ;
   1422 	LD	B,$1F		; binary 000 11111
   1423 	OR	(HL)		;
   1424 	AND	B		; truncate column, 0 to 31
   1425 #endif
   1426 	RRA			;
   1427 	LD	(HL),A		;
   1428 
   1429 	OUT	(IO_PORT_SCREEN),A	; end the TV frame synchronization pulse.
   1430 
   1431 	LD	HL,(D_FILE)	; (12) set HL to the Display File from D_FILE
   1432 	SET	7,H		; (8) set bit 15 to address the echo display.
   1433 
   1434 	CALL	DISPLAY_3 <#DISPLAY_3>	; (17) routine DISPLAY_3 displays the top set 
   1435 				; of blank lines.
   1436 
   1437 ------------------------------------------------------------------------
   1438 
   1439 ; THE *'VIDEO_1'* ROUTINE
   1440 ------------------------------------------------------------------------
   1441 
   1442 
   1443 mark_0281:
   1444 *R_IX_1:*
   1445 	LD	A,R		; (9)	Harmless Nonsensical Timing
   1446 				;	or something very clever?
   1447 	LD	BC,25*256+1	; (10)	25 lines, 1 scanline in first. ($1901)
   1448 
   1449 ; 32 characters, use $F5 (i.e. minus 11)
   1450 ; 40 characters, use $ED (i.e. minus 19)
   1451 ;
   1452 
   1453 mark_0286:
   1454 	LD	A,277-CHARS_PER_LINE_WINDOW	; $F5 for 6.5MHz clocked machines
   1455 				; (7)	This value will be loaded into R and 
   1456 				; ensures that the cycle starts at the right 
   1457 				; part of the display	- after last character 
   1458 				; position.
   1459 
   1460 	CALL	DISPLAY_5 <#DISPLAY_5>	; (17) routine DISPLAY_5 completes the current 
   1461 				; blank line and then generates the display of 
   1462 				; the live picture using INT interrupts
   1463 				; The final interrupt returns to the next 
   1464 				; address.
   1465 *R_IX_1_LAST_NEWLINE:*
   1466 	DEC	HL		; point HL to the last NEWLINE/HALT.
   1467 
   1468 	CALL	DISPLAY_3 <#DISPLAY_3>	; displays the bottom set of blank lines.
   1469 
   1470 ; ___
   1471 
   1472 mark_028F:
   1473 *R_IX_2:*
   1474 	JP	DISPLAY_1 <#DISPLAY_1>	; JUMP back to DISPLAY_1
   1475 
   1476 ------------------------------------------------------------------------
   1477 
   1478 ; THE *'DISPLAY BLANK LINES'* ROUTINE 
   1479 ------------------------------------------------------------------------
   1480 
   1481 ;	This subroutine is called twice (see above) to generate first the blank 
   1482 ;	lines at the top of the television display and then the blank lines at the
   1483 ;	bottom of the display. 
   1484 ;
   1485 ;	It is actually pretty bad.
   1486 ;	PAL or NTSC = 312 or 
   1487 ;   1 to   5 = 5 long and 5 short sync
   1488 ;   6 to  23 = blank
   1489 ;  24 to 309 = image
   1490 ; 310 to 312 = 6 short sync
   1491 ;
   1492 ; The ZX80 generates either 62 or 110 blank lines
   1493 ;
   1494 ; 262 - 31 - 31 = 200
   1495 ; 312 - 55 - 55 = 202
   1496 ;
   1497 ; This does not include 'VSYNC' line periods.
   1498 ;
   1499 
   1500 mark_0292:
   1501 *DISPLAY_3:*
   1502 	POP	IX		; pop the return address to IX register.
   1503 				; will be either R_IX_1 or R_IX_2 - see above.
   1504 
   1505 	LD	C,(IY+MARGIN-RAMBASE)	; load C with value of system constant MARGIN.
   1506 	BIT	7,(IY+CDFLAG-RAMBASE)	; test CDFLAG for compute and display.
   1507 	JR	Z,DISPLAY_4 <#DISPLAY_4>	; forward, with FAST mode, to DISPLAY_4
   1508 
   1509 	LD	A,C		; move MARGIN to A	- 31d or 55d.
   1510 	NEG			; Negate
   1511 	INC	A		;
   1512 	EX	AF,AF'		; place negative count of blank lines in A'
   1513 
   1514 	OUT	(IO_PORT_NMI_GEN_ON),A	; enable the NMI generator.
   1515 
   1516 	POP	HL		; ****
   1517 	POP	DE		; ***
   1518 	POP	BC		; **
   1519 	POP	AF		; *		Restore Main Registers
   1520 
   1521 	RET			; return - end of interrupt.	Return is to 
   1522 				; user's program - BASIC or machine code.
   1523 				; which will be interrupted by every NMI.
   1524 
   1525 ------------------------------------------------------------------------
   1526 
   1527 ; THE *'FAST MODE'* ROUTINES
   1528 ------------------------------------------------------------------------
   1529 
   1530 
   1531 mark_02A9:
   1532 
   1533 *DISPLAY_4:*
   1534 
   1535 	LD	A,284-CHARS_PER_LINE_WINDOW	; $FC for 6.5MHz clocked machines
   1536 				; (7)	load A with first R delay value
   1537 
   1538 	LD	B,1		; (7)	one row only.
   1539 
   1540 	CALL	DISPLAY_5 <#DISPLAY_5>	; (17) routine DISPLAY_5
   1541 
   1542 	DEC	HL		; (6)	point back to the HALT.
   1543 	EX	(SP),HL		; (19) Harmless Nonsensical Timing if paired.
   1544 	EX	(SP),HL		; (19) Harmless Nonsensical Timing.
   1545 	JP	(IX)		; (8)	to R_IX_1 or R_IX_2
   1546 
   1547 ------------------------------------------------------------------------
   1548 
   1549 ; THE *'DISPLAY_5'* SUBROUTINE
   1550 ------------------------------------------------------------------------
   1551 
   1552 ;	This subroutine is called from SLOW mode and FAST mode to generate the 
   1553 ;	central TV picture. With SLOW mode the R register is incremented, with
   1554 ;	each instruction, to $F7 by the time it completes.	With fast mode, the 
   1555 ;	final R value will be $FF and an interrupt will occur as soon as the 
   1556 ;	Program Counter reaches the HALT.	(24 clock cycles)
   1557 
   1558 mark_02B5:
   1559 *DISPLAY_5:*
   1560 	LD	R,A		; (9) Load R from A.	R = slow: $F5 fast: $FC
   1561 
   1562 ;; Original, for 32 column display:
   1563 ;;
   1564 ;;	LD	A,$DD		; (7) load future R value.	$F6	$FD
   1565 ;;
   1566 ;; For other display widths,
   1567 ;; need to count down three instructions then the number of characters
   1568 ;;
   1569 	LD	A,256-3-CHARS_PER_LINE_WINDOW	; (7) load future R value.	$F6	$FD
   1570 
   1571 	EI			; (4) Enable Interrupts		$F7	$FE
   1572 
   1573 	JP	(HL)		; (4) jump to the echo display.	$F8	$FF
   1574 
   1575 ------------------------------------------------------------------------
   1576 
   1577 ; THE *'KEYBOARD SCANNING'* SUBROUTINE
   1578 ------------------------------------------------------------------------
   1579 
   1580 ; The keyboard is read during the vertical sync interval while no video is 
   1581 ; being displayed.	Reading a port with address bit 0 low i.e. $FE starts the 
   1582 ; vertical sync pulse.
   1583 
   1584 mark_02BB:
   1585 *KEYBOARD:*
   1586 	LD	HL,$FFFF	; (16) prepare a buffer to take key.
   1587 	LD	BC,$FEFE	; (20) set BC to port $FEFE. The B register, 
   1588 				;	with its single reset bit also acts as 
   1589 				;	an 8-counter.
   1590 	IN	A,(C)		; (11) read the port - all 16 bits are put on 
   1591 				;	the address bus.	Start VSYNC pulse.
   1592 	OR	$01		; (7)	set the rightmost bit so as to ignore 
   1593 				;	the SHIFT key.
   1594 
   1595 mark_02C5:
   1596 *EACH_LINE:*
   1597 	OR	$E0		; [7] OR %11100000
   1598 	LD	D,A		; [4] transfer to D.
   1599 	CPL			; [4] complement - only bits 4-0 meaningful now.
   1600 	CP	1		; [7] sets carry if A is zero.
   1601 	SBC	A,A		; [4] $FF if $00 else zero.
   1602 	OR	B		; [7] $FF or port FE,FD,FB....
   1603 	AND	L		; [4] unless more than one key, L will still be 
   1604 				;	$FF. if more than one key is pressed then A is 
   1605 				;	now invalid.
   1606 	LD	L,A		; [4] transfer to L.
   1607 
   1608 ; now consider the column identifier.
   1609 
   1610 	LD	A,H		; [4] will be $FF if no previous keys.
   1611 	AND	D		; [4] 111xxxxx
   1612 	LD	H,A		; [4] transfer A to H
   1613 
   1614 ; since only one key may be pressed, H will, if valid, be one of
   1615 ; 11111110, 11111101, 11111011, 11110111, 11101111
   1616 ; reading from the outer column, say Q, to the inner column, say T.
   1617 
   1618 	RLC	B		; [8]	rotate the 8-counter/port address.
   1619 				;	sets carry if more to do.
   1620 	IN	A,(C)		; [10] read another half-row.
   1621 				;	all five bits this time.
   1622 
   1623 	JR	C,EACH_LINE <#EACH_LINE>	; [12](7) loop back, until done, to EACH_LINE
   1624 
   1625 ;	The last row read is SHIFT,Z,X,C,V	for the second time.
   1626 
   1627 	RRA			; (4) test the shift key - carry will be reset
   1628 				;	if the key is pressed.
   1629 	RL	H		; (8) rotate left H picking up the carry giving
   1630 				;	column values -
   1631 				;	$FD, $FB, $F7, $EF, $DF.
   1632 				;	or $FC, $FA, $F6, $EE, $DE if shifted.
   1633 
   1634 ;	We now have H identifying the column and L identifying the row in the
   1635 ;	keyboard matrix.
   1636 
   1637 ;	This is a good time to test if this is an American or British machine.
   1638 ;	The US machine has an extra diode that causes bit 6 of a byte read from
   1639 ;	a port to be reset.
   1640 
   1641 	RLA			; (4) compensate for the shift test.
   1642 	RLA			; (4) rotate bit 7 out.
   1643 	RLA			; (4) test bit 6.
   1644 
   1645 	SBC	A,A		; (4)		$FF or 0 {USA}
   1646 	AND	$18		; (7)		24 or 0
   1647 	ADD	A,31		; (7)		55 or 31
   1648 
   1649 ;	result is either 31 (USA) or 55 (UK) blank lines above and below the TV 
   1650 ;	picture.
   1651 
   1652 	LD	(MARGIN),A	; (13) update system variable MARGIN
   1653 
   1654 	RET			; (10) return
   1655 
   1656 ------------------------------------------------------------------------
   1657 
   1658 ; THE *'SET FAST MODE'* SUBROUTINE
   1659 ------------------------------------------------------------------------
   1660 
   1661 ;
   1662 ;
   1663 
   1664 mark_02E7:
   1665 *SET_FAST:*
   1666 	BIT	7,(IY+CDFLAG-RAMBASE)
   1667 	RET	Z		;
   1668 
   1669 	HALT			; Wait for Interrupt
   1670 	OUT	(IO_PORT_NMI_GEN_OFF),A	;
   1671 	RES	7,(IY+CDFLAG-RAMBASE)
   1672 	RET			; return.
   1673 
   1674 
   1675 ------------------------------------------------------------------------
   1676 
   1677 ; THE *'REPORT_F'*
   1678 ------------------------------------------------------------------------
   1679 
   1680 
   1681 mark_02F4:
   1682 *REPORT_F:*
   1683 	RST	_ERROR_1
   1684 	DEFB	$0E		; Error Report: No Program Name supplied.
   1685 
   1686 ------------------------------------------------------------------------
   1687 
   1688 ; THE *'SAVE COMMAND'* ROUTINE
   1689 ------------------------------------------------------------------------
   1690 
   1691 ;
   1692 ;
   1693 
   1694 mark_02F6:
   1695 *SAVE:*
   1696 	CALL	NAME <#NAME>
   1697 	JR	C,REPORT_F <#REPORT_F>	; back with null name
   1698 
   1699 	EX	DE,HL		;
   1700 
   1701 
   1702 
   1703 
   1704 ;
   1705 ; The next 6 bytes differ
   1706 ;
   1707 #if NOT_BODGED
   1708 ; what ZASM assembled:
   1709 ; 02FC: 11CB12
   1710 	LD	DE,$12CB	; five seconds timing value (4811 decimal)
   1711 ; 02FF: CD460F
   1712 mark_02FF:
   1713 *HEADER:*
   1714 	CALL	BREAK_1 <#BREAK_1>
   1715 
   1716 #else
   1717 ; what the SG ROM disassembled to:
   1718 ;	02FC   ED;FD
   1719 			LDIR			; Patch tape SAVE
   1720 ;	02FE   C3;07;02
   1721 			JP	SLOW_FAST	; to $0207
   1722 ;	0301   0F
   1723 			RRCA
   1724 #endif
   1725 
   1726 
   1727 mark_0302:
   1728 	JR	NC,BREAK_2 <#BREAK_2>
   1729 
   1730 mark_0304:
   1731 *DELAY_1:*
   1732 	DJNZ	DELAY_1 <#DELAY_1>
   1733 
   1734 	DEC	DE		;
   1735 	LD	A,D		;
   1736 	OR	E		;
   1737 	JR	NZ,HEADER <#HEADER>	; back for delay to HEADER
   1738 
   1739 mark_030B:
   1740 *OUT_NAME:*
   1741 	CALL	OUT_BYTE <#OUT_BYTE>
   1742 	BIT	7,(HL)		; test for inverted bit.
   1743 	INC	HL		; address next character of name.
   1744 	JR	Z,OUT_NAME <#OUT_NAME>	; back if not inverted to OUT_NAME
   1745 
   1746 ; now start saving the system variables onwards.
   1747 
   1748 	LD	HL,VERSN	; set start of area to VERSN thereby
   1749 				; preserving RAMTOP etc.
   1750 
   1751 mark_0316:
   1752 *OUT_PROG:*
   1753 	CALL	OUT_BYTE <#OUT_BYTE>
   1754 
   1755 	CALL	LOAD_SAVE <#LOAD_SAVE>	; 			>>
   1756 	JR	OUT_PROG <#OUT_PROG>	; loop back
   1757 
   1758 ------------------------------------------------------------------------
   1759 
   1760 ; THE *'OUT_BYTE'* SUBROUTINE
   1761 ------------------------------------------------------------------------
   1762 
   1763 ; This subroutine outputs a byte a bit at a time to a domestic tape recorder.
   1764 
   1765 mark_031E:
   1766 *OUT_BYTE:*
   1767 	LD	E,(HL)		; fetch byte to be saved.
   1768 	SCF			; set carry flag - as a marker.
   1769 
   1770 mark_0320:
   1771 *EACH_BIT:*
   1772 	RL	E		; C < 76543210 < C
   1773 	RET	Z		; return when the marker bit has passed 
   1774 				; right through.			>>
   1775 
   1776 	SBC	A,A		; $FF if set bit or $00 with no carry.
   1777 	AND	$05		; $05 "  "   "   "  $00
   1778 	ADD	A,$04		; $09 "  "   "   "  $04
   1779 	LD	C,A		; transfer timer to C. a set bit has a longer
   1780 				; pulse than a reset bit.
   1781 
   1782 mark_0329:
   1783 *PULSES:*
   1784 	OUT	(IO_PORT_TAPE),A	; pulse to cassette.
   1785 	LD	B,$23		; set timing constant
   1786 
   1787 mark_032D:
   1788 *DELAY_2:*
   1789 	DJNZ	DELAY_2 <#DELAY_2>		; self-loop
   1790 
   1791 	CALL	BREAK_1 <#BREAK_1>		; test for BREAK key.
   1792 
   1793 mark_0332:
   1794 *BREAK_2:*
   1795 	JR	NC,REPORT_D <#REPORT_D>	; forward with break to REPORT_D
   1796 
   1797 	LD	B,$1E		; set timing value.
   1798 
   1799 mark_0336:
   1800 *DELAY_3:*
   1801 
   1802 	DJNZ	DELAY_3 <#DELAY_3>		; self-loop
   1803 
   1804 	DEC	C		; decrement counter
   1805 	JR	NZ,PULSES <#PULSES>	; loop back
   1806 
   1807 mark_033B:
   1808 *DELAY_4:*
   1809 	AND	A		; clear carry for next bit test.
   1810 	DJNZ	DELAY_4 <#DELAY_4>		; self loop (B is zero - 256)
   1811 
   1812 	JR	EACH_BIT <#EACH_BIT>	; loop back
   1813 
   1814 ------------------------------------------------------------------------
   1815 
   1816 ; THE *'LOAD COMMAND'* ROUTINE
   1817 ------------------------------------------------------------------------
   1818 
   1819 
   1820 mark_0340:
   1821 *LOAD:*
   1822 	CALL	NAME <#NAME>
   1823 
   1824 ; DE points to start of name in RAM.
   1825 
   1826 	RL	D		; pick up carry 
   1827 	RRC	D		; carry now in bit 7.
   1828 
   1829 mark_0347:
   1830 
   1831 
   1832 
   1833 #if NOT_BODGED
   1834 
   1835 *LNEXT_PROG:*
   1836 	CALL	IN_BYTE <#IN_BYTE>
   1837 	JR	LNEXT_PROG <#LNEXT_PROG>	; loop
   1838 
   1839 ------------------------------------------------------------------------
   1840 
   1841 ; THE *'IN_BYTE'* SUBROUTINE
   1842 ------------------------------------------------------------------------
   1843 
   1844 
   1845 mark_034C:
   1846 *IN_BYTE:*
   1847 	LD	C,$01		; prepare an eight counter 00000001.
   1848 
   1849 mark_034E:
   1850 *NEXT_BIT:*
   1851 	LD	B,$00		; set counter to 256
   1852 
   1853 #else
   1854 ; what the SG ROM has:
   1855 ;0347   EB
   1856 			EX DE,HL            ; NEXT-PROG
   1857 ;0348   ED;FC
   1858 			LDIR                ; Patch tape LOAD
   1859 ;034A   C3;07;02
   1860 			JP SLOW_FAST
   1861 ;034D   01;06;00
   1862 			LD BC,6          
   1863 #endif
   1864 
   1865 
   1866 
   1867 
   1868 mark_0350:
   1869 *BREAK_3:*
   1870 	LD	A,$7F		; read the keyboard row 
   1871 	IN	A,(IO_PORT_KEYBOARD_RD)	; with the SPACE key.
   1872 
   1873 	OUT	(IO_PORT_SCREEN),A	; output signal to screen.
   1874 
   1875 	RRA			; test for SPACE pressed.
   1876 	JR	NC,BREAK_4 <#BREAK_4>	; forward if so to BREAK_4
   1877 
   1878 	RLA			; reverse above rotation
   1879 	RLA			; test tape bit.
   1880 	JR	C,GET_BIT <#GET_BIT>	; forward if set to GET_BIT
   1881 
   1882 	DJNZ	BREAK_3 <#BREAK_3>		; loop back
   1883 
   1884 	POP	AF		; drop the return address.
   1885 	CP	D		; ugh.
   1886 
   1887 mark_0361:
   1888 *RESTART:*
   1889 	JP	NC,INITIAL <#INITIAL>	; jump forward to INITIAL if D is zero 
   1890 				; to reset the system
   1891 				; if the tape signal has timed out for example
   1892 				; if the tape is stopped. Not just a simple 
   1893 				; report as some system variables will have
   1894 				; been overwritten.
   1895 
   1896 	LD	H,D		; else transfer the start of name
   1897 	LD	L,E		; to the HL register
   1898 
   1899 mark_0366:
   1900 *IN_NAME:*
   1901 	CALL	IN_BYTE <#IN_BYTE>		; is sort of recursion for name
   1902 				; part. received byte in C.
   1903 	BIT	7,D		; is name the null string ?
   1904 	LD	A,C		; transfer byte to A.
   1905 	JR	NZ,MATCHING <#MATCHING>	; forward with null string
   1906 
   1907 	CP	(HL)		; else compare with string in memory.
   1908 	JR	NZ,LNEXT_PROG <#LNEXT_PROG>	; back with mis-match
   1909 				; (seemingly out of subroutine but return 
   1910 				; address has been dropped).
   1911 
   1912 
   1913 mark_0371:
   1914 *MATCHING:*
   1915 	INC	HL		; address next character of name
   1916 	RLA			; test for inverted bit.
   1917 	JR	NC,IN_NAME <#IN_NAME>	; back if not
   1918 
   1919 ; the name has been matched in full. 
   1920 ; proceed to load the data but first increment the high byte of E_LINE, which
   1921 ; is one of the system variables to be loaded in. Since the low byte is loaded
   1922 ; before the high byte, it is possible that, at the in-between stage, a false
   1923 ; value could cause the load to end prematurely - see	LOAD_SAVE check.
   1924 
   1925 	INC	(IY+E_LINE_hi-RAMBASE)	; increment E_LINE_hi.
   1926 	LD	HL,VERSN	; start loading at VERSN.
   1927 
   1928 mark_037B:
   1929 *IN_PROG:*
   1930 	LD	D,B		; set D to zero as indicator.
   1931 	CALL	IN_BYTE <#IN_BYTE>		; loads a byte
   1932 	LD	(HL),C		; insert assembled byte in memory.
   1933 	CALL	LOAD_SAVE <#LOAD_SAVE>		; 		>>
   1934 	JR	IN_PROG <#IN_PROG>		; loop back
   1935 
   1936 ; ___
   1937 
   1938 ; this branch assembles a full byte before exiting normally
   1939 ; from the IN_BYTE subroutine.
   1940 
   1941 mark_0385:
   1942 *GET_BIT:*
   1943 	PUSH	DE		; save the 
   1944 	LD	E,$94		; timing value.
   1945 
   1946 mark_0388:
   1947 *TRAILER:*
   1948 	LD	B,26		; counter to twenty six.
   1949 
   1950 mark_038A:
   1951 *COUNTER:*
   1952 	DEC	E		; decrement the measuring timer.
   1953 	IN	A,(IO_PORT_KEYBOARD_RD)	; read the tape input
   1954 	RLA			;
   1955 	BIT	7,E		;
   1956 	LD	A,E		;
   1957 	JR	C,TRAILER <#TRAILER>	; loop back with carry to TRAILER
   1958 
   1959 	DJNZ	COUNTER <#COUNTER>
   1960 
   1961 	POP	DE		;
   1962 	JR	NZ,BIT_DONE <#BIT_DONE>
   1963 
   1964 	CP	$56		;
   1965 	JR	NC,NEXT_BIT <#NEXT_BIT>
   1966 
   1967 mark_039C:
   1968 *BIT_DONE:*
   1969 	CCF			; complement carry flag
   1970 	RL	C		;
   1971 	JR	NC,NEXT_BIT <#NEXT_BIT>
   1972 
   1973 	RET			; return with full byte.
   1974 
   1975 ; ___
   1976 
   1977 ; if break is pressed while loading data then perform a reset.
   1978 ; if break pressed while waiting for program on tape then OK to break.
   1979 
   1980 mark_03A2:
   1981 *BREAK_4:*
   1982 	LD	A,D		; transfer indicator to A.
   1983 	AND	A		; test for zero.
   1984 	JR	Z,RESTART <#RESTART>	; back if so
   1985 
   1986 
   1987 mark_03A6:
   1988 *REPORT_D:*
   1989 	RST	_ERROR_1
   1990 	DEFB	$0C		; Error Report: BREAK - CONT repeats
   1991 
   1992 ------------------------------------------------------------------------
   1993 
   1994 ; THE *'PROGRAM NAME'* SUBROUTINE
   1995 ------------------------------------------------------------------------
   1996 
   1997 
   1998 mark_03A8:
   1999 *NAME:*
   2000 	CALL	SCANNING <#SCANNING>
   2001 	LD	A,(FLAGS)	; sv
   2002 	ADD	A,A		;
   2003 	JP	M,REPORT_C <#REPORT_C>
   2004 
   2005 	POP	HL		;
   2006 	RET	NC		;
   2007 
   2008 	PUSH	HL		;
   2009 	CALL	SET_FAST <#SET_FAST>
   2010 	CALL	STK_FETCH <#STK_FETCH>
   2011 	LD	H,D		;
   2012 	LD	L,E		;
   2013 	DEC	C		;
   2014 	RET	M		;
   2015 
   2016 	ADD	HL,BC		;
   2017 	SET	7,(HL)		;
   2018 	RET			;
   2019 
   2020 ------------------------------------------------------------------------
   2021 
   2022 ; THE *'NEW'* COMMAND ROUTINE
   2023 ------------------------------------------------------------------------
   2024 
   2025 
   2026 mark_03C3:
   2027 *NEW:*
   2028 	CALL	SET_FAST <#SET_FAST>
   2029 	LD	BC,(RAMTOP)	; fetch value of system variable RAMTOP
   2030 	DEC	BC		; point to last system byte.
   2031 
   2032 ------------------------------------------------------------------------
   2033 
   2034 ; THE *'RAM CHECK'* ROUTINE
   2035 ------------------------------------------------------------------------
   2036 
   2037 
   2038 mark_03CB:
   2039 *RAM_CHECK:*
   2040 	LD	H,B		;
   2041 	LD	L,C		;
   2042 	LD	A,$3F		;
   2043 
   2044 mark_03CF:
   2045 *RAM_FILL:*
   2046 	LD	(HL),$02	;
   2047 	DEC	HL		;
   2048 	CP	H		;
   2049 	JR	NZ,RAM_FILL <#RAM_FILL>
   2050 
   2051 mark_03D5:
   2052 *RAM_READ:*
   2053 	AND	A		;
   2054 	SBC	HL,BC		;
   2055 	ADD	HL,BC		;
   2056 	INC	HL		;
   2057 	JR	NC,SET_TOP <#SET_TOP>
   2058 
   2059 	DEC	(HL)		;
   2060 	JR	Z,SET_TOP <#SET_TOP>
   2061 
   2062 	DEC	(HL)		;
   2063 	JR	Z,RAM_READ <#RAM_READ>
   2064 
   2065 mark_03E2:
   2066 *SET_TOP:*
   2067 	LD	(RAMTOP),HL	; set system variable RAMTOP to first byte 
   2068 				; above the BASIC system area.
   2069 
   2070 ------------------------------------------------------------------------
   2071 
   2072 ; THE *'INITIALIZATION'* ROUTINE
   2073 ------------------------------------------------------------------------
   2074 
   2075 
   2076 mark_03E5:
   2077 *INITIAL:*
   2078 	LD	HL,(RAMTOP)	; fetch system variable RAMTOP.
   2079 	DEC	HL		; point to last system byte.
   2080 	LD	(HL),$3E	; make GO SUB end-marker $3E - too high for
   2081 				; high order byte of line number.
   2082 				; (was $3F on ZX80)
   2083 	DEC	HL		; point to unimportant low-order byte.
   2084 	LD	SP,HL		; and initialize the stack-pointer to this
   2085 				; location.
   2086 	DEC	HL		; point to first location on the machine stack
   2087 	DEC	HL		; which will be filled by next CALL/PUSH.
   2088 	LD	(ERR_SP),HL	; set the error stack pointer ERR_SP to
   2089 				; the base of the now empty machine stack.
   2090 
   2091 ; Now set the I register so that the video hardware knows where to find the
   2092 ; character set. This ROM only uses the character set when printing to 
   2093 ; the ZX Printer. The TV picture is formed by the external video hardware. 
   2094 ; Consider also, that this 8K ROM can be retro-fitted to the ZX80 instead of 
   2095 ; its original 4K ROM so the video hardware could be on the ZX80.
   2096 
   2097 	LD	A,$1E		; address for this ROM is $1E00.
   2098 	LD	I,A		; set I register from A.
   2099 	IM	1		; select Z80 Interrupt Mode 1.
   2100 
   2101 	LD	IY,ERR_NR	; set IY to the start of RAM so that the 
   2102 				; system variables can be indexed.
   2103 
   2104 	LD	(IY+CDFLAG-RAMBASE),%01000000
   2105 				; Bit 6 indicates Compute and Display required.
   2106 
   2107 	LD	HL,USER_RAM	; The first location after System Variables -
   2108 				; 16509 decimal.
   2109 	LD	(D_FILE),HL	; set system variable D_FILE to this value.
   2110 	LD	B,$19		; prepare minimal screen of 24 NEWLINEs
   2111 				; following an initial NEWLINE.
   2112 
   2113 mark_0408:
   2114 *LINE:*
   2115 	LD	(HL),ZX_NEWLINE	; insert NEWLINE (HALT instruction)
   2116 	INC	HL		; point to next location.
   2117 	DJNZ	LINE <#LINE>		; loop back for all twenty five to LINE
   2118 
   2119 	LD	(VARS),HL	; set system variable VARS to next location
   2120 
   2121 	CALL	CLEAR <#CLEAR>		; sets $80 end-marker and the 
   2122 				; dynamic memory pointers E_LINE, STKBOT and
   2123 				; STKEND.
   2124 
   2125 mark_0413:
   2126 *N_L_ONLY:*
   2127 	CALL	CURSOR_IN <#CURSOR_IN>	; inserts the cursor and 
   2128 				; end-marker in the Edit Line also setting
   2129 				; size of lower display to two lines.
   2130 
   2131 	CALL	SLOW_FAST <#SLOW_FAST>	; selects COMPUTE and DISPLAY
   2132 
   2133 ------------------------------------------------------------------------
   2134 
   2135 ; THE *'BASIC LISTING'* SECTION
   2136 ------------------------------------------------------------------------
   2137 
   2138 
   2139 mark_0419:
   2140 *UPPER:*
   2141 	CALL	CLS <#CLS>
   2142 	LD	HL,(E_PPC)	; sv
   2143 	LD	DE,(S_TOP)	; sv
   2144 	AND	A		;
   2145 	SBC	HL,DE		;
   2146 	EX	DE,HL		;
   2147 	JR	NC,ADDR_TOP <#ADDR_TOP>
   2148 
   2149 	ADD	HL,DE		;
   2150 	LD	(S_TOP),HL	; sv
   2151 
   2152 mark_042D:
   2153 *ADDR_TOP:*
   2154 	CALL	LINE_ADDR <#LINE_ADDR>
   2155 	JR	Z,LIST_TOP <#LIST_TOP>
   2156 
   2157 	EX	DE,HL		;
   2158 
   2159 mark_0433:
   2160 *LIST_TOP:*
   2161 	CALL	LIST_PROG <#LIST_PROG>
   2162 	DEC	(IY+BERG-RAMBASE)
   2163 	JR	NZ,LOWER <#LOWER>
   2164 
   2165 	LD	HL,(E_PPC)	; sv
   2166 	CALL	LINE_ADDR <#LINE_ADDR>
   2167 	LD	HL,(CH_ADD)	; sv
   2168 	SCF			; Set Carry Flag
   2169 	SBC	HL,DE		;
   2170 	LD	HL,S_TOP	; sv
   2171 	JR	NC,INC_LINE <#INC_LINE>
   2172 
   2173 	EX	DE,HL		;
   2174 	LD	A,(HL)		;
   2175 	INC	HL		;
   2176 	LDI			;
   2177 	LD	(DE),A		;
   2178 	JR	UPPER <#UPPER>
   2179 ; ___
   2180 
   2181 mark_0454:
   2182 *DOWN_KEY:*
   2183 
   2184 	LD	HL,E_PPC	; sv
   2185 
   2186 mark_0457:
   2187 *INC_LINE:*
   2188 	LD	E,(HL)		;
   2189 	INC	HL		;
   2190 	LD	D,(HL)		;
   2191 	PUSH	HL		;
   2192 	EX	DE,HL		;
   2193 	INC	HL		;
   2194 	CALL	LINE_ADDR <#LINE_ADDR>
   2195 	CALL	LINE_NUM <#LINE_NUM>
   2196 	POP	HL		;
   2197 
   2198 mark_0464:
   2199 *KEY_INPUT:*
   2200 	BIT	5,(IY+FLAGX-RAMBASE)
   2201 	JR	NZ,LOWER <#LOWER>	; forward
   2202 
   2203 	LD	(HL),D		;
   2204 	DEC	HL		;
   2205 	LD	(HL),E		;
   2206 	JR	UPPER <#UPPER>
   2207 
   2208 ------------------------------------------------------------------------
   2209 
   2210 ; THE *'EDIT LINE COPY'* SECTION
   2211 ------------------------------------------------------------------------
   2212 
   2213 ; This routine sets the edit line to just the cursor when
   2214 ; 1) There is not enough memory to edit a BASIC line.
   2215 ; 2) The edit key is used during input.
   2216 ; The entry point LOWER
   2217 
   2218 
   2219 mark_046F:
   2220 *EDIT_INP:*
   2221 	CALL	CURSOR_IN <#CURSOR_IN>	; sets cursor only edit line.
   2222 
   2223 ; ->
   2224 
   2225 mark_0472:
   2226 *LOWER:*
   2227 	LD	HL,(E_LINE)	; fetch edit line start from E_LINE.
   2228 
   2229 mark_0475:
   2230 *EACH_CHAR:*
   2231 	LD	A,(HL)		; fetch a character from edit line.
   2232 	CP	$7E		; compare to the number marker.
   2233 	JR	NZ,END_LINE <#END_LINE>	; forward if not
   2234 
   2235 	LD	BC,6		; else six invisible bytes to be removed.
   2236 	CALL	RECLAIM_2 <#RECLAIM_2>
   2237 	JR	EACH_CHAR <#EACH_CHAR>	; back
   2238 ; ___
   2239 
   2240 mark_0482:
   2241 *END_LINE:*
   2242 	CP	ZX_NEWLINE		;
   2243 	INC	HL		;
   2244 	JR	NZ,EACH_CHAR <#EACH_CHAR>
   2245 
   2246 mark_0487:
   2247 *EDIT_LINE:*
   2248 	CALL	CURSOR <#CURSOR>		; sets cursor K or L.
   2249 
   2250 mark_048A:
   2251 *EDIT_ROOM:*
   2252 	CALL	LINE_ENDS <#LINE_ENDS>
   2253 	LD	HL,(E_LINE)	; sv
   2254 	LD	(IY+ERR_NR-RAMBASE),$FF
   2255 	CALL	COPY_LINE <#COPY_LINE>
   2256 	BIT	7,(IY+ERR_NR-RAMBASE)
   2257 	JR	NZ,DISPLAY_6 <#DISPLAY_6>
   2258 
   2259 	LD	A,(DF_SZ)	; 
   2260 	CP	CHARS_VERTICAL	; $18 = 24
   2261 	JR	NC,DISPLAY_6 <#DISPLAY_6>
   2262 
   2263 	INC	A		;
   2264 	LD	(DF_SZ),A	; 
   2265 	LD	B,A		;
   2266 	LD	C,1		;
   2267 	CALL	LOC_ADDR <#LOC_ADDR>
   2268 	LD	D,H		;
   2269 	LD	E,L		;
   2270 	LD	A,(HL)		;
   2271 
   2272 mark_04B1:
   2273 *FREE_LINE:*
   2274 	DEC	HL		;
   2275 	CP	(HL)		;
   2276 	JR	NZ,FREE_LINE <#FREE_LINE>
   2277 
   2278 	INC	HL		;
   2279 	EX	DE,HL		;
   2280 	LD	A,(RAMTOP+1)	; sv RAMTOP_hi
   2281 	CP	$4D		;
   2282 	CALL	C,RECLAIM_1 <#RECLAIM_1>
   2283 	JR	EDIT_ROOM <#EDIT_ROOM>
   2284 
   2285 ------------------------------------------------------------------------
   2286 
   2287 ; THE *'WAIT FOR KEY'* SECTION
   2288 ------------------------------------------------------------------------
   2289 
   2290 
   2291 mark_04C1:
   2292 *DISPLAY_6:*
   2293 	LD	HL,$0000	;
   2294 	LD	(X_PTR),HL	; sv
   2295 
   2296 	LD	HL,CDFLAG	; system variable CDFLAG
   2297 
   2298 
   2299 
   2300 
   2301 #if NOT_BODGED
   2302 	BIT	7,(HL)		;
   2303 
   2304 	CALL	Z,DISPLAY_1 <#DISPLAY_1>
   2305 
   2306 mark_04CF:
   2307 *SLOW_DISP:*
   2308 	BIT	0,(HL)		;
   2309 	JR	Z,SLOW_DISP <#SLOW_DISP>
   2310 
   2311 #else
   2312 ;	04CA   D3;00
   2313 			OUT ($00),A         ; PORT 0
   2314 ;	04CC   CB;46
   2315 L04CC:
   2316 			BIT 0,(HL)           
   2317 ;	04CE   28;FC
   2318 			JR Z,L04CC
   2319 ;	04D0   D3;01
   2320 			OUT ($01),A         ; PORT 1
   2321 ;	04D2   00
   2322 			NOP
   2323 
   2324 
   2325 #endif
   2326 
   2327 
   2328 
   2329 
   2330 	LD	BC,(LAST_K)	; sv
   2331 	CALL	DEBOUNCE <#DEBOUNCE>
   2332 	CALL	DECODE <#DECODE>
   2333 
   2334 	JR	NC,LOWER <#LOWER>	; back
   2335 
   2336 ------------------------------------------------------------------------
   2337 
   2338 ; THE *'KEYBOARD DECODING'* SECTION
   2339 ------------------------------------------------------------------------
   2340 
   2341 ;	The decoded key value is in E and HL points to the position in the 
   2342 ;	key table. D contains zero.
   2343 
   2344 mark_04DF:
   2345 *K_DECODE:*
   2346 	LD	A,(MODE)	; Fetch value of system variable MODE
   2347 	DEC	A		; test the three values together
   2348 
   2349 	JP	M,FETCH_2 <#FETCH_2>	; forward, if was zero
   2350 
   2351 	JR	NZ,FETCH_1 <#FETCH_1>	; forward, if was 2
   2352 
   2353 ;	The original value was one and is now zero.
   2354 
   2355 	LD	(MODE),A	; update the system variable MODE
   2356 
   2357 	DEC	E		; reduce E to range $00 - $7F
   2358 	LD	A,E		; place in A
   2359 	SUB	39		; subtract 39 setting carry if range 00 - 38
   2360 	JR	C,FUNC_BASE <#FUNC_BASE>	; forward, if so
   2361 
   2362 	LD	E,A		; else set E to reduced value
   2363 
   2364 mark_04F2:
   2365 *FUNC_BASE:*
   2366 	LD	HL,K_FUNCT <#K_FUNCT>	; address of K_FUNCT table for function keys.
   2367 	JR	TABLE_ADD <#TABLE_ADD>	; forward
   2368 ; ___
   2369 mark_04F7:
   2370 *FETCH_1:*
   2371 	LD	A,(HL)		;
   2372 	CP	ZX_NEWLINE	;
   2373 	JR	Z,K_L_KEY <#K_L_KEY>
   2374 
   2375 	CP	ZX_RND		; $40
   2376 	SET	7,A		;
   2377 	JR	C,ENTER <#ENTER>
   2378 
   2379 	LD	HL,$00C7	; (expr reqd)
   2380 
   2381 mark_0505:
   2382 *TABLE_ADD:*
   2383 	ADD	HL,DE		;
   2384 	JR	FETCH_3 <#FETCH_3>
   2385 
   2386 ; ___
   2387 
   2388 mark_0508:
   2389 *FETCH_2:*
   2390 	LD	A,(HL)		;
   2391 	BIT	2,(IY+FLAGS-RAMBASE)	; K or L mode ?
   2392 	JR	NZ,TEST_CURS <#TEST_CURS>
   2393 
   2394 	ADD	A,$C0		;
   2395 	CP	$E6		;
   2396 	JR	NC,TEST_CURS <#TEST_CURS>
   2397 
   2398 mark_0515:
   2399 *FETCH_3:*
   2400 	LD	A,(HL)		;
   2401 
   2402 mark_0516:
   2403 *TEST_CURS:*
   2404 	CP	$F0		;
   2405 	JP	PE,KEY_SORT <#KEY_SORT>
   2406 
   2407 mark_051B:
   2408 *ENTER:*
   2409 	LD	E,A		;
   2410 	CALL	CURSOR <#CURSOR>
   2411 
   2412 	LD	A,E		;
   2413 	CALL	ADD_CHAR <#ADD_CHAR>
   2414 
   2415 mark_0523:
   2416 *BACK_NEXT:*
   2417 	JP	LOWER <#LOWER>		; back
   2418 
   2419 ------------------------------------------------------------------------
   2420 
   2421 ; THE *'ADD CHARACTER'* SUBROUTINE
   2422 ------------------------------------------------------------------------
   2423 
   2424 mark_0526:
   2425 *ADD_CHAR:*
   2426 	CALL	ONE_SPACE <#ONE_SPACE>
   2427 	LD	(DE),A		;
   2428 	RET			;
   2429 
   2430 ------------------------------------------------------------------------
   2431 
   2432 ; THE *'CURSOR KEYS'* ROUTINE
   2433 ------------------------------------------------------------------------
   2434 
   2435 mark_052B:
   2436 *K_L_KEY:*
   2437 	LD	A,ZX_KL		;
   2438 
   2439 mark_052D:
   2440 *KEY_SORT:*
   2441 	LD	E,A		;
   2442 	LD	HL,$0482	; base address of ED_KEYS (exp reqd)
   2443 	ADD	HL,DE		;
   2444 	ADD	HL,DE		;
   2445 	LD	C,(HL)		;
   2446 	INC	HL		;
   2447 	LD	B,(HL)		;
   2448 	PUSH	BC		;
   2449 
   2450 mark_0537:
   2451 *CURSOR:*
   2452 	LD	HL,(E_LINE)	; sv
   2453 	BIT	5,(IY+FLAGX-RAMBASE)
   2454 	JR	NZ,L_MODE <#L_MODE>
   2455 
   2456 mark_0540:
   2457 *K_MODE:*
   2458 	RES	2,(IY+FLAGS-RAMBASE)	; Signal use K mode
   2459 
   2460 mark_0544:
   2461 *TEST_CHAR:*
   2462 	LD	A,(HL)		;
   2463 	CP	ZX_CURSOR	;
   2464 	RET	Z		; return
   2465 
   2466 	INC	HL		;
   2467 	CALL	NUMBER <#NUMBER>
   2468 	JR	Z,TEST_CHAR <#TEST_CHAR>
   2469 
   2470 	CP	ZX_A		; $26
   2471 	JR	C,TEST_CHAR <#TEST_CHAR>
   2472 
   2473 	CP	$DE		; ZX_THEN ??
   2474 	JR	Z,K_MODE <#K_MODE>
   2475 
   2476 mark_0556:
   2477 *L_MODE:*
   2478 	SET	2,(IY+FLAGS-RAMBASE)	; Signal use L mode
   2479 	JR	TEST_CHAR <#TEST_CHAR>
   2480 
   2481 ------------------------------------------------------------------------
   2482 
   2483 ; THE *'CLEAR_ONE'* SUBROUTINE
   2484 ------------------------------------------------------------------------
   2485 
   2486 mark_055C:
   2487 *CLEAR_ONE:*
   2488 	LD	BC,$0001	;
   2489 	JP	RECLAIM_2 <#RECLAIM_2>
   2490 
   2491 ------------------------------------------------------------------------
   2492 
   2493 ; THE *'EDITING KEYS'* TABLE
   2494 ------------------------------------------------------------------------
   2495 
   2496 mark_0562:
   2497 *ED_KEYS:*
   2498 	DEFW	UP_KEY <#UP_KEY>
   2499 	DEFW	DOWN_KEY <#DOWN_KEY>
   2500 	DEFW	LEFT_KEY <#LEFT_KEY>
   2501 	DEFW	RIGHT_KEY <#RIGHT_KEY>
   2502 	DEFW	FUNCTION <#FUNCTION>
   2503 	DEFW	EDIT_KEY <#EDIT_KEY>
   2504 	DEFW	N_L_KEY <#N_L_KEY>
   2505 	DEFW	RUBOUT <#RUBOUT>
   2506 	DEFW	FUNCTION <#FUNCTION>
   2507 	DEFW	FUNCTION <#FUNCTION>
   2508 
   2509 
   2510 ------------------------------------------------------------------------
   2511 
   2512 ; THE *'CURSOR LEFT'* ROUTINE
   2513 ------------------------------------------------------------------------
   2514 
   2515 ;
   2516 ;
   2517 
   2518 mark_LEFT_KEY:
   2519 *LEFT_KEY:*
   2520 	CALL	LEFT_EDGE <#LEFT_EDGE>
   2521 	LD	A,(HL)		;
   2522 	LD	(HL),ZX_CURSOR	;
   2523 	INC	HL		;
   2524 	JR	GET_CODE <#GET_CODE>
   2525 
   2526 ------------------------------------------------------------------------
   2527 
   2528 ; THE *'CURSOR RIGHT'* ROUTINE
   2529 ------------------------------------------------------------------------
   2530 
   2531 
   2532 mark_RIGHT_KEY:
   2533 *RIGHT_KEY:*
   2534 	INC	HL		;
   2535 	LD	A,(HL)		;
   2536 	CP	ZX_NEWLINE		;
   2537 	JR	Z,ENDED_2 <#ENDED_2>
   2538 
   2539 	LD	(HL),ZX_CURSOR	;
   2540 	DEC	HL		;
   2541 
   2542 mark_0588:
   2543 *GET_CODE:*
   2544 	LD	(HL),A		;
   2545 
   2546 mark_0589:
   2547 *ENDED_1:*
   2548 	JR	BACK_NEXT <#BACK_NEXT>
   2549 
   2550 ------------------------------------------------------------------------
   2551 
   2552 ; THE *'RUBOUT'* ROUTINE
   2553 ------------------------------------------------------------------------
   2554 
   2555 
   2556 mark_058B:
   2557 *RUBOUT:*
   2558 	CALL	LEFT_EDGE <#LEFT_EDGE>
   2559 	CALL	CLEAR_ONE <#CLEAR_ONE>
   2560 	JR	ENDED_1 <#ENDED_1>
   2561 
   2562 ------------------------------------------------------------------------
   2563 
   2564 ; THE *'ED_EDGE'* SUBROUTINE
   2565 ------------------------------------------------------------------------
   2566 
   2567 ;
   2568 ;
   2569 
   2570 mark_0593:
   2571 *LEFT_EDGE:*
   2572 	DEC	HL		;
   2573 	LD	DE,(E_LINE)	; sv
   2574 	LD	A,(DE)		;
   2575 	CP	ZX_CURSOR	;
   2576 	RET	NZ		;
   2577 
   2578 	POP	DE		;
   2579 
   2580 mark_059D:
   2581 *ENDED_2:*
   2582 	JR	ENDED_1 <#ENDED_1>
   2583 
   2584 ------------------------------------------------------------------------
   2585 
   2586 ; THE *'CURSOR UP'* ROUTINE
   2587 ------------------------------------------------------------------------
   2588 
   2589 ;
   2590 ;
   2591 
   2592 mark_059F:
   2593 *UP_KEY:*
   2594 	LD	HL,(E_PPC)	; sv
   2595 	CALL	LINE_ADDR <#LINE_ADDR>
   2596 	EX	DE,HL		;
   2597 	CALL	LINE_NUM <#LINE_NUM>
   2598 	LD	HL,E_PPC+1	; point to system variable E_PPC_hi
   2599 	JP	KEY_INPUT <#KEY_INPUT>	; jump back
   2600 
   2601 ------------------------------------------------------------------------
   2602 
   2603 ; THE *'FUNCTION KEY'* ROUTINE
   2604 ------------------------------------------------------------------------
   2605 
   2606 ;
   2607 ;
   2608 
   2609 mark_FUNCTION:
   2610 *FUNCTION:*
   2611 	LD	A,E		;
   2612 	AND	$07		;
   2613 	LD	(MODE),A	; sv
   2614 	JR	ENDED_2 <#ENDED_2>		; back
   2615 
   2616 ------------------------------------------------------------------------
   2617 
   2618 ; THE *'COLLECT LINE NUMBER'* SUBROUTINE
   2619 ------------------------------------------------------------------------
   2620 
   2621 mark_05B7:
   2622 *ZERO_DE:*
   2623 	EX	DE,HL		;
   2624 	LD	DE,DISPLAY_6 <#DISPLAY_6> + 1	; $04C2 - a location addressing two zeros.
   2625 
   2626 ; ->
   2627 
   2628 mark_05BB:
   2629 *LINE_NUM:*
   2630 	LD	A,(HL)		;
   2631 	AND	$C0		;
   2632 	JR	NZ,ZERO_DE <#ZERO_DE>
   2633 
   2634 	LD	D,(HL)		;
   2635 	INC	HL		;
   2636 	LD	E,(HL)		;
   2637 	RET			;
   2638 
   2639 ------------------------------------------------------------------------
   2640 
   2641 ; THE *'EDIT KEY'* ROUTINE
   2642 ------------------------------------------------------------------------
   2643 
   2644 
   2645 mark_EDIT_KEY:
   2646 *EDIT_KEY:*
   2647 	CALL	LINE_ENDS <#LINE_ENDS>	; clears lower display.
   2648 
   2649 	LD	HL,EDIT_INP <#EDIT_INP>	; Address: EDIT_INP
   2650 	PUSH	HL		; ** is pushed as an error looping address.
   2651 
   2652 	BIT	5,(IY+FLAGX-RAMBASE)	; test FLAGX
   2653 	RET	NZ		; indirect jump if in input mode
   2654 				; to EDIT_INP <#EDIT_INP> (begin again).
   2655 
   2656 ;
   2657 
   2658 	LD	HL,(E_LINE)	; fetch E_LINE
   2659 	LD	(DF_CC),HL	; and use to update the screen cursor DF_CC
   2660 
   2661 ; so now RST $10 will print the line numbers to the edit line instead of screen.
   2662 ; first make sure that no newline/out of screen can occur while sprinting the
   2663 ; line numbers to the edit line.
   2664 
   2665 				; prepare line 0, column 0.
   2666 
   2667 	LD	HL,256*CHARS_VERTICAL + CHARS_HORIZONTAL + 1
   2668 ;
   2669 	LD	(S_POSN),HL	; update S_POSN with these dummy values.
   2670 
   2671 	LD	HL,(E_PPC)	; fetch current line from E_PPC may be a 
   2672 				; non-existent line e.g. last line deleted.
   2673 	CALL	LINE_ADDR <#LINE_ADDR>	; gets address or that of
   2674 				; the following line.
   2675 	CALL	LINE_NUM <#LINE_NUM>	; gets line number if any in DE
   2676 				; leaving HL pointing at second low byte.
   2677 
   2678 	LD	A,D		; test the line number for zero.
   2679 	OR	E		;
   2680 	RET	Z		; return if no line number - no program to edit.
   2681 
   2682 	DEC	HL		; point to high byte.
   2683 	CALL	OUT_NO <#OUT_NO>		; writes number to edit line.
   2684 
   2685 	INC	HL		; point to length bytes.
   2686 	LD	C,(HL)		; low byte to C.
   2687 	INC	HL		;
   2688 	LD	B,(HL)		; high byte to B.
   2689 
   2690 	INC	HL		; point to first character in line.
   2691 	LD	DE,(DF_CC)	; fetch display file cursor DF_CC
   2692 
   2693 	LD	A,ZX_CURSOR	; prepare the cursor character.
   2694 	LD	(DE),A		; and insert in edit line.
   2695 	INC	DE		; increment intended destination.
   2696 
   2697 	PUSH	HL		; * save start of BASIC.
   2698 
   2699 	LD	HL,29		; set an overhead of 29 bytes.
   2700 	ADD	HL,DE		; add in the address of cursor.
   2701 	ADD	HL,BC		; add the length of the line.
   2702 	SBC	HL,SP		; subtract the stack pointer.
   2703 
   2704 	POP	HL		; * restore pointer to start of BASIC.
   2705 
   2706 	RET	NC		; return if not enough room to EDIT_INP EDIT_INP.
   2707 				; the edit key appears not to work.
   2708 
   2709 	LDIR			; else copy bytes from program to edit line.
   2710 				; Note. hidden floating point forms are also
   2711 				; copied to edit line.
   2712 
   2713 	EX	DE,HL		; transfer free location pointer to HL
   2714 
   2715 	POP	DE		; ** remove address EDIT_INP from stack.
   2716 
   2717 	CALL	SET_STK_B <#SET_STK_B>	; sets STKEND from HL.
   2718 
   2719 	JR	ENDED_2 <#ENDED_2>		; back to ENDED_2 and after 3 more jumps
   2720 				; to LOWER <#LOWER>, LOWER.
   2721 				; Note. The LOWER routine removes the hidden 
   2722 				; floating-point numbers from the edit line.
   2723 
   2724 ------------------------------------------------------------------------
   2725 
   2726 ; THE *'NEWLINE KEY'* ROUTINE
   2727 ------------------------------------------------------------------------
   2728 
   2729 
   2730 mark_060C:
   2731 *N_L_KEY:*
   2732 	CALL	LINE_ENDS <#LINE_ENDS>
   2733 
   2734 	LD	HL,LOWER <#LOWER>	; prepare address: LOWER
   2735 
   2736 	BIT	5,(IY+FLAGX-RAMBASE)
   2737 	JR	NZ,NOW_SCAN <#NOW_SCAN>
   2738 
   2739 	LD	HL,(E_LINE)	; sv
   2740 	LD	A,(HL)		;
   2741 	CP	$FF		;
   2742 	JR	Z,STK_UPPER <#STK_UPPER>
   2743 
   2744 	CALL	CLEAR_PRB <#CLEAR_PRB>
   2745 	CALL	CLS <#CLS>
   2746 
   2747 mark_0626:
   2748 *STK_UPPER:*
   2749 	LD	HL,UPPER <#UPPER>	; Address: UPPER
   2750 
   2751 mark_0629:
   2752 *NOW_SCAN:*
   2753 	PUSH	HL		; push routine address (LOWER or UPPER).
   2754 	CALL	LINE_SCAN <#LINE_SCAN>
   2755 	POP	HL		;
   2756 	CALL	CURSOR <#CURSOR>
   2757 	CALL	CLEAR_ONE <#CLEAR_ONE>
   2758 	CALL	E_LINE_NUM <#E_LINE_NUM>
   2759 	JR	NZ,N_L_INP <#N_L_INP>
   2760 
   2761 	LD	A,B		;
   2762 	OR	C		;
   2763 	JP	NZ,N_L_LINE <#N_L_LINE>
   2764 
   2765 	DEC	BC		;
   2766 	DEC	BC		;
   2767 	LD	(PPC),BC	; sv
   2768 	LD	(IY+DF_SZ-RAMBASE),2
   2769 	LD	DE,(D_FILE)	; sv
   2770 
   2771 	JR	TEST_NULL <#TEST_NULL>	; forward
   2772 
   2773 ; ___
   2774 
   2775 mark_064E:
   2776 *N_L_INP:*
   2777 	CP	ZX_NEWLINE	;
   2778 	JR	Z,N_L_NULL <#N_L_NULL>
   2779 
   2780 	LD	BC,(T_ADDR)	; 
   2781 	CALL	LOC_ADDR <#LOC_ADDR>
   2782 	LD	DE,(NXTLIN)	; 
   2783 	LD	(IY+DF_SZ-RAMBASE),2
   2784 
   2785 mark_0661:
   2786 *TEST_NULL:*
   2787 	RST	_GET_CHAR
   2788 	CP	ZX_NEWLINE	;
   2789 
   2790 mark_0664:
   2791 *N_L_NULL:*
   2792 	JP	Z,N_L_ONLY <#N_L_ONLY>
   2793 
   2794 	LD	(IY+FLAGS-RAMBASE),$80
   2795 	EX	DE,HL		;
   2796 
   2797 mark_066C:
   2798 *NEXT_LINE:*
   2799 	LD	(NXTLIN),HL	; 
   2800 	EX	DE,HL		;
   2801 	CALL	TEMP_PTR2 <#TEMP_PTR2>
   2802 	CALL	LINE_RUN <#LINE_RUN>
   2803 	RES	1,(IY+FLAGS-RAMBASE)	; Signal printer not in use
   2804 	LD	A,$C0		;
   2805 ;;	LD	(IY+X_PTR_lo-RAMBASE),A		;; ERROR IN htm SOURCE! IY+$19 is X_PTR_hi
   2806 	LD	(IY+X_PTR_hi-RAMBASE),A
   2807 	CALL	X_TEMP <#X_TEMP>
   2808 	RES	5,(IY+FLAGX-RAMBASE)
   2809 	BIT	7,(IY+ERR_NR-RAMBASE)
   2810 	JR	Z,STOP_LINE <#STOP_LINE>
   2811 
   2812 	LD	HL,(NXTLIN)	;
   2813 	AND	(HL)		;
   2814 	JR	NZ,STOP_LINE <#STOP_LINE>
   2815 
   2816 	LD	D,(HL)		;
   2817 	INC	HL		;
   2818 	LD	E,(HL)		;
   2819 	LD	(PPC),DE	;
   2820 	INC	HL		;
   2821 	LD	E,(HL)		;
   2822 	INC	HL		;
   2823 	LD	D,(HL)		;
   2824 	INC	HL		;
   2825 	EX	DE,HL		;
   2826 	ADD	HL,DE		;
   2827 	CALL	BREAK_1 <#BREAK_1>
   2828 	JR	C,NEXT_LINE <#NEXT_LINE>
   2829 
   2830 	LD	HL,ERR_NR
   2831 	BIT	7,(HL)
   2832 	JR	Z,STOP_LINE <#STOP_LINE>
   2833 
   2834 	LD	(HL),$0C
   2835 
   2836 mark_06AE:
   2837 *STOP_LINE:*
   2838 	BIT	7,(IY+PR_CC-RAMBASE)
   2839 	CALL	Z,COPY_BUFF <#COPY_BUFF>
   2840 ;
   2841 #if 0
   2842 	LD	BC,$0121	;
   2843 #else
   2844 	LD	BC,256*1 + CHARS_HORIZONTAL + 1
   2845 #endif
   2846 ;
   2847 ;
   2848 	CALL	LOC_ADDR <#LOC_ADDR>
   2849 	LD	A,(ERR_NR)
   2850 	LD	BC,(PPC)
   2851 	INC	A
   2852 	JR	Z,REPORT <#REPORT>
   2853 
   2854 	CP	$09
   2855 	JR	NZ,CONTINUE <#CONTINUE>
   2856 
   2857 	INC	BC
   2858 
   2859 mark_06CA:
   2860 *CONTINUE:*
   2861 	LD	(OLDPPC),BC	;
   2862 	JR	NZ,REPORT <#REPORT>
   2863 
   2864 	DEC	BC		;
   2865 
   2866 mark_06D1:
   2867 *REPORT:*
   2868 	CALL	OUT_CODE <#OUT_CODE>
   2869 	LD	A,ZX_SLASH
   2870 
   2871 	RST	_PRINT_A
   2872 	CALL	OUT_NUM <#OUT_NUM>
   2873 	CALL	CURSOR_IN <#CURSOR_IN>
   2874 	JP	DISPLAY_6 <#DISPLAY_6>
   2875 
   2876 ; ___
   2877 
   2878 mark_06E0:
   2879 *N_L_LINE:*
   2880 	LD	(E_PPC),BC	;
   2881 	LD	HL,(CH_ADD)	;
   2882 	EX	DE,HL		;
   2883 	LD	HL,N_L_ONLY <#N_L_ONLY>
   2884 	PUSH	HL		;
   2885 	LD	HL,(STKBOT)	;
   2886 	SBC	HL,DE		;
   2887 	PUSH	HL		;
   2888 	PUSH	BC		;
   2889 	CALL	SET_FAST <#SET_FAST>
   2890 	CALL	CLS <#CLS>
   2891 	POP	HL		;
   2892 	CALL	LINE_ADDR <#LINE_ADDR>
   2893 	JR	NZ,COPY_OVER <#COPY_OVER>
   2894 
   2895 	CALL	NEXT_ONE <#NEXT_ONE>
   2896 	CALL	RECLAIM_2 <#RECLAIM_2>
   2897 
   2898 mark_0705:
   2899 *COPY_OVER:*
   2900 	POP	BC		;
   2901 	LD	A,C		;
   2902 	DEC	A		;
   2903 	OR	B		;
   2904 	RET	Z		;
   2905 
   2906 	PUSH	BC		;
   2907 	INC	BC		;
   2908 	INC	BC		;
   2909 	INC	BC		;
   2910 	INC	BC		;
   2911 	DEC	HL		;
   2912 	CALL	MAKE_ROOM <#MAKE_ROOM>
   2913 	CALL	SLOW_FAST <#SLOW_FAST>
   2914 	POP	BC		;
   2915 	PUSH	BC		;
   2916 	INC	DE		;
   2917 	LD	HL,(STKBOT)	;
   2918 	DEC	HL		;
   2919 	LDDR			; copy bytes
   2920 	LD	HL,(E_PPC)	;
   2921 	EX	DE,HL		;
   2922 	POP	BC		;
   2923 	LD	(HL),B		;
   2924 	DEC	HL		;
   2925 	LD	(HL),C		;
   2926 	DEC	HL		;
   2927 	LD	(HL),E		;
   2928 	DEC	HL		;
   2929 	LD	(HL),D		;
   2930 
   2931 	RET			; return.
   2932 
   2933 ------------------------------------------------------------------------
   2934 
   2935 ; THE *'LIST'* AND 'LLIST' COMMAND ROUTINES
   2936 ------------------------------------------------------------------------
   2937 
   2938 
   2939 mark_072C:
   2940 *LLIST:*
   2941 	SET	1,(IY+FLAGS-RAMBASE)	; signal printer in use
   2942 
   2943 mark_0730:
   2944 *LIST:*
   2945 	CALL	FIND_INT <#FIND_INT>
   2946 
   2947 	LD	A,B		; fetch high byte of user-supplied line number.
   2948 	AND	$3F		; and crudely limit to range 1-16383.
   2949 
   2950 	LD	H,A		;
   2951 	LD	L,C		;
   2952 	LD	(E_PPC),HL	;
   2953 	CALL	LINE_ADDR <#LINE_ADDR>
   2954 
   2955 mark_073E:
   2956 *LIST_PROG:*
   2957 	LD	E,$00		;
   2958 
   2959 mark_0740:
   2960 *UNTIL_END:*
   2961 	CALL	OUT_LINE <#OUT_LINE>	; lists one line of BASIC
   2962 				; making an early return when the screen is
   2963 				; full or the end of program is reached.
   2964 	JR	UNTIL_END <#UNTIL_END>	; loop back to UNTIL_END
   2965 
   2966 ------------------------------------------------------------------------
   2967 
   2968 ; THE *'PRINT A BASIC LINE'* SUBROUTINE
   2969 ------------------------------------------------------------------------
   2970 
   2971 
   2972 mark_0745:
   2973 *OUT_LINE:*
   2974 	LD	BC,(E_PPC)	; sv
   2975 	CALL	CP_LINES <#CP_LINES>
   2976 	LD	D,$92		;
   2977 	JR	Z,TEST_END <#TEST_END>
   2978 
   2979 	LD	DE,$0000	;
   2980 	RL	E		;
   2981 
   2982 mark_0755:
   2983 *TEST_END:*
   2984 	LD	(IY+BERG-RAMBASE),E
   2985 	LD	A,(HL)		;
   2986 	CP	$40		;
   2987 	POP	BC		;
   2988 	RET	NC		;
   2989 
   2990 	PUSH	BC		;
   2991 	CALL	OUT_NO <#OUT_NO>
   2992 	INC	HL		;
   2993 	LD	A,D		;
   2994 
   2995 	RST	_PRINT_A
   2996 	INC	HL		;
   2997 	INC	HL		;
   2998 
   2999 mark_0766:
   3000 *COPY_LINE:*
   3001 	LD	(CH_ADD),HL	;
   3002 	SET	0,(IY+FLAGS-RAMBASE)	; Suppress leading space
   3003 
   3004 mark_076D:
   3005 *MORE_LINE:*
   3006 	LD	BC,(X_PTR)	;
   3007 	LD	HL,(CH_ADD)	;
   3008 	AND	A		;
   3009 	SBC	HL,BC		;
   3010 	JR	NZ,TEST_NUM <#TEST_NUM>
   3011 
   3012 	LD	A,ZX_INV_S	; $B8	; 
   3013 
   3014 	RST	_PRINT_A
   3015 
   3016 mark_077C:
   3017 *TEST_NUM:*
   3018 	LD	HL,(CH_ADD)	;
   3019 	LD	A,(HL)		;
   3020 	INC	HL		;
   3021 	CALL	NUMBER <#NUMBER>
   3022 	LD	(CH_ADD),HL	;
   3023 	JR	Z,MORE_LINE <#MORE_LINE>
   3024 
   3025 	CP	ZX_CURSOR	;
   3026 	JR	Z,OUT_CURS <#OUT_CURS>
   3027 
   3028 	CP	ZX_NEWLINE		;
   3029 	JR	Z,OUT_CH <#OUT_CH>
   3030 
   3031 	BIT	6,A		;
   3032 	JR	Z,NOT_TOKEN <#NOT_TOKEN>
   3033 
   3034 	CALL	TOKENS <#TOKENS>
   3035 	JR	MORE_LINE <#MORE_LINE>
   3036 ; ___
   3037 
   3038 mark_079A:
   3039 *NOT_TOKEN:*
   3040 	RST	_PRINT_A
   3041 	JR	MORE_LINE <#MORE_LINE>
   3042 ; ___
   3043 
   3044 mark_079D:
   3045 *OUT_CURS:*
   3046 	LD	A,(MODE)	; Fetch value of system variable MODE
   3047 	LD	B,$AB		; Prepare an inverse [F] for function cursor.
   3048 
   3049 	AND	A		; Test for zero -
   3050 	JR	NZ,FLAGS_2 <#FLAGS_2>	; forward if not to FLAGS_2
   3051 
   3052 	LD	A,(FLAGS)	; Fetch system variable FLAGS.
   3053 	LD	B,ZX_INV_K	; Prepare an inverse [K] for keyword cursor.
   3054 
   3055 mark_07AA:
   3056 *FLAGS_2:*
   3057 	RRA			; 00000?00 -> 000000?0
   3058 	RRA			; 000000?0 -> 0000000?
   3059 	AND	$01		; 0000000?	0000000x
   3060 
   3061 	ADD	A,B		; Possibly [F] -> [G]	or	[K] -> [L]
   3062 
   3063 	CALL	PRINT_SP <#PRINT_SP>
   3064 	JR	MORE_LINE <#MORE_LINE>
   3065 
   3066 ------------------------------------------------------------------------
   3067 
   3068 ; THE *'NUMBER'* SUBROUTINE
   3069 ------------------------------------------------------------------------
   3070 
   3071 
   3072 mark_07B4:
   3073 *NUMBER:*
   3074 	CP	$7E		;
   3075 	RET	NZ		;
   3076 
   3077 	INC	HL		;
   3078 	INC	HL		;
   3079 	INC	HL		;
   3080 	INC	HL		;
   3081 	INC	HL		;
   3082 	RET			;
   3083 
   3084 ------------------------------------------------------------------------
   3085 
   3086 ; THE *'KEYBOARD DECODE'* SUBROUTINE
   3087 ------------------------------------------------------------------------
   3088 
   3089 
   3090 mark_07BD:
   3091 *DECODE:*
   3092 	LD	D,0		;
   3093 	SRA	B		; shift bit from B to Carry
   3094 	SBC	A,A		; A = 0 - Carry
   3095 	OR	$26		; %00100110
   3096 	LD	L,5		;
   3097 	SUB	L		;
   3098 
   3099 mark_07C7:
   3100 *KEY_LINE:*
   3101 	ADD	A,L		;
   3102 	SCF			; Set Carry Flag
   3103 	RR	C		;
   3104 	JR	C,KEY_LINE <#KEY_LINE>
   3105 
   3106 	INC	C		;
   3107 	RET	NZ		;
   3108 
   3109 	LD	C,B		;
   3110 	DEC	L		;
   3111 	LD	L,1		;
   3112 	JR	NZ,KEY_LINE <#KEY_LINE>
   3113 
   3114 	LD	HL,$007D	; (expr reqd)
   3115 	LD	E,A		;
   3116 	ADD	HL,DE		;
   3117 	SCF			; Set Carry Flag
   3118 	RET			;
   3119 
   3120 ------------------------------------------------------------------------
   3121 
   3122 ; THE *'PRINTING'* SUBROUTINE
   3123 ------------------------------------------------------------------------
   3124 
   3125 
   3126 mark_07DC:
   3127 *LEAD_SP:*
   3128 	LD	A,E		;
   3129 	AND	A		;
   3130 	RET	M		;
   3131 
   3132 	JR	PRINT_CH <#PRINT_CH>
   3133 
   3134 ; ___
   3135 ; HL is typically -10000, -1000, -100, -10 
   3136 ; and repeatedly subtracted from BC
   3137 ; i.e. it print
   3138 ;
   3139 ;
   3140 mark_07E1:
   3141 *OUT_DIGIT:*
   3142 	XOR	A		; assume the digit is zero to begin with
   3143 
   3144 mark_07E2:
   3145 *DIGIT_INC:*
   3146 	ADD	HL,BC		; HL += -ve number
   3147 	INC	A		;
   3148 	JR	C,DIGIT_INC <#DIGIT_INC>	; loop
   3149 
   3150 	SBC	HL,BC		; undo last iteration
   3151 	DEC	A		; undo last iteration
   3152 	JR	Z,LEAD_SP <#LEAD_SP>	; leading zeros shown as spaces
   3153 
   3154 mark_07EB:
   3155 *OUT_CODE:*
   3156 	LD	E,ZX_0		; $1C
   3157 	ADD	A,E		;
   3158 
   3159 mark_07EE:
   3160 *OUT_CH:*
   3161 	AND	A		;
   3162 	JR	Z,PRINT_SP <#PRINT_SP>
   3163 
   3164 mark_07F1:
   3165 *PRINT_CH:*
   3166 	RES	0,(IY+FLAGS-RAMBASE)	; signal leading space permitted
   3167 
   3168 mark_07F5:
   3169 *PRINT_SP:*
   3170 	EXX			;
   3171 	PUSH	HL		;
   3172 	BIT	1,(IY+FLAGS-RAMBASE)	; is printer in use ?
   3173 	JR	NZ,LPRINT_A <#LPRINT_A>
   3174 
   3175 	CALL	ENTER_CH <#ENTER_CH>
   3176 	JR	PRINT_EXX <#PRINT_EXX>
   3177 
   3178 ; ___
   3179 
   3180 mark_0802:
   3181 *LPRINT_A:*
   3182 	CALL	LPRINT_CH <#LPRINT_CH>
   3183 
   3184 mark_0805:
   3185 *PRINT_EXX:*
   3186 	POP	HL		;
   3187 	EXX			;
   3188 	RET			;
   3189 
   3190 ; ___
   3191 
   3192 mark_0808:
   3193 *ENTER_CH:*
   3194 	LD	D,A		;
   3195 	LD	BC,(S_POSN)	;
   3196 	LD	A,C		;
   3197 	CP	CHARS_HORIZONTAL+1	;
   3198 	JR	Z,TEST_LOW <#TEST_LOW>
   3199 
   3200 mark_0812:
   3201 *TEST_N_L:*
   3202 	LD	A,ZX_NEWLINE		;
   3203 	CP	D		;
   3204 	JR	Z,WRITE_N_L <#WRITE_N_L>
   3205 
   3206 	LD	HL,(DF_CC)	;
   3207 	CP	(HL)		;
   3208 	LD	A,D		;
   3209 	JR	NZ,WRITE_CH <#WRITE_CH>
   3210 
   3211 	DEC	C		;
   3212 	JR	NZ,EXPAND_1 <#EXPAND_1>
   3213 
   3214 	INC	HL			;
   3215 	LD	(DF_CC),HL		;
   3216 	LD	C,CHARS_HORIZONTAL+1	; $21 = 33 normally
   3217 	DEC	B			;
   3218 	LD	(S_POSN),BC		;
   3219 
   3220 mark_082C:
   3221 *TEST_LOW:*
   3222 	LD	A,B		;
   3223 	CP	(IY+DF_SZ-RAMBASE)
   3224 	JR	Z,REPORT_5 <#REPORT_5>
   3225 
   3226 	AND	A		;
   3227 	JR	NZ,TEST_N_L <#TEST_N_L>
   3228 
   3229 mark_0835:
   3230 *REPORT_5:*
   3231 	LD	L,4		; 'No more room on screen'
   3232 	JP	ERROR_3 <#ERROR_3>
   3233 
   3234 ; ___
   3235 
   3236 mark_083A:
   3237 *EXPAND_1:*
   3238 	CALL	ONE_SPACE <#ONE_SPACE>
   3239 	EX	DE,HL		;
   3240 
   3241 mark_083E:
   3242 *WRITE_CH:*
   3243 	LD	(HL),A		;
   3244 	INC	HL		;
   3245 	LD	(DF_CC),HL	;
   3246 	DEC	(IY+S_POSN_x-RAMBASE)
   3247 	RET			;
   3248 
   3249 ; ___
   3250 
   3251 mark_0847:
   3252 *WRITE_N_L:*
   3253 	LD	C,CHARS_HORIZONTAL+1	; $21 = 33
   3254 	DEC	B		;
   3255 	SET	0,(IY+FLAGS-RAMBASE)	; Suppress leading space
   3256 	JP	LOC_ADDR <#LOC_ADDR>
   3257 
   3258 ------------------------------------------------------------------------
   3259 
   3260 ; THE *'LPRINT_CH'* SUBROUTINE
   3261 ------------------------------------------------------------------------
   3262 
   3263 ; This routine sends a character to the ZX-Printer placing the code for the
   3264 ; character in the Printer Buffer.
   3265 ; Note. PR_CC contains the low byte of the buffer address. The high order byte 
   3266 ; is always constant. 
   3267 
   3268 
   3269 mark_0851:
   3270 *LPRINT_CH:*
   3271 	CP	ZX_NEWLINE	; compare to NEWLINE.
   3272 	JR	Z,COPY_BUFF <#COPY_BUFF>	; forward if so
   3273 
   3274 	LD	C,A		; take a copy of the character in C.
   3275 	LD	A,(PR_CC)	; fetch print location from PR_CC
   3276 	AND	$7F		; ignore bit 7 to form true position.
   3277 	CP	$5C		; compare to 33rd location
   3278 
   3279 	LD	L,A		; form low-order byte.
   3280 	LD	H,$40		; the high-order byte is fixed.
   3281 
   3282 	CALL	Z,COPY_BUFF <#COPY_BUFF>	; to send full buffer to 
   3283 				; the printer if first 32 bytes full.
   3284 				; (this will reset HL to start.)
   3285 
   3286 	LD	(HL),C		; place character at location.
   3287 	INC	L		; increment - will not cross a 256 boundary.
   3288 	LD	(IY+PR_CC-RAMBASE),L	; update system variable PR_CC
   3289 				; automatically resetting bit 7 to show that
   3290 				; the buffer is not empty.
   3291 	RET			; return.
   3292 
   3293 ------------------------------------------------------------------------
   3294 
   3295 ; THE *'COPY'* COMMAND ROUTINE
   3296 ------------------------------------------------------------------------
   3297 
   3298 ; The full character-mapped screen is copied to the ZX-Printer.
   3299 ; All twenty-four text/graphic lines are printed.
   3300 
   3301 mark_0869:
   3302 *COPY:*
   3303 ;
   3304 ; check - is this $16==22 or 24?
   3305 ;
   3306 ;;	LD	D,$16		; prepare to copy twenty four text lines.
   3307 	LD	D,22		; prepare to copy twenty four text lines.
   3308 	LD	HL,(D_FILE)	; set HL to start of display file from D_FILE.
   3309 	INC	HL		; 
   3310 	JR	COPY_D <#COPY_D>		; forward
   3311 
   3312 ; ___
   3313 
   3314 ; A single character-mapped printer buffer is copied to the ZX-Printer.
   3315 
   3316 mark_0871:
   3317 *COPY_BUFF:*
   3318 	LD	D,1		; prepare to copy a single text line.
   3319 	LD	HL,PRBUFF	; set HL to start of printer buffer PRBUFF.
   3320 
   3321 ; both paths converge here.
   3322 
   3323 mark_0876:
   3324 *COPY_D:*
   3325 	CALL	SET_FAST <#SET_FAST>
   3326 
   3327 	PUSH	BC		; *** preserve BC throughout.
   3328 				; a pending character may be present 
   3329 				; in C from LPRINT_CH
   3330 
   3331 mark_087A:
   3332 *COPY_LOOP:*
   3333 	PUSH	HL		; save first character of line pointer. (*)
   3334 	XOR	A		; clear accumulator.
   3335 	LD	E,A		; set pixel line count, range 0-7, to zero.
   3336 
   3337 ; this inner loop deals with each horizontal pixel line.
   3338 
   3339 mark_087D:
   3340 *COPY_TIME:*
   3341 	OUT	(IO_PORT_PRINTER),A	; bit 2 reset starts the printer motor
   3342 				; with an inactive stylus - bit 7 reset.
   3343 	POP	HL		; pick up first character of line pointer (*)
   3344 				; on inner loop.
   3345 
   3346 mark_0880:
   3347 *COPY_BRK:*
   3348 	CALL	BREAK_1 <#BREAK_1>
   3349 	JR	C,COPY_CONT <#COPY_CONT>	; forward with no keypress to COPY_CONT
   3350 
   3351 ; else A will hold 11111111 0
   3352 
   3353 	RRA			; 0111 1111
   3354 	OUT	(IO_PORT_PRINTER),A	; stop ZX printer motor, de-activate stylus.
   3355 
   3356 mark_0888:
   3357 *REPORT_D2:*
   3358 	RST	_ERROR_1
   3359 	DEFB	$0C		; Error Report: BREAK - CONT repeats
   3360 
   3361 ; ___
   3362 
   3363 mark_088A:
   3364 *COPY_CONT:*
   3365 	IN	A,(IO_PORT_PRINTER)	; read from printer port.
   3366 	ADD	A,A		; test bit 6 and 7
   3367 	JP	M,COPY_END <#COPY_END>	; jump forward with no printer to COPY_END
   3368 
   3369 	JR	NC,COPY_BRK <#COPY_BRK>	; back if stylus not in position to COPY_BRK
   3370 
   3371 	PUSH	HL		; save first character of line pointer (*)
   3372 	PUSH	DE		; ** preserve character line and pixel line.
   3373 
   3374 	LD	A,D		; text line count to A?
   3375 	CP	2		; sets carry if last line.
   3376 	SBC	A,A		; now $FF if last line else zero.
   3377 
   3378 ; now cleverly prepare a printer control mask setting bit 2 (later moved to 1)
   3379 ; of D to slow printer for the last two pixel lines ( E = 6 and 7)
   3380 
   3381 	AND	E		; and with pixel line offset 0-7
   3382 	RLCA			; shift to left.
   3383 	AND	E		; and again.
   3384 	LD	D,A		; store control mask in D.
   3385 
   3386 mark_089C:
   3387 *COPY_NEXT:*
   3388 	LD	C,(HL)		; load character from screen or buffer.
   3389 	LD	A,C		; save a copy in C for later inverse test.
   3390 	INC	HL		; update pointer for next time.
   3391 	CP	ZX_NEWLINE	; is character a NEWLINE ?
   3392 	JR	Z,COPY_N_L <#COPY_N_L>	; forward, if so, to COPY_N_L
   3393 
   3394 	PUSH	HL		; * else preserve the character pointer.
   3395 
   3396 	SLA	A		; (?) multiply by two
   3397 	ADD	A,A		; multiply by four
   3398 	ADD	A,A		; multiply by eight
   3399 
   3400 	LD	H,$0F		; load H with half the address of character set.
   3401 	RL	H		; now $1E or $1F (with carry)
   3402 	ADD	A,E		; add byte offset 0-7
   3403 	LD	L,A		; now HL addresses character source byte
   3404 
   3405 	RL	C		; test character, setting carry if inverse.
   3406 	SBC	A,A		; accumulator now $00 if normal, $FF if inverse.
   3407 
   3408 	XOR	(HL)		; combine with bit pattern at end or ROM.
   3409 	LD	C,A		; transfer the byte to C.
   3410 	LD	B,8		; count eight bits to output.
   3411 
   3412 mark_08B5:
   3413 *COPY_BITS:*
   3414 	LD	A,D		; fetch speed control mask from D.
   3415 	RLC	C		; rotate a bit from output byte to carry.
   3416 	RRA			; pick up in bit 7, speed bit to bit 1
   3417 	LD	H,A		; store aligned mask in H register.
   3418 
   3419 mark_08BA:
   3420 *COPY_WAIT:*
   3421 	IN	A,(IO_PORT_PRINTER)	; read the printer port
   3422 	RRA				; test for alignment signal from encoder.
   3423 	JR	NC,COPY_WAIT <#COPY_WAIT>		; loop if not present to COPY_WAIT
   3424 
   3425 	LD	A,H			; control byte to A.
   3426 	OUT	(IO_PORT_PRINTER),A	; and output to printer port.
   3427 	DJNZ	COPY_BITS <#COPY_BITS>		; loop for all eight bits to COPY_BITS
   3428 
   3429 	POP	HL			; * restore character pointer.
   3430 	JR	COPY_NEXT <#COPY_NEXT>		; back for adjacent character line to COPY_NEXT
   3431 
   3432 ; ___
   3433 
   3434 ; A NEWLINE has been encountered either following a text line or as the 
   3435 ; first character of the screen or printer line.
   3436 
   3437 mark_08C7:
   3438 *COPY_N_L:*
   3439 	IN	A,(IO_PORT_PRINTER)	; read printer port.
   3440 	RRA			; wait for encoder signal.
   3441 	JR	NC,COPY_N_L <#COPY_N_L>	; loop back if not to COPY_N_L
   3442 
   3443 	LD	A,D		; transfer speed mask to A.
   3444 	RRCA			; rotate speed bit to bit 1. 
   3445 				; bit 7, stylus control is reset.
   3446 	OUT	(IO_PORT_PRINTER),A	; set the printer speed.
   3447 
   3448 	POP	DE		; ** restore character line and pixel line.
   3449 	INC	E		; increment pixel line 0-7.
   3450 	BIT	3,E		; test if value eight reached.
   3451 	JR	Z,COPY_TIME <#COPY_TIME>	; back if not
   3452 
   3453 ; eight pixel lines, a text line have been completed.
   3454 
   3455 	POP	BC		; lose the now redundant first character 
   3456 				; pointer
   3457 	DEC	D		; decrease text line count.
   3458 	JR	NZ,COPY_LOOP <#COPY_LOOP>	; back if not zero
   3459 
   3460 	LD	A,$04			; stop the already slowed printer motor.
   3461 	OUT	(IO_PORT_PRINTER),A	; output to printer port.
   3462 
   3463 mark_08DE:
   3464 *COPY_END:*
   3465 	CALL	SLOW_FAST <#SLOW_FAST>
   3466 	POP	BC		; *** restore preserved BC.
   3467 
   3468 ------------------------------------------------------------------------
   3469 
   3470 ; THE *'CLEAR PRINTER BUFFER'* SUBROUTINE
   3471 ------------------------------------------------------------------------
   3472 
   3473 ; This subroutine sets 32 bytes of the printer buffer to zero (space) and
   3474 ; the 33rd character is set to a NEWLINE.
   3475 ; This occurs after the printer buffer is sent to the printer but in addition
   3476 ; after the 24 lines of the screen are sent to the printer. 
   3477 ; Note. This is a logic error as the last operation does not involve the 
   3478 ; buffer at all. Logically one should be able to use 
   3479 ; 10 LPRINT "HELLO ";
   3480 ; 20 COPY
   3481 ; 30 LPRINT ; "WORLD"
   3482 ; and expect to see the entire greeting emerge from the printer.
   3483 ; Surprisingly this logic error was never discovered and although one can argue
   3484 ; if the above is a bug, the repetition of this error on the Spectrum was most
   3485 ; definitely a bug.
   3486 ; Since the printer buffer is fixed at the end of the system variables, and
   3487 ; the print position is in the range $3C - $5C, then bit 7 of the system
   3488 ; variable is set to show the buffer is empty and automatically reset when
   3489 ; the variable is updated with any print position - neat.
   3490 
   3491 mark_08E2:
   3492 *CLEAR_PRB:*
   3493 	LD	HL,PRBUFF_END	; address fixed end of PRBUFF
   3494 	LD	(HL),ZX_NEWLINE	; place a newline at last position.
   3495 	LD	B,32		; prepare to blank 32 preceding characters. 
   3496 ;
   3497 ; NB the printer is fixed at 32 characters, maybe it can be tweaked ???
   3498 ;
   3499 mark_08E9:
   3500 *PRB_BYTES:*
   3501 	DEC	HL		; decrement address - could be DEC L.
   3502 	LD	(HL),0		; place a zero byte.
   3503 	DJNZ	PRB_BYTES <#PRB_BYTES>	; loop for all thirty-two
   3504 
   3505 	LD	A,L		; fetch character print position.
   3506 	SET	7,A		; signal the printer buffer is clear.
   3507 	LD	(PR_CC),A	; update one-byte system variable PR_CC
   3508 	RET			; return.
   3509 
   3510 ------------------------------------------------------------------------
   3511 
   3512 ; THE *'PRINT AT'* SUBROUTINE
   3513 ------------------------------------------------------------------------
   3514 
   3515 ;
   3516 ;
   3517 ;
   3518 mark_08F5:
   3519 *PRINT_AT:*
   3520 
   3521 	LD	A,CHARS_VERTICAL-1	; originally 23
   3522 	SUB	B		;
   3523 	JR	C,WRONG_VAL <#WRONG_VAL>
   3524 
   3525 mark_08FA:
   3526 *TEST_VAL:*
   3527 	CP	(IY+DF_SZ-RAMBASE)
   3528 	JP	C,REPORT_5 <#REPORT_5>
   3529 
   3530 	INC	A		;
   3531 	LD	B,A		;
   3532 	LD	A,CHARS_HORIZONTAL-1	; originally 31
   3533 
   3534 	SUB	C		;
   3535 
   3536 mark_0905:
   3537 *WRONG_VAL:*
   3538 	JP	C,REPORT_B <#REPORT_B>
   3539 
   3540 	ADD	A,2		;
   3541 	LD	C,A		;
   3542 
   3543 mark_090B:
   3544 *SET_FIELD:*
   3545 	BIT	1,(IY+FLAGS-RAMBASE)	; Is printer in use?
   3546 	JR	Z,LOC_ADDR <#LOC_ADDR>
   3547 
   3548 	LD	A,$5D		;
   3549 	SUB	C		;
   3550 	LD	(PR_CC),A	;
   3551 	RET			;
   3552 
   3553 ------------------------------------------------------------------------
   3554 
   3555 ; THE *'LOCATE ADDRESS'* ROUTINE
   3556 ------------------------------------------------------------------------
   3557 
   3558 ;
   3559 ; I'm guessing this locates the address of a character at X,Y 
   3560 ; on the screen, with 0,0 being on the bottom left?
   3561 ; S_POSN_x    equ $4039
   3562 ; S_POSN_y    equ $403A
   3563 ; so when BC is stored there, B is Y and C is X
   3564 ;
   3565 mark_0918:
   3566 *LOC_ADDR:*
   3567 	LD	(S_POSN),BC	;
   3568 	LD	HL,(VARS)	;
   3569 	LD	D,C		;
   3570 	LD	A,CHARS_HORIZONTAL+2	; $22 == 34 originally.
   3571 	SUB	C		;
   3572 	LD	C,A		;
   3573 	LD	A,ZX_NEWLINE	;
   3574 	INC	B		;
   3575 
   3576 mark_0927:
   3577 *LOOK_BACK:*
   3578 	DEC	HL		;
   3579 	CP	(HL)		;
   3580 	JR	NZ,LOOK_BACK <#LOOK_BACK>
   3581 
   3582 	DJNZ	LOOK_BACK <#LOOK_BACK>
   3583 
   3584 	INC	HL		;
   3585 	CPIR			;
   3586 	DEC	HL		;
   3587 	LD	(DF_CC),HL	;
   3588 	SCF			; Set Carry Flag
   3589 	RET	PO		;
   3590 
   3591 	DEC	D		;
   3592 	RET	Z		;
   3593 
   3594 	PUSH	BC		;
   3595 	CALL	MAKE_ROOM <#MAKE_ROOM>
   3596 	POP	BC		;
   3597 	LD	B,C		;
   3598 	LD	H,D		; HL := DE
   3599 	LD	L,E		;
   3600 
   3601 mark_0940:
   3602 *EXPAND_2:*
   3603 ;
   3604 ; Writes B spaces to HL--
   3605 ;
   3606 	LD	(HL),ZX_SPACE	;
   3607 	DEC	HL		;
   3608 	DJNZ	EXPAND_2 <#EXPAND_2>
   3609 
   3610 	EX	DE,HL		; restore HL
   3611 	INC	HL		;
   3612 	LD	(DF_CC),HL	;
   3613 	RET			;
   3614 
   3615 ------------------------------------------------------------------------
   3616 
   3617 ; THE *'EXPAND TOKENS'* SUBROUTINE
   3618 ------------------------------------------------------------------------
   3619 
   3620 
   3621 mark_094B:
   3622 *TOKENS:*
   3623 	PUSH	AF		;
   3624 	CALL	TOKEN_ADD <#TOKEN_ADD>
   3625 	JR	NC,ALL_CHARS <#ALL_CHARS>
   3626 
   3627 	BIT	0,(IY+FLAGS-RAMBASE)	; Leading space if set
   3628 	JR	NZ,ALL_CHARS <#ALL_CHARS>
   3629 
   3630 	XOR	A		; A = 0 = ZX_SPACE
   3631 
   3632 	RST	_PRINT_A
   3633 
   3634 mark_0959:
   3635 *ALL_CHARS:*
   3636 	LD	A,(BC)		;
   3637 	AND	$3F		; truncate to printable values ???
   3638 
   3639 	RST	_PRINT_A
   3640 	LD	A,(BC)		;
   3641 	INC	BC		;
   3642 	ADD	A,A		;
   3643 	JR	NC,ALL_CHARS <#ALL_CHARS>
   3644 
   3645 	POP	BC		;
   3646 	BIT	7,B		;
   3647 	RET	Z		;
   3648 
   3649 	CP	ZX_COMMA	; $1A == 26
   3650 	JR	Z,TRAIL_SP <#TRAIL_SP>
   3651 
   3652 	CP	ZX_S		; $38 == 56
   3653 	RET	C		;
   3654 
   3655 mark_096D:
   3656 *TRAIL_SP:*
   3657 	XOR	A		;
   3658 	SET	0,(IY+FLAGS-RAMBASE)	; Suppress leading space
   3659 	JP	PRINT_SP <#PRINT_SP>
   3660 
   3661 ; ___
   3662 
   3663 mark_0975:
   3664 *TOKEN_ADD:*
   3665 	PUSH	HL		;
   3666 	LD	HL,TOKEN_TABLE <#TOKEN_TABLE>
   3667 	BIT	7,A		;
   3668 	JR	Z,TEST_HIGH <#TEST_HIGH>
   3669 
   3670 	AND	$3F		;
   3671 
   3672 mark_097F:
   3673 *TEST_HIGH:*
   3674 	CP	$43		;
   3675 	JR	NC,FOUND <#FOUND>
   3676 
   3677 	LD	B,A		;
   3678 	INC	B		;
   3679 
   3680 mark_0985:
   3681 *WORDS:*
   3682 	BIT	7,(HL)		;
   3683 	INC	HL		;
   3684 	JR	Z,WORDS <#WORDS>
   3685 
   3686 	DJNZ	WORDS <#WORDS>
   3687 
   3688 	BIT	6,A		;
   3689 	JR	NZ,COMP_FLAG <#COMP_FLAG>
   3690 
   3691 	CP	$18		;
   3692 
   3693 mark_0992:
   3694 *COMP_FLAG:*
   3695 	CCF			; Complement Carry Flag
   3696 
   3697 mark_0993:
   3698 *FOUND:*
   3699 	LD	B,H		;
   3700 	LD	C,L		;
   3701 	POP	HL		;
   3702 	RET	NC		;
   3703 
   3704 	LD	A,(BC)		;
   3705 	ADD	A,$E4		;
   3706 	RET			;
   3707 
   3708 ------------------------------------------------------------------------
   3709 
   3710 ; THE *'ONE_SPACE'* SUBROUTINE
   3711 ------------------------------------------------------------------------
   3712 
   3713 
   3714 mark_099B:
   3715 *ONE_SPACE:*
   3716 	LD	BC,$0001	;
   3717 
   3718 ------------------------------------------------------------------------
   3719 
   3720 ; THE *'MAKE ROOM'* SUBROUTINE
   3721 ------------------------------------------------------------------------
   3722 
   3723 ;
   3724 ;
   3725 
   3726 mark_099E:
   3727 *MAKE_ROOM:*
   3728 	PUSH	HL		;
   3729 	CALL	TEST_ROOM <#TEST_ROOM>
   3730 	POP	HL		;
   3731 	CALL	POINTERS <#POINTERS>
   3732 	LD	HL,(STKEND)	;
   3733 	EX	DE,HL		;
   3734 	LDDR			; Copy Bytes
   3735 	RET			;
   3736 
   3737 ------------------------------------------------------------------------
   3738 
   3739 ; THE *'POINTERS'* SUBROUTINE
   3740 ------------------------------------------------------------------------
   3741 
   3742 
   3743 mark_09AD:
   3744 *POINTERS:*
   3745 	PUSH	AF		;
   3746 	PUSH	HL		;
   3747 	LD	HL,D_FILE	;
   3748 	LD	A,$09		;
   3749 
   3750 mark_09B4:
   3751 *NEXT_PTR:*
   3752 	LD	E,(HL)		;
   3753 	INC	HL		;
   3754 	LD	D,(HL)		;
   3755 	EX	(SP),HL	;
   3756 	AND	A		;
   3757 	SBC	HL,DE		;
   3758 	ADD	HL,DE		;
   3759 	EX	(SP),HL	;
   3760 	JR	NC,PTR_DONE <#PTR_DONE>
   3761 
   3762 	PUSH	DE		;
   3763 	EX	DE,HL		;
   3764 	ADD	HL,BC		;
   3765 	EX	DE,HL		;
   3766 	LD	(HL),D		;
   3767 	DEC	HL		;
   3768 	LD	(HL),E		;
   3769 	INC	HL		;
   3770 	POP	DE		;
   3771 
   3772 mark_09C8:
   3773 *PTR_DONE:*
   3774 	INC	HL		;
   3775 	DEC	A		;
   3776 	JR	NZ,NEXT_PTR <#NEXT_PTR>
   3777 
   3778 	EX	DE,HL		;
   3779 	POP	DE		;
   3780 	POP	AF		;
   3781 	AND	A		;
   3782 	SBC	HL,DE		;
   3783 	LD	B,H		;
   3784 	LD	C,L		;
   3785 	INC	BC		;
   3786 	ADD	HL,DE		;
   3787 	EX	DE,HL		;
   3788 	RET			;
   3789 
   3790 ------------------------------------------------------------------------
   3791 
   3792 ; THE *'LINE ADDRESS'* SUBROUTINE
   3793 ------------------------------------------------------------------------
   3794 
   3795 
   3796 mark_09D8:
   3797 *LINE_ADDR:*
   3798 	PUSH	HL		;
   3799 	LD	HL,USER_RAM	;
   3800 	LD	D,H		;
   3801 	LD	E,L		;
   3802 
   3803 mark_09DE:
   3804 *NEXT_TEST:*
   3805 	POP	BC		;
   3806 	CALL	CP_LINES <#CP_LINES>
   3807 	RET	NC		;
   3808 
   3809 	PUSH	BC		;
   3810 	CALL	NEXT_ONE <#NEXT_ONE>
   3811 	EX	DE,HL		;
   3812 	JR	NEXT_TEST <#NEXT_TEST>
   3813 
   3814 ------------------------------------------------------------------------
   3815 
   3816 ; THE *'COMPARE LINE NUMBERS'* SUBROUTINE
   3817 ------------------------------------------------------------------------
   3818 
   3819 
   3820 mark_09EA:
   3821 *CP_LINES:*
   3822 	LD	A,(HL)		;
   3823 	CP	B		;
   3824 	RET	NZ		;
   3825 
   3826 	INC	HL		;
   3827 	LD	A,(HL)		;
   3828 	DEC	HL		;
   3829 	CP	C		;
   3830 	RET			;
   3831 
   3832 ------------------------------------------------------------------------
   3833 
   3834 ; THE *'NEXT LINE OR VARIABLE'* SUBROUTINE
   3835 ------------------------------------------------------------------------
   3836 
   3837 
   3838 mark_09F2:
   3839 *NEXT_ONE:*
   3840 	PUSH	HL		;
   3841 	LD	A,(HL)		;
   3842 	CP	$40		;
   3843 	JR	C,LINES <#LINES>
   3844 
   3845 	BIT	5,A		;
   3846 	JR	Z,NEXT_0_4 <#NEXT_0_4>	; skip forward
   3847 
   3848 	ADD	A,A		;
   3849 	JP	M,NEXT_PLUS_FIVE <#NEXT_PLUS_FIVE>
   3850 
   3851 	CCF			; Complement Carry Flag
   3852 
   3853 mark_0A01:
   3854 *NEXT_PLUS_FIVE:*
   3855 	LD	BC,$0005	;
   3856 	JR	NC,NEXT_LETT <#NEXT_LETT>
   3857 
   3858 	LD	C,$11		; 17
   3859 
   3860 mark_0A08:
   3861 *NEXT_LETT:*
   3862 	RLA			;
   3863 	INC	HL		;
   3864 	LD	A,(HL)		;
   3865 	JR	NC,NEXT_LETT <#NEXT_LETT>	; loop 
   3866 
   3867 	JR	NEXT_ADD <#NEXT_ADD>
   3868 ; ___
   3869 
   3870 mark_0A0F:
   3871 *LINES:*
   3872 	INC	HL		;
   3873 
   3874 mark_0A10:
   3875 *NEXT_0_4:*
   3876 	INC	HL		; BC = word at HL++
   3877 	LD	C,(HL)		;
   3878 	INC	HL		;
   3879 	LD	B,(HL)		;
   3880 	INC	HL		;
   3881 
   3882 mark_0A15:
   3883 *NEXT_ADD:*
   3884 	ADD	HL,BC		;
   3885 	POP	DE		;
   3886 
   3887 ------------------------------------------------------------------------
   3888 
   3889 ; THE *'DIFFERENCE'* SUBROUTINE
   3890 ------------------------------------------------------------------------
   3891 
   3892 
   3893 mark_0A17:
   3894 *DIFFER:*
   3895 	AND	A		;
   3896 	SBC	HL,DE		;
   3897 	LD	B,H		; BC := (HL-DE)
   3898 	LD	C,L		;
   3899 	ADD	HL,DE		;
   3900 	EX	DE,HL		; DE := old HL ???
   3901 	RET			;
   3902 
   3903 ------------------------------------------------------------------------
   3904 
   3905 ; THE *'LINE_ENDS'* SUBROUTINE
   3906 ------------------------------------------------------------------------
   3907 
   3908 
   3909 mark_0A1F:
   3910 *LINE_ENDS:*
   3911 	LD	B,(IY+DF_SZ-RAMBASE)
   3912 	PUSH	BC		;
   3913 	CALL	B_LINES <#B_LINES>
   3914 	POP	BC		;
   3915 	DEC	B		;
   3916 	JR	B_LINES <#B_LINES>
   3917 
   3918 ------------------------------------------------------------------------
   3919 
   3920 ; THE *'CLS'* COMMAND ROUTINE
   3921 ------------------------------------------------------------------------
   3922 
   3923 
   3924 mark_0A2A:
   3925 *CLS:*
   3926 	LD	B,CHARS_VERTICAL	; number of lines to clear. $18 = 24 originally.
   3927 
   3928 mark_0A2C:
   3929 *B_LINES:*
   3930 	RES	1,(IY+FLAGS-RAMBASE)	; Signal printer not in use
   3931 	LD	C,CHARS_HORIZONTAL+1	; $21		; extra 1 is for HALT opcode ?
   3932 	PUSH	BC		;
   3933 	CALL	LOC_ADDR <#LOC_ADDR>
   3934 	POP	BC		;
   3935 	LD	A,(RAMTOP+1)	; is RAMTOP_hi
   3936 	CP	$4D		;
   3937 	JR	C,COLLAPSED <#COLLAPSED>
   3938 ;
   3939 ; If RAMTOP less then 4D00, RAM less than D00 = 3.25 K, 
   3940 ; uses collapsed display.
   3941 ;
   3942 
   3943 	SET	7,(IY+S_POSN_y-RAMBASE)
   3944 
   3945 mark_0A42:
   3946 *CLEAR_LOC:*
   3947 	XOR	A		; prepare a space
   3948 	CALL	PRINT_SP <#PRINT_SP>	; prints a space
   3949 	LD	HL,(S_POSN)	;
   3950 	LD	A,L		;
   3951 	OR	H		;
   3952 	AND	$7E		; 
   3953 	JR	NZ,CLEAR_LOC <#CLEAR_LOC>
   3954 
   3955 	JP	LOC_ADDR <#LOC_ADDR>
   3956 
   3957 ; ___
   3958 
   3959 mark_0A52:
   3960 *COLLAPSED:*
   3961 	LD	D,H		; DE := HL
   3962 	LD	E,L		;
   3963 	DEC	HL		;
   3964 	LD	C,B		;
   3965 	LD	B,0		; Will loop 256 times
   3966 	LDIR			; Copy Bytes
   3967 	LD	HL,(VARS)	;
   3968 
   3969 ------------------------------------------------------------------------
   3970 
   3971 ; THE *'RECLAIMING'* SUBROUTINES
   3972 ------------------------------------------------------------------------
   3973 
   3974 
   3975 mark_0A5D:
   3976 *RECLAIM_1:*
   3977 	CALL	DIFFER <#DIFFER>
   3978 
   3979 mark_0A60:
   3980 *RECLAIM_2:*
   3981 	PUSH	BC		;
   3982 	LD	A,B		;
   3983 	CPL			;
   3984 	LD	B,A		;
   3985 	LD	A,C		;
   3986 	CPL			;
   3987 	LD	C,A		;
   3988 	INC	BC		;
   3989 	CALL	POINTERS <#POINTERS>
   3990 	EX	DE,HL		;
   3991 	POP	HL		;
   3992 	ADD	HL,DE		;
   3993 	PUSH	DE		;
   3994 	LDIR			; Copy Bytes
   3995 	POP	HL		;
   3996 	RET			;
   3997 
   3998 ------------------------------------------------------------------------
   3999 
   4000 ; THE *'E_LINE NUMBER'* SUBROUTINE
   4001 ------------------------------------------------------------------------
   4002 
   4003 
   4004 mark_0A73:
   4005 *E_LINE_NUM:*
   4006 	LD	HL,(E_LINE)	;
   4007 	CALL	TEMP_PTR2 <#TEMP_PTR2>
   4008 
   4009 	RST	_GET_CHAR
   4010 	BIT	5,(IY+FLAGX-RAMBASE)
   4011 	RET	NZ		;
   4012 
   4013 	LD	HL,MEM_0_1st	;
   4014 	LD	(STKEND),HL	;
   4015 	CALL	INT_TO_FP <#INT_TO_FP>
   4016 	CALL	FP_TO_BC <#FP_TO_BC>
   4017 	JR	C,NO_NUMBER <#NO_NUMBER>	; to NO_NUMBER
   4018 
   4019 	LD	HL,-10000	; $D8F0	; value '-10000'
   4020 	ADD	HL,BC		;
   4021 
   4022 mark_0A91:
   4023 *NO_NUMBER:*
   4024 	JP	C,REPORT_C <#REPORT_C>	; to REPORT_C
   4025 
   4026 	CP	A		;
   4027 	JP	SET_MIN <#SET_MIN>
   4028 
   4029 ------------------------------------------------------------------------
   4030 
   4031 ; THE *'REPORT AND LINE NUMBER'* PRINTING SUBROUTINES
   4032 ------------------------------------------------------------------------
   4033 
   4034 
   4035 mark_0A98:
   4036 *OUT_NUM:*
   4037 	PUSH	DE		;
   4038 	PUSH	HL		;
   4039 	XOR	A		;
   4040 	BIT	7,B		;
   4041 	JR	NZ,UNITS <#UNITS>
   4042 
   4043 	LD	H,B		; HL := BC
   4044 	LD	L,C		;
   4045 	LD	E,$FF		;
   4046 	JR	THOUSAND <#THOUSAND>
   4047 ; ___
   4048 
   4049 mark_0AA5:
   4050 *OUT_NO:*
   4051 	PUSH	DE		;
   4052 	LD	D,(HL)		;
   4053 	INC	HL		;
   4054 	LD	E,(HL)		;
   4055 	PUSH	HL		;
   4056 	EX	DE,HL		;
   4057 	LD	E,ZX_SPACE	; set E to leading space.
   4058 
   4059 mark_0AAD:
   4060 *THOUSAND:*
   4061 	LD	BC,-1000	; $FC18	;
   4062 	CALL	OUT_DIGIT <#OUT_DIGIT>
   4063 	LD	BC,-100		; $FF9C	;
   4064 	CALL	OUT_DIGIT <#OUT_DIGIT>
   4065 	LD	C,-10		; $F6		; B is already FF, so saves a byte.
   4066 	CALL	OUT_DIGIT <#OUT_DIGIT>
   4067 	LD	A,L		;
   4068 
   4069 mark_0ABF:
   4070 *UNITS:*
   4071 	CALL	OUT_CODE <#OUT_CODE>
   4072 	POP	HL		;
   4073 	POP	DE		;
   4074 	RET			;
   4075 
   4076 ------------------------------------------------------------------------
   4077 
   4078 ; THE *'UNSTACK_Z'* SUBROUTINE
   4079 ------------------------------------------------------------------------
   4080 
   4081 
   4082 ; This subroutine is used to return early from a routine when checking syntax.
   4083 ; On the ZX81 the same routines that execute commands also check the syntax
   4084 ; on line entry. This enables precise placement of the error marker in a line
   4085 ; that fails syntax.
   4086 ; The sequence CALL SYNTAX_Z ; RET Z can be replaced by a call to this routine
   4087 ; although it has not replaced every occurrence of the above two instructions.
   4088 ; Even on the ZX80 this routine was not fully utilized.
   4089 
   4090 mark_0AC5:
   4091 *UNSTACK_Z:*
   4092 	CALL	SYNTAX_Z <#SYNTAX_Z>		; resets the ZERO flag if
   4093 				; checking syntax.
   4094 	POP	HL		; drop the return address.
   4095 	RET	Z		; return to previous calling routine if 
   4096 				; checking syntax.
   4097 
   4098 	JP	(HL)		; else jump to the continuation address in
   4099 				; the calling routine as RET would have done.
   4100 
   4101 ------------------------------------------------------------------------
   4102 
   4103 ; THE *'LPRINT'* COMMAND ROUTINE
   4104 ------------------------------------------------------------------------
   4105 
   4106 ;
   4107 ;
   4108 
   4109 mark_0ACB:
   4110 *LPRINT:*
   4111 	SET	1,(IY+FLAGS-RAMBASE)	; Signal printer in use
   4112 
   4113 ------------------------------------------------------------------------
   4114 
   4115 ; THE *'PRINT'* COMMAND ROUTINE
   4116 ------------------------------------------------------------------------
   4117 
   4118 
   4119 mark_0ACF:
   4120 *PRINT:*
   4121 	LD	A,(HL)		;
   4122 	CP	ZX_NEWLINE		;
   4123 	JP	Z,PRINT_END <#PRINT_END>	; to PRINT_END
   4124 
   4125 mark_0AD5:
   4126 *PRINT_1:*
   4127 	SUB	ZX_COMMA	; $1A == 26
   4128 	ADC	A,$00		; 
   4129 	JR	Z,SPACING <#SPACING>	; to SPACING
   4130 				; 
   4131 				; Compare with AT, 
   4132 				; less comma recently subtracted.
   4133 				; 
   4134 	CP	ZX_AT-ZX_COMMA	; $A7 == 167
   4135 	JR	NZ,NOT_AT <#NOT_AT>	;
   4136 
   4137 
   4138 	RST	_NEXT_CHAR
   4139 	CALL	CLASS_6 <#CLASS_6>
   4140 	CP	ZX_COMMA	; $1A = 26
   4141 	JP	NZ,REPORT_C <#REPORT_C>	;
   4142 
   4143 	RST	_NEXT_CHAR
   4144 	CALL	CLASS_6 <#CLASS_6>
   4145 	CALL	SYNTAX_ON <#SYNTAX_ON>
   4146 
   4147 	RST	_FP_CALC	;;
   4148 	DEFB	__exchange	;;
   4149 	DEFB	__end_calc	;;
   4150 
   4151 	CALL	STK_TO_BC <#STK_TO_BC>
   4152 	CALL	PRINT_AT <#PRINT_AT>
   4153 	JR	PRINT_ON <#PRINT_ON>
   4154 ; ___
   4155 
   4156 mark_0AFA:
   4157 *NOT_AT:*
   4158 	CP	ZX_TAB-ZX_COMMA	; $A8 == 168
   4159 	JR	NZ,NOT_TAB <#NOT_TAB>
   4160 
   4161 
   4162 	RST	_NEXT_CHAR
   4163 	CALL	CLASS_6 <#CLASS_6>
   4164 	CALL	SYNTAX_ON <#SYNTAX_ON>
   4165 	CALL	STK_TO_A <#STK_TO_A>
   4166 	JP	NZ,REPORT_B <#REPORT_B>
   4167 
   4168 	AND	$1F		; truncate to 0 to 31 characters ???
   4169 	LD	C,A		;
   4170 	BIT	1,(IY+FLAGS-RAMBASE)	; Is printer in use
   4171 	JR	Z,TAB_TEST <#TAB_TEST>
   4172 
   4173 	SUB	(IY+PR_CC-RAMBASE)
   4174 	SET	7,A		;
   4175 	ADD	A,$3C		; 60
   4176 	CALL	NC,COPY_BUFF <#COPY_BUFF>
   4177 
   4178 mark_0B1E:
   4179 *TAB_TEST:*
   4180 	ADD	A,(IY+S_POSN_x-RAMBASE)	; screen position X
   4181 	CP	CHARS_HORIZONTAL+1	; 33 (characters horizontal plus newline ???)
   4182 	LD	A,(S_POSN_y)		; screen position Y
   4183 	SBC	A,1			;
   4184 	CALL	TEST_VAL <#TEST_VAL>
   4185 	SET	0,(IY+FLAGS-RAMBASE)	; sv FLAGS	- Suppress leading space
   4186 	JR	PRINT_ON <#PRINT_ON>
   4187 ; ___
   4188 
   4189 mark_0B31:
   4190 *NOT_TAB:*
   4191 	CALL	SCANNING <#SCANNING>
   4192 	CALL	PRINT_STK <#PRINT_STK>
   4193 
   4194 mark_0B37:
   4195 *PRINT_ON:*
   4196 	RST	_GET_CHAR
   4197 	SUB	ZX_COMMA	;  $1A
   4198 	ADC	A,0		;
   4199 	JR	Z,SPACING <#SPACING>
   4200 
   4201 	CALL	CHECK_END <#CHECK_END>
   4202 	JP	PRINT_END <#PRINT_END>
   4203 ; ___
   4204 mark_0B44:
   4205 *SPACING:*
   4206 	CALL	NC,FIELD <#FIELD>
   4207 
   4208 	RST	_NEXT_CHAR
   4209 	CP	ZX_NEWLINE	;
   4210 	RET	Z		;
   4211 
   4212 	JP	PRINT_1 <#PRINT_1>
   4213 ; ___
   4214 mark_0B4E:
   4215 *SYNTAX_ON:*
   4216 	CALL	SYNTAX_Z <#SYNTAX_Z>
   4217 	RET	NZ		;
   4218 
   4219 	POP	HL		;
   4220 	JR	PRINT_ON <#PRINT_ON>
   4221 ; ___
   4222 mark_0B55:
   4223 *PRINT_STK:*
   4224 	CALL	UNSTACK_Z <#UNSTACK_Z>
   4225 	BIT	6,(IY+FLAGS-RAMBASE)	; Numeric or string result?
   4226 	CALL	Z,STK_FETCH <#STK_FETCH>
   4227 	JR	Z,PR_STR_4 <#PR_STR_4>
   4228 
   4229 	JP	PRINT_FP <#PRINT_FP>		; jump forward
   4230 ; ___
   4231 
   4232 mark_0B64:
   4233 *PR_STR_1:*
   4234 	LD	A,ZX_QUOTE	; $0B
   4235 
   4236 mark_0B66:
   4237 *PR_STR_2:*
   4238 	RST	_PRINT_A
   4239 
   4240 mark_0B67:
   4241 *PR_STR_3:*
   4242 	LD	DE,(X_PTR)	;
   4243 
   4244 mark_0B6B:
   4245 *PR_STR_4:*
   4246 	LD	A,B		;
   4247 	OR	C		;
   4248 	DEC	BC		;
   4249 	RET	Z		;
   4250 
   4251 	LD	A,(DE)		;
   4252 	INC	DE		;
   4253 	LD	(X_PTR),DE	;
   4254 	BIT	6,A		;
   4255 	JR	Z,PR_STR_2 <#PR_STR_2>
   4256 
   4257 	CP	$C0		;
   4258 	JR	Z,PR_STR_1 <#PR_STR_1>
   4259 
   4260 	PUSH	BC		;
   4261 	CALL	TOKENS <#TOKENS>
   4262 	POP	BC		;
   4263 	JR	PR_STR_3 <#PR_STR_3>
   4264 
   4265 ; ___
   4266 
   4267 mark_0B84:
   4268 *PRINT_END:*
   4269 	CALL	UNSTACK_Z <#UNSTACK_Z>
   4270 	LD	A,ZX_NEWLINE		;
   4271 
   4272 	RST	_PRINT_A
   4273 	RET			;
   4274 
   4275 ; ___
   4276 
   4277 mark_0B8B:
   4278 *FIELD:*
   4279 	CALL	UNSTACK_Z <#UNSTACK_Z>
   4280 	SET	0,(IY+FLAGS-RAMBASE)	; Suppress leading space
   4281 	XOR	A		;
   4282 
   4283 	RST	_PRINT_A
   4284 	LD	BC,(S_POSN)	;
   4285 	LD	A,C		;
   4286 	BIT	1,(IY+FLAGS-RAMBASE)	; Is printer in use
   4287 	JR	Z,CENTRE <#CENTRE>
   4288 
   4289 	LD	A,$5D		;
   4290 	SUB	(IY+PR_CC-RAMBASE)
   4291 
   4292 mark_0BA4:
   4293 *CENTRE:*
   4294 	LD	C,$11		;
   4295 	CP	C		;
   4296 	JR	NC,RIGHT <#RIGHT>
   4297 
   4298 	LD	C,$01		;
   4299 
   4300 mark_0BAB:
   4301 *RIGHT:*
   4302 	CALL	SET_FIELD <#SET_FIELD>
   4303 	RET			;
   4304 
   4305 ------------------------------------------------------------------------
   4306 
   4307 ; THE *'PLOT AND UNPLOT'* COMMAND ROUTINES
   4308 ------------------------------------------------------------------------
   4309 
   4310 
   4311 mark_0BAF:
   4312 *PLOT_UNPLOT:*
   4313 ;
   4314 ; Of the 24 lines, only top 22 ar used for plotting.
   4315 ;
   4316 	CALL	STK_TO_BC <#STK_TO_BC>
   4317 	LD	(COORDS_x),BC	;
   4318 ;;	LD	A,$2B		; originally $2B == 32+11 = 43 = 2*22-1
   4319 	LD	A,2*(CHARS_VERTICAL-2)-1	; 
   4320 	SUB	B		;
   4321 	JP	C,REPORT_B <#REPORT_B>
   4322 
   4323 	LD	B,A		;
   4324 	LD	A,$01		;
   4325 	SRA	B		;
   4326 	JR	NC,COLUMNS <#COLUMNS>
   4327 
   4328 	LD	A,$04		;
   4329 
   4330 mark_0BC5:
   4331 *COLUMNS:*
   4332 	SRA	C		;
   4333 	JR	NC,FIND_ADDR <#FIND_ADDR>
   4334 
   4335 	RLCA			;
   4336 
   4337 mark_0BCA:
   4338 *FIND_ADDR:*
   4339 	PUSH	AF		;
   4340 	CALL	PRINT_AT <#PRINT_AT>
   4341 	LD	A,(HL)		;
   4342 	RLCA			;
   4343 	CP	ZX_BRACKET_LEFT	; $10
   4344 	JR	NC,TABLE_PTR <#TABLE_PTR>
   4345 
   4346 	RRCA			;
   4347 	JR	NC,SQ_SAVED <#SQ_SAVED>
   4348 
   4349 	XOR	$8F		;
   4350 
   4351 mark_0BD9:
   4352 *SQ_SAVED:*
   4353 	LD	B,A		;
   4354 
   4355 mark_0BDA:
   4356 *TABLE_PTR:*
   4357 	LD	DE,P_UNPLOT <#P_UNPLOT>	; Address: P_UNPLOT
   4358 	LD	A,(T_ADDR)	; get T_ADDR_lo
   4359 	SUB	E		;
   4360 	JP	M,PLOT <#PLOT>
   4361 
   4362 	POP	AF		;
   4363 	CPL			;
   4364 	AND	B		;
   4365 	JR	UNPLOT <#UNPLOT>
   4366 
   4367 ; ___
   4368 
   4369 mark_0BE9:
   4370 *PLOT:*
   4371 	POP	AF		;
   4372 	OR	B		;
   4373 
   4374 mark_0BEB:
   4375 *UNPLOT:*
   4376 	CP	8		; Only apply to graphic characters (0 to 7)
   4377 	JR	C,PLOT_END <#PLOT_END>
   4378 
   4379 	XOR	$8F		; binary 1000 1111
   4380 
   4381 mark_0BF1:
   4382 *PLOT_END:*
   4383 	EXX			;
   4384 
   4385 	RST	_PRINT_A
   4386 	EXX			;
   4387 	RET			;
   4388 
   4389 ------------------------------------------------------------------------
   4390 
   4391 ; THE *'STACK_TO_BC'* SUBROUTINE
   4392 ------------------------------------------------------------------------
   4393 
   4394 mark_0BF5:
   4395 *STK_TO_BC:*
   4396 	CALL	STK_TO_A <#STK_TO_A>
   4397 	LD	B,A		;
   4398 	PUSH	BC		;
   4399 	CALL	STK_TO_A <#STK_TO_A>
   4400 	LD	E,C		;
   4401 	POP	BC		;
   4402 	LD	D,C		;
   4403 	LD	C,A		;
   4404 	RET			;
   4405 
   4406 ------------------------------------------------------------------------
   4407 
   4408 ; THE *'STACK_TO_A'* SUBROUTINE
   4409 ------------------------------------------------------------------------
   4410 
   4411 
   4412 mark_0C02:
   4413 *STK_TO_A:*
   4414 	CALL	FP_TO_A <#FP_TO_A>
   4415 	JP	C,REPORT_B <#REPORT_B>
   4416 
   4417 	LD	C,$01		; 
   4418 	RET	Z		;
   4419 
   4420 	LD	C,$FF		;
   4421 	RET			;
   4422 
   4423 ------------------------------------------------------------------------
   4424 
   4425 ; THE *'SCROLL'* SUBROUTINE
   4426 ------------------------------------------------------------------------
   4427 
   4428 
   4429 mark_0C0E:
   4430 *SCROLL:*
   4431 	LD	B,(IY+DF_SZ-RAMBASE)
   4432 	LD	C,CHARS_HORIZONTAL+1		;
   4433 	CALL	LOC_ADDR <#LOC_ADDR>
   4434 	CALL	ONE_SPACE <#ONE_SPACE>
   4435 	LD	A,(HL)		;
   4436 	LD	(DE),A		;
   4437 	INC	(IY+S_POSN_y-RAMBASE)
   4438 	LD	HL,(D_FILE)	;
   4439 	INC	HL		;
   4440 	LD	D,H		;
   4441 	LD	E,L		;
   4442 	CPIR			;
   4443 	JP	RECLAIM_1 <#RECLAIM_1>
   4444 
   4445 ------------------------------------------------------------------------
   4446 
   4447 ; THE *'SYNTAX'* TABLES
   4448 ------------------------------------------------------------------------
   4449 
   4450 
   4451 ; i) The Offset table
   4452 
   4453 mark_0C29:
   4454 *offset_t:*
   4455 	DEFB	P_LPRINT <#P_LPRINT> - $	; 8B offset
   4456 	DEFB	P_LLIST <#P_LLIST> - $	; 8D offset
   4457 	DEFB	P_STOP <#P_STOP> - $	; 2D offset
   4458 	DEFB	P_SLOW <#P_SLOW> - $	; 7F offset
   4459 	DEFB	P_FAST <#P_FAST> - $	; 81 offset
   4460 	DEFB	P_NEW <#P_NEW> - $	; 49 offset
   4461 	DEFB	P_SCROLL <#P_SCROLL> - $	; 75 offset
   4462 	DEFB	P_CONT <#P_CONT> - $	; 5F offset
   4463 	DEFB	P_DIM <#P_DIM> - $	; 40 offset
   4464 	DEFB	P_REM <#P_REM> - $	; 42 offset
   4465 	DEFB	P_FOR <#P_FOR> - $	; 2B offset
   4466 	DEFB	P_GOTO <#P_GOTO> - $	; 17 offset
   4467 	DEFB	P_GOSUB <#P_GOSUB> - $	; 1F offset
   4468 	DEFB	P_INPUT <#P_INPUT> - $	; 37 offset
   4469 	DEFB	P_LOAD <#P_LOAD> - $	; 52 offset
   4470 	DEFB	P_LIST <#P_LIST> - $	; 45 offset
   4471 	DEFB	P_LET <#P_LET> - $	; 0F offset
   4472 	DEFB	P_PAUSE <#P_PAUSE> - $	; 6D offset
   4473 	DEFB	P_NEXT <#P_NEXT> - $	; 2B offset
   4474 	DEFB	P_POKE <#P_POKE> - $	; 44 offset
   4475 	DEFB	P_PRINT <#P_PRINT> - $	; 2D offset
   4476 	DEFB	P_PLOT <#P_PLOT> - $	; 5A offset
   4477 	DEFB	P_RUN <#P_RUN> - $	; 3B offset
   4478 	DEFB	P_SAVE <#P_SAVE> - $	; 4C offset
   4479 	DEFB	P_RAND <#P_RAND> - $	; 45 offset
   4480 	DEFB	P_IF <#P_IF> - $	; 0D offset
   4481 	DEFB	P_CLS <#P_CLS> - $	; 52 offset
   4482 	DEFB	P_UNPLOT <#P_UNPLOT> - $	; 5A offset
   4483 	DEFB	P_CLEAR <#P_CLEAR> - $	; 4D offset
   4484 	DEFB	P_RETURN <#P_RETURN> - $	; 15 offset
   4485 	DEFB	P_COPY <#P_COPY> - $	; 6A offset
   4486 ------------------------------------------------------------------------
   4487 
   4488 ; ii) The parameter table.
   4489 
   4490 mark_0C48:
   4491 *P_LET:*
   4492 	DEFB	_CLASS_01	; A variable is required.
   4493 	DEFB	ZX_EQUAL	; Separator:	'='
   4494 	DEFB	_CLASS_02	; An expression, numeric or string,
   4495 				; must follow.
   4496 
   4497 mark_0C4B:
   4498 *P_GOTO:*
   4499 	DEFB	_CLASS_06	; A numeric expression must follow.
   4500 	DEFB	_CLASS_00	; No further operands.
   4501 	DEFW	GOTO <#GOTO>
   4502 
   4503 mark_0C4F:
   4504 *P_IF:*
   4505 	DEFB	_CLASS_06	; A numeric expression must follow.
   4506 	DEFB	ZX_THEN		; Separator:	'THEN'
   4507 	DEFB	_CLASS_05	; Variable syntax checked entirely
   4508 				; by routine.
   4509 	DEFW	IF <#IF>
   4510 
   4511 mark_0C54:
   4512 *P_GOSUB:*
   4513 	DEFB	_CLASS_06	; A numeric expression must follow.
   4514 	DEFB	_CLASS_00	; No further operands.
   4515 	DEFW	GOSUB <#GOSUB>
   4516 
   4517 mark_0C58:
   4518 *P_STOP:*
   4519 	DEFB	_CLASS_00	; No further operands.
   4520 	DEFW	STOP <#STOP>
   4521 
   4522 mark_0C5B:
   4523 *P_RETURN:*
   4524 	DEFB	_CLASS_00	; No further operands.
   4525 	DEFW	RETURN <#RETURN>
   4526 
   4527 mark_0C5E:
   4528 *P_FOR:*
   4529 	DEFB	_CLASS_04	; A single character variable must
   4530 				; follow.
   4531 	DEFB	ZX_EQUAL	; Separator:	'='
   4532 	DEFB	_CLASS_06	; A numeric expression must follow.
   4533 	DEFB	ZX_TO		; Separator:	'TO'
   4534 	DEFB	_CLASS_06	; A numeric expression must follow.
   4535 	DEFB	_CLASS_05	; Variable syntax checked entirely
   4536 				; by routine.
   4537 	DEFW	FOR <#FOR>
   4538 
   4539 mark_0C66:
   4540 *P_NEXT:*
   4541 	DEFB	_CLASS_04	; A single character variable must
   4542 				; follow.
   4543 	DEFB	_CLASS_00	; No further operands.
   4544 	DEFW	NEXT <#NEXT>
   4545 
   4546 mark_0C6A:
   4547 *P_PRINT:*
   4548 	DEFB	_CLASS_05	; Variable syntax checked entirely
   4549 				; by routine.
   4550 	DEFW	PRINT <#PRINT>		; not LPRINT ???
   4551 
   4552 mark_0C6D:
   4553 *P_INPUT:*
   4554 	DEFB	_CLASS_01	; A variable is required.
   4555 	DEFB	_CLASS_00	; No further operands.
   4556 	DEFW	INPUT <#INPUT>
   4557 
   4558 mark_0C71:
   4559 *P_DIM:*
   4560 	DEFB	_CLASS_05	; Variable syntax checked entirely
   4561 				; by routine.
   4562 	DEFW	DIM <#DIM>
   4563 
   4564 mark_0C74:
   4565 *P_REM:*
   4566 	DEFB	_CLASS_05	; Variable syntax checked entirely
   4567 				; by routine.
   4568 	DEFW	REM <#REM>
   4569 
   4570 mark_0C77:
   4571 *P_NEW:*
   4572 	DEFB	_CLASS_00	; No further operands.
   4573 	DEFW	NEW <#NEW>
   4574 
   4575 mark_0C7A:
   4576 *P_RUN:*
   4577 	DEFB	_CLASS_03	; A numeric expression may follow
   4578 				; else default to zero.
   4579 	DEFW	RUN <#RUN>
   4580 
   4581 mark_0C7D:
   4582 *P_LIST:*
   4583 	DEFB	_CLASS_03	; A numeric expression may follow
   4584 				; else default to zero.
   4585 	DEFW	LIST <#LIST>
   4586 
   4587 mark_0C80:
   4588 *P_POKE:*
   4589 	DEFB	_CLASS_06	; A numeric expression must follow.
   4590 	DEFB	ZX_COMMA	; Separator:	','
   4591 	DEFB	_CLASS_06	; A numeric expression must follow.
   4592 	DEFB	_CLASS_00	; No further operands.
   4593 	DEFW	POKE <#POKE>
   4594 
   4595 mark_0C86:
   4596 *P_RAND:*
   4597 	DEFB	_CLASS_03	; A numeric expression may follow
   4598 				; else default to zero.
   4599 	DEFW	RAND <#RAND>
   4600 
   4601 mark_0C89:
   4602 *P_LOAD:*
   4603 	DEFB	_CLASS_05	; Variable syntax checked entirely
   4604 				; by routine.
   4605 	DEFW	LOAD <#LOAD>
   4606 
   4607 mark_0C8C:
   4608 *P_SAVE:*
   4609 	DEFB	_CLASS_05	; Variable syntax checked entirely
   4610 				; by routine.
   4611 	DEFW	SAVE <#SAVE>
   4612 
   4613 mark_0C8F:
   4614 *P_CONT:*
   4615 	DEFB	_CLASS_00	; No further operands.
   4616 	DEFW	CONT <#CONT>
   4617 
   4618 mark_0C92:
   4619 *P_CLEAR:*
   4620 	DEFB	_CLASS_00	; No further operands.
   4621 	DEFW	CLEAR <#CLEAR>
   4622 
   4623 mark_0C95:
   4624 *P_CLS:*
   4625 	DEFB	_CLASS_00	; No further operands.
   4626 	DEFW	CLS <#CLS>
   4627 
   4628 mark_0C98:
   4629 *P_PLOT:*
   4630 	DEFB	_CLASS_06	; A numeric expression must follow.
   4631 	DEFB	ZX_COMMA	; Separator:	','
   4632 	DEFB	_CLASS_06	; A numeric expression must follow.
   4633 	DEFB	_CLASS_00	; No further operands.
   4634 	DEFW	PLOT_UNPLOT <#PLOT_UNPLOT>
   4635 
   4636 mark_0C9E:
   4637 *P_UNPLOT:*
   4638 	DEFB	_CLASS_06	; A numeric expression must follow.
   4639 	DEFB	ZX_COMMA	; Separator:	','
   4640 	DEFB	_CLASS_06	; A numeric expression must follow.
   4641 	DEFB	_CLASS_00	; No further operands.
   4642 	DEFW	PLOT_UNPLOT <#PLOT_UNPLOT>
   4643 
   4644 mark_0CA4:
   4645 *P_SCROLL:*
   4646 	DEFB	_CLASS_00	; No further operands.
   4647 	DEFW	SCROLL <#SCROLL>
   4648 
   4649 mark_0CA7:
   4650 *P_PAUSE:*
   4651 	DEFB	_CLASS_06	; A numeric expression must follow.
   4652 	DEFB	_CLASS_00	; No further operands.
   4653 	DEFW	PAUSE <#PAUSE>
   4654 
   4655 mark_0CAB:
   4656 *P_SLOW:*
   4657 	DEFB	_CLASS_00	; No further operands.
   4658 	DEFW	SLOW <#SLOW>
   4659 
   4660 mark_0CAE:
   4661 *P_FAST:*
   4662 	DEFB	_CLASS_00	; No further operands.
   4663 	DEFW	FAST <#FAST>
   4664 
   4665 mark_0CB1:
   4666 *P_COPY:*
   4667 	DEFB	_CLASS_00	; No further operands.
   4668 	DEFW	COPY <#COPY>
   4669 
   4670 mark_0CB4:
   4671 *P_LPRINT:*
   4672 	DEFB	_CLASS_05	; Variable syntax checked entirely
   4673 				; by routine.
   4674 	DEFW	LPRINT <#LPRINT>
   4675 
   4676 mark_0CB7:
   4677 *P_LLIST:*
   4678 	DEFB	_CLASS_03	; A numeric expression may follow
   4679 				; else default to zero.
   4680 	DEFW	LLIST <#LLIST>
   4681 
   4682 
   4683 ------------------------------------------------------------------------
   4684 
   4685 ; THE *'LINE SCANNING'* ROUTINE
   4686 ------------------------------------------------------------------------
   4687 
   4688 
   4689 mark_0CBA:
   4690 *LINE_SCAN:*
   4691 	LD	(IY+FLAGS-RAMBASE),1
   4692 	CALL	E_LINE_NUM <#E_LINE_NUM>
   4693 
   4694 mark_0CC1:
   4695 *LINE_RUN:*
   4696 	CALL	SET_MIN <#SET_MIN>
   4697 	LD	HL,ERR_NR	;
   4698 	LD	(HL),$FF	;
   4699 	LD	HL,FLAGX	;
   4700 	BIT	5,(HL)		;
   4701 	JR	Z,LINE_NULL <#LINE_NULL>
   4702 
   4703 	CP	$E3		; 'STOP' ?
   4704 	LD	A,(HL)		;
   4705 	JP	NZ,INPUT_REP <#INPUT_REP>
   4706 
   4707 	CALL	SYNTAX_Z <#SYNTAX_Z>
   4708 	RET	Z		;
   4709 
   4710 
   4711 	RST	_ERROR_1
   4712 	DEFB	$0C		; Error Report: BREAK - CONT repeats
   4713 
   4714 
   4715 ------------------------------------------------------------------------
   4716 
   4717 ; THE *'STOP'* COMMAND ROUTINE
   4718 ------------------------------------------------------------------------
   4719 
   4720 ;
   4721 ;
   4722 
   4723 mark_0CDC:
   4724 *STOP:*
   4725 	RST	_ERROR_1
   4726 	DEFB	$08		; Error Report: STOP statement
   4727 ; ___
   4728 
   4729 ; the interpretation of a line continues with a check for just spaces
   4730 ; followed by a carriage return.
   4731 ; The IF command also branches here with a true value to execute the
   4732 ; statement after the THEN but the statement can be null so
   4733 ; 10 IF 1 = 1 THEN
   4734 ; passes syntax (on all ZX computers).
   4735 
   4736 mark_0CDE:
   4737 *LINE_NULL:*
   4738 	RST	_GET_CHAR
   4739 	LD	B,$00		; prepare to index - early.
   4740 	CP	ZX_NEWLINE		; compare to NEWLINE.
   4741 	RET	Z		; return if so.
   4742 
   4743 
   4744 
   4745 
   4746 
   4747 	LD	C,A		; transfer character to C.
   4748 
   4749 	RST	_NEXT_CHAR	; advances.
   4750 	LD	A,C		; character to A
   4751 	SUB	$E1		; subtract 'LPRINT' - lowest command.
   4752 	JR	C,REPORT_C2 <#REPORT_C2>	; forward if less
   4753 
   4754 	LD	C,A		; reduced token to C
   4755 	LD	HL,offset_t <#offset_t>	; set HL to address of offset table.
   4756 	ADD	HL,BC		; index into offset table.
   4757 	LD	C,(HL)		; fetch offset
   4758 	ADD	HL,BC		; index into parameter table.
   4759 	JR	GET_PARAM <#GET_PARAM>
   4760 ; ___
   4761 
   4762 mark_0CF4:
   4763 *SCAN_LOOP:*
   4764 	LD	HL,(T_ADDR)	;
   4765 
   4766 ; -> Entry Point to Scanning Loop
   4767 
   4768 mark_0CF7:
   4769 *GET_PARAM:*
   4770 	LD	A,(HL)		;
   4771 	INC	HL		;
   4772 	LD	(T_ADDR),HL	;
   4773 
   4774 	LD	BC,SCAN_LOOP <#SCAN_LOOP>
   4775 	PUSH	BC		; is pushed on machine stack.
   4776 
   4777 	LD	C,A		;
   4778 	CP	ZX_QUOTE	; $0B
   4779 	JR	NC,SEPARATOR <#SEPARATOR>
   4780 
   4781 	LD	HL,class_tbl <#class_tbl>	; class_tbl - the address of the class table.
   4782 	LD	B,$00		;
   4783 	ADD	HL,BC		;
   4784 	LD	C,(HL)		;
   4785 	ADD	HL,BC		;
   4786 	PUSH	HL		;
   4787 
   4788 	RST	_GET_CHAR
   4789 	RET			; indirect jump to class routine and
   4790 				; by subsequent RET to SCAN_LOOP.
   4791 
   4792 ------------------------------------------------------------------------
   4793 
   4794 ; THE *'SEPARATOR'* ROUTINE
   4795 ------------------------------------------------------------------------
   4796 
   4797 
   4798 mark_0D10:
   4799 *SEPARATOR:*
   4800 	RST	_GET_CHAR
   4801 	CP	C		;
   4802 	JR	NZ,REPORT_C2 <#REPORT_C2>
   4803 				; 'Nonsense in BASIC'
   4804 
   4805 	RST	_NEXT_CHAR
   4806 	RET			; return
   4807 
   4808 
   4809 ------------------------------------------------------------------------
   4810 
   4811 ; THE *'COMMAND CLASS'* TABLE
   4812 ------------------------------------------------------------------------
   4813 
   4814 ;
   4815 mark_0D16:
   4816 *class_tbl:*
   4817 	DEFB	CLASS_0 <#CLASS_0> - $	; 17 offset to; Address: CLASS_0
   4818 	DEFB	CLASS_1 <#CLASS_1> - $	; 25 offset to; Address: CLASS_1
   4819 	DEFB	CLASS_2 <#CLASS_2> - $	; 53 offset to; Address: CLASS_2
   4820 	DEFB	CLASS_3 <#CLASS_3> - $	; 0F offset to; Address: CLASS_3
   4821 	DEFB	CLASS_4 <#CLASS_4> - $	; 6B offset to; Address: CLASS_4
   4822 	DEFB	CLASS_5 <#CLASS_5> - $	; 13 offset to; Address: CLASS_5
   4823 	DEFB	CLASS_6 <#CLASS_6> - $	; 76 offset to; Address: CLASS_6
   4824 
   4825 ------------------------------------------------------------------------
   4826 
   4827 ; THE *'CHECK END'* SUBROUTINE
   4828 ------------------------------------------------------------------------
   4829 
   4830 ; Check for end of statement and that no spurious characters occur after
   4831 ; a correctly parsed statement. Since only one statement is allowed on each
   4832 ; line, the only character that may follow a statement is a NEWLINE.
   4833 ;
   4834 mark_0D1D:
   4835 *CHECK_END:*
   4836 	CALL	SYNTAX_Z <#SYNTAX_Z>
   4837 	RET	NZ		; return in runtime.
   4838 
   4839 	POP	BC		; else drop return address.
   4840 
   4841 mark_0D22:
   4842 *CHECK_2:*
   4843 	LD	A,(HL)		; fetch character.
   4844 	CP	ZX_NEWLINE	; compare to NEWLINE.
   4845 	RET	Z		; return if so.
   4846 
   4847 mark_0D26:
   4848 *REPORT_C2:*
   4849 	JR	REPORT_C <#REPORT_C>
   4850 				; 'Nonsense in BASIC'
   4851 
   4852 ------------------------------------------------------------------------
   4853 
   4854 ; COMMAND CLASSES 03, 00, 05
   4855 ------------------------------------------------------------------------
   4856 
   4857 
   4858 mark_0D28:
   4859 *CLASS_3:*
   4860 	CP	ZX_NEWLINE		;
   4861 	CALL	NUMBER_TO_STK <#NUMBER_TO_STK>
   4862 
   4863 mark_0D2D:
   4864 *CLASS_0:*
   4865 	CP	A		;
   4866 
   4867 mark_0D2E:
   4868 *CLASS_5:*
   4869 	POP	BC		;
   4870 	CALL	Z,CHECK_END <#CHECK_END>
   4871 	EX	DE,HL		;
   4872 	LD	HL,(T_ADDR)	;
   4873 	LD	C,(HL)		;
   4874 	INC	HL		;
   4875 	LD	B,(HL)		;
   4876 	EX	DE,HL		;
   4877 
   4878 mark_0D3A:
   4879 *CLASS_END:*
   4880 	PUSH	BC		;
   4881 	RET			;
   4882 
   4883 ------------------------------------------------------------------------
   4884 
   4885 ; COMMAND CLASSES 01, 02, 04, 06
   4886 ------------------------------------------------------------------------
   4887 
   4888 
   4889 mark_0D3C:
   4890 *CLASS_1:*
   4891 	CALL	LOOK_VARS <#LOOK_VARS>
   4892 
   4893 mark_0D3F:
   4894 *CLASS_4_2:*
   4895 	LD	(IY+FLAGX-RAMBASE),$00
   4896 	JR	NC,SET_STK <#SET_STK>
   4897 
   4898 	SET	1,(IY+FLAGX-RAMBASE)
   4899 	JR	NZ,SET_STRLN <#SET_STRLN>
   4900 
   4901 
   4902 mark_0D4B:
   4903 *REPORT_2:*
   4904 	RST	_ERROR_1
   4905 	DEFB	$01		; Error Report: Variable not found
   4906 ; ___
   4907 
   4908 mark_0D4D:
   4909 *SET_STK:*
   4910 	CALL	Z,STK_VAR <#STK_VAR>
   4911 	BIT	6,(IY+FLAGS-RAMBASE)	; Numeric or string result?
   4912 	JR	NZ,SET_STRLN <#SET_STRLN>
   4913 
   4914 	XOR	A		;
   4915 	CALL	SYNTAX_Z <#SYNTAX_Z>
   4916 	CALL	NZ,STK_FETCH <#STK_FETCH>
   4917 	LD	HL,FLAGX	; 
   4918 	OR	(HL)		;
   4919 	LD	(HL),A		;
   4920 	EX	DE,HL		;
   4921 
   4922 mark_0D63:
   4923 *SET_STRLN:*
   4924 	LD	(STRLEN),BC	;
   4925 	LD	(DEST),HL	; 
   4926 
   4927 ; THE *'REM'* COMMAND ROUTINE
   4928 
   4929 mark_0D6A:
   4930 *REM:*
   4931 	RET			;
   4932 
   4933 ; ___
   4934 
   4935 mark_0D6B:
   4936 *CLASS_2:*
   4937 	POP	BC		;
   4938 	LD	A,(FLAGS)	; sv
   4939 
   4940 mark_0D6F:
   4941 *INPUT_REP:*
   4942 	PUSH	AF		;
   4943 	CALL	SCANNING <#SCANNING>
   4944 	POP	AF		;
   4945 	LD	BC,LET <#LET>	; Address: LET
   4946 	LD	D,(IY+FLAGS-RAMBASE)
   4947 	XOR	D		;
   4948 	AND	$40		;
   4949 	JR	NZ,REPORT_C <#REPORT_C>	; to REPORT_C
   4950 
   4951 	BIT	7,D		;
   4952 	JR	NZ,CLASS_END <#CLASS_END>	; to CLASS_END
   4953 
   4954 	JR	CHECK_2 <#CHECK_2>		; to CHECK_2
   4955 ; ___
   4956 
   4957 mark_0D85:
   4958 *CLASS_4:*
   4959 	CALL	LOOK_VARS <#LOOK_VARS>
   4960 	PUSH	AF		;
   4961 	LD	A,C		;
   4962 	OR	$9F		;
   4963 	INC	A		;
   4964 	JR	NZ,REPORT_C <#REPORT_C>	; to REPORT_C
   4965 
   4966 	POP	AF		;
   4967 	JR	CLASS_4_2 <#CLASS_4_2>		; to CLASS_4_2
   4968 
   4969 ; ___
   4970 
   4971 mark_0D92:
   4972 *CLASS_6:*
   4973 	CALL	SCANNING <#SCANNING>
   4974 	BIT	6,(IY+FLAGS-RAMBASE)	; Numeric or string result?
   4975 	RET	NZ		;
   4976 
   4977 
   4978 mark_0D9A:
   4979 *REPORT_C:*
   4980 	RST	_ERROR_1
   4981 	DEFB	$0B		; Error Report: Nonsense in BASIC
   4982 
   4983 ------------------------------------------------------------------------
   4984 
   4985 ; THE *'NUMBER TO STACK'* SUBROUTINE
   4986 ------------------------------------------------------------------------
   4987 
   4988 ;
   4989 ;
   4990 
   4991 mark_0D9C:
   4992 *NUMBER_TO_STK:*
   4993 	JR	NZ,CLASS_6 <#CLASS_6>	; back to CLASS_6 with a non-zero number.
   4994 
   4995 	CALL	SYNTAX_Z <#SYNTAX_Z>
   4996 	RET	Z		; return if checking syntax.
   4997 
   4998 ; in runtime a zero default is placed on the calculator stack.
   4999 
   5000 	RST	_FP_CALC	;;
   5001 	DEFB	__stk_zero	;;
   5002 	DEFB	__end_calc	;;
   5003 
   5004 	RET			; return.
   5005 
   5006 ------------------------------------------------------------------------
   5007 
   5008 ; THE *'SYNTAX_Z'* SUBROUTINE
   5009 ------------------------------------------------------------------------
   5010 
   5011 ; This routine returns with zero flag set if checking syntax.
   5012 ; Calling this routine uses three instruction bytes compared to four if the
   5013 ; bit test is implemented inline.
   5014 
   5015 mark_0DA6:
   5016 *SYNTAX_Z:*
   5017 	BIT	7,(IY+FLAGS-RAMBASE)	; checking syntax only?
   5018 	RET			; return.
   5019 
   5020 ------------------------------------------------------------------------
   5021 
   5022 ; THE *'IF'* COMMAND ROUTINE
   5023 ------------------------------------------------------------------------
   5024 
   5025 ; In runtime, the class routines have evaluated the test expression and
   5026 ; the result, true or false, is on the stack.
   5027 
   5028 mark_0DAB:
   5029 *IF:*
   5030 	CALL	SYNTAX_Z <#SYNTAX_Z>
   5031 	JR	Z,IF_END <#IF_END>	; forward if checking syntax
   5032 
   5033 ; else delete the Boolean value on the calculator stack.
   5034 
   5035 	RST	_FP_CALC	;;
   5036 	DEFB	__delete	;;
   5037 	DEFB	__end_calc	;;
   5038 
   5039 ; register DE points to exponent of floating point value.
   5040 
   5041 	LD	A,(DE)		; fetch exponent.
   5042 	AND	A		; test for zero - FALSE.
   5043 	RET	Z		; return if so.
   5044 
   5045 mark_0DB6:
   5046 *IF_END:*
   5047 	JP	LINE_NULL <#LINE_NULL>		; jump back
   5048 
   5049 ------------------------------------------------------------------------
   5050 
   5051 ; THE *'FOR'* COMMAND ROUTINE
   5052 ------------------------------------------------------------------------
   5053 
   5054 ;
   5055 ;
   5056 
   5057 mark_0DB9:
   5058 *FOR:*
   5059 	CP	ZX_STEP		; is current character 'STEP' ?
   5060 	JR	NZ,F_USE_ONE <#F_USE_ONE>	; forward if not
   5061 
   5062 
   5063 	RST	_NEXT_CHAR
   5064 	CALL	CLASS_6 <#CLASS_6>		; stacks the number
   5065 	CALL	CHECK_END <#CHECK_END>
   5066 	JR	F_REORDER <#F_REORDER>	; forward to F_REORDER
   5067 ; ___
   5068 
   5069 mark_0DC6:
   5070 *F_USE_ONE:*
   5071 	CALL	CHECK_END <#CHECK_END>
   5072 
   5073 	RST	_FP_CALC	;;
   5074 	DEFB	__stk_one	;;
   5075 	DEFB	__end_calc	;;
   5076 
   5077 
   5078 
   5079 mark_0DCC:
   5080 *F_REORDER:*
   5081 	RST	_FP_CALC	;;	v, l, s.
   5082 	DEFB	__st_mem_0	;;	v, l, s.
   5083 	DEFB	__delete	;;	v, l.
   5084 	DEFB	__exchange	;;	l, v.
   5085 	DEFB	__get_mem_0	;;	l, v, s.
   5086 	DEFB	__exchange	;;	l, s, v.
   5087 	DEFB	__end_calc	;;	l, s, v.
   5088 
   5089 	CALL	LET <#LET>
   5090 
   5091 	LD	(MEM),HL	; set MEM to address variable.
   5092 	DEC	HL		; point to letter.
   5093 	LD	A,(HL)		;
   5094 	SET	7,(HL)		;
   5095 	LD	BC,$0006	;
   5096 	ADD	HL,BC		;
   5097 	RLCA			;
   5098 	JR	C,F_LMT_STP <#F_LMT_STP>
   5099 
   5100 	SLA	C		;
   5101 	CALL	MAKE_ROOM <#MAKE_ROOM>
   5102 	INC	HL		;
   5103 
   5104 mark_0DEA:
   5105 *F_LMT_STP:*
   5106 	PUSH	HL		;
   5107 
   5108 	RST	_FP_CALC	;; 
   5109 	DEFB	__delete	;;
   5110 	DEFB	__delete	;;
   5111 	DEFB	__end_calc	;;
   5112 
   5113 	POP	HL		;
   5114 	EX	DE,HL		;
   5115 
   5116 	LD	C,$0A		; ten bytes to be moved.
   5117 	LDIR			; copy bytes
   5118 
   5119 	LD	HL,(PPC)	; set HL to system variable PPC current line.
   5120 	EX	DE,HL		; transfer to DE, variable pointer to HL.
   5121 	INC	DE		; loop start will be this line + 1 at least.
   5122 	LD	(HL),E		;
   5123 	INC	HL		;
   5124 	LD	(HL),D		;
   5125 	CALL	NEXT_LOOP <#NEXT_LOOP>	; considers an initial pass.
   5126 	RET	NC		; return if possible.
   5127 
   5128 ; else program continues from point following matching NEXT.
   5129 
   5130 	BIT	7,(IY+PPC_hi-RAMBASE)
   5131 	RET	NZ		; return if over 32767 ???
   5132 
   5133 	LD	B,(IY+STRLEN_lo-RAMBASE)	; fetch variable name from STRLEN_lo
   5134 	RES	6,B		; make a true letter.
   5135 	LD	HL,(NXTLIN)	; set HL from NXTLIN
   5136 
   5137 ; now enter a loop to look for matching next.
   5138 
   5139 mark_0E0E:
   5140 *NXTLIN_NO:*
   5141 	LD	A,(HL)		; fetch high byte of line number.
   5142 	AND	$C0		; mask off low bits $3F
   5143 	JR	NZ,FOR_END <#FOR_END>	; forward at end of program
   5144 
   5145 	PUSH	BC		; save letter
   5146 	CALL	NEXT_ONE <#NEXT_ONE>	; finds next line.
   5147 	POP	BC		; restore letter
   5148 
   5149 	INC	HL		; step past low byte
   5150 	INC	HL		; past the
   5151 	INC	HL		; line length.
   5152 	CALL	TEMP_PTR1 <#TEMP_PTR1>	; sets CH_ADD
   5153 
   5154 	RST	_GET_CHAR
   5155 	CP	ZX_NEXT		;
   5156 	EX	DE,HL		; next line to HL.
   5157 	JR	NZ,NXTLIN_NO <#NXTLIN_NO>	; back with no match
   5158 
   5159 ;
   5160 
   5161 	EX	DE,HL		; restore pointer.
   5162 
   5163 	RST	_NEXT_CHAR	; advances and gets letter in A.
   5164 	EX	DE,HL		; save pointer
   5165 	CP	B		; compare to variable name.
   5166 	JR	NZ,NXTLIN_NO <#NXTLIN_NO>	; back with mismatch
   5167 
   5168 mark_0E2A:
   5169 *FOR_END:*
   5170 	LD	(NXTLIN),HL	; update system variable NXTLIN
   5171 	RET			; return.
   5172 
   5173 ------------------------------------------------------------------------
   5174 
   5175 ; THE *'NEXT'* COMMAND ROUTINE
   5176 ------------------------------------------------------------------------
   5177 
   5178 ;
   5179 ;
   5180 
   5181 mark_0E2E:
   5182 *NEXT:*
   5183 	BIT	1,(IY+FLAGX-RAMBASE)
   5184 	JP	NZ,REPORT_2 <#REPORT_2>
   5185 
   5186 	LD	HL,(DEST)
   5187 	BIT	7,(HL)
   5188 	JR	Z,REPORT_1 <#REPORT_1>
   5189 
   5190 	INC	HL		;
   5191 	LD	(MEM),HL	;
   5192 
   5193 	RST	_FP_CALC	;;
   5194 	DEFB	__get_mem_0	;;
   5195 	DEFB	__get_mem_2	;;
   5196 	DEFB	__addition	;;
   5197 	DEFB	__st_mem_0	;;
   5198 	DEFB	__delete	;;
   5199 	DEFB	__end_calc	;;
   5200 
   5201 	CALL	NEXT_LOOP <#NEXT_LOOP>
   5202 	RET	C		;
   5203 
   5204 	LD	HL,(MEM)	; 
   5205 	LD	DE,$000F	;
   5206 	ADD	HL,DE		;
   5207 	LD	E,(HL)		;
   5208 	INC	HL		;
   5209 	LD	D,(HL)		;
   5210 	EX	DE,HL		;
   5211 	JR	GOTO_2 <#GOTO_2>
   5212 ; ___
   5213 
   5214 mark_0E58:
   5215 *REPORT_1:*
   5216 	RST	_ERROR_1
   5217 	DEFB	$00		; Error Report: NEXT without FOR
   5218 
   5219 
   5220 ------------------------------------------------------------------------
   5221 
   5222 ; THE *'NEXT_LOOP'* SUBROUTINE
   5223 ------------------------------------------------------------------------
   5224 
   5225 ;
   5226 ;
   5227 
   5228 mark_0E5A:
   5229 *NEXT_LOOP:*
   5230 	RST	_FP_CALC	;;
   5231 	DEFB	__get_mem_1	;;
   5232 	DEFB	__get_mem_0	;;
   5233 	DEFB	__get_mem_2	;;
   5234 	DEFB	__less_0	;;
   5235 	DEFB	__jump_true	;;
   5236 	DEFB	LMT_V_VAL <#LMT_V_VAL> - $	;;
   5237 
   5238 	DEFB	__exchange	;;
   5239 
   5240 mark_0E62:
   5241 *LMT_V_VAL:*
   5242 	DEFB	__subtract	;;
   5243 	DEFB	__greater_0	;;
   5244 	DEFB	__jump_true	;;
   5245 	DEFB	IMPOSS <#IMPOSS> - $	;;
   5246 
   5247 	DEFB	__end_calc	;;
   5248 
   5249 	AND	A		; clear carry flag
   5250 	RET			; return.
   5251 ; ___
   5252 
   5253 mark_0E69:
   5254 *IMPOSS:*
   5255 	DEFB	__end_calc	;;
   5256 
   5257 	SCF			; set carry flag
   5258 	RET			; return.
   5259 
   5260 ------------------------------------------------------------------------
   5261 
   5262 ; THE *'RAND'* COMMAND ROUTINE
   5263 ------------------------------------------------------------------------
   5264 
   5265 ; The keyword was *'RANDOMISE'* on the ZX80, is 'RAND' here on the ZX81 and
   5266 ; becomes 'RANDOMIZE' on the ZX Spectrum.
   5267 ; In all invocations the procedure is the same - to set the SEED system variable
   5268 ; with a supplied integer value or to use a time-based value if no number, or
   5269 ; zero, is supplied.
   5270 
   5271 mark_0E6C:
   5272 *RAND:*
   5273 	CALL	FIND_INT <#FIND_INT>
   5274 	LD	A,B		; test value
   5275 	OR	C		; for zero
   5276 	JR	NZ,SET_SEED <#SET_SEED>	; forward if not zero
   5277 
   5278 	LD	BC,(FRAMES)	; fetch value of FRAMES system variable.
   5279 
   5280 mark_0E77:
   5281 *SET_SEED:*
   5282 	LD	(SEED),BC	; update the SEED system variable.
   5283 	RET			; return.
   5284 
   5285 ------------------------------------------------------------------------
   5286 
   5287 ; THE *'CONT'* COMMAND ROUTINE
   5288 ------------------------------------------------------------------------
   5289 
   5290 ; Another abbreviated command. ROM space was really tight.
   5291 ; CONTINUE at the line number that was set when break was pressed.
   5292 ; Sometimes the current line, sometimes the next line.
   5293 
   5294 mark_0E7C:
   5295 *CONT:*
   5296 	LD	HL,(OLDPPC)	; set HL from system variable OLDPPC
   5297 	JR	GOTO_2 <#GOTO_2>		; forward
   5298 
   5299 ------------------------------------------------------------------------
   5300 
   5301 ; THE *'GOTO'* COMMAND ROUTINE
   5302 ------------------------------------------------------------------------
   5303 
   5304 ; This token also suffered from the shortage of room and there is no space
   5305 ; getween GO and TO as there is on the ZX80 and ZX Spectrum. The same also 
   5306 ; applies to the GOSUB keyword.
   5307 
   5308 mark_0E81:
   5309 *GOTO:*
   5310 	CALL	FIND_INT <#FIND_INT>
   5311 	LD	H,B		;
   5312 	LD	L,C		;
   5313 
   5314 mark_0E86:
   5315 *GOTO_2:*
   5316 	LD	A,H		;
   5317 	CP	$F0		; ZX_LIST ???
   5318 	JR	NC,REPORT_B <#REPORT_B>
   5319 
   5320 	CALL	LINE_ADDR <#LINE_ADDR>
   5321 	LD	(NXTLIN),HL	; sv
   5322 	RET			;
   5323 
   5324 ------------------------------------------------------------------------
   5325 
   5326 ; THE *'POKE'* COMMAND ROUTINE
   5327 ------------------------------------------------------------------------
   5328 
   5329 
   5330 mark_0E92:
   5331 *POKE:*
   5332 	CALL	FP_TO_A <#FP_TO_A>
   5333 	JR	C,REPORT_B <#REPORT_B>	; forward, with overflow
   5334 
   5335 	JR	Z,POKE_SAVE <#POKE_SAVE>	; forward, if positive
   5336 
   5337 	NEG			; negate
   5338 
   5339 mark_0E9B:
   5340 *POKE_SAVE:*
   5341 	PUSH	AF		; preserve value.
   5342 	CALL	FIND_INT <#FIND_INT>		; gets address in BC
   5343 				; invoking the error routine with overflow
   5344 				; or a negative number.
   5345 	POP	AF		; restore value.
   5346 
   5347 ; Note. the next two instructions are legacy code from the ZX80 and
   5348 ; inappropriate here.
   5349 
   5350 	BIT	7,(IY+ERR_NR-RAMBASE)	; test ERR_NR - is it still $FF ?
   5351 	RET	Z		; return with error.
   5352 
   5353 	LD	(BC),A		; update the address contents.
   5354 	RET			; return.
   5355 
   5356 ------------------------------------------------------------------------
   5357 
   5358 ; THE *'FIND INTEGER'* SUBROUTINE
   5359 ------------------------------------------------------------------------
   5360 
   5361 
   5362 mark_0EA7:
   5363 *FIND_INT:*
   5364 	CALL	FP_TO_BC <#FP_TO_BC>
   5365 	JR	C,REPORT_B <#REPORT_B>	; forward with overflow
   5366 
   5367 	RET	Z		; return if positive (0-65535).
   5368 
   5369 
   5370 mark_0EAD:
   5371 *REPORT_B:*
   5372 	RST	_ERROR_1
   5373 	DEFB	$0A		; Error Report: Integer out of range
   5374 ;
   5375 ; Seems stupid, $0A is 10 but the ERROR_CODE_INTEGER_OUT_OF_RANGE is 11
   5376 ; maybe gets incremented ???
   5377 
   5378 ------------------------------------------------------------------------
   5379 
   5380 ; THE *'RUN'* COMMAND ROUTINE
   5381 ------------------------------------------------------------------------
   5382 
   5383 
   5384 mark_0EAF:
   5385 *RUN:*
   5386 	CALL	GOTO <#GOTO>
   5387 	JP	CLEAR <#CLEAR>
   5388 
   5389 ------------------------------------------------------------------------
   5390 
   5391 ; THE *'GOSUB'* COMMAND ROUTINE
   5392 ------------------------------------------------------------------------
   5393 
   5394 
   5395 mark_0EB5:
   5396 *GOSUB:*
   5397 	LD	HL,(PPC)	;
   5398 	INC	HL		;
   5399 	EX	(SP),HL		;
   5400 	PUSH	HL		;
   5401 	LD	(ERR_SP),SP	; set the error stack pointer - ERR_SP
   5402 	CALL	GOTO <#GOTO>
   5403 	LD	BC,6		;
   5404 
   5405 ------------------------------------------------------------------------
   5406 
   5407 ; THE *'TEST ROOM'* SUBROUTINE
   5408 ------------------------------------------------------------------------
   5409 
   5410 ;
   5411 ; checks ther is room for 36 bytes on the stack
   5412 ;
   5413 mark_0EC5:
   5414 *TEST_ROOM:*
   5415 	LD	HL,(STKEND)	;
   5416 	ADD	HL,BC		; HL = STKEND + BC
   5417 	JR	C,REPORT_4 <#REPORT_4>
   5418 
   5419 	EX	DE,HL		; DE = STKEND + BC
   5420 	LD	HL,$0024	; 36 decimal
   5421 	ADD	HL,DE		; HL = 36 + STKEND + BC
   5422 	SBC	HL,SP		; HL = 36 + STKEND + BC - SP
   5423 	RET	C		;
   5424 
   5425 mark_0ED3:
   5426 *REPORT_4:*
   5427 	LD	L,3		;
   5428 	JP	ERROR_3 <#ERROR_3>
   5429 
   5430 ------------------------------------------------------------------------
   5431 
   5432 ; THE *'RETURN'* COMMAND ROUTINE
   5433 ------------------------------------------------------------------------
   5434 
   5435 
   5436 mark_0ED8:
   5437 *RETURN:*
   5438 	POP	HL		;
   5439 	EX	(SP),HL	;
   5440 	LD	A,H		;
   5441 	CP	$3E		;
   5442 	JR	Z,REPORT_7 <#REPORT_7>
   5443 
   5444 	LD	(ERR_SP),SP	;
   5445 	JR	GOTO_2 <#GOTO_2>		; back
   5446 ; ___
   5447 
   5448 mark_0EE5:
   5449 *REPORT_7:*
   5450 	EX	(SP),HL	;
   5451 	PUSH	HL		;
   5452 
   5453 	RST	_ERROR_1
   5454 	DEFB	6		; Error Report: RETURN without GOSUB
   5455 
   5456 ;
   5457 ; Contradicts BASIC manual:
   5458 ; 7 is ERROR_CODE_RETURN_WITHOUT_GOSUB
   5459 ; 6 is ERROR_CODE_ARITHMETIC_OVERFLOW
   5460 ;
   5461 
   5462 ------------------------------------------------------------------------
   5463 
   5464 ; THE *'INPUT'* COMMAND ROUTINE
   5465 ------------------------------------------------------------------------
   5466 
   5467 
   5468 mark_0EE9:
   5469 *INPUT:*
   5470 	BIT	7,(IY+PPC_hi-RAMBASE)
   5471 	JR	NZ,REPORT_8 <#REPORT_8>	; to REPORT_8
   5472 
   5473 	CALL	X_TEMP <#X_TEMP>
   5474 	LD	HL,FLAGX	; 
   5475 	SET	5,(HL)		;
   5476 	RES	6,(HL)		;
   5477 	LD	A,(FLAGS)	;
   5478 	AND	$40		; 64
   5479 	LD	BC,2		;
   5480 	JR	NZ,PROMPT <#PROMPT>	; to PROMPT
   5481 
   5482 	LD	C,$04		;
   5483 
   5484 mark_0F05:
   5485 *PROMPT:*
   5486 	OR	(HL)		;
   5487 	LD	(HL),A		;
   5488 
   5489 	RST	_BC_SPACES
   5490 	LD	(HL),ZX_NEWLINE
   5491 	LD	A,C		;
   5492 	RRCA			;
   5493 	RRCA			;
   5494 	JR	C,ENTER_CUR <#ENTER_CUR>
   5495 
   5496 	LD	A,$0B		; ZX_QUOTE ???
   5497 	LD	(DE),A		;
   5498 	DEC	HL		;
   5499 	LD	(HL),A		;
   5500 
   5501 mark_0F14:
   5502 *ENTER_CUR:*
   5503 	DEC	HL		;
   5504 	LD	(HL),ZX_CURSOR	;
   5505 	LD	HL,(S_POSN)	;
   5506 	LD	(T_ADDR),HL	;
   5507 	POP	HL		;
   5508 	JP	LOWER <#LOWER>
   5509 
   5510 ; ___
   5511 
   5512 mark_0F21:
   5513 *REPORT_8:*
   5514 	RST	_ERROR_1
   5515 	DEFB	7		; Error Report: End of file
   5516 
   5517 ------------------------------------------------------------------------
   5518 
   5519 ; THE *'PAUSE'* COMMAND ROUTINE
   5520 ------------------------------------------------------------------------
   5521 
   5522 
   5523 mark_0F23:
   5524 *FAST:*
   5525 	CALL	SET_FAST <#SET_FAST>
   5526 	RES	6,(IY+CDFLAG-RAMBASE)
   5527 	RET			; return.
   5528 
   5529 ------------------------------------------------------------------------
   5530 
   5531 ; THE *'SLOW'* COMMAND ROUTINE
   5532 ------------------------------------------------------------------------
   5533 
   5534 
   5535 mark_0F2B:
   5536 *SLOW:*
   5537 	SET	6,(IY+CDFLAG-RAMBASE)
   5538 	JP	SLOW_FAST <#SLOW_FAST>
   5539 
   5540 ------------------------------------------------------------------------
   5541 
   5542 ; THE *'PAUSE'* COMMAND ROUTINE
   5543 ------------------------------------------------------------------------
   5544 
   5545 
   5546 mark_0F32:
   5547 *PAUSE:*
   5548 	CALL	FIND_INT <#FIND_INT>
   5549 	CALL	SET_FAST <#SET_FAST>
   5550 	LD	H,B		;
   5551 	LD	L,C		;
   5552 	CALL	DISPLAY_P <#DISPLAY_P>
   5553 
   5554 	LD	(IY+FRAMES_hi-RAMBASE),$FF
   5555 
   5556 	CALL	SLOW_FAST <#SLOW_FAST>
   5557 	JR	DEBOUNCE <#DEBOUNCE>
   5558 
   5559 ------------------------------------------------------------------------
   5560 
   5561 ; THE *'BREAK'* SUBROUTINE
   5562 ------------------------------------------------------------------------
   5563 
   5564 
   5565 mark_0F46:
   5566 *BREAK_1:*
   5567 	LD	A,$7F			; read port $7FFE - keys B,N,M,.,SPACE.
   5568 	IN	A,(IO_PORT_KEYBOARD_RD)	;
   5569 	RRA				; carry will be set if space not pressed.
   5570 
   5571 ------------------------------------------------------------------------
   5572 
   5573 ; THE *'DEBOUNCE'* SUBROUTINE
   5574 ------------------------------------------------------------------------
   5575 
   5576 
   5577 mark_0F4B:
   5578 *DEBOUNCE:*
   5579 	RES	0,(IY+CDFLAG-RAMBASE)	; update
   5580 	LD	A,$FF		;
   5581 	LD	(DEBOUNCE_VAR),A	; update
   5582 	RET			; return.
   5583 
   5584 
   5585 ------------------------------------------------------------------------
   5586 
   5587 ; THE *'SCANNING'* SUBROUTINE
   5588 ------------------------------------------------------------------------
   5589 
   5590 ; This recursive routine is where the ZX81 gets its power.
   5591 ; Provided there is enough memory it can evaluate 
   5592 ; an expression of unlimited complexity.
   5593 ; Note. there is no unary plus so, as on the ZX80, PRINT +1 gives a syntax error.
   5594 ; PRINT +1 works on the Spectrum but so too does PRINT + "STRING".
   5595 
   5596 mark_0F55:
   5597 *SCANNING:*
   5598 	RST	_GET_CHAR
   5599 	LD	B,0		; set B register to zero.
   5600 	PUSH	BC		; stack zero as a priority end-marker.
   5601 
   5602 mark_0F59:
   5603 *S_LOOP_1:*
   5604 	CP	ZX_RND
   5605 	JR	NZ,S_TEST_PI <#S_TEST_PI>	; forward, if not, to S_TEST_PI
   5606 
   5607 ------------------------------------------------------------------------
   5608 
   5609 ; THE *'RND'* FUNCTION
   5610 ------------------------------------------------------------------------
   5611 
   5612 *RND:*
   5613 
   5614 	CALL	SYNTAX_Z <#SYNTAX_Z>
   5615 	JR	Z,S_JPI_END <#S_JPI_END>	; forward if checking syntax to S_JPI_END
   5616 
   5617 	LD	BC,(SEED)	; sv
   5618 	CALL	STACK_BC <#STACK_BC>
   5619 
   5620 	RST	_FP_CALC	;;
   5621 	DEFB	__stk_one	;;
   5622 	DEFB	__addition	;;
   5623 	DEFB	__stk_data	;;
   5624 	DEFB	$37		;;Exponent: $87, Bytes: 1
   5625 	DEFB	$16		;;(+00,+00,+00)
   5626 	DEFB	__multiply	;;
   5627 	DEFB	__stk_data	;;
   5628 	DEFB	$80		;;Bytes: 3
   5629 	DEFB	$41		;;Exponent $91
   5630 	DEFB	$00,$00,$80	;;(+00)
   5631 	DEFB	__n_mod_m	;;
   5632 	DEFB	__delete	;;
   5633 	DEFB	__stk_one	;;
   5634 	DEFB	__subtract	;;
   5635 	DEFB	__duplicate	;;
   5636 	DEFB	__end_calc	;;
   5637 
   5638 	CALL	FP_TO_BC <#FP_TO_BC>
   5639 	LD	(SEED),BC	; update the SEED system variable.
   5640 	LD	A,(HL)		; HL addresses the exponent of the last value.
   5641 	AND	A		; test for zero
   5642 	JR	Z,S_JPI_END <#S_JPI_END>	; forward, if so
   5643 
   5644 	SUB	$10		; else reduce exponent by sixteen
   5645 	LD	(HL),A		; thus dividing by 65536 for last value.
   5646 
   5647 mark_0F8A:
   5648 *S_JPI_END:*
   5649 	JR	S_PI_END <#S_PI_END>	; forward
   5650 
   5651 ; ___
   5652 
   5653 mark_0F8C:
   5654 *S_TEST_PI:*
   5655 	CP	ZX_PI		; the 'PI' character
   5656 	JR	NZ,S_TST_INK <#S_TST_INK>	; forward, if not
   5657 
   5658 ------------------------------------------------------------------------
   5659 
   5660 ; THE *'PI'* EVALUATION
   5661 ------------------------------------------------------------------------
   5662 
   5663 
   5664 	CALL	SYNTAX_Z <#SYNTAX_Z>
   5665 	JR	Z,S_PI_END <#S_PI_END>	; forward if checking syntax
   5666 
   5667 
   5668 	RST	_FP_CALC	;;
   5669 	DEFB	__stk_half_pi	;;
   5670 	DEFB	__end_calc	;;
   5671 
   5672 	INC	(HL)		; double the exponent giving PI on the stack.
   5673 
   5674 mark_0F99:
   5675 *S_PI_END:*
   5676 	RST	_NEXT_CHAR	; advances character pointer.
   5677 
   5678 	JP	S_NUMERIC <#S_NUMERIC>	; jump forward to set the flag
   5679 				; to signal numeric result before advancing.
   5680 
   5681 ; ___
   5682 
   5683 mark_0F9D:
   5684 *S_TST_INK:*
   5685 	CP	ZX_INKEY_STR	;
   5686 	JR	NZ,S_ALPHANUM <#S_ALPHANUM>	; forward, if not
   5687 
   5688 ------------------------------------------------------------------------
   5689 
   5690 ; THE *'INKEY$'* EVALUATION
   5691 ------------------------------------------------------------------------
   5692 
   5693 
   5694 	CALL	KEYBOARD <#KEYBOARD>
   5695 	LD	B,H		;
   5696 	LD	C,L		;
   5697 	LD	D,C		;
   5698 	INC	D		;
   5699 	CALL	NZ,DECODE <#DECODE>
   5700 	LD	A,D		;
   5701 	ADC	A,D		;
   5702 	LD	B,D		;
   5703 	LD	C,A		;
   5704 	EX	DE,HL		;
   5705 	JR	S_STRING <#S_STRING>		; forward
   5706 
   5707 ; ___
   5708 
   5709 mark_0FB2:
   5710 *S_ALPHANUM:*
   5711 	CALL	ALPHANUM <#ALPHANUM>
   5712 	JR	C,S_LTR_DGT <#S_LTR_DGT>	; forward, if alphanumeric
   5713 
   5714 	CP	ZX_PERIOD	; is character a '.' ?
   5715 	JP	Z,S_DECIMAL <#S_DECIMAL>	; jump forward if so
   5716 
   5717 	LD	BC,$09D8	; prepare priority 09, operation 'subtract'
   5718 	CP	ZX_MINUS	; is character unary minus '-' ?
   5719 	JR	Z,S_PUSH_PO <#S_PUSH_PO>	; forward, if so
   5720 
   5721 	CP	ZX_BRACKET_LEFT	; is character a '(' ?
   5722 	JR	NZ,S_QUOTE <#S_QUOTE>	; forward if not
   5723 
   5724 	CALL	CH_ADD_PLUS_1 <#CH_ADD_PLUS_1>	; advances character pointer.
   5725 
   5726 	CALL	SCANNING <#SCANNING>	; recursively call to evaluate the sub_expression.
   5727 
   5728 	CP	ZX_BRACKET_RIGHT; is subsequent character a ')' ?
   5729 	JR	NZ,S_RPT_C <#S_RPT_C>	; forward if not
   5730 
   5731 
   5732 	CALL	CH_ADD_PLUS_1 <#CH_ADD_PLUS_1>	; advances.
   5733 	JR	S_J_CONT_3 <#S_J_CONT_3>	; relative jump to S_JP_CONT3 and then S_CONT3
   5734 
   5735 ; ___
   5736 
   5737 ; consider a quoted string e.g. PRINT "Hooray!"
   5738 ; Note. quotes are not allowed within a string.
   5739 
   5740 mark_0FD6:
   5741 *S_QUOTE:*
   5742 	CP	ZX_QUOTE	; is character a quote (") ?
   5743 	JR	NZ,S_FUNCTION <#S_FUNCTION>	; forward, if not
   5744 
   5745 	CALL	CH_ADD_PLUS_1 <#CH_ADD_PLUS_1>	; advances
   5746 	PUSH	HL		; * save start of string.
   5747 	JR	S_QUOTE_S <#S_QUOTE_S>	; forward
   5748 
   5749 ; ___
   5750 
   5751 
   5752 mark_0FE0:
   5753 *S_Q_AGAIN:*
   5754 	CALL	CH_ADD_PLUS_1 <#CH_ADD_PLUS_1>
   5755 
   5756 mark_0FE3:
   5757 *S_QUOTE_S:*
   5758 	CP	ZX_QUOTE	; is character a '"' ?
   5759 	JR	NZ,S_Q_NL <#S_Q_NL>	; forward if not to S_Q_NL
   5760 
   5761 	POP	DE		; * retrieve start of string
   5762 	AND	A		; prepare to subtract.
   5763 	SBC	HL,DE		; subtract start from current position.
   5764 	LD	B,H		; transfer this length
   5765 	LD	C,L		; to the BC register pair.
   5766 
   5767 mark_0FED:
   5768 *S_STRING:*
   5769 	LD	HL,FLAGS	; address system variable FLAGS
   5770 	RES	6,(HL)		; signal string result
   5771 	BIT	7,(HL)		; test if checking syntax.
   5772 
   5773 	CALL	NZ,STK_STO_STR <#STK_STO_STR>	; in run-time stacks the
   5774 				; string descriptor - start DE, length BC.
   5775 
   5776 	RST	_NEXT_CHAR	; advances pointer.
   5777 
   5778 mark_0FF8:
   5779 *S_J_CONT_3:*
   5780 	JP	S_CONT_3 <#S_CONT_3>
   5781 
   5782 ; ___
   5783 
   5784 ; A string with no terminating quote has to be considered.
   5785 
   5786 mark_0FFB:
   5787 *S_Q_NL:*
   5788 	CP	ZX_NEWLINE
   5789 	JR	NZ,S_Q_AGAIN <#S_Q_AGAIN>	; loop back if not
   5790 
   5791 mark_0FFF:
   5792 *S_RPT_C:*
   5793 	JP	REPORT_C <#REPORT_C>
   5794 ; ___
   5795 
   5796 mark_1002:
   5797 *S_FUNCTION:*
   5798 	SUB	$C4		; subtract 'CODE' reducing codes
   5799 				; CODE thru '<>' to range $00 - $XX
   5800 	JR	C,S_RPT_C <#S_RPT_C>	; back, if less
   5801 
   5802 ; test for NOT the last function in character set.
   5803 
   5804 	LD	BC,$04EC	; prepare priority $04, operation 'not'
   5805 	CP	$13		; compare to 'NOT'	( - CODE)
   5806 	JR	Z,S_PUSH_PO <#S_PUSH_PO>	; forward, if so
   5807 
   5808 	JR	NC,S_RPT_C <#S_RPT_C>	; back with anything higher
   5809 
   5810 ; else is a function 'CODE' thru 'CHR$'
   5811 
   5812 	LD	B,$10		; priority sixteen binds all functions to
   5813 				; arguments removing the need for brackets.
   5814 
   5815 	ADD	A,$D9		; add $D9 to give range $D9 thru $EB
   5816 				; bit 6 is set to show numeric argument.
   5817 				; bit 7 is set to show numeric result.
   5818 
   5819 ; now adjust these default argument/result indicators.
   5820 
   5821 	LD	C,A		; save code in C
   5822 
   5823 	CP	$DC		; separate 'CODE', 'VAL', 'LEN'
   5824 	JR	NC,S_NUMBER_TO_STRING <#S_NUMBER_TO_STRING>	; skip forward if string operand
   5825 
   5826 	RES	6,C		; signal string operand.
   5827 
   5828 mark_101A:
   5829 *S_NUMBER_TO_STRING:*
   5830 	CP	$EA		; isolate top of range 'STR$' and 'CHR$'
   5831 	JR	C,S_PUSH_PO <#S_PUSH_PO>	; skip forward with others
   5832 
   5833 	RES	7,C		; signal string result.
   5834 
   5835 mark_1020:
   5836 *S_PUSH_PO:*
   5837 	PUSH	BC		; push the priority/operation
   5838 
   5839 	RST	_NEXT_CHAR
   5840 	JP	S_LOOP_1 <#S_LOOP_1>		; jump back
   5841 ; ___
   5842 
   5843 mark_1025:
   5844 *S_LTR_DGT:*
   5845 	CP	ZX_A		; compare to 'A'.
   5846 	JR	C,S_DECIMAL <#S_DECIMAL>	; forward if less to S_DECIMAL
   5847 
   5848 	CALL	LOOK_VARS <#LOOK_VARS>
   5849 	JP	C,REPORT_2 <#REPORT_2>	; back if not found
   5850 				; a variable is always 'found' when checking
   5851 				; syntax.
   5852 
   5853 	CALL	Z,STK_VAR <#STK_VAR>	; stacks string parameters or
   5854 				; returns cell location if numeric.
   5855 
   5856 	LD	A,(FLAGS)	; fetch FLAGS
   5857 	CP	$C0		; compare to numeric result/numeric operand
   5858 	JR	C,S_CONT_2 <#S_CONT_2>	; forward if not numeric
   5859 
   5860 	INC	HL		; address numeric contents of variable.
   5861 	LD	DE,(STKEND)	; set destination to STKEND
   5862 	CALL	MOVE_FP <#MOVE_FP>		; stacks the five bytes
   5863 	EX	DE,HL		; transfer new free location from DE to HL.
   5864 	LD	(STKEND),HL	; update STKEND system variable.
   5865 	JR	S_CONT_2 <#S_CONT_2>		; forward
   5866 ; ___
   5867 
   5868 ; The Scanning Decimal routine is invoked when a decimal point or digit is
   5869 ; found in the expression.
   5870 ; When checking syntax, then the 'hidden floating point' form is placed
   5871 ; after the number in the BASIC line.
   5872 ; In run-time, the digits are skipped and the floating point number is picked
   5873 ; up.
   5874 
   5875 mark_1047:
   5876 *S_DECIMAL:*
   5877 	CALL	SYNTAX_Z <#SYNTAX_Z>
   5878 	JR	NZ,S_STK_DEC <#S_STK_DEC>	; forward in run-time
   5879 
   5880 	CALL	DEC_TO_FP <#DEC_TO_FP>
   5881 
   5882 	RST	_GET_CHAR	; advances HL past digits
   5883 	LD	BC,$0006	; six locations are required.
   5884 	CALL	MAKE_ROOM <#MAKE_ROOM>
   5885 	INC	HL		; point to first new location
   5886 	LD	(HL),$7E	; insert the number marker 126 decimal.
   5887 	INC	HL		; increment
   5888 	EX	DE,HL		; transfer destination to DE.
   5889 	LD	HL,(STKEND)	; set HL from STKEND which points to the
   5890 				; first location after the 'last value'
   5891 	LD	C,$05		; five bytes to move.
   5892 	AND	A		; clear carry.
   5893 	SBC	HL,BC		; subtract five pointing to 'last value'.
   5894 	LD	(STKEND),HL	; update STKEND thereby 'deleting the value.
   5895 
   5896 	LDIR			; copy the five value bytes.
   5897 
   5898 	EX	DE,HL		; basic pointer to HL which may be white-space
   5899 				; following the number.
   5900 	DEC	HL		; now points to last of five bytes.
   5901 	CALL	TEMP_PTR1 <#TEMP_PTR1>		; advances the character
   5902 				; address skipping any white-space.
   5903 	JR	S_NUMERIC <#S_NUMERIC>		; forward
   5904 				; to signal a numeric result.
   5905 ; ___
   5906 ; In run-time the branch is here when a digit or point is encountered.
   5907 
   5908 mark_106F:
   5909 *S_STK_DEC:*
   5910 	RST	_NEXT_CHAR
   5911 	CP	$7E		; compare to 'number marker'
   5912 	JR	NZ,S_STK_DEC <#S_STK_DEC>	; loop back until found
   5913 				; skipping all the digits.
   5914 
   5915 	INC	HL		; point to first of five hidden bytes.
   5916 	LD	DE,(STKEND)	; set destination from STKEND system variable
   5917 	CALL	MOVE_FP <#MOVE_FP>		; stacks the number.
   5918 	LD	(STKEND),DE	; update system variable STKEND.
   5919 	LD	(CH_ADD),HL	; update system variable CH_ADD.
   5920 
   5921 mark_1083:
   5922 *S_NUMERIC:*
   5923 	SET	6,(IY+FLAGS-RAMBASE)	; Signal numeric result
   5924 
   5925 mark_1087:
   5926 *S_CONT_2:*
   5927 	RST	_GET_CHAR
   5928 
   5929 mark_1088:
   5930 *S_CONT_3:*
   5931 	CP	ZX_BRACKET_LEFT		; compare to opening bracket '('
   5932 	JR	NZ,S_OPERTR <#S_OPERTR>	; forward if not
   5933 
   5934 	BIT	6,(IY+FLAGS-RAMBASE)	; Numeric or string result?
   5935 	JR	NZ,S_LOOP <#S_LOOP>	; forward if numeric
   5936 
   5937 ; else is a string
   5938 
   5939 	CALL	SLICING <#SLICING>
   5940 
   5941 	RST	_NEXT_CHAR
   5942 	JR	S_CONT_3 <#S_CONT_3>	; back
   5943 ; ___
   5944 ; the character is now manipulated to form an equivalent in the table of
   5945 ; calculator literals. This is quite cumbersome and in the ZX Spectrum a
   5946 ; simple look-up table was introduced at this point.
   5947 
   5948 mark_1098:
   5949 *S_OPERTR:*
   5950 	LD	BC,$00C3	; prepare operator 'subtract' as default.
   5951 				; also set B to zero for later indexing.
   5952 
   5953 	CP	ZX_GREATER_THAN	; is character '>' ?
   5954 	JR	C,S_LOOP <#S_LOOP>	; forward if less, as
   5955 				; we have reached end of meaningful expression
   5956 
   5957 	SUB	ZX_MINUS	; is character '-' ?
   5958 	JR	NC,SUBMLTDIV <#SUBMLTDIV>	; forward with - * / and '**' '<>'
   5959 
   5960 	ADD	A,13		; increase others by thirteen
   5961 				; $09 '>' thru $0C '+'
   5962 	JR	GET_PRIO <#GET_PRIO>	; forward
   5963 
   5964 ; ___
   5965 
   5966 mark_10A7:
   5967 *SUBMLTDIV:*
   5968 	CP	$03		; isolate $00 '-', $01 '*', $02 '/'
   5969 	JR	C,GET_PRIO <#GET_PRIO>	; forward if so
   5970 
   5971 ; else possibly originally $D8 '**' thru $DD '<>' already reduced by $16
   5972 
   5973 	SUB	$C2		; giving range $00 to $05
   5974 	JR	C,S_LOOP <#S_LOOP>	; forward if less
   5975 
   5976 	CP	$06		; test the upper limit for nonsense also
   5977 	JR	NC,S_LOOP <#S_LOOP>	; forward if so
   5978 
   5979 	ADD	A,$03		; increase by 3 to give combined operators of
   5980 
   5981 				; $00 '-'
   5982 				; $01 '*'
   5983 				; $02 '/'
   5984 
   5985 				; $03 '**'
   5986 				; $04 'OR'
   5987 				; $05 'AND'
   5988 				; $06 '<='
   5989 				; $07 '>='
   5990 				; $08 '<>'
   5991 
   5992 				; $09 '>'
   5993 				; $0A '<'
   5994 				; $0B '='
   5995 				; $0C '+'
   5996 
   5997 mark_10B5:
   5998 *GET_PRIO:*
   5999 	ADD	A,C		; add to default operation 'sub' ($C3)
   6000 	LD	C,A		; and place in operator byte - C.
   6001 
   6002 	LD	HL,tbl_pri <#tbl_pri> - $C3	; theoretical base of the priorities table.
   6003 	ADD	HL,BC		; add C ( B is zero)
   6004 	LD	B,(HL)		; pick up the priority in B
   6005 
   6006 mark_10BC:
   6007 *S_LOOP:*
   6008 	POP	DE		; restore previous
   6009 	LD	A,D		; load A with priority.
   6010 	CP	B		; is present priority higher
   6011 	JR	C,S_TIGHTER <#S_TIGHTER>	; forward if so to S_TIGHTER
   6012 
   6013 	AND	A		; are both priorities zero
   6014 	JP	Z,GET_CHAR <#GET_CHAR>	; exit if zero via GET_CHAR
   6015 
   6016 	PUSH	BC		; stack present values
   6017 	PUSH	DE		; stack last values
   6018 	CALL	SYNTAX_Z <#SYNTAX_Z>
   6019 	JR	Z,S_SYNTEST <#S_SYNTEST>	; forward is checking syntax
   6020 
   6021 	LD	A,E		; fetch last operation
   6022 	AND	$3F		; mask off the indicator bits to give true
   6023 				; calculator literal.
   6024 	LD	B,A		; place in the B register for BERG
   6025 
   6026 ; perform the single operation
   6027 
   6028 	RST	_FP_CALC	;;
   6029 	DEFB	__fp_calc_2	;;
   6030 	DEFB	__end_calc	;;
   6031 
   6032 	JR	S_RUNTEST <#S_RUNTEST>	; forward
   6033 
   6034 ; ___
   6035 
   6036 mark_10D5:
   6037 *S_SYNTEST:*
   6038 	LD	A,E			; transfer masked operator to A
   6039 	XOR	(IY+FLAGS-RAMBASE)	; XOR with FLAGS like results will reset bit 6
   6040 	AND	$40			; test bit 6
   6041 
   6042 mark_10DB:
   6043 *S_RPORT_C:*
   6044 	JP	NZ,REPORT_C <#REPORT_C>	; back if results do not agree.
   6045 
   6046 ; ___
   6047 
   6048 ; in run-time impose bit 7 of the operator onto bit 6 of the FLAGS
   6049 
   6050 mark_10DE:
   6051 *S_RUNTEST:*
   6052 	POP	DE		; restore last operation.
   6053 	LD	HL,FLAGS	; address system variable FLAGS
   6054 	SET	6,(HL)		; presume a numeric result
   6055 	BIT	7,E		; test expected result in operation
   6056 	JR	NZ,S_LOOPEND <#S_LOOPEND>	; forward if numeric
   6057 
   6058 	RES	6,(HL)		; reset to signal string result
   6059 
   6060 mark_10EA:
   6061 *S_LOOPEND:*
   6062 	POP	BC		; restore present values
   6063 	JR	S_LOOP <#S_LOOP>		; back
   6064 
   6065 ; ___
   6066 
   6067 mark_10ED:
   6068 *S_TIGHTER:*
   6069 	PUSH	DE		; push last values and consider these
   6070 
   6071 	LD	A,C		; get the present operator.
   6072 	BIT	6,(IY+FLAGS-RAMBASE)	; Numeric or string result?
   6073 	JR	NZ,S_NEXT <#S_NEXT>	; forward if numeric to S_NEXT
   6074 
   6075 	AND	$3F		; strip indicator bits to give clear literal.
   6076 	ADD	A,$08		; add eight - augmenting numeric to equivalent
   6077 				; string literals.
   6078 	LD	C,A		; place plain literal back in C.
   6079 	CP	$10		; compare to 'AND'
   6080 	JR	NZ,S_NOT_AND <#S_NOT_AND>	; forward if not
   6081 
   6082 	SET	6,C		; set the numeric operand required for 'AND'
   6083 	JR	S_NEXT <#S_NEXT>		; forward to S_NEXT
   6084 
   6085 ; ___
   6086 
   6087 mark_1102:
   6088 *S_NOT_AND:*
   6089 	JR	C,S_RPORT_C <#S_RPORT_C>	; back if less than 'AND'
   6090 				; Nonsense if '-', '*' etc.
   6091 
   6092 	CP	__strs_add	; compare to 'strs_add' literal
   6093 	JR	Z,S_NEXT <#S_NEXT>	; forward if so signaling string result
   6094 
   6095 	SET	7,C		; set bit to numeric (Boolean) for others.
   6096 
   6097 mark_110A:
   6098 *S_NEXT:*
   6099 	PUSH	BC		; stack 'present' values
   6100 
   6101 	RST	_NEXT_CHAR
   6102 	JP	S_LOOP_1 <#S_LOOP_1>	; jump back
   6103 
   6104 
   6105 
   6106 ------------------------------------------------------------------------
   6107 
   6108 ; THE *'TABLE OF PRIORITIES'*
   6109 ------------------------------------------------------------------------
   6110 
   6111 
   6112 mark_110F:
   6113 *tbl_pri:*
   6114 	DEFB	6		;	'-'
   6115 	DEFB	8		;	'*'
   6116 	DEFB	8		;	'/'
   6117 	DEFB	10		;	'**'
   6118 	DEFB	2		;	'OR'
   6119 	DEFB	3		;	'AND'
   6120 	DEFB	5		;	'<='
   6121 	DEFB	5		;	'>='
   6122 	DEFB	5		;	'<>'
   6123 	DEFB	5		;	'>'
   6124 	DEFB	5		;	'<'
   6125 	DEFB	5		;	'='
   6126 	DEFB	6		;	'+'
   6127 
   6128 ------------------------------------------------------------------------
   6129 
   6130 ; THE *'LOOK_VARS'* SUBROUTINE
   6131 ------------------------------------------------------------------------
   6132 
   6133 
   6134 mark_111C:
   6135 *LOOK_VARS:*
   6136 	SET	6,(IY+FLAGS-RAMBASE)	; Signal numeric result
   6137 
   6138 	RST	_GET_CHAR
   6139 	CALL	ALPHA <#ALPHA>
   6140 	JP	NC,REPORT_C <#REPORT_C>	; to REPORT_C
   6141 
   6142 	PUSH	HL		;
   6143 	LD	C,A		;
   6144 
   6145 	RST	_NEXT_CHAR
   6146 	PUSH	HL		;
   6147 	RES	5,C		;
   6148 	CP	$10		; $10
   6149 	JR	Z,V_RUN_SYN <#V_RUN_SYN>
   6150 
   6151 	SET	6,C		;
   6152 	CP	ZX_DOLLAR	; $0D
   6153 	JR	Z,V_STR_VAR <#V_STR_VAR>	; forward
   6154 
   6155 	SET	5,C		;
   6156 
   6157 mark_1139:
   6158 *V_CHAR:*
   6159 	CALL	ALPHANUM <#ALPHANUM>
   6160 	JR	NC,V_RUN_SYN <#V_RUN_SYN>	; forward when not
   6161 
   6162 	RES	6,C		;
   6163 
   6164 	RST	_NEXT_CHAR
   6165 	JR	V_CHAR <#V_CHAR>		; loop back
   6166 
   6167 ; ___
   6168 
   6169 mark_1143:
   6170 *V_STR_VAR:*
   6171 	RST	_NEXT_CHAR
   6172 	RES	6,(IY+FLAGS-RAMBASE)	; Signal string result
   6173 
   6174 mark_1148:
   6175 *V_RUN_SYN:*
   6176 	LD	B,C		;
   6177 	CALL	SYNTAX_Z <#SYNTAX_Z>
   6178 	JR	NZ,V_RUN <#V_RUN>	; forward
   6179 
   6180 	LD	A,C		;
   6181 	AND	$E0		;
   6182 	SET	7,A		;
   6183 	LD	C,A		;
   6184 	JR	V_SYNTAX <#V_SYNTAX>	; forward
   6185 
   6186 ; ___
   6187 
   6188 mark_1156:
   6189 *V_RUN:*
   6190 	LD	HL,(VARS)	; sv
   6191 
   6192 mark_1159:
   6193 *V_EACH:*
   6194 	LD	A,(HL)		;
   6195 	AND	$7F		;
   6196 	JR	Z,V_80_BYTE <#V_80_BYTE>	;
   6197 
   6198 	CP	C		;
   6199 	JR	NZ,V_NEXT <#V_NEXT>	;
   6200 
   6201 	RLA			;
   6202 	ADD	A,A		;
   6203 	JP	P,V_FOUND_2 <#V_FOUND_2>
   6204 
   6205 	JR	C,V_FOUND_2 <#V_FOUND_2>
   6206 
   6207 	POP	DE		;
   6208 	PUSH	DE		;
   6209 	PUSH	HL		;
   6210 
   6211 mark_116B:
   6212 *V_MATCHES:*
   6213 	INC	HL		;
   6214 
   6215 mark_116C:
   6216 *V_SPACES:*
   6217 	LD	A,(DE)		;
   6218 	INC	DE		;
   6219 	AND	A		;
   6220 	JR	Z,V_SPACES <#V_SPACES>	; back
   6221 
   6222 	CP	(HL)		;
   6223 	JR	Z,V_MATCHES <#V_MATCHES>	; back
   6224 
   6225 	OR	$80		;
   6226 	CP	(HL)		;
   6227 	JR	NZ,V_GET_PTR <#V_GET_PTR>	; forward
   6228 
   6229 	LD	A,(DE)		;
   6230 	CALL	ALPHANUM <#ALPHANUM>
   6231 	JR	NC,V_FOUND_1 <#V_FOUND_1>	; forward
   6232 
   6233 mark_117F:
   6234 *V_GET_PTR:*
   6235 	POP	HL		;
   6236 
   6237 mark_1180:
   6238 *V_NEXT:*
   6239 	PUSH	BC		;
   6240 	CALL	NEXT_ONE <#NEXT_ONE>
   6241 	EX	DE,HL		;
   6242 	POP	BC		;
   6243 	JR	V_EACH <#V_EACH>		; back
   6244 
   6245 ; ___
   6246 
   6247 mark_1188:
   6248 *V_80_BYTE:*
   6249 	SET	7,B		;
   6250 
   6251 mark_118A:
   6252 *V_SYNTAX:*
   6253 	POP	DE		;
   6254 
   6255 	RST	_GET_CHAR
   6256 	CP	$10		;
   6257 	JR	Z,V_PASS <#V_PASS>	; forward
   6258 
   6259 	SET	5,B		;
   6260 	JR	V_END <#V_END>		; forward
   6261 
   6262 ; ___
   6263 
   6264 mark_1194:
   6265 *V_FOUND_1:*
   6266 	POP	DE		;
   6267 
   6268 mark_1195:
   6269 *V_FOUND_2:*
   6270 	POP	DE		;
   6271 	POP	DE		;
   6272 	PUSH	HL		;
   6273 
   6274 	RST	_GET_CHAR
   6275 
   6276 mark_1199:
   6277 *V_PASS:*
   6278 	CALL	ALPHANUM <#ALPHANUM>
   6279 	JR	NC,V_END <#V_END>	; forward if not alphanumeric
   6280 
   6281 
   6282 	RST	_NEXT_CHAR
   6283 	JR	V_PASS <#V_PASS>		; back
   6284 
   6285 ; ___
   6286 
   6287 mark_11A1:
   6288 *V_END:*
   6289 	POP	HL		;
   6290 	RL	B		;
   6291 	BIT	6,B		;
   6292 	RET			;
   6293 
   6294 ------------------------------------------------------------------------
   6295 
   6296 ; THE *'STK_VAR'* SUBROUTINE
   6297 ------------------------------------------------------------------------
   6298 
   6299 
   6300 mark_11A7:
   6301 *STK_VAR:*
   6302 	XOR	A		;
   6303 	LD	B,A		;
   6304 	BIT	7,C		;
   6305 	JR	NZ,SV_COUNT <#SV_COUNT>	; forward
   6306 
   6307 	BIT	7,(HL)		;
   6308 	JR	NZ,SV_ARRAYS <#SV_ARRAYS>	; forward
   6309 
   6310 	INC	A		;
   6311 
   6312 mark_11B2:
   6313 *SV_SIMPLE_STR:*
   6314 	INC	HL		;
   6315 	LD	C,(HL)		;
   6316 	INC	HL		;
   6317 	LD	B,(HL)		;
   6318 	INC	HL		;
   6319 	EX	DE,HL		;
   6320 	CALL	STK_STO_STR <#STK_STO_STR>
   6321 
   6322 	RST	_GET_CHAR
   6323 	JP	SV_SLICE_QUERY <#SV_SLICE_QUERY>	; jump forward
   6324 
   6325 ; ___
   6326 
   6327 mark_11BF:
   6328 *SV_ARRAYS:*
   6329 	INC	HL		;
   6330 	INC	HL		;
   6331 	INC	HL		;
   6332 	LD	B,(HL)		;
   6333 	BIT	6,C		;
   6334 	JR	Z,SV_PTR <#SV_PTR>	; forward
   6335 
   6336 	DEC	B		;
   6337 	JR	Z,SV_SIMPLE_STR <#SV_SIMPLE_STR>	; forward
   6338 
   6339 	EX	DE,HL		;
   6340 
   6341 	RST	_GET_CHAR
   6342 	CP	$10		;
   6343 	JR	NZ,REPORT_3 <#REPORT_3>	; forward
   6344 
   6345 	EX	DE,HL		;
   6346 
   6347 mark_11D1:
   6348 *SV_PTR:*
   6349 	EX	DE,HL		;
   6350 	JR	SV_COUNT <#SV_COUNT>	; forward
   6351 ; ___
   6352 mark_11D4:
   6353 *SV_COMMA:*
   6354 	PUSH	HL		;
   6355 
   6356 	RST	_GET_CHAR
   6357 	POP	HL		;
   6358 	CP	ZX_COMMA	; $1A == 26
   6359 	JR	Z,SV_LOOP <#SV_LOOP>	; forward
   6360 
   6361 	BIT	7,C		;
   6362 	JR	Z,REPORT_3 <#REPORT_3>	; forward
   6363 
   6364 	BIT	6,C		;
   6365 	JR	NZ,SV_CLOSE <#SV_CLOSE>	; forward
   6366 
   6367 	CP	ZX_BRACKET_RIGHT		; $11
   6368 	JR	NZ,SV_RPT_C <#SV_RPT_C>	; forward
   6369 
   6370 
   6371 	RST	_NEXT_CHAR
   6372 	RET			;
   6373 ; ___
   6374 mark_11E9:
   6375 *SV_CLOSE:*
   6376 	CP	ZX_BRACKET_RIGHT		; $11
   6377 	JR	Z,SV_DIM <#SV_DIM>	; forward
   6378 
   6379 	CP	$DF		;
   6380 	JR	NZ,SV_RPT_C <#SV_RPT_C>	; forward
   6381 
   6382 mark_11F1:
   6383 *SV_CH_ADD:*
   6384 	RST	_GET_CHAR
   6385 	DEC	HL		;
   6386 	LD	(CH_ADD),HL	; sv
   6387 	JR	SV_SLICE <#SV_SLICE>	; forward
   6388 
   6389 ; ___
   6390 
   6391 mark_11F8:
   6392 *SV_COUNT:*
   6393 	LD	HL,$0000	;
   6394 
   6395 mark_11FB:
   6396 *SV_LOOP:*
   6397 	PUSH	HL		;
   6398 
   6399 	RST	_NEXT_CHAR
   6400 	POP	HL		;
   6401 	LD	A,C		;
   6402 	CP	ZX_DOUBLE_QUOTE	;
   6403 	JR	NZ,SV_MULT <#SV_MULT>	; forward
   6404 
   6405 
   6406 	RST	_GET_CHAR
   6407 	CP	ZX_BRACKET_RIGHT
   6408 	JR	Z,SV_DIM <#SV_DIM>	; forward
   6409 
   6410 	CP	ZX_TO		;
   6411 	JR	Z,SV_CH_ADD <#SV_CH_ADD>	; back
   6412 
   6413 mark_120C:
   6414 *SV_MULT:*
   6415 	PUSH	BC		;
   6416 	PUSH	HL		;
   6417 	CALL	DE_DE_PLUS_ONE <#DE_DE_PLUS_ONE>
   6418 	EX	(SP),HL	;
   6419 	EX	DE,HL		;
   6420 	CALL	INT_EXP1 <#INT_EXP1>
   6421 	JR	C,REPORT_3 <#REPORT_3>
   6422 
   6423 	DEC	BC		;
   6424 	CALL	GET_HL_TIMES_DE <#GET_HL_TIMES_DE>
   6425 	ADD	HL,BC		;
   6426 	POP	DE		;
   6427 	POP	BC		;
   6428 	DJNZ	SV_COMMA <#SV_COMMA>		; loop back
   6429 
   6430 	BIT	7,C		;
   6431 
   6432 mark_1223:
   6433 *SV_RPT_C:*
   6434 	JR	NZ,SL_RPT_C <#SL_RPT_C>
   6435 
   6436 	PUSH	HL		;
   6437 	BIT	6,C		;
   6438 	JR	NZ,SV_ELEM_STR <#SV_ELEM_STR>
   6439 
   6440 	LD	B,D		;
   6441 	LD	C,E		;
   6442 
   6443 	RST	_GET_CHAR
   6444 	CP	ZX_BRACKET_RIGHT; is character a ')' ?
   6445 	JR	Z,SV_NUMBER <#SV_NUMBER>	; skip forward
   6446 
   6447 
   6448 mark_1231:
   6449 *REPORT_3:*
   6450 	RST	_ERROR_1
   6451 	DEFB	$02		; Error Report: Subscript wrong
   6452 
   6453 
   6454 mark_1233:
   6455 *SV_NUMBER:*
   6456 	RST	_NEXT_CHAR
   6457 	POP	HL		;
   6458 	LD	DE,$0005	;
   6459 	CALL	GET_HL_TIMES_DE <#GET_HL_TIMES_DE>
   6460 	ADD	HL,BC		;
   6461 	RET			; return				>>
   6462 
   6463 ; ___
   6464 
   6465 mark_123D:
   6466 *SV_ELEM_STR:*
   6467 	CALL	DE_DE_PLUS_ONE <#DE_DE_PLUS_ONE>
   6468 	EX	(SP),HL	;
   6469 	CALL	GET_HL_TIMES_DE <#GET_HL_TIMES_DE>
   6470 	POP	BC		;
   6471 	ADD	HL,BC		;
   6472 	INC	HL		;
   6473 	LD	B,D		;
   6474 	LD	C,E		;
   6475 	EX	DE,HL		;
   6476 	CALL	STK_ST_0 <#STK_ST_0>
   6477 
   6478 	RST	_GET_CHAR
   6479 	CP	ZX_BRACKET_RIGHT ; is it ')' ?
   6480 	JR	Z,SV_DIM <#SV_DIM>	; forward if so
   6481 
   6482 	CP	ZX_COMMA	; $1A == 26		; is it ',' ?
   6483 	JR	NZ,REPORT_3 <#REPORT_3>	; back if not
   6484 
   6485 mark_1256:
   6486 *SV_SLICE:*
   6487 	CALL	SLICING <#SLICING>
   6488 
   6489 mark_1259:
   6490 *SV_DIM:*
   6491 	RST	_NEXT_CHAR
   6492 
   6493 mark_125A:
   6494 *SV_SLICE_QUERY:*
   6495 	CP	$10		;
   6496 	JR	Z,SV_SLICE <#SV_SLICE>	; back
   6497 
   6498 	RES	6,(IY+FLAGS-RAMBASE)	; Signal string result
   6499 	RET			; return.
   6500 
   6501 ------------------------------------------------------------------------
   6502 
   6503 ; THE *'SLICING'* SUBROUTINE
   6504 ------------------------------------------------------------------------
   6505 
   6506 ;
   6507 ;
   6508 
   6509 mark_1263:
   6510 *SLICING:*
   6511 	CALL	SYNTAX_Z <#SYNTAX_Z>
   6512 	CALL	NZ,STK_FETCH <#STK_FETCH>
   6513 
   6514 	RST	_NEXT_CHAR
   6515 	CP	ZX_BRACKET_RIGHT; is it ')' ?
   6516 	JR	Z,SL_STORE <#SL_STORE>	; forward if so
   6517 
   6518 	PUSH	DE		;
   6519 	XOR	A		;
   6520 	PUSH	AF		;
   6521 	PUSH	BC		;
   6522 	LD	DE,$0001	;
   6523 
   6524 	RST	_GET_CHAR
   6525 	POP	HL		;
   6526 	CP	ZX_TO		; is it 'TO' ?
   6527 	JR	Z,SL_SECOND <#SL_SECOND>	; forward if so
   6528 
   6529 	POP	AF		;
   6530 	CALL	INT_EXP2 <#INT_EXP2>
   6531 	PUSH	AF		;
   6532 	LD	D,B		;
   6533 	LD	E,C		;
   6534 	PUSH	HL		;
   6535 
   6536 	RST	_GET_CHAR
   6537 	POP	HL		;
   6538 	CP	ZX_TO		; is it 'TO' ?
   6539 	JR	Z,SL_SECOND <#SL_SECOND>	; forward if so
   6540 
   6541 	CP	ZX_BRACKET_RIGHT; $11
   6542 
   6543 mark_128B:
   6544 *SL_RPT_C:*
   6545 	JP	NZ,REPORT_C <#REPORT_C>
   6546 
   6547 	LD	H,D		;
   6548 	LD	L,E		;
   6549 	JR	SL_DEFINE <#SL_DEFINE>		; forward
   6550 
   6551 ; ___
   6552 
   6553 mark_1292:
   6554 *SL_SECOND:*
   6555 	PUSH	HL		;
   6556 
   6557 	RST	_NEXT_CHAR
   6558 	POP	HL		;
   6559 	CP	ZX_BRACKET_RIGHT; is it ')' ?
   6560 	JR	Z,SL_DEFINE <#SL_DEFINE>	; forward if so
   6561 
   6562 	POP	AF		;
   6563 	CALL	INT_EXP2 <#INT_EXP2>
   6564 	PUSH	AF		;
   6565 
   6566 	RST	_GET_CHAR
   6567 	LD	H,B		;
   6568 	LD	L,C		;
   6569 	CP	ZX_BRACKET_RIGHT; is it ')' ?
   6570 	JR	NZ,SL_RPT_C <#SL_RPT_C>	; back if not
   6571 
   6572 mark_12A5:
   6573 *SL_DEFINE:*
   6574 	POP	AF		;
   6575 	EX	(SP),HL	;
   6576 	ADD	HL,DE		;
   6577 	DEC	HL		;
   6578 	EX	(SP),HL	;
   6579 	AND	A		;
   6580 	SBC	HL,DE		;
   6581 	LD	BC,$0000	;
   6582 	JR	C,SL_OVER <#SL_OVER>	; forward
   6583 
   6584 	INC	HL		;
   6585 	AND	A		;
   6586 	JP	M,REPORT_3 <#REPORT_3>	; jump back
   6587 
   6588 	LD	B,H		;
   6589 	LD	C,L		;
   6590 
   6591 mark_12B9:
   6592 *SL_OVER:*
   6593 	POP	DE		;
   6594 	RES	6,(IY+FLAGS-RAMBASE)	; Signal string result
   6595 
   6596 mark_12BE:
   6597 *SL_STORE:*
   6598 	CALL	SYNTAX_Z <#SYNTAX_Z>
   6599 	RET	Z		; return if checking syntax.
   6600 
   6601 ------------------------------------------------------------------------
   6602 
   6603 ; THE *'STK_STORE'* SUBROUTINE
   6604 ------------------------------------------------------------------------
   6605 
   6606 ;
   6607 ;
   6608 
   6609 mark_12C2:
   6610 *STK_ST_0:*
   6611 	XOR	A		;
   6612 
   6613 mark_12C3:
   6614 *STK_STO_STR:*
   6615 	PUSH	BC		;
   6616 	CALL	TEST_5_SP <#TEST_5_SP>
   6617 	POP	BC		;
   6618 	LD	HL,(STKEND)	; sv
   6619 	LD	(HL),A		;
   6620 	INC	HL		;
   6621 	LD	(HL),E		;
   6622 	INC	HL		;
   6623 	LD	(HL),D		;
   6624 	INC	HL		;
   6625 	LD	(HL),C		;
   6626 	INC	HL		;
   6627 	LD	(HL),B		;
   6628 	INC	HL		;
   6629 	LD	(STKEND),HL	; sv
   6630 	RES	6,(IY+FLAGS-RAMBASE)	; Signal string result
   6631 	RET			; return.
   6632 
   6633 ------------------------------------------------------------------------
   6634 
   6635 ; THE *'INT EXP'* SUBROUTINES
   6636 ------------------------------------------------------------------------
   6637 
   6638 ;
   6639 ;
   6640 
   6641 mark_12DD:
   6642 *INT_EXP1:*
   6643 	XOR	A		;
   6644 
   6645 mark_12DE:
   6646 *INT_EXP2:*
   6647 	PUSH	DE		;
   6648 	PUSH	HL		;
   6649 	PUSH	AF		;
   6650 	CALL	CLASS_6 <#CLASS_6>
   6651 	POP	AF		;
   6652 	CALL	SYNTAX_Z <#SYNTAX_Z>
   6653 	JR	Z,I_RESTORE <#I_RESTORE>	; forward if checking syntax
   6654 
   6655 	PUSH	AF		;
   6656 	CALL	FIND_INT <#FIND_INT>
   6657 	POP	DE		;
   6658 	LD	A,B		;
   6659 	OR	C		;
   6660 	SCF			; Set Carry Flag
   6661 	JR	Z,I_CARRY <#I_CARRY>	; forward
   6662 
   6663 	POP	HL		;
   6664 	PUSH	HL		;
   6665 	AND	A		;
   6666 	SBC	HL,BC		;
   6667 
   6668 mark_12F9:
   6669 *I_CARRY:*
   6670 	LD	A,D		;
   6671 	SBC	A,$00		;
   6672 
   6673 mark_12FC:
   6674 *I_RESTORE:*
   6675 	POP	HL		;
   6676 	POP	DE		;
   6677 	RET			;
   6678 
   6679 ------------------------------------------------------------------------
   6680 
   6681 ; THE *'DE,(DE+1)'* SUBROUTINE
   6682 ------------------------------------------------------------------------
   6683 
   6684 ; INDEX and LOAD Z80 subroutine. 
   6685 ; This emulates the 6800 processor instruction LDX 1,X which loads a two_byte
   6686 ; value from memory into the register indexing it. Often these are hardly worth
   6687 ; the bother of writing as subroutines and this one doesn't save any time or 
   6688 ; memory. The timing and space overheads have to be offset against the ease of
   6689 ; writing and the greater program readability from using such toolkit routines.
   6690 
   6691 mark_12FF:
   6692 *DE_DE_PLUS_ONE:*
   6693 	EX	DE,HL		; move index address into HL.
   6694 	INC	HL		; increment to address word.
   6695 	LD	E,(HL)		; pick up word low_order byte.
   6696 	INC	HL		; index high_order byte and 
   6697 	LD	D,(HL)		; pick it up.
   6698 	RET			; return with DE = word.
   6699 
   6700 ------------------------------------------------------------------------
   6701 
   6702 ; THE *'GET_HL_TIMES_DE'* SUBROUTINE
   6703 ------------------------------------------------------------------------
   6704 
   6705 ;
   6706 
   6707 mark_1305:
   6708 *GET_HL_TIMES_DE:*
   6709 	CALL	SYNTAX_Z <#SYNTAX_Z>
   6710 	RET	Z		;
   6711 
   6712 	PUSH	BC		;
   6713 	LD	B,$10		;
   6714 	LD	A,H		;
   6715 	LD	C,L		;
   6716 	LD	HL,$0000	;
   6717 
   6718 mark_1311:
   6719 *HL_LOOP:*
   6720 	ADD	HL,HL		;
   6721 	JR	C,HL_END <#HL_END>	; forward with carry
   6722 
   6723 	RL	C		;
   6724 	RLA			;
   6725 	JR	NC,HL_AGAIN <#HL_AGAIN>	; forward with no carry
   6726 
   6727 	ADD	HL,DE		;
   6728 
   6729 mark_131A:
   6730 *HL_END:*
   6731 	JP	C,REPORT_4 <#REPORT_4>
   6732 
   6733 mark_131D:
   6734 *HL_AGAIN:*
   6735 	DJNZ	HL_LOOP <#HL_LOOP>		; loop back
   6736 
   6737 	POP	BC		;
   6738 	RET			; return.
   6739 
   6740 ------------------------------------------------------------------------
   6741 
   6742 ; THE *'LET'* SUBROUTINE
   6743 ------------------------------------------------------------------------
   6744 
   6745 ;
   6746 ;
   6747 
   6748 mark_1321:
   6749 *LET:*
   6750 	LD	HL,(DEST)
   6751 	BIT	1,(IY+FLAGX-RAMBASE)
   6752 	JR	Z,L_EXISTS <#L_EXISTS>	; forward
   6753 
   6754 	LD	BC,$0005	;
   6755 
   6756 mark_132D:
   6757 *L_EACH_CH:*
   6758 	INC	BC		;
   6759 
   6760 ; check
   6761 
   6762 mark_132E:
   6763 *L_NO_SP:*
   6764 	INC	HL		;
   6765 	LD	A,(HL)		;
   6766 	AND	A		;
   6767 	JR	Z,L_NO_SP <#L_NO_SP>	; back
   6768 
   6769 	CALL	ALPHANUM <#ALPHANUM>
   6770 	JR	C,L_EACH_CH <#L_EACH_CH>	; back
   6771 
   6772 	CP	ZX_DOLLAR	; is it '$' ?
   6773 	JP	Z,L_NEW_STR <#L_NEW_STR>	; forward if so
   6774 
   6775 
   6776 	RST	_BC_SPACES		; BC_SPACES
   6777 	PUSH	DE		;
   6778 	LD	HL,(DEST)	; 
   6779 	DEC	DE		;
   6780 	LD	A,C		;
   6781 	SUB	$06		;
   6782 	LD	B,A		;
   6783 	LD	A,$40		;
   6784 	JR	Z,L_SINGLE <#L_SINGLE>
   6785 
   6786 mark_134B:
   6787 *L_CHAR:*
   6788 	INC	HL		;
   6789 	LD	A,(HL)		;
   6790 	AND	A		; is it a space ?
   6791 	JR	Z,L_CHAR <#L_CHAR>	; back
   6792 
   6793 	INC	DE		;
   6794 	LD	(DE),A		;
   6795 	DJNZ	L_CHAR <#L_CHAR>		; loop back
   6796 
   6797 	OR	$80		;
   6798 	LD	(DE),A		;
   6799 	LD	A,$80		;
   6800 
   6801 mark_1359:
   6802 *L_SINGLE:*
   6803 	LD	HL,(DEST)	; 
   6804 	XOR	(HL)		;
   6805 	POP	HL		;
   6806 	CALL	L_FIRST <#L_FIRST>
   6807 
   6808 mark_1361:
   6809 *L_NUMERIC:*
   6810 	PUSH	HL		;
   6811 
   6812 	RST	_FP_CALC	;;
   6813 	DEFB	__delete	;;
   6814 	DEFB	__end_calc	;;
   6815 
   6816 	POP	HL		;
   6817 	LD	BC,$0005	;
   6818 	AND	A		;
   6819 	SBC	HL,BC		;
   6820 	JR	L_ENTER <#L_ENTER>		; forward
   6821 
   6822 ; ___
   6823 
   6824 mark_136E:
   6825 *L_EXISTS:*
   6826 	BIT	6,(IY+FLAGS-RAMBASE)	; Numeric or string result?
   6827 	JR	Z,L_DELETE_STR <#L_DELETE_STR>	; forward
   6828 
   6829 	LD	DE,$0006	;
   6830 	ADD	HL,DE		;
   6831 	JR	L_NUMERIC <#L_NUMERIC>		; back
   6832 
   6833 ; ___
   6834 
   6835 mark_137A:
   6836 *L_DELETE_STR:*
   6837 	LD	HL,(DEST)	; 
   6838 	LD	BC,(STRLEN)	;
   6839 	BIT	0,(IY+FLAGX-RAMBASE)
   6840 	JR	NZ,L_ADD_STR <#L_ADD_STR>	; forward
   6841 
   6842 	LD	A,B		;
   6843 	OR	C		;
   6844 	RET	Z		;
   6845 
   6846 	PUSH	HL		;
   6847 
   6848 	RST	_BC_SPACES
   6849 	PUSH	DE		;
   6850 	PUSH	BC		;
   6851 	LD	D,H		;
   6852 	LD	E,L		;
   6853 	INC	HL		;
   6854 	LD	(HL),$00	;
   6855 	LDDR			; Copy Bytes
   6856 	PUSH	HL		;
   6857 	CALL	STK_FETCH <#STK_FETCH>
   6858 	POP	HL		;
   6859 	EX	(SP),HL	;
   6860 	AND	A		;
   6861 	SBC	HL,BC		;
   6862 	ADD	HL,BC		;
   6863 	JR	NC,L_LENGTH <#L_LENGTH>	; forward
   6864 
   6865 	LD	B,H		;
   6866 	LD	C,L		;
   6867 
   6868 mark_13A3:
   6869 *L_LENGTH:*
   6870 	EX	(SP),HL	;
   6871 	EX	DE,HL		;
   6872 	LD	A,B		;
   6873 	OR	C		;
   6874 	JR	Z,L_IN_W_S <#L_IN_W_S>	; forward if zero
   6875 
   6876 	LDIR			; Copy Bytes
   6877 
   6878 mark_13AB:
   6879 *L_IN_W_S:*
   6880 	POP	BC		;
   6881 	POP	DE		;
   6882 	POP	HL		;
   6883 
   6884 ------------------------------------------------------------------------
   6885 
   6886 ; THE *'L_ENTER'* SUBROUTINE
   6887 ;
   6888 ;   Part of the LET command contains a natural subroutine which is a 
   6889 ;   conditional LDIR. The copy only occurs of BC is non-zero.
   6890 ------------------------------------------------------------------------
   6891 
   6892 mark_13AE:
   6893 *L_ENTER:*
   6894 	EX	DE,HL		;
   6895 #if ORIGINAL
   6896 #else
   6897 *COND_MV*
   6898 #endif
   6899 	LD	A,B		;
   6900 	OR	C		;
   6901 	RET	Z		;
   6902 
   6903 	PUSH	DE		;
   6904 	LDIR			; Copy Bytes
   6905 	POP	HL		;
   6906 	RET			; return.
   6907 ------------------------------------------------------------------------
   6908 
   6909 mark_13B7:
   6910 *L_ADD_STR:*
   6911 	DEC	HL		;
   6912 	DEC	HL		;
   6913 	DEC	HL		;
   6914 	LD	A,(HL)		;
   6915 	PUSH	HL		;
   6916 	PUSH	BC		;
   6917 
   6918 	CALL	L_STRING <#L_STRING>
   6919 
   6920 	POP	BC		;
   6921 	POP	HL		;
   6922 	INC	BC		;
   6923 	INC	BC		;
   6924 	INC	BC		;
   6925 	JP	RECLAIM_2 <#RECLAIM_2>		; jump back to exit via RECLAIM_2
   6926 
   6927 ; ___
   6928 
   6929 mark_13C8:
   6930 *L_NEW_STR:*
   6931 	LD	A,$60		; prepare mask %01100000
   6932 	LD	HL,(DEST)	; 
   6933 	XOR	(HL)		;
   6934 
   6935 ------------------------------------------------------------------------
   6936 
   6937 ; THE *'L_STRING'* SUBROUTINE
   6938 ------------------------------------------------------------------------
   6939 
   6940 ;
   6941 
   6942 mark_13CE:
   6943 *L_STRING:*
   6944 	PUSH	AF		;
   6945 	CALL	STK_FETCH <#STK_FETCH>
   6946 	EX	DE,HL		;
   6947 	ADD	HL,BC		;
   6948 	PUSH	HL		;
   6949 	INC	BC		;
   6950 	INC	BC		;
   6951 	INC	BC		;
   6952 
   6953 	RST	_BC_SPACES
   6954 	EX	DE,HL		;
   6955 	POP	HL		;
   6956 	DEC	BC		;
   6957 	DEC	BC		;
   6958 	PUSH	BC		;
   6959 	LDDR			; Copy Bytes
   6960 	EX	DE,HL		;
   6961 	POP	BC		;
   6962 	DEC	BC		;
   6963 	LD	(HL),B		;
   6964 	DEC	HL		;
   6965 	LD	(HL),C		;
   6966 	POP	AF		;
   6967 
   6968 mark_13E7:
   6969 *L_FIRST:*
   6970 	PUSH	AF		;
   6971 	CALL	REC_V80 <#REC_V80>
   6972 	POP	AF		;
   6973 	DEC	HL		;
   6974 	LD	(HL),A		;
   6975 	LD	HL,(STKBOT)	; sv
   6976 	LD	(E_LINE),HL	; sv
   6977 	DEC	HL		;
   6978 	LD	(HL),$80	;
   6979 	RET			;
   6980 
   6981 ------------------------------------------------------------------------
   6982 
   6983 ; THE *'STK_FETCH'* SUBROUTINE
   6984 ------------------------------------------------------------------------
   6985 
   6986 ; This routine fetches a five-byte value from the calculator stack
   6987 ; reducing the pointer to the end of the stack by five.
   6988 ; For a floating-point number the exponent is in A and the mantissa
   6989 ; is the thirty-two bits EDCB.
   6990 ; For strings, the start of the string is in DE and the length in BC.
   6991 ; A is unused.
   6992 
   6993 mark_13F8:
   6994 *STK_FETCH:*
   6995 	LD	HL,(STKEND)	; load HL from system variable STKEND
   6996 
   6997 	DEC	HL		;
   6998 	LD	B,(HL)		;
   6999 	DEC	HL		;
   7000 	LD	C,(HL)		;
   7001 	DEC	HL		;
   7002 	LD	D,(HL)		;
   7003 	DEC	HL		;
   7004 	LD	E,(HL)		;
   7005 	DEC	HL		;
   7006 	LD	A,(HL)		;
   7007 
   7008 	LD	(STKEND),HL	; set system variable STKEND to lower value.
   7009 	RET			; return.
   7010 
   7011 ------------------------------------------------------------------------
   7012 
   7013 ; THE *'DIM'* COMMAND ROUTINE
   7014 ------------------------------------------------------------------------
   7015 
   7016 ; An array is created and initialized to zeros which is also the space
   7017 ; character on the ZX81.
   7018 
   7019 mark_1409:
   7020 *DIM:*
   7021 	CALL	LOOK_VARS <#LOOK_VARS>
   7022 
   7023 mark_140C:
   7024 *D_RPORT_C:*
   7025 	JP	NZ,REPORT_C <#REPORT_C>
   7026 
   7027 	CALL	SYNTAX_Z <#SYNTAX_Z>
   7028 	JR	NZ,D_RUN <#D_RUN>	; forward
   7029 
   7030 	RES	6,C		;
   7031 	CALL	STK_VAR <#STK_VAR>
   7032 	CALL	CHECK_END <#CHECK_END>
   7033 
   7034 mark_141C:
   7035 *D_RUN:*
   7036 	JR	C,D_LETTER <#D_LETTER>	; forward
   7037 
   7038 	PUSH	BC		;
   7039 	CALL	NEXT_ONE <#NEXT_ONE>
   7040 	CALL	RECLAIM_2 <#RECLAIM_2>
   7041 	POP	BC		;
   7042 
   7043 mark_1426:
   7044 *D_LETTER:*
   7045 	SET	7,C		;
   7046 	LD	B,$00		;
   7047 	PUSH	BC		;
   7048 	LD	HL,$0001	;
   7049 	BIT	6,C		;
   7050 	JR	NZ,D_SIZE <#D_SIZE>	; forward
   7051 
   7052 	LD	L,$05		;
   7053 
   7054 mark_1434:
   7055 *D_SIZE:*
   7056 	EX	DE,HL		;
   7057 
   7058 mark_1435:
   7059 *D_NO_LOOP:*
   7060 	RST	_NEXT_CHAR
   7061 	LD	H,$40		;
   7062 	CALL	INT_EXP1 <#INT_EXP1>
   7063 	JP	C,REPORT_3 <#REPORT_3>
   7064 
   7065 	POP	HL		;
   7066 	PUSH	BC		;
   7067 	INC	H		;
   7068 	PUSH	HL		;
   7069 	LD	H,B		;
   7070 	LD	L,C		;
   7071 	CALL	GET_HL_TIMES_DE <#GET_HL_TIMES_DE>
   7072 	EX	DE,HL		;
   7073 
   7074 	RST	_GET_CHAR
   7075 	CP	ZX_COMMA	; $1A == 26
   7076 	JR	Z,D_NO_LOOP <#D_NO_LOOP>	; back
   7077 
   7078 	CP	ZX_BRACKET_RIGHT; is it ')' ?
   7079 	JR	NZ,D_RPORT_C <#D_RPORT_C>	; back if not
   7080 
   7081 
   7082 	RST	_NEXT_CHAR
   7083 	POP	BC		;
   7084 	LD	A,C		;
   7085 	LD	L,B		;
   7086 	LD	H,$00		;
   7087 	INC	HL		;
   7088 	INC	HL		;
   7089 	ADD	HL,HL		;
   7090 	ADD	HL,DE		;
   7091 	JP	C,REPORT_4 <#REPORT_4>
   7092 
   7093 	PUSH	DE		;
   7094 	PUSH	BC		;
   7095 	PUSH	HL		;
   7096 	LD	B,H		;
   7097 	LD	C,L		;
   7098 	LD	HL,(E_LINE)	; sv
   7099 	DEC	HL		;
   7100 	CALL	MAKE_ROOM <#MAKE_ROOM>
   7101 	INC	HL		;
   7102 	LD	(HL),A	;
   7103 	POP	BC		;
   7104 	DEC	BC		;
   7105 	DEC	BC		;
   7106 	DEC	BC		;
   7107 	INC	HL		;
   7108 	LD	(HL),C		;
   7109 	INC	HL		;
   7110 	LD	(HL),B		;
   7111 	POP	AF		;
   7112 	INC	HL		;
   7113 	LD	(HL),A		;
   7114 	LD	H,D		;
   7115 	LD	L,E		;
   7116 	DEC	DE		;
   7117 	LD	(HL),0		;
   7118 	POP	BC		;
   7119 	LDDR			; Copy Bytes
   7120 
   7121 mark_147F:
   7122 *DIM_SIZES:*
   7123 	POP	BC		;
   7124 	LD	(HL),B		;
   7125 	DEC	HL		;
   7126 	LD	(HL),C		;
   7127 	DEC	HL		;
   7128 	DEC	A		;
   7129 	JR	NZ,DIM_SIZES <#DIM_SIZES>	; back
   7130 
   7131 	RET			; return.
   7132 
   7133 ------------------------------------------------------------------------
   7134 
   7135 ; THE *'RESERVE'* ROUTINE
   7136 ------------------------------------------------------------------------
   7137 
   7138 ;
   7139 ;
   7140 
   7141 mark_1488:
   7142 *RESERVE:*
   7143 	LD	HL,(STKBOT)	; address STKBOT
   7144 	DEC	HL		; now last byte of workspace
   7145 	CALL	MAKE_ROOM <#MAKE_ROOM>
   7146 	INC	HL		;
   7147 	INC	HL		;
   7148 	POP	BC		;
   7149 	LD	(E_LINE),BC	; sv
   7150 	POP	BC		;
   7151 	EX	DE,HL		;
   7152 	INC	HL		;
   7153 	RET			;
   7154 
   7155 ------------------------------------------------------------------------
   7156 
   7157 ; THE *'CLEAR'* COMMAND ROUTINE
   7158 ------------------------------------------------------------------------
   7159 
   7160 ;
   7161 ;
   7162 
   7163 mark_149A:
   7164 *CLEAR:*
   7165 	LD	HL,(VARS)	; sv
   7166 	LD	(HL),$80	;
   7167 	INC	HL		;
   7168 	LD	(E_LINE),HL	; sv
   7169 
   7170 ------------------------------------------------------------------------
   7171 
   7172 ; THE *'X_TEMP'* SUBROUTINE
   7173 ------------------------------------------------------------------------
   7174 
   7175 ;
   7176 ;
   7177 
   7178 mark_14A3:
   7179 *X_TEMP:*
   7180 	LD	HL,(E_LINE)	; sv
   7181 
   7182 ------------------------------------------------------------------------
   7183 
   7184 ; THE *'SET_STK'* ROUTINES
   7185 ------------------------------------------------------------------------
   7186 
   7187 ;
   7188 ;
   7189 
   7190 mark_14A6:
   7191 *SET_STK_B:*
   7192 	LD	(STKBOT),HL	; sv
   7193 
   7194 ;
   7195 
   7196 mark_14A9:
   7197 *SET_STK_E:*
   7198 	LD	(STKEND),HL	; sv
   7199 	RET			;
   7200 
   7201 ------------------------------------------------------------------------
   7202 
   7203 ; THE *'CURSOR_IN'* ROUTINE
   7204 ------------------------------------------------------------------------
   7205 
   7206 ; This routine is called to set the edit line to the minimum cursor/newline
   7207 ; and to set STKEND, the start of free space, at the next position.
   7208 
   7209 mark_14AD:
   7210 *CURSOR_IN:*
   7211 	LD	HL,(E_LINE)		; fetch start of edit line
   7212 	LD	(HL),ZX_CURSOR		; insert cursor character
   7213 
   7214 	INC	HL			; point to next location.
   7215 	LD	(HL),ZX_NEWLINE		; insert NEWLINE character
   7216 	INC	HL			; point to next free location.
   7217 
   7218 	LD	(IY+DF_SZ-RAMBASE),2	; set lower screen display file size
   7219 
   7220 	JR	SET_STK_B <#SET_STK_B>		; exit via SET_STK_B above
   7221 
   7222 ------------------------------------------------------------------------
   7223 
   7224 ; THE *'SET_MIN'* SUBROUTINE
   7225 ------------------------------------------------------------------------
   7226 
   7227 ;
   7228 ;
   7229 
   7230 mark_14BC:
   7231 *SET_MIN:*
   7232 	LD	HL,$405D	; normal location of calculator's memory area
   7233 	LD	(MEM),HL	; update system variable MEM
   7234 	LD	HL,(STKBOT)	;
   7235 	JR	SET_STK_E <#SET_STK_E>		; back
   7236 
   7237 
   7238 ------------------------------------------------------------------------
   7239 
   7240 ; THE *'RECLAIM THE END_MARKER'* ROUTINE
   7241 ------------------------------------------------------------------------
   7242 
   7243 
   7244 mark_14C7:
   7245 *REC_V80:*
   7246 	LD	DE,(E_LINE)	; sv
   7247 	JP	RECLAIM_1 <#RECLAIM_1>
   7248 
   7249 ------------------------------------------------------------------------
   7250 
   7251 ; THE *'ALPHA'* SUBROUTINE
   7252 ------------------------------------------------------------------------
   7253 
   7254 
   7255 mark_14CE:
   7256 *ALPHA:*
   7257 	CP	ZX_A		; $26
   7258 	JR	ALPHA_2 <#ALPHA_2>		; skip forward
   7259 
   7260 
   7261 ------------------------------------------------------------------------
   7262 
   7263 ; THE *'ALPHANUM'* SUBROUTINE
   7264 ------------------------------------------------------------------------
   7265 
   7266 
   7267 mark_14D2:
   7268 *ALPHANUM:*
   7269 	CP	ZX_0		;
   7270 
   7271 
   7272 mark_14D4:
   7273 *ALPHA_2:*
   7274 	CCF			; Complement Carry Flag
   7275 	RET	NC		;
   7276 
   7277 	CP	$40		;
   7278 	RET			;
   7279 
   7280 
   7281 ------------------------------------------------------------------------
   7282 
   7283 ; THE *'DECIMAL TO FLOATING POINT'* SUBROUTINE
   7284 ------------------------------------------------------------------------
   7285 
   7286 ;
   7287 
   7288 mark_14D9:
   7289 *DEC_TO_FP:*
   7290 	CALL	INT_TO_FP <#INT_TO_FP>		; gets first part
   7291 	CP	ZX_PERIOD		; is character a '.' ?
   7292 	JR	NZ,E_FORMAT <#E_FORMAT>	; forward if not
   7293 
   7294 
   7295 	RST	_FP_CALC	;;
   7296 	DEFB	__stk_one	;;
   7297 	DEFB	__st_mem_0	;;
   7298 	DEFB	__delete	;;
   7299 	DEFB	__end_calc	;;
   7300 
   7301 
   7302 mark_14E5:
   7303 
   7304 *NXT_DGT_1:*
   7305 	RST	_NEXT_CHAR
   7306 	CALL	STK_DIGIT <#STK_DIGIT>
   7307 	JR	C,E_FORMAT <#E_FORMAT>	; forward
   7308 
   7309 
   7310 	RST	_FP_CALC	;;
   7311 	DEFB	__get_mem_0	;;
   7312 	DEFB	__stk_ten	;;
   7313 #if ORIGINAL
   7314 	DEFB	__division	;
   7315 	DEFB	$C0		;;st-mem-0
   7316 	DEFB	__multiply	;;
   7317 #else
   7318 	DEFB	$04		;;+multiply
   7319 	DEFB	$C0		;;st-mem-0
   7320 	DEFB	$05		;;+division
   7321 #endif
   7322 	DEFB	__addition	;;
   7323 	DEFB	__end_calc	;;
   7324 
   7325 	JR	NXT_DGT_1 <#NXT_DGT_1>		; loop back till exhausted
   7326 
   7327 ; ___
   7328 
   7329 mark_14F5:
   7330 *E_FORMAT:*
   7331 	CP	ZX_E		; is character 'E' ?
   7332 	RET	NZ		; return if not
   7333 
   7334 	LD	(IY+MEM_0_1st-RAMBASE),$FF	; initialize sv MEM_0_1st to $FF TRUE
   7335 
   7336 	RST	_NEXT_CHAR
   7337 	CP	ZX_PLUS		; is character a '+' ?
   7338 	JR	Z,SIGN_DONE <#SIGN_DONE>	; forward if so
   7339 
   7340 	CP	ZX_MINUS		; is it a '-' ?
   7341 	JR	NZ,ST_E_PART <#ST_E_PART>	; forward if not
   7342 
   7343 	INC	(IY+MEM_0_1st-RAMBASE)	; sv MEM_0_1st change to FALSE
   7344 
   7345 mark_1508:
   7346 *SIGN_DONE:*
   7347 	RST	_NEXT_CHAR
   7348 
   7349 mark_1509:
   7350 *ST_E_PART:*
   7351 	CALL	INT_TO_FP <#INT_TO_FP>
   7352 
   7353 	RST	_FP_CALC	;;		m, e.
   7354 	DEFB	__get_mem_0	;;		m, e, (1/0) TRUE/FALSE
   7355 	DEFB	__jump_true	;;
   7356 	DEFB	E_POSTVE <#E_POSTVE> - $	;;
   7357 	DEFB	__negate	;;		m, _e
   7358 
   7359 mark_1511:
   7360 *E_POSTVE:*
   7361 	DEFB	__e_to_fp	;;		x.
   7362 	DEFB	__end_calc	;;		x.
   7363 
   7364 	RET			; return.
   7365 
   7366 
   7367 ------------------------------------------------------------------------
   7368 
   7369 ; THE *'STK_DIGIT'* SUBROUTINE
   7370 ------------------------------------------------------------------------
   7371 
   7372 ;
   7373 
   7374 mark_1514:
   7375 *STK_DIGIT:*
   7376 	CP	ZX_0		;
   7377 	RET	C		;
   7378 
   7379 	CP	ZX_A		; $26
   7380 	CCF			; Complement Carry Flag
   7381 	RET	C		;
   7382 
   7383 	SUB	ZX_0		;
   7384 
   7385 ------------------------------------------------------------------------
   7386 
   7387 ; THE *'STACK_A'* SUBROUTINE
   7388 ------------------------------------------------------------------------
   7389 
   7390 ;
   7391 
   7392 
   7393 mark_151D:
   7394 *STACK_A:*
   7395 	LD	C,A		;
   7396 	LD	B,0		;
   7397 
   7398 ------------------------------------------------------------------------
   7399 
   7400 ; THE *'STACK_BC'* SUBROUTINE
   7401 ------------------------------------------------------------------------
   7402 
   7403 ; The ZX81 does not have an integer number format so the BC register contents
   7404 ; must be converted to their full floating-point form.
   7405 
   7406 mark_1520:
   7407 *STACK_BC:*
   7408 	LD	IY,ERR_NR	; re-initialize the system variables pointer.
   7409 	PUSH	BC		; save the integer value.
   7410 
   7411 ; now stack zero, five zero bytes as a starting point.
   7412 
   7413 	RST	_FP_CALC	;;
   7414 	DEFB	__stk_zero	;;			0.
   7415 	DEFB	__end_calc	;;
   7416 
   7417 	POP	BC		; restore integer value.
   7418 
   7419 	LD	(HL),$91	; place $91 in exponent	65536.
   7420 				; this is the maximum possible value
   7421 
   7422 	LD	A,B		; fetch hi-byte.
   7423 	AND	A		; test for zero.
   7424 	JR	NZ,STK_BC_2 <#STK_BC_2>	; forward if not zero
   7425 
   7426 	LD	(HL),A		; else make exponent zero again
   7427 	OR	C		; test lo-byte
   7428 	RET	Z		; return if BC was zero - done.
   7429 
   7430 ; else	there has to be a set bit if only the value one.
   7431 
   7432 	LD	B,C		; save C in B.
   7433 	LD	C,(HL)		; fetch zero to C
   7434 	LD	(HL),$89	; make exponent $89		256.
   7435 
   7436 mark_1536:
   7437 *STK_BC_2:*
   7438 	DEC	(HL)		; decrement exponent - halving number
   7439 	SLA	C		;	C<-76543210<-0
   7440 	RL	B		;	C<-76543210<-C
   7441 	JR	NC,STK_BC_2 <#STK_BC_2>	; loop back if no carry
   7442 
   7443 	SRL	B		;	0->76543210->C
   7444 	RR	C		;	C->76543210->C
   7445 
   7446 	INC	HL		; address first byte of mantissa
   7447 	LD	(HL),B		; insert B
   7448 	INC	HL		; address second byte of mantissa
   7449 	LD	(HL),C		; insert C
   7450 
   7451 	DEC	HL		; point to the
   7452 	DEC	HL		; exponent again
   7453 	RET			; return.
   7454 
   7455 ------------------------------------------------------------------------
   7456 
   7457 ; THE *'INTEGER TO FLOATING POINT'* SUBROUTINE
   7458 ------------------------------------------------------------------------
   7459 
   7460 ;
   7461 ;
   7462 
   7463 mark_1548:
   7464 *INT_TO_FP:*
   7465 	PUSH	AF		;
   7466 
   7467 	RST	_FP_CALC	;;
   7468 	DEFB	__stk_zero	;;
   7469 	DEFB	__end_calc	;;
   7470 
   7471 	POP	AF		;
   7472 
   7473 mark_154D:
   7474 *NXT_DGT_2:*
   7475 	CALL	STK_DIGIT <#STK_DIGIT>
   7476 	RET	C		;
   7477 
   7478 	RST	_FP_CALC	;;
   7479 	DEFB	__exchange	;;
   7480 	DEFB	__stk_ten	;;
   7481 	DEFB	__multiply	;;
   7482 	DEFB	__addition	;;
   7483 	DEFB	__end_calc	;;
   7484 
   7485 	RST	_NEXT_CHAR
   7486 	JR	NXT_DGT_2 <#NXT_DGT_2>
   7487 
   7488 
   7489 ------------------------------------------------------------------------
   7490 
   7491 ; THE *'E_FORMAT TO FLOATING POINT'* SUBROUTINE
   7492 ------------------------------------------------------------------------
   7493 
   7494 ; (Offset $38: 'e_to_fp')
   7495 ; invoked from DEC_TO_FP and PRINT_FP.
   7496 ; e.g. 2.3E4 is 23000.
   7497 ; This subroutine evaluates xEm where m is a positive or negative integer.
   7498 ; At a simple level x is multiplied by ten for every unit of m.
   7499 ; If the decimal exponent m is negative then x is divided by ten for each unit.
   7500 ; A short-cut is taken if the exponent is greater than seven and in this
   7501 ; case the exponent is reduced by seven and the value is multiplied or divided
   7502 ; by ten million.
   7503 ; Note. for the ZX Spectrum an even cleverer method was adopted which involved
   7504 ; shifting the bits out of the exponent so the result was achieved with six
   7505 ; shifts at most. The routine below had to be completely re-written mostly
   7506 ; in Z80 machine code.
   7507 ; Although no longer operable, the calculator literal was retained for old
   7508 ; times sake, the routine being invoked directly from a machine code CALL.
   7509 ;
   7510 ; On entry in the ZX81, m, the exponent, is the 'last value', and the
   7511 ; floating-point decimal mantissa is beneath it.
   7512 
   7513 
   7514 mark_155A:
   7515 *e_to_fp:*
   7516 	RST	_FP_CALC	;;		x, m.
   7517 	DEFB	__duplicate	;;		x, m, m.
   7518 	DEFB	__less_0	;;		x, m, (1/0).
   7519 	DEFB	__st_mem_0	;;		x, m, (1/0).
   7520 	DEFB	__delete	;;		x, m.
   7521 	DEFB	__abs		;;		x, +m.
   7522 
   7523 mark_1560:
   7524 *E_LOOP:*
   7525 	DEFB	__stk_one	;;		x, m,1.
   7526 	DEFB	__subtract	;;		x, m-1.
   7527 	DEFB	__duplicate	;;		x, m-1,m-1.
   7528 	DEFB	__less_0	;;		x, m-1, (1/0).
   7529 	DEFB	__jump_true	;;		x, m-1.
   7530 	DEFB	E_END <#E_END> - $	;;		x, m-1.
   7531 
   7532 	DEFB	__duplicate	;;		x, m-1, m-1.
   7533 	DEFB	__stk_data	;;
   7534 	DEFB	$33		;;Exponent: $83, Bytes: 1
   7535 
   7536 	DEFB	$40		;;(+00,+00,+00)	x, m-1, m-1, 6.
   7537 	DEFB	__subtract	;;		x, m-1, m-7.
   7538 	DEFB	__duplicate	;;		x, m-1, m-7, m-7.
   7539 	DEFB	__less_0	;;		x, m-1, m-7, (1/0).
   7540 	DEFB	__jump_true	;;		x, m-1, m-7.
   7541 	DEFB	E_LOW <#E_LOW> - $	;;
   7542 
   7543 ; but if exponent m is higher than 7 do a bigger chunk.
   7544 ; multiplying (or dividing if negative) by 10 million - 1e7.
   7545 
   7546 	DEFB	__exchange	;;		x, m-7, m-1.
   7547 	DEFB	__delete	;;		x, m-7.
   7548 	DEFB	__exchange	;;		m-7, x.
   7549 	DEFB	__stk_data	;;
   7550 	DEFB	$80		;;Bytes: 3
   7551 	DEFB	$48		;;Exponent $98
   7552 	DEFB	$18,$96,$80	;;(+00)		m-7, x, 10,000,000 (=f)
   7553 	DEFB	__jump		;;
   7554 	DEFB	E_CHUNK <#E_CHUNK> - $	;;
   7555 
   7556 ; ___
   7557 
   7558 mark_157A:
   7559 *E_LOW:*
   7560 	DEFB	__delete	;;		x, m-1.
   7561 	DEFB	__exchange	;;		m-1, x.
   7562 	DEFB	__stk_ten	;;		m-1, x, 10 (=f).
   7563 
   7564 mark_157D:
   7565 *E_CHUNK:*
   7566 	DEFB	__get_mem_0	;;		m-1, x, f, (1/0)
   7567 	DEFB	__jump_true	;;		m-1, x, f
   7568 	DEFB	E_DIVSN <#E_DIVSN> - $	;;
   7569 
   7570 	DEFB	__multiply	;;		m-1, x*f.
   7571 	DEFB	__jump		;;
   7572 	DEFB	E_SWAP <#E_SWAP> - $	;;
   7573 
   7574 ; ___
   7575 
   7576 mark_1583:
   7577 *E_DIVSN:*
   7578 	DEFB	__division	;;		m-1, x/f (= new x).
   7579 
   7580 mark_1584:
   7581 *E_SWAP:*
   7582 	DEFB	__exchange	;;		x, m-1 (= new m).
   7583 	DEFB	__jump		;;		x, m.
   7584 	DEFB	E_LOOP <#E_LOOP> - $	;;
   7585 
   7586 ; ___
   7587 
   7588 mark_1587:
   7589 *E_END:*
   7590 	DEFB	__delete	;;		x. (-1)
   7591 	DEFB	__end_calc	;;		x.
   7592 
   7593 	RET			; return.
   7594 
   7595 ------------------------------------------------------------------------
   7596 
   7597 ; THE *'FLOATING-POINT TO BC'* SUBROUTINE
   7598 ------------------------------------------------------------------------
   7599 
   7600 ; The floating-point form on the calculator stack is compressed directly into
   7601 ; the BC register rounding up if necessary.
   7602 ; Valid range is 0 to 65535.4999
   7603 
   7604 mark_158A:
   7605 *FP_TO_BC:*
   7606 	CALL	STK_FETCH <#STK_FETCH>		; exponent to A
   7607 				; mantissa to EDCB.
   7608 	AND	A		; test for value zero.
   7609 	JR	NZ,FPBC_NZRO <#FPBC_NZRO>	; forward if not
   7610 
   7611 ; else value is zero
   7612 
   7613 	LD	B,A		; zero to B
   7614 	LD	C,A		; also to C
   7615 	PUSH	AF		; save the flags on machine stack
   7616 	JR	FPBC_END <#FPBC_END>		; forward
   7617 
   7618 ; ___
   7619 
   7620 ; EDCB	=>	BCE
   7621 
   7622 mark_1595:
   7623 *FPBC_NZRO:*
   7624 	LD	B,E		; transfer the mantissa from EDCB
   7625 	LD	E,C		; to BCE. Bit 7 of E is the 17th bit which
   7626 	LD	C,D		; will be significant for rounding if the
   7627 				; number is already normalized.
   7628 
   7629 	SUB	$91		; subtract 65536
   7630 	CCF			; complement carry flag
   7631 	BIT	7,B		; test sign bit
   7632 	PUSH	AF		; push the result
   7633 
   7634 	SET	7,B		; set the implied bit
   7635 	JR	C,FPBC_END <#FPBC_END>	; forward with carry from SUB/CCF
   7636 				; number is too big.
   7637 
   7638 	INC	A		; increment the exponent and
   7639 	NEG			; negate to make range $00 - $0F
   7640 
   7641 	CP	$08		; test if one or two bytes
   7642 	JR	C,BIG_INT <#BIG_INT>	; forward with two
   7643 
   7644 	LD	E,C		; shift mantissa
   7645 	LD	C,B		; 8 places right
   7646 	LD	B,$00		; insert a zero in B
   7647 	SUB	$08		; reduce exponent by eight
   7648 
   7649 mark_15AF:
   7650 *BIG_INT:*
   7651 	AND	A		; test the exponent
   7652 	LD	D,A		; save exponent in D.
   7653 
   7654 	LD	A,E		; fractional bits to A
   7655 	RLCA			; rotate most significant bit to carry for
   7656 				; rounding of an already normal number.
   7657 
   7658 	JR	Z,EXP_ZERO <#EXP_ZERO>	; forward if exponent zero
   7659 				; the number is normalized
   7660 
   7661 mark_15B5:
   7662 *FPBC_NORM:*
   7663 	SRL	B		;	0->76543210->C
   7664 	RR	C		;	C->76543210->C
   7665 
   7666 	DEC	D		; decrement exponent
   7667 
   7668 	JR	NZ,FPBC_NORM <#FPBC_NORM>	; loop back till zero
   7669 
   7670 mark_15BC:
   7671 *EXP_ZERO:*
   7672 	JR	NC,FPBC_END <#FPBC_END>	; forward without carry to NO_ROUND	???
   7673 
   7674 	INC	BC		; round up.
   7675 	LD	A,B		; test result
   7676 	OR	C		; for zero
   7677 	JR	NZ,FPBC_END <#FPBC_END>	; forward if not to GRE_ZERO	???
   7678 
   7679 	POP	AF		; restore sign flag
   7680 	SCF			; set carry flag to indicate overflow
   7681 	PUSH	AF		; save combined flags again
   7682 
   7683 mark_15C6:
   7684 *FPBC_END:*
   7685 	PUSH	BC		; save BC value
   7686 
   7687 ; set HL and DE to calculator stack pointers.
   7688 
   7689 	RST	_FP_CALC	;;
   7690 	DEFB	__end_calc	;;
   7691 
   7692 
   7693 	POP	BC		; restore BC value
   7694 	POP	AF		; restore flags
   7695 	LD	A,C		; copy low byte to A also.
   7696 	RET			; return
   7697 
   7698 ------------------------------------------------------------------------
   7699 
   7700 ; THE *'FLOATING-POINT TO A'* SUBROUTINE
   7701 ------------------------------------------------------------------------
   7702 
   7703 ;
   7704 ;
   7705 
   7706 mark_15CD:
   7707 *FP_TO_A:*
   7708 	CALL	FP_TO_BC <#FP_TO_BC>
   7709 	RET	C		;
   7710 
   7711 	PUSH	AF		;
   7712 	DEC	B		;
   7713 	INC	B		;
   7714 	JR	Z,FP_A_END <#FP_A_END>	; forward if in range
   7715 
   7716 	POP	AF		; fetch result
   7717 	SCF			; set carry flag signaling overflow
   7718 	RET			; return
   7719 
   7720 mark_15D9:
   7721 *FP_A_END:*
   7722 	POP	AF		;
   7723 	RET			;
   7724 
   7725 
   7726 ------------------------------------------------------------------------
   7727 
   7728 ; THE *'PRINT A FLOATING-POINT NUMBER'* SUBROUTINE
   7729 ------------------------------------------------------------------------
   7730 
   7731 ; prints 'last value' x on calculator stack.
   7732 ; There are a wide variety of formats see Chapter 4.
   7733 ; e.g. 
   7734 ; PI		prints as	3.1415927
   7735 ; .123		prints as	0.123
   7736 ; .0123	prints as	.0123
   7737 ; 999999999999	prints as	1000000000000
   7738 ; 9876543210123 prints as	9876543200000
   7739 
   7740 ; Begin by isolating zero and just printing the '0' character
   7741 ; for that case. For negative numbers print a leading '-' and
   7742 ; then form the absolute value of x.
   7743 
   7744 mark_15DB:
   7745 *PRINT_FP:*
   7746 	RST	_FP_CALC	;;		x.
   7747 	DEFB	__duplicate	;;		x, x.
   7748 	DEFB	__less_0	;;		x, (1/0).
   7749 	DEFB	__jump_true	;;
   7750 	DEFB	PF_NEGTVE <#PF_NEGTVE> - $	;;	 	x.
   7751 
   7752 	DEFB	__duplicate	;;		x, x
   7753 	DEFB	__greater_0	;;		x, (1/0).
   7754 	DEFB	__jump_true	;;
   7755 	DEFB	PF_POSTVE <#PF_POSTVE> - $	;;		x.
   7756 
   7757 	DEFB	__delete	;;		.
   7758 	DEFB	__end_calc	;;		.
   7759 
   7760 	LD	A,ZX_0		; load accumulator with character '0'
   7761 
   7762 	RST	_PRINT_A
   7763 	RET			; return.				>>
   7764 
   7765 ; ___
   7766 
   7767 mark_15EA:
   7768 *PF_NEGTVE:*
   7769 	DEFB	__abs		;;		+x.
   7770 	DEFB	__end_calc	;;		x.
   7771 
   7772 	LD	A,ZX_MINUS	; load accumulator with '-'
   7773 
   7774 	RST	_PRINT_A
   7775 
   7776 	RST	_FP_CALC	;;		x.
   7777 
   7778 mark_15F0:
   7779 *PF_POSTVE:*
   7780 	DEFB	__end_calc	;;		x.
   7781 
   7782 ; register HL addresses the exponent of the floating-point value.
   7783 ; if positive, and point floats to left, then bit 7 is set.
   7784 
   7785 	LD	A,(HL)		; pick up the exponent byte
   7786 	CALL	STACK_A <#STACK_A>		; places on calculator stack.
   7787 
   7788 ; now calculate roughly the number of digits, n, before the decimal point by
   7789 ; subtracting a half from true exponent and multiplying by log to 
   7790 ; the base 10 of 2. 
   7791 ; The true number could be one higher than n, the integer result.
   7792 
   7793 	RST	_FP_CALC	;;			x, e.
   7794 	DEFB	__stk_data	;;
   7795 	DEFB	$78		;;Exponent: $88, Bytes: 2
   7796 	DEFB	$00,$80		;;(+00,+00)		x, e, 128.5.
   7797 	DEFB	__subtract	;;			x, e -.5.
   7798 	DEFB	__stk_data	;;
   7799 	DEFB	$EF		;;Exponent: $7F, Bytes: 4
   7800 	DEFB	$1A,$20,$9A,$85 ;;			.30103 (log10 2)
   7801 	DEFB	__multiply	;;			x,
   7802 	DEFB	__int		;;
   7803 	DEFB	__st_mem_1	;;			x, n.
   7804 
   7805 
   7806 	DEFB	__stk_data	;;
   7807 	DEFB	$34		;;Exponent: $84, Bytes: 1
   7808 	DEFB	$00		;;(+00,+00,+00)		x, n, 8.
   7809 
   7810 	DEFB	__subtract	;;			x, n-8.
   7811 	DEFB	__negate	;;			x, 8-n.
   7812 	DEFB	__e_to_fp	;;			x * (10^n)
   7813 
   7814 ; finally the 8 or 9 digit decimal is rounded.
   7815 ; a ten-digit integer can arise in the case of, say, 999999999.5
   7816 ; which gives 1000000000.
   7817 
   7818 	DEFB	__stk_half	;;
   7819 	DEFB	__addition	;;
   7820 	DEFB	__int		;;			i.
   7821 	DEFB	__end_calc	;;
   7822 
   7823 ; If there were 8 digits then final rounding will take place on the calculator 
   7824 ; stack above and the next two instructions insert a masked zero so that
   7825 ; no further rounding occurs. If the result is a 9 digit integer then
   7826 ; rounding takes place within the buffer.
   7827 
   7828 	LD	HL,$406B	; address system variable MEM_2_5th
   7829 				; which could be the 'ninth' digit.
   7830 	LD	(HL),$90	; insert the value $90	10010000
   7831 
   7832 ; now starting from lowest digit lay down the 8, 9 or 10 digit integer
   7833 ; which represents the significant portion of the number
   7834 ; e.g. PI will be the nine-digit integer 314159265
   7835 
   7836 	LD	B,10		; count is ten digits.
   7837 
   7838 mark_1615:
   7839 *PF_LOOP:*
   7840 	INC	HL		; increase pointer
   7841 
   7842 	PUSH	HL		; preserve buffer address.
   7843 	PUSH	BC		; preserve counter.
   7844 
   7845 	RST	_FP_CALC	;;		i.
   7846 	DEFB	__stk_ten	;;		i, 10.
   7847 	DEFB	__n_mod_m	;;		i mod 10, i/10
   7848 	DEFB	__exchange	;;		i/10, remainder.
   7849 	DEFB	__end_calc	;;
   7850 
   7851 	CALL	FP_TO_A <#FP_TO_A>		; $00-$09
   7852 
   7853 	OR	$90		; make left hand nibble 9 
   7854 
   7855 	POP	BC		; restore counter
   7856 	POP	HL		; restore buffer address.
   7857 
   7858 	LD	(HL),A		; insert masked digit in buffer.
   7859 	DJNZ	PF_LOOP <#PF_LOOP>		; loop back for all ten 
   7860 
   7861 ; the most significant digit will be last but if the number is exhausted then
   7862 ; the last one or two positions will contain zero ($90).
   7863 
   7864 ; e.g. for 'one' we have zero as estimate of leading digits.
   7865 ; 1*10^8 100000000 as integer value
   7866 ; 90 90 90 90 90	90 90 90 91 90 as buffer mem3/mem4 contents.
   7867 
   7868 
   7869 	INC	HL		; advance pointer to one past buffer 
   7870 	LD	BC,$0008	; set C to 8 ( B is already zero )
   7871 	PUSH	HL		; save pointer.
   7872 
   7873 mark_162C:
   7874 *PF_NULL:*
   7875 	DEC	HL		; decrease pointer
   7876 	LD	A,(HL)		; fetch masked digit
   7877 	CP	$90		; is it a leading zero ?
   7878 	JR	Z,PF_NULL <#PF_NULL>	; loop back if so
   7879 
   7880 ; at this point a significant digit has been found. carry is reset.
   7881 
   7882 	SBC	HL,BC		; subtract eight from the address.
   7883 	PUSH	HL		; ** save this pointer too
   7884 	LD	A,(HL)		; fetch addressed byte
   7885 	ADD	A,$6B		; add $6B - forcing a round up ripple
   7886 				; if	$95 or over.
   7887 	PUSH	AF		; save the carry result.
   7888 
   7889 ; now enter a loop to round the number. After rounding has been considered
   7890 ; a zero that has arisen from rounding or that was present at that position
   7891 ; originally is changed from $90 to $80.
   7892 
   7893 mark_1639:
   7894 *PF_RND_LP:*
   7895 	POP	AF		; retrieve carry from machine stack.
   7896 	INC	HL		; increment address
   7897 	LD	A,(HL)		; fetch new byte
   7898 	ADC	A,0		; add in any carry
   7899 
   7900 	DAA			; decimal adjust accumulator
   7901 				; carry will ripple through the '9'
   7902 
   7903 	PUSH	AF		; save carry on machine stack.
   7904 	AND	$0F		; isolate character 0 - 9 AND set zero flag
   7905 				; if zero.
   7906 	LD	(HL),A		; place back in location.
   7907 	SET	7,(HL)		; set bit 7 to show printable.
   7908 				; but not if trailing zero after decimal point.
   7909 	JR	Z,PF_RND_LP <#PF_RND_LP>	; back if a zero
   7910 				; to consider further rounding and/or trailing
   7911 				; zero identification.
   7912 
   7913 	POP	AF		; balance stack
   7914 	POP	HL		; ** retrieve lower pointer
   7915 
   7916 ; now insert 6 trailing zeros which are printed if before the decimal point
   7917 ; but mark the end of printing if after decimal point.
   7918 ; e.g. 9876543210123 is printed as 9876543200000
   7919 ; 123.456001 is printed as 123.456
   7920 
   7921 	LD	B,6		; the count is six.
   7922 
   7923 mark_164B:
   7924 *PF_ZERO_6:*
   7925 	LD	(HL),$80	; insert a masked zero
   7926 	DEC	HL		; decrease pointer.
   7927 	DJNZ	PF_ZERO_6 <#PF_ZERO_6>	; loop back for all six
   7928 
   7929 ; n-mod-m reduced the number to zero and this is now deleted from the calculator
   7930 ; stack before fetching the original estimate of leading digits.
   7931 
   7932 
   7933 	RST	_FP_CALC	;;		0.
   7934 	DEFB	__delete	;;		.
   7935 	DEFB	__get_mem_1	;;		n.
   7936 	DEFB	__end_calc	;;		n.
   7937 
   7938 	CALL	FP_TO_A <#FP_TO_A>
   7939 	JR	Z,PF_POS <#PF_POS>	; skip forward if positive
   7940 
   7941 	NEG			; negate makes positive
   7942 
   7943 mark_165B:
   7944 *PF_POS:*
   7945 	LD	E,A		; transfer count of digits to E
   7946 	INC	E		; increment twice 
   7947 	INC	E		; 
   7948 	POP	HL		; * retrieve pointer to one past buffer.
   7949 
   7950 mark_165F:
   7951 *GET_FIRST:*
   7952 	DEC	HL		; decrement address.
   7953 	DEC	E		; decrement digit counter.
   7954 	LD	A,(HL)		; fetch masked byte.
   7955 	AND	$0F		; isolate right-hand nibble.
   7956 	JR	Z,GET_FIRST <#GET_FIRST>	; back with leading zero
   7957 
   7958 ; now determine if E-format printing is needed
   7959 
   7960 	LD	A,E		; transfer now accurate number count to A.
   7961 	SUB	5		; subtract five
   7962 	CP	8		; compare with 8 as maximum digits is 13.
   7963 	JP	P,PF_E_FMT <#PF_E_FMT>	; forward if positive to PF_E_FMT
   7964 
   7965 	CP	$F6		; test for more than four zeros after point.
   7966 	JP	M,PF_E_FMT <#PF_E_FMT>	; forward if so to PF_E_FMT
   7967 
   7968 	ADD	A,6		; test for zero leading digits, e.g. 0.5
   7969 	JR	Z,PF_ZERO_1 <#PF_ZERO_1>	; forward if so to PF_ZERO_1 
   7970 
   7971 	JP	M,PF_ZEROS <#PF_ZEROS>	; forward if more than one zero to PF_ZEROS
   7972 
   7973 ; else digits before the decimal point are to be printed
   7974 
   7975 	LD	B,A		; count of leading characters to B.
   7976 
   7977 mark_167B:
   7978 *PF_NIB_LP:*
   7979 	CALL	PF_NIBBLE <#PF_NIBBLE>
   7980 	DJNZ	PF_NIB_LP <#PF_NIB_LP>		; loop back for counted numbers
   7981 
   7982 	JR	PF_DC_OUT <#PF_DC_OUT>		; forward to consider decimal part to PF_DC_OUT
   7983 
   7984 ; ___
   7985 
   7986 mark_1682:
   7987 *PF_E_FMT:*
   7988 	LD	B,E		; count to B
   7989 	CALL	PF_NIBBLE <#PF_NIBBLE>		; prints one digit.
   7990 	CALL	PF_DC_OUT <#PF_DC_OUT>		; considers fractional part.
   7991 
   7992 	LD	A,ZX_E		; 
   7993 	RST	_PRINT_A
   7994 
   7995 	LD	A,B		; transfer exponent to A
   7996 	AND	A		; test the sign.
   7997 	JP	P,PF_E_POS <#PF_E_POS>	; forward if positive to PF_E_POS
   7998 
   7999 	NEG			; negate the negative exponent.
   8000 	LD	B,A		; save positive exponent in B.
   8001 
   8002 	LD	A,ZX_MINUS	; 
   8003 	JR	PF_E_SIGN <#PF_E_SIGN>		; skip forward to PF_E_SIGN
   8004 
   8005 ; ___
   8006 
   8007 mark_1698:
   8008 *PF_E_POS:*
   8009 	LD	A,ZX_PLUS	; 
   8010 
   8011 mark_169A:
   8012 *PF_E_SIGN:*
   8013 	RST	_PRINT_A
   8014 
   8015 ; now convert the integer exponent in B to two characters.
   8016 ; it will be less than 99.
   8017 
   8018 	LD	A,B		; fetch positive exponent.
   8019 	LD	B,$FF		; initialize left hand digit to minus one.
   8020 
   8021 mark_169E:
   8022 *PF_E_TENS:*
   8023 	INC	B		; increment ten count
   8024 	SUB	10		; subtract ten from exponent
   8025 	JR	NC,PF_E_TENS <#PF_E_TENS>	; loop back if greater than ten
   8026 
   8027 	ADD	A,10		; reverse last subtraction
   8028 	LD	C,A		; transfer remainder to C
   8029 
   8030 	LD	A,B		; transfer ten value to A.
   8031 	AND	A		; test for zero.
   8032 	JR	Z,PF_E_LOW <#PF_E_LOW>	; skip forward if so to PF_E_LOW
   8033 
   8034 	CALL	OUT_CODE <#OUT_CODE>		; prints as digit '1' - '9'
   8035 
   8036 mark_16AD:
   8037 *PF_E_LOW:*
   8038 	LD	A,C		; low byte to A
   8039 	CALL	OUT_CODE <#OUT_CODE>		; prints final digit of the
   8040 				; exponent.
   8041 	RET			; return.				>>
   8042 
   8043 ------------------------------------------------------------------------
   8044 
   8045 ; THE *'FLOATING POINT PRINT ZEROS'* LOOP
   8046 ; -------------------------------------
   8047 ; This branch deals with zeros after decimal point.
   8048 ; e.g.      .01 or .0000999
   8049 ; Note. that printing to the ZX Printer destroys A and that A should be 
   8050 ; initialized to '0' at each stage of the loop.
   8051 ; Originally LPRINT .00001 printed as .0XYZ1
   8052 ------------------------------------------------------------------------
   8053 
   8054 mark_16B2:
   8055 *PF_ZEROS:*
   8056 	NEG			; negate makes number positive 1 to 4.
   8057 	LD	B,A		; zero count to B.
   8058 
   8059 	LD	A,ZX_PERIOD	; prepare character '.'
   8060 	RST	_PRINT_A
   8061 
   8062 
   8063 #if ORIGINAL
   8064 	LD	A,ZX_0		; prepare a '0'
   8065 *PFZROLP*
   8066 	RST	_PRINT_A
   8067 	DJNZ	PFZROLP <#PFZROLP>		; obsolete loop back to PFZROLP
   8068 #else
   8069 *PF_ZRO_LP*
   8070 	LD	A,ZX_0		; prepare a '0' in the accumulator each time.
   8071 	RST	_PRINT_A
   8072 	DJNZ	PF_ZRO_LP <#PF_ZRO_LP>	;+ New loop back to PF-ZRO-LP
   8073 #endif
   8074 
   8075 	JR	PF_FRAC_LP <#PF_FRAC_LP>		; forward
   8076 
   8077 ; there is	a need to print a leading zero e.g. 0.1 but not with .01
   8078 
   8079 mark_16BF:
   8080 *PF_ZERO_1:*
   8081 	LD	A,ZX_0		; prepare character '0'.
   8082 	RST	_PRINT_A
   8083 
   8084 ; this subroutine considers the decimal point and any trailing digits.
   8085 ; if the next character is a marked zero, $80, then nothing more to print.
   8086 
   8087 mark_16C2:
   8088 *PF_DC_OUT:*
   8089 	DEC	(HL)		; decrement addressed character
   8090 	INC	(HL)		; increment it again
   8091 	RET	PE		; return with overflow	(was 128) >>
   8092 				; as no fractional part
   8093 
   8094 ; else there is a fractional part so print the decimal point.
   8095 
   8096 	LD	A,ZX_PERIOD		; prepare character '.'
   8097 	RST	_PRINT_A
   8098 
   8099 ; now enter a loop to print trailing digits
   8100 
   8101 mark_16C8:
   8102 *PF_FRAC_LP:*
   8103 	DEC	(HL)		; test for a marked zero.
   8104 	INC	(HL)		;
   8105 	RET	PE		; return when digits exhausted		>>
   8106 
   8107 	CALL	PF_NIBBLE <#PF_NIBBLE>
   8108 	JR	PF_FRAC_LP <#PF_FRAC_LP>		; back for all fractional digits
   8109 
   8110 ; ___
   8111 
   8112 ; subroutine to print right-hand nibble
   8113 
   8114 mark_16D0:
   8115 *PF_NIBBLE:*
   8116 	LD	A,(HL)		; fetch addressed byte
   8117 	AND	$0F		; mask off lower 4 bits
   8118 	CALL	OUT_CODE <#OUT_CODE>
   8119 	DEC	HL		; decrement pointer.
   8120 	RET			; return.
   8121 
   8122 
   8123 ------------------------------------------------------------------------
   8124 
   8125 ; THE *'PREPARE TO ADD'* SUBROUTINE
   8126 ------------------------------------------------------------------------
   8127 
   8128 ; This routine is called twice to prepare each floating point number for
   8129 ; addition, in situ, on the calculator stack.
   8130 ; The exponent is picked up from the first byte which is then cleared to act
   8131 ; as a sign byte and accept any overflow.
   8132 ; If the exponent is zero then the number is zero and an early return is made.
   8133 ; The now redundant sign bit of the mantissa is set and if the number is 
   8134 ; negative then all five bytes of the number are twos-complemented to prepare 
   8135 ; the number for addition.
   8136 ; On the second invocation the exponent of the first number is in B.
   8137 
   8138 
   8139 mark_16D8:
   8140 *PREP_ADD:*
   8141 	LD	A,(HL)		; fetch exponent.
   8142 	LD	(HL),0		; make this byte zero to take any overflow and
   8143 				; default to positive.
   8144 	AND	A		; test stored exponent for zero.
   8145 	RET	Z		; return with zero flag set if number is zero.
   8146 
   8147 	INC	HL		; point to first byte of mantissa.
   8148 	BIT	7,(HL)		; test the sign bit.
   8149 	SET	7,(HL)		; set it to its implied state.
   8150 	DEC	HL		; set pointer to first byte again.
   8151 	RET	Z		; return if bit indicated number is positive.>>
   8152 
   8153 ; if negative then all five bytes are twos complemented starting at LSB.
   8154 
   8155 	PUSH	BC		; save B register contents.
   8156 	LD	BC,$0005	; set BC to five.
   8157 	ADD	HL,BC		; point to location after 5th byte.
   8158 	LD	B,C		; set the B counter to five.
   8159 	LD	C,A		; store original exponent in C.
   8160 	SCF			; set carry flag so that one is added.
   8161 
   8162 ; now enter a loop to twos_complement the number.
   8163 ; The first of the five bytes becomes $FF to denote a negative number.
   8164 
   8165 mark_16EC:
   8166 *NEG_BYTE:*
   8167 	DEC	HL		; point to first or more significant byte.
   8168 	LD	A,(HL)		; fetch to accumulator.
   8169 	CPL			; complement.
   8170 	ADC	A,0		; add in initial carry or any subsequent carry.
   8171 	LD	(HL),A		; place number back.
   8172 	DJNZ	NEG_BYTE <#NEG_BYTE>		; loop back five times
   8173 
   8174 	LD	A,C		; restore the exponent to accumulator.
   8175 	POP	BC		; restore B register contents.
   8176 
   8177 	RET			; return.
   8178 
   8179 ------------------------------------------------------------------------
   8180 
   8181 ; THE *'FETCH TWO NUMBERS'* SUBROUTINE
   8182 ------------------------------------------------------------------------
   8183 
   8184 ; This routine is used by addition, multiplication and division to fetch
   8185 ; the two five_byte numbers addressed by HL and DE from the calculator stack
   8186 ; into the Z80 registers.
   8187 ; The HL register may no longer point to the first of the two numbers.
   8188 ; Since the 32-bit addition operation is accomplished using two Z80 16-bit
   8189 ; instructions, it is important that the lower two bytes of each mantissa are
   8190 ; in one set of registers and the other bytes all in the alternate set.
   8191 ;
   8192 ; In: HL = highest number, DE= lowest number
   8193 ;
   8194 ;	: alt':
   8195 ;	:
   8196 ; Out:
   8197 ;	:H,B-C:C,B: num1
   8198 ;	:L,D-E:D-E: num2
   8199 
   8200 mark_16F7:
   8201 *FETCH_TWO:*
   8202 	PUSH	HL		; save HL 
   8203 	PUSH	AF		; save A - result sign when used from division.
   8204 
   8205 	LD	C,(HL)		;
   8206 	INC	HL		;
   8207 	LD	B,(HL)		;
   8208 	LD	(HL),A		; insert sign when used from multiplication.
   8209 	INC	HL		;
   8210 	LD	A,C		; m1
   8211 	LD	C,(HL)		;
   8212 	PUSH	BC		; PUSH m2 m3
   8213 
   8214 	INC	HL		;
   8215 	LD	C,(HL)		; m4
   8216 	INC	HL		;
   8217 	LD	B,(HL)		; m5	BC holds m5 m4
   8218 
   8219 	EX	DE,HL		; make HL point to start of second number.
   8220 
   8221 	LD	D,A		; m1
   8222 	LD	E,(HL)		;
   8223 	PUSH	DE		; PUSH m1 n1
   8224 
   8225 	INC	HL		;
   8226 	LD	D,(HL)		;
   8227 	INC	HL		;
   8228 	LD	E,(HL)		;
   8229 	PUSH	DE		; PUSH n2 n3
   8230 
   8231 	EXX			; - - - - - - -
   8232 
   8233 	POP	DE		; POP n2 n3
   8234 	POP	HL		; POP m1 n1
   8235 	POP	BC		; POP m2 m3
   8236 
   8237 	EXX			; - - - - - - -
   8238 
   8239 	INC	HL		;
   8240 	LD	D,(HL)		;
   8241 	INC	HL		;
   8242 	LD	E,(HL)		; DE holds n4 n5
   8243 
   8244 	POP	AF		; restore saved
   8245 	POP	HL		; registers.
   8246 	RET			; return.
   8247 
   8248 ------------------------------------------------------------------------
   8249 
   8250 ; THE *'SHIFT ADDEND'* SUBROUTINE
   8251 ------------------------------------------------------------------------
   8252 
   8253 ; The accumulator A contains the difference between the two exponents.
   8254 ; This is the lowest of the two numbers to be added 
   8255 
   8256 mark_171A:
   8257 *SHIFT_FP:*
   8258 	AND	A		; test difference between exponents.
   8259 	RET	Z		; return if zero. both normal.
   8260 
   8261 	CP	33		; compare with 33 bits.
   8262 	JR	NC,ADDEND_0 <#ADDEND_0>	; forward if greater than 32
   8263 
   8264 	PUSH	BC		; preserve BC - part 
   8265 	LD	B,A		; shift counter to B.
   8266 
   8267 ; Now perform B right shifts on the addend	L'D'E'D E
   8268 ; to bring it into line with the augend	H'B'C'C B
   8269 
   8270 mark_1722:
   8271 *ONE_SHIFT:*
   8272 	EXX			; - - -
   8273 	SRA	L		;	76543210->C	bit 7 unchanged.
   8274 	RR	D		; C->76543210->C
   8275 	RR	E		; C->76543210->C
   8276 	EXX			; - - - 
   8277 	RR	D		; C->76543210->C
   8278 	RR	E		; C->76543210->C
   8279 	DJNZ	ONE_SHIFT <#ONE_SHIFT>		; loop back B times
   8280 
   8281 	POP	BC		; restore BC
   8282 	RET	NC		; return if last shift produced no carry.	>>
   8283 
   8284 ; if carry flag was set then accuracy is being lost so round up the addend.
   8285 
   8286 	CALL	ADD_BACK <#ADD_BACK>
   8287 	RET	NZ		; return if not FF 00 00 00 00
   8288 
   8289 ; this branch makes all five bytes of the addend zero and is made during
   8290 ; addition when the exponents are too far apart for the addend bits to 
   8291 ; affect the result.
   8292 
   8293 mark_1736:
   8294 *ADDEND_0:*
   8295 	EXX			; select alternate set for more significant 
   8296 				; bytes.
   8297 	XOR	A		; clear accumulator.
   8298 
   8299 
   8300 ; this entry point (from multiplication) sets four of the bytes to zero or if 
   8301 ; continuing from above, during addition, then all five bytes are set to zero.
   8302 
   8303 mark_1738:
   8304 *ZEROS_4_OR_5:*
   8305 	LD	L,0		; set byte 1 to zero.
   8306 	LD	D,A		; set byte 2 to A.
   8307 	LD	E,L		; set byte 3 to zero.
   8308 	EXX			; select main set 
   8309 	LD	DE,$0000	; set lower bytes 4 and 5 to zero.
   8310 	RET			; return.
   8311 
   8312 ------------------------------------------------------------------------
   8313 
   8314 ; THE *'ADD_BACK'* SUBROUTINE
   8315 ------------------------------------------------------------------------
   8316 
   8317 ; Called from SHIFT_FP above during addition and after normalization from
   8318 ; multiplication.
   8319 ; This is really a 32_bit increment routine which sets the zero flag according
   8320 ; to the 32-bit result.
   8321 ; During addition, only negative numbers like FF FF FF FF FF,
   8322 ; the twos-complement version of xx 80 00 00 01 say 
   8323 ; will result in a full ripple FF 00 00 00 00.
   8324 ; FF FF FF FF FF when shifted right is unchanged by SHIFT_FP but sets the 
   8325 ; carry invoking this routine.
   8326 
   8327 mark_1741:
   8328 *ADD_BACK:*
   8329 	INC	E		;
   8330 	RET	NZ		;
   8331 
   8332 	INC	D		;
   8333 	RET	NZ		;
   8334 
   8335 	EXX			;
   8336 	INC	E		;
   8337 	JR	NZ,ALL_ADDED <#ALL_ADDED>	; forward if no overflow
   8338 
   8339 	INC	D		;
   8340 
   8341 mark_174A:
   8342 *ALL_ADDED:*
   8343 	EXX			;
   8344 	RET			; return with zero flag set for zero mantissa.
   8345 
   8346 
   8347 ------------------------------------------------------------------------
   8348 
   8349 ; THE *'SUBTRACTION'* OPERATION
   8350 ------------------------------------------------------------------------
   8351 
   8352 ; just switch the sign of subtrahend and do an add.
   8353 
   8354 mark_174C:
   8355 *SUBTRACT:*
   8356 	LD	A,(DE)		; fetch exponent byte of second number the
   8357 				; subtrahend. 
   8358 	AND	A		; test for zero
   8359 	RET	Z		; return if zero - first number is result.
   8360 
   8361 	INC	DE		; address the first mantissa byte.
   8362 	LD	A,(DE)		; fetch to accumulator.
   8363 	XOR	$80		; toggle the sign bit.
   8364 	LD	(DE),A		; place back on calculator stack.
   8365 	DEC	DE		; point to exponent byte.
   8366 				; continue into addition routine.
   8367 
   8368 ------------------------------------------------------------------------
   8369 
   8370 ; THE *'ADDITION'* OPERATION
   8371 ------------------------------------------------------------------------
   8372 
   8373 ; The addition operation pulls out all the stops and uses most of the Z80's
   8374 ; registers to add two floating-point numbers.
   8375 ; This is a binary operation and on entry, HL points to the first number
   8376 ; and DE to the second.
   8377 
   8378 mark_1755:
   8379 *ADDITION:*
   8380 	EXX			; - - -
   8381 	PUSH	HL		; save the pointer to the next literal.
   8382 	EXX			; - - -
   8383 
   8384 	PUSH	DE		; save pointer to second number
   8385 	PUSH	HL		; save pointer to first number - will be the
   8386 				; result pointer on calculator stack.
   8387 
   8388 	CALL	PREP_ADD <#PREP_ADD>
   8389 	LD	B,A		; save first exponent byte in B.
   8390 	EX	DE,HL		; switch number pointers.
   8391 	CALL	PREP_ADD <#PREP_ADD>
   8392 	LD	C,A		; save second exponent byte in C.
   8393 	CP	B		; compare the exponent bytes.
   8394 	JR	NC,SHIFT_LEN <#SHIFT_LEN>	; forward if second higher
   8395 
   8396 	LD	A,B		; else higher exponent to A
   8397 	LD	B,C		; lower exponent to B
   8398 	EX	DE,HL		; switch the number pointers.
   8399 
   8400 mark_1769:
   8401 *SHIFT_LEN:*
   8402 	PUSH	AF		; save higher exponent
   8403 	SUB	B		; subtract lower exponent
   8404 
   8405 	CALL	FETCH_TWO <#FETCH_TWO>
   8406 	CALL	SHIFT_FP <#SHIFT_FP>
   8407 
   8408 	POP	AF		; restore higher exponent.
   8409 	POP	HL		; restore result pointer.
   8410 	LD	(HL),A		; insert exponent byte.
   8411 	PUSH	HL		; save result pointer again.
   8412 
   8413 ; now perform the 32-bit addition using two 16-bit Z80 add instructions.
   8414 
   8415 	LD	L,B		; transfer low bytes of mantissa individually
   8416 	LD	H,C		; to HL register
   8417 
   8418 	ADD	HL,DE		; the actual binary addition of lower bytes
   8419 
   8420 ; now the two higher byte pairs that are in the alternate register sets.
   8421 
   8422 	EXX			; switch in set 
   8423 	EX	DE,HL		; transfer high mantissa bytes to HL register.
   8424 
   8425 	ADC	HL,BC		; the actual addition of higher bytes with
   8426 				; any carry from first stage.
   8427 
   8428 	EX	DE,HL		; result in DE, sign bytes ($FF or $00) to HL
   8429 
   8430 ; now consider the two sign bytes
   8431 
   8432 	LD	A,H		; fetch sign byte of num1
   8433 
   8434 	ADC	A,L		; add including any carry from mantissa 
   8435 				; addition. 00 or 01 or FE or FF
   8436 
   8437 	LD	L,A		; result in L.
   8438 
   8439 ; possible outcomes of signs and overflow from mantissa are
   8440 ;
   8441 ;	H +	L + carry =	L	RRA	XOR L	RRA
   8442 ------------------------------------------------------------------------
   8443 
   8444 ; 00 + 00		= 00	00	00
   8445 ; 00 + 00 + carry	= 01	00	01	carry
   8446 ; FF + FF		= FE C	FF	01	carry
   8447 ; FF + FF + carry	= FF C	FF	00
   8448 ; FF + 00		= FF	FF	00
   8449 ; FF + 00 + carry	= 00 C	80	80
   8450 
   8451 	RRA			; C->76543210->C
   8452 	XOR	L		; set bit 0 if shifting required.
   8453 
   8454 	EXX			; switch back to main set
   8455 	EX	DE,HL		; full mantissa result now in D'E'D E registers.
   8456 	POP	HL		; restore pointer to result exponent on 
   8457 				; the calculator stack.
   8458 
   8459 	RRA			; has overflow occurred ?
   8460 	JR	NC,TEST_NEG <#TEST_NEG>	; skip forward if not
   8461 
   8462 ; if the addition of two positive mantissas produced overflow or if the
   8463 ; addition of two negative mantissas did not then the result exponent has to
   8464 ; be incremented and the mantissa shifted one place to the right.
   8465 
   8466 	LD	A,1		; one shift required.
   8467 	CALL	SHIFT_FP <#SHIFT_FP>		; performs a single shift 
   8468 				; rounding any lost bit
   8469 	INC	(HL)		; increment the exponent.
   8470 	JR	Z,ADD_REP_6 <#ADD_REP_6>	; forward to ADD_REP_6 if the exponent
   8471 				; wraps round from FF to zero as number is too
   8472 				; big for the system.
   8473 
   8474 ; at this stage the exponent on the calculator stack is correct.
   8475 
   8476 mark_1790:
   8477 *TEST_NEG:*
   8478 	EXX			; switch in the alternate set.
   8479 	LD	A,L		; load result sign to accumulator.
   8480 	AND	$80		; isolate bit 7 from sign byte setting zero
   8481 				; flag if positive.
   8482 	EXX			; back to main set.
   8483 
   8484 	INC	HL		; point to first byte of mantissa
   8485 	LD	(HL),A		; insert $00 positive or $80 negative at 
   8486 				; position on calculator stack.
   8487 
   8488 	DEC	HL		; point to exponent again.
   8489 	JR	Z,GO_NC_MLT <#GO_NC_MLT>	; forward if positive to GO_NC_MLT
   8490 
   8491 ; a negative number has to be twos-complemented before being placed on stack.
   8492 
   8493 	LD	A,E		; fetch lowest (rightmost) mantissa byte.
   8494 	NEG			; Negate
   8495 	CCF			; Complement Carry Flag
   8496 	LD	E,A		; place back in register
   8497 
   8498 	LD	A,D		; ditto
   8499 	CPL			;
   8500 	ADC	A,0		;
   8501 	LD	D,A		;
   8502 
   8503 	EXX			; switch to higher (leftmost) 16 bits.
   8504 
   8505 	LD	A,E		; ditto
   8506 	CPL			;
   8507 	ADC	A,0		;
   8508 	LD	E,A		;
   8509 
   8510 	LD	A,D		; ditto
   8511 	CPL			;
   8512 	ADC	A,0		;
   8513 	JR	NC,END_COMPL <#END_COMPL>	; forward without overflow to END_COMPL
   8514 
   8515 ; else entire mantissa is now zero.	00 00 00 00
   8516 
   8517 	RRA			; set mantissa to 80 00 00 00
   8518 	EXX			; switch.
   8519 	INC	(HL)		; increment the exponent.
   8520 
   8521 mark_17B3:
   8522 *ADD_REP_6:*
   8523 	JP	Z,REPORT_6 <#REPORT_6>	; jump forward if exponent now zero to REPORT_6
   8524 				; 'Number too big'
   8525 
   8526 	EXX			; switch back to alternate set.
   8527 
   8528 mark_17B7:
   8529 *END_COMPL:*
   8530 	LD	D,A		; put first byte of mantissa back in DE.
   8531 	EXX			; switch to main set.
   8532 
   8533 mark_17B9:
   8534 *GO_NC_MLT:*
   8535 	XOR	A		; clear carry flag and
   8536 				; clear accumulator so no extra bits carried
   8537 				; forward as occurs in multiplication.
   8538 
   8539 	JR	TEST_NORM <#TEST_NORM>		; forward to common code at TEST_NORM 
   8540 				; but should go straight to NORMALIZE.
   8541 
   8542 
   8543 ------------------------------------------------------------------------
   8544 
   8545 ; THE *'PREPARE TO MULTIPLY OR DIVIDE'* SUBROUTINE
   8546 ------------------------------------------------------------------------
   8547 
   8548 ; this routine is called twice from multiplication and twice from division
   8549 ; to prepare each of the two numbers for the operation.
   8550 ; Initially the accumulator holds zero and after the second invocation bit 7
   8551 ; of the accumulator will be the sign bit of the result.
   8552 
   8553 mark_17BC:
   8554 *PREP_MULTIPLY_OR_DIVIDE:*
   8555 	SCF			; set carry flag to signal number is zero.
   8556 	DEC	(HL)		; test exponent
   8557 	INC	(HL)		; for zero.
   8558 	RET	Z		; return if zero with carry flag set.
   8559 
   8560 	INC	HL		; address first mantissa byte.
   8561 	XOR	(HL)		; exclusive or the running sign bit.
   8562 	SET	7,(HL)		; set the implied bit.
   8563 	DEC	HL		; point to exponent byte.
   8564 	RET			; return.
   8565 
   8566 ------------------------------------------------------------------------
   8567 
   8568 ; THE *'MULTIPLICATION'* OPERATION
   8569 ------------------------------------------------------------------------
   8570 
   8571 ;
   8572 ;
   8573 
   8574 mark_17C6:
   8575 *MULTIPLY:*
   8576 	XOR	A		; reset bit 7 of running sign flag.
   8577 	CALL	PREP_MULTIPLY_OR_DIVIDE <#PREP_MULTIPLY_OR_DIVIDE>
   8578 	RET	C		; return if number is zero.
   8579 				; zero * anything = zero.
   8580 
   8581 	EXX			; - - -
   8582 	PUSH	HL		; save pointer to 'next literal'
   8583 	EXX			; - - -
   8584 
   8585 	PUSH	DE		; save pointer to second number 
   8586 
   8587 	EX	DE,HL		; make HL address second number.
   8588 
   8589 	CALL	PREP_MULTIPLY_OR_DIVIDE <#PREP_MULTIPLY_OR_DIVIDE>
   8590 
   8591 	EX	DE,HL		; HL first number, DE - second number
   8592 	JR	C,ZERO_RESULT <#ZERO_RESULT>	; forward with carry to ZERO_RESULT
   8593 				; anything * zero = zero.
   8594 
   8595 	PUSH	HL		; save pointer to first number.
   8596 
   8597 	CALL	FETCH_TWO <#FETCH_TWO>		; fetches two mantissas from
   8598 				; calc stack to B'C'C,B	D'E'D E
   8599 				; (HL will be overwritten but the result sign
   8600 				; in A is inserted on the calculator stack)
   8601 
   8602 	LD	A,B		; transfer low mantissa byte of first number
   8603 	AND	A		; clear carry.
   8604 	SBC	HL,HL		; a short form of LD HL,$0000 to take lower
   8605 				; two bytes of result. (2 program bytes)
   8606 	EXX			; switch in alternate set
   8607 	PUSH	HL		; preserve HL
   8608 	SBC	HL,HL		; set HL to zero also to take higher two bytes
   8609 				; of the result and clear carry.
   8610 	EXX			; switch back.
   8611 
   8612 	LD	B,33		; register B can now be used to count 33 shifts.
   8613 	JR	STRT_MLT <#STRT_MLT>		; forward to loop entry point STRT_MLT
   8614 
   8615 ; ___
   8616 
   8617 ; The multiplication loop is entered at	STRT_LOOP.
   8618 
   8619 mark_17E7:
   8620 *MLT_LOOP:*
   8621 	JR	NC,NO_ADD <#NO_ADD>	; forward if no carry
   8622 
   8623 				; else add in the multiplicand.
   8624 
   8625 	ADD	HL,DE		; add the two low bytes to result
   8626 	EXX			; switch to more significant bytes.
   8627 	ADC	HL,DE		; add high bytes of multiplicand and any carry.
   8628 	EXX			; switch to main set.
   8629 
   8630 ; in either case shift result right into B'C'C A
   8631 
   8632 mark_17EE:
   8633 *NO_ADD:*
   8634 	EXX			; switch to alternate set
   8635 	RR	H		; C > 76543210 > C
   8636 	RR	L		; C > 76543210 > C
   8637 	EXX			;
   8638 	RR	H		; C > 76543210 > C
   8639 	RR	L		; C > 76543210 > C
   8640 
   8641 mark_17F8:
   8642 *STRT_MLT:*
   8643 	EXX			; switch in alternate set.
   8644 	RR	B		; C > 76543210 > C
   8645 	RR	C		; C > 76543210 > C
   8646 	EXX			; now main set
   8647 	RR	C		; C > 76543210 > C
   8648 	RRA			; C > 76543210 > C
   8649 	DJNZ	MLT_LOOP <#MLT_LOOP>		; loop back 33 timeS
   8650 
   8651 ;
   8652 
   8653 	EX	DE,HL		;
   8654 	EXX			;
   8655 	EX	DE,HL		;
   8656 	EXX			;
   8657 	POP	BC		;
   8658 	POP	HL		;
   8659 	LD	A,B		;
   8660 	ADD	A,C		;
   8661 	JR	NZ,MAKE_EXPT <#MAKE_EXPT>	; forward
   8662 
   8663 	AND	A		;
   8664 
   8665 mark_180E:
   8666 *MAKE_EXPT:*
   8667 	DEC	A		;
   8668 	CCF			; Complement Carry Flag
   8669 
   8670 mark_1810:
   8671 *DIVN_EXPT:*
   8672 	RLA			;
   8673 	CCF			; Complement Carry Flag
   8674 	RRA			;
   8675 	JP	P,OFLW1_CLR <#OFLW1_CLR>
   8676 
   8677 	JR	NC,REPORT_6 <#REPORT_6>
   8678 
   8679 	AND	A		;
   8680 
   8681 mark_1819:
   8682 *OFLW1_CLR:*
   8683 	INC	A		;
   8684 	JR	NZ,OFLW2_CLR <#OFLW2_CLR>
   8685 
   8686 	JR	C,OFLW2_CLR <#OFLW2_CLR>
   8687 
   8688 	EXX			;
   8689 	BIT	7,D		;
   8690 	EXX			;
   8691 	JR	NZ,REPORT_6 <#REPORT_6>
   8692 
   8693 mark_1824:
   8694 *OFLW2_CLR:*
   8695 	LD	(HL),A		;
   8696 	EXX			;
   8697 	LD	A,B		;
   8698 	EXX			;
   8699 
   8700 ; addition joins here with carry flag clear.
   8701 
   8702 mark_1828:
   8703 *TEST_NORM:*
   8704 	JR	NC,NORMALIZE <#NORMALIZE>	; forward
   8705 
   8706 	LD	A,(HL)		;
   8707 	AND	A		;
   8708 
   8709 mark_182C:
   8710 *NEAR_ZERO:*
   8711 	LD	A,$80		; prepare to rescue the most significant bit 
   8712 				; of the mantissa if it is set.
   8713 	JR	Z,SKIP_ZERO <#SKIP_ZERO>	; skip forward
   8714 
   8715 mark_1830:
   8716 *ZERO_RESULT:*
   8717 	XOR	A		; make mask byte zero signaling set five
   8718 				; bytes to zero.
   8719 
   8720 mark_1831:
   8721 *SKIP_ZERO:*
   8722 	EXX			; switch in alternate set
   8723 	AND	D		; isolate most significant bit (if A is $80).
   8724 
   8725 	CALL	ZEROS_4_OR_5 <#ZEROS_4_OR_5>		; sets mantissa without 
   8726 				; affecting any flags.
   8727 
   8728 	RLCA			; test if MSB set. bit 7 goes to bit 0.
   8729 				; either $00 -> $00 or $80 -> $01
   8730 	LD	(HL),A		; make exponent $01 (lowest) or $00 zero
   8731 	JR	C,OFLOW_CLR <#OFLOW_CLR>	; forward if first case
   8732 
   8733 	INC	HL		; address first mantissa byte on the
   8734 				; calculator stack.
   8735 	LD	(HL),A		; insert a zero for the sign bit.
   8736 	DEC	HL		; point to zero exponent
   8737 	JR	OFLOW_CLR <#OFLOW_CLR>		; forward
   8738 
   8739 ; ___
   8740 
   8741 ; this branch is common to addition and multiplication with the mantissa
   8742 ; result still in registers D'E'D E .
   8743 
   8744 mark_183F:
   8745 *NORMALIZE:*
   8746 	LD	B,32		; a maximum of thirty-two left shifts will be 
   8747 				; needed.
   8748 
   8749 mark_1841:
   8750 *SHIFT_ONE:*
   8751 	EXX			; address higher 16 bits.
   8752 	BIT	7,D		; test the leftmost bit
   8753 	EXX			; address lower 16 bits.
   8754 
   8755 	JR	NZ,NORML_NOW <#NORML_NOW>	; forward if leftmost bit was set
   8756 
   8757 	RLCA			; this holds zero from addition, 33rd bit 
   8758 				; from multiplication.
   8759 
   8760 	RL	E		; C < 76543210 < C
   8761 	RL	D		; C < 76543210 < C
   8762 
   8763 	EXX			; address higher 16 bits.
   8764 
   8765 	RL	E		; C < 76543210 < C
   8766 	RL	D		; C < 76543210 < C
   8767 
   8768 	EXX			; switch to main set.
   8769 
   8770 	DEC	(HL)		; decrement the exponent byte on the calculator
   8771 				; stack.
   8772 
   8773 	JR	Z,NEAR_ZERO <#NEAR_ZERO>	; back if exponent becomes zero
   8774 				; it's just possible that the last rotation
   8775 				; set bit 7 of D. We shall see.
   8776 
   8777 	DJNZ	SHIFT_ONE <#SHIFT_ONE>	; loop back
   8778 
   8779 ; if thirty-two left shifts were performed without setting the most significant 
   8780 ; bit then the result is zero.
   8781 
   8782 	JR	ZERO_RESULT <#ZERO_RESULT>	; back
   8783 
   8784 ; ___
   8785 
   8786 mark_1859:
   8787 *NORML_NOW:*
   8788 	RLA			; for the addition path, A is always zero.
   8789 				; for the mult path, ...
   8790 
   8791 	JR	NC,OFLOW_CLR <#OFLOW_CLR>	; forward
   8792 
   8793 ; this branch is taken only with multiplication.
   8794 
   8795 	CALL	ADD_BACK <#ADD_BACK>
   8796 
   8797 	JR	NZ,OFLOW_CLR <#OFLOW_CLR>	; forward
   8798 
   8799 	EXX			;
   8800 	LD	D,$80		;
   8801 	EXX			;
   8802 	INC	(HL)		;
   8803 	JR	Z,REPORT_6 <#REPORT_6>	; forward
   8804 
   8805 ; now transfer the mantissa from the register sets to the calculator stack
   8806 ; incorporating the sign bit already there.
   8807 
   8808 mark_1868:
   8809 *OFLOW_CLR:*
   8810 	PUSH	HL		; save pointer to exponent on stack.
   8811 	INC	HL		; address first byte of mantissa which was 
   8812 				; previously loaded with sign bit $00 or $80.
   8813 
   8814 	EXX			; - - -
   8815 	PUSH	DE		; push the most significant two bytes.
   8816 	EXX			; - - -
   8817 
   8818 	POP	BC		; pop - true mantissa is now BCDE.
   8819 
   8820 ; now pick up the sign bit.
   8821 
   8822 	LD	A,B		; first mantissa byte to A 
   8823 	RLA			; rotate out bit 7 which is set
   8824 	RL	(HL)		; rotate sign bit on stack into carry.
   8825 	RRA			; rotate sign bit into bit 7 of mantissa.
   8826 
   8827 ; and transfer mantissa from main registers to calculator stack.
   8828 
   8829 	LD	(HL),A		;
   8830 	INC	HL		;
   8831 	LD	(HL),C		;
   8832 	INC	HL		;
   8833 	LD	(HL),D		;
   8834 	INC	HL		;
   8835 	LD	(HL),E		;
   8836 
   8837 	POP	HL		; restore pointer to num1 now result.
   8838 	POP	DE		; restore pointer to num2 now STKEND.
   8839 
   8840 	EXX			; - - -
   8841 	POP	HL		; restore pointer to next calculator literal.
   8842 	EXX			; - - -
   8843 
   8844 	RET			; return.
   8845 
   8846 ; ___
   8847 
   8848 mark_1880:
   8849 *REPORT_6:*
   8850 	RST	_ERROR_1
   8851 	DEFB	5		; Error Report: Arithmetic overflow.
   8852 
   8853 ------------------------------------------------------------------------
   8854 
   8855 ; THE *'DIVISION'* OPERATION
   8856 ------------------------------------------------------------------------
   8857 
   8858 ;	"Of all the arithmetic subroutines, division is the most complicated and
   8859 ;	the least understood.	It is particularly interesting to note that the 
   8860 ;	Sinclair programmer himself has made a mistake in his programming ( or has
   8861 ;	copied over someone else's mistake!) for
   8862 ;	PRINT PEEK 6352 [ $18D0 ] ('unimproved' ROM, 6351 [ $18CF ] )
   8863 ;	should give 218 not 225."
   8864 ;	- Dr. Ian Logan, Syntax magazine Jul/Aug 1982.
   8865 ;	[ i.e. the jump should be made to div-34th ]
   8866 
   8867 ;	First check for division by zero.
   8868 
   8869 mark_1882:
   8870 *DIVISION:*
   8871 	EX	DE,HL		; consider the second number first. 
   8872 	XOR	A		; set the running sign flag.
   8873 	CALL	PREP_MULTIPLY_OR_DIVIDE <#PREP_MULTIPLY_OR_DIVIDE>
   8874 	JR	C,REPORT_6 <#REPORT_6>	; back if zero
   8875 				; 'Arithmetic overflow'
   8876 
   8877 	EX	DE,HL		; now prepare first number and check for zero.
   8878 	CALL	PREP_MULTIPLY_OR_DIVIDE <#PREP_MULTIPLY_OR_DIVIDE>
   8879 	RET	C		; return if zero, 0/anything is zero.
   8880 
   8881 	EXX			; - - -
   8882 	PUSH	HL		; save pointer to the next calculator literal.
   8883 	EXX			; - - -
   8884 
   8885 	PUSH	DE		; save pointer to divisor - will be STKEND.
   8886 	PUSH	HL		; save pointer to dividend - will be result.
   8887 
   8888 	CALL	FETCH_TWO <#FETCH_TWO>		; fetches the two numbers
   8889 				; into the registers H'B'C'C B
   8890 				;			L'D'E'D E
   8891 	EXX			; - - -
   8892 	PUSH	HL		; save the two exponents.
   8893 
   8894 	LD	H,B		; transfer the dividend to H'L'H L
   8895 	LD	L,C		; 
   8896 	EXX			;
   8897 	LD	H,C		;
   8898 	LD	L,B		; 
   8899 
   8900 	XOR	A		; clear carry bit and accumulator.
   8901 	LD	B,$DF		; count upwards from -33 decimal
   8902 	JR	DIVISION_START <#DIVISION_START>		; forward to mid-loop entry point
   8903 
   8904 ; ___
   8905 
   8906 mark_18A2:
   8907 *DIV_LOOP:*
   8908 	RLA			; multiply partial quotient by two
   8909 	RL	C		; setting result bit from carry.
   8910 	EXX			;
   8911 	RL	C		;
   8912 	RL	B		;
   8913 	EXX			;
   8914 
   8915 mark_18AB:
   8916 *DIV_34TH:*
   8917 	ADD	HL,HL		;
   8918 	EXX			;
   8919 	ADC	HL,HL		;
   8920 	EXX			;
   8921 	JR	C,SUBN_ONLY <#SUBN_ONLY>	; forward
   8922 
   8923 mark_18B2:
   8924 *DIVISION_START:*
   8925 	SBC	HL,DE		; subtract divisor part.
   8926 	EXX			;
   8927 	SBC	HL,DE		;
   8928 	EXX			;
   8929 	JR	NC,NUM_RESTORE <#NUM_RESTORE>	; forward if subtraction goes
   8930 
   8931 	ADD	HL,DE		; else restore
   8932 	EXX			;
   8933 	ADC	HL,DE		;
   8934 	EXX			;
   8935 	AND	A		; clear carry
   8936 	JR	COUNT_ONE <#COUNT_ONE>		; forward
   8937 
   8938 ; ___
   8939 
   8940 mark_18C2:
   8941 *SUBN_ONLY:*
   8942 	AND	A		;
   8943 	SBC	HL,DE		;
   8944 	EXX			;
   8945 	SBC	HL,DE		;
   8946 	EXX			;
   8947 
   8948 mark_18C9:
   8949 *NUM_RESTORE:*
   8950 	SCF			; set carry flag
   8951 
   8952 mark_18CA:
   8953 *COUNT_ONE:*
   8954 	INC	B		; increment the counter
   8955 	JP	M,DIV_LOOP <#DIV_LOOP>	; back while still minus to DIV_LOOP
   8956 
   8957 	PUSH	AF		;
   8958 	JR	Z,DIVISION_START <#DIVISION_START>	; back to DIV_START
   8959 
   8960 ; "This jump is made to the wrong place. No 34th bit will ever be obtained
   8961 ; without first shifting the dividend. Hence important results like 1/10 and
   8962 ; 1/1000 are not rounded up as they should be. Rounding up never occurs when
   8963 ; it depends on the 34th bit. The jump should be made to div_34th above."
   8964 ; - Dr. Frank O'Hara, "The Complete Spectrum ROM Disassembly", 1983,
   8965 ; published by Melbourne House.
   8966 ; (Note. on the ZX81 this would be JR Z,DIV_34TH)
   8967 ;
   8968 ; However if you make this change, then while (1/2=.5) will now evaluate as
   8969 ; true, (.25=1/4), which did evaluate as true, no longer does.
   8970 
   8971 	LD	E,A		;
   8972 	LD	D,C		;
   8973 	EXX			;
   8974 	LD	E,C		;
   8975 	LD	D,B		;
   8976 
   8977 	POP	AF		;
   8978 	RR	B		;
   8979 	POP	AF		;
   8980 	RR	B		;
   8981 
   8982 	EXX			;
   8983 	POP	BC		;
   8984 	POP	HL		;
   8985 	LD	A,B		;
   8986 	SUB	C		;
   8987 	JP	DIVN_EXPT <#DIVN_EXPT>		; jump back
   8988 
   8989 ------------------------------------------------------------------------
   8990 
   8991 ; THE *'INTEGER TRUNCATION TOWARDS ZERO'* SUBROUTINE
   8992 ------------------------------------------------------------------------
   8993 
   8994 ;
   8995 
   8996 mark_18E4:
   8997 *TRUNCATE:*
   8998 	LD	A,(HL)		; fetch exponent
   8999 	CP	$81		; compare to +1
   9000 	JR	NC,T_GR_ZERO <#T_GR_ZERO>	; forward, if 1 or more
   9001 
   9002 ; else the number is smaller than plus or minus 1 and can be made zero.
   9003 
   9004 	LD	(HL),$00	; make exponent zero.
   9005 	LD	A,$20		; prepare to set 32 bits of mantissa to zero.
   9006 	JR	NIL_BYTES <#NIL_BYTES>	; forward
   9007 
   9008 ; ___
   9009 
   9010 mark_18EF:
   9011 *T_GR_ZERO:*
   9012 	SUB	$A0		; subtract +32 from exponent
   9013 	RET	P		; return if result is positive as all 32 bits 
   9014 				; of the mantissa relate to the integer part.
   9015 				; The floating point is somewhere to the right 
   9016 				; of the mantissa
   9017 
   9018 	NEG			; else negate to form number of rightmost bits 
   9019 				; to be blanked.
   9020 
   9021 ; for instance, disregarding the sign bit, the number 3.5 is held as 
   9022 ; exponent $82 mantissa .11100000 00000000 00000000 00000000
   9023 ; we need to set $82 - $A0 = $E2 NEG = $1E (thirty) bits to zero to form the 
   9024 ; integer.
   9025 ; The sign of the number is never considered as the first bit of the mantissa
   9026 ; must be part of the integer.
   9027 
   9028 mark_18F4:
   9029 *NIL_BYTES:*
   9030 	PUSH	DE		; save pointer to STKEND
   9031 	EX	DE,HL		; HL points at STKEND
   9032 	DEC	HL		; now at last byte of mantissa.
   9033 	LD	B,A		; Transfer bit count to B register.
   9034 	SRL	B		; divide by 
   9035 	SRL	B		; eight
   9036 	SRL	B		;
   9037 	JR	Z,BITS_ZERO <#BITS_ZERO>	; forward if zero
   9038 
   9039 ; else the original count was eight or more and whole bytes can be blanked.
   9040 
   9041 mark_1900:
   9042 *BYTE_ZERO:*
   9043 	LD	(HL),0		; set eight bits to zero.
   9044 	DEC	HL		; point to more significant byte of mantissa.
   9045 	DJNZ	BYTE_ZERO <#BYTE_ZERO>		; loop back
   9046 
   9047 ; now consider any residual bits.
   9048 
   9049 mark_1905:
   9050 *BITS_ZERO:*
   9051 	AND	$07		; isolate the remaining bits
   9052 	JR	Z,IX_END <#IX_END>	; forward if none
   9053 
   9054 	LD	B,A		; transfer bit count to B counter.
   9055 	LD	A,$FF		; form a mask 11111111
   9056 
   9057 mark_190C:
   9058 *LESS_MASK:*
   9059 	SLA	A		; 1 <- 76543210 <- o	slide mask leftwards.
   9060 	DJNZ	LESS_MASK <#LESS_MASK>		; loop back for bit count
   9061 
   9062 	AND	(HL)		; lose the unwanted rightmost bits
   9063 	LD	(HL),A		; and place in mantissa byte.
   9064 
   9065 mark_1912:
   9066 *IX_END:*
   9067 	EX	DE,HL		; restore result pointer from DE. 
   9068 	POP	DE		; restore STKEND from stack.
   9069 	RET			; return.
   9070 
   9071 ------------------------------------------------------------------------
   9072 
   9073 ;   Up to this point all routine addresses have been maintained so that the
   9074 ;   modified ROM is compatible with any machine-code software that uses ROM
   9075 ;   routines.
   9076 ;   The final section does not maintain address entry points as the routines
   9077 ;   within are not generally called directly.
   9078 ------------------------------------------------------------------------
   9079 
   9080 ;**	FLOATING-POINT CALCULATOR **
   9081 ;********************************
   9082 ; As a general rule the calculator avoids using the IY register.
   9083 ; Exceptions are val and str$.
   9084 ; So an assembly language programmer who has disabled interrupts to use IY
   9085 ; for other purposes can still use the calculator for mathematical
   9086 ; purposes.
   9087 ------------------------------------------------------------------------
   9088 
   9089 ; THE *'TABLE OF CONSTANTS'*
   9090 ------------------------------------------------------------------------
   9091 
   9092 ; The ZX81 has only floating-point number representation.
   9093 ; Both the ZX80 and the ZX Spectrum have integer numbers in some form.
   9094 
   9095 
   9096 *TAB_CNST*
   9097 
   9098 #if ORIGINAL
   9099 mark_1915:
   9100 **				;	00 00 00 00 00
   9101 stk_zero:
   9102 	DEFB	$00		;;Bytes: 1
   9103 	DEFB	$B0		;;Exponent $00
   9104 	DEFB	$00		;;(+00,+00,+00)
   9105 
   9106 mark_1918:
   9107 **				;	81 00 00 00 00
   9108 stk_one:
   9109 	DEFB	$31		;;Exponent $81, Bytes: 1
   9110 	DEFB	$00		;;(+00,+00,+00)
   9111 
   9112 
   9113 mark_191A:
   9114 **				;	80 00 00 00 00
   9115 stk_half:
   9116 	DEFB	$30		;;Exponent: $80, Bytes: 1
   9117 	DEFB	$00		;;(+00,+00,+00)
   9118 
   9119 
   9120 mark_191C:
   9121 **				;	81 49 0F DA A2
   9122 stk_half_pi:
   9123 	DEFB	$F1		;;Exponent: $81, Bytes: 4
   9124 	DEFB	$49,$0F,$DA,$A2 ;;
   9125 
   9126 mark_1921:
   9127 **				;	84 20 00 00 00
   9128 stk_ten:
   9129 	DEFB	$34		;;Exponent: $84, Bytes: 1
   9130 	DEFB	$20		;;(+00,+00,+00)
   9131 #else
   9132 ;	This table has been modified so that the constants are held in their
   9133 ;	uncompressed, ready-to-use, 5-byte form.
   9134 
   9135 	DEFB	$00	; the value zero.
   9136 	DEFB	$00	;
   9137 	DEFB	$00	;
   9138 	DEFB	$00	;
   9139 	DEFB	$00	;
   9140 
   9141 	DEFB	$81	; the floating point value 1.
   9142 	DEFB	$00	;
   9143 	DEFB	$00	;
   9144 	DEFB	$00	;
   9145 	DEFB	$00	;
   9146 
   9147 	DEFB	$80	; the floating point value 1/2.
   9148 	DEFB	$00	;
   9149 	DEFB	$00	;
   9150 	DEFB	$00	;
   9151 	DEFB	$00	;
   9152 
   9153 	DEFB	$81	; the floating point value pi/2.
   9154 	DEFB	$49	;
   9155 	DEFB	$0F	;
   9156 	DEFB	$DA	;
   9157 	DEFB	$A2	;
   9158 
   9159 	DEFB	$84	; the floating point value ten.
   9160 	DEFB	$20	;
   9161 	DEFB	$00	;
   9162 	DEFB	$00	;
   9163 	DEFB	$00	;
   9164 #endif
   9165 
   9166 ------------------------------------------------------------------------
   9167 
   9168 ; THE *'TABLE OF ADDRESSES'*
   9169 ------------------------------------------------------------------------
   9170 
   9171 ;
   9172 ; starts with binary operations which have two operands and one result.
   9173 ; three pseudo binary operations first.
   9174 
   9175 #if ORIGINAL
   9176 mark_1923:
   9177 #else
   9178 #endif
   9179 
   9180 *tbl_addrs:*
   9181 
   9182 	DEFW	jump_true <#jump_true>		; $00 Address: $1C2F - jump_true
   9183 	DEFW	exchange <#exchange>		; $01 Address: $1A72 - exchange
   9184 	DEFW	delete <#delete>			; $02 Address: $19E3 - delete
   9185 
   9186 ; true binary operations.
   9187 
   9188 	DEFW	SUBTRACT <#SUBTRACT>		; $03 Address: $174C - subtract
   9189 	DEFW	MULTIPLY <#MULTIPLY>		; $04 Address: $176C - multiply
   9190 	DEFW	DIVISION <#DIVISION>		; $05 Address: $1882 - division
   9191 	DEFW	to_power <#to_power>		; $06 Address: $1DE2 - to_power
   9192 	DEFW	or <#or>			; $07 Address: $1AED - or
   9193 
   9194 	DEFW	boolean_num_and_num <#boolean_num_and_num>		; $08 Address: $1AF3 - boolean_num_and_num
   9195 	DEFW	num_l_eql <#num_l_eql>		; $09 Address: $1B03 - num_l_eql
   9196 	DEFW	num_gr_eql <#num_gr_eql>		; $0A Address: $1B03 - num_gr_eql
   9197 	DEFW	nums_neql <#nums_neql>		; $0B Address: $1B03 - nums_neql
   9198 	DEFW	num_grtr <#num_grtr>		; $0C Address: $1B03 - num_grtr
   9199 	DEFW	num_less <#num_less>		; $0D Address: $1B03 - num_less
   9200 	DEFW	nums_eql <#nums_eql>		; $0E Address: $1B03 - nums_eql
   9201 	DEFW	ADDITION <#ADDITION>		; $0F Address: $1755 - addition
   9202 
   9203 	DEFW	strs_and_num <#strs_and_num>		; $10 Address: $1AF8 - str_and_num
   9204 	DEFW	str_l_eql <#str_l_eql>		; $11 Address: $1B03 - str_l_eql
   9205 	DEFW	str_gr_eql <#str_gr_eql>		; $12 Address: $1B03 - str_gr_eql
   9206 	DEFW	strs_neql <#strs_neql>		; $13 Address: $1B03 - strs_neql
   9207 	DEFW	str_grtr <#str_grtr>		; $14 Address: $1B03 - str_grtr
   9208 	DEFW	str_less <#str_less>		; $15 Address: $1B03 - str_less
   9209 	DEFW	strs_eql <#strs_eql>		; $16 Address: $1B03 - strs_eql
   9210 	DEFW	strs_add <#strs_add>		; $17 Address: $1B62 - strs_add
   9211 
   9212 ; unary follow
   9213 
   9214 	DEFW	neg <#neg>		; $18
   9215 	DEFW	code <#code>		; $19
   9216 	DEFW	val <#val>		; $1A 
   9217 	DEFW	len <#len>		; $1B 
   9218 	DEFW	sin <#sin>		; $1C
   9219 	DEFW	cos <#cos>		; $1D
   9220 	DEFW	tan <#tan>		; $1E
   9221 	DEFW	asn <#asn>		; $1F
   9222 	DEFW	acs <#acs>		; $20
   9223 	DEFW	atn <#atn>		; $21
   9224 	DEFW	ln <#ln>		; $22
   9225 	DEFW	exp <#exp>		; $23
   9226 	DEFW	int <#int>		; $24
   9227 	DEFW	sqr <#sqr>		; $25
   9228 	DEFW	sgn <#sgn>		; $26
   9229 	DEFW	abs <#abs>		; $27
   9230 	DEFW	PEEK <#PEEK>		; $28 Address: $1A1B - peek		!!!!
   9231 	DEFW	usr_num <#usr_num>		; $29
   9232 	DEFW	str_dollar <#str_dollar>	; $2A
   9233 	DEFW	chr_dollar <#chr_dollar>	; $2B
   9234 	DEFW	not <#not>		; $2C
   9235 
   9236 ; end of true unary
   9237 
   9238 	DEFW	duplicate <#duplicate>	; $2D
   9239 	DEFW	n_mod_m <#n_mod_m>		; $2E
   9240 
   9241 	DEFW	jump <#jump>		; $2F
   9242 	DEFW	stk_data <#stk_data>	; $30
   9243 
   9244 	DEFW	dec_jr_nz <#dec_jr_nz>	; $31
   9245 	DEFW	less_0 <#less_0>		; $32
   9246 	DEFW	greater_0 <#greater_0>	; $33
   9247 	DEFW	end_calc <#end_calc>	; $34
   9248 	DEFW	get_argt <#get_argt>	; $35
   9249 	DEFW	TRUNCATE <#TRUNCATE>	; $36
   9250 	DEFW	FP_CALC_2 <#FP_CALC_2>	; $37
   9251 	DEFW	e_to_fp <#e_to_fp>		; $38
   9252 
   9253 ; the following are just the next available slots for the 128 compound literals
   9254 ; which are in range $80 - $FF.
   9255 
   9256 	DEFW	series_xx <#series_xx>		; $39 : $80 - $9F.
   9257 	DEFW	stk_const_xx <#stk_const_xx>		; $3A : $A0 - $BF.
   9258 	DEFW	st_mem_xx <#st_mem_xx>		; $3B : $C0 - $DF.
   9259 	DEFW	get_mem_xx <#get_mem_xx>		; $3C : $E0 - $FF.
   9260 
   9261 ; Aside: 3D - 7F are therefore unused calculator literals.
   9262 ;	39 - 7B would be available for expansion.
   9263 
   9264 ------------------------------------------------------------------------
   9265 
   9266 ; THE *'FLOATING POINT CALCULATOR'*
   9267 ------------------------------------------------------------------------
   9268 
   9269 ;
   9270 ;
   9271 
   9272 mark_199D:
   9273 *CALCULATE:*
   9274 	CALL	STACK_POINTERS <#STACK_POINTERS>	; is called to set up the
   9275 				; calculator stack pointers for a default
   9276 				; unary operation. HL = last value on stack.
   9277 				; DE = STKEND first location after stack.
   9278 
   9279 ; the calculate routine is called at this point by the series generator...
   9280 
   9281 mark_19A0:
   9282 *GEN_ENT_1:*
   9283 	LD	A,B		; fetch the Z80 B register to A
   9284 	LD	(BERG),A	; and store value in system variable BERG.
   9285 				; this will be the counter for dec_jr_nz
   9286 				; or if used from FP_CALC2 the calculator
   9287 				; instruction.
   9288 
   9289 ; ... and again later at this point
   9290 
   9291 mark_19A4:
   9292 *GEN_ENT_2:*
   9293 	EXX			; switch sets
   9294 	EX	(SP),HL		; and store the address of next instruction,
   9295 				; the return address, in H'L'.
   9296 				; If this is a recursive call then the H'L'
   9297 				; of the previous invocation goes on stack.
   9298 				; c.f. end_calc.
   9299 	EXX			; switch back to main set.
   9300 
   9301 ; this is the re-entry looping point when handling a string of literals.
   9302 
   9303 mark_19A7:
   9304 *RE_ENTRY:*
   9305 	LD	(STKEND),DE	; save end of stack
   9306 	EXX			; switch to alt
   9307 	LD	A,(HL)		; get next literal
   9308 	INC	HL		; increase pointer'
   9309 
   9310 ; single operation jumps back to here
   9311 
   9312 mark_19AE:
   9313 *SCAN_ENT:*
   9314 	PUSH	HL		; save pointer on stack	*
   9315 	AND	A		; now test the literal
   9316 	JP	P,FIRST_3D <#FIRST_3D>	; forward if in range $00 - $3D
   9317 				; anything with bit 7 set will be one of
   9318 				; 128 compound literals.
   9319 
   9320 ; compound literals have the following format.
   9321 ; bit 7 set indicates compound.
   9322 ; bits 6-5 the subgroup 0-3.
   9323 ; bits 4-0 the embedded parameter $00 - $1F.
   9324 ; The subgroup 0-3 needs to be manipulated to form the next available four
   9325 ; address places after the simple literals in the address table.
   9326 
   9327 	LD	D,A		; save literal in D
   9328 	AND	$60		; and with 01100000 to isolate subgroup
   9329 	RRCA			; rotate bits
   9330 	RRCA			; 4 places to right
   9331 	RRCA			; not five as we need offset * 2
   9332 	RRCA			; 00000xx0
   9333 	ADD	A,$72		; add ($39 * 2) to give correct offset.
   9334 				; alter above if you add more literals.
   9335 	LD	L,A		; store in L for later indexing.
   9336 	LD	A,D		; bring back compound literal
   9337 	AND	$1F		; use mask to isolate parameter bits
   9338 	JR	ENT_TABLE <#ENT_TABLE>	; forward
   9339 
   9340 ; ___
   9341 
   9342 ; the branch was here with simple literals.
   9343 
   9344 mark_19C2:
   9345 *FIRST_3D:*
   9346 	CP	$18		; compare with first unary operations.
   9347 	JR	NC,DOUBLE_A <#DOUBLE_A>	; with unary operations
   9348 
   9349 ; it is binary so adjust pointers.
   9350 
   9351 	EXX			;
   9352 	LD	BC,-5
   9353 	LD	D,H		; transfer HL, the last value, to DE.
   9354 	LD	E,L		;
   9355 	ADD	HL,BC		; subtract 5 making HL point to second
   9356 				; value.
   9357 	EXX			;
   9358 
   9359 mark_19CE:
   9360 *DOUBLE_A:*
   9361 	RLCA			; double the literal
   9362 	LD	L,A		; and store in L for indexing
   9363 
   9364 mark_19D0:
   9365 *ENT_TABLE:*
   9366 	LD	DE,tbl_addrs <#tbl_addrs>	; Address: tbl_addrs
   9367 	LD	H,$00		; prepare to index
   9368 	ADD	HL,DE		; add to get address of routine
   9369 	LD	E,(HL)		; low byte to E
   9370 	INC	HL		;
   9371 	LD	D,(HL)		; high byte to D
   9372 
   9373 	LD	HL,RE_ENTRY <#RE_ENTRY>
   9374 	EX	(SP),HL	; goes on machine stack
   9375 				; address of next literal goes to HL. *
   9376 
   9377 
   9378 	PUSH	DE		; now the address of routine is stacked.
   9379 	EXX			; back to main set
   9380 				; avoid using IY register.
   9381 	LD	BC,(STKEND+1)	; STKEND_hi
   9382 				; nothing much goes to C but BERG to B
   9383 				; and continue into next ret instruction
   9384 				; which has a dual identity
   9385 
   9386 
   9387 ------------------------------------------------------------------------
   9388 
   9389 ; THE *'DELETE'* SUBROUTINE
   9390 ------------------------------------------------------------------------
   9391 
   9392 ; offset $02: 'delete'
   9393 ; A simple return but when used as a calculator literal this
   9394 ; deletes the last value from the calculator stack.
   9395 ; On entry, as always with binary operations,
   9396 ; HL=first number, DE=second number
   9397 ; On exit, HL=result, DE=stkend.
   9398 ; So nothing to do
   9399 
   9400 mark_19E3:
   9401 *delete:*
   9402 	RET			; return - indirect jump if from above.
   9403 
   9404 ------------------------------------------------------------------------
   9405 
   9406 ; THE *'SINGLE OPERATION'* SUBROUTINE
   9407 ------------------------------------------------------------------------
   9408 
   9409 ; offset $37: 'FP_CALC_2'
   9410 ; this single operation is used, in the first instance, to evaluate most
   9411 ; of the mathematical and string functions found in BASIC expressions.
   9412 
   9413 mark_19E4:
   9414 *FP_CALC_2:*
   9415 	POP	AF		; drop return address.
   9416 	LD	A,(BERG)	; load accumulator from system variable BERG
   9417 				; value will be literal eg. 'tan'
   9418 	EXX			; switch to alt
   9419 	JR	SCAN_ENT <#SCAN_ENT>	; back
   9420 				; next literal will be end_calc in scanning
   9421 
   9422 ------------------------------------------------------------------------
   9423 
   9424 ; THE *'TEST 5 SPACES'* SUBROUTINE
   9425 ------------------------------------------------------------------------
   9426 
   9427 ; This routine is called from MOVE_FP, STK_CONST and STK_STORE to
   9428 ; test that there is enough space between the calculator stack and the
   9429 ; machine stack for another five_byte value. It returns with BC holding
   9430 ; the value 5 ready for any subsequent LDIR.
   9431 
   9432 mark_19EB:
   9433 *TEST_5_SP:*
   9434 	PUSH	DE		; save
   9435 	PUSH	HL		; registers
   9436 	LD	BC,5		; an overhead of five bytes
   9437 	CALL	TEST_ROOM <#TEST_ROOM>	; tests free RAM raising
   9438 				; an error if not.
   9439 	POP	HL		; else restore
   9440 	POP	DE		; registers.
   9441 	RET			; return with BC set at 5.
   9442 
   9443 
   9444 ------------------------------------------------------------------------
   9445 
   9446 ; THE *'MOVE A FLOATING POINT NUMBER'* SUBROUTINE
   9447 ------------------------------------------------------------------------
   9448 
   9449 ; offset $2D: 'duplicate'
   9450 ; This simple routine is a 5-byte LDIR instruction
   9451 ; that incorporates a memory check.
   9452 ; When used as a calculator literal it duplicates the last value on the
   9453 ; calculator stack.
   9454 ; Unary so on entry HL points to last value, DE to stkend
   9455 
   9456 mark_19F6:
   9457 *duplicate:*
   9458 *MOVE_FP:*
   9459 	CALL	TEST_5_SP <#TEST_5_SP>	; test free memory
   9460 				; and sets BC to 5.
   9461 	LDIR			; copy the five bytes.
   9462 	RET			; return with DE addressing new STKEND
   9463 				; and HL addressing new last value.
   9464 
   9465 ------------------------------------------------------------------------
   9466 
   9467 ; THE *'STACK LITERALS'* SUBROUTINE
   9468 ------------------------------------------------------------------------
   9469 
   9470 ; offset $30: 'stk_data'
   9471 ; When a calculator subroutine needs to put a value on the calculator
   9472 ; stack that is not a regular constant this routine is called with a
   9473 ; variable number of following data bytes that convey to the routine
   9474 ; the floating point form as succinctly as is possible.
   9475 
   9476 mark_19FC:
   9477 *stk_data:*
   9478 	LD	H,D		; transfer STKEND
   9479 	LD	L,E		; to HL for result.
   9480 
   9481 mark_19FE:
   9482 *STK_CONST:*
   9483 	CALL	TEST_5_SP <#TEST_5_SP>	; tests that room exists
   9484 				; and sets BC to $05.
   9485 
   9486 	EXX			; switch to alternate set
   9487 	PUSH	HL		; save the pointer to next literal on stack
   9488 	EXX			; switch back to main set
   9489 
   9490 	EX	(SP),HL	; pointer to HL, destination to stack.
   9491 
   9492 #if ORIGINAL
   9493 	PUSH	BC		; save BC - value 5 from test room ??.
   9494 #else
   9495 ;;	PUSH	BC		; save BC - value 5 from test room. No need.
   9496 #endif
   9497 	LD	A,(HL)		; fetch the byte following 'stk_data'
   9498 	AND	$C0		; isolate bits 7 and 6
   9499 	RLCA			; rotate
   9500 	RLCA			; to bits 1 and 0	range $00 - $03.
   9501 	LD	C,A		; transfer to C
   9502 	INC	C		; and increment to give number of bytes
   9503 				; to read. $01 - $04
   9504 	LD	A,(HL)		; reload the first byte
   9505 	AND	$3F		; mask off to give possible exponent.
   9506 	JR	NZ,FORM_EXP <#FORM_EXP>	; forward to FORM_EXP if it was possible to
   9507 				; include the exponent.
   9508 
   9509 ; else byte is just a byte count and exponent comes next.
   9510 
   9511 	INC	HL		; address next byte and
   9512 	LD	A,(HL)		; pick up the exponent ( - $50).
   9513 
   9514 mark_1A14:
   9515 *FORM_EXP:*
   9516 	ADD	A,$50		; now add $50 to form actual exponent
   9517 	LD	(DE),A		; and load into first destination byte.
   9518 	LD	A,$05		; load accumulator with $05 and
   9519 	SUB	C		; subtract C to give count of trailing
   9520 				; zeros plus one.
   9521 	INC	HL		; increment source
   9522 	INC	DE		; increment destination
   9523 
   9524 
   9525 #if ORIGINAL
   9526 	LD	B,$00		; prepare to copy. Note. B is zero.
   9527 	LDIR			; copy C bytes
   9528 	POP	BC		; restore 5 counter to BC.
   9529 #else
   9530 	LDIR			; copy C bytes
   9531 #endif
   9532 
   9533 	EX	(SP),HL		; put HL on stack as next literal pointer
   9534 				; and the stack value - result pointer -
   9535 				; to HL.
   9536 
   9537 	EXX			; switch to alternate set.
   9538 	POP	HL		; restore next literal pointer from stack
   9539 				; to H'L'.
   9540 	EXX			; switch back to main set.
   9541 
   9542 	LD	B,A		; zero count to B
   9543 	XOR	A		; clear accumulator
   9544 
   9545 mark_1A27:
   9546 *STK_ZEROS:*
   9547 	DEC	B		; decrement B counter
   9548 	RET	Z		; return if zero.		>>
   9549 				; DE points to new STKEND
   9550 				; HL to new number.
   9551 
   9552 	LD	(DE),A		; else load zero to destination
   9553 	INC	DE		; increase destination
   9554 	JR	STK_ZEROS <#STK_ZEROS>	; loop back until done.
   9555 
   9556 ------------------------------------------------------------------------
   9557 
   9558 ; THE *'SKIP CONSTANTS'* SUBROUTINE
   9559 ------------------------------------------------------------------------
   9560 
   9561 ; This routine traverses variable-length entries in the table of constants,
   9562 ; stacking intermediate, unwanted constants onto a dummy calculator stack,
   9563 ; in the first five bytes of the ZX81 ROM.
   9564 
   9565 #if ORIGINAL
   9566 mark_1A2D:
   9567 *SKIP_CONS:*
   9568 	AND	A		; test if initially zero.
   9569 
   9570 mark_1A2E:
   9571 *SKIP_NEXT:*
   9572 	RET	Z		; return if zero.		>>
   9573 
   9574 	PUSH	AF		; save count.
   9575 	PUSH	DE		; and normal STKEND
   9576 
   9577 	LD	DE,$0000	; dummy value for STKEND at start of ROM
   9578 				; Note. not a fault but this has to be
   9579 				; moved elsewhere when running in RAM.
   9580 				;
   9581 	CALL	STK_CONST <#STK_CONST>		; works through variable
   9582 				; length records.
   9583 
   9584 	POP	DE		; restore real STKEND
   9585 	POP	AF		; restore count
   9586 	DEC	A		; decrease
   9587 	JR	SKIP_NEXT <#SKIP_NEXT>	; loop back
   9588 #else
   9589 ; Since the table now uses uncompressed values, some extra ROM space is 
   9590 ; required for the table but much more is released by getting rid of routines
   9591 ; like this.
   9592 #endif
   9593 
   9594 ------------------------------------------------------------------------
   9595 
   9596 ; THE *'MEMORY LOCATION'* SUBROUTINE
   9597 ------------------------------------------------------------------------
   9598 
   9599 ; This routine, when supplied with a base address in HL and an index in A,
   9600 ; will calculate the address of the A'th entry, where each entry occupies
   9601 ; five bytes. It is used for addressing floating-point numbers in the
   9602 ; calculator's memory area.
   9603 
   9604 mark_1A3C:
   9605 *LOC_MEM:*
   9606 	LD	C,A		; store the original number $00-$1F.
   9607 	RLCA			; double.
   9608 	RLCA			; quadruple.
   9609 	ADD	A,C		; now add original value to multiply by five.
   9610 
   9611 	LD	C,A		; place the result in C.
   9612 	LD	B,$00		; set B to 0.
   9613 	ADD	HL,BC		; add to form address of start of number in HL.
   9614 
   9615 	RET			; return.
   9616 
   9617 ------------------------------------------------------------------------
   9618 
   9619 ; THE *'GET FROM MEMORY AREA'* SUBROUTINE
   9620 ------------------------------------------------------------------------
   9621 
   9622 ; offsets $E0 to $FF: 'get_mem_0', 'get_mem_1' etc.
   9623 ; A holds $00-$1F offset.
   9624 ; The calculator stack increases by 5 bytes.
   9625 
   9626 mark_1A45:
   9627 *get_mem_xx:*
   9628 
   9629 #if ORIGINAL
   9630 	PUSH	DE		; save STKEND
   9631 	LD	HL,(MEM)	; MEM is base address of the memory cells.
   9632 #else
   9633 				; Note. first two instructions have been swapped to create a subroutine.
   9634 	LD	HL,(MEM)	; MEM is base address of the memory cells.
   9635 *INDEX_5*				; new label
   9636 	PUSH	DE		; save STKEND
   9637 #endif
   9638 	CALL	LOC_MEM <#LOC_MEM>		; so that HL = first byte
   9639 	CALL	MOVE_FP <#MOVE_FP>		; moves 5 bytes with memory
   9640 				; check.
   9641 				; DE now points to new STKEND.
   9642 	POP	HL		; the original STKEND is now RESULT pointer.
   9643 	RET			; return.
   9644 
   9645 ------------------------------------------------------------------------
   9646 
   9647 ; THE *'STACK A CONSTANT'* SUBROUTINE
   9648 ------------------------------------------------------------------------
   9649 
   9650 
   9651 *stk_const_xx:*
   9652 #if ORIGINAL
   9653 
   9654 ; offset $A0: 'stk_zero'
   9655 ; offset $A1: 'stk_one'
   9656 ; offset $A2: 'stk_half'
   9657 ; offset $A3: 'stk_half_pi'
   9658 ; offset $A4: 'stk_ten'
   9659 ;
   9660 ; This routine allows a one-byte instruction to stack up to 32 constants
   9661 ; held in short form in a table of constants. In fact only 5 constants are
   9662 ; required. On entry the A register holds the literal ANDed with $1F.
   9663 ; It isn't very efficient and it would have been better to hold the
   9664 ; numbers in full, five byte form and stack them in a similar manner
   9665 ; to that which would be used later for semi-tone table values.
   9666 
   9667 mark_1A51:
   9668 
   9669 	LD	H,D		; save STKEND - required for result
   9670 	LD	L,E		;
   9671 	EXX			; swap
   9672 	PUSH	HL		; save pointer to next literal
   9673 	LD	HL,stk_zero <#stk_zero>	; Address: stk_zero - start of table of
   9674 				; constants
   9675 	EXX			;
   9676 	CALL	SKIP_CONS <#SKIP_CONS>
   9677 	CALL	STK_CONST <#STK_CONST>
   9678 	EXX			;
   9679 	POP	HL		; restore pointer to next literal.
   9680 	EXX			;
   9681 	RET			; return.
   9682 #else
   9683 *stk_con_x*
   9684 	LD	HL,TAB_CNST	; Address: Table of constants.
   9685 
   9686 	JR	INDEX_5 <#INDEX_5>		; and join subroutine above.
   9687 #endif
   9688 
   9689 
   9690 
   9691 ------------------------------------------------------------------------
   9692 
   9693 ; THE *'STORE IN A MEMORY AREA'* SUBROUTINE
   9694 ------------------------------------------------------------------------
   9695 
   9696 ; Offsets $C0 to $DF: 'st_mem_0', 'st_mem_1' etc.
   9697 ; Although 32 memory storage locations can be addressed, only six
   9698 ; $C0 to $C5 are required by the ROM and only the thirty bytes (6*5)
   9699 ; required for these are allocated. ZX81 programmers who wish to
   9700 ; use the floating point routines from assembly language may wish to
   9701 ; alter the system variable MEM to point to 160 bytes of RAM to have
   9702 ; use the full range available.
   9703 ; A holds derived offset $00-$1F.
   9704 ; Unary so on entry HL points to last value, DE to STKEND.
   9705 
   9706 mark_1A63:
   9707 *st_mem_xx:*
   9708 	PUSH	HL		; save the result pointer.
   9709 	EX	DE,HL		; transfer to DE.
   9710 	LD	HL,(MEM)	; fetch MEM the base of memory area.
   9711 	CALL	LOC_MEM <#LOC_MEM>		; sets HL to the destination.
   9712 	EX	DE,HL		; swap - HL is start, DE is destination.
   9713 
   9714 #if ORIGINAL
   9715 	CALL	MOVE_FP <#MOVE_FP>
   9716 				; note. a short ld bc,5; ldir
   9717 				; the embedded memory check is not required
   9718 				; so these instructions would be faster!
   9719 #else
   9720 	LD	C,5		;+ one extra byte but 
   9721 	LDIR			;+ faster and no memory check.
   9722 #endif
   9723 
   9724 
   9725 	EX	DE,HL		; DE = STKEND
   9726 	POP	HL		; restore original result pointer
   9727 	RET			; return.
   9728 
   9729 ------------------------------------------------------------------------
   9730 
   9731 ; THE *'EXCHANGE'* SUBROUTINE
   9732 ------------------------------------------------------------------------
   9733 
   9734 ; offset $01: 'exchange'
   9735 ; This routine exchanges the last two values on the calculator stack
   9736 ; On entry, as always with binary operations,
   9737 ; HL=first number, DE=second number
   9738 ; On exit, HL=result, DE=stkend.
   9739 
   9740 mark_1A72:
   9741 *exchange:*
   9742 	LD	B,$05		; there are five bytes to be swapped
   9743 
   9744 ; start of loop.
   9745 
   9746 mark_1A74:
   9747 *SWAP_BYTE:*
   9748 	LD	A,(DE)		; each byte of second
   9749 #if ORIGINAL
   9750 	LD	C,(HL)		; each byte of first
   9751 	EX	DE,HL		; swap pointers
   9752 #else
   9753 	LD	C,A		;+
   9754 	LD	A,(HL)
   9755 #endif
   9756 	LD	(DE),A		; store each byte of first
   9757 	LD	(HL),C		; store each byte of second
   9758 	INC	HL		; advance both
   9759 	INC	DE		; pointers.
   9760 	DJNZ	SWAP_BYTE <#SWAP_BYTE>	; loop back until all 5 done.
   9761 
   9762 #if ORIGINAL
   9763 	EX	DE,HL		; even up the exchanges so that DE addresses STKEND.
   9764 #else
   9765 ;	omit
   9766 #endif
   9767 	RET			; return.
   9768 
   9769 ------------------------------------------------------------------------
   9770 
   9771 ; THE *'SERIES GENERATOR'* SUBROUTINE
   9772 ------------------------------------------------------------------------
   9773 
   9774 
   9775 ; The ZX81 uses Chebyshev polynomials to generate approximations for
   9776 ; SIN, ATN, LN and EXP. These are named after the Russian mathematician
   9777 ; Pafnuty Chebyshev, born in 1821, who did much pioneering work on numerical
   9778 ; series. As far as calculators are concerned, Chebyshev polynomials have an
   9779 ; advantage over other series, for example the Taylor series, as they can
   9780 ; reach an approximation in just six iterations for SIN, eight for EXP and
   9781 ; twelve for LN and ATN. The mechanics of the routine are interesting but
   9782 ; for full treatment of how these are generated with demonstrations in
   9783 ; Sinclair BASIC see "The Complete Spectrum ROM Disassembly" by Dr Ian Logan
   9784 ; and Dr Frank O'Hara, published 1983 by Melbourne House.
   9785 
   9786 mark_1A7F:
   9787 *series_xx:*
   9788 	LD	B,A		; parameter $00 - $1F to B counter
   9789 	CALL	GEN_ENT_1 <#GEN_ENT_1>
   9790 				; A recursive call to a special entry point
   9791 				; in the calculator that puts the B register
   9792 				; in the system variable BERG. The return
   9793 				; address is the next location and where
   9794 				; the calculator will expect its first
   9795 				; instruction - now pointed to by HL'.
   9796 				; The previous pointer to the series of
   9797 				; five-byte numbers goes on the machine stack.
   9798 
   9799 ; The initialization phase.
   9800 
   9801 	DEFB	__duplicate	;;	x,x
   9802 	DEFB	__addition	;;	x+x
   9803 	DEFB	__st_mem_0	;;	x+x
   9804 	DEFB	__delete	;;	.
   9805 	DEFB	__stk_zero	;;	0
   9806 	DEFB	__st_mem_2	;;	0
   9807 
   9808 ; a loop is now entered to perform the algebraic calculation for each of
   9809 ; the numbers in the series
   9810 
   9811 mark_1A89:
   9812 *G_LOOP:*
   9813 	DEFB	__duplicate	;;	v,v.
   9814 	DEFB	__get_mem_0	;;	v,v,x+2
   9815 	DEFB	__multiply	;;	v,v*x+2
   9816 	DEFB	__get_mem_2	;;	v,v*x+2,v
   9817 	DEFB	__st_mem_1	;;
   9818 	DEFB	__subtract	;;
   9819 	DEFB	__end_calc	;;
   9820 
   9821 ; the previous pointer is fetched from the machine stack to H'L' where it
   9822 ; addresses one of the numbers of the series following the series literal.
   9823 
   9824 	CALL	stk_data <#stk_data>		; is called directly to
   9825 				; push a value and advance H'L'.
   9826 	CALL	GEN_ENT_2 <#GEN_ENT_2>		; recursively re-enters
   9827 				; the calculator without disturbing
   9828 				; system variable BERG
   9829 				; H'L' value goes on the machine stack and is
   9830 				; then loaded as usual with the next address.
   9831 
   9832 	DEFB	__addition	;;
   9833 	DEFB	__exchange	;;
   9834 	DEFB	__st_mem_2	;;
   9835 	DEFB	__delete	;;
   9836 
   9837 	DEFB	__dec_jr_nz	;;
   9838 	DEFB	$EE		;;back to G_LOOP <#G_LOOP>, G_LOOP
   9839 
   9840 ; when the counted loop is complete the final subtraction yields the result
   9841 ; for example SIN X.
   9842 
   9843 	DEFB	__get_mem_1	;;
   9844 	DEFB	__subtract	;;
   9845 	DEFB	__end_calc	;;
   9846 
   9847 	RET			; return with H'L' pointing to location
   9848 				; after last number in series.
   9849 
   9850 ------------------------------------------------------------------------
   9851 
   9852 ; Handle unary minus (18)
   9853 ------------------------------------------------------------------------
   9854 
   9855 ; Unary so on entry HL points to last value, DE to STKEND.
   9856 
   9857 mark_1AA0:
   9858 *mark_1AA0:*
   9859 *neg:*
   9860 	LD A,	(HL)		; fetch exponent of last value on the
   9861 				; calculator stack.
   9862 	AND	A		; test it.
   9863 	RET	Z		; return if zero.
   9864 
   9865 	INC	HL		; address the byte with the sign bit.
   9866 	LD	A,(HL)		; fetch to accumulator.
   9867 	XOR	$80		; toggle the sign bit.
   9868 	LD	(HL),A		; put it back.
   9869 	DEC	HL		; point to last value again.
   9870 	RET			; return.
   9871 
   9872 ------------------------------------------------------------------------
   9873 
   9874 ; Absolute magnitude (27)
   9875 ------------------------------------------------------------------------
   9876 
   9877 ; This calculator literal finds the absolute value of the last value,
   9878 ; floating point, on calculator stack.
   9879 
   9880 mark_1AAA:
   9881 *abs:*
   9882 	INC	HL		; point to byte with sign bit.
   9883 	RES	7,(HL)		; make the sign positive.
   9884 	DEC	HL		; point to last value again.
   9885 	RET			; return.
   9886 
   9887 ------------------------------------------------------------------------
   9888 
   9889 ; Signum (26)
   9890 ------------------------------------------------------------------------
   9891 
   9892 ; This routine replaces the last value on the calculator stack,
   9893 ; which is in floating point form, with one if positive and with -minus one
   9894 ; if negative. If it is zero then it is left as such.
   9895 
   9896 mark_1AAF:
   9897 *sgn:*
   9898 	INC	HL		; point to first byte of 4-byte mantissa.
   9899 	LD	A,(HL)		; pick up the byte with the sign bit.
   9900 	DEC	HL		; point to exponent.
   9901 	DEC	(HL)		; test the exponent for
   9902 	INC	(HL)		; the value zero.
   9903 
   9904 	SCF			; set the carry flag.
   9905 	CALL	NZ,FP_0_OR_1 <#FP_0_OR_1>	; replaces last value with one
   9906 				; if exponent indicates the value is non-zero.
   9907 				; in either case mantissa is now four zeros.
   9908 
   9909 	INC HL			; point to first byte of 4-byte mantissa.
   9910 	RLCA			; rotate original sign bit to carry.
   9911 	RR	(HL)		; rotate the carry into sign.
   9912 	DEC HL			; point to last value.
   9913 	RET			; return.
   9914 
   9915 
   9916 ------------------------------------------------------------------------
   9917 
   9918 ; Handle PEEK function (28)
   9919 ------------------------------------------------------------------------
   9920 
   9921 ; This function returns the contents of a memory address.
   9922 ; The entire address space can be peeked including the ROM.
   9923 
   9924 mark_1ABE:
   9925 *PEEK:*
   9926 	CALL	FIND_INT <#FIND_INT>	; puts address in BC.
   9927 	LD	A,(BC)		; load contents into A register.
   9928 
   9929 mark_1AC2:
   9930 *IN_PK_STK:*
   9931 	JP	STACK_A <#STACK_A>		; exit via STACK_A to put value on the
   9932 				; calculator stack.
   9933 
   9934 ------------------------------------------------------------------------
   9935 
   9936 ; USR number (29)
   9937 ------------------------------------------------------------------------
   9938 
   9939 ; The USR function followed by a number 0-65535 is the method by which
   9940 ; the ZX81 invokes machine code programs. This function returns the
   9941 ; contents of the BC register pair.
   9942 ; Note. that STACK_BC re-initializes the IY register to ERR_NR if a user-written
   9943 ; program has altered it.
   9944 
   9945 mark_1AC5:
   9946 *usr_num:*
   9947 	CALL	FIND_INT <#FIND_INT>	; to fetch the
   9948 				; supplied address into BC.
   9949 
   9950 	LD	HL,STACK_BC <#STACK_BC>	; address: STACK_BC is
   9951 	PUSH	HL		; pushed onto the machine stack.
   9952 	PUSH	BC		; then the address of the machine code
   9953 				; routine.
   9954 
   9955 	RET			; make an indirect jump to the routine
   9956 				; and, hopefully, to STACK_BC also.
   9957 
   9958 
   9959 ------------------------------------------------------------------------
   9960 
   9961 ; Greater than zero ($33)
   9962 ------------------------------------------------------------------------
   9963 
   9964 ; Test if the last value on the calculator stack is greater than zero.
   9965 ; This routine is also called directly from the end-tests of the comparison
   9966 ; routine.
   9967 
   9968 mark_1ACE:
   9969 *greater_0:*
   9970 	LD	A,(HL)		; fetch exponent.
   9971 	AND	A		; test it for zero.
   9972 	RET	Z		; return if so.
   9973 
   9974 
   9975 	LD	A,$FF		; prepare XOR mask for sign bit
   9976 	JR	SIGN_TO_C <#SIGN_TO_C>	; forward to SIGN_TO_C
   9977 				; to put sign in carry
   9978 				; (carry will become set if sign is positive)
   9979 				; and then overwrite location with 1 or 0
   9980 				; as appropriate.
   9981 
   9982 ------------------------------------------------------------------------
   9983 
   9984 ; Handle NOT operator ($2C)
   9985 ------------------------------------------------------------------------
   9986 
   9987 ; This overwrites the last value with 1 if it was zero else with zero
   9988 ; if it was any other value.
   9989 ;
   9990 ; e.g. NOT 0 returns 1, NOT 1 returns 0, NOT -3 returns 0.
   9991 ;
   9992 ; The subroutine is also called directly from the end-tests of the comparison
   9993 ; operator.
   9994 
   9995 mark_1AD5:
   9996 *not:*
   9997 	LD	A,(HL)		; get exponent byte.
   9998 	NEG			; negate - sets carry if non-zero.
   9999 	CCF			; complement so carry set if zero, else reset.
  10000 	JR	FP_0_OR_1 <#FP_0_OR_1>	; forward to FP_0_OR_1.
  10001 
  10002 ------------------------------------------------------------------------
  10003 
  10004 ; Less than zero (32)
  10005 ------------------------------------------------------------------------
  10006 
  10007 ; Destructively test if last value on calculator stack is less than zero.
  10008 ; Bit 7 of second byte will be set if so.
  10009 
  10010 mark_1ADB:
  10011 *less_0:*
  10012 	XOR	A		; set xor mask to zero
  10013 				; (carry will become set if sign is negative).
  10014 
  10015 ; transfer sign of mantissa to Carry Flag.
  10016 
  10017 mark_1ADC:
  10018 *SIGN_TO_C:*
  10019 	INC	HL		; address 2nd byte.
  10020 	XOR	(HL)		; bit 7 of HL will be set if number is negative.
  10021 	DEC	HL		; address 1st byte again.
  10022 	RLCA			; rotate bit 7 of A to carry.
  10023 
  10024 ------------------------------------------------------------------------
  10025 
  10026 ; Zero or one
  10027 ------------------------------------------------------------------------
  10028 
  10029 ; This routine places an integer value zero or one at the addressed location
  10030 ; of calculator stack or MEM area. The value one is written if carry is set on
  10031 ; entry else zero.
  10032 
  10033 mark_1AE0:
  10034 *FP_0_OR_1:*
  10035 	PUSH	HL		; save pointer to the first byte
  10036 	LD	B,$05		; five bytes to do.
  10037 
  10038 mark_1AE3:
  10039 *FP_loop:*
  10040 	LD	(HL),$00	; insert a zero.
  10041 	INC	HL		;
  10042 	DJNZ	FP_loop <#FP_loop>		; repeat.
  10043 
  10044 	POP	HL		;
  10045 	RET	NC		;
  10046 
  10047 	LD	(HL),$81	; make value 1
  10048 	RET			; return.
  10049 
  10050 
  10051 ------------------------------------------------------------------------
  10052 
  10053 ; Handle OR operator (07)
  10054 ------------------------------------------------------------------------
  10055 
  10056 ; The Boolean OR operator. eg. X OR Y
  10057 ; The result is zero if both values are zero else a non-zero value.
  10058 ;
  10059 ; e.g.	0 OR 0	returns 0.
  10060 ;	-3 OR 0	returns -3.
  10061 ;	0 OR -3 returns 1.
  10062 ;	-3 OR 2	returns 1.
  10063 ;
  10064 ; A binary operation.
  10065 ; On entry HL points to first operand (X) and DE to second operand (Y).
  10066 
  10067 mark_1AED:
  10068 *or:*
  10069 	LD	A,(DE)		; fetch exponent of second number
  10070 	AND	A		; test it.
  10071 	RET	Z		; return if zero.
  10072 
  10073 	SCF			; set carry flag
  10074 	JR	FP_0_OR_1 <#FP_0_OR_1>	; back to FP_0_OR_1 to overwrite the first operand
  10075 				; with the value 1.
  10076 
  10077 
  10078 ------------------------------------------------------------------------
  10079 
  10080 ; Handle number AND number (08)
  10081 ------------------------------------------------------------------------
  10082 
  10083 ; The Boolean AND operator.
  10084 ;
  10085 ; e.g.	-3 AND 2	returns -3.
  10086 ;	-3 AND 0	returns 0.
  10087 ;		0 and -2 returns 0.
  10088 ;		0 and 0	returns 0.
  10089 ;
  10090 ; Compare with OR routine above.
  10091 
  10092 *boolean_num_and_num:*
  10093 	LD	A,(DE)		; fetch exponent of second number.
  10094 	AND	A		; test it.
  10095 	RET	NZ		; return if not zero.
  10096 
  10097 	JR	FP_0_OR_1 <#FP_0_OR_1>	; back to FP_0_OR_1 to overwrite the first operand
  10098 				; with zero for return value.
  10099 
  10100 ------------------------------------------------------------------------
  10101 
  10102 ; Handle string AND number (10)
  10103 ------------------------------------------------------------------------
  10104 
  10105 ; e.g. "YOU WIN" AND SCORE>99 will return the string if condition is true
  10106 ; or the null string if false.
  10107 
  10108 *strs_and_num:*
  10109 	LD	A,(DE)		; fetch exponent of second number.
  10110 	AND	A		; test it.
  10111 	RET	NZ		; return if number was not zero - the string
  10112 				; is the result.
  10113 
  10114 ; if the number was zero (false) then the null string must be returned by
  10115 ; altering the length of the string on the calculator stack to zero.
  10116 
  10117 	PUSH	DE		; save pointer to the now obsolete number
  10118 				; (which will become the new STKEND)
  10119 
  10120 	DEC	DE		; point to the 5th byte of string descriptor.
  10121 	XOR	A		; clear the accumulator.
  10122 	LD	(DE),A		; place zero in high byte of length.
  10123 	DEC	DE		; address low byte of length.
  10124 	LD	(DE),A		; place zero there - now the null string.
  10125 
  10126 	POP	DE		; restore pointer - new STKEND.
  10127 	RET			; return.
  10128 
  10129 ------------------------------------------------------------------------
  10130 
  10131 ; Perform comparison ($09-$0E, $11-$16)
  10132 ------------------------------------------------------------------------
  10133 
  10134 ; True binary operations.
  10135 ;
  10136 ; A single entry point is used to evaluate six numeric and six string
  10137 ; comparisons. On entry, the calculator literal is in the B register and
  10138 ; the two numeric values, or the two string parameters, are on the
  10139 ; calculator stack.
  10140 ; The individual bits of the literal are manipulated to group similar
  10141 ; operations although the SUB 8 instruction does nothing useful and merely
  10142 ; alters the string test bit.
  10143 ; Numbers are compared by subtracting one from the other, strings are
  10144 ; compared by comparing every character until a mismatch, or the end of one
  10145 ; or both, is reached.
  10146 ;
  10147 ; Numeric Comparisons.
  10148 ------------------------------------------------------------------------
  10149 
  10150 ; The *'x>y'* example is the easiest as it employs straight-thru logic.
  10151 ; Number y is subtracted from x and the result tested for greater_0 yielding
  10152 ; a final value 1 (true) or 0 (false).
  10153 ; For 'x<y' the same logic is used but the two values are first swapped on the
  10154 ; calculator stack.
  10155 ; For 'x=y' NOT is applied to the subtraction result yielding true if the
  10156 ; difference was zero and false with anything else.
  10157 ; The first three numeric comparisons are just the opposite of the last three
  10158 ; so the same processing steps are used and then a final NOT is applied.
  10159 ;
  10160 ; literal	Test	No sub 8        ExOrNot  1st RRCA	exch sub	?	End-Tests
  10161 ; =========	====	== ======== === ======== ========	==== ===	=	=== === ===
  10162 ; num_l_eql	x<=y	09 00000001 dec 00000000 00000000	---- x-y	?	--- >0? NOT
  10163 ; num_gr_eql	x>=y	0A 00000010 dec 00000001 10000000c	swap y-x	?	--- >0? NOT
  10164 ; nums_neql	x<>y	0B 00000011 dec 00000010 00000001	---- x-y	?	NOT --- NOT
  10165 ; num_grtr	x>y	0C 00000100 -	00000100 00000010	---- x-y	?	--- >0? ---
  10166 ; num_less	x<y	0D 00000101 -	00000101 10000010c	swap y-x	?	--- >0? ---
  10167 ; nums_eql	x=y	0E 00000110 -	00000110 00000011	---- x-y	?	NOT --- ---
  10168 ;
  10169 ;								comp -> C/F
  10170 ;								====	===
  10171 ; str_l_eql	x$<=y$	11 00001001 dec 00001000 00000100	---- x$y$ 0	!or >0? NOT
  10172 ; str_gr_eql	x$>=y$	12 00001010 dec 00001001 10000100c	swap y$x$ 0	!or >0? NOT
  10173 ; strs_neql	x$<>y$	13 00001011 dec 00001010 00000101	---- x$y$ 0	!or >0? NOT
  10174 ; str_grtr	x$>y$	14 00001100 -	00001100 00000110	---- x$y$ 0	!or >0? ---
  10175 ; str_less	x$<y$	15 00001101 -	00001101 10000110c	swap y$x$ 0	!or >0? ---
  10176 ; strs_eql	x$=y$	16 00001110 -	00001110 00000111	---- x$y$ 0	!or >0? ---
  10177 ;
  10178 ; String comparisons are a little different in that the eql/neql carry flag
  10179 ; from the 2nd RRCA is, as before, fed into the first of the end tests but
  10180 ; along the way it gets modified by the comparison process. The result on the
  10181 ; stack always starts off as zero and the carry fed in determines if NOT is
  10182 ; applied to it. So the only time the greater-0 test is applied is if the
  10183 ; stack holds zero which is not very efficient as the test will always yield
  10184 ; zero. The most likely explanation is that there were once separate end tests
  10185 ; for numbers and strings.
  10186 
  10187 ; $1B03 SAME ADDRESS FOR MULTIPLE ROUTINES ???
  10188 
  10189 *num_l_eql:*
  10190 *num_gr_eql:*
  10191 *nums_neql:*
  10192 *num_grtr:*
  10193 *num_less:*
  10194 *nums_eql:*
  10195 *str_l_eql:*
  10196 *str_gr_eql:*
  10197 *strs_neql:*
  10198 *str_grtr:*
  10199 *str_less:*
  10200 *strs_eql:*
  10201 *num_lt_eql:*
  10202 #if ORIGINAL
  10203 mark_1B03:
  10204 	LD	A,B		; transfer literal to accumulator.
  10205 	SUB	$08		; subtract eight - which is not useful.
  10206 #else
  10207 	LD	A,B		; transfer literal to accumulator.
  10208 ;;	SUB	$08		; subtract eight - which is not useful.
  10209 #endif
  10210 	BIT	2,A		; isolate '>', '<', '='.
  10211 
  10212 	JR	NZ,EX_OR_NOT <#EX_OR_NOT>	; skip to EX_OR_NOT with these.
  10213 
  10214 	DEC	A		; else make $00-$02, $08-$0A to match bits 0-2.
  10215 
  10216 *EX_OR_NOT:*
  10217 #if ORIGINAL
  10218 mark_1B0B:
  10219 #endif
  10220 	RRCA			; the first RRCA sets carry for a swap.
  10221 	JR	NC,NUM_OR_STR <#NUM_OR_STR>	; forward to NUM_OR_STR with other 8 cases
  10222 
  10223 ; for the other 4 cases the two values on the calculator stack are exchanged.
  10224 
  10225 	PUSH	AF		; save A and carry.
  10226 	PUSH	HL		; save HL - pointer to first operand.
  10227 				; (DE points to second operand).
  10228 
  10229 	CALL	exchange <#exchange>		; routine exchange swaps the two values.
  10230 				; (HL = second operand, DE = STKEND)
  10231 
  10232 	POP	DE		; DE = first operand
  10233 	EX	DE,HL		; as we were.
  10234 	POP	AF		; restore A and carry.
  10235 
  10236 ; Note. it would be better if the 2nd RRCA preceded the string test.
  10237 ; It would save two duplicate bytes and if we also got rid of that sub 8
  10238 ; at the beginning we wouldn't have to alter which bit we test.
  10239 
  10240 *NUM_OR_STR:*
  10241 #if ORIGINAL
  10242 mark_1B16:
  10243 
  10244 	BIT	2,A		; test if a string comparison.
  10245 	JR	NZ,STRINGS <#STRINGS>	; forward to STRINGS if so.
  10246 
  10247 ; continue with numeric comparisons.
  10248 
  10249 	RRCA			; 2nd RRCA causes eql/neql to set carry.
  10250 	PUSH	AF		; save A and carry
  10251 #else
  10252 	RRCA			;+ causes 'eql/neql' to set carry.
  10253 	PUSH	AF		;+ save the carry flag.
  10254 
  10255 	BIT	2,A		; test if a string comparison.
  10256 	JR	NZ,STRINGS <#STRINGS>	; forward to STRINGS if so.
  10257 
  10258 #endif
  10259 
  10260 	CALL	SUBTRACT <#SUBTRACT>	; leaves result on stack.
  10261 	JR	END_TESTS <#END_TESTS>	; forward to END_TESTS
  10262 
  10263 ; ___
  10264 
  10265 
  10266 *STRINGS:*
  10267 #if ORIGINAL
  10268 mark_1B21:
  10269 	RRCA			; 2nd RRCA causes eql/neql to set carry.
  10270 	PUSH	AF		; save A and carry.
  10271 #else
  10272 ;;	RRCA			; 2nd RRCA causes eql/neql to set carry.
  10273 ;;	PUSH	AF		; save A and carry.
  10274 #endif
  10275 	CALL	STK_FETCH <#STK_FETCH>	; gets 2nd string params
  10276 	PUSH	DE		; save start2 *.
  10277 	PUSH	BC		; and the length.
  10278 
  10279 	CALL	STK_FETCH <#STK_FETCH>	; gets 1st string
  10280 				; parameters - start in DE, length in BC.
  10281 	POP	HL		; restore length of second to HL.
  10282 
  10283 ; A loop is now entered to compare, by subtraction, each corresponding character
  10284 ; of the strings. For each successful match, the pointers are incremented and
  10285 ; the lengths decreased and the branch taken back to here. If both string
  10286 ; remainders become null at the same time, then an exact match exists.
  10287 
  10288 #if ORIGINAL
  10289 mark_1B2C:
  10290 #endif
  10291 *BYTE_COMP:*
  10292 	LD	A,H		; test if the second string
  10293 	OR	L		; is the null string and hold flags.
  10294 
  10295 	EX	(SP),HL	; put length2 on stack, bring start2 to HL *.
  10296 	LD	A,B		; hi byte of length1 to A
  10297 
  10298 	JR	NZ,SEC_PLUS <#SEC_PLUS>	; forward to SEC_PLUS if second not null.
  10299 
  10300 	OR	C		; test length of first string.
  10301 
  10302 #if ORIGINAL
  10303 mark_1B33:
  10304 #endif
  10305 
  10306 *SECOND_LOW:*
  10307 	POP	BC		; pop the second length off stack.
  10308 	JR	Z,BOTH_NULL <#BOTH_NULL>	; forward if first string is also
  10309 				; of zero length.
  10310 
  10311 ; the true condition - first is longer than second (SECOND_LESS)
  10312 
  10313 	POP	AF		; restore carry (set if eql/neql)
  10314 	CCF			; complement carry flag.
  10315 				; Note. equality becomes false.
  10316 				; Inequality is true. By swapping or applying
  10317 				; a terminal 'not', all comparisons have been
  10318 				; manipulated so that this is success path.
  10319 	JR	STR_TEST <#STR_TEST>		; forward to leave via STR_TEST
  10320 
  10321 ; ___
  10322 ; the branch was here with a match
  10323 
  10324 #if ORIGINAL
  10325 mark_1B3A:
  10326 #endif
  10327 
  10328 *BOTH_NULL:*
  10329 	POP	AF		; restore carry - set for eql/neql
  10330 	JR	STR_TEST <#STR_TEST>		; forward to STR_TEST
  10331 
  10332 ; ___
  10333 ; the branch was here when 2nd string not null and low byte of first is yet
  10334 ; to be tested.
  10335 
  10336 
  10337 mark_1B3D:
  10338 *SEC_PLUS:*
  10339 	OR	C		; test the length of first string.
  10340 	JR	Z,FRST_LESS <#FRST_LESS>	; forward to FRST_LESS if length is zero.
  10341 
  10342 ; both strings have at least one character left.
  10343 
  10344 	LD	A,(DE)		; fetch character of first string.
  10345 	SUB	(HL)		; subtract with that of 2nd string.
  10346 	JR	C,FRST_LESS <#FRST_LESS>	; forward to FRST_LESS if carry set
  10347 
  10348 	JR	NZ,SECOND_LOW <#SECOND_LOW>	; back to SECOND_LOW and then STR_TEST
  10349 				; if not exact match.
  10350 
  10351 	DEC	BC		; decrease length of 1st string.
  10352 	INC	DE		; increment 1st string pointer.
  10353 
  10354 	INC	HL		; increment 2nd string pointer.
  10355 	EX	(SP),HL	; swap with length on stack
  10356 	DEC	HL		; decrement 2nd string length
  10357 	JR	BYTE_COMP <#BYTE_COMP>		; back to BYTE_COMP
  10358 
  10359 ; ___
  10360 ;	the false condition.
  10361 
  10362 mark_1B4D:
  10363 *FRST_LESS:*
  10364 	POP	BC		; discard length
  10365 	POP	AF		; pop A
  10366 	AND	A		; clear the carry for false result.
  10367 
  10368 ; ___
  10369 ;	exact match and x$>y$ rejoin here
  10370 
  10371 mark_1B50:
  10372 *STR_TEST:*
  10373 	PUSH	AF		; save A and carry
  10374 
  10375 	RST	_FP_CALC	;;
  10376 	DEFB	__stk_zero	;;	an initial false value.
  10377 	DEFB	__end_calc	;;
  10378 
  10379 ;	both numeric and string paths converge here.
  10380 
  10381 mark_1B54:
  10382 *END_TESTS:*
  10383 	POP	AF		; pop carry	- will be set if eql/neql
  10384 	PUSH	AF		; save it again.
  10385 
  10386 	CALL	C,not <#not>	; sets true(1) if equal(0)
  10387 				; or, for strings, applies true result.
  10388 	CALL	greater_0 <#greater_0>		; ??????????
  10389 
  10390 
  10391 	POP	AF		; pop A
  10392 	RRCA			; the third RRCA - test for '<=', '>=' or '<>'.
  10393 	CALL	NC,not <#not>	; apply a terminal NOT if so.
  10394 	RET			; return.
  10395 ------------------------------------------------------------------------
  10396 
  10397 ; String concatenation ($17)
  10398 ------------------------------------------------------------------------
  10399 
  10400 ;	This literal combines two strings into one e.g. LET A$ = B$ + C$
  10401 ;	The two parameters of the two strings to be combined are on the stack.
  10402 
  10403 mark_1B62:
  10404 *strs_add:*
  10405 	CALL	STK_FETCH <#STK_FETCH>	; fetches string parameters
  10406 				; and deletes calculator stack entry.
  10407 	PUSH	DE		; save start address.
  10408 	PUSH	BC		; and length.
  10409 
  10410 	CALL	STK_FETCH <#STK_FETCH>	; for first string
  10411 	POP	HL		; re-fetch first length
  10412 	PUSH	HL		; and save again
  10413 	PUSH	DE		; save start of second string
  10414 	PUSH	BC		; and its length.
  10415 
  10416 	ADD	HL,BC		; add the two lengths.
  10417 	LD	B,H		; transfer to BC
  10418 	LD	C,L		; and create
  10419 	RST	_BC_SPACES	; BC_SPACES in workspace.
  10420 				; DE points to start of space.
  10421 
  10422 	CALL	STK_STO_STR <#STK_STO_STR>	; stores parameters
  10423 				; of new string updating STKEND.
  10424 	POP	BC		; length of first
  10425 	POP	HL		; address of start
  10426 
  10427 #if ORIGINAL
  10428 	LD	A,B		; test for
  10429 	OR	C		; zero length.
  10430 	JR	Z,OTHER_STR <#OTHER_STR>	; to OTHER_STR if null string
  10431 	LDIR			; copy string to workspace.
  10432 #else
  10433 	CALL	COND_MV <#COND_MV>		;+ a conditional (NZ) ldir routine. 
  10434 #endif
  10435 
  10436 mark_1B7D:
  10437 *OTHER_STR:*
  10438 	POP	BC		; now second length
  10439 	POP	HL		; and start of string
  10440 #if ORIGINAL
  10441 	LD	A,B		; test this one
  10442 	OR	C		; for zero length
  10443 	JR	Z,STACK_POINTERS <#STACK_POINTERS>	; skip forward to STACK_POINTERS if so as complete.
  10444 
  10445 	LDIR			; else copy the bytes.
  10446 				; and continue into next routine which
  10447 				; sets the calculator stack pointers.
  10448 #else
  10449 	CALL	COND_MV <#COND_MV>		;+ a conditional (NZ) ldir routine. 
  10450 #endif
  10451 
  10452 ------------------------------------------------------------------------
  10453 
  10454 ; Check stack pointers
  10455 ------------------------------------------------------------------------
  10456 
  10457 ;	Register DE is set to STKEND and HL, the result pointer, is set to five
  10458 ;	locations below this.
  10459 ;	This routine is used when it is inconvenient to save these values at the
  10460 ;	time the calculator stack is manipulated due to other activity on the
  10461 ;	machine stack.
  10462 ;	This routine is also used to terminate the VAL routine for
  10463 ;	the same reason and to initialize the calculator stack at the start of
  10464 ;	the CALCULATE routine.
  10465 
  10466 mark_1B85:
  10467 *STACK_POINTERS:*
  10468 	LD	HL,(STKEND)	; fetch STKEND value from system variable.
  10469 	LD	DE,-5
  10470 	PUSH	HL		; push STKEND value.
  10471 
  10472 	ADD	HL,DE		; subtract 5 from HL.
  10473 
  10474 	POP	DE		; pop STKEND to DE.
  10475 	RET			; return.
  10476 
  10477 ------------------------------------------------------------------------
  10478 
  10479 ; Handle CHR$ (2B)
  10480 ------------------------------------------------------------------------
  10481 
  10482 ;	This function returns a single character string that is a result of
  10483 ;	converting a number in the range 0-255 to a string e.g. CHR$ 38 = "A".
  10484 ;	Note. the ZX81 does not have an ASCII character set.
  10485 
  10486 mark_1B8F:
  10487 *chr_dollar:*
  10488 	CALL	FP_TO_A <#FP_TO_A>		; puts the number in A.
  10489 
  10490 	JR	C,REPORT_Bd <#REPORT_Bd>	; forward if overflow
  10491 	JR	NZ,REPORT_Bd <#REPORT_Bd>	; forward if negative
  10492 #if ORIGINAL
  10493 	PUSH	AF		; save the argument.
  10494 #endif
  10495 	LD	BC,1		; one space required.
  10496 	RST	_BC_SPACES	; BC_SPACES makes DE point to start
  10497 #if ORIGINAL
  10498 	POP	AF		; restore the number.
  10499 #endif
  10500 	LD	(DE),A		; and store in workspace
  10501 
  10502 #if ORIGINAL
  10503 	CALL	STK_STO_STR <#STK_STO_STR>	; stacks descriptor.
  10504 
  10505 	EX	DE,HL		; make HL point to result and DE to STKEND.
  10506 	RET			; return.
  10507 #else
  10508 	JR	str_STK	;+ relative jump to similar sequence in str$.
  10509 #endif
  10510 ; ___
  10511 
  10512 mark_1BA2:
  10513 *REPORT_Bd:*
  10514 	RST	_ERROR_1
  10515 	DEFB	$0A		; Error Report: Integer out of range
  10516 
  10517 ------------------------------------------------------------------------
  10518 
  10519 ; Handle VAL ($1A)
  10520 ------------------------------------------------------------------------
  10521 
  10522 ;	VAL treats the characters in a string as a numeric expression.
  10523 ;	e.g. VAL "2.3" = 2.3, VAL "2+4" = 6, VAL ("2" + "4") = 24.
  10524 
  10525 *val:*
  10526 #if ORIGINAL
  10527 mark_1BA4:
  10528 	LD	HL,(CH_ADD)	; fetch value of system variable CH_ADD
  10529 #else
  10530 	RST	_GET_CHAR	;+ shorter way to fetch CH_ADD.
  10531 #endif
  10532 	PUSH	HL		; and save on the machine stack.
  10533 
  10534 	CALL	STK_FETCH <#STK_FETCH>	; fetches the string operand
  10535 				; from calculator stack.
  10536 
  10537 	PUSH	DE		; save the address of the start of the string.
  10538 	INC	BC		; increment the length for a carriage return.
  10539 
  10540 	RST	_BC_SPACES	; BC_SPACES creates the space in workspace.
  10541 	POP	HL		; restore start of string to HL.
  10542 	LD	(CH_ADD),DE	; load CH_ADD with start DE in workspace.
  10543 
  10544 	PUSH	DE		; save the start in workspace
  10545 	LDIR			; copy string from program or variables or
  10546 				; workspace to the workspace area.
  10547 	EX	DE,HL		; end of string + 1 to HL
  10548 	DEC	HL		; decrement HL to point to end of new area.
  10549 	LD	(HL),ZX_NEWLINE	; insert a carriage return at end.
  10550 				; ZX81 has a non-ASCII character set
  10551 	RES	7,(IY+FLAGS-RAMBASE)	; signal checking syntax.
  10552 	CALL	CLASS_6 <#CLASS_6>		; evaluates string
  10553 				; expression and checks for integer result.
  10554 
  10555 	CALL	CHECK_2 <#CHECK_2>		; checks for carriage return.
  10556 
  10557 
  10558 	POP	HL		; restore start of string in workspace.
  10559 
  10560 	LD	(CH_ADD),HL	; set CH_ADD to the start of the string again.
  10561 	SET	7,(IY+FLAGS-RAMBASE)	; signal running program.
  10562 	CALL	SCANNING <#SCANNING>	; evaluates the string
  10563 				; in full leaving result on calculator stack.
  10564 
  10565 	POP	HL		; restore saved character address in program.
  10566 	LD	(CH_ADD),HL	; and reset the system variable CH_ADD.
  10567 
  10568 	JR	STACK_POINTERS <#STACK_POINTERS>	; back to exit via STACK_POINTERS.
  10569 				; resetting the calculator stack pointers
  10570 				; HL and DE from STKEND as it wasn't possible
  10571 				; to preserve them during this routine.
  10572 
  10573 ------------------------------------------------------------------------
  10574 
  10575 ; Handle STR$ (2A)
  10576 ------------------------------------------------------------------------
  10577 
  10578 ;	This function returns a string representation of a numeric argument.
  10579 ;	The method used is to trick the PRINT_FP routine into thinking it
  10580 ;	is writing to a collapsed display file when in fact it is writing to
  10581 ;	string workspace.
  10582 ;	If there is already a newline at the intended print position and the
  10583 ;	column count has not been reduced to zero then the print routine
  10584 ;	assumes that there is only 1K of RAM and the screen memory, like the rest
  10585 ;	of dynamic memory, expands as necessary using calls to the ONE_SPACE
  10586 ;	routine. The screen is character-mapped not bit-mapped.
  10587 
  10588 mark_1BD5:
  10589 *str_dollar:*
  10590 	LD	BC,1		; create an initial byte in workspace
  10591 	RST	_BC_SPACES	; using BC_SPACES restart.
  10592 
  10593 	LD	(HL),ZX_NEWLINE	; place a carriage return there.
  10594 
  10595 	LD	HL,(S_POSN)	; fetch value of S_POSN column/line
  10596 	PUSH	HL		; and preserve on stack.
  10597 
  10598 	LD	L,$FF		; make column value high to create a
  10599 				; contrived buffer of length 254.
  10600 	LD	(S_POSN),HL	; and store in system variable S_POSN.
  10601 
  10602 	LD	HL,(DF_CC)	; fetch value of DF_CC
  10603 	PUSH	HL		; and preserve on stack also.
  10604 
  10605 	LD	(DF_CC),DE	; now set DF_CC which normally addresses
  10606 				; somewhere in the display file to the start
  10607 				; of workspace.
  10608 	PUSH	DE		; save the start of new string.
  10609 
  10610 	CALL	PRINT_FP <#PRINT_FP>
  10611 
  10612 	POP	DE		; retrieve start of string.
  10613 
  10614 	LD	HL,(DF_CC)	; fetch end of string from DF_CC.
  10615 	AND	A		; prepare for true subtraction.
  10616 	SBC	HL,DE		; subtract to give length.
  10617 
  10618 	LD	B,H		; and transfer to the BC
  10619 	LD	C,L		; register.
  10620 
  10621 	POP	HL		; restore original
  10622 	LD	(DF_CC),HL	; DF_CC value
  10623 
  10624 	POP	HL		; restore original
  10625 	LD	(S_POSN),HL	; S_POSN values.
  10626 
  10627 #if ORIGINAL
  10628 #else
  10629 str_STK:			; New entry-point to exploit similarities and save 3 bytes of code.
  10630 #endif
  10631 
  10632 	CALL	STK_STO_STR <#STK_STO_STR>	; stores the string
  10633 				; descriptor on the calculator stack.
  10634 
  10635 	EX	DE,HL		; HL = last value, DE = STKEND.
  10636 	RET			; return.
  10637 
  10638 
  10639 ------------------------------------------------------------------------
  10640 
  10641 ; THE *'CODE'* FUNCTION
  10642 ------------------------------------------------------------------------
  10643 
  10644 ; (offset $19: 'code')
  10645 ;	Returns the code of a character or first character of a string
  10646 ;	e.g. CODE "AARDVARK" = 38	(not 65 as the ZX81 does not have an ASCII
  10647 ;	character set).
  10648 
  10649 
  10650 mark_1C06:
  10651 *code:*
  10652 	CALL	STK_FETCH <#STK_FETCH>	; fetch and delete the string parameters.
  10653 				; DE points to the start, BC holds the length.
  10654 	LD	A,B		; test length
  10655 	OR	C		; of the string.
  10656 	JR	Z,STK_CODE <#STK_CODE>	; skip with zero if the null string.
  10657 
  10658 	LD	A,(DE)		; else fetch the first character.
  10659 
  10660 mark_1C0E:
  10661 *STK_CODE:*
  10662 	JP	STACK_A <#STACK_A>		; jump back (with memory check)
  10663 
  10664 ------------------------------------------------------------------------
  10665 
  10666 ; THE *'LEN'* SUBROUTINE
  10667 ------------------------------------------------------------------------
  10668 
  10669 ; (offset $1b: 'len')
  10670 ;	Returns the length of a string.
  10671 ;	In Sinclair BASIC strings can be more than twenty thousand characters long
  10672 ;	so a sixteen-bit register is required to store the length
  10673 
  10674 mark_1C11:
  10675 *len:*
  10676 	CALL	STK_FETCH <#STK_FETCH>	; fetch and delete the
  10677 				; string parameters from the calculator stack.
  10678 				; register BC now holds the length of string.
  10679 
  10680 	JP	STACK_BC <#STACK_BC>	; jump back to save result on the
  10681 				; calculator stack (with memory check).
  10682 
  10683 ------------------------------------------------------------------------
  10684 
  10685 ; THE *'DECREASE THE COUNTER'* SUBROUTINE
  10686 ------------------------------------------------------------------------
  10687 
  10688 ; (offset $31: 'dec_jr_nz')
  10689 ;	The calculator has an instruction that decrements a single-byte
  10690 ;	pseudo-register and makes consequential relative jumps just like
  10691 ;	the Z80's DJNZ instruction.
  10692 
  10693 mark_1C17:
  10694 *dec_jr_nz:*
  10695 	EXX			; switch in set that addresses code
  10696 
  10697 	PUSH	HL		; save pointer to offset byte
  10698 	LD	HL,BERG		; address BERG in system variables
  10699 	DEC	(HL)		; decrement it
  10700 	POP	HL		; restore pointer
  10701 
  10702 	JR	NZ,JUMP_2 <#JUMP_2>	; to JUMP_2 if not zero
  10703 
  10704 	INC	HL		; step past the jump length.
  10705 	EXX			; switch in the main set.
  10706 	RET			; return.
  10707 
  10708 ;	Note. as a general rule the calculator avoids using the IY register
  10709 ;	otherwise the cumbersome 4 instructions in the middle could be replaced by
  10710 ;	dec (iy+$xx) - using three instruction bytes instead of six.
  10711 
  10712 
  10713 ------------------------------------------------------------------------
  10714 
  10715 ; THE *'JUMP'* SUBROUTINE
  10716 ------------------------------------------------------------------------
  10717 
  10718 ; (Offset $2F; 'jump')
  10719 ;	This enables the calculator to perform relative jumps just like
  10720 ;	the Z80 chip's JR instruction.
  10721 ;	This is one of the few routines to be polished for the ZX Spectrum.
  10722 ;	See, without looking at the ZX Spectrum ROM, if you can get rid of the
  10723 ;	relative jump.
  10724 
  10725 mark_1C23:
  10726 *jump:*
  10727 	EXX			;switch in pointer set
  10728 *JUMP_2:*
  10729 	LD	E,(HL)		; the jump byte 0-127 forward, 128-255 back.
  10730 
  10731 #if ORIGINAL
  10732 mark_1C24:
  10733 	XOR	A		; clear accumulator.
  10734 	BIT	7,E		; test if negative jump
  10735 	JR	Z,JUMP_3 <#JUMP_3>	; skip, if positive
  10736 	CPL			; else change to $FF.
  10737 #else
  10738 				; Note. Elegance from the ZX Spectrum.
  10739 	LD	A,E		;+
  10740 	RLA			;+
  10741 	SBC	A,A		;+
  10742 #endif
  10743 
  10744 mark_1C2B:
  10745 *JUMP_3:*
  10746 	LD	D,A		; transfer to high byte.
  10747 	ADD	HL,DE		; advance calculator pointer forward or back.
  10748 
  10749 	EXX			; switch out pointer set.
  10750 	RET			; return.
  10751 
  10752 ------------------------------------------------------------------------
  10753 
  10754 ; THE *'JUMP ON TRUE'* SUBROUTINE
  10755 ------------------------------------------------------------------------
  10756 
  10757 ; (Offset $00; 'jump_true')
  10758 ;	This enables the calculator to perform conditional relative jumps
  10759 ;	dependent on whether the last test gave a true result
  10760 ;	On the ZX81, the exponent will be zero for zero or else $81 for one.
  10761 
  10762 mark_1C2F:
  10763 *jump_true:*
  10764 	LD	A,(DE)		; collect exponent byte
  10765 
  10766 	AND	A		; is result 0 or 1 ?
  10767 	JR	NZ,jump <#jump>		; back to JUMP if true (1).
  10768 
  10769 	EXX			; else switch in the pointer set.
  10770 	INC	HL		; step past the jump length.
  10771 	EXX			; switch in the main set.
  10772 	RET			; return.
  10773 
  10774 
  10775 ------------------------------------------------------------------------
  10776 
  10777 ; THE *'MODULUS'* SUBROUTINE
  10778 ------------------------------------------------------------------------
  10779 
  10780 ; ( Offset $2E: 'n_mod_m' )
  10781 ; ( i1, i2 -- i3, i4 )
  10782 ;	The subroutine calculate N mod M where M is the positive integer, the
  10783 ;	'last value' on the calculator stack and N is the integer beneath.
  10784 ;	The subroutine returns the integer quotient as the last value and the
  10785 ;	remainder as the value beneath.
  10786 ;	e.g.	17 MOD 3 = 5 remainder 2
  10787 ;	It is invoked during the calculation of a random number and also by
  10788 ;	the PRINT_FP routine.
  10789 
  10790 mark_1C37:
  10791 *n_mod_m:*
  10792 	RST	_FP_CALC	;;	17, 3.
  10793 	DEFB	__st_mem_0	;;	17, 3.
  10794 	DEFB	__delete	;;	17.
  10795 	DEFB	__duplicate	;;	17, 17.
  10796 	DEFB	__get_mem_0	;;	17, 17, 3.
  10797 	DEFB	__division	;;	17, 17/3.
  10798 	DEFB	__int		;;	17, 5.
  10799 	DEFB	__get_mem_0	;;	17, 5, 3.
  10800 	DEFB	__exchange	;;	17, 3, 5.
  10801 	DEFB	__st_mem_0	;;	17, 3, 5.
  10802 	DEFB	__multiply	;;	17, 15.
  10803 	DEFB	__subtract	;;	2.
  10804 	DEFB	__get_mem_0	;;	2, 5.
  10805 	DEFB	__end_calc	;;	2, 5.
  10806 
  10807 	RET			; return.
  10808 
  10809 
  10810 ------------------------------------------------------------------------
  10811 
  10812 ; THE *'INTEGER'* FUNCTION
  10813 ------------------------------------------------------------------------
  10814 
  10815 ; (offset $24: 'int')
  10816 ;	This function returns the integer of x, which is just the same as truncate
  10817 ;	for positive numbers. The truncate literal truncates negative numbers
  10818 ;	upwards so that -3.4 gives -3 whereas the BASIC INT function has to
  10819 ;	truncate negative numbers down so that INT -3.4 is 4.
  10820 ;	It is best to work through using, say, plus or minus 3.4 as examples.
  10821 
  10822 mark_1C46:
  10823 *int:*
  10824 	RST	_FP_CALC	;;		x.	(= 3.4 or -3.4).
  10825 	DEFB	__duplicate	;;		x, x.
  10826 	DEFB	__less_0	;;		x, (1/0)
  10827 	DEFB	__jump_true	;;		x, (1/0)
  10828 	DEFB	int <#int> - $	;; X_NEG
  10829 
  10830 	DEFB	__truncate	;;		trunc 3.4 = 3.
  10831 	DEFB	__end_calc	;;		3.
  10832 
  10833 	RET			; return with + int x on stack.
  10834 
  10835 
  10836 mark_1C4E:
  10837 *X_NEG:*
  10838 	DEFB	__duplicate	;;		-3.4, -3.4.
  10839 	DEFB	__truncate	;;		-3.4, -3.
  10840 	DEFB	__st_mem_0	;;		-3.4, -3.
  10841 	DEFB	__subtract	;;		-.4
  10842 	DEFB	__get_mem_0	;;		-.4, -3.
  10843 	DEFB	__exchange	;;		-3, -.4.
  10844 	DEFB	__not		;;			-3, (0).
  10845 	DEFB	__jump_true	;;		-3.
  10846 	DEFB	EXIT <#EXIT> - $	;;		-3.
  10847 
  10848 	DEFB	__stk_one	;;		-3, 1.
  10849 	DEFB	__subtract	;;		-4.
  10850 
  10851 mark_1C59:
  10852 *EXIT:*
  10853 	DEFB	__end_calc	;;		-4.
  10854 
  10855 	RET			; return.
  10856 
  10857 
  10858 ------------------------------------------------------------------------
  10859 
  10860 ; Exponential (23)
  10861 ------------------------------------------------------------------------
  10862 
  10863 ;
  10864 ;
  10865 
  10866 mark_1C5B:
  10867 *exp:*
  10868 	RST	_FP_CALC	;;
  10869 	DEFB	__stk_data	;;
  10870 	DEFB	$F1		;;Exponent: $81, Bytes: 4
  10871 	DEFB	$38,$AA,$3B,$29 ;;
  10872 	DEFB	__multiply	;;
  10873 	DEFB	__duplicate	;;
  10874 	DEFB	__int		;;
  10875 	DEFB	$C3		;;st_mem_3
  10876 	DEFB	__subtract	;;
  10877 	DEFB	__duplicate	;;
  10878 	DEFB	__addition	;;
  10879 	DEFB	__stk_one	;;
  10880 	DEFB	__subtract	;;
  10881 	DEFB	__series_08	;;
  10882 	DEFB	$13		;;Exponent: $63, Bytes: 1
  10883 	DEFB	$36		;;(+00,+00,+00)
  10884 	DEFB	$58		;;Exponent: $68, Bytes: 2
  10885 	DEFB	$65,$66	;;(+00,+00)
  10886 	DEFB	$9D		;;Exponent: $6D, Bytes: 3
  10887 	DEFB	$78,$65,$40	;;(+00)
  10888 	DEFB	$A2		;;Exponent: $72, Bytes: 3
  10889 	DEFB	$60,$32,$C9	;;(+00)
  10890 	DEFB	$E7		;;Exponent: $77, Bytes: 4
  10891 	DEFB	$21,$F7,$AF,$24 ;;
  10892 	DEFB	$EB		;;Exponent: $7B, Bytes: 4
  10893 	DEFB	$2F,$B0,$B0,$14 ;;
  10894 	DEFB	$EE		;;Exponent: $7E, Bytes: 4
  10895 	DEFB	$7E,$BB,$94,$58 ;;
  10896 	DEFB	$F1		;;Exponent: $81, Bytes: 4
  10897 	DEFB	$3A,$7E,$F8,$CF ;;
  10898 	DEFB	$E3		;;get_mem_3
  10899 	DEFB	__end_calc	;;
  10900 
  10901 	CALL	FP_TO_A <#FP_TO_A>
  10902 	JR	NZ,N_NEGTV <#N_NEGTV>
  10903 
  10904 	JR	C,REPORT_6b <#REPORT_6b>
  10905 
  10906 	ADD	A,(HL)		;
  10907 	JR	NC,RESULT_OK <#RESULT_OK>
  10908 
  10909 
  10910 mark_1C99:
  10911 *REPORT_6b:*
  10912 	RST	_ERROR_1
  10913 	DEFB	$05		; Error Report: Number too big
  10914 
  10915 mark_1C9B:
  10916 *N_NEGTV:*
  10917 	JR	C,RESULT_ZERO <#RESULT_ZERO>
  10918 
  10919 	SUB	(HL)		;
  10920 	JR	NC,RESULT_ZERO <#RESULT_ZERO>
  10921 
  10922 	NEG			; Negate
  10923 
  10924 mark_1CA2:
  10925 *RESULT_OK:*
  10926 	LD	(HL),A		;
  10927 	RET			; return.
  10928 
  10929 
  10930 mark_1CA4:
  10931 *RESULT_ZERO:*
  10932 	RST	_FP_CALC	;;
  10933 	DEFB	__delete	;;
  10934 	DEFB	__stk_zero	;;
  10935 	DEFB	__end_calc	;;
  10936 
  10937 	RET			; return.
  10938 
  10939 
  10940 ------------------------------------------------------------------------
  10941 
  10942 ; THE *'NATURAL LOGARITHM'* FUNCTION
  10943 ------------------------------------------------------------------------
  10944 
  10945 ; (offset $22: 'ln')
  10946 ;	Like the ZX81 itself, 'natural' logarithms came from Scotland.
  10947 ;	They were devised in 1614 by well-traveled Scotsman John Napier who noted
  10948 ;	"Nothing doth more molest and hinder calculators than the multiplications,
  10949 ;	divisions, square and cubical extractions of great numbers".
  10950 ;
  10951 ;	Napier's logarithms enabled the above operations to be accomplished by 
  10952 ;	simple addition and subtraction simplifying the navigational and 
  10953 ;	astronomical calculations which beset his age.
  10954 ;	Napier's logarithms were quickly overtaken by logarithms to the base 10
  10955 ;	devised, in conjunction with Napier, by Henry Briggs a Cambridge-educated 
  10956 ;	professor of Geometry at Oxford University. These simplified the layout
  10957 ;	of the tables enabling humans to easily scale calculations.
  10958 ;
  10959 ;	It is only recently with the introduction of pocket calculators and
  10960 ;	computers like the ZX81 that natural logarithms are once more at the fore,
  10961 ;	although some computers retain logarithms to the base ten.
  10962 ;	'Natural' logarithms are powers to the base 'e', which like 'pi' is a 
  10963 ;	naturally occurring number in branches of mathematics.
  10964 ;	Like 'pi' also, 'e' is an irrational number and starts 2.718281828...
  10965 ;
  10966 ;	The tabular use of logarithms was that to multiply two numbers one looked
  10967 ;	up their two logarithms in the tables, added them together and then looked 
  10968 ;	for the result in a table of antilogarithms to give the desired product.
  10969 ;
  10970 ;	The EXP function is the BASIC equivalent of a calculator's 'antiln' function 
  10971 ;	and by picking any two numbers, 1.72 and 6.89 say,
  10972 ;	10 PRINT EXP ( LN 1.72 + LN 6.89 ) 
  10973 ;	will give just the same result as
  10974 ;	20 PRINT 1.72 * 6.89.
  10975 ;	Division is accomplished by subtracting the two logs.
  10976 ;
  10977 ;	Napier also mentioned "square and cubicle extractions". 
  10978 ;	To raise a number to the power 3, find its 'ln', multiply by 3 and find the 
  10979 ;	'antiln'.	e.g. PRINT EXP( LN 4 * 3 )	gives 64.
  10980 ;	Similarly to find the n'th root divide the logarithm by 'n'.
  10981 ;	The ZX81 ROM used PRINT EXP ( LN 9 / 2 ) to find the square root of the 
  10982 ;	number 9. The Napieran square root function is just a special case of 
  10983 ;	the 'to_power' function. A cube root or indeed any root/power would be just
  10984 ;	as simple.
  10985 
  10986 ;	First test that the argument to LN is a positive, non-zero number.
  10987 
  10988 mark_1CA9:
  10989 *ln:*
  10990 	RST	_FP_CALC	;;
  10991 	DEFB	__duplicate	;;
  10992 	DEFB	__greater_0	;;
  10993 	DEFB	__jump_true	;;
  10994 	DEFB	VALID - $		;;to VALID <#VALID>
  10995 
  10996 	DEFB	__end_calc	;;
  10997 
  10998 
  10999 mark_1CAF:
  11000 *REPORT_Ab:*
  11001 	RST	_ERROR_1
  11002 	DEFB	$09		; Error Report: Invalid argument
  11003 
  11004 *VALID:*
  11005 #if ORIGINAL
  11006 mark_1CB1:
  11007 	DEFB	__stk_zero	;;		Note. not necessary.
  11008 	DEFB	__delete	;;
  11009 #endif
  11010 	DEFB	__end_calc	;;
  11011 	LD	A,(HL)		;
  11012 
  11013 	LD	(HL),$80	;
  11014 	CALL	STACK_A <#STACK_A>
  11015 
  11016 	RST	_FP_CALC	;;
  11017 	DEFB	__stk_data	;;
  11018 	DEFB	$38		;;Exponent: $88, Bytes: 1
  11019 	DEFB	$00		;;(+00,+00,+00)
  11020 	DEFB	__subtract	;;
  11021 	DEFB	__exchange	;;
  11022 	DEFB	__duplicate	;;
  11023 	DEFB	__stk_data	;;
  11024 	DEFB	$F0		;;Exponent: $80, Bytes: 4
  11025 	DEFB	$4C,$CC,$CC,$CD ;;
  11026 	DEFB	__subtract	;;
  11027 	DEFB	__greater_0	;;
  11028 	DEFB	__jump_true	;;
  11029 	DEFB	GRE_8 <#GRE_8> - $		;;
  11030 
  11031 	DEFB	__exchange	;;
  11032 	DEFB	__stk_one	;;
  11033 	DEFB	__subtract	;;
  11034 	DEFB	__exchange	;;
  11035 	DEFB	__end_calc	;;
  11036 
  11037 	INC	(HL)		;
  11038 
  11039 	RST	_FP_CALC	;;
  11040 
  11041 mark_1CD2:
  11042 *GRE_8:*
  11043 	DEFB	__exchange	;;
  11044 	DEFB	__stk_data	;;
  11045 	DEFB	$F0		;;Exponent: $80, Bytes: 4
  11046 	DEFB	$31,$72,$17,$F8 ;;
  11047 	DEFB	__multiply	;;
  11048 	DEFB	__exchange	;;
  11049 	DEFB	__stk_half		;;
  11050 	DEFB	__subtract	;;
  11051 	DEFB	__stk_half		;;
  11052 	DEFB	__subtract	;;
  11053 	DEFB	__duplicate	;;
  11054 	DEFB	__stk_data	;;
  11055 	DEFB	$32		;;Exponent: $82, Bytes: 1
  11056 	DEFB	$20		;;(+00,+00,+00)
  11057 	DEFB	__multiply	;;
  11058 	DEFB	__stk_half		;;
  11059 	DEFB	__subtract	;;
  11060 	DEFB	__series_0C	;;
  11061 	DEFB	$11		;;Exponent: $61, Bytes: 1
  11062 	DEFB	$AC		;;(+00,+00,+00)
  11063 	DEFB	$14		;;Exponent: $64, Bytes: 1
  11064 	DEFB	$09		;;(+00,+00,+00)
  11065 	DEFB	$56		;;Exponent: $66, Bytes: 2
  11066 	DEFB	$DA,$A5		;;(+00,+00)
  11067 	DEFB	$59		;;Exponent: $69, Bytes: 2
  11068 	DEFB	$30,$C5		;;(+00,+00)
  11069 	DEFB	$5C		;;Exponent: $6C, Bytes: 2
  11070 	DEFB	$90,$AA		;;(+00,+00)
  11071 	DEFB	$9E		;;Exponent: $6E, Bytes: 3
  11072 	DEFB	$70,$6F,$61	;;(+00)
  11073 	DEFB	$A1		;;Exponent: $71, Bytes: 3
  11074 	DEFB	$CB,$DA,$96	;;(+00)
  11075 	DEFB	$A4		;;Exponent: $74, Bytes: 3
  11076 	DEFB	$31,$9F,$B4	;;(+00)
  11077 	DEFB	$E7		;;Exponent: $77, Bytes: 4
  11078 	DEFB	$A0,$FE,$5C,$FC ;;
  11079 	DEFB	$EA		;;Exponent: $7A, Bytes: 4
  11080 	DEFB	$1B,$43,$CA,$36 ;;
  11081 	DEFB	$ED		;;Exponent: $7D, Bytes: 4
  11082 	DEFB	$A7,$9C,$7E,$5E ;;
  11083 	DEFB	$F0		;;Exponent: $80, Bytes: 4
  11084 	DEFB	$6E,$23,$80,$93 ;;
  11085 	DEFB	__multiply	;;
  11086 	DEFB	__addition	;;
  11087 	DEFB	__end_calc	;;
  11088 
  11089 	RET			; return.
  11090 ------------------------------------------------------------------------
  11091 
  11092 #if ORIGINAL
  11093 #else
  11094 ; ------------------------------
  11095 ; THE NEW *'SQUARE ROOT'* FUNCTION
  11096 ; ------------------------------
  11097 ; (Offset $25: 'sqr')
  11098 ;	"If I have seen further, it is by standing on the shoulders of giants" -
  11099 ;	Sir Isaac Newton, Cambridge 1676.
  11100 ;	The sqr function has been re-written to use the Newton-Raphson method.
  11101 ;	Joseph Raphson was a student of Sir Isaac Newton at Cambridge University
  11102 ;	and helped publicize his work.
  11103 ;	Although Newton's method is centuries old, this routine, appropriately, is 
  11104 ;	based on a FORTH word written by Steven Vickers in the Jupiter Ace manual.
  11105 ;	Whereas that method uses an initial guess of one, this one manipulates 
  11106 ;	the exponent byte to obtain a better starting guess. 
  11107 ;	First test for zero and return zero, if so, as the result.
  11108 ;	If the argument is negative, then produce an error.
  11109 ;
  11110 *sqr*	RST	_FP_CALC	;; 		x
  11111 	DEFB	__st_mem_3	;;		x.	(seed for guess)
  11112 	DEFB	__end_calc	;;		x.
  11113 
  11114 ;	HL now points to exponent of argument on calculator stack.
  11115 
  11116 	LD	A,(HL)		; Test for zero argument
  11117 	AND	A		; 
  11118 
  11119 	RET	Z		; Return with zero on the calculator stack.
  11120 
  11121 ;	Test for a positive argument
  11122 
  11123 	INC	HL		; Address byte with sign bit.
  11124 	BIT	7,(HL)		; Test the bit.
  11125 
  11126 	JR	NZ,REPORT_Ab <#REPORT_Ab>	; back to REPORT_A 
  11127 				; 'Invalid argument'
  11128  
  11129 ;	This guess is based on a Usenet discussion.
  11130 ;	Halve the exponent to achieve a good guess.(accurate with .25 16 64 etc.)
  11131 
  11132 	LD	HL,$4071	; Address first byte of mem-3
  11133 
  11134 	LD	A,(HL)		; fetch exponent of mem-3
  11135 	XOR	$80		; toggle sign of exponent of mem-3
  11136 	SRA	A		; shift right, bit 7 unchanged.
  11137 	INC	A		;
  11138 	JR	Z,ASIS <#ASIS>		; forward with say .25 -> .5
  11139 	JP	P,ASIS <#ASIS>		; leave increment if value > .5
  11140 	DEC	A		; restore to shift only.
  11141 *ASIS*	XOR	$80		; restore sign.
  11142 	LD	(HL),A	; and put back 'halved' exponent.
  11143 
  11144 ;	Now re-enter the calculator.
  11145 
  11146 	RST	28H		;; FP-CALC		x
  11147 
  11148 *SLOOP*	DEFB	__duplicate	;;		x,x.
  11149 	DEFB	__get_mem_3	;;		x,x,guess
  11150 	DEFB	__st_mem_4	;;		x,x,guess
  11151 	DEFB	__division	;;		x,x/guess.
  11152 	DEFB	__get_mem_3	;;		x,x/guess,guess
  11153 	DEFB	__addition	;;		x,x/guess+guess
  11154 	DEFB	__stk_half	;;		x,x/guess+guess,.5
  11155 	DEFB	__multiply	;;		x,(x/guess+guess)*.5
  11156 	DEFB	__st_mem_3	;;		x,newguess
  11157 	DEFB	__get_mem_4	;;		x,newguess,oldguess
  11158 	DEFB	__subtract	;;		x,newguess-oldguess
  11159 	DEFB	__abs		;;		x,difference.
  11160 	DEFB	__greater_0	;;		x,(0/1).
  11161 	DEFB	__jump_true	;;		x.
  11162 
  11163 	DEFB	SLOOP <#SLOOP> - $	;;		x.
  11164 
  11165 	DEFB	__delete	;;		.
  11166 	DEFB	__get_mem_3	;;		retrieve final guess.
  11167 	DEFB	__end_calc	;;		sqr x.
  11168 
  11169 	RET			; return with square root on stack
  11170 
  11171 ;	or in ZX81 BASIC
  11172 ;
  11173 ;	5 PRINT "NEWTON RAPHSON SQUARE ROOTS"
  11174 ;	10 INPUT "NUMBER ";N
  11175 ;	20 INPUT "GUESS ";G
  11176 ;	30 PRINT " NUMBER "; N ;" GUESS "; G
  11177 ;	40 FOR I = 1 TO 10
  11178 ;	50	LET B = N/G
  11179 ;	60	LET C = B+G
  11180 ;	70	LET G = C/2
  11181 ;	80	PRINT I; " VALUE "; G
  11182 ;	90 NEXT I
  11183 ;	100 PRINT "NAPIER METHOD"; SQR N
  11184 #endif
  11185 
  11186 ------------------------------------------------------------------------
  11187 
  11188 ; THE *'TRIGONOMETRIC'* FUNCTIONS
  11189 ------------------------------------------------------------------------
  11190 
  11191 ;	Trigonometry is rocket science. It is also used by carpenters and pyramid
  11192 ;	builders. 
  11193 ;	Some uses can be quite abstract but the principles can be seen in simple
  11194 ;	right-angled triangles. Triangles have some special properties -
  11195 ;
  11196 ;	1) The sum of the three angles is always PI radians (180 degrees).
  11197 ;	Very helpful if you know two angles and wish to find the third.
  11198 ;	2) In any right-angled triangle the sum of the squares of the two shorter
  11199 ;	sides is equal to the square of the longest side opposite the right-angle.
  11200 ;	Very useful if you know the length of two sides and wish to know the
  11201 ;	length of the third side.
  11202 ;	3) Functions sine, cosine and tangent enable one to calculate the length 
  11203 ;	of an unknown side when the length of one other side and an angle is 
  11204 ;	known.
  11205 ;	4) Functions arcsin, arccosine and arctan enable one to calculate an unknown
  11206 ;	angle when the length of two of the sides is known.
  11207 
  11208 ------------------------------------------------------------------------
  11209 
  11210 ; THE *'REDUCE ARGUMENT'* SUBROUTINE
  11211 ------------------------------------------------------------------------
  11212 
  11213 ; (offset $35: 'get_argt')
  11214 ;
  11215 ;	This routine performs two functions on the angle, in radians, that forms
  11216 ;	the argument to the sine and cosine functions.
  11217 ;	First it ensures that the angle 'wraps round'. That if a ship turns through 
  11218 ;	an angle of, say, 3*PI radians (540 degrees) then the net effect is to turn 
  11219 ;	through an angle of PI radians (180 degrees).
  11220 ;	Secondly it converts the angle in radians to a fraction of a right angle,
  11221 ;	depending within which quadrant the angle lies, with the periodicity 
  11222 ;	resembling that of the desired sine value.
  11223 ;	The result lies in the range -1 to +1.
  11224 ;
  11225 ;			90 deg.
  11226 ; 
  11227 ;			(pi/2)
  11228 ;			II  +1    I
  11229 ;			|
  11230 ;		sin+	|\   |   /|	sin+
  11231 ;		cos-	| \  |	/ |	cos+
  11232 ;		tan-	|  \ | /  |	tan+
  11233 ;			|   \|/)  |
  11234 ;	180 deg. (pi) 0 |----+----|-- 0	(0)	0 degrees
  11235 ;			|   /|\   |
  11236 ;		sin-	|  / | \  |	sin-
  11237 ;		cos-	| /  |  \ |	cos+
  11238 ;		tan+	|/   |   \|	tan-
  11239 ;			|
  11240 ;			III -1	 IV
  11241 ;			(3pi/2)
  11242 ;
  11243 ;			270 deg.
  11244 
  11245 mark_1D18:
  11246 *get_argt:*
  11247 	RST	_FP_CALC	;;		X.
  11248 	DEFB	__stk_data	;;
  11249 	DEFB	$EE		;;Exponent: $7E, 
  11250 				;;Bytes: 4
  11251 	DEFB	$22,$F9,$83,$6E ;;		X, 1/(2*PI)
  11252 	DEFB	__multiply	;;		X/(2*PI) = fraction
  11253 
  11254 	DEFB	__duplicate	;;
  11255 	DEFB	__stk_half	;;
  11256 	DEFB	__addition	;;
  11257 	DEFB	__int		;;
  11258 
  11259 	DEFB	__subtract	;;	now range -.5 to .5
  11260 
  11261 	DEFB	__duplicate	;;
  11262 	DEFB	__addition	;;	now range -1 to 1.
  11263 	DEFB	__duplicate	;;
  11264 	DEFB	__addition	;;	now range -2 to 2.
  11265 
  11266 ;	quadrant I (0 to +1) and quadrant IV (-1 to 0) are now correct.
  11267 ;	quadrant II ranges +1 to +2.
  11268 ;	quadrant III ranges -2 to -1.
  11269 
  11270 	DEFB	__duplicate	;;	Y, Y.
  11271 	DEFB	__abs		;;	Y, abs(Y).	range 1 to 2
  11272 	DEFB	__stk_one	;;	Y, abs(Y), 1.
  11273 	DEFB	__subtract	;;	Y, abs(Y)-1.	range 0 to 1
  11274 	DEFB	__duplicate	;;	Y, Z, Z.
  11275 	DEFB	__greater_0	;;	Y, Z, (1/0).
  11276 
  11277 	DEFB	__st_mem_0	;;	store as possible sign 
  11278 				;;	for cosine function.
  11279 
  11280 	DEFB	__jump_true	;;
  11281 	DEFB	Z_PLUS <#Z_PLUS> - $	;;	with quadrants II and III
  11282 
  11283 ;	else the angle lies in quadrant I or IV and value Y is already correct.
  11284 
  11285 	DEFB	__delete	;;	Y	delete test value.
  11286 	DEFB	__end_calc	;;	Y.
  11287 
  11288 	RET			; return.	with Q1 and Q4 >>>
  11289 
  11290 ;	The branch was here with quadrants II (0 to 1) and III (1 to 0).
  11291 ;	Y will hold -2 to -1 if this is quadrant III.
  11292 
  11293 mark_1D35:
  11294 *Z_PLUS:*
  11295 	DEFB	__stk_one	;;	Y, Z, 1
  11296 	DEFB	__subtract	;;	Y, Z-1.	Q3 = 0 to -1
  11297 	DEFB	__exchange	;;	Z-1, Y.
  11298 	DEFB	__less_0	;;	Z-1, (1/0).
  11299 	DEFB	__jump_true	;;	Z-1.
  11300 	DEFB	YNEG <#YNEG> - $	;; 
  11301 				;;if angle in quadrant III
  11302 
  11303 ;	else angle is within quadrant II (-1 to 0)
  11304 
  11305 	DEFB	__negate	;	range +1 to 0
  11306 
  11307 
  11308 mark_1D3C:
  11309 *YNEG:*
  11310 	DEFB	__end_calc	;;	quadrants II and III correct.
  11311 
  11312 	RET			; return.
  11313 
  11314 
  11315 ------------------------------------------------------------------------
  11316 
  11317 ; THE *'COSINE'* FUNCTION
  11318 ------------------------------------------------------------------------
  11319 
  11320 ; (offset $1D: 'cos')
  11321 ;	Cosines are calculated as the sine of the opposite angle rectifying the 
  11322 ;	sign depending on the quadrant rules. 
  11323 ;
  11324 ;
  11325 ;	    /|
  11326 ;	 h /y|
  11327 ;	  /  |o
  11328 ;	 / x |
  11329 ;	/----|
  11330 ;	  a
  11331 ;
  11332 ;	The cosine of angle x is the adjacent side (a) divided by the hypotenuse 1.
  11333 ;	However if we examine angle y then a/h is the sine of that angle.
  11334 ;	Since angle x plus angle y equals a right-angle, we can find angle y by 
  11335 ;	subtracting angle x from pi/2.
  11336 ;	However it's just as easy to reduce the argument first and subtract the
  11337 ;	reduced argument from the value 1 (a reduced right-angle).
  11338 ;	It's even easier to subtract 1 from the angle and rectify the sign.
  11339 ;	In fact, after reducing the argument, the absolute value of the argument
  11340 ;	is used and rectified using the test result stored in mem-0 by 'get-argt'
  11341 ;	for that purpose.
  11342 
  11343 mark_1D3E:
  11344 *cos:*
  11345 	RST	_FP_CALC	;;	angle in radians.
  11346 	DEFB	__get_argt	;;	X	reduce -1 to +1
  11347 
  11348 	DEFB	__abs		;;	ABS X	0 to 1
  11349 	DEFB	__stk_one	;;	ABS X, 1.
  11350 	DEFB	__subtract	;;		now opposite angle 
  11351 				;;		though negative sign.
  11352 	DEFB	__get_mem_0	;;		fetch sign indicator.
  11353 	DEFB	__jump_true	;;
  11354 	DEFB	C_ENT <#C_ENT> - $	;;fwd to C_ENT
  11355 				;;forward to common code if in QII or QIII 
  11356 
  11357 
  11358 	DEFB	__negate	;;		else make positive.
  11359 	DEFB	__jump		;;
  11360 	DEFB	C_ENT <#C_ENT> - $	;;fwd to C_ENT
  11361 				;;with quadrants QI and QIV 
  11362 
  11363 ------------------------------------------------------------------------
  11364 
  11365 ; THE *'SINE'* FUNCTION
  11366 ------------------------------------------------------------------------
  11367 
  11368 ; (offset $1C: 'sin')
  11369 ;	This is a fundamental transcendental function from which others such as cos
  11370 ;	and tan are directly, or indirectly, derived.
  11371 ;	It uses the series generator to produce Chebyshev polynomials.
  11372 ;
  11373 ;
  11374 ;	    /|
  11375 ;	 1 / |
  11376 ;	  /  |x
  11377 ;	 /a  |
  11378 ;	/----|
  11379 ;	  y
  11380 ;
  11381 ;	The 'get-argt' function is designed to modify the angle and its sign 
  11382 ;	in line with the desired sine value and afterwards it can launch straight
  11383 ;	into common code.
  11384 
  11385 mark_1D49:
  11386 *sin:*
  11387 	RST	_FP_CALC	;;	angle in radians
  11388 	DEFB	__get_argt	;;	reduce - sign now correct.
  11389 
  11390 mark_1D4B:
  11391 *C_ENT:*
  11392 	DEFB	__duplicate	;;
  11393 	DEFB	__duplicate	;;
  11394 	DEFB	__multiply	;;
  11395 	DEFB	__duplicate	;;
  11396 	DEFB	__addition	;;
  11397 	DEFB	__stk_one	;;
  11398 	DEFB	__subtract	;;
  11399 
  11400 	DEFB	__series_06	;;
  11401 	DEFB	$14		;;Exponent: $64, Bytes: 1
  11402 	DEFB	$E6		;;(+00,+00,+00)
  11403 	DEFB	$5C		;;Exponent: $6C, Bytes: 2
  11404 	DEFB	$1F,$0B		;;(+00,+00)
  11405 	DEFB	$A3		;;Exponent: $73, Bytes: 3
  11406 	DEFB	$8F,$38,$EE	;;(+00)
  11407 	DEFB	$E9		;;Exponent: $79, Bytes: 4
  11408 	DEFB	$15,$63,$BB,$23 ;;
  11409 	DEFB	$EE		;;Exponent: $7E, Bytes: 4
  11410 	DEFB	$92,$0D,$CD,$ED ;;
  11411 	DEFB	$F1		;;Exponent: $81, Bytes: 4
  11412 	DEFB	$23,$5D,$1B,$EA ;;
  11413 
  11414 	DEFB	__multiply	;;
  11415 	DEFB	__end_calc	;;
  11416 
  11417 	RET			; return.
  11418 
  11419 
  11420 ------------------------------------------------------------------------
  11421 
  11422 ; THE *'TANGENT'* FUNCTION
  11423 ------------------------------------------------------------------------
  11424 
  11425 ; (offset $1E: 'tan')
  11426 ;
  11427 ;	Evaluates tangent x as	sin(x) / cos(x).
  11428 ;
  11429 ;
  11430 ;	    /|
  11431 ;	 h / |
  11432 ;	  /  |o
  11433 ;	 /x  |
  11434 ;	/----|
  11435 ;	   a
  11436 ;
  11437 ;	The tangent of angle x is the ratio of the length of the opposite side 
  11438 ;	divided by the length of the adjacent side. As the opposite length can 
  11439 ;	be calculates using sin(x) and the adjacent length using cos(x) then 
  11440 ;	the tangent can be defined in terms of the previous two functions.
  11441 
  11442 ;	Error 6 if the argument, in radians, is too close to one like pi/2
  11443 ;	which has an infinite tangent. e.g. PRINT TAN (PI/2)	evaluates as 1/0.
  11444 ;	Similarly PRINT TAN (3*PI/2), TAN (5*PI/2) etc.
  11445 
  11446 mark_1D6E:
  11447 *tan:*
  11448 	RST	_FP_CALC	;;	x.
  11449 	DEFB	__duplicate	;;	x, x.
  11450 	DEFB	__sin		;;	x, sin x.
  11451 	DEFB	__exchange	;;	sin x, x.
  11452 	DEFB	__cos		;;	sin x, cos x.
  11453 	DEFB	__division	;;	sin x/cos x (= tan x).
  11454 	DEFB	__end_calc	;;	tan x.
  11455 
  11456 	RET			; return.
  11457 
  11458 ------------------------------------------------------------------------
  11459 
  11460 ; THE *'ARCTAN'* FUNCTION
  11461 ------------------------------------------------------------------------
  11462 
  11463 ; (Offset $21: 'atn')
  11464 ;	The inverse tangent function with the result in radians.
  11465 ;	This is a fundamental transcendental function from which others such as
  11466 ;	asn and acs are directly, or indirectly, derived.
  11467 ;	It uses the series generator to produce Chebyshev polynomials.
  11468 
  11469 mark_1D76:
  11470 *atn:*
  11471 	LD	A,(HL)		; fetch exponent
  11472 	CP	$81		; compare to that for 'one'
  11473 	JR	C,SMALL <#SMALL>	; forward, if less
  11474 
  11475 	RST	_FP_CALC	;;		X.
  11476 	DEFB	__stk_one	;;
  11477 	DEFB	__negate	;;
  11478 	DEFB	__exchange	;;
  11479 	DEFB	__division	;;
  11480 	DEFB	__duplicate	;;
  11481 	DEFB	__less_0	;;
  11482 	DEFB	__stk_half_pi	;;
  11483 	DEFB	__exchange	;;
  11484 	DEFB	__jump_true	;;
  11485 	DEFB	CASES <#CASES> - $	;;
  11486 
  11487 	DEFB	__negate	;;
  11488 	DEFB	__jump		;;
  11489 	DEFB	CASES <#CASES> - $	;;
  11490 
  11491 ; ___
  11492 
  11493 mark_1D89:
  11494 *SMALL:*
  11495 	RST	_FP_CALC	;;
  11496 	DEFB	__stk_zero	;;
  11497 
  11498 mark_1D8B:
  11499 *CASES:*
  11500 	DEFB	__exchange	;;
  11501 	DEFB	__duplicate	;;
  11502 	DEFB	__duplicate	;;
  11503 	DEFB	__multiply	;;
  11504 	DEFB	__duplicate	;;
  11505 	DEFB	__addition	;;
  11506 	DEFB	__stk_one	;;
  11507 	DEFB	__subtract	;;
  11508 
  11509 	DEFB	__series_0C	;;
  11510 	DEFB	$10		;;Exponent: $60, Bytes: 1
  11511 	DEFB	$B2		;;(+00,+00,+00)
  11512 	DEFB	$13		;;Exponent: $63, Bytes: 1
  11513 	DEFB	$0E		;;(+00,+00,+00)
  11514 	DEFB	$55		;;Exponent: $65, Bytes: 2
  11515 	DEFB	$E4,$8D		;;(+00,+00)
  11516 	DEFB	$58		;;Exponent: $68, Bytes: 2
  11517 	DEFB	$39,$BC		;;(+00,+00)
  11518 	DEFB	$5B		;;Exponent: $6B, Bytes: 2
  11519 	DEFB	$98,$FD		;;(+00,+00)
  11520 	DEFB	$9E		;;Exponent: $6E, Bytes: 3
  11521 	DEFB	$00,$36,$75	;;(+00)
  11522 	DEFB	$A0		;;Exponent: $70, Bytes: 3
  11523 	DEFB	$DB,$E8,$B4	;;(+00)
  11524 	DEFB	$63		;;Exponent: $73, Bytes: 2
  11525 	DEFB	$42,$C4		;;(+00,+00)
  11526 	DEFB	$E6		;;Exponent: $76, Bytes: 4
  11527 	DEFB	$B5,$09,$36,$BE ;;
  11528 	DEFB	$E9		;;Exponent: $79, Bytes: 4
  11529 	DEFB	$36,$73,$1B,$5D ;;
  11530 	DEFB	$EC		;;Exponent: $7C, Bytes: 4
  11531 	DEFB	$D8,$DE,$63,$BE ;;
  11532 	DEFB	$F0		;;Exponent: $80, Bytes: 4
  11533 	DEFB	$61,$A1,$B3,$0C ;;
  11534 
  11535 	DEFB	__multiply	;;
  11536 	DEFB	__addition	;;
  11537 	DEFB	__end_calc	;;
  11538 
  11539 	RET			; return.
  11540 
  11541 
  11542 ------------------------------------------------------------------------
  11543 
  11544 ; THE *'ARCSIN'* FUNCTION
  11545 ------------------------------------------------------------------------
  11546 
  11547 ; (Offset $1F: 'asn')
  11548 ;	The inverse sine function with result in radians.
  11549 ;	Derived from arctan function above.
  11550 ;	Error A unless the argument is between -1 and +1 inclusive.
  11551 ;	Uses an adaptation of the formula asn(x) = atn(x/sqr(1-x*x))
  11552 ;
  11553 ;
  11554 ;		    /|
  11555 ;		   / |
  11556 ;		 1/  |x
  11557 ;		 /a  |
  11558 ;		/----|
  11559 ;		  y
  11560 ;
  11561 ;	e.g. We know the opposite side (x) and hypotenuse (1) 
  11562 ;	and we wish to find angle a in radians.
  11563 ;	We can derive length y by Pythagoras and then use ATN instead. 
  11564 ;	Since y*y + x*x = 1*1 (Pythagoras Theorem) then
  11565 ;	y=sqr(1-x*x)			- no need to multiply 1 by itself.
  11566 ;	So, asn(a) = atn(x/y)
  11567 ;	or more fully,
  11568 ;	asn(a) = atn(x/sqr(1-x*x))
  11569 
  11570 ;	Close but no cigar.
  11571 
  11572 ;	While PRINT ATN (x/SQR (1-x*x)) gives the same results as PRINT ASN x,
  11573 ;	it leads to division by zero when x is 1 or -1.
  11574 ;	To overcome this, 1 is added to y giving half the required angle and the 
  11575 ;	result is then doubled. 
  11576 ;	That is, PRINT ATN (x/(SQR (1-x*x) +1)) *2
  11577 ;
  11578 ;
  11579 ;	.            /|
  11580 ;	.          c/ |
  11581 ;	.          /1 |x
  11582 ;	. c	b /a  |
  11583 ;	---------/----|
  11584 ;	1	y
  11585 ;
  11586 ;	By creating an isosceles triangle with two equal sides of 1, angles c and 
  11587 ;	c are also equal. If b+c+d = 180 degrees and b+a = 180 degrees then c=a/2.
  11588 ;
  11589 ;	A value higher than 1 gives the required error as attempting to find	the
  11590 ;	square root of a negative number generates an error in Sinclair BASIC.
  11591 
  11592 mark_1DC4:
  11593 *asn:*
  11594 	RST	_FP_CALC	;;	x.
  11595 	DEFB	__duplicate	;;	x, x.
  11596 	DEFB	__duplicate	;;	x, x, x.
  11597 	DEFB	__multiply	;;	x, x*x.
  11598 	DEFB	__stk_one	;;	x, x*x, 1.
  11599 	DEFB	__subtract	;;	x, x*x-1.
  11600 	DEFB	__negate	;;	x, 1-x*x.
  11601 	DEFB	__sqr		;;	x, sqr(1-x*x) = y.
  11602 	DEFB	__stk_one	;;	x, y, 1.
  11603 	DEFB	__addition	;;	x, y+1.
  11604 	DEFB	__division	;;	x/y+1.
  11605 	DEFB	__atn		;;	a/2	(half the angle)
  11606 	DEFB	__duplicate	;;	a/2, a/2.
  11607 	DEFB	__addition	;;	a.
  11608 	DEFB	__end_calc	;;	a.
  11609 
  11610 	RET			; return.
  11611 
  11612 
  11613 ------------------------------------------------------------------------
  11614 
  11615 ; THE *'ARCCOS'* FUNCTION
  11616 ------------------------------------------------------------------------
  11617 
  11618 ; (Offset $20: 'acs')
  11619 ;	The inverse cosine function with the result in radians.
  11620 ;	Error A unless the argument is between -1 and +1.
  11621 ;	Result in range 0 to pi.
  11622 ;	Derived from asn above which is in turn derived from the preceding atn. It 
  11623 ;	could have been derived directly from atn using acs(x) = atn(sqr(1-x*x)/x).
  11624 ;	However, as sine and cosine are horizontal translations of each other,
  11625 ;	uses acs(x) = pi/2 - asn(x)
  11626 
  11627 ;	e.g. the arccosine of a known x value will give the required angle b in 
  11628 ;	radians.
  11629 ;	We know, from above, how to calculate the angle a using asn(x). 
  11630 ;	Since the three angles of any triangle add up to 180 degrees, or pi radians,
  11631 ;	and the largest angle in this case is a right-angle (pi/2 radians), then
  11632 ;	we can calculate angle b as pi/2 (both angles) minus asn(x) (angle a).
  11633 ; 
  11634 ;;
  11635 ;	    /|
  11636 ;	 1 /b|
  11637 ;	  /  |x
  11638 ;	 /a  |
  11639 ;	/----|
  11640 ;	  y
  11641 
  11642 mark_1DD4:
  11643 *acs:*
  11644 	RST	_FP_CALC	;;	x.
  11645 	DEFB	__asn		;;	asn(x).
  11646 	DEFB	__stk_half_pi	;;	asn(x), pi/2.
  11647 	DEFB	__subtract	;;	asn(x) - pi/2.
  11648 	DEFB	__negate	;;	pi/2 - asn(x) = acs(x).
  11649 	DEFB	__end_calc	;;	acs(x)
  11650 
  11651 	RET			; return.
  11652 
  11653 #if ORIGINAL
  11654 ------------------------------------------------------------------------
  11655 
  11656 ; THE *'SQUARE ROOT'* FUNCTION
  11657 ------------------------------------------------------------------------
  11658 
  11659 ; (Offset $25: 'sqr')
  11660 ;	Error A if argument is negative.
  11661 ;	This routine is remarkable for its brevity - 7 bytes.
  11662 ;
  11663 ;	The ZX81 code was originally 9K and various techniques had to be
  11664 ;	used to shoe-horn it into an 8K Rom chip.
  11665 
  11666 ; This routine uses Napier's method for calculating square roots which was 
  11667 ; devised in 1614 and calculates the value as EXP (LN 'x' * 0.5).
  11668 ;
  11669 ; This is a little on the slow side as it involves two polynomial series.
  11670 ; A series of 12 for LN and a series of 8 for EXP.
  11671 ; This was of no concern to John Napier since his tables were 'compiled forever'.
  11672 
  11673 mark_1DDB:
  11674 *sqr:*
  11675 	RST	_FP_CALC	;;	x.
  11676 	DEFB	__duplicate	;;	x, x.
  11677 	DEFB	__not		;;	x, 1/0
  11678 	DEFB	__jump_true	;;	x, (1/0).
  11679 	DEFB	LAST <#LAST> - $	;; exit if argument zero
  11680 				;;		with zero result.
  11681 
  11682 ;	else continue to calculate as x ** .5
  11683 
  11684 	DEFB	__stk_half	;;	x, .5.
  11685 	DEFB	__end_calc	;;	x, .5.
  11686 
  11687 #endif
  11688 
  11689 ------------------------------------------------------------------------
  11690 
  11691 ; THE *'EXPONENTIATION'* OPERATION
  11692 ------------------------------------------------------------------------
  11693 
  11694 ; (Offset $06: 'to_power')
  11695 ;	This raises the first number X to the power of the second number Y.
  11696 ;	As with the ZX80,
  11697 ;	0 ** 0 = 1
  11698 ;	0 ** +n = 0
  11699 ;	0 ** -n = arithmetic overflow.
  11700 
  11701 mark_1DE2:
  11702 *to_power:*
  11703 	RST	_FP_CALC	;;	X,Y.
  11704 	DEFB	__exchange	;;	Y,X.
  11705 	DEFB	__duplicate	;;	Y,X,X.
  11706 	DEFB	__not		;;	Y,X,(1/0).
  11707 	DEFB	__jump_true	;;
  11708 	DEFB	XISO <#XISO> - $	;;forward to XISO if X is zero.
  11709 
  11710 ;	else X is non-zero. function 'ln' will catch a negative value of X.
  11711 
  11712 	DEFB	__ln		;;	Y, LN X.
  11713 	DEFB	__multiply	;;	Y * LN X
  11714 	DEFB	__end_calc	;;
  11715 
  11716 	JP	exp <#exp>		; jump back to EXP routine.	->
  11717 
  11718 ; ___
  11719 
  11720 ;	These routines form the three simple results when the number is zero.
  11721 ;	begin by deleting the known zero to leave Y the power factor.
  11722 
  11723 mark_1DEE:
  11724 *XISO:*
  11725 	DEFB	__delete	;;	Y.
  11726 	DEFB	__duplicate	;;	Y, Y.
  11727 	DEFB	__not		;;	Y, (1/0).
  11728 	DEFB	__jump_true	;;
  11729 	DEFB	ONE <#ONE> - $		;; if Y is zero.
  11730 
  11731 ;	the power factor is not zero. If negative then an error exists.
  11732 
  11733 	DEFB	__stk_zero	;;	Y, 0.
  11734 	DEFB	__exchange	;;	0, Y.
  11735 	DEFB	__greater_0	;;	0, (1/0).
  11736 	DEFB	__jump_true	;;	0
  11737 	DEFB	LAST <#LAST> - $	;; if Y was any positive 
  11738 				;; number.
  11739 
  11740 ;	else force division by zero thereby raising an Arithmetic overflow error.
  11741 ;	There are some one and two-byte alternatives but perhaps the most formal
  11742 ;	might have been to use end_calc; rst 08; defb 05.
  11743 
  11744 ;	#if ORIGINAL
  11745 
  11746 ; the SG ROM seems to want it the old way!
  11747 #if 1
  11748 	DEFB	__stk_one	;;	0, 1.
  11749 	DEFB	__exchange	;;	1, 0.
  11750 	DEFB	__division	;;	1/0	>> error 
  11751 #else
  11752 	DEFB	$34		;+ end-calc
  11753 *REPORT_6c*
  11754 	RST	08H		;+ ERROR-1
  11755 	DEFB	$05		;+ Error Report: Number too big
  11756 #endif
  11757 
  11758 
  11759 ; ___
  11760 
  11761 mark_1DFB:
  11762 *ONE:*
  11763 	DEFB	__delete	;;	.
  11764 	DEFB	__stk_one	;;	1.
  11765 
  11766 mark_1DFD:
  11767 *LAST:*
  11768 	DEFB	__end_calc	;;		last value 1 or 0.
  11769 
  11770 	RET			; return.
  11771 
  11772 ------------------------------------------------------------------------
  11773 
  11774 ; THE *'SPARE LOCATIONS'*
  11775 ------------------------------------------------------------------------
  11776 
  11777 *SPARE:*
  11778 
  11779 #if ORIGINAL
  11780 mark_1DFF:
  11781 	DEFB	$FF		; That's all folks.
  11782 #else
  11783 mark_1DFE:
  11784 *L1DFE:*
  11785 
  11786 ;;	DEFB	$FF, $FF	; Two spare bytes.
  11787 	DEFB	$00, $00	; Two spare bytes (as per the Shoulders of Giants ROM)
  11788 #endif
  11789 
  11790 
  11791 ------------------------------------------------------------------------
  11792 
  11793 ; THE *'ZX81 CHARACTER SET'*
  11794 ------------------------------------------------------------------------
  11795 
  11796 
  11797 mark_1E00:
  11798 *char_set*	; - begins with space character.
  11799 
  11800 ; $00 - *Character: ' '*		CHR$(0)
  11801 
  11802 	DEFB	%00000000
  11803 	DEFB	%00000000
  11804 	DEFB	%00000000
  11805 	DEFB	%00000000
  11806 	DEFB	%00000000
  11807 	DEFB	%00000000
  11808 	DEFB	%00000000
  11809 	DEFB	%00000000
  11810 
  11811 ; $01 - *Character: mosaic*	CHR$(1)
  11812 
  11813 	DEFB	%*1111*0000
  11814 	DEFB	%*1111*0000
  11815 	DEFB	%*1111*0000
  11816 	DEFB	%*1111*0000
  11817 	DEFB	%00000000
  11818 	DEFB	%00000000
  11819 	DEFB	%00000000
  11820 	DEFB	%00000000
  11821 
  11822 
  11823 ; $02 - *Character: mosaic*	CHR$(2)
  11824 
  11825 	DEFB	%0000*1111*
  11826 	DEFB	%0000*1111*
  11827 	DEFB	%0000*1111*
  11828 	DEFB	%0000*1111*
  11829 	DEFB	%00000000
  11830 	DEFB	%00000000
  11831 	DEFB	%00000000
  11832 	DEFB	%00000000
  11833 
  11834 
  11835 ; $03 - *Character: mosaic*	CHR$(3)
  11836 
  11837 	DEFB	%*11111111*
  11838 	DEFB	%*11111111*
  11839 	DEFB	%*11111111*
  11840 	DEFB	%*11111111*
  11841 	DEFB	%00000000
  11842 	DEFB	%00000000
  11843 	DEFB	%00000000
  11844 	DEFB	%00000000
  11845 
  11846 ; $04 - *Character: mosaic*	CHR$(4)
  11847 
  11848 	DEFB	%00000000
  11849 	DEFB	%00000000
  11850 	DEFB	%00000000
  11851 	DEFB	%00000000
  11852 	DEFB	%*1111*0000
  11853 	DEFB	%*1111*0000
  11854 	DEFB	%*1111*0000
  11855 	DEFB	%*1111*0000
  11856 
  11857 ; $05 - *Character: mosaic*	CHR$(5)
  11858 
  11859 	DEFB	%*1111*0000
  11860 	DEFB	%*1111*0000
  11861 	DEFB	%*1111*0000
  11862 	DEFB	%*1111*0000
  11863 	DEFB	%*1111*0000
  11864 	DEFB	%*1111*0000
  11865 	DEFB	%*1111*0000
  11866 	DEFB	%*1111*0000
  11867 
  11868 ; $06 - *Character: mosaic*	CHR$(6)
  11869 
  11870 	DEFB	%0000*1111*
  11871 	DEFB	%0000*1111*
  11872 	DEFB	%0000*1111*
  11873 	DEFB	%0000*1111*
  11874 	DEFB	%*1111*0000
  11875 	DEFB	%*1111*0000
  11876 	DEFB	%*1111*0000
  11877 	DEFB	%*1111*0000
  11878 
  11879 ; $07 - *Character: mosaic*	CHR$(7)
  11880 
  11881 	DEFB	%*11111111*
  11882 	DEFB	%*11111111*
  11883 	DEFB	%*11111111*
  11884 	DEFB	%*11111111*
  11885 	DEFB	%*1111*0000
  11886 	DEFB	%*1111*0000
  11887 	DEFB	%*1111*0000
  11888 	DEFB	%*1111*0000
  11889 
  11890 ; $08 - *Character: mosaic*	CHR$(8)
  11891 
  11892 	DEFB	%*1*0*1*0*1*0*1*0
  11893 	DEFB	%0*1*0*1*0*1*0*1*
  11894 	DEFB	%*1*0*1*0*1*0*1*0
  11895 	DEFB	%0*1*0*1*0*1*0*1*
  11896 	DEFB	%*1*0*1*0*1*0*1*0
  11897 	DEFB	%0*1*0*1*0*1*0*1*
  11898 	DEFB	%*1*0*1*0*1*0*1*0
  11899 	DEFB	%0*1*0*1*0*1*0*1*
  11900 ; $09 - *Character: mosaic*	CHR$(9)
  11901 
  11902 	DEFB	%00000000
  11903 	DEFB	%00000000
  11904 	DEFB	%00000000
  11905 	DEFB	%00000000
  11906 	DEFB	%*1*0*1*0*1*0*1*0
  11907 	DEFB	%0*1*0*1*0*1*0*1*
  11908 	DEFB	%*1*0*1*0*1*0*1*0
  11909 	DEFB	%0*1*0*1*0*1*0*1*
  11910 ; $0A - *Character: mosaic*	CHR$(10)
  11911 
  11912 	DEFB	%*1*0*1*0*1*0*1*0
  11913 	DEFB	%0*1*0*1*0*1*0*1*
  11914 	DEFB	%*1*0*1*0*1*0*1*0
  11915 	DEFB	%0*1*0*1*0*1*0*1*
  11916 	DEFB	%00000000
  11917 	DEFB	%00000000
  11918 	DEFB	%00000000
  11919 	DEFB	%00000000
  11920 
  11921 ; $0B - *Character: '"'*		CHR$(11)
  11922 
  11923 	DEFB	%00000000
  11924 	DEFB	%00*1*00*1*00
  11925 	DEFB	%00*1*00*1*00
  11926 	DEFB	%00000000
  11927 	DEFB	%00000000
  11928 	DEFB	%00000000
  11929 	DEFB	%00000000
  11930 	DEFB	%00000000
  11931 
  11932 ; $0C - *Character:*	£		CHR$(12)
  11933 
  11934 	DEFB	%00000000
  11935 	DEFB	%000*111*00
  11936 	DEFB	%00*1*000*1*0
  11937 	DEFB	%0*1111*000
  11938 	DEFB	%00*1*00000
  11939 	DEFB	%00*1*00000
  11940 	DEFB	%0*111111*0
  11941 	DEFB	%00000000
  11942 
  11943 ; $0D - *Character: '$'*		CHR$(13)
  11944 
  11945 	DEFB	%00000000
  11946 	DEFB	%0000*1*000
  11947 	DEFB	%00*11111*0
  11948 	DEFB	%00*1*0*1*000
  11949 	DEFB	%00*11111*0
  11950 	DEFB	%0000*1*0*1*0
  11951 	DEFB	%00*11111*0
  11952 	DEFB	%0000*1*000
  11953 
  11954 ; $0E - *Character: ':'*		CHR$(14)
  11955 
  11956 	DEFB	%00000000
  11957 	DEFB	%00000000
  11958 	DEFB	%00000000
  11959 	DEFB	%000*1*0000
  11960 	DEFB	%00000000
  11961 	DEFB	%00000000
  11962 	DEFB	%000*1*0000
  11963 	DEFB	%00000000
  11964 
  11965 ; $0F - *Character: '?'*		CHR$(15)
  11966 
  11967 	DEFB	%00000000
  11968 	DEFB	%00*1111*00
  11969 	DEFB	%0*1*0000*1*0
  11970 	DEFB	%00000*1*00
  11971 	DEFB	%0000*1*000
  11972 	DEFB	%00000000
  11973 	DEFB	%0000*1*000
  11974 	DEFB	%00000000
  11975 
  11976 ; $10 - *Character: '('*		CHR$(16)
  11977 
  11978 	DEFB	%00000000
  11979 	DEFB	%00000*1*00
  11980 	DEFB	%0000*1*000
  11981 	DEFB	%0000*1*000
  11982 	DEFB	%0000*1*000
  11983 	DEFB	%0000*1*000
  11984 	DEFB	%00000*1*00
  11985 	DEFB	%00000000
  11986 
  11987 ; $11 - *Character: ')'*		CHR$(17)
  11988 
  11989 	DEFB	%00000000
  11990 	DEFB	%00*1*00000
  11991 	DEFB	%000*1*0000
  11992 	DEFB	%000*1*0000
  11993 	DEFB	%000*1*0000
  11994 	DEFB	%000*1*0000
  11995 	DEFB	%00*1*00000
  11996 	DEFB	%00000000
  11997 
  11998 ; $12 - *Character: '>'*		CHR$(18)
  11999 
  12000 	DEFB	%00000000
  12001 	DEFB	%00000000
  12002 	DEFB	%000*1*0000
  12003 	DEFB	%0000*1*000
  12004 	DEFB	%00000*1*00
  12005 	DEFB	%0000*1*000
  12006 	DEFB	%000*1*0000
  12007 	DEFB	%00000000
  12008 
  12009 ; $13 - *Character: '<'*		CHR$(19)
  12010 
  12011 	DEFB	%00000000
  12012 	DEFB	%00000000
  12013 	DEFB	%00000*1*00
  12014 	DEFB	%0000*1*000
  12015 	DEFB	%000*1*0000
  12016 	DEFB	%0000*1*000
  12017 	DEFB	%00000*1*00
  12018 	DEFB	%00000000
  12019 
  12020 ; $14 - *Character: '='*		CHR$(20)
  12021 
  12022 	DEFB	%00000000
  12023 	DEFB	%00000000
  12024 	DEFB	%00000000
  12025 	DEFB	%00*11111*0
  12026 	DEFB	%00000000
  12027 	DEFB	%00*11111*0
  12028 	DEFB	%00000000
  12029 	DEFB	%00000000
  12030 
  12031 ; $15 - *Character: '+'*		CHR$(21)
  12032 
  12033 	DEFB	%00000000
  12034 	DEFB	%00000000
  12035 	DEFB	%0000*1*000
  12036 	DEFB	%0000*1*000
  12037 	DEFB	%00*11111*0
  12038 	DEFB	%0000*1*000
  12039 	DEFB	%0000*1*000
  12040 	DEFB	%00000000
  12041 
  12042 ; $16 - *Character: '-'*		CHR$(22)
  12043 
  12044 	DEFB	%00000000
  12045 	DEFB	%00000000
  12046 	DEFB	%00000000
  12047 	DEFB	%00000000
  12048 	DEFB	%00*11111*0
  12049 	DEFB	%00000000
  12050 	DEFB	%00000000
  12051 	DEFB	%00000000
  12052 
  12053 ; $17 - *Character: '*'*		CHR$(23)
  12054 
  12055 	DEFB	%00000000
  12056 	DEFB	%00000000
  12057 	DEFB	%000*1*0*1*00
  12058 	DEFB	%0000*1*000
  12059 	DEFB	%00*11111*0
  12060 	DEFB	%0000*1*000
  12061 	DEFB	%000*1*0*1*00
  12062 	DEFB	%00000000
  12063 
  12064 ; $18 - *Character: '/'*		CHR$(24)
  12065 
  12066 	DEFB	%00000000
  12067 	DEFB	%00000000
  12068 	DEFB	%000000*1*0
  12069 	DEFB	%00000*1*00
  12070 	DEFB	%0000*1*000
  12071 	DEFB	%000*1*0000
  12072 	DEFB	%00*1*00000
  12073 	DEFB	%00000000
  12074 
  12075 ; $19 - *Character: ';'*		CHR$(25)
  12076 
  12077 	DEFB	%00000000
  12078 	DEFB	%00000000
  12079 	DEFB	%000*1*0000
  12080 	DEFB	%00000000
  12081 	DEFB	%00000000
  12082 	DEFB	%000*1*0000
  12083 	DEFB	%000*1*0000
  12084 	DEFB	%00*1*00000
  12085 
  12086 ; $1A - *Character: ','*		CHR$(26)
  12087 
  12088 	DEFB	%00000000
  12089 	DEFB	%00000000
  12090 	DEFB	%00000000
  12091 	DEFB	%00000000
  12092 	DEFB	%00000000
  12093 	DEFB	%0000*1*000
  12094 	DEFB	%0000*1*000
  12095 	DEFB	%000*1*0000
  12096 
  12097 ; $1B - *Character: '"'*		CHR$(27)
  12098 
  12099 	DEFB	%00000000
  12100 	DEFB	%00000000
  12101 	DEFB	%00000000
  12102 	DEFB	%00000000
  12103 	DEFB	%00000000
  12104 	DEFB	%000*11*000
  12105 	DEFB	%000*11*000
  12106 	DEFB	%00000000
  12107 
  12108 ; $1C - *Character: '0'*		CHR$(28)
  12109 
  12110 	DEFB	%00000000
  12111 	DEFB	%00*1111*00
  12112 	DEFB	%0*1*000*11*0
  12113 	DEFB	%0*1*00*1*0*1*0
  12114 	DEFB	%0*1*0*1*00*1*0
  12115 	DEFB	%0*11*000*1*0
  12116 	DEFB	%00*1111*00
  12117 	DEFB	%00000000
  12118 
  12119 ; $1D - *Character: '1'*		CHR$(29)
  12120 
  12121 	DEFB	%00000000
  12122 	DEFB	%000*11*000
  12123 	DEFB	%00*1*0*1*000
  12124 	DEFB	%0000*1*000
  12125 	DEFB	%0000*1*000
  12126 	DEFB	%0000*1*000
  12127 	DEFB	%00*11111*0
  12128 	DEFB	%00000000
  12129 
  12130 ; $1E - *Character: '2'*		CHR$(30)
  12131 
  12132 	DEFB	%00000000
  12133 	DEFB	%00*1111*00
  12134 	DEFB	%0*1*0000*1*0
  12135 	DEFB	%000000*1*0
  12136 	DEFB	%00*1111*00
  12137 	DEFB	%0*1*000000
  12138 	DEFB	%0*111111*0
  12139 	DEFB	%00000000
  12140 
  12141 ; $1F - *Character: '3'*		CHR$(31)
  12142 
  12143 	DEFB	%00000000
  12144 	DEFB	%00*1111*00
  12145 	DEFB	%0*1*0000*1*0
  12146 	DEFB	%0000*11*00
  12147 	DEFB	%000000*1*0
  12148 	DEFB	%0*1*0000*1*0
  12149 	DEFB	%00*1111*00
  12150 	DEFB	%00000000
  12151 
  12152 ; $20 - *Character: '4'*		CHR$(32)
  12153 
  12154 	DEFB	%00000000
  12155 	DEFB	%0000*1*000
  12156 	DEFB	%000*11*000
  12157 	DEFB	%00*1*0*1*000
  12158 	DEFB	%0*1*00*1*000
  12159 	DEFB	%0*111111*0
  12160 	DEFB	%0000*1*000
  12161 	DEFB	%00000000
  12162 
  12163 ; $21 - *Character: '5'*		CHR$(33)
  12164 
  12165 	DEFB	%00000000
  12166 	DEFB	%0*111111*0
  12167 	DEFB	%0*1*000000
  12168 	DEFB	%0*11111*00
  12169 	DEFB	%000000*1*0
  12170 	DEFB	%0*1*0000*1*0
  12171 	DEFB	%00*1111*00
  12172 	DEFB	%00000000
  12173 
  12174 ; $22 - *Character: '6'*		CHR$(34)
  12175 
  12176 	DEFB	%00000000
  12177 	DEFB	%00*1111*00
  12178 	DEFB	%0*1*000000
  12179 	DEFB	%0*11111*00
  12180 	DEFB	%0*1*0000*1*0
  12181 	DEFB	%0*1*0000*1*0
  12182 	DEFB	%00*1111*00
  12183 	DEFB	%00000000
  12184 
  12185 ; $23 - *Character: '7'*		CHR$(35)
  12186 
  12187 	DEFB	%00000000
  12188 	DEFB	%0*111111*0
  12189 	DEFB	%000000*1*0
  12190 	DEFB	%00000*1*00
  12191 	DEFB	%0000*1*000
  12192 	DEFB	%000*1*0000
  12193 	DEFB	%000*1*0000
  12194 	DEFB	%00000000
  12195 
  12196 ; $24 - *Character: '8'*		CHR$(36)
  12197 
  12198 	DEFB	%00000000
  12199 	DEFB	%00*1111*00
  12200 	DEFB	%0*1*0000*1*0
  12201 	DEFB	%00*1111*00
  12202 	DEFB	%0*1*0000*1*0
  12203 	DEFB	%0*1*0000*1*0
  12204 	DEFB	%00*1111*00
  12205 	DEFB	%00000000
  12206 
  12207 ; $25 - *Character: '9'*		CHR$(37)
  12208 
  12209 	DEFB	%00000000
  12210 	DEFB	%00*1111*00
  12211 	DEFB	%0*1*0000*1*0
  12212 	DEFB	%0*1*0000*1*0
  12213 	DEFB	%00*11111*0
  12214 	DEFB	%000000*1*0
  12215 	DEFB	%00*1111*00
  12216 	DEFB	%00000000
  12217 
  12218 ; $26 - *Character: 'A'*		CHR$(38)
  12219 
  12220 	DEFB	%00000000
  12221 	DEFB	%00*1111*00
  12222 	DEFB	%0*1*0000*1*0
  12223 	DEFB	%0*1*0000*1*0
  12224 	DEFB	%0*111111*0
  12225 	DEFB	%0*1*0000*1*0
  12226 	DEFB	%0*1*0000*1*0
  12227 	DEFB	%00000000
  12228 
  12229 ; $27 - *Character: 'B'*		CHR$(39)
  12230 
  12231 	DEFB	%00000000
  12232 	DEFB	%0*11111*00
  12233 	DEFB	%0*1*0000*1*0
  12234 	DEFB	%0*11111*00
  12235 	DEFB	%0*1*0000*1*0
  12236 	DEFB	%0*1*0000*1*0
  12237 	DEFB	%0*11111*00
  12238 	DEFB	%00000000
  12239 
  12240 ; $28 - *Character: 'C'*		CHR$(40)
  12241 
  12242 	DEFB	%00000000
  12243 	DEFB	%00*1111*00
  12244 	DEFB	%0*1*0000*1*0
  12245 	DEFB	%0*1*000000
  12246 	DEFB	%0*1*000000
  12247 	DEFB	%0*1*0000*1*0
  12248 	DEFB	%00*1111*00
  12249 	DEFB	%00000000
  12250 
  12251 ; $29 - *Character: 'D'*		CHR$(41)
  12252 
  12253 	DEFB	%00000000
  12254 	DEFB	%0*1111*000
  12255 	DEFB	%0*1*000*1*00
  12256 	DEFB	%0*1*0000*1*0
  12257 	DEFB	%0*1*0000*1*0
  12258 	DEFB	%0*1*000*1*00
  12259 	DEFB	%0*1111*000
  12260 	DEFB	%00000000
  12261 
  12262 ; $2A - *Character: 'E'*		CHR$(42)
  12263 
  12264 	DEFB	%00000000
  12265 	DEFB	%0*111111*0
  12266 	DEFB	%0*1*000000
  12267 	DEFB	%0*11111*00
  12268 	DEFB	%0*1*000000
  12269 	DEFB	%0*1*000000
  12270 	DEFB	%0*111111*0
  12271 	DEFB	%00000000
  12272 
  12273 ; $2B - *Character: 'F'*		CHR$(43)
  12274 
  12275 	DEFB	%00000000
  12276 	DEFB	%0*111111*0
  12277 	DEFB	%0*1*000000
  12278 	DEFB	%0*11111*00
  12279 	DEFB	%0*1*000000
  12280 	DEFB	%0*1*000000
  12281 	DEFB	%0*1*000000
  12282 	DEFB	%00000000
  12283 
  12284 ; $2C - *Character: 'G'*		CHR$(44)
  12285 
  12286 	DEFB	%00000000
  12287 	DEFB	%00*1111*00
  12288 	DEFB	%0*1*0000*1*0
  12289 	DEFB	%0*1*000000
  12290 	DEFB	%0*1*00*111*0
  12291 	DEFB	%0*1*0000*1*0
  12292 	DEFB	%00*1111*00
  12293 	DEFB	%00000000
  12294 
  12295 ; $2D - *Character: 'H'*		CHR$(45)
  12296 
  12297 	DEFB	%00000000
  12298 	DEFB	%0*1*0000*1*0
  12299 	DEFB	%0*1*0000*1*0
  12300 	DEFB	%0*111111*0
  12301 	DEFB	%0*1*0000*1*0
  12302 	DEFB	%0*1*0000*1*0
  12303 	DEFB	%0*1*0000*1*0
  12304 	DEFB	%00000000
  12305 
  12306 ; $2E - *Character: 'I'*		CHR$(46)
  12307 
  12308 	DEFB	%00000000
  12309 	DEFB	%00*11111*0
  12310 	DEFB	%0000*1*000
  12311 	DEFB	%0000*1*000
  12312 	DEFB	%0000*1*000
  12313 	DEFB	%0000*1*000
  12314 	DEFB	%00*11111*0
  12315 	DEFB	%00000000
  12316 
  12317 ; $2F - *Character: 'J'*		CHR$(47)
  12318 
  12319 	DEFB	%00000000
  12320 	DEFB	%000000*1*0
  12321 	DEFB	%000000*1*0
  12322 	DEFB	%000000*1*0
  12323 	DEFB	%0*1*0000*1*0
  12324 	DEFB	%0*1*0000*1*0
  12325 	DEFB	%00*1111*00
  12326 	DEFB	%00000000
  12327 
  12328 ; $30 - *Character: 'K'*		CHR$(48)
  12329 
  12330 	DEFB	%00000000
  12331 	DEFB	%0*1*000*1*00
  12332 	DEFB	%0*1*00*1*000
  12333 	DEFB	%0*111*0000
  12334 	DEFB	%0*1*00*1*000
  12335 	DEFB	%0*1*000*1*00
  12336 	DEFB	%0*1*0000*1*0
  12337 	DEFB	%00000000
  12338 
  12339 ; $31 - *Character: 'L'*		CHR$(49)
  12340 
  12341 	DEFB	%00000000
  12342 	DEFB	%0*1*000000
  12343 	DEFB	%0*1*000000
  12344 	DEFB	%0*1*000000
  12345 	DEFB	%0*1*000000
  12346 	DEFB	%0*1*000000
  12347 	DEFB	%0*111111*0
  12348 	DEFB	%00000000
  12349 
  12350 ; $32 - *Character: 'M'*		CHR$(50)
  12351 
  12352 	DEFB	%00000000
  12353 	DEFB	%0*1*0000*1*0
  12354 	DEFB	%0*11*00*11*0
  12355 	DEFB	%0*1*0*11*0*1*0
  12356 	DEFB	%0*1*0000*1*0
  12357 	DEFB	%0*1*0000*1*0
  12358 	DEFB	%0*1*0000*1*0
  12359 	DEFB	%00000000
  12360 
  12361 ; $33 - *Character: 'N'*		CHR$(51)
  12362 
  12363 	DEFB	%00000000
  12364 	DEFB	%0*1*0000*1*0
  12365 	DEFB	%0*11*000*1*0
  12366 	DEFB	%0*1*0*1*00*1*0
  12367 	DEFB	%0*1*00*1*0*1*0
  12368 	DEFB	%0*1*000*11*0
  12369 	DEFB	%0*1*0000*1*0
  12370 	DEFB	%00000000
  12371 
  12372 ; $34 - *Character: 'O'*		CHR$(52)
  12373 
  12374 	DEFB	%00000000
  12375 	DEFB	%00*1111*00
  12376 	DEFB	%0*1*0000*1*0
  12377 	DEFB	%0*1*0000*1*0
  12378 	DEFB	%0*1*0000*1*0
  12379 	DEFB	%0*1*0000*1*0
  12380 	DEFB	%00*1111*00
  12381 	DEFB	%00000000
  12382 
  12383 ; $35 - *Character: 'P'*		CHR$(53)
  12384 
  12385 	DEFB	%00000000
  12386 	DEFB	%0*11111*00
  12387 	DEFB	%0*1*0000*1*0
  12388 	DEFB	%0*1*0000*1*0
  12389 	DEFB	%0*11111*00
  12390 	DEFB	%0*1*000000
  12391 	DEFB	%0*1*000000
  12392 	DEFB	%00000000
  12393 
  12394 ; $36 - *Character: 'Q'*		CHR$(54)
  12395 
  12396 	DEFB	%00000000
  12397 	DEFB	%00*1111*00
  12398 	DEFB	%0*1*0000*1*0
  12399 	DEFB	%0*1*0000*1*0
  12400 	DEFB	%0*1*0*1*00*1*0
  12401 	DEFB	%0*1*00*1*0*1*0
  12402 	DEFB	%00*1111*00
  12403 	DEFB	%00000000
  12404 
  12405 ; $37 - *Character: 'R'*		CHR$(55)
  12406 
  12407 	DEFB	%00000000
  12408 	DEFB	%0*11111*00
  12409 	DEFB	%0*1*0000*1*0
  12410 	DEFB	%0*1*0000*1*0
  12411 	DEFB	%0*11111*00
  12412 	DEFB	%0*1*000*1*00
  12413 	DEFB	%0*1*0000*1*0
  12414 	DEFB	%00000000
  12415 
  12416 ; $38 - *Character: 'S'*		CHR$(56)
  12417 
  12418 	DEFB	%00000000
  12419 	DEFB	%00*1111*00
  12420 	DEFB	%0*1*000000
  12421 	DEFB	%00*1111*00
  12422 	DEFB	%000000*1*0
  12423 	DEFB	%0*1*0000*1*0
  12424 	DEFB	%00*1111*00
  12425 	DEFB	%00000000
  12426 
  12427 ; $39 - *Character: 'T'*		CHR$(57)
  12428 
  12429 	DEFB	%00000000
  12430 	DEFB	%*1111111*0
  12431 	DEFB	%000*1*0000
  12432 	DEFB	%000*1*0000
  12433 	DEFB	%000*1*0000
  12434 	DEFB	%000*1*0000
  12435 	DEFB	%000*1*0000
  12436 	DEFB	%00000000
  12437 
  12438 ; $3A - *Character: 'U'*		CHR$(58)
  12439 
  12440 	DEFB	%00000000
  12441 	DEFB	%0*1*0000*1*0
  12442 	DEFB	%0*1*0000*1*0
  12443 	DEFB	%0*1*0000*1*0
  12444 	DEFB	%0*1*0000*1*0
  12445 	DEFB	%0*1*0000*1*0
  12446 	DEFB	%00*1111*00
  12447 	DEFB	%00000000
  12448 
  12449 ; $3B - *Character: 'V'*		CHR$(59)
  12450 
  12451 	DEFB	%00000000
  12452 	DEFB	%0*1*0000*1*0
  12453 	DEFB	%0*1*0000*1*0
  12454 	DEFB	%0*1*0000*1*0
  12455 	DEFB	%0*1*0000*1*0
  12456 	DEFB	%00*1*00*1*00
  12457 	DEFB	%000*11*000
  12458 	DEFB	%00000000
  12459 
  12460 ; $3C - *Character: 'W'*		CHR$(60)
  12461 
  12462 	DEFB	%00000000
  12463 	DEFB	%0*1*0000*1*0
  12464 	DEFB	%0*1*0000*1*0
  12465 	DEFB	%0*1*0000*1*0
  12466 	DEFB	%0*1*0000*1*0
  12467 	DEFB	%0*1*0*11*0*1*0
  12468 	DEFB	%00*1*00*1*00
  12469 	DEFB	%00000000
  12470 
  12471 ; $3D - *Character: 'X'*		CHR$(61)
  12472 
  12473 	DEFB	%00000000
  12474 	DEFB	%0*1*0000*1*0
  12475 	DEFB	%00*1*00*1*00
  12476 	DEFB	%000*11*000
  12477 	DEFB	%000*11*000
  12478 	DEFB	%00*1*00*1*00
  12479 	DEFB	%0*1*0000*1*0
  12480 	DEFB	%00000000
  12481 
  12482 ; $3E - *Character: 'Y'*		CHR$(62)
  12483 
  12484 	DEFB	%00000000
  12485 	DEFB	%*1*00000*1*0
  12486 	DEFB	%0*1*000*1*00
  12487 	DEFB	%00*1*0*1*000
  12488 	DEFB	%000*1*0000
  12489 	DEFB	%000*1*0000
  12490 	DEFB	%000*1*0000
  12491 	DEFB	%00000000
  12492 
  12493 ; $3F - *Character: 'Z'*		CHR$(63)
  12494 
  12495 	DEFB	%00000000
  12496 	DEFB	%0*111111*0
  12497 	DEFB	%00000*1*00
  12498 	DEFB	%0000*1*000
  12499 	DEFB	%000*1*0000
  12500 	DEFB	%00*1*00000
  12501 	DEFB	%0*111111*0
  12502 	DEFB	%00000000
  12503 
  12504 
  12505 ;	.END				;TASM assembler instruction.
  12506 
  12507 
  12508 
  12509 ;
  12510 ; This marks the end of the ZX81 ROM.
  12511 ;
  12512 ; As a bonus feature, I will now include the code for
  12513 ; the G007 graphics board and
  12514 ; the ZX81 monitor
  12515 ;
  12516 ; The 8K space divides into four 2K spaces like so:
  12517 ;
  12518 ; 2000 RAM (1K or 2K) remapped
  12519 ; 2800 G007 ROM
  12520 ; 3000 
  12521 ; 3800 ZX81 Monitor
  12522 ;
  12523 ; The G007 uses some RAM
  12524 ; 2300 G007 RAM variables
  12525 ;
  12526 ; 2000
  12527 #code   $2000,$0800
  12528 ; RAM_2K
  12529 ; 2300
  12530 ; xxxx    data    4           ; reserves 4 bytes from the #data segment for variable "Toto"
  12531 
  12532 #code   $2800,$0800
  12533 
  12534 #if 0
  12535 ;
  12536 ; just copy bytes. Provides a reference for comparing code output.
  12537 ;
  12538 ;	G007 Graphics
  12539 ;	Start = 2800H
  12540 ;	End = 2FFFH
  12541 mark_2800:	DEFB	$2A, $23, $23, $3A, $25, $23, $67, $EB
  12542 mark_2808:	DEFB	$3A, $18, $23, $3D, $92, $57, $3E, $07
  12543 mark_2810:	DEFB	$A3, $6F, $26, $2D, $7E, $2A, $08, $23
  12544 mark_2818:	DEFB	$4A, $06, $00, $09, $09, $CB, $3A, $CB
  12545 mark_2820:	DEFB	$1B, $CB, $3A, $CB, $1B, $CB, $3A, $CB
  12546 mark_2828:	DEFB	$1B, $19, $47, $C9, $3A, $21, $23, $2A
  12547 mark_2830:	DEFB	$27, $23, $ED, $5B, $23, $23, $D9, $2A
  12548 mark_2838:	DEFB	$25, $23, $ED, $5B, $29, $23, $CB, $77
  12549 mark_2840:	DEFB	$28, $1C, $CB, $7F, $C0, $3A, $21, $40
  12550 mark_2848:	DEFB	$F5, $06, $08, $0F, $FD, $CB, $21, $16
  12551 mark_2850:	DEFB	$10, $F9, $EB, $D9, $EB, $D9, $CD, $5E
  12552 mark_2858:	DEFB	$28, $F1, $32, $21, $40, $C9, $01, $DE
  12553 mark_2860:	DEFB	$FF, $3A, $18, $23, $3D, $93, $ED, $52
  12554 mark_2868:	DEFB	$F2, $76, $28, $01, $22, $00, $7B, $D5
  12555 mark_2870:	DEFB	$19, $EB, $B7, $ED, $52, $D1, $E5, $63
  12556 mark_2878:	DEFB	$5F, $D9, $01, $FB, $28, $7D, $D9, $6F
  12557 mark_2880:	DEFB	$D9, $B7, $ED, $52, $F2, $90, $28, $01
  12558 mark_2888:	DEFB	$04, $29, $2F, $19, $EB, $B7, $ED, $52
  12559 mark_2890:	DEFB	$ED, $43, $1A, $23, $D1, $B7, $ED, $52
  12560 mark_2898:	DEFB	$19, $30, $09, $EB, $01, $F6, $28, $D9
  12561 mark_28A0:	DEFB	$53, $5F, $7A, $D9, $ED, $43, $1C, $23
  12562 mark_28A8:	DEFB	$D9, $57, $D5, $D9, $C1, $3A, $21, $23
  12563 mark_28B0:	DEFB	$FE, $40, $30, $02, $45, $4B, $04, $0C
  12564 mark_28B8:	DEFB	$CB, $3C, $38, $02, $28, $08, $CB, $1D
  12565 mark_28C0:	DEFB	$CB, $3A, $CB, $1B, $18, $F2, $55, $CB
  12566 mark_28C8:	DEFB	$3D, $D9, $C5, $CD, $07, $28, $D1, $3A
  12567 mark_28D0:	DEFB	$1F, $23, $4F, $FD, $CB, $21, $06, $38
  12568 mark_28D8:	DEFB	$08, $3A, $1E, $23, $AE, $B1, $A0, $AE
  12569 mark_28E0:	DEFB	$77, $D9, $7D, $05, $C8, $93, $30, $0A
  12570 mark_28E8:	DEFB	$0D, $C8, $82, $D9, $19, $D9, $2A, $1A
  12571 mark_28F0:	DEFB	$23, $E9, $2A, $1C, $23, $E9, $6F, $D9
  12572 mark_28F8:	DEFB	$19, $18, $D8, $6F, $D9, $CB, $00, $30
  12573 mark_2900:	DEFB	$D2, $2B, $18, $CF, $6F, $D9, $CB, $08
  12574 mark_2908:	DEFB	$30, $C9, $23, $18, $C6, $2A, $A8, $0E
  12575 mark_2910:	DEFB	$E9, $CD, $0D, $29, $38, $0E, $21, $00
  12576 mark_2918:	DEFB	$00, $28, $06, $ED, $42, $F8, $C8, $18
  12577 mark_2920:	DEFB	$03, $ED, $4A, $F0, $E1, $C9, $CD, $11
  12578 mark_2928:	DEFB	$29, $22, $25, $23, $CD, $11, $29, $E5
  12579 mark_2930:	DEFB	$CD, $02, $0C, $C1, $ED, $5B, $25, $23
  12580 mark_2938:	DEFB	$28, $0C, $3D, $C0, $21, $9C, $0C, $22
  12581 mark_2940:	DEFB	$30, $40, $43, $C3, $B2, $0B
  12582 ; The Plot Routine:
  12583 ; A == the plot number N
  12584 ; BC == screen X
  12585 ; DE == screen Y
  12586 mark_2946:	DEFB	$B7, $28
  12587 mark_2948:	DEFB	$F9, $3D, $D5, $C5, $F5, $CD, $1F, $2E
  12588 mark_2950:	DEFB	$F1, $D1, $C1, $FE, $81, $20, $0F, $ED
  12589 mark_2958:	DEFB	$53, $30, $23, $ED, $43, $32, $23, $01
  12590 mark_2960:	DEFB	$00, $00, $50, $58, $3E, $0B, $CB, $57
  12591 mark_2968:	DEFB	$28, $09, $2A, $29, $23, $E5, $2A, $27
  12592 mark_2970:	DEFB	$23, $18, $07, $2A, $32, $23, $E5, $2A
  12593 mark_2978:	DEFB	$30, $23, $B7, $ED, $5A, $D1, $E8, $22
  12594 mark_2980:	DEFB	$23, $23, $EB, $B7, $ED, $4A, $E8, $22
  12595 mark_2988:	DEFB	$25, $23, $5F, $3E, $C0, $A4, $E0, $3E
  12596 mark_2990:	DEFB	$C0, $A2, $E0, $D9, $E5, $D5, $C5, $CD
  12597 mark_2998:	DEFB	$9F, $29, $C1, $D1, $E1, $D9, $C9, $D9
  12598 mark_29A0:	DEFB	$7C, $B2, $37, $20, $05, $3A, $18, $23
  12599 mark_29A8:	DEFB	$3D, $BD, $3A, $21, $23, $1F, $32, $21
  12600 mark_29B0:	DEFB	$23, $7B, $CB, $7F, $28, $04, $2A, $10
  12601 mark_29B8:	DEFB	$23, $E9, $F5, $E6, $03, $1F, $3D, $2F
  12602 mark_29C0:	DEFB	$67, $9F, $6F, $22, $1E, $23, $E5, $CB
  12603 mark_29C8:	DEFB	$5B, $20, $28, $3A, $20, $23, $AB, $E6
  12604 mark_29D0:	DEFB	$FB, $28, $0F, $21, $34, $23, $7B, $07
  12605 mark_29D8:	DEFB	$07, $07, $E6, $03, $85, $6F, $7E, $32
  12606 mark_29E0:	DEFB	$21, $40, $CD, $2C, $28, $E1, $FD, $CB
  12607 mark_29E8:	DEFB	$21, $0E, $38, $26, $7C, $A5, $28, $22
  12608 mark_29F0:	DEFB	$2C, $5D, $E5, $3A, $21, $23, $CB, $6B
  12609 mark_29F8:	DEFB	$20, $3D, $CB, $73, $20, $3E, $E1, $CB
  12610 mark_2A00:	DEFB	$7F, $20, $0F, $E5, $CD, $00, $28, $A6
  12611 mark_2A08:	DEFB	$32, $17, $23, $D1, $7E, $B2, $AB, $A0
  12612 mark_2A10:	DEFB	$AE, $77, $F1, $32, $20, $23, $21, $2A
  12613 mark_2A18:	DEFB	$23, $11, $2E, $23, $01, $08, $00, $CB
  12614 mark_2A20:	DEFB	$67, $28, $11, $3A, $21, $23, $E6, $C0
  12615 mark_2A28:	DEFB	$17, $30, $02, $CB, $F7, $32, $21, $23
  12616 mark_2A30:	DEFB	$2E, $26, $0E, $04, $ED, $B8, $C9, $21
  12617 mark_2A38:	DEFB	$FF, $FF, $18, $03, $2A, $0A, $23, $D9
  12618 mark_2A40:	DEFB	$E6, $E0, $C2, $AD, $0E, $21, $21, $23
  12619 mark_2A48:	DEFB	$FD, $36, $21, $55, $06, $03, $23, $23
  12620 mark_2A50:	DEFB	$5E, $23, $23, $56, $D5, $10, $F7, $C1
  12621 mark_2A58:	DEFB	$D1, $E1, $B7, $28, $02, $44, $4D, $78
  12622 mark_2A60:	DEFB	$BC, $30, $03, $C5, $E3, $C1, $7C, $BA
  12623 mark_2A68:	DEFB	$30, $01, $EB, $7A, $D9, $E6, $07, $3C
  12624 mark_2A70:	DEFB	$47, $7C, $CB, $05, $07, $07, $07, $10
  12625 mark_2A78:	DEFB	$F9, $67, $22, $38, $23, $D9, $7C, $B8
  12626 mark_2A80:	DEFB	$3E, $07, $30, $03, $C5, $E3, $C1, $EB
  12627 mark_2A88:	DEFB	$F5, $79, $D9, $67, $6F, $4F, $22, $1A
  12628 mark_2A90:	DEFB	$23, $06, $FE, $D9, $93, $D9, $30, $04
  12629 mark_2A98:	DEFB	$06, $00, $ED, $44, $57, $D9, $7A, $90
  12630 mark_2AA0:	DEFB	$D9, $67, $BA, $30, $02, $EB, $04, $6C
  12631 mark_2AA8:	DEFB	$2C, $5C, $CB, $3B, $F1, $0F, $30, $09
  12632 mark_2AB0:	DEFB	$E5, $D5, $C5, $0F, $D9, $38, $CD, $18
  12633 mark_2AB8:	DEFB	$CE, $D9, $60, $2E, $01, $C1, $D1, $E3
  12634 mark_2AC0:	DEFB	$2D, $20, $16, $2A, $1A, $23, $79, $BC
  12635 mark_2AC8:	DEFB	$38, $01, $67, $BD, $30, $01, $6F, $22
  12636 mark_2AD0:	DEFB	$1A, $23, $E1, $2D, $28, $E7, $E5, $18
  12637 mark_2AD8:	DEFB	$15, $7B, $92, $38, $0A, $5F, $CB, $40
  12638 mark_2AE0:	DEFB	$28, $0C, $79, $80, $4F, $18, $D9, $84
  12639 mark_2AE8:	DEFB	$5F, $3E, $01, $B0, $81, $4F, $79, $D9
  12640 mark_2AF0:	DEFB	$FD, $CB, $21, $0E, $38, $CA, $E3, $D5
  12641 mark_2AF8:	DEFB	$C5, $E5, $ED, $5B, $1A, $23, $47, $B9
  12642 mark_2B00:	DEFB	$30, $02, $41, $4F, $ED, $43, $1A, $23
  12643 mark_2B08:	DEFB	$79, $BB, $3C, $38, $01, $7B, $6F, $7A
  12644 mark_2B10:	DEFB	$B8, $30, $02, $78, $3D, $95, $3C, $F5
  12645 mark_2B18:	DEFB	$CD, $07, $28, $F1, $4F, $EB, $21, $39
  12646 mark_2B20:	DEFB	$23, $7E, $07, $07, $07, $77, $2B, $CB
  12647 mark_2B28:	DEFB	$06, $B6, $2A, $1E, $23, $AD, $2F, $6F
  12648 mark_2B30:	DEFB	$EB, $7B, $AE, $B2, $A0, $AE, $77, $0D
  12649 mark_2B38:	DEFB	$20, $14, $E1, $24, $CB, $7D, $28, $94
  12650 mark_2B40:	DEFB	$E1, $E1, $E1, $E1, $7C, $A5, $CA, $12
  12651 mark_2B48:	DEFB	$2A, $2C, $E5, $C3, $45, $2A, $CB, $18
  12652 mark_2B50:	DEFB	$30, $DF, $23, $41, $79, $E6, $07, $4F
  12653 mark_2B58:	DEFB	$CB, $38, $CB, $38, $CB, $38, $28, $08
  12654 mark_2B60:	DEFB	$7B, $AE, $B2, $AE, $77, $23, $10, $F8
  12655 mark_2B68:	DEFB	$37, $0C, $18, $CB, $2A, $13, $23, $2D
  12656 mark_2B70:	DEFB	$B5, $C2, $09, $08, $25, $C2, $B8, $23
  12657 mark_2B78:	DEFB	$3A, $21, $23, $17, $D8, $00, $00, $2A
  12658 mark_2B80:	DEFB	$28, $23, $3A, $27, $23, $CB, $72, $20
  12659 mark_2B88:	DEFB	$05, $6F, $C6, $08, $30, $0D, $7C, $D6
  12660 mark_2B90:	DEFB	$08, $30, $04, $3A, $18, $23, $3D, $32
  12661 mark_2B98:	DEFB	$29, $23, $AF, $32, $27, $23, $CB, $72
  12662 mark_2BA0:	DEFB	$C0, $CD, $EF, $2E, $7D, $FE, $F9, $38
  12663 mark_2BA8:	DEFB	$02, $1E, $02, $2F, $E6, $07, $3C, $57
  12664 mark_2BB0:	DEFB	$7C, $3C, $D9, $57, $D9, $D5, $CD, $07
  12665 mark_2BB8:	DEFB	$28, $D9, $79, $AE, $D9, $EB, $C1, $C5
  12666 mark_2BC0:	DEFB	$6F, $26, $00, $29, $10, $FD, $EB, $06
  12667 mark_2BC8:	DEFB	$02, $3A, $7B, $40, $AE, $FD, $B6, $7C
  12668 mark_2BD0:	DEFB	$A2, $AE, $0D, $28, $01, $77, $53, $23
  12669 mark_2BD8:	DEFB	$10, $EF, $0E, $20, $09, $D9, $23, $15
  12670 mark_2BE0:	DEFB	$28, $02, $10, $D6, $E1, $C3, $9A, $29
  12671 mark_2BE8:	DEFB	$ED, $57, $0F, $30, $08, $AF, $32, $22
  12672 mark_2BF0:	DEFB	$40, $3C, $32, $13, $23, $CD, $CF, $0A
  12673 mark_2BF8:	DEFB	$AF, $32, $13, $23, $FD, $36, $22, $02
  12674 mark_2C00:	DEFB	$4F, $C9, $CD, $A0, $0C, $DA, $AD, $0E
  12675 mark_2C08:	DEFB	$0E, $01, $C8, $0E, $FF, $C9, $FD, $46
  12676 mark_2C10:	DEFB	$22, $0E, $21, $CD, $18, $09, $CD, $9B
  12677 mark_2C18:	DEFB	$09, $7E, $12, $FD, $34, $3A, $2A, $0C
  12678 mark_2C20:	DEFB	$40, $23, $54, $5D, $ED, $B1, $C3, $5D
  12679 mark_2C28:	DEFB	$0A, $8B, $8D, $2D, $7F, $81, $49, $75
  12680 mark_2C30:	DEFB	$5F, $40, $42, $2B, $17, $1F, $37, $52
  12681 mark_2C38:	DEFB	$45, $0F, $6D, $2B, $44, $2D, $5A, $3B
  12682 mark_2C40:	DEFB	$4C, $45, $0D, $52, $54, $4D, $15, $6A
  12683 mark_2C48:	DEFB	$01, $14, $02, $06, $00, $81, $0E, $06
  12684 mark_2C50:	DEFB	$DE, $05, $AB, $0D, $06, $00, $B5, $0E
  12685 mark_2C58:	DEFB	$00, $DC, $0C, $00, $D8, $0E, $04, $14
  12686 mark_2C60:	DEFB	$06, $DF, $06, $05, $B9, $0D, $04, $00
  12687 mark_2C68:	DEFB	$2E, $0E, $05, $E8, $2B, $01, $00, $E9
  12688 mark_2C70:	DEFB	$0E, $05, $A7, $2E, $05, $6A, $0D, $00
  12689 mark_2C78:	DEFB	$C3, $03, $03, $AF, $0E, $03, $30, $07
  12690 mark_2C80:	DEFB	$06, $1A, $06, $00, $92, $0E, $03, $6C
  12691 mark_2C88:	DEFB	$0E, $05, $40, $03, $05, $4D, $2F, $00
  12692 mark_2C90:	DEFB	$7C, $0E, $00, $B2, $0E, $03, $4E, $2E
  12693 mark_2C98:	DEFB	$06, $1A, $06, $1A, $06, $00, $26, $29
  12694 mark_2CA0:	DEFB	$2A, $A8, $0E, $E9, $00, $0E, $0C, $06
  12695 mark_2CA8:	DEFB	$00, $AE, $2E, $03, $B2, $2E, $03, $B6
  12696 mark_2CB0:	DEFB	$2E, $03, $53, $2F, $05, $CB, $0A, $03
  12697 mark_2CB8:	DEFB	$2C, $07, $FD, $36, $01, $01, $CD, $73
  12698 mark_2CC0:	DEFB	$0A, $CD, $95, $0A, $21, $00, $40, $36
  12699 mark_2CC8:	DEFB	$FF, $21, $2D, $40, $CB, $6E, $28, $0E
  12700 mark_2CD0:	DEFB	$FE, $E3, $7E, $C2, $6F, $0D, $CD, $A6
  12701 mark_2CD8:	DEFB	$0D, $C8, $CF, $0C, $CF, $08, $DF, $06
  12702 mark_2CE0:	DEFB	$00, $FE, $76, $C8, $4F, $E7, $79, $D6
  12703 mark_2CE8:	DEFB	$E1, $38, $3B, $4F, $21, $29, $0C, $09
  12704 mark_2CF0:	DEFB	$4E, $09, $18, $03, $2A, $30, $40, $7E
  12705 mark_2CF8:	DEFB	$23, $22, $30, $40, $01, $F4, $0C, $C5
  12706 ;
  12707 ; bits shifting right within a byte:
  12708 ;
  12709 mark_2D00:	DEFB	$80, $40, $20, $10, $08, $04, $02, $01
  12710 ;
  12711 mark_2D08:	DEFB	$CD, $F7, $2B, $C3, $07, $02, $32, $28
  12712 mark_2D10:	DEFB	$40, $EB, $21, $0A, $00, $39, $7E, $3C
  12713 mark_2D18:	DEFB	$E6, $F0, $D6, $D0, $4F, $23, $7E, $D6
  12714 mark_2D20:	DEFB	$04, $B1, $4F, $3A, $3B, $40, $07, $9F
  12715 mark_2D28:	DEFB	$A1, $20, $10, $2A, $10, $40, $01, $DF
  12716 mark_2D30:	DEFB	$FF, $09, $CB, $FC, $22, $04, $23, $3E
  12717 mark_2D38:	DEFB	$01, $18, $0E, $2A, $0C, $40, $ED, $4B
  12718 mark_2D40:	DEFB	$00, $23, $09, $CB, $FC, $22, $06, $23
  12719 mark_2D48:	DEFB	$AF, $32, $19, $23, $2B, $7E, $EB, $C9
  12720 mark_2D50:	DEFB	$3A, $19, $23, $3D, $C2, $73, $2D, $3E
  12721 mark_2D58:	DEFB	$1E, $ED, $47, $ED, $6A, $2A, $04, $23
  12722 mark_2D60:	DEFB	$01, $08, $01, $3E, $FE, $CD, $B5, $02
  12723 mark_2D68:	DEFB	$3E, $1F, $ED, $47, $3A, $28, $40, $D6
  12724 mark_2D70:	DEFB	$08, $18, $04, $2B, $3A, $28, $40, $4F
  12725 mark_2D78:	DEFB	$DD, $E1, $FD, $CB, $3B, $7E, $C2, $9D
  12726 mark_2D80:	DEFB	$02, $3E, $FE, $06, $01, $21, $9A, $2D
  12727 mark_2D88:	DEFB	$CD, $95, $2D, $29, $00, $5F, $2A, $06
  12728 mark_2D90:	DEFB	$23, $CB, $FC, $DD, $E9, $ED, $4F, $3E
  12729 mark_2D98:	DEFB	$DD, $FB, $76, $21, $00, $22, $3E, $24
  12730 mark_2DA0:	DEFB	$36, $01, $35, $28, $02, $CF, $1A, $23
  12731 mark_2DA8:	DEFB	$BC, $20, $F5, $65, $11, $00, $20, $01
  12732 mark_2DB0:	DEFB	$00, $01, $ED, $B0, $24, $14, $04, $ED
  12733 mark_2DB8:	DEFB	$B0, $21, $F1, $07, $11, $A0, $23, $01
  12734 mark_2DC0:	DEFB	$60, $00, $ED, $B0, $16, $20, $21, $B4
  12735 mark_2DC8:	DEFB	$2F, $46, $18, $04, $5E, $23, $7E, $12
  12736 mark_2DD0:	DEFB	$23, $10, $F9, $14, $CB, $52, $28, $F1
  12737 mark_2DD8:	DEFB	$C9
  12738 
  12739 ; Delete Display File:
  12740 
  12741 mark_2DD9:	DEFB	$CD, $E7, $02, $21, $87, $3E, $CD
  12742 mark_2DE0:	DEFB	$D8, $09, $C0, $EB, $2A, $29, $40, $CB
  12743 mark_2DE8:	DEFB	$76, $28, $04, $ED, $53, $29, $40, $2A
  12744 mark_2DF0:	DEFB	$0C, $40, $C3, $5D, $0A, $CD, $D9, $2D
  12745 mark_2DF8:	DEFB	$01, $92, $19, $2A, $0C, $40, $2B, $CD
  12746 mark_2E00:	DEFB	$9E, $09, $3E, $76, $12, $13, $12, $23
  12747 mark_2E08:	DEFB	$23, $36, $3E, $23, $36, $87, $23, $36
  12748 mark_2E10:	DEFB	$8D, $23, $36, $19, $23, $77, $23, $77
  12749 mark_2E18:	DEFB	$CD, $07, $02, $3E, $01, $18, $37
  12750 ; Check & Set Up Display File:
  12751 mark_2E1F:	DEFB	$2A
  12752 mark_2E20:	DEFB	$65, $22, $11, $D9, $BF, $19, $3A, $64
  12753 mark_2E28:	DEFB	$22, $D6, $21, $B4, $B5, $C4, $9B, $2D
  12754 mark_2E30:	DEFB	$2A, $0C, $40, $3E, $76, $2B, $2B, $BE
  12755 mark_2E38:	DEFB	$C4, $F5, $2D, $2A, $0C, $40, $ED, $5B
  12756 mark_2E40:	DEFB	$00, $23, $19, $22, $06, $23, $11, $09
  12757 mark_2E48:	DEFB	$00, $19, $22, $08, $23, $C9, $CD, $02
  12758 mark_2E50:	DEFB	$0C, $C0
  12759 ; Clear The Screen:
  12760 mark_2E52:	DEFB	$3D, $FA, $2A, $0A, $F5, $CD
  12761 mark_2E58:	DEFB	$1F, $2E, $F1, $FE, $02, $ED, $4B, $18
  12762 mark_2E60:	DEFB	$23, $2A, $0C, $40, $30, $30, $3D, $23
  12763 mark_2E68:	DEFB	$22, $0E, $40, $2B, $2B, $2B, $1E, $00
  12764 mark_2E70:	DEFB	$06, $10, $2B, $73, $2B, $73, $2B, $77
  12765 mark_2E78:	DEFB	$2B, $77, $10, $FA, $0D, $20, $F1, $06
  12766 mark_2E80:	DEFB	$09, $3E, $01, $2B, $73, $10, $FC, $21
  12767 mark_2E88:	DEFB	$34, $23, $06, $14, $3D, $28, $F4, $21
  12768 mark_2E90:	DEFB	$21, $18, $22, $39, $40, $C9, $C0, $2B
  12769 mark_2E98:	DEFB	$2B, $06, $20, $2B, $2B, $2B, $7E, $2F
  12770 mark_2EA0:	DEFB	$77, $10, $FA, $0D, $20, $F3, $C9, $2A
  12771 mark_2EA8:	DEFB	$96, $0A, $3E, $4D, $18, $35, $3E, $DD
  12772 mark_2EB0:	DEFB	$18, $2E, $3E, $D6, $18, $02, $3E, $CE
  12773 mark_2EB8:	DEFB	$F5, $CD, $02, $0C, $06, $1E, $3D, $FE
  12774 mark_2EC0:	DEFB	$06, $30, $19, $CB, $3F, $67, $28, $02
  12775 mark_2EC8:	DEFB	$3E, $01, $F5, $9F, $6F, $CB, $8C, $25
  12776 mark_2ED0:	DEFB	$22, $7B, $40, $CD, $1F, $2E, $06, $1F
  12777 mark_2ED8:	DEFB	$F1, $32, $14, $23, $78, $ED, $47, $F1
  12778 mark_2EE0:	DEFB	$2A, $71, $0D, $85, $6F, $E9, $57, $3A
  12779 mark_2EE8:	DEFB	$39, $40, $E6, $80, $C3, $6C, $2B, $7A
  12780 mark_2EF0:	DEFB	$D1, $D9, $E5, $D5, $C5, $2A, $0C, $23
  12781 mark_2EF8:	DEFB	$87, $30, $0B, $2A, $0E, $23, $CB, $77
  12782 mark_2F00:	DEFB	$28, $04, $2A, $15, $23, $3F, $EB, $6F
  12783 mark_2F08:	DEFB	$26, $00, $9F, $4F, $3A, $7B, $40, $2F
  12784 mark_2F10:	DEFB	$FD, $A6, $7C, $A9, $4F, $29, $29, $19
  12785 mark_2F18:	DEFB	$06, $08, $D9, $D5, $C9, $FD, $35, $39
  12786 mark_2F20:	DEFB	$3E, $18, $90, $47, $87, $87, $87, $6F
  12787 mark_2F28:	DEFB	$3A, $18, $23, $95, $D8, $3E, $21, $91
  12788 mark_2F30:	DEFB	$4F, $26, $00, $29, $09, $ED, $4B, $08
  12789 mark_2F38:	DEFB	$23, $09, $CD, $EF, $2E, $01, $22, $00
  12790 mark_2F40:	DEFB	$D9, $79, $AE, $D9, $77, $09, $D9, $23
  12791 mark_2F48:	DEFB	$10, $F7, $C3, $9A, $29, $CD, $D9, $2D
  12792 mark_2F50:	DEFB	$C3, $F6, $02, $CD, $02, $0C, $C0, $3D
  12793 mark_2F58:	DEFB	$FA, $69, $08, $CD, $1F, $2E, $CD, $E7
  12794 mark_2F60:	DEFB	$02, $3A, $18, $23, $47, $2A, $08, $23
  12795 mark_2F68:	DEFB	$AF, $5F, $D3, $FB, $3E, $7F, $DB, $FE
  12796 mark_2F70:	DEFB	$0F, $D2, $86, $08, $DB, $FB, $87, $FA
  12797 mark_2F78:	DEFB	$AD, $2F, $30, $F0, $0E, $20, $C5, $4E
  12798 mark_2F80:	DEFB	$06, $08, $CB, $01, $1F, $B3, $57, $DB
  12799 mark_2F88:	DEFB	$FB, $1F, $30, $FB, $7A, $D3, $FB, $10
  12800 mark_2F90:	DEFB	$F1, $23, $C1, $0D, $20, $E8, $23, $23
  12801 mark_2F98:	DEFB	$3E, $03, $B8, $38, $02, $5F, $1D, $DB
  12802 mark_2FA0:	DEFB	$FB, $1F, $30, $FB, $7B, $D3, $FB, $10
  12803 mark_2FA8:	DEFB	$C3, $3E, $04, $D3, $FB, $C3, $07, $02
  12804 mark_2FB0:	DEFB	$FB, $10, $C3, $3E, $0A, $12, $A0, $13
  12805 mark_2FB8:	DEFB	$23, $15, $A4, $16, $23, $40, $C1, $60
  12806 mark_2FC0:	DEFB	$08, $61, $2D, $75, $06, $76, $23, $01
  12807 mark_2FC8:	DEFB	$0A, $54, $02, $85, $C1, $7F, $73, $80
  12808 mark_2FD0:	DEFB	$2D, $8D, $50, $8E, $2D, $E3, $C3, $E4
  12809 mark_2FD8:	DEFB	$0E, $E5, $2D, $13, $00, $75, $01, $E6
  12810 mark_2FE0:	DEFB	$0A, $55, $0D, $1E, $0F, $1E, $16, $20
  12811 mark_2FE8:	DEFB	$10, $07, $11, $08, $18, $C0, $35, $EE
  12812 mark_2FF0:	DEFB	$36, $55, $37, $C6, $AD, $E6, $AE, $2E
  12813 mark_2FF8:	DEFB	$F2, $C3, $F3, $1D, $F4, $2F, $ED, $00
  12814 ;
  12815 #else
  12816 ; G007 source code, reverse engineered.
  12817 ;
  12818 ; The ZX81 labels will have been generated already.
  12819 ; No need to include ZX definitions:
  12820 ;
  12821 
  12822 
  12823 ;===============================
  12824 ; G007 Hi-Res graphics board for the ZX81
  12825 ; 
  12826 ; Source code partially reverse-engineered.
  12827 ; A work in progress...
  12828 ;
  12829 ; 2011-05-15 Assembles to create correct ROM image.
  12830 ;
  12831 ; Verifed by comparing the hex files,
  12832 ; the known-good reference generated by
  12833 ; 2048 defb statements containing the original bytes.
  12834 ; 
  12835 ; The source code below is not guaranteed to create the ROM image
  12836 ; exactly the way the original author had in mind,
  12837 ; as I'm not him and I don't have the original source code.
  12838 ;
  12839 ; This file was created from a disassembly generated by the
  12840 ; impressive VB81 emulator program.
  12841 ;
  12842 ; It was already know that the G007 switched out pages of
  12843 ; the ZX81 BASIC ROM and patched in replacements from
  12844 ; the G007 ROM and the ZX81's internal 1K (or 2K) RAM.
  12845 ; This is a thrifty use of RAM that expansion RAM packs
  12846 ; usually just disabled.
  12847 ;
  12848 ; Memory map:
  12849 ;
  12850 ; 0000-0FFF
  12851 ; 2000-23FF	1K RAM inside ZX81, remapped here.
  12852 ; 2400-27FF	1K RAM more RAM if ZX81 has a 2K RAM chip
  12853 ; 2800-2FFF	2K G007
  12854 ; 3000-3FFF	Empty
  12855 ; 4000-7FFF	External RAM pack
  12856 ;
  12857 ; Patching:
  12858 ;
  12859 ; 2C00-2CFF (ROM) also appears at 0C00-0CFF
  12860 ; 2000-20FF (RAM) also appears at 0000-00FF
  12861 ; 2200-22FF (RAM) also appears at 0200-02FF
  12862 ;
  12863 ; The ROM patching is active all the time.
  12864 ; The RAM patching is active only in hi-res mode.
  12865 ;
  12866 ; The patches didn't cover every modification needed,
  12867 ; so one routine is copied from ROM to RAM and
  12868 ; then individual bytes are modified there
  12869 ; by the initialisation routine which also
  12870 ; initialises some variables.
  12871 ;
  12872 ; Graphics routines:
  12873 ;
  12874 ; These have not yet been analysed.
  12875 ; Bresenham's algorithm will be there is some form.
  12876 ;
  12877 ; Triangle-filling is a sophisticated feature,
  12878 ; using 8-bit maths for a practical speed.
  12879 ;
  12880 ; Future enhancements
  12881 ;
  12882 ; Programmers may like to try writing faster routines,
  12883 ; or adding more commands now that memory is cheap.
  12884 ;
  12885 ; The bit-mask array at $2D00 looks like this:
  12886 ; 10000000
  12887 ; 01000000
  12888 ; 00100000
  12889 ; 00010000
  12890 ; 00001000
  12891 ; 00000100
  12892 ; 00000010
  12893 ; 00000001
  12894 ;
  12895 ; and suggests that pixels
  12896 ; may be plotted one at a time.
  12897 ; When I wrote a triangle-filling algorithm for the Atom,
  12898 ; I made frequent use of horizontal lines.
  12899 ; I optimised these by working out the partially-filled
  12900 ; bytes at the left and right sides, and writing
  12901 ; whole bytes (of 8 pixels) between the partial bytes.
  12902 ; This used two overlapping tables like so:
  12903 ;
  12904 ; 10000000	; BIT_MASK_R
  12905 ; 11000000
  12906 ; 11100000
  12907 ; 11110000
  12908 ; 11111000
  12909 ; 11111100
  12910 ; 11111110
  12911 ; 11111111	; BIT_MASK_L
  12912 ; 01111111
  12913 ; 00111111
  12914 ; 00011111
  12915 ; 00001111
  12916 ; 00000111
  12917 ; 00000011
  12918 ; 00000001
  12919 ;
  12920 ; This technique might be able to increase the triangle filling speed.
  12921 ;
  12922 ; A proper ellipse algorithm would also be welcome,
  12923 ; not one of those approximations using polygons!
  12924 ;
  12925 ;===============================
  12926 ; Assembly was done by a very handy online tool:
  12927 ; http://k1.dyndns.org/cgi-bin/zasm.cgi
  12928 ; which avoids the chore of installing it
  12929 ; on one's own machine.
  12930 ; The online tool is limited to one source file and
  12931 ; one include file, but that's not a big deal
  12932 ; for a tiny 2K ROM like this one.
  12933 ;
  12934 ;===============================
  12935 ; Problems
  12936 ; The G007 ROM had several instances of opcdoes
  12937 ; beginning with FD CB
  12938 ; involving the Y register.
  12939 ; VB81 disassembled them into statements
  12940 ; that looked mangled and would not re-assemble.
  12941 ; So I've just added them with defb statements.
  12942 ;
  12943 ;
  12944 ;===============================
  12945 ; Global constants:
  12946 ;===============================
  12947 FALSE		equ	0
  12948 NOT_G007	equ	FALSE
  12949 
  12950 
  12951 
  12952 ;===============================
  12953 ; ZX81 constants:
  12954 ;===============================
  12955 ; ZX characters (not the same as ASCII)
  12956 ;-------------------------------
  12957 ZX_EQU			equ	$14
  12958 ZX_COMMA		equ	$1A
  12959 ZX_THEN			equ	$DE
  12960 ZX_TO			equ	$DF
  12961 ZX_INV_K		equ	$B0
  12962 ZX_NEWLINE		equ	$76
  12963 HRG_BYTES_PER_LINE	equ	34
  12964 ALL_BITS_SET		equ	-1
  12965 ;-------------------------------
  12966 ; tokens
  12967 ;-------------------------------
  12968 _CLASS_00	equ	0
  12969 _CLASS_01	equ	1
  12970 _CLASS_02	equ	2
  12971 _CLASS_03	equ	3
  12972 _CLASS_04	equ	4
  12973 _CLASS_05	equ	5
  12974 _CLASS_06	equ	6
  12975 ;===============================
  12976 ; ZX81 I/O locations:
  12977 ;===============================	
  12978 IO_PORT_KEYBOARD_RD	equ	$FE	; A0 low			
  12979 ZX_NMI_GEN		equ	$FD	; A1 low		
  12980 ZX_PRINTER_PORT		equ	$FB	; A2 low		
  12981 ;===============================
  12982 ; ZX81 RAM variables
  12983 ;===============================
  12984 RAMBASE		equ	$4000
  12985 ERR_NR		equ	$4000
  12986 FLAGS		equ	$4001
  12987 ERR_SP		equ	$4002
  12988 RAMTOP		equ	$4004
  12989 MODE		equ	$4006
  12990 PPC		equ	$4007
  12991 VERSN		equ	$4009
  12992 E_PPC		equ	$400A
  12993 D_FILE		equ	$400C
  12994 DF_CC		equ	$400E
  12995 VARS		equ	$4010
  12996 DEST		equ	$4012
  12997 E_LINE		equ	$4014
  12998 CH_ADD		equ	$4016
  12999 X_PTR		equ	$4018
  13000 STKBOT		equ	$401A
  13001 STKEND		equ	$401C
  13002 BERG		equ	$401E
  13003 MEM		equ	$401F
  13004 UNUSED_8	equ	$4021
  13005 G007_FLAG_Y	equ	UNUSED_8	;
  13006 
  13007 DF_SZ		equ	$4022
  13008 S_TOP		equ	$4023
  13009 LAST_K		equ	$4025
  13010 DEBOUNCE	equ	$4027
  13011 MARGIN		equ	$4028
  13012 NXTLIN		equ	$4029
  13013 NXT_LINE	equ	$4029
  13014 OLDPPC		equ	$402B
  13015 FLAGX		equ	$402D
  13016 
  13017 STRLEN		equ	$402E
  13018 T_ADDR		equ	$4030
  13019 SEED		equ	$4032
  13020 FRAMES		equ	$4034
  13021 COORDS		equ	$4036
  13022 PR_CC		equ	$4038
  13023 S_POSN		equ	$4039
  13024 S_POSN_hi	equ	S_POSN+1
  13025 CDFLAG		equ	$403B
  13026 PRBUFF		equ	$403C
  13027 MEMBOT		equ	$407B
  13028 PROGRAM		equ	$407D
  13029 UNUSED_16	equ	$407B
  13030 UNUSED_16_hi	equ	UNUSED_16+1
  13031 
  13032 G007_RESTART	equ	UNUSED_16
  13033 
  13034 ; First byte after system variables:
  13035 USER_RAM	equ	$407D
  13036 MAX_RAM		equ	$7FFF
  13037 
  13038 ;===============================
  13039 ; ZX BASIC ROM addresses		
  13040 ;===============================
  13041 ; restart constants
  13042 START		equ	$0000   ; =      0
  13043 ERROR_1		equ	$0008   ; =      8
  13044 PRINT_A		equ	$0010   ; =     16
  13045 GET_CHAR	equ	$0018   ; =     24
  13046 TEST_SP		equ	$001C   ; =     28
  13047 NEXT_CH		equ	$0020   ; =     32
  13048 FP_CALC		equ	$0028   ; =     40
  13049 ;-------------------------------
  13050 L0108		equ	$0108
  13051 SLOW_FAST	equ	$0207	;
  13052 DISPLAY_5	equ	$02B5	;
  13053 L029D		equ	$029D	; Inside the 'LOC_ADDR' subroutine
  13054 SET_FAST	equ	$02E7
  13055 LOAD		equ	$0340
  13056 LIST		equ	$0730
  13057 COPY		equ	$0869
  13058 SAVE		equ	$02F6
  13059 NEW		equ	$03C3
  13060 LLIST		equ	$072C
  13061 PRINT_CH	equ	$07F1	; old, replaced
  13062 L0809		equ	$0809
  13063 LOC_ADDR	equ	$0918
  13064 ONE_SPACE	equ	$099B
  13065 MAKE_ROOM	equ	$099E
  13066 LINE_ADDR	equ	$09D8
  13067 E_LINE_NO	equ	$0A73
  13068 L0A95		equ	$0A95	; []*BIOS ROM*. Part way into 088A COPY_CONT
  13069 PRINT		equ	$0ACF
  13070 CLS		equ	$0A2A
  13071 RECLAIM_1	equ	$0A5D
  13072 LPRINT		equ	$0ACB
  13073 PRINT		equ	$0ACF
  13074 PLOT_UNPLOT	equ	$0BAF
  13075 L0BB2		equ	$0BB2	;
  13076 STK_TO_A	equ	$0C02
  13077 SCROLL		equ	$0C0E
  13078 
  13079 ;-------------------------------
  13080 ; Parameter table addresses:
  13081 ; Checked in ROM disassembly book:
  13082 ;-------------------------------
  13083 P_LET		equ	$0C48
  13084 P_GOTO		equ	$0C4B
  13085 P_IF		equ	$0C4F
  13086 P_GOSUB		equ	$0C54
  13087 P_STOP		equ	$0C58
  13088 P_RETURN	equ	$0C5B
  13089 P_FOR		equ	$0C5E
  13090 P_NEXT		equ	$0C66
  13091 P_PRINT		equ	$0C6A
  13092 P_INPUT		equ	$0C6D
  13093 P_DIM		equ	$0C71
  13094 P_REM		equ	$0C74
  13095 P_NEW		equ	$0C77
  13096 P_RUN		equ	$0C7A
  13097 P_LIST		equ	$0C7D
  13098 P_POKE		equ	$0C80
  13099 P_RAND		equ	$0C86
  13100 P_LOAD		equ	$0C89
  13101 P_SAVE		equ	$0C8C
  13102 P_CONT		equ	$0C8F
  13103 P_CLEAR		equ	$0C92
  13104 P_CLS		equ	$0C95
  13105 
  13106 P_PLOT		equ	$0C98	; redefined in G007 patch
  13107 P_UNPLOT	equ	$0C9E	; redefined in G007 patch
  13108 P_SCROLL	equ	$0CA4
  13109 
  13110 P_PAUSE		equ	$0CA7
  13111 ;P_SLOW		equ	$0CAB
  13112 ;P_FAST		equ	$0CAE
  13113 ;P_COPY		equ	$0CB1
  13114 ;P_LPRINT	equ	$0CB4
  13115 ;P_LLIST	equ	$0CB7
  13116 ;-------------------------------
  13117 
  13118 STOP		equ	$0CDC	; defined in this file
  13119 
  13120 REM		equ	$0D6A
  13121 INPUT_RE	equ	$0D6F
  13122 
  13123 REPORT_C	equ	$0D9A	; according to the book
  13124 REPORT_C_007	equ	$0D26	; seems the right one
  13125 SYNTAX_Z	equ	$0DA6
  13126 IF		equ	$0DAB
  13127 FOR		equ	$0DB9
  13128 
  13129 NEXT		equ	$0E2E
  13130 RAND		equ	$0E6C
  13131 CONT		equ	$0E7C
  13132 GOTO		equ	$0E81
  13133 POKE		equ	$0E92
  13134 L0EA8		equ	$0EA8	; Inside the 'FIND_INT.' subroutine
  13135 REPORT_B	equ	$0EAD
  13136 				; check this!!!
  13137 RUN		equ	$0EAF
  13138 CLEAR_007	equ	$0EB2	; goes to JP CLEAR
  13139 GOSUB		equ	$0EB5
  13140 RETURN		equ	$0ED8
  13141 INPUT		equ	$0EE9
  13142 
  13143 FAST		equ	$0F23
  13144 SLOW		equ	$0F2B
  13145 PAUSE		equ	$0F32
  13146 
  13147 DIM		equ	$1409
  13148 CLEAR		equ	$149A
  13149 SET_MEM		equ	$14BC
  13150 
  13151 
  13152 ;===============================
  13153 ; G007 Memory patch addresses
  13154 ;===============================
  13155 ; These patches only appear in hi-res mode
  13156 ;
  13157 RAM_PATCH_0000	equ	$0000
  13158 RAM_PATCH_0200	equ	$0200
  13159 ROM_PATCH_0C00	equ	$0C00
  13160 ;
  13161 ; Their aliases are always present:
  13162 ;
  13163 RAM_PATCH_2000	equ	$2000
  13164 RAM_PATCH_2200	equ	$2200
  13165 ;===============================
  13166 ; G007 Plot number notes (a work in prgress)		
  13167 ;===============================
  13168 ;	N-1
  13169 ;
  13170 ;	76543 210	
  13171 ;	..... .00	Line in white.
  13172 ;	..... .01	Line black.
  13173 ;	..... .10	Line inverting.
  13174 ;	..... .11	Line inverting, omit last pixel.
  13175 ;
  13176 ;	..... 0..	Absolute co-ordinates
  13177 ;	..... 1..	Relative co-ordinates
  13178 ;
  13179 ;	....0 ...	Line
  13180 ;	....1 ...	Single pixel
  13181 ;
  13182 ;	.0100 ...	Coarse dotted line
  13183 ;	.0101 ...	Add 40: triangle, plain
  13184 ;	.1001....	Add 72: triangle, textured (not available in invert mode)
  13185 ;	.1000 ...	Add 64:   fine dotted line
  13186 ;	.1100 ...	Add 96:  chain dotted line
  13187 ;
  13188 ;	Note that PLOT 12 and PLOT 16 miss out the pixel, so simply move the PLOT position.
  13189 ;
  13190 
  13191 
  13192 
  13193 
  13194 
  13195 ;===============================
  13196 ; G007 Byte constants			
  13197 ;===============================
  13198 
  13199 
  13200 
  13201 
  13202 
  13203 G007_INT_REG_VALUE_FOR_HI_RES_GRAPHICS		equ	$1F
  13204 G007_INT_REG_VALUE_FOR_LO_RES_GRAPHICS		equ	$1E
  13205 
  13206 ;	Dec. 	Hex. 	Bytes 	System Variables: G007			
  13207 			
  13208 ;	8448	2100	Reserved for user defined characters
  13209 ;	8703	21FF	
  13210 ;			
  13211 ;	8704	2200	Another page, possibly 
  13212 ;	8959	22FF	
  13213 			
  13214 ;===============================
  13215 ; G007 Byte constants			
  13216 ;===============================
  13217 MEM_PATCH_SIZE	equ	$0100
  13218 ;===============================
  13219 ; G007 RAM variables
  13220 ;===============================
  13221 
  13222 V2265		equ	$2265
  13223 V2264		equ	$2264
  13224 
  13225 ;	Dec. 	Hex. 	Bytes 	System Variables: G007			
  13226 ;	8960	2300	2	Offset of hi-res display file, less 9, from the D-FILE variable			
  13227 ;	8962	2302	2	Not used			
  13228 ;	8964	2304	2	Start address of last line of lo-res display file			
  13229 
  13230 G007_DISPLAY_OFFSET_FROM_DFILE_LESS_9	equ	$2300	; conflict!
  13231 
  13232 G007_UNUSED_2302			equ	$2302
  13233 G007_DISPLAY_ADDRESS_LO_RES_LAST_LINE	equ	$2304
  13234 G007_DISPLAY_ADDRESS_LESS_9	equ	$2306	;	8966	2306	2	Start address of hi-res display file, less 9 (used for video)			
  13235 G007_DISPLAY_ADDRESS		equ	$2308	;	8968	2308	2	Start address of hi-res display file			
  13236 G007_TRIANGLE_TEXTURE		equ	$230A	;	8970	230A 	2	Bytes defining triangle texture			
  13237 G007_CHAR_TABLE_ADDR_0_63	equ	$230C	;	8972	230C 	2	Character table address for CHR$0-63			
  13238 G007_CHAR_TABLE_ADDR_128_159	equ	$230E	;	8974	230E 	2	Character table address for CHR$128-159			
  13239 G007_PLOT_ROUTINES_VECTOR	equ	$2310	;	8976	2310	2	Vector for additional plot routines			
  13240 G007_FLAG_0			equ	$2312	;	8978	2312	3 * 	Various flags			
  13241 G007_FLAG_1			equ	$2313
  13242 G007_FLAG_2			equ	$2314
  13243 G007_USR_DEF_CHR_TAB_LESS_256	equ	$2315	;	8981	2315	2	Address of user-defined character table, less 256			
  13244 G007_READ_POINT_BYTE		equ	$2317	;	8983	2317	1	Read-point byte. Non-zero if pixel is set.			
  13245 G007_DISPLAY_HEIGHT		equ	$2318	;	8984	2318	1 * 	Display height, normally 192			
  13246 G007_FLAG_3			equ	$2319	;	8985	2319	1	Flags			
  13247 
  13248 ;G007_TEMP_WORD_0		equ	$231C	;
  13249 G007_TEMP_BYTE_0		equ	$231A	;	9886	231A 	7	Temporary variables for PLOT routine.			
  13250 G007_TEMP_BYTE_1		equ	$231B
  13251 
  13252 G007_TEMP_WORD_1		equ	$231C	;
  13253 ;G007_TEMP_BYTE_2		equ	$231C
  13254 ;G007_TEMP_BYTE_3		equ	$231D
  13255 
  13256 G007_TEMP_WORD_2		equ	$231E	;
  13257 G007_TEMP_BYTE_4		equ	$231E
  13258 G007_TEMP_BYTE_5		equ	$231F
  13259 
  13260 G007_TEMP_BYTE_6		equ	$2320
  13261 G007_OUT_OF_RANGE_FLAGS		equ	$2321	;	8993	2321	1	Plot out of range flags. Bit 7 = latest statement			
  13262 G007_UNUSED			equ	$2322	;	8994	2322	1	Not used		
  13263 G007_PLOT_X			equ	$2323	;	8995	2323	2	X co-ordinate for PLOT. Signed 16-bit			
  13264 G007_PLOT_Y			equ	$2325	;	8997	2325	2	Y co-ordinate for PLOT. Signed 16-bit			
  13265 G007_PLOT_X_PREVIOUS_N1		equ	$2327	;	8999	2327	8	X and Y co-ordinates for previous two statements			
  13266 G007_PLOT_Y_PREVIOUS_N1		equ	$2329
  13267 G007_PLOT_X_PREVIOUS_N2		equ	$232B
  13268 G007_PLOT_Y_PREVIOUS_N2		equ	$232D
  13269 G007_FLAG_4			equ	$232F	;	9007	232F 	1	Flags			
  13270 G007_ORIGIN_Y			equ	$2330	;	9008	2330	2	Y co-ordinate of graphics origin			
  13271 G007_ORIGIN_X			equ	$2332	;	9010	2332	2	X co-ordinate of graphics origin			
  13272 G007_LINE_TYPE			equ	$2334	;	9012	2334	4	Bytes defining four line types			
  13273 G007_TEMP_BYTE_7		equ	$2338	;	9016	2338	2	Temporary variable for PLOT			
  13274 G007_TEMP_BYTE_8		equ	$2339	;
  13275 G007_V23A0			equ	$23A0
  13276 ;===============================
  13277 ; G007 RAM routines
  13278 ;===============================
  13279 ; Yes, there is such a thing!
  13280 L23B8				equ	$23B8
  13281 ;===============================
  13282 ; G007 ROM routines
  13283 ;===============================
  13284 L2BF7		equ	$2BF7	; invalid opcode address
  13285 SLOW_FAST_007	equ	$2D08	; new!
  13286 ;===============================
  13287 ; Needed by zasm:
  13288 #target	rom		; declare target file format
  13289 #code	$2800,$0800	; declare code segment start and size	
  13290 ;
  13291 ;===============================
  13292 ; G007 ROM assembly code
  13293 ;===============================
  13294 ; Start of ROM contents;
  13295 ; 10240/12287 : 2800/2FFF	
  13296 ;===============================
  13297 G007_GET_PIXEL_ADDRESS_AND_MASK:	;	
  13298 	LD	HL,(G007_PLOT_X)	; X co-ordinate for PLOT. Signed 16-bit. Fetch 16 bits	
  13299 L2803:	
  13300 	LD	A,(G007_PLOT_Y)	; Y co-ordinate for PLOT. Signed 16-bit. Fetch 8 bits	
  13301 	LD	H,A	; and store in H	
  13302 L2807:	
  13303 	EX	DE,HL	; then swap it into D	
  13304 	LD	A,(G007_DISPLAY_HEIGHT)	
  13305 	DEC	A;	
  13306 	SUB	D	;	
  13307 	LD	D,A	
  13308 	LD	A,7	; A must be 0 to 7	
  13309 	AND	A,E	; E is the LS byte of the X co-ordinate	
  13310 	LD	L,A	; L = A	= selects bit-mask	
  13311 	LD	H,$2D	; bit-mask array is at $2D00	
  13312 	LD	A,(HL)	; get byte with bit set at appropriate position	
  13313 	
  13314 	LD	HL,(G007_DISPLAY_ADDRESS)	; Start address of hi-res display file	
  13315 ;-------------------------------	
  13316 ; Add two bytes for every line 	
  13317 ;	
  13318 	LD	C,D	; BC = Y coordinate	
  13319 	LD	B,0	
  13320 	ADD	HL,BC	; HL += BC*2	
  13321 	ADD	HL,BC	
  13322 ;-------------------------------
  13323 ; DE /= 8 gets byte offset from left of screen	
  13324 ;	
  13325 	SRL	D	; shift DE right	
  13326 	RR	E	
  13327 	SRL	D	; shift DE right	
  13328 	RR	E	
  13329 	SRL	D	; shift DE right	
  13330 	RR	E	
  13331 	
  13332 	ADD	HL,DE	; HL = G007_DISPLAY_ADDRESS + byte offset of XY-co-ordinates	
  13333 	LD	B,A	; A and B hold the bitmask	
  13334 	RET	; return	
  13335 ;===============================	
  13336 L282C:	
  13337 	LD	A,(G007_OUT_OF_RANGE_FLAGS)	; Plot out of range flags. Bit 7 = latest statement	
  13338 	
  13339 	LD	HL,(G007_PLOT_X_PREVIOUS_N1)	
  13340 	LD	DE,(G007_PLOT_X)		; X co-ordinate for PLOT. Signed 16-bit	
  13341 	
  13342 	EXX	
  13343 	
  13344 	LD	HL,(G007_PLOT_Y)	
  13345 	LD	DE,(G007_PLOT_Y_PREVIOUS_N1)	
  13346 
  13347 						; test two most recent out-of-range flag bits:
  13348 	BIT	6,A	
  13349 	JR	Z,L285E	
  13350 	BIT	7,A	
  13351 	RET	NZ	
  13352 	
  13353 	LD	A,(G007_FLAG_Y);	
  13354 	PUSH	AF	
  13355 	LD	B,8
  13356 ;-------------------------------	
  13357 loop_284B:	
  13358 	RRCA
  13359 
  13360 ;284C   FD;CB;21;16      LD C,SLA (IY+CH_ADD-RAMBASE)     output from VB81 disassembler
  13361 
  13362 #if 1
  13363 	RL	(IY+G007_FLAG_Y-RAMBASE)	; makes FD CB 21 16	- correct!
  13364 #else						; force bytes
  13365 	defb	$FD
  13366 	defb	$CB
  13367 	defb	$21
  13368 	defb	$16
  13369 #endif
  13370 	DJNZ	loop_284B	
  13371 ;-------------------------------
  13372 	EX	DE,HL	
  13373 	EXX	
  13374 	EX	DE,HL	
  13375 	EXX	
  13376 	CALL	L285E	
  13377 	POP	AF	
  13378 	LD	(G007_FLAG_Y),A;	
  13379 	RET	
  13380 ;===============================
  13381 L285E:	
  13382 	LD	BC,-HRG_BYTES_PER_LINE		; NB negative number = $FFDE
  13383 	LD	A,(G007_DISPLAY_HEIGHT)	
  13384 	DEC	A	
  13385 	SUB	E	
  13386 	SBC	HL,DE	
  13387 	JP	P,L2876
  13388 ;-------------------------------
  13389 	LD	BC,HRG_BYTES_PER_LINE
  13390 	LD	A,E	
  13391 	
  13392 	PUSH	DE	
  13393 	ADD	HL,DE	
  13394 	EX	DE,HL	
  13395 	OR	A,A	
  13396 	SBC	HL,DE	
  13397 	POP	DE	
  13398 ;-------------------------------
  13399 L2876:	
  13400 	PUSH	HL	
  13401 	LD	H,E	
  13402 	LD	E,A	
  13403 	EXX	
  13404 
  13405 	LD	BC,L28FB	
  13406 	LD	A,L	
  13407 	EXX	
  13408 	LD	L,A	
  13409 	EXX	
  13410 	OR	A,A	
  13411 	SBC	HL,DE	
  13412 	JP	P,L2890	; [10384]	
  13413 ;-------------------------------
  13414 	LD	BC,L2904	
  13415 	CPL	
  13416 	ADD	HL,DE	
  13417 	EX	DE,HL	
  13418 	OR	A,A	
  13419 	SBC	HL,DE	
  13420 L2890:	
  13421 	LD	(G007_TEMP_BYTE_0),BC	; Temporary variables for PLOT routine. 	
  13422 	POP	DE	
  13423 	OR	A,A	
  13424 	SBC	HL,DE	
  13425 	ADD	HL,DE	
  13426 	JR	NC,L28A4	
  13427 ;-------------------------------
  13428 	EX	DE,HL	
  13429 
  13430 	LD	BC,L28F6	
  13431 	EXX	
  13432 	LD	D,E	
  13433 	LD	E,A	
  13434 	LD	A,D	
  13435 	EXX	
  13436 L28A4:
  13437 	LD	(G007_TEMP_WORD_1),BC	
  13438 	EXX	
  13439 	LD	D,A	
  13440 ;-------------------------------
  13441 	PUSH	DE	
  13442 	EXX	
  13443 	POP	BC	
  13444 ;-------------------------------
  13445 	LD	A,(G007_OUT_OF_RANGE_FLAGS)	; Plot out of range flags. Bit 7 = latest statement	
  13446 	CP	$40	
  13447 	JR	NC,L28B6	
  13448 ;-------------------------------	
  13449 	LD	B,L	; BC = LE	
  13450 	LD	C,E	
  13451 ;-------------------------------
  13452 L28B6:	
  13453 	INC	B	
  13454 	INC	C	
  13455 ;-------------------------------
  13456 L28B8:	
  13457 	SRL	H	
  13458 	JR	C,L28BE	
  13459 	
  13460 	JR	Z,L28C6	
  13461 ;-------------------------------
  13462 L28BE:	
  13463 	RR	L	
  13464 	SRL	D	
  13465 	RR	E	
  13466 	JR	L28B8	
  13467 ;-------------------------------
  13468 L28C6:	
  13469 	LD	D,L	
  13470 	SRL	L	
  13471 	EXX	
  13472 	PUSH	BC	
  13473 	CALL	L2807	
  13474 	POP	DE	
  13475 	LD	A,(G007_TEMP_BYTE_5)	
  13476 	LD	C,A	
  13477 ;-------------------------------
  13478 L28D3:
  13479 ;	Bytes from disassembler:
  13480 ;28D3   FD;CB;21;06      LD C,SLA (IY+6)      
  13481 #if 1
  13482 	RLC (IY+G007_FLAG_Y-RAMBASE)   ; makes FD CB 21 06
  13483 #else
  13484 ;	force bytes
  13485 	defb	$FD
  13486 	defb	$CB
  13487 	defb	$21
  13488 	defb	$06
  13489 #endif
  13490 	
  13491 	JR	C,L28E1	
  13492 ;-------------------------------
  13493 	LD	A,(G007_TEMP_BYTE_4)	
  13494 	XOR	A,(HL)	
  13495 	OR	A,C	
  13496 	AND	A,B	
  13497 	XOR	A,(HL)	
  13498 	LD	(HL),A	
  13499 ;-------------------------------
  13500 L28E1:
  13501 	EXX	
  13502 
  13503 	LD	A,L	
  13504 	DEC	B	
  13505 	RET	Z	
  13506 ;-------------------------------
  13507 	SUB	E	
  13508 	JR	NC,L28F2	
  13509 ;-------------------------------
  13510 	DEC	C	
  13511 	RET	Z	
  13512 ;-------------------------------
  13513 	ADD	A,D	
  13514 	EXX	
  13515 	ADD	HL,DE	
  13516 	EXX	
  13517 	LD	HL,(G007_TEMP_BYTE_0)	; Temporary variables for PLOT routine.	
  13518 	JP	(HL)
  13519 ;-------------------------------
  13520 L28F2:	
  13521 	LD	HL,(G007_TEMP_WORD_1)	
  13522 	JP	(HL)
  13523 ;-------------------------------
  13524 L28F6:
  13525 	LD	L,A	
  13526 	EXX	
  13527 	ADD	HL,DE	
  13528 	JR	L28D3
  13529 ;-------------------------------
  13530 L28FB:	
  13531 	LD	L,A	
  13532 	EXX	
  13533 	RLC	B	
  13534 	JR	NC,L28D3	
  13535 ;-------------------------------
  13536 	DEC	HL	
  13537 	JR	L28D3
  13538 ;-------------------------------
  13539 L2904:
  13540 	LD	L,A	
  13541 	EXX
  13542 		
  13543 	RRC	B	
  13544 	JR	NC,L28D3	
  13545 ;-------------------------------
  13546 	INC	HL	
  13547 	JR	L28D3	
  13548 ;-------------------------------
  13549 G007_INTEGER_FROM_STACK_TO_BC:	
  13550 	LD	HL,(L0EA8)	; Inside the 'FIND_INT.' subroutine	
  13551 				; 0EA7 FIND_INT	CALL	158A,FP_TO_BC	
  13552 				; so 0EA8 should contain $158A, pointing to the FP_TO_BC routine	
  13553 	JP	(HL)		; exit	
  13554 ;===============================	
  13555 G007_INTEGER_FROM_STACK_TO_HL:	
  13556 	CALL	G007_INTEGER_FROM_STACK_TO_BC	; get an integer	
  13557 	JR	C,L2924	
  13558 ;-------------------------------
  13559 	LD	HL,0	
  13560 	JR	Z,L2921	
  13561 ;-------------------------------
  13562 	SBC	HL,BC		; HL = 0 - BC	
  13563 	RET	M	
  13564 	RET	Z	
  13565 ;-------------------------------
  13566 	JR	L2924
  13567 ;-------------------------------
  13568 L2921:
  13569 	ADC	HL,BC
  13570 	RET	P
  13571 ;-------------------------------
  13572 L2924:	
  13573 	POP	HL	
  13574 	RET	
  13575 ;===============================
  13576 ;	
  13577 G007_PLOT_UNPLOT_N_X_Y:				; takes parameters from the stack
  13578 ;
  13579 	CALL	G007_INTEGER_FROM_STACK_TO_HL	; get Y
  13580 	LD	(G007_PLOT_Y),HL	
  13581 	CALL	G007_INTEGER_FROM_STACK_TO_HL	; get X
  13582 	PUSH	HL	
  13583 	CALL	STK_TO_A			; get N
  13584 						;
  13585 	POP	BC				; BC = X
  13586 	LD	DE,(G007_PLOT_Y)		; DE = Y
  13587 	JR	Z,G007_PLOT			; 
  13588 	DEC	A				; if (N-1) is zero
  13589 	RET	NZ	
  13590 ;-------------------------------
  13591 	LD	HL,L0C9C			; then T_ADDR = HL = L0C9C
  13592 	LD	(T_ADDR),HL			; 
  13593 ;-------------------------------
  13594 L2942:	
  13595 	LD	B,E	
  13596 	JP	L0BB2				; []*BIOS ROM*	
  13597 ;===============================	
  13598 ; The Plot Routine:	
  13599 ; A  == the plot number N	
  13600 ; BC == screen X	
  13601 ; DE == screen Y	
  13602 ;-------------------------------
  13603 G007_PLOT:	
  13604 	OR	A,A	
  13605 	JR	Z,L2942	
  13606 ;-------------------------------
  13607 	DEC	A				; when PLOT N value is decremented, bits make more sense	
  13608 ;-------------------------------
  13609 	PUSH	DE				; push screen Y	
  13610 	PUSH	BC				; push screen X	
  13611 	PUSH	AF				; push plot number-1	
  13612 	
  13613 	CALL	G007_CHECK_AND_SET_UP_DISPLAY_FILE	
  13614 	
  13615 	POP	AF	
  13616 	POP	DE	
  13617 	POP	BC				; NB BC and DE are swapped
  13618 ;-------------------------------
  13619 	CP	$81				; Was A=129 (PLOT 130 sets graphics origin)	
  13620 	JR	NZ,G007_PLOT_XY_TO_HISTORY	
  13621 
  13622 ;-------------------------------
  13623 G007_ORIGIN_SET:	
  13624 	;	
  13625 	LD	(G007_ORIGIN_Y),DE		; Y co-ordinate of graphics origin	
  13626 	LD	(G007_ORIGIN_X),BC		; X co-ordinate of graphics origin	
  13627 	LD	BC,$0000			; BC = 0	
  13628 	LD	D,B				; DE = BC = 0	
  13629 	LD	E,B	
  13630 	LD	A,$0B	
  13631 
  13632 ;-------------------------------
  13633 G007_PLOT_XY_TO_HISTORY:	
  13634 	;	
  13635 	BIT	2,A;			; the (PLOT_N -1)
  13636 	JR	Z,G007_PLOT_ABSOLUTE	
  13637 
  13638 ;-------------------------------	
  13639 G007_PLOT_RELATIVE:			;	
  13640 	LD	HL,(G007_PLOT_Y_PREVIOUS_N1)	
  13641 	PUSH	HL	
  13642 	LD	HL,(G007_PLOT_X_PREVIOUS_N1)	
  13643 	JR	G007_PLOT_ABSOLUTE_OR_RELATIVE	
  13644 ;===============================
  13645 G007_PLOT_ABSOLUTE:	
  13646 	LD	HL,(G007_ORIGIN_X)	; X co-ordinate of graphics origin	
  13647 	PUSH	HL	
  13648 	LD	HL,(G007_ORIGIN_Y)	; Y co-ordinate of graphics origin	
  13649 ;-------------------------------	;
  13650 					; 
  13651 G007_PLOT_ABSOLUTE_OR_RELATIVE:		;	
  13652 	OR	A,A			; update flags
  13653 	ADC	HL,DE			; HL = G007_PLOT_Y + G007_ORIGIN_Y	
  13654 	POP	DE			; DE = G007_PLOT_X co-ordinate of graphics origin
  13655 	RET	PE			
  13656 ;-------------------------------
  13657 	LD	(G007_PLOT_X),HL	; record plot X 	
  13658 	EX	DE,HL	
  13659 	OR	A,A			; restore Flags 
  13660 	ADC	HL,BC			; HL = G007_PLOT_X + G007_ORIGIN_X	
  13661 	RET	PE
  13662 ;-------------------------------
  13663 	LD	(G007_PLOT_Y),HL	; record plot Y 	
  13664 	LD	E,A	
  13665 	LD	A,%11000000		; $C0
  13666 	AND	A,H			; 	
  13667 	RET	PO;	
  13668 ;-------------------------------
  13669 	LD	A,%11000000		; $C0
  13670 	AND	A,D	
  13671 	RET	PO	
  13672 ;-------------------------------	; push alternate HL,DE,BC
  13673 	EXX	
  13674 	PUSH	HL	
  13675 	PUSH	DE	
  13676 	PUSH	BC	
  13677 	CALL	G007_RANGE_CHECK
  13678 ;-------------------------------	; pop alternate BC,DE,HL
  13679 L299A:	
  13680 	POP	BC	
  13681 	POP	DE	
  13682 	POP	HL	
  13683 	EXX	
  13684 	RET	
  13685 ;===============================
  13686 G007_RANGE_CHECK:	
  13687 	EXX	
  13688 	LD	A,H	; A = H OR D	
  13689 	OR	A,D	
  13690 	SCF	
  13691 	JR	NZ,G007_RANGE_CHECK_UPDATE	; if not zero, out of range already so ignore display height	
  13692 ;-------------------------------
  13693 	LD	A,(G007_DISPLAY_HEIGHT)		; check Y coordinate 
  13694 	DEC	A				; if (G007_DISPLAY_HEIGHT - Y ) is less than zero,
  13695 	CP	L				; set the Carry flag
  13696 ;-------------------------------
  13697 G007_RANGE_CHECK_UPDATE:			; latest flag in Carry is shifted into history flags
  13698 	LD	A,(G007_OUT_OF_RANGE_FLAGS)	; 	
  13699 	RRA					; shift bits right. Bit 7 = latest statement	
  13700 	LD	(G007_OUT_OF_RANGE_FLAGS),A	; 	
  13701 	LD	A,E				; E bit 7
  13702 	BIT	7,A	
  13703 	JR	Z,L29BA	
  13704 ;-------------------------------		; gets here if PLOT_N is over 130
  13705 	LD	HL,(G007_PLOT_ROUTINES_VECTOR)	; Vector for additional plot routines	
  13706 	JP	(HL)				; This looks very promising,
  13707 						; makes it easy to bolt-on extra graphics routines
  13708 ;===============================
  13709 L29BA:	
  13710 	PUSH	AF	
  13711 	AND	3	
  13712 	RRA	
  13713 	DEC	A	
  13714 	CPL	
  13715 	LD	H,A	
  13716 	SBC	A,A	
  13717 	LD	L,A	
  13718 	LD	(G007_TEMP_WORD_2),HL	
  13719 	PUSH	HL	
  13720 	BIT	3,E	
  13721 	JR	NZ,L29F3	
  13722 ;-------------------------------
  13723 	LD	A,(G007_TEMP_BYTE_6)	
  13724 	XOR	A,E	
  13725 	AND	%11111011			; $FB. Bit 2 ignored
  13726 	JR	Z,L29E2	
  13727 ;-------------------------------
  13728 	LD	HL,G007_LINE_TYPE	
  13729 	LD	A,E	
  13730 ;-------------------------------		; A *= 8
  13731 	RLCA		
  13732 	RLCA	
  13733 	RLCA	
  13734 ;-------------------------------
  13735 	AND	$03	
  13736 	ADD	A,L	
  13737 	LD	L,A	
  13738 	LD	A,(HL)	
  13739 	LD	(G007_FLAG_Y),A;
  13740 ;-------------------------------
  13741 L29E2:	
  13742 	CALL	L282C;	
  13743 	POP	HL	
  13744 
  13745 ;-------------------------------
  13746 ;	Bytes from disassembler:	29E6   FD;CB;21;0E      LD C,SLA (IY+14)
  13747 
  13748 	RRC (IY+G007_FLAG_Y-RAMBASE)		; makes FD CB 21 0E	
  13749 	JR	C,L2A12	
  13750 ;===============================	
  13751 	LD	A,H				; A = H and L
  13752 	AND	A,L	
  13753 	JR	Z,L2A12	
  13754 ;-------------------------------
  13755 	INC	L	
  13756 	LD	E,L	
  13757 	PUSH	HL	
  13758 ;-------------------------------
  13759 L29F3:	
  13760 	LD	A,(G007_OUT_OF_RANGE_FLAGS)	; Bit 7 = latest statement	
  13761 	BIT	5,E				
  13762 	JR	NZ,G007_TRIANGLE_PLAIN	
  13763 ;-------------------------------
  13764 	BIT	6,E	
  13765 	JR	NZ,G007_TRIANGLE_TEXTURED	
  13766 ;-------------------------------
  13767 	POP	HL	
  13768 	BIT	7,A	
  13769 	JR	NZ,L2A12	
  13770 ;-------------------------------
  13771 	PUSH	HL	
  13772 	CALL	G007_GET_PIXEL_ADDRESS_AND_MASK	
  13773 	AND	A,(HL)	
  13774 	LD	(G007_READ_POINT_BYTE),A	; "Read-point" byte. Non-zero if pixel is set.	
  13775 	POP	DE	
  13776 	LD	A,(HL)	
  13777 	OR	A,D	
  13778 	XOR	A,E	
  13779 	AND	A,B	
  13780 	XOR	A,(HL)	
  13781 	LD	(HL),A
  13782 ;-------------------------------
  13783 L2A12:	
  13784 	POP	AF	
  13785 	LD	(G007_TEMP_BYTE_6),A	
  13786 	LD	HL,G007_PLOT_Y_PREVIOUS_N1+1	
  13787 	LD	DE,G007_PLOT_Y_PREVIOUS_N2+1	
  13788 	LD	BC,8	
  13789 	BIT	4,A	
  13790 	JR	Z,L2A34	
  13791 ;-------------------------------
  13792 	LD	A,(G007_OUT_OF_RANGE_FLAGS)	; Plot out of range flags. Bit 7 = latest statement	
  13793 	AND	$C0	; only want most recent two bits	
  13794 	RLA	
  13795 	JR	NC,L2A2D	
  13796 	SET	6,A	; carry flag into bit 6 of A	
  13797 ;-------------------------------
  13798 L2A2D:	
  13799 	LD	(G007_OUT_OF_RANGE_FLAGS),A	
  13800 	LD	L,$26	
  13801 	LD	C,4	
  13802 ;-------------------------------
  13803 L2A34:	
  13804 	LDDR					; (DE--)=(HL--); BC-- UNTIL BC IS ZERO	
  13805 	RET	
  13806 ;===============================
  13807 G007_TRIANGLE_PLAIN:	
  13808 	LD	HL,ALL_BITS_SET	
  13809 	JR	G007_TRIANGLE_TEXTURED_BY_HL	
  13810 ;===============================
  13811 G007_TRIANGLE_TEXTURED:	
  13812 	LD	HL,(G007_TRIANGLE_TEXTURE)	; Bytes defining triangle texture
  13813 ;-------------------------------
  13814 G007_TRIANGLE_TEXTURED_BY_HL:	
  13815 	EXX	
  13816 	AND	$E0	; = 224	
  13817 	JP	NZ,REPORT_B;	
  13818 ;-------------------------------
  13819 L2A45:	
  13820 	LD	HL,G007_OUT_OF_RANGE_FLAGS	
  13821 	LD	(IY+G007_FLAG_Y-RAMBASE),$55	
  13822 	LD	B,3	
  13823 ;-------------------------------
  13824 loop_2A4E:	
  13825 	INC	HL		; HL+=2	
  13826 	INC	HL	
  13827 	LD	E,(HL)	
  13828 	INC	HL		; HL+=2	
  13829 	INC	HL	
  13830 	LD	D,(HL)	
  13831 	PUSH	DE	
  13832 	DJNZ	loop_2A4E	; BC--	
  13833 ;-------------------------------
  13834 	POP	BC		; restore register pairs	
  13835 	POP	DE	
  13836 	POP	HL	
  13837 ;-------------------------------
  13838 	OR	A,A		
  13839 	JR	Z,L2A5F	
  13840 ;-------------------------------
  13841 	LD	B,H		; BC=HL	
  13842 	LD	C,L	
  13843 ;-------------------------------
  13844 L2A5F:	
  13845 	LD	A,B	
  13846 	CP	H	
  13847 	JR	NC,L2A66	
  13848 ;-------------------------------
  13849 	PUSH	BC	
  13850 	EX	(SP),HL	
  13851 	POP	BC	
  13852 ;-------------------------------
  13853 L2A66:	
  13854 	LD	A,H	
  13855 	CP	D	
  13856 	JR	NC,L2A6B	
  13857 ;-------------------------------
  13858 	EX	DE,HL	
  13859 ;-------------------------------
  13860 L2A6B:	
  13861 	LD	A,D	
  13862 	EXX	
  13863 	AND	7	
  13864 	INC	A	
  13865 	LD	B,A	
  13866 	LD	A,H	
  13867 ;-------------------------------
  13868 loop_2A72:	
  13869 	RLC	L	; L *= 2	
  13870 ;-------------------------------
  13871 	RLCA		; A *= 8	
  13872 	RLCA	
  13873 	RLCA	
  13874 ;-------------------------------
  13875 	DJNZ	loop_2A72	; loop while BC-- is not zero	
  13876 ;-------------------------------
  13877 	LD	H,A	
  13878 	LD	(G007_TEMP_BYTE_7),HL	; Temporary variable for PLOT	
  13879 	EXX	
  13880 ;-------------------------------
  13881 	LD	A,H	
  13882 	CP	B	
  13883 	LD	A,7	
  13884 	JR	NC,L2A87
  13885 ;-------------------------------
  13886 loop_2A84:	
  13887 	PUSH	BC	
  13888 	EX	(SP),HL	
  13889 	POP	BC	
  13890 ;-------------------------------
  13891 L2A87:	
  13892 	EX	DE,HL	
  13893 	PUSH	AF	
  13894 	LD	A,C	
  13895 	EXX	
  13896 	LD	H,A	
  13897 	LD	L,A	
  13898 	LD	C,A	
  13899 	LD	(G007_TEMP_BYTE_0),HL	; Temporary variables for PLOT routine. 	
  13900 	LD	B,$FE	
  13901 	EXX	
  13902 	SUB	E	
  13903 	EXX	
  13904 ;-------------------------------
  13905 	JR	NC,skip_2A9C	
  13906 	LD	B,$00	
  13907 	NEG	
  13908 skip_2A9C:	
  13909 ;-------------------------------
  13910 	LD	D,A	
  13911 	EXX	
  13912 	LD	A,D	
  13913 	SUB	B	
  13914 	EXX	
  13915 	LD	H,A	
  13916 ;-------------------------------
  13917 	CP	D	
  13918 	JR	NC,skip_2AA7	
  13919 	EX	DE,HL	
  13920 	INC	B	
  13921 skip_2AA7:	
  13922 ;-------------------------------
  13923 	LD	L,H	
  13924 	INC	L	
  13925 	LD	E,H	
  13926 	SRL	E	
  13927 
  13928 	POP	AF	
  13929 	RRCA	
  13930 	JR	NC,L2AB9	
  13931 ;-------------------------------
  13932 	PUSH	HL	
  13933 ;-------------------------------
  13934 	PUSH	DE	
  13935 	PUSH	BC	
  13936 ;-------------------------------
  13937 	RRCA	
  13938 	EXX	
  13939 ;-------------------------------
  13940 	JR	C,loop_2A84	
  13941 	JR	L2A87	
  13942 ;===============================
  13943 L2AB9:	
  13944 	EXX	
  13945 	LD	H,B	
  13946 	LD	L,1
  13947 ;-------------------------------
  13948 loop_2ABD:
  13949 	POP	BC	
  13950 	POP	DE	
  13951 ;-------------------------------
  13952 	EX	(SP),HL	
  13953 ;-------------------------------
  13954 L2AC0:	
  13955 	DEC	L	
  13956 	JR	NZ,L2AD9	
  13957 ;-------------------------------
  13958 	LD	HL,(G007_TEMP_BYTE_0)	; Temporary variables for PLOT routine.	
  13959 	LD	A,C	
  13960 ;-------------------------------
  13961 	CP	H	
  13962 	JR	C,skip_2ACB	
  13963 	LD	H,A	
  13964 skip_2ACB:	
  13965 ;-------------------------------
  13966 	CP	L
  13967 	JR	NC,skip_2ACF	
  13968 	LD	L,A	
  13969 skip_2ACF:	
  13970 ;-------------------------------
  13971 	LD	(G007_TEMP_BYTE_0),HL	; Temporary variables for PLOT routine. 	
  13972 	POP	HL	
  13973 	DEC	L	
  13974 ;-------------------------------
  13975 L2AD4:	
  13976 	
  13977 	JR	Z,loop_2ABD	
  13978 	
  13979 	PUSH	HL	
  13980 	JR	L2AEE	
  13981 ;-------------------------------
  13982 L2AD9:	
  13983 	LD	A,E	
  13984 	SUB	D	
  13985 	JR	C,L2AE7	
  13986 ;-------------------------------
  13987 	LD	E,A	
  13988 	BIT	0,B	
  13989 	JR	Z,L2AEE	
  13990 ;-------------------------------
  13991 	LD	A,C	
  13992 	ADD	A,B	
  13993 	LD	C,A	
  13994 	JR	L2AC0	
  13995 ;-------------------------------
  13996 L2AE7:	
  13997 	ADD	A,H	
  13998 	LD	E,A	
  13999 	LD	A,1	
  14000 	OR	A,B	
  14001 	ADD	A,C	
  14002 	LD	C,A	
  14003 ;-------------------------------
  14004 L2AEE:	
  14005 	LD	A,C	
  14006 	EXX
  14007 ;-------------------------------
  14008 	RRC	(IY+G007_FLAG_Y-RAMBASE)   ; makes FD CB 21 0E
  14009 
  14010 	JR	C,L2AC0				; if 
  14011 ;-------------------------------
  14012 	EX	(SP),HL	
  14013 ;-------------------------------
  14014 	PUSH	DE	
  14015 	PUSH	BC	
  14016 	PUSH	HL	
  14017 ;-------------------------------
  14018 	LD	DE,(G007_TEMP_BYTE_0)	
  14019 	LD	B,A	
  14020 ;-------------------------------
  14021 	CP	C	
  14022 	JR	NC,skip_2B04	
  14023 	LD	B,C	
  14024 	LD	C,A	
  14025 skip_2B04:	
  14026 ;-------------------------------
  14027 	LD	(G007_TEMP_BYTE_0),BC	
  14028 	LD	A,C	
  14029 ;-------------------------------
  14030 	CP	E	
  14031 	INC	A	
  14032 	JR	C,skip_2B0E	
  14033 	LD	A,E	
  14034 skip_2B0E:	
  14035 ;-------------------------------
  14036 	LD	L,A	
  14037 	LD	A,D	
  14038 ;-------------------------------
  14039 	CP	B	
  14040 	JR	NC,skip_2B15	
  14041 	LD	A,B	
  14042 	DEC	A
  14043 skip_2B15:	
  14044 ;-------------------------------
  14045 	SUB	L	
  14046 	INC	A	
  14047 	PUSH	AF	
  14048 	CALL	L2807	
  14049 	
  14050 	POP	AF	
  14051 	LD	C,A	
  14052 	EX	DE,HL	
  14053 	LD	HL,G007_TEMP_BYTE_8	
  14054 	LD	A,(HL)	
  14055 ;-------------------------------	
  14056 	RLCA	
  14057 	RLCA	
  14058 	RLCA	
  14059 ;-------------------------------
  14060 	LD	(HL),A	
  14061 	DEC	HL	
  14062 	RLC	(HL)	
  14063 	OR	A,(HL)	
  14064 	LD	HL,(G007_TEMP_WORD_2)	
  14065 	XOR	A,L	
  14066 	CPL	
  14067 	LD	L,A	
  14068 	EX	DE,HL	
  14069 ;-------------------------------
  14070 loop_2B31:
  14071 	LD	A,E	
  14072 	XOR	A,(HL)	
  14073 	OR	A,D	
  14074 	AND	A,B	
  14075 	XOR	A,(HL)	
  14076 	LD	(HL),A 	
  14077 ;-------------------------------
  14078 loop_2B37:	
  14079 	DEC	C	
  14080 	JR	NZ,L2B4E	
  14081 ;-------------------------------
  14082 	POP	HL	
  14083 	INC	H	
  14084 	BIT	7,L	
  14085 	JR	Z,L2AD4	
  14086 ;-------------------------------	; discard 3 words from stack
  14087 	POP	HL	
  14088 	POP	HL	
  14089 	POP	HL	
  14090 ;-------------------------------
  14091 	POP	HL	
  14092 	LD	A,H	
  14093 	AND	A,L	
  14094 	JP	Z,L2A12	
  14095 ;-------------------------------
  14096 	INC	L	
  14097 	PUSH	HL	
  14098 	JP	L2A45	
  14099 ;-------------------------------
  14100 L2B4E:	
  14101 	RR	B	
  14102 	JR	NC,loop_2B31	
  14103 ;-------------------------------
  14104 	INC	HL	
  14105 	LD	B,C	
  14106 	LD	A,C	
  14107 	AND	$07	
  14108 	LD	C,A	
  14109 ;-------------------------------
  14110 	SRL	B	; B *= 8	
  14111 	SRL	B	
  14112 	SRL	B	
  14113 ;-------------------------------
  14114 	JR	Z,L2B68	
  14115 ;-------------------------------
  14116 loop_2B60:
  14117 	LD	A,E	
  14118 	XOR	A,(HL)	
  14119 	OR	A,D	
  14120 	XOR	A,(HL)	
  14121 	LD	(HL),A	
  14122 	INC	HL	
  14123 	DJNZ	loop_2B60	
  14124 ;-------------------------------
  14125 L2B68:	
  14126 	SCF	
  14127 	INC	C	
  14128 	JR	loop_2B37	
  14129 ;-------------------------------
  14130 L2B6C:
  14131 	LD	HL,(G007_FLAG_1)	
  14132 	DEC	L	
  14133 	OR	A,L	
  14134 	JP	NZ,L0809	; iii) Testing S-POSN: 0808 ENTER-CH	LD	D,A	
  14135 				; G007 skips that first instruction though.
  14136 ;-------------------------------
  14137 
  14138 	DEC	H				; if --H, 
  14139 	JP	NZ,L23B8			; then jump to modified copy of a ZX81 routine, in RAM.
  14140 ;-------------------------------		; 
  14141 	LD	A,(G007_OUT_OF_RANGE_FLAGS)	; Plot out of range flags. Bit 7 = latest statement	
  14142 	RLA	
  14143 	RET	C	
  14144 ;-------------------------------
  14145 	NOP	
  14146 	NOP	
  14147 	LD	HL,(G007_PLOT_X_PREVIOUS_N1+1)	
  14148 	LD	A, (G007_PLOT_X_PREVIOUS_N1)	
  14149 	BIT	6,D	
  14150 ;-------------------------------
  14151 mark_2B87:
  14152 	JR	NZ,L2B8E	; 20;05
  14153 	
  14154 	LD	L,A	
  14155 	ADD	A,8
  14156 	JR	NC,L2B9B	
  14157 ;-------------------------------
  14158 L2B8E:	
  14159 	LD	A,H	
  14160 ;-------------------------------
  14161 	SUB	8	
  14162 	JR	NC,skip_2B97	
  14163 	LD	A,(G007_DISPLAY_HEIGHT)	
  14164 	DEC	A	
  14165 skip_2B97:
  14166 ;-------------------------------
  14167 	LD	(G007_PLOT_Y_PREVIOUS_N1),A;	
  14168 	XOR	A,A	; A = 0
  14169 ;-------------------------------
  14170 L2B9B:
  14171 	LD	(G007_PLOT_X_PREVIOUS_N1),A	
  14172 	BIT	6,D	
  14173 	RET	NZ	
  14174 ;-------------------------------
  14175 	CALL	L2EEF	
  14176 	
  14177 	LD	A,L	
  14178 ;-------------------------------
  14179 	CP	$F9	
  14180 	JR	C,skip_2BAB	
  14181 	LD	E,2	
  14182 skip_2BAB:	
  14183 ;-------------------------------
  14184 	CPL	
  14185 	AND	7	
  14186 	INC	A	
  14187 	LD	D,A	
  14188 	LD	A,H	
  14189 	INC	A	
  14190 	EXX
  14191 
  14192 	LD	D,A	
  14193 	EXX	
  14194 	PUSH	DE	
  14195 	CALL	L2807	
  14196 	EXX	
  14197 ;-------------------------------
  14198 L2BBA:
  14199 	LD	A,C	
  14200 	XOR	A,(HL)	
  14201 	EXX	
  14202 	EX	DE,HL	
  14203 LXXX:
  14204 	POP	BC	
  14205 	PUSH	BC	
  14206 	LD	L,A	
  14207 	LD	H,$00
  14208 ;-------------------------------
  14209 loop_2BC3:
  14210 	ADD	HL,HL	
  14211 	DJNZ	loop_2BC3	
  14212 ;-------------------------------
  14213 	EX	DE,HL	
  14214 	LD	B,2
  14215 ;-------------------------------
  14216 L2BC9:	
  14217 	LD	A,(G007_RESTART);	
  14218 	XOR	A,(HL)	
  14219 	OR	A,(IY+G007_RESTART+1-RAMBASE)	
  14220 	AND	A,D	
  14221 	XOR	A,(HL)	
  14222 ;-------------------------------
  14223 	DEC	C	
  14224 	JR	Z,skip_2BD6	
  14225 	LD	(HL),A
  14226 skip_2BD6:	
  14227 ;-------------------------------
  14228 	LD	D,E	
  14229 	INC	HL	
  14230 	DJNZ	L2BC9	
  14231 ;-------------------------------
  14232 	LD	C,$20	
  14233 	ADD	HL,BC	
  14234 	EXX	
  14235 	INC	HL	
  14236 ;-------------------------------
  14237 	DEC	D	
  14238 	JR	Z,skip_2BE4	
  14239 ;-------------------------------
  14240 	DJNZ	L2BBA	
  14241 ;-------------------------------
  14242 skip_2BE4:
  14243 ;-------------------------------
  14244 	POP	HL	
  14245 	JP	L299A
  14246 ;===============================
  14247 PRINT_007:	
  14248 	LD	A,I		; read graphics mode	
  14249 	RRCA	
  14250 ;-------------------------------
  14251 	JR	NC,skip_2BF5	
  14252 	XOR	A,A		; A = 0	
  14253 	LD	(DF_SZ),A	; SET DF_SZ	
  14254 	INC	A	
  14255 	LD	(G007_FLAG_1),A	
  14256 skip_2BF5:	
  14257 ;-------------------------------
  14258 	CALL	PRINT		; [PRINT]	
  14259 	XOR	A,A		; A = 0	
  14260 	LD	(G007_FLAG_1),A	
  14261 	LD	(IY+DF_SZ-RAMBASE),2	 ; The lines above have no return or jump statements	
  14262 ; They will fall into copy of the end of the STK_TO_BC routine	
  14263 ; Perhaps a cunning trick to save two bytes? :-)
  14264 ;===============================
  14265 ;===============================
  14266 ;===============================
  14267 
  14268 	org	ROM_PATCH_0C00
  14269 ;
  14270 ; 256-byte block patched in to ZX81 BASIC at 0C00 hex	
  14271 ; This cleverly alters the language syntax,	
  14272 ; adding parameters and/or pointing to new routines.	
  14273 ;	
  14274 	LD	C,A	; from the end of the STK_TO_BC routine	
  14275 	RET	
  14276 ;===============================
  14277 ; THE 'STK_TO_A' SUBROUTINE  (duplicated for the paged ROM)	
  14278 	
  14279 ; This subroutine 'loads' the A register with the floating point number held at the top of the calculator stack. The number must be in the range 00-FF.	
  14280 ;-------------------------------
  14281 STK_TO_A:
  14282 
  14283 #if NOT_G007
  14284 ;	CALL	15CD,FP_TO_A	;     This is what the disassembly book says	
  14285 #else
  14286 	CALL	L0CA0		;  new in G007
  14287 #endif
  14288 	JP	C,REPORT_B
  14289 ;-------------------------------
  14290 	LD	C,$01	
  14291 	RET	Z	
  14292 	LD	C,$FF	
  14293 	RET	
  14294 ;===============================
  14295 	
  14296 ; THE 'SCROLL' COMMAND ROUTINE (duplicated for the paged ROM)	
  14297 	
  14298 ; The first part of the routine sets the correct values of DF_CC and S_POSN to allow for the next printing to occur at the start of the bottom line + 1.	
  14299 	
  14300 ; Next the end address of the first line in the display file is identified and the whole of the display file moved to overwrite this line.	
  14301 ;-------------------------------
  14302 
  14303 SCROLL:
  14304 mark_0C0E:
  14305 	LD	B,(IY+DF_SZ-RAMBASE)		; ???	Disassembly book says	LD	B,(DF_SZ)	
  14306 	LD	C,CHARS_HORIZONTAL + 1  ;change here, $21 originally
  14307 	CALL	LOC_ADDR	
  14308 	CALL	ONE_SPACE	
  14309 	LD	A,(HL)	
  14310 	LD	(DE),A	
  14311 
  14312 	INC	(IY+S_POSN_hi-RAMBASE)		; 	
  14313 
  14314 	LD	HL,(D_FILE);	
  14315 	INC	HL	
  14316 	LD	D,H	
  14317 	LD	E,L	
  14318 	CPIR	
  14319 	JP	RECLAIM_1
  14320 ;===============================	
  14321 ;	
  14322 ; THE SYNTAX TABLES	
  14323 ;	
  14324 ; i) The offset table	
  14325 ;	
  14326 ; There is an offset value for each of the BASIC commands and by	
  14327 ; adding this offset to the value of the address where it is found,	
  14328 ; the correct address for the command in the parameter table is	
  14329 ; obtained.	
  14330 	
  14331 ; 2C29: 8B 8D 2D 7F 81 49 75
  14332 
  14333 mark_0C29:
  14334 offset_t:
  14335 
  14336 ;		expression	  address	byte offset expected
  14337 	defb	P_LPRINT-$	; 0CB4		$8B
  14338 	defb	P_LLIST-$	; 0CB1	;	$8D	;
  14339 	defb	P_STOP-$	; 0C58	;	$2D	;
  14340 	defb	P_SLOW-$	; 0CAB	;	$7F	;
  14341 	defb	P_FAST-$	; 0CAE	;	$81	;
  14342 	defb	P_NEW-$		; 0C77	;	$49	;
  14343 	defb	P_SCROLL_007-$	; 0CA4	;	$75	;	
  14344 							; 2C30: 5F 40 42 2B 17 1F 37 52		
  14345 	defb	P_CONT-$	; 0CBF	;	$5F	;
  14346 	defb	P_DIM-$		; 0C71	;	$40	;
  14347 	defb	P_REM-$		; 0C74	;	$42	;
  14348 	defb	P_FOR-$		; 0C5E	;	$2B	;
  14349 	defb	P_GOTO-$	; 0C4B	;	$17	;
  14350 	defb	P_GOSUB-$	; 0C54	;	$1F	;
  14351 	defb	P_INPUT-$	; 0C6D	;	$37	;
  14352 	defb	P_LOAD-$	; 0C89	;	$52	;
  14353 							; 2C38: 45 0F 6D 2B 44 2D 5A 3B	
  14354 	defb	P_LIST-$	; 0C7D	;	$45	;
  14355 	defb	P_LET-$		; 0C48	;	$0F	;
  14356 	defb	P_PAUSE-$	; 0CA7	;	$6D	;
  14357 	defb	P_NEXT-$	; 0C66	;	$2B	;
  14358 	defb	P_POKE-$	; 0C80	;	$44	;
  14359 	defb	P_PRINT-$	; 0C6A	;	$2D	; Same as normal ZX81	
  14360 	defb	P_PLOT_007-$	; 0C98	;	$5A	;
  14361 	defb	P_RUN-$		; 0C7A	;	$3B	;
  14362 							; 2C40: 4C 45 0D 52 54 4D 15 6A	
  14363 	defb	P_SAVE-$	; 0C8C	;	$4C	;
  14364 	defb	P_RAND-$	; 0C86	;	$45	;
  14365 	defb	P_IF-$		; 0C4F	;	$0D	;
  14366 	defb	P_CLS-$		; 0C95	;	$52	;
  14367 	defb	P_UNPLOT_007-$	; 0C98	;	$54	; This byte is 5A, an offset to 0C9E, in normal ZX81	
  14368 							; NB same address as PLOT	
  14369 	defb	P_CLEAR-$	; 0C92	;	$4D	;
  14370 	defb	P_RETURN-$	; 0C5B	;	$15	;
  14371 	defb	P_COPY-$	; 0CB1	;	$6A	;
  14372 ;
  14373 ;	ii) The parameter table.	
  14374 ;
  14375 ;	For each of the BASIC commands there are between 3 and 8	
  14376 ;	entries in the parameter table. The command classes for each of	
  14377 ;	the commands are given, together with the required separators and	
  14378 ;	these are followed by the address of the appropriate routine.	
  14379 	
  14380 	
  14381 	; 2C48: 01 14 02 	
  14382 mark_0C48:
  14383 P_LET:
  14384 	defb	_CLASS_01	; A variable is required.
  14385 	defb	ZX_EQU		; Separator:	'='
  14386 	defb	_CLASS_02	; An expression, numeric or string,
  14387 				; must follow.
  14388 	
  14389 ; 244B: 06 00 81 0E 06	
  14390 	
  14391 P_GOTO:
  14392 mark_0C4B:
  14393 	defb	_CLASS_06	; A numeric expression must follow.
  14394 	defb	_CLASS_00	; No further operands.
  14395 	defw	GOTO
  14396 
  14397 
  14398 P_IF:	
  14399 mark_0C4F:
  14400 	defb	_CLASS_06	; A numeric expression must follow.
  14401 mark_0C50			; 2C50: DE 05 AB 0D
  14402 	defb	ZX_THEN		; Separator:	'THEN'
  14403 	defb	_CLASS_05	; Variable syntax checked entirely
  14404 				; by routine.
  14405 	defw	IF
  14406 
  14407 
  14408 P_GOSUB:			; mark_0C54:
  14409 	defb	_CLASS_06	; A numeric expression must follow.
  14410 	defb	_CLASS_00	; No further operands.
  14411 	defw	GOSUB		; 0EB5
  14412 	
  14413 	; 2C58: 00 DC 0C 	
  14414 	
  14415 P_STOP:				; mark_0C58:
  14416 				; 2C54: 06 00 B5 0E	
  14417 	defb	_CLASS_00	; No further operands.
  14418 	defw	STOP
  14419 
  14420 	; 2c5B: 00 D8 0E 	
  14421 	
  14422 P_RETURN
  14423 	defb	_CLASS_00	; No further operands.
  14424 	defw	RETURN
  14425 	
  14426 	
  14427 	; 2c5e: 04 14	
  14428 	
  14429 	
  14430 P_FOR:
  14431 #if	0
  14432 mark_0C5E:
  14433 #else
  14434 #endif
  14435 	defb	_CLASS_04	; A single character variable must
  14436 				; follow.
  14437 	defb	ZX_EQU		; Separator:	'='
  14438 	defb	_CLASS_06	; A numeric expression must follow.
  14439 	defb	ZX_TO		; Separator:	'TO'
  14440 	defb	_CLASS_06	; A numeric expression must follow.
  14441 	defb	_CLASS_05	; Variable syntax checked entirely
  14442 				; by routine.
  14443 	defw	FOR
  14444 
  14445 	; 0C66: 04 00 2E 0E	
  14446 	
  14447 P_NEXT:				; at $0C66:
  14448 
  14449 	defb	_CLASS_04	; A single character variable must follow.
  14450 	defb	_CLASS_00	; No further operands.
  14451 	defw	NEXT
  14452 
  14453 	
  14454 ; 2C6A: 05 E8 2B 	
  14455 	
  14456 P_PRINT:
  14457 
  14458 mark_0C6A:
  14459 
  14460 
  14461 
  14462 	defb	_CLASS_05	; Variable syntax checked entirely
  14463 				; by routine.
  14464 #if NOT_G007
  14465 	defw	PRINT		; This is the original routine
  14466 #else
  14467 	defw	PRINT_007	; 2BE8	This is the new routine!	
  14468 #endif	
  14469 	
  14470 ;	; 2C6D: 01 00 E9 0E	
  14471 	
  14472 
  14473 mark_0C6D:
  14474 
  14475 
  14476 P_INPUT:
  14477 	defb	_CLASS_01	; A variable is required.
  14478 	defb	_CLASS_00	; No further operands.
  14479 	defw	INPUT
  14480 
  14481 P_DIM:
  14482 mark_0C71:
  14483 	defb	_CLASS_05	; Variable syntax checked entirely
  14484 				; by routine.
  14485 #if NOT_G007
  14486 	defw	DIM		; 1409	Original ZX81 replaced by
  14487 #else
  14488 	defw	DIM_007		; 2EA7	new routine	
  14489 #endif
  14490 ;	
  14491 ;	; 2c74: 05 6A 0D 	
  14492 ;	
  14493 mark_0C74:
  14494 P_REM:
  14495 
  14496 	defb	_CLASS_05	; Variable syntax checked entirely by routine.
  14497 	defw	REM
  14498 
  14499 mark_0C77:
  14500 P_NEW:
  14501 	defb	_CLASS_00	; No further operands.
  14502 	defw	NEW
  14503 
  14504 P_RUN:
  14505 mark_0C7A:
  14506 
  14507 P_RUN:
  14508 	defb	_CLASS_03	; A numeric expression may follow
  14509 				; else default to zero.
  14510 	defw	RUN
  14511 
  14512 P_LIST:
  14513 #if	0
  14514 mark_0C7D:
  14515 #else
  14516 #endif
  14517 	defb	_CLASS_03	; A numeric expression may follow
  14518 				; else default to zero.
  14519 	defw	LIST
  14520 
  14521 P_POKE:				; mark_0C80:
  14522 	defb	_CLASS_06	; A numeric expression must follow.
  14523 	defb	ZX_COMMA	; Separator:	','
  14524 	defb	_CLASS_06	; A numeric expression must follow.
  14525 	defb	_CLASS_00	; No further operands.
  14526 	defw	POKE
  14527 
  14528 P_RAND:				; mark_0C86:
  14529 	defb	_CLASS_03	; A numeric expression may follow
  14530 				; else default to zero.
  14531 	defw	RAND
  14532 
  14533 P_LOAD:				; mark_0C89:
  14534 	defb	_CLASS_05	; Variable syntax checked entirely
  14535 				; by routine.
  14536 	defw	LOAD
  14537 
  14538 P_SAVE:				; mark_0C8C:
  14539 	defb	_CLASS_05	; Variable syntax checked entirely
  14540 				; by routine.
  14541 #if NOT_G007	
  14542 	defw	SAVE		; 02F6	original
  14543 #else
  14544 	defw	SAVE_007	; 2F4D	new!	
  14545 #endif	
  14546 ;	
  14547 P_CONT:
  14548 #if	0
  14549 #else
  14550 #endif
  14551 mark_0C8F:
  14552 	defb	_CLASS_00	; No further operands.
  14553 	defw	CONT		; 0E7C
  14554 ;	
  14555 P_CLEAR:			; mark_0C92:
  14556 	defb	_CLASS_00
  14557 #if NOT_G007	
  14558 	defw	CLEAR		; 149A	original
  14559 #else
  14560 	defw	CLEAR_007	; 0EB2	new. this points outside the G007 ROM	
  14561 #endif
  14562 
  14563 
  14564 P_CLS:				; mark_0C95:
  14565 #if NOT_G007
  14566 	defb	_CLASS_00	; No further operands.
  14567 ;;	defw	CLS		; original	
  14568 #else
  14569 	defb	_CLASS_03	; A numeric expression may follow
  14570 				; else default to zero.
  14571 	defw	G007_CLS_N	; 2E4E	new!	
  14572 #endif
  14573 ;	
  14574 ;	
  14575 ;	
  14576 mark_0C98:
  14577 
  14578 #if	NOT_G007
  14579 				; originally the ZX81 does this:	
  14580 P_PLOT:				; original: plot X,Y
  14581 	defb	_CLASS_06	; A numeric expression must follow. X
  14582 	defb	ZX_COMMA	; Separator:	','
  14583 	defb	_CLASS_06	; A numeric expression must follow. Y
  14584 	defb	_CLASS_00	; No further operands.
  14585 	defw	PLOT_UNPLOT	; 0BAF
  14586 
  14587 P_UNPLOT:			; original: plot X,Y
  14588 	defb	_CLASS_06	; A numeric expression must follow. X
  14589 	defb	ZX_COMMA	; Separator:	','
  14590 	defb	_CLASS_06	; A numeric expression must follow. Y
  14591 	defb	_CLASS_00	; No further operands.
  14592 	defw	PLOT_UNPLOT	; 0BAF
  14593 
  14594 				; These are identical, so they could overlap
  14595 #else
  14596 				; The G007 saves bytes by having these
  14597 				; identical parameter table entries overlapping:	
  14598 				; 0C98 / 2C98: 06 1A 06 1A 06 00 26 29	
  14599 P_PLOT_007:
  14600 P_UNPLOT_007:
  14601 				; new: plot N,X,Y
  14602 	defb	_CLASS_06	; A numeric expression must follow. N
  14603 	defb	ZX_COMMA	; Separator:	','
  14604 	defb	_CLASS_06	; A numeric expression must follow. X
  14605 	defb	ZX_COMMA	; Separator:	','
  14606 L0C9C:
  14607 	defb	_CLASS_06	; A numeric expression must follow. Y
  14608 	defb	_CLASS_00	; No further operands.
  14609 	defw	G007_PLOT_UNPLOT_N_X_Y		; 2926	new!
  14610 				;
  14611 				; by saving those bytes, can put a tiny routine here:
  14612 L0CA0:
  14613 	LD HL,(L0EA8)		; Inside the 'FIND_INT.' subroutine
  14614 	JP (HL)
  14615 #endif
  14616 ;
  14617 ; Now back to the table!	
  14618 ;	
  14619 P_SCROLL_007
  14620 mark_0CA4:
  14621 	defb	_CLASS_00	
  14622 	defw	SCROLL		; 0C0E	
  14623 	
  14624 
  14625 
  14626 P_PAUSE:
  14627 	defb		_CLASS_06
  14628 	defb		_CLASS_00
  14629 #if NOT_G007
  14630 mark_0CA9:
  14631 ;	2CA9: 0F 32 	
  14632 	defw		PAUSE		; 0F32	original
  14633 #else
  14634 mark_0CA9:
  14635 ;	2CA9: AE 2E 	
  14636 ;	0CA7	
  14637 	defw		PAUSE_007	; 2EAE	new!	
  14638 #endif
  14639 ;	
  14640 ; 2CAB: 03 B2 2E 	
  14641 ; 0CAB	
  14642 
  14643 
  14644 
  14645 P_SLOW:
  14646 mark_0CAB:
  14647 #if NOT_G007
  14648 	defb	_CLASS_00	; No further operands.
  14649 	defw	SLOW		;	2B 0F	SLOW,0F2B	original
  14650 #else
  14651 	defb	_CLASS_03	; new! Extra parameter sets graphic mode	
  14652 	defw	SLOW_007	; 2EB2	new!	
  14653 #endif
  14654 
  14655 
  14656 P_FAST:
  14657 mark_0CAE:
  14658 #if NOT_G007
  14659 	defb	_CLASS_00	; No further operands.
  14660 	defw	FAST		; 23 0F		FAST,0F23	original
  14661 #else
  14662 	defb	_CLASS_03	; new! Extra parameter sets graphic mode	
  14663 	defw	FAST_007	; 2EB6	new!	
  14664 #endif
  14665 
  14666 
  14667 
  14668 
  14669 
  14670 
  14671 
  14672 	
  14673 ;	
  14674 ;	2CB1: 03 53 2F 	
  14675 ;	
  14676 ;	0CB1
  14677 
  14678 P_COPY:
  14679 #if NOT_G007
  14680 	defb	_CLASS_00	; original
  14681 	defw	COPY		; 0869	original
  14682 #else
  14683 	defb	_CLASS_03	; new!	Extra parameter sets graphic mode	
  14684 ;;;	defw	COPY_007	; 2EB6	new but wrong ???!	
  14685 	defw	L2F53		; what the disassembler said
  14686 #endif
  14687 
  14688 mark_0CB4:
  14689 
  14690 
  14691 P_LPRINT:
  14692 
  14693 	defb	_CLASS_05	
  14694 	defw	LPRINT		; 0ACB	
  14695 ;	
  14696 ;	;	2CB7: 03 2C 07 	
  14697 ;	0CB7	
  14698 P_LLIST:
  14699 	defb	_CLASS_03	
  14700 	defw	LLIST		; 072C	
  14701 ;	
  14702 ;	
  14703 ; the rest of this page is just a copy of the usual ZX81 code	
  14704 
  14705 LINE_SCAN:
  14706 L0CBA:
  14707 ;	2CBA: FD 36 01 01 CD 73	
  14708 ;	2CC0: 0A CD 95 0A 21 00 40 36	
  14709 ;	2CC8: FF 21 2D 40 CB 6E 28 0E	
  14710 ;	2CD0: FE E3 7E C2 6F 0D CD A6	
  14711 ;	2CD8: 0D C8 CF 0C CF 08 DF 06	
  14712 ;	2CE0: 00 FE 76 C8 4F E7 79 D6	
  14713 ;	2CE8: E1 38 3B 4F 21 29 0C 09	
  14714 ;	2CF0: 4E 09 18 03 2A 30 40 7E	
  14715 ;	2CF8: 23 22 30 40 01 F4 0C C5	
  14716 ;
  14717 ; which is described as follows in the ZX81 disassembly book:	
  14718 ;	
  14719 ;	THE 'LINE SCANNING' ROUTINE	
  14720 ;
  14721 ;	The BASIC interpreter scans each line for BASIC commands and as each one is found
  14722 ;	the appropriate command routine is followed.	
  14723 ;	The different parts of the routine are:
  14724 ;-------------------------------
  14725 ;	i) The LINE_SCAN entry point leads to the line number being checked for validity.	
  14726 
  14727 	LD      (IY+FLAGS-RAMBASE),$01		; FLAGS = 1
  14728         CALL    E_LINE_NO			; 
  14729 ;-------------------------------
  14730 ;	ii) The LINE_RUN entry point is used when replying to an INPUT prompt
  14731 ;	and this fact has be identified.	
  14732 ;-------------------------------
  14733 LINE_RUN
  14734 #if NOT_G007
  14735 	CALL	SET_MEM		; at $14BC
  14736 #else
  14737 	CALL	L0A95		; JP 14BC,SET_MEM then return
  14738 				; why it does this I do not know - KH
  14739 #endif
  14740 	LD	HL,ERR_NR	
  14741 	LD	(HL),$FF	
  14742 	LD	HL,FLAGX	
  14743 	BIT	5,(HL)	
  14744 	JR	Z,LINE_NULL
  14745 ;-------------------------------
  14746 ;	iii) The INPUT reply is tested to see if STOP was entered.	
  14747 	
  14748 	CP	$E3	
  14749 	LD	A,(HL)	
  14750 	JP	NZ,INPUT_RE	
  14751 	CALL	SYNTAX_Z
  14752 	RET	Z	
  14753 	
  14754 ;	iv) If appropriate, report D is given.	
  14755 	
  14756 	RST	ERROR_1	
  14757 	defb	$0C	
  14758 ;-------------------------------
  14759 	;	THE 'STOP' COMMAND ROUTINE	
  14760 	;	The only action is to give report 9.	
  14761 ;-------------------------------
  14762 STOP
  14763 	RST	ERROR_1	
  14764 	defb	8	
  14765 ;-------------------------------
  14766 	; v) A return is made if the line is 'null'.
  14767 ;-------------------------------
  14768 LINE_NULL:
  14769 
  14770 mark_0CDE:
  14771 
  14772 ; old software from disassembly book:
  14773 
  14774 	RST	GET_CHAR
  14775 	LD	B,0
  14776 	CP	ZX_NEWLINE
  14777 	RET	Z
  14778 	
  14779 	; vi) The first character is tested so as to check that it is a command.	
  14780 
  14781 	LD	C,A	
  14782 	RST	NEXT_CH
  14783 	LD	A,C	
  14784 	SUB	$E1
  14785 #if NOT_G007
  14786 	JR	C,REPORT_C	; $0D9A as per the book
  14787 #else
  14788 	JR	C,REPORT_C_007	; $0D26 in G007 systems
  14789 #endif	
  14790 ;-------------------------------
  14791 	; vii) The offset for the command is found from the offset table.	
  14792 	
  14793 	LD	C,A	
  14794 	LD	HL,offset_t	; $0C29	
  14795 	ADD	HL,BC	
  14796 	LD	C,(HL)	
  14797 	ADD	HL,BC	
  14798 	JR	GET_PARAM
  14799 	
  14800 	; viii) The parameters are fetched in turn by a loc that returns to 0CF4.
  14801 	; The separators are identitied by the test against +0B.	
  14802 ;-------------------------------
  14803 mark_0CF4:
  14804 
  14805 SCAN_LOOP:
  14806 	LD	HL,(T_ADDR)	
  14807 GET_PARAM:
  14808 	LD	A,(HL)	
  14809 	INC	HL	
  14810 	LD	(T_ADDR),HL	
  14811 	LD	BC,SCAN_LOOP	
  14812 	PUSH	BC	
  14813 
  14814 ;
  14815 ;	there is more to this routine but the patch ends here
  14816 ;
  14817 ; end of patch	
  14818 ;-------------------------------
  14819 	org	$2D00
  14820 
  14821 
  14822 ; bits shifting right within a byte:	
  14823 ;	
  14824 	defb	%10000000	; $80
  14825 	defb	%01000000	; $40
  14826 	defb	%00100000	; $20
  14827 	defb	%00010000	; $10
  14828 	defb	%00001000	; $08
  14829 	defb	%00000100	; $04
  14830 	defb	%00000010	; $02
  14831 	defb	%00000001	; $01
  14832 ;-------------------------------
  14833 L2D08:
  14834 
  14835 SLOW_FAST_007:		; at $2D08	
  14836 	
  14837 	CALL	L2BF7	; ??? not a valid opcode address?	
  14838 	JP	SLOW_FAST	; old routine	
  14839 ;-------------------------------
  14840 L2D0E:	
  14841 	LD	(MARGIN),A	; 	
  14842 	EX	DE,HL	
  14843 	LD	HL,10
  14844 	ADD	HL,SP	
  14845 	LD	A,(HL)	
  14846 	INC	A	
  14847 	AND	$F0	
  14848 	SUB	$D0	
  14849 	LD	C,A	
  14850 	INC	HL	
  14851 	LD	A,(HL)	
  14852 	SUB	4	
  14853 	OR	A,C	
  14854 	LD	C,A	
  14855 	LD	A,(CDFLAG)	; 	
  14856 	RLCA	
  14857 	SBC	A,A	
  14858 	AND	A,C	
  14859 	JR	NZ,L2D3B	
  14860 ;-------------------------------
  14861 	LD	HL,(VARS)	; 	
  14862 	LD	BC,-(CHARS_HORIZONTAL+1)	; $FFDF	
  14863 	ADD	HL,BC	
  14864 	SET	7,H	
  14865 	LD	(G007_DISPLAY_ADDRESS_LO_RES_LAST_LINE),HL	
  14866 	LD	A,1	
  14867 	JR	L2D49	
  14868 ;-------------------------------
  14869 L2D3B:	
  14870 	LD	HL,(D_FILE)	; GET D_FILE	
  14871 	LD	BC,(G007_DISPLAY_OFFSET_FROM_DFILE_LESS_9)	
  14872 	ADD	HL,BC	
  14873 	SET	7,H	
  14874 	LD	(G007_DISPLAY_ADDRESS_LESS_9),HL	
  14875 	XOR	A,A	; A = 0	
  14876 ;-------------------------------
  14877 L2D49:
  14878 	LD	(G007_FLAG_3),A
  14879 	DEC	HL	
  14880 	LD	A,(HL)	
  14881 	EX	DE,HL	
  14882 	RET
  14883 ;-------------------------------
  14884 	LD	A,(G007_FLAG_3)
  14885 	DEC	A	
  14886 	JP	NZ,L2D73	; [11635]	
  14887 ;-------------------------------
  14888 	LD	A,G007_INT_REG_VALUE_FOR_LO_RES_GRAPHICS	
  14889 	LD	I,A						; Interrupt register = 0x1E sets low res mode	
  14890 	ADC	HL,HL	
  14891 	LD	HL,(G007_DISPLAY_ADDRESS_LO_RES_LAST_LINE)	
  14892 	
  14893 	LD	BC,$0108	
  14894 	LD	A,$FE	
  14895 	CALL	DISPLAY_5;	
  14896 	LD	A,G007_INT_REG_VALUE_FOR_HI_RES_GRAPHICS	
  14897 	LD	I,A						; Interrupt register = 0x1F sets high res mode	
  14898 	LD	A,(MARGIN)					; GET MARGIN	
  14899 	SUB	8	
  14900 	JR	L2D77
  14901 ;-------------------------------
  14902 L2D73:	
  14903 	DEC	HL	
  14904 	LD	A,(MARGIN)					; GET MARGIN	
  14905 ;-------------------------------
  14906 L2D77:	
  14907 	LD	C,A	
  14908 	POP	IX
  14909 ;-------------------------------
  14910 	BIT	7,(IY+CDFLAG-RAMBASE)				; makes FD CB 3B 7E
  14911 	JP	NZ,L029D					; []*BIOS ROM*	
  14912 ;-------------------------------
  14913 	
  14914 ; This jumps into the middle of the DISPLAY_3, where it meets this code:	
  14915 ;029D   79               LD A,C  	
  14916 ;029E   ED;44            NEG                  	
  14917 ;02A0   3C               INC A                	
  14918 ;02A1   08               EX AF,AF'            	
  14919 ;02A2   D3;FE            OUT (IO_PORT_KEYBOARD_RD),A         ; ZX81 NMI GENERATOR on, for SLOW mode	
  14920 ;02A4   E1               POP HL               ; restore registers	
  14921 ;02A5   D1               POP DE               	
  14922 ;02A6   C1               POP BC               	
  14923 ;02A7   F1               POP AF               	
  14924 ;02A8   C9               RET  	
  14925 ;-------------------------------
  14926 	LD	A,$FE		
  14927 	LD	B,$01	
  14928 	LD	HL,HALT_AT_2D9A	
  14929 	CALL	LOAD_R_AND_WAIT_FOR_INT
  14930 	ADD	HL,HL		; double HL
  14931 	NOP	
  14932 	LD	E,A	
  14933 	LD	HL,(G007_DISPLAY_ADDRESS_LESS_9)	
  14934 	SET	7,H	
  14935 	JP	(IX)	
  14936 ;===============================
  14937 LOAD_R_AND_WAIT_FOR_INT		; mark_2D95
  14938 				; Sets up the refresh register and waits for an interrupt:
  14939 	LD	R,A		; Refresh row counter := accumulator	
  14940 	LD	A,221		; 221 = $DD
  14941 	EI			; Enable interrupts, then drop into HALT	
  14942 ;-------------------------------
  14943 HALT_AT_2D9A:
  14944 
  14945 	HALT	
  14946 ;===============================
  14947 ; Copy two pages of ZX81 BASIC ROM to RAM patch areas,	
  14948 ; then modify bytes as controlled by a table of offsets and values	
  14949 ; This uses less memory than two whole pages of ROM	
  14950 ; If the RAM patches are not changed thereafter,	
  14951 ; one might be able to use a 16K ROM to hold two different versions of the ZX81 BASIC space,	
  14952 ; one with the 'RAM' patch and one without.	
  14953 ; The RAM testing would have to be disabled, because the ROM would cause it to fail.	
  14954 ;-------------------------------
  14955 #if NOT_G007
  14956 ZX81_COPY:
  14957 #else
  14958 G007_COPY:	
  14959 #endif
  14960 ;-------------------------------
  14961 ; First check RAM by loading 512 bytes RAM from $2200 to $23FF with value 1,
  14962 ; and decrement them to zero to test they are working RAM	
  14963 ;	
  14964 	LD	HL,RAM_PATCH_2200	; destination RAM patch 2	
  14965 	LD	A,$24	
  14966 ;-------------------------------
  14967 mark_2DA0:
  14968 G007_COPY_LOOP:	
  14969 	LD	(HL),1			; try writing the value 1 to a byte in RAM patch 2	
  14970 	DEC	(HL)			; try decrementing it to zero	
  14971 	JR	Z,G007_COPY_SKIP	; if result is zero, skip error code report	
  14972 ;-------------------------------
  14973 	RST	$08
  14974 	defb	$1A ; RST8 Arg		; Error Code:'R' (ZX81 on-board 1K/2K RAM not found)	
  14975 ;-------------------------------
  14976 G007_COPY_SKIP
  14977 mark_2DA7:	
  14978 	INC	HL			; next address	
  14979 	CP	H			; has HL reached $2400 (yet?	
  14980 	JR	NZ,G007_COPY_LOOP	; no, repeat. 	
  14981 ;-------------------------------
  14982 	; HL is now $2400	
  14983 	; Copy 256 bytes from BASIC ROM to RAM patch 1:	
  14984 	LD	H,L			; HL is now $0000 (data source is start of ZX81 BASIC ROM)	
  14985 	LD	DE,RAM_PATCH_2000	; data destination	
  14986 	LD	BC,$0100		; 256 bytes	
  14987 	LDIR				; (HL) -> (DE) 256 times	
  14988 ;-------------------------------
  14989 	; HL is now $0100	
  14990 	; DE is now $2100	
  14991 	; BC is now $0000	
  14992 ;-------------------------------
  14993 	INC	H	; HL is now $0200 	
  14994 	INC	D	; DE is now $2200	
  14995 	INC	B	; BC is now $0100	
  14996 	LDIR	; copy another 256 bytes to RAM patch 2	
  14997 ;-------------------------------
  14998 	LD	HL,PRINT_CH	; src = the original ZX81 print character routine	
  14999 	LD	DE,G007_V23A0	; dst = 	
  15000 	LD	BC,$0060	; 60hex = 96 bytes, so stops just before 0851 (the 'LPRINT_CH routine)	
  15001 	LDIR	; move	
  15002 	; BC is now $0000	
  15003 	LD	D,$20	; DE is now $20??	
  15004 	LD	HL,TABLE_ONE	; copy data from this table:
  15005 LOOP_2DC9:
  15006 	LD	B,(HL)	; BC is now $0A00 (seems way too many bytes)	
  15007 	JR	G007_TABLE_END_TEST	; branch to end-of-table test	
  15008 ;-------------------------------
  15009 G007_TABLE_ONE_LOOP:	
  15010 	LD	E,(HL)	; Get the offset	
  15011 	INC	HL	; next byte is data	
  15012 	LD	A,(HL)	; Get the data byte	
  15013 	LD	(DE),A	; ($2000+offset) = data byte
  15014 ;-------------------------------
  15015 G007_TABLE_END_TEST:
  15016 mark_2DD0:
  15017 	INC	HL	; next offset	
  15018 	DJNZ	G007_TABLE_ONE_LOOP	; repeat until BC is zero	
  15019 ;-------------------------------
  15020 	INC	D	; D becomes $21	
  15021 	BIT	2,D	; test bit 2 (has D incremented to $23 ?)	
  15022 	JR	Z,LOOP_2DC9	
  15023 	
  15024 	RET	
  15025 ;===============================	
  15026 ; Delete Display File:	
  15027 ;	
  15028 G007_DELETE_DISPLAY_FILE:	
  15029 	CALL	SET_FAST;	
  15030 	LD	HL,$3E87	
  15031 	CALL	LINE_ADDR;	
  15032 	RET	NZ
  15033 ;-------------------------------
  15034 	EX	DE,HL	
  15035 	LD	HL,(NXT_LINE)	; 	
  15036 	BIT	6,(HL)	
  15037 	JR	Z,L2DEF	
  15038 ;-------------------------------
  15039 	LD	(NXT_LINE),DE	;
  15040 ;-------------------------------
  15041 L2DEF:	
  15042 	LD	HL,(D_FILE)	; 
  15043 	JP	RECLAIM_1	; exit	
  15044 ;-------------------------------
  15045 L2DF5:	
  15046 	CALL	G007_DELETE_DISPLAY_FILE	
  15047 	LD	BC,$1992	; 6546 decimal = 	
  15048 	LD	HL,(D_FILE)	; 	
  15049 	DEC	HL	
  15050 	CALL	MAKE_ROOM	
  15051 	
  15052 	LD	A,ZX_NEWLINE	
  15053 	LD	(DE),A	; to DE	
  15054 	INC	DE	
  15055 	LD	(DE),A	; and DE+1	
  15056 	
  15057 	INC	HL	; HL += 2	
  15058 	INC	HL	
  15059 	
  15060 	LD	(HL),$3E	; (HL++) = $3E	'Y'	
  15061 	INC	HL	
  15062 	LD	(HL),$87	; (HL++) = $87	
  15063 	INC	HL	
  15064 	LD	(HL),$8D	; (HL++) = $8D	
  15065 	INC	HL	
  15066 	LD	(HL),$19	; (HL++) = $19	';'	
  15067 	INC	HL	
  15068 	LD	(HL),A	; (HL++) = ZX_NEWLINE	
  15069 	INC	HL	
  15070 	LD	(HL),A	; (HL++) = ZX_NEWLINE
  15071 ;-------------------------------
  15072 L2E18:
  15073 	CALL	SLOW_FAST	; 
  15074 	LD	A,1	
  15075 	JR	G007_CLS_HI_RES	
  15076 ;-------------------------------
  15077 G007_CHECK_AND_SET_UP_DISPLAY_FILE:	
  15078 	;	
  15079 	LD	HL,(V2265)	; in the RAM page 2 area ! Usually $4027	
  15080 	LD	DE,$BFD9	; 3FD9 + 32K, or -16423 = 16K - 39 bytes	
  15081 	ADD	HL,DE	
  15082 
  15083 	LD	A,(V2264)	
  15084 	SUB	CHARS_HORIZONTAL+1		; bytes per screen line
  15085 	
  15086 	OR	A,H	
  15087 	OR	A,L	
  15088 
  15089 	CALL	NZ,G007_COPY	
  15090 	LD	HL,(D_FILE)	; GET D_FILE	
  15091 	LD	A,ZX_NEWLINE	
  15092 
  15093 	DEC	HL	
  15094 	DEC	HL	
  15095 	CP	(HL)		; pointing to a HALT?	
  15096 
  15097 	CALL	NZ,L2DF5	; no, 	
  15098 				; else yes	
  15099 	LD	HL,(D_FILE)	; GET D_FILE	
  15100 	LD	DE,(G007_DISPLAY_OFFSET_FROM_DFILE_LESS_9)
  15101 	ADD	HL,DE	
  15102 	LD	(G007_DISPLAY_ADDRESS_LESS_9),HL	
  15103 
  15104 	LD	DE,9		; HL += 9
  15105 	ADD	HL,DE	
  15106 
  15107 	LD	(G007_DISPLAY_ADDRESS),HL	
  15108 	RET	
  15109 ;-------------------------------
  15110 G007_CLS_N:	
  15111 ;	
  15112 	CALL	STK_TO_A	
  15113 	RET	NZ		; drop through if zero flag set	
  15114 ;-------------------------------
  15115 ; Clear The Screen:	
  15116 ;	
  15117 G007_CLS_A:	
  15118 	DEC	A	
  15119 	JP	M,CLS		; if A was zero	
  15120 ;-------------------------------
  15121 G007_CLS_HI_RES:	
  15122 	PUSH	AF	
  15123 	CALL	G007_CHECK_AND_SET_UP_DISPLAY_FILE	
  15124 	POP	AF	
  15125 ;-------------------------------
  15126 	CP	2	
  15127 	LD	BC,(G007_DISPLAY_HEIGHT)	
  15128 	LD	HL,(D_FILE)	
  15129 	JR	NC,L2E96	
  15130 ;-------------------------------
  15131 	DEC	A
  15132 	
  15133 	INC	HL	
  15134 	LD	(DF_CC),HL	; Addr. for PRINT AT position
  15135 	DEC	HL	
  15136 
  15137 	DEC	HL	
  15138 	DEC	HL	
  15139 
  15140 	LD	E,0		; E = 0 is byte to fill screen
  15141 ;-------------------------------
  15142 loop_2E70:	
  15143 	LD	B,16			; 16
  15144 	DEC	HL
  15145 	LD	(HL),E			; but writes 2 bytes for each loop
  15146 	DEC	HL	
  15147 	LD	(HL),E			; perhaps to reduce loop overhead?
  15148 ;-------------------------------
  15149 loop_2E76:	
  15150 	DEC	HL	
  15151 	LD	(HL),A			; writes A twice over	
  15152 	DEC	HL	
  15153 	LD	(HL),A	
  15154 	DJNZ	loop_2E76	
  15155 ;-------------------------------
  15156 	DEC	C	
  15157 	JR	NZ,loop_2E70	
  15158 ;-------------------------------	; C is now zero
  15159 	LD	B,9			; BC is now $0900
  15160 	LD	A,1	
  15161 ;-------------------------------
  15162 loop_2E83:	
  15163 	DEC	HL	
  15164 	LD	(HL),E			; (--HL) = E while --BC
  15165 	DJNZ	loop_2E83	
  15166 ;-------------------------------	; BC is now zero
  15167 	LD	HL,G007_LINE_TYPE	
  15168 	LD	B,20			; decimal 20
  15169 	DEC	A	
  15170 	JR	Z,loop_2E83	
  15171 ;-------------------------------
  15172 	LD	HL,256*CHARS_VERTICAL + CHARS_HORIZONTAL + 1
  15173 	LD	(S_POSN),HL		; SET S_POSN	
  15174 	RET	
  15175 ;===============================
  15176 L2E96:	
  15177 	RET	NZ	
  15178 
  15179 	DEC	HL			; HL -= 2
  15180 	DEC	HL
  15181 ;------------------------------- outer loop
  15182 loop_2E99:	
  15183 	LD	B,32			; 32 bytes to invert
  15184 	DEC	HL			; HL -= 2
  15185 	DEC	HL			; skips past 2 HALT characters
  15186 
  15187 ;------------------------------- inner loop
  15188 loop_2E9D:	
  15189 	DEC	HL
  15190 	
  15191 	LD	A,(HL)			; read
  15192 	CPL				; invert (one's complement)
  15193 	LD	(HL),A			; write
  15194 
  15195 	DJNZ	loop_2E9D	
  15196 ;-------------------------------
  15197 	DEC	C			; C is obviously the number of horizontal lines to invert
  15198 	JR	NZ,loop_2E99	
  15199 ;-------------------------------
  15200 	RET
  15201 ;-------------------------------
  15202 mark_2EA7:
  15203 DIM_007:			; 2EA7
  15204 	LD	HL,($0A96)	
  15205 	LD	A,$4D	
  15206 	JR	L2EE3	
  15207 ;-------------------------------
  15208 PAUSE_007:	
  15209 	LD	A,$DD	
  15210 	JR	skip_2EE0	
  15211 ;-------------------------------
  15212 SLOW_007:			; 2EB2
  15213 	LD	A,$D6	
  15214 	JR	skip_2EB8	
  15215 ;-------------------------------
  15216 FAST_007:			; 2EB6	
  15217 	LD	A,$CE	
  15218 ;-------------------------------
  15219 skip_2EB8:
  15220 	PUSH	AF	
  15221 
  15222 	CALL	STK_TO_A	
  15223 	LD	B,$1E	
  15224 	DEC	A	
  15225 	CP	6	
  15226 	JR	NC,skip_2EDC	
  15227 ;-------------------------------
  15228 	SRL	A	
  15229 	LD	H,A	
  15230 ;-------------------------------
  15231 	JR	Z,skip_2ECA	
  15232 	LD	A,1
  15233 skip_2ECA:	
  15234 ;-------------------------------
  15235 	PUSH	AF	
  15236 	SBC	A,A	
  15237 	LD	L,A	
  15238 	RES	1,H	
  15239 	DEC	H	
  15240 	LD	(G007_RESTART),HL	
  15241 	CALL	G007_CHECK_AND_SET_UP_DISPLAY_FILE	
  15242 	LD	B,G007_INT_REG_VALUE_FOR_HI_RES_GRAPHICS	
  15243 	POP	AF
  15244 	
  15245 	LD	(G007_FLAG_2),A
  15246 ;-------------------------------
  15247 skip_2EDC:
  15248 	LD	A,B		;	
  15249 	LD	I,A		; I = B = G007_INT_REG_VALUE_FOR_HI_RES_GRAPHICS = set video mode 	
  15250 	POP	AF
  15251 ;-------------------------------
  15252 skip_2EE0:
  15253 	LD	HL,($0D71)				; inside the 'COMMAND CLASS 2' routine of the ZX BASIC ROM
  15254 ;-------------------------------
  15255 L2EE3:
  15256 	ADD	A,L	
  15257 	LD	L,A	
  15258 	JP	(HL)	
  15259 	
  15260 	LD	D,A	
  15261 	LD	A,(S_POSN)	; 	
  15262 	AND	$80	
  15263 	JP	L2B6C	
  15264 ;===============================
  15265 L2EEF:							; print a character on high-res screen perhaps?
  15266 	LD	A,D	
  15267 	POP	DE	
  15268 
  15269 	EXX
  15270 ;-------------------------------
  15271 	PUSH	HL	
  15272 	PUSH	DE	
  15273 	PUSH	BC
  15274 ;-------------------------------
  15275 	LD	HL,(G007_CHAR_TABLE_ADDR_0_63)
  15276 	ADD	A,A					; if (A < 128) goto 
  15277 	JR	NC,skip_2F06				
  15278 ;-------------------------------			;
  15279 	LD	HL,(G007_CHAR_TABLE_ADDR_128_159)	
  15280 	BIT	6,A
  15281 	JR	Z,skip_2F06	
  15282 ;-------------------------------
  15283 	LD	HL,(G007_USR_DEF_CHR_TAB_LESS_256)	
  15284 	CCF	
  15285 ;-------------------------------
  15286 skip_2F06:
  15287 	EX	DE,HL				; DE now points to the selected charater table
  15288 
  15289 	LD	L,A				; HL = A
  15290 	LD	H,0	
  15291 
  15292 	SBC	A,A				; A = carry
  15293 	LD	C,A				; 
  15294 ;-------------------------------
  15295 	LD	A,(G007_RESTART)		; invert this variable
  15296 	CPL	
  15297 	AND	A,(IY+G007_RESTART+1-RAMBASE)	
  15298 ;-------------------------------
  15299 	XOR	A,C	
  15300 	LD	C,A
  15301 	
  15302 	ADD	HL,HL				; HL *= 4
  15303 	ADD	HL,HL	
  15304 	ADD	HL,DE				; HD += DE
  15305 
  15306 	LD	B,8	
  15307 
  15308 	EXX	
  15309 	PUSH	DE	
  15310 	RET	
  15311 ;===============================
  15312 L2F1D:					; The copied and modified PRINT_CH / WRITE_CH jumps here from $23FF	
  15313 	DEC	(IY+S_POSN-RAMBASE)	; Line and Column for PRINT AT
  15314 	LD	A,24			; 24 character rows per screen	
  15315 	SUB	B	
  15316 	LD	B,A	
  15317 ;
  15318 	ADD	A,A
  15319 	ADD	A,A	
  15320 	ADD	A,A
  15321 	LD	L,A		; L = A * 8
  15322 ;	
  15323 	LD	A,(G007_DISPLAY_HEIGHT)	
  15324 	SUB	L			; A = G007_DISPLAY_HEIGHT - something
  15325 	RET	C			; return if beyond limit
  15326 ;-------------------------------
  15327 	LD	A,CHARS_HORIZONTAL+1			; 32 video bytes plus HALT ?
  15328 	SUB	C	
  15329 	LD	C,A	
  15330 ;------------------------------- 
  15331 	LD	H,0
  15332 	ADD	HL,HL	
  15333 	ADD	HL,BC	
  15334 	LD	BC,(G007_DISPLAY_ADDRESS)	
  15335 	ADD	HL,BC			; HL = L*2 + BC + G007_DISPLAY_ADDRESS:
  15336 ;-------------------------------
  15337 	CALL	L2EEF	
  15338 	LD	BC,$0022		; B = 0, C = 34
  15339 	EXX
  15340 ;-------------------------------
  15341 COPY_007:
  15342 loop_2F41:					;
  15343 	LD	A,C	
  15344 	XOR	A,(HL)	
  15345 	EXX	
  15346 	LD	(HL),A	
  15347 	ADD	HL,BC	
  15348 	EXX	
  15349 	INC	HL	
  15350 	DJNZ	loop_2F41	
  15351 ;-------------------------------
  15352 	JP	L299A	
  15353 ;-------------------------------
  15354 SAVE_007:				; 2F4D
  15355 	CALL	G007_DELETE_DISPLAY_FILE	
  15356 	JP	SAVE	
  15357 ;-------------------------------
  15358 L2F53:
  15359 	CALL	STK_TO_A	
  15360 	RET	NZ	
  15361 	
  15362 	DEC	A	
  15363 	JP	M,COPY			; A was zero, jump to low-res copy-to-printer
  15364 ;-------------------------------
  15365 	CALL	G007_CHECK_AND_SET_UP_DISPLAY_FILE	; check we have a display
  15366 	CALL	SET_FAST			; print in FAST mode!
  15367 	LD	A,(G007_DISPLAY_HEIGHT)	
  15368 	LD	B,A				; B = (G007_DISPLAY_HEIGHT)
  15369 	LD	HL,(G007_DISPLAY_ADDRESS)	
  15370 	XOR	A,A				; A = 0	
  15371 	LD	E,A				; E = 0	
  15372 	OUT	(ZX_PRINTER_PORT),A	
  15373 ;-------------------------------
  15374 loop_2F6C:	
  15375 	LD	A,$7F				; looks pointless
  15376 	IN	A,(IO_PORT_KEYBOARD_RD)	
  15377 	RRCA	
  15378 	JP	NC,$0886		; []*BIOS ROM* between 0880 COPY-BRK and 0888 REPORT-D2	
  15379 	IN	A,(ZX_PRINTER_PORT)	
  15380 ;-------------------------------
  15381 loop_2F76:	
  15382 	ADD	A,A	
  15383 	JP	M,L2FAD	
  15384 ;-------------------------------
  15385 	JR	NC,loop_2F6C	
  15386 ;-------------------------------
  15387 	LD	C,$20	; 32
  15388 ;-------------------------------
  15389 loop_2F7E:	
  15390 	PUSH	BC	
  15391 	LD	C,(HL)	
  15392 	LD	B,8
  15393 ;-------------------------------	; outer loop
  15394 loop_2F82:	
  15395 	RLC	C	
  15396 	RRA	
  15397 	OR	A,E	
  15398 	LD	D,A	
  15399 ;-------------------------------	; inner loop
  15400 loop_2F87:	
  15401 	IN	A,(ZX_PRINTER_PORT)	; read printer port bit 0 into carry flag	
  15402 	RRA	
  15403 	JR	NC,loop_2F87		; repeat while bit is zero
  15404 ;-------------------------------
  15405 	LD	A,D	
  15406 	OUT	(ZX_PRINTER_PORT),A	; D register to printer
  15407 	DJNZ	loop_2F82	
  15408 ;-------------------------------
  15409 	INC	HL	
  15410 	POP	BC	
  15411 	DEC	C	
  15412 	JR	NZ,loop_2F7E	
  15413 ;-------------------------------
  15414 	INC	HL	
  15415 	INC	HL	
  15416 	LD	A,3	
  15417 ;-------------------------------
  15418 	CP	B	
  15419 	JR	C,skip_2F9F	
  15420 ;-------------------------------
  15421 	LD	E,A	
  15422 	DEC	E
  15423 skip_2F9F:
  15424 ;-------------------------------
  15425 loop_2F9F:	
  15426 	IN	A,(ZX_PRINTER_PORT)	; read printer port bit 0 into carry flag
  15427 	RRA	
  15428 	JR	NC,loop_2F9F		; repeat while bit is zero
  15429 ;-------------------------------
  15430 	LD	A,E	
  15431 	OUT	(ZX_PRINTER_PORT),A	; E register to printer
  15432 	DJNZ	loop_2F6C	
  15433 ;-------------------------------
  15434 	LD	A,4	
  15435 	OUT	(ZX_PRINTER_PORT),A	
  15436 ;-------------------------------
  15437 L2FAD:	
  15438 	JP	SLOW_FAST	; normal
  15439 	EI	
  15440 	DJNZ	loop_2F76	
  15441 ;-------------------------------
  15442 	defb	$3E			; something to do with the table below?
  15443 ;-------------------------------
  15444 TABLE_ONE:
  15445 ;	
  15446 ; this table is copied to offsets from $2000, $2200, and $2300	
  15447 ;-------------------------------
  15448 ; Modify 9 bytes in page 20xx / 00xx:	
  15449 ;-------------------------------
  15450 L2FB4	:
  15451 	defb	(9+1)			; Modify 9 bytes in page 20xx / 00xx:
  15452 ;-------------------------------
  15453 ;	Original routine 	Modifications made in page 00xx	
  15454 ;	
  15455 L2FB5:
  15456 ;	0011   C2;F1;07         JP	NZ,PRINT_CH	; old	
  15457 ;	0011   C2;A0;23         JP	NZ,L23A0	; new, jump somewhere in RAM ???	
  15458 
  15459 	defb	$12
  15460 	defb	$A0
  15461 	defb	$13
  15462 	defb	$23
  15463 ;-------------------------------
  15464 L2FB9
  15465 ;	0014	F5	07	JP	PRINT_SP	; $07F5
  15466 ;	2014	A4	23	JP 	L23A4		; new, jumps to somewhere in RAM
  15467 
  15468 	defb	$15
  15469 	defb	$A4        
  15470 	defb	$16
  15471 	defb	$23
  15472 ;-------------------------------
  15473 ;	003F   CB;D9            SET	3,C	; old	
  15474 ;	003F   CB;C1            SET	0,C	; new	
  15475 
  15476 L2FBD:	defb	$40
  15477 L2FBE:	defb	$C1
  15478 ;-------------------------------
  15479 ;	005F   CD;07;02         CALL	SLOW_FAST	; 0207 is old	
  15480 ;	005F   CD;08;2D         CALL	SLOW_FAST_007	; 2D08 is new
  15481 
  15482 L2FBF:	defb	$60
  15483 L2FC0:	defb	$08
  15484 L2FC1:	defb	$61
  15485 L2FC2:	defb	$2D
  15486 ;-------------------------------
  15487 ;	0074   2A;0C;40         LD	HL,(D_FILE)	
  15488 ;	0074   2A;06:23         LD	HL,(G007_DISPLAY_ADDRESS_LESS_9)       ; new	
  15489 
  15490 L2FC3:	defb	$75
  15491 L2FC4:	defb	$06
  15492 	defb	$76
  15493 L2FC6:	defb	$23
  15494 ;-------------------------------
  15495 ;	Modifications made in page 02xx	
  15496 ;-------------------------------
  15497 L2FC7:	defb	$01
  15498 	defb	$0A
  15499 
  15500 ;	0253	06;0B	LD B,$0B
  15501 ;	2253	06;02	LD B,$02
  15502 
  15503 L2FC9	defb	$54
  15504 	defb	$02
  15505 ;-------------------------------
  15506 ;	0283	01;01;19	LD BC,$1901
  15507 ;	2283	01;01;C1	LD BC,$C101
  15508 L2FCB:	defb	$85
  15509 	defb	$C1
  15510 ;-------------------------------
  15511 ;	027E	CD;92;02	CALL DISPLAY_3
  15512 ;	227E	CD;73;2D	CALL L2D73	
  15513 ;
  15514 L2FCD:	defb	$7F
  15515 	defb	$73
  15516 L2FCF:	defb	$80
  15517 	defb	$2D
  15518 ;-------------------------------
  15519 ;	028C	CD;92;02	CALL $0292	; [DISPLAY-3]
  15520 ;	228C	CD;50;2D	CALL $2D50
  15521 L2FD1:	defb	$8D
  15522 L2FD2:	defb	$50
  15523 L2FD3:	defb	$8E
  15524 L2FD4:	defb	$2D
  15525 ;-------------------------------
  15526 ;	02E3	32;28;40	LD ($4028),A	; SET MARGIN
  15527 ;	22E3	C3;0E;2D	JP L2D0E
  15528 L2FD5:	defb	$E3
  15529 L2FD6:	defb	$C3
  15530 	defb	$E4
  15531 	defb	$0E
  15532 L2FD9:	defb	$E5
  15533 L2FDA:	defb	$2D
  15534 ;-------------------------------
  15535 L2FDB:	defb	$13		; some kind of marker?
  15536 ;-------------------------------
  15537 ;	
  15538 ;	Original routine 	Modifications made to the copy of the PRINT-CH routines:	
  15539 ;	
  15540 ;	
  15541 ;	Variables in the sparsely populated G007 RAM areas	
  15542 ;
  15543 ; Initialise 18 (decimal, = 12 in hex)RAM variables at $23xx:	
  15544 ;
  15545 ;	2FE0	E6	0A	;	23E6	0A
  15546 ;	2FE2	55	0D	;	2355	0D
  15547 ;	2FE4	1E	0F	;	231E	0F	
  15548 ;	2FE6	16	20	;	2316	20
  15549 ;	2FE8	10	07	;	2310	07			
  15550 ;	2FEA	11	08	;	2311	08				
  15551 ;	2FEC	18	C0	;	2318	C0
  15552 ;
  15553 ;------------------	; G007_DISPLAY_OFFSET_FROM_DFILE_LESS_9 = E675 (6675 echoed in top 32K ???)
  15554 L2FDC:	defb	$00	;	2300	75
  15555 	defb	$75
  15556 ;------------------
  15557 L2FDE:	defb	$01	;	2301	E6
  15558 	defb	$E6
  15559 ;------------------
  15560 L2FE0:	defb	$0A         
  15561 ;------------------
  15562 L2FE1:	defb	$55	;	2355	0D
  15563 L2FE2:	defb	$0D
  15564 ;------------------
  15565 L2FE3:	defb	$1E	;	231E	0F
  15566 L2FE4:	defb	$0F
  15567 ;------------------
  15568 	defb	$1E	; some kind of marker?
  15569 ;------------------
  15570 L2FE6:	defb	$16	;	2316	20           
  15571 	defb	$20
  15572 ;------------------	; G007_PLOT_ROUTINES_VECTOR = G007_PLOT_ROUTINES_VECTOR_DEFAULT = $0807
  15573 L2FE8:	defb	$10	;	2310	07	
  15574 	defb	$07
  15575 ;------------------
  15576 L2FEA:	defb	$11	;	2311	08
  15577 	defb	$08
  15578 ;------------------
  15579 L2FEC:	defb	$18	;	2318	C0	
  15580 	defb	$C0
  15581 ;------------------
  15582 L2FEE:	defb	$35	;	2335	EE	
  15583 	defb	$EE
  15584 ;------------------
  15585 L2FF0:	defb	$36	;	2336	55
  15586 	defb	$55
  15587 ;------------------
  15588 L2FF2:	defb	$37	;	2337	C6
  15589 	defb	$C6
  15590 ;------------------
  15591 ;	The values below were seen in RAM but are not initialised from this table:	
  15592 ;	
  15593 ;	2306	84	4084	G007_DISPLAY_ADDRESS_LESS_9	
  15594 ;	2307	40	
  15595 ;	2308	8D	408D	G007_DISPLAY_ADDRESS	
  15596 ;	2309	40	
  15597 ;	230A	55 00	55,00	G007_TRIANGLE_TEXTURE	
  15598 ;	230C	00	1E00	Character table address for CHR$0-63	
  15599 ;	230D	1E	
  15600 ;	230E	00	1E00	Character table address for CHR$128-159	
  15601 ;	230F	1E
  15602 ;------------------
  15603 ;	 Modding offsets in copied code:
  15604 ;------------------
  15605 ;	07FD	CD	08	08	CALL $0808	; [ENTER-CH]	
  15606 ;	23AC	CD	E6	2E	CALL $2EE6	
  15607 ;
  15608 L2FF4:	defb	$AD
  15609 	defb	$E6
  15610 	defb	$AE
  15611 	defb	$2E
  15612 ;------------------
  15613 ;	0843	FD	35	39	DEC (IY+SPOSN-RAMBASE)	
  15614 ;	23F2	C3	1D	2F	JP $2F1D
  15615 ;
  15616 L2FF8:	defb	$F2
  15617 	defb	$C3
  15618 
  15619 	defb	$F3
  15620 	defb	$1D
  15621 
  15622 	defb	$F4
  15623 	defb	$2F
  15624 ;------------------
  15625 ;
  15626 ;	083E	77	LD (HL),A	; WRITE-CH
  15627 ;	23ED	00	NOP		; WRITE-CH modified!
  15628 ;
  15629 L2FFE:	defb	$ED
  15630 	defb	$00                 
  15631 ;------------------
  15632 
  15633 
  15634 
  15635 
  15636 
  15637 
  15638 
  15639 
  15640 
  15641 
  15642 
  15643 
  15644 
  15645 
  15646 
  15647 
  15648 
  15649 
  15650 
  15651 
  15652 
  15653 
  15654 
  15655 ; end of g007 stuff
  15656 ;
  15657 #endif
  15658 
  15659 
  15660 
  15661 #code   $3800,$0800
  15662 
  15663 
  15664 
  15665 
  15666 #if 1
  15667 
  15668 mark_3800:	DEFB	 $21, $00, $38		;	ld	hl,Source
  15669 mark_3803:	DEFB	 $11, $00, $78		;	ld	de,Destination
  15670 mark_3806:	DEFB	 $01, $00, $08		;	ld	bc,MonitorSize
  15671 mark_3809:	DEFB	 $ED, $B0		;	ldir
  15672 mark_380B:	DEFB	 $3E, $74		;	ld	a,74
  15673 mark_380D:	DEFB	 $32, $05, $40		;	ld	(RamtopHi),a
  15674 mark_3810:	DEFB	 $CD, $C3, $03		;	call	New
  15675 
  15676 mark_3813:	DEFB	 $3E, $01		;	ld	a,01
  15677 mark_3815:	DEFB	 $01, $93, $7B		;	ld	bc,Input_Prompt_Data
  15678 mark_3818:	DEFB	 $CD, $02, $79		;	call	Get_A_addresses
  15679 mark_381B:	DEFB	 $CD, $2A, $0A		;	call	Cls
  15680 mark_381E:	DEFB	 $ED, $6B, $F8, $7F	;	ld	hl,Next_Address
  15681 mark_3822:	DEFB	 $E9		;	jp	(hl)
  15682 
  15683 ; Routine 0 the disassembler
  15684 mark_3823:	DEFB	 $CD, $FD, $78, $CD, $09
  15685 mark_3828:	DEFB	 $79, $18, $05, $16, $13, $CD, $53, $7B
  15686 mark_3830:	DEFB	 $CD, $81, $7B, $30, $05, $AF, $32, $21
  15687 mark_3838:	DEFB	 $40, $C9
  15688 mark_383A:	DEFB	 $21, $7B, $40, $36, $30, $23
  15689 mark_3840:	DEFB	 $36, $78, $CD, $2E, $7A, $CD, $72, $7A
  15690 mark_3848:	DEFB	 $78, $FE, $76, $20, $08, $21, $F5, $7C
  15691 mark_3850:	DEFB	 $CD, $A4, $7B, $18, $D6, $FE, $CB, $28
  15692 mark_3858:	DEFB	 $32, $FE, $ED, $28, $38, $FE, $DD, $28
  15693 mark_3860:	DEFB	 $44, $FE, $FD, $28, $44, $CD, $4F, $7A
  15694 mark_3868:	DEFB	 $2E, $24, $FE, $00, $28, $11, $2E, $2C
  15695 mark_3870:	DEFB	 $FE, $01, $28, $0E, $2C, $FE, $02, $28
  15696 mark_3878:	DEFB	 $09, $3E, $5E, $32, $42, $7D, $2C, $7D
  15697 mark_3880:	DEFB	 $81, $6F, $26, $7D, $6E, $EB, $CD, $D4
  15698 mark_3888:	DEFB	 $7A, $18, $A0, $CD, $72, $7A, $CD, $4F
  15699 mark_3890:	DEFB	 $7A, $C6, $36, $18, $EC, $CD, $72, $7A
  15700 mark_3898:	DEFB	 $CD, $4F, $7A, $2E, $18, $FE, $01, $28
  15701 mark_38A0:	DEFB	 $DE, $2E, $20, $18, $DA, $3E, $0B, $18
  15702 mark_38A8:	DEFB	 $02, $3E, $0D, $32, $41, $7D, $3E, $12
  15703 mark_38B0:	DEFB	 $32, $40, $7D, $2A, $F8, $7F, $23, $7E
  15704 mark_38B8:	DEFB	 $21, $16, $7D, $CD, $89, $7A, $23, $CB
  15705 mark_38C0:	DEFB	 $BE, $CD, $72, $7A, $78, $FE, $CB, $20
  15706 mark_38C8:	DEFB	 $05, $CD, $72, $7A, $18, $BD, $CD, $4F
  15707 mark_38D0:	DEFB	 $7A, $FE, $03, $28, $93, $F5, $C5, $FE
  15708 mark_38D8:	DEFB	 $00, $20, $05, $3E, $06, $B8, $20, $03
  15709 mark_38E0:	DEFB	 $CD, $72, $7A, $C1, $F1, $18, $81
  15710 
  15711 ; Spare bytes
  15712 mark_38E7:	DEFB	 $00
  15713 mark_38E8:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  15714 mark_38F0:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  15715 mark_38F8:	DEFB	 $00, $00, $00, $00, $00
  15716 
  15717 ; Start/Finish Addresses
  15718 ; prints request for input then calls input address routine
  15719 mark_38FD:	DEFB	 $01, $93, $7B
  15720 mark_3900:	DEFB	 $3E, $02
  15721 
  15722 ; Get_A_addresses
  15723 mark_3902:	DEFB	 $11, $F8, $7F, $CD, $14, $7A, $C9
  15724 
  15725 ; Check printer
  15726 mark_3909:	DEFB	 $11, $E1, $10, $CD, $3B, $7B, $2B
  15727 mark_3910:	DEFB	 $7E, $21, $21, $40, $36, $83, $FD, $CB
  15728 mark_3918:	DEFB	 $01, $CE, $FE, $1D, $C4, $2A, $0A, $C9
  15729 
  15730 ; routine 1:	DEFB	 hex dump
  15731 mark_3920:	DEFB	 $CD, $FD, $78, $CD, $09, $79, $21, $F9
  15732 mark_3928:	DEFB	 $7C, $CD, $9F, $7B, $21, $7B, $40, $36
  15733 mark_3930:	DEFB	 $33, $23, $36, $79, $CD, $81, $7B, $F8
  15734 mark_3938:	DEFB	 $CD, $3D, $7A, $0E, $08, $CD, $72, $7A
  15735 mark_3940:	DEFB	 $0D, $28, $0B, $CD, $81, $7B, $30, $F5
  15736 mark_3948:	DEFB	 $16, $0B, $CD, $53, $7B, $C9
  15737 mark_394E:	DEFB	 $CD, $48, $79, $18, $E1
  15738 
  15739 ; routine 2:	DEFB	 write
  15740 mark_3953:	DEFB	 $3E, $01, $01, $93, $7B
  15741 mark_3958:	DEFB	 $CD, $02, $79, $CD, $2A, $0A, $CD, $0E
  15742 mark_3960:	DEFB	 $0C, $CD, $3D, $7A, $11, $E8, $1C, $CD
  15743 mark_3968:	DEFB	 $A5, $7F, $CB, $45, $28, $05, $CD, $AD
  15744 mark_3970:	DEFB	 $7F, $18, $F7, $ED, $5B, $F8, $7F, $CD
  15745 mark_3978:	DEFB	 $0B, $7B, $ED, $53, $F8, $7F, $3E, $76
  15746 mark_3980:	DEFB	 $D7, $18, $DB
  15747 
  15748 ; prints data associated with RST 08 or RST 28
  15749 mark_3983:	DEFB	 $0D, $20, $24, $0E, $04
  15750 mark_3988:	DEFB	 $16, $13, $CD, $53, $7B, $18, $18, $78
  15751 mark_3990:	DEFB	 $FE, $01, $20, $1A, $21, $7B, $40, $36
  15752 mark_3998:	DEFB	 $62, $23, $36, $7A, $16, $13, $CD, $53
  15753 mark_39A0:	DEFB	 $7B, $21, $F9, $7C, $CD, $9F, $7B, $CD
  15754 mark_39A8:	DEFB	 $3D, $7A, $CD, $72, $7A, $C9
  15755 mark_39AE:	DEFB	 $FE, $05
  15756 mark_39B0:	DEFB	 $C0, $21, $7B, $40, $36, $68, $23, $36
  15757 mark_39B8:	DEFB	 $7A, $0E, $04, $CD, $9C, $79, $78, $FE
  15758 mark_39C0:	DEFB	 $34, $C8, $CD, $83, $79, $18, $F7
  15759 
  15760 ; Data Calculates absolute address for JR instructions
  15761 ; and adds number and addresses to mnemonic
  15762 mark_39C7:	DEFB	 $CD
  15763 mark_39C8:	DEFB	 $72, $7A, $AF, $CB, $78, $28, $01, $2F
  15764 mark_39D0:	DEFB	 $48, $47, $2A, $F8, $7F, $09, $EB, $21
  15765 mark_39D8:	DEFB	 $00, $7D, $7B, $CD, $89, $7A, $2B, $7A
  15766 mark_39E0:	DEFB	 $CD, $89, $7A, $23, $CB, $BE, $2B, $18
  15767 mark_39E8:	DEFB	 $1B, $CD, $72, $7A, $2B, $18, $15, $CD
  15768 mark_39F0:	DEFB	 $07, $7A, $18, $10, $CD, $72, $7A, $2B
  15769 mark_39F8:	DEFB	 $18, $03, $CD, $07, $7A, $2B, $CD, $A4
  15770 mark_3A00:	DEFB	 $7B, $21, $0D, $7C, $C3, $A4, $7B, $21
  15771 mark_3A08:	DEFB	 $00, $7D, $CD, $75, $7A, $CD, $72, $7A
  15772 mark_3A10:	DEFB	 $CB, $BE, $2B, $C9
  15773 
  15774 ; Input_Address
  15775 mark_3A14:	DEFB	 $F5, $D5, $11, $E4
  15776 mark_3A18:	DEFB	 $10, $CD, $3B, $7B, $7D, $BB, $28, $05
  15777 mark_3A20:	DEFB	 $CD, $AD, $7F, $18, $F7, $D1, $CD, $21
  15778 mark_3A28:	DEFB	 $7B, $F1, $3D, $20, $E7, $C9
  15779 
  15780 ; Initial
  15781 mark_3A2E:	DEFB	 $21, $42
  15782 mark_3A30:	DEFB	 $7D, $36, $5C, $2B, $36, $09, $2B, $36
  15783 mark_3A38:	DEFB	 $0F, $2B, $2B, $36, $E0
  15784 
  15785 ; Next_Address
  15786 mark_3A3D:	DEFB	 $11, $F9, $7F
  15787 mark_3A40:	DEFB	 $21, $FE, $7C, $1A, $CD, $7F, $7A, $1B
  15788 mark_3A48:	DEFB	 $1A, $CD, $7F, $7A, $AF, $D7, $C9
  15789 
  15790 ; Octal
  15791 mark_3A4F:	DEFB	 $78
  15792 mark_3A50:	DEFB	 $E6, $07, $4F, $78, $F5, $E6, $38, $0F
  15793 mark_3A58:	DEFB	 $0F, $0F, $47, $F1, $E6, $C0, $07, $CB
  15794 mark_3A60:	DEFB	 $07, $C9
  15795 
  15796 ; Cont, $RST
  15797 mark_3A62:	DEFB	 $CD, $A1, $79, $C3, $2B, $78
  15798 mark_3A68:	DEFB	 $0E, $04, $CD, $A1, $79, $CD, $BE, $79
  15799 mark_3A70:	DEFB	 $18, $F3
  15800 
  15801 ; Next_Byte
  15802 mark_3A72:	DEFB	 $21, $FE, $7C, $ED, $5B, $F8
  15803 mark_3A78:	DEFB	 $7F, $1A, $13, $ED, $53, $F8, $7F, $CD
  15804 mark_3A80:	DEFB	 $89, $7A, $D7, $23, $7E, $CB, $BF, $D7
  15805 mark_3A88:	DEFB	 $C9
  15806 mark_3A89:	DEFB	 $47, $E6, $0F, $C6, $1C, $CB, $FF
  15807 mark_3A90:	DEFB	 $77, $2B, $78, $E6, $F0, $1F, $1F, $1F
  15808 mark_3A98:	DEFB	 $1F, $C6, $1C, $77, $C9
  15809 
  15810 ; Offsets
  15811 mark_3A9D:	DEFB	 $CB, $40, $20
  15812 mark_3AA0:	DEFB	 $19, $CD, $B3, $7A, $13, $C9
  15813 mark_3AA6:	DEFB	 $3E, $01
  15814 mark_3AA8:	DEFB	 $CB, $40, $20, $1E, $18, $05, $CB, $40
  15815 mark_3AB0:	DEFB	 $28, $0F, $13, $AF, $18, $14, $CB, $40
  15816 mark_3AB8:	DEFB	 $28, $07, $13, $78, $CB, $87, $0F, $18
  15817 mark_3AC0:	DEFB	 $09, $CD, $BB, $7A, $13, $C9
  15818 mark_3AC7:	DEFB	 $78, $18
  15819 mark_3AC8:	DEFB	 $01, $79, $13, $62, $6B, $6E, $26, $7C
  15820 mark_3AD0:	DEFB	 $CD, $A5, $7B, $C9
  15821 
  15822 ; Control
  15823 mark_3AD4:	DEFB	 $1A, $F5, $E6, $07
  15824 mark_3AD8:	DEFB	 $21, $DD, $7A, $18, $1E, $F1, $F5, $CB
  15825 mark_3AE0:	DEFB	 $77, $28, $0D, $2A, $3E, $7D, $CB, $55
  15826 mark_3AE8:	DEFB	 $36, $00, $23, $28, $F9, $22, $3E, $7D
  15827 mark_3AF0:	DEFB	 $E6, $38, $0F, $0F, $CB, $0F, $28, $0C
  15828 mark_3AF8:	DEFB	 $21, $04, $7B, $E5, $3C, $26, $7D, $6F
  15829 mark_3B00:	DEFB	 $6E, $26, $7A, $E9, $F1, $CB, $7F, $C0
  15830 mark_3B08:	DEFB	 $13, $18, $C9
  15831 
  15832 ; Transfer
  15833 mark_3B0B:	DEFB	 $C5, $7D, $2E, $E0, $95
  15834 mark_3B10:	DEFB	 $0F, $47, $7E, $CD, $8C, $7B, $23, $86
  15835 mark_3B18:	DEFB	 $D6, $1C, $12, $13, $23, $10, $F3, $C1
  15836 mark_3B20:	DEFB	 $C9
  15837 mark_3B21:	DEFB	 $C5, $06, $02, $2B, $4E, $2B, $7E
  15838 mark_3B28:	DEFB	 $CD, $8C, $7B, $81, $D6, $1C, $12, $13
  15839 mark_3B30:	DEFB	 $10, $F2, $C1, $3E, $76, $D7, $D7, $C9
  15840 
  15841 mark_3B38:	DEFB	 $11, $EF, $10, $CD, $33, $78, $26, $7E
  15842 mark_3B40:	DEFB	 $0A, $6F, $CD, $9F, $7B, $03, $0A, $6F
  15843 mark_3B48:	DEFB	 $03, $CD, $A4, $7B, $CD, $53, $7B, $CD
  15844 mark_3B50:	DEFB	 $A5, $7F, $C9
  15845 
  15846 ; Print_String
  15847 mark_3B53:	DEFB	 $C5, $D5, $E5, $FD, $CB
  15848 mark_3B58:	DEFB	 $21, $46, $28, $08, $ED, $4B, $39, $40
  15849 mark_3B60:	DEFB	 $4A, $CD, $0B, $09, $11, $E0, $7F, $ED
  15850 mark_3B68:	DEFB	 $4B, $3E, $7D, $06, $00, $79, $D6, $E0
  15851 mark_3B70:	DEFB	 $4F, $CD, $6B, $0B, $FD, $CB, $21, $4E
  15852 mark_3B78:	DEFB	 $28, $03, $3E, $76, $D7, $E1, $D1, $C1
  15853 mark_3B80:	DEFB	 $C9
  15854 
  15855 ; Check_Finish
  15856 mark_3B81:	DEFB	 $2A, $FA, $7F, $ED, $5B, $F8, $7F
  15857 mark_3B88:	DEFB	 $A7, $ED, $52, $C9
  15858 mark_3B8C:	DEFB	 $D6, $1C, $07, $07
  15859 mark_3B90:	DEFB	 $07, $07, $C9
  15860 
  15861 ; data for input prompt messages
  15862 mark_3B93:	DEFB	 $DD, $E3, $EB, $E3, $F2
  15863 mark_3B98:	DEFB	 $F8, $D5, $DC, $30, $E3, $D0, $E3
  15864 
  15865 ; Add_String, for building mnemonic
  15866 mark_3B9F:	DEFB	 $3E
  15867 mark_3BA0:	DEFB	 $E0, $32, $3E, $7D, $AF, $C5, $D5, $A7
  15868 mark_3BA8:	DEFB	 $28, $0B, $CB, $7E, $20, $03, $23, $18
  15869 mark_3BB0:	DEFB	 $F9, $3D, $23, $18, $F2, $CD, $BB, $7B
  15870 mark_3BB8:	DEFB	 $D1, $C1, $C9
  15871 mark_3BBB:	DEFB	 $ED, $5B, $3E, $7D, $7E
  15872 mark_3BC0:	DEFB	 $CB, $7F, $20, $05, $CD, $CB, $7B, $18
  15873 mark_3BC8:	DEFB	 $F2, $CB, $BF, $FE, $40, $30, $08, $12
  15874 mark_3BD0:	DEFB	 $13, $ED, $53, $3E, $7D, $23, $C9
  15875 mark_3BD7:	DEFB	 $23
  15876 mark_3BD8:	DEFB	 $ED, $53, $3E, $7D, $E5, $FE, $43, $30
  15877 mark_3BE0:	DEFB	 $06, $26, $7D, $6F, $6E, $18, $14, $FE
  15878 mark_3BE8:	DEFB	 $64, $30, $05, $26, $7D, $6F, $18, $0B
  15879 mark_3BF0:	DEFB	 $21, $FE, $7B, $E5, $26, $7D, $6F, $6E
  15880 mark_3BF8:	DEFB	 $26, $79, $E9, $CD, $BB, $7B, $E1, $C9
  15881 ;
  15882 ; data for mnemonics
  15883 ; lower case are ZX inverse characters
  15884 ;          
  15885 mark_3C00: DEFB  $A7, $A8, $A9, $AA, $AD, $B1, $C0, $A6
  15886 mark_3C08: DEFB  $A6, $C1, $A6, $10, $43, $91, $10, $45
  15887 mark_3C10: DEFB  $91, $E7, $E7, $C3, $C5, $C1, $C2, $62
  15888 mark_3C18: DEFB  $A8, $45, $A8, $47, $D6, $49, $D6, $47
  15889 mark_3C20: DEFB  $A6, $49, $A6, $29, $26, $A6, $28, $35
  15890 mark_3C28: DEFB  $B1, $38, $28, $AB, $28, $28, $AB, $9C
  15891 mark_3C30: DEFB  $9D, $9E, $9F, $A0, $A1, $A2, $A3, $35
  15892 mark_3C38: DEFB  $3A, $38, $AD, $56, $31, $B1, $37, $2A
  15893 mark_3C40: DEFB  $B9, $4B, $BD, $2F, $B5, $CD, $58, $A9
  15894 mark_3C48: DEFB  $58, $A8, $38, $3A, $A7, $38, $C3, $26
  15895 mark_3C50: DEFB  $33, $A9, $3D, $34, $B7, $34, $B7, $28
  15896 mark_3C58: DEFB  $B5, $35, $34, $B5, $37, $38, $B9, $2F
  15897 mark_3C60: DEFB  $B5, $80, $D3, $E2, $CB, $CB, $29, $AE
  15898 mark_3C68: DEFB  $2A, $AE, $E5, $E8, $66, $1A, $A6, $4F
  15899 mark_3C70: DEFB  $E6, $10, $5C, $11, $DA, $45, $DA, $80
  15900 mark_3C78: DEFB  $80, $10, $41, $91, $5C, $DA, $CF, $CF
  15901 mark_3C80: DEFB  $80, $CF, $80, $80, $80, $80, $33, $BF
  15902 mark_3C88: DEFB  $BF, $33, $A8, $A8, $35, $B4, $35, $AA
  15903 mark_3C90: DEFB  $B5, $B2, $47, $A8, $49, $A8, $C7, $C9
  15904 mark_3C98: DEFB  $38, $31, $A6, $38, $37, $A6, $E4, $38
  15905 mark_3CA0: DEFB  $C7, $27, $2E, $B9, $37, $2A, $B8, $38
  15906 mark_3CA8: DEFB  $2A, $B9, $10, $28, $91, $33, $2A, $AC
  15907 mark_3CB0: DEFB  $B3, $AE, $38, $C3, $58, $A8, $2E, $B2
  15908 mark_3CB8: DEFB  $9C, $A4, $9D, $9E, $CD, $CD, $CD, $CD
  15909 mark_3CC0: DEFB  $49, $A9, $47, $A9, $2E, $9A, $37, $9A
  15910 mark_3CC8: DEFB  $CF, $CF, $80, $80, $5E, $1A, $DE, $E9
  15911 mark_3CD0: DEFB  $E9, $E0, $E0, $E0, $E0, $A6, $A6, $AE
  15912 mark_3CD8: DEFB  $B7, $80, $80, $AE, $A9, $2E, $B7, $29
  15913 mark_3CE0: DEFB  $B7, $CD, $28, $B5, $E2, $D3, $34, $B9
  15914 mark_3CE8: DEFB  $33, $34, $B5, $CB, $29, $2F, $33, $BF
  15915 mark_3CF0: DEFB  $D1, $D1, $D1, $D1, $D1, $2D, $26, $31
  15916 mark_3CF8: DEFB  $B9, $45, $2B, $A7, $10, $1D, $A9, $27
  15917 ;          
  15918 ; data and data pointers for disassembler    
  15919 ;          
  15920 mark_3D00: DEFB  $9F, $A6, $C9, $B3, $AE, $BB, $9D, $B6
  15921 mark_3D08: DEFB  $C6, $2D, $B1, $2E, $BD, $2E, $BE, $10
  15922 mark_3D10: DEFB  $41, $91, $10, $41, $15, $2A, $27, $91
  15923 mark_3D18: DEFB  $CD, $D3, $D9, $DF, $3C, $E8, $EB, $EE
  15924 mark_3D20: DEFB  $F3, $F3, $F3, $F5, $91, $81, $89, $6D
  15925 mark_3D28: DEFB  $6A, $F9, $7B, $3A, $70, $9C, $A1, $76
  15926 mark_3D30: DEFB  $A4, $AA, $AD, $FC, $B3, $96, $B8, $BB
  15927 mark_3D38: DEFB  $C1, $C7, $87, $1B, $81, $A1, $E4, $7F
  15928 mark_3D40: DEFB  $0F, $09, $5C, $27, $A8, $29, $AA, $37
  15929 mark_3D48: DEFB  $B1, $37, $B7, $2A, $BD, $31, $A9, $26
  15930 mark_3D50: DEFB  $9A, $2F, $B7, $34, $3A, $B9, $28, $A6
  15931 mark_3D58: DEFB  $26, $A9, $1A, $C1, $38, $B5, $26, $AB
  15932 mark_3D60: DEFB  $1A, $E9, $2E, $B3, $E9, $EF, $F4, $FA
  15933 mark_3D68: DEFB  $8F, $C7, $FA, $17, $00, $E0, $17, $13
  15934 mark_3D70: DEFB  $7A, $45, $00, $8A, $C5, $00, $F5, $59
  15935 mark_3D78: DEFB  $3E, $13, $77, $7A, $45, $00, $92, $C5
  15936 mark_3D80: DEFB  $9E, $58, $45, $13, $15, $AA, $C5, $6A
  15937 mark_3D88: DEFB  $13, $72, $45, $0B, $07, $B2, $C5, $07
  15938 mark_3D90: DEFB  $0B, $7F, $E8, $82, $87, $CB, $62, $5C
  15939 mark_3D98: DEFB  $2F, $90, $B8, $6B, $7F, $46, $7E, $81
  15940 mark_3DA0: DEFB  $00, $FA, $3E, $86, $7A, $43, $86, $92
  15941 mark_3DA8: DEFB  $C5, $6A, $FF, $5F, $6A, $7A, $3B, $86
  15942 mark_3DB0: DEFB  $92, $C5, $6A, $7F, $46, $7E, $82, $9E
  15943 mark_3DB8: DEFB  $CF, $92, $00, $7A, $A1, $2F, $8A, $C5
  15944 mark_3DC0: DEFB  $00, $7A, $A4, $2F, $8A, $C5, $00, $7A
  15945 mark_3DC8: DEFB  $A7, $2F, $8A, $C5, $00, $7A, $63, $00
  15946 mark_3DD0: DEFB  $92, $C5, $AA, $52, $62, $AA, $BA, $C5
  15947 mark_3DD8: DEFB  $00, $50, $B2, $15, $A2, $C5, $13, $6A
  15948 mark_3DE0: DEFB  $45, $11, $13, $9A, $C5, $13, $11, $00
  15949 mark_3DE8: DEFB  $BA, $3E, $B0, $FA, $B6, $B8, $7F, $BC
  15950 mark_3DF0: DEFB  $C4, $87, $D5, $B9, $E1, $D7, $BC, $E2
  15951 mark_3DF8: DEFB  $D7, $FA, $19, $00, $D8, $37, $13, $6A
  15952 ;
  15953 ; print data for menu & routines
  15954 ;
  15955 mark_3E00:	DEFB	 $00, $00, $00, $00, $32, $2A, $33, $BA
  15956 mark_3E08:	DEFB	 $00, $00, $00, $00, $14, $14, $14, $94
  15957 mark_3E10:	DEFB	 $1C, $00, $35, $37, $2E, $33, $39, $00
  15958 mark_3E18:	DEFB	 $28, $34, $29, $AA, $1D, $00, $2D, $2A
  15959 mark_3E20:	DEFB	 $3D, $00, $29, $3A, $32, $B5, $1E, $00
  15960 mark_3E28:	DEFB	 $3C, $37, $2E, $39, $AA, $1F, $00, $2E
  15961 mark_3E30:	DEFB	 $33, $38, $2A, $37, $B9, $20, $00, $29
  15962 mark_3E38:	DEFB	 $2A, $31, $2A, $39, $AA, $21, $00, $39
  15963 mark_3E40:	DEFB	 $37, $26, $33, $38, $2B, $2A, $B7, $22
  15964 mark_3E48:	DEFB	 $00, $38, $2A, $26, $37, $28, $AD, $23
  15965 mark_3E50:	DEFB	 $00, $37, $2A, $35, $31, $26, $28, $AA
  15966 mark_3E58:	DEFB	 $24, $00, $26, $38, $38, $2A, $32, $27
  15967 mark_3E60:	DEFB	 $31, $2A, $B7, $25, $00, $37, $3A, $33
  15968 mark_3E68:	DEFB	 $00, $28, $34, $29, $AA, $26, $00, $28
  15969 mark_3E70:	DEFB	 $26, $31, $28, $3A, $31, $26, $39, $34
  15970 mark_3E78:	DEFB	 $B7, $27, $00, $28, $2D, $37, $0D, $00
  15971 mark_3E80:	DEFB	 $29, $3A, $32, $B5, $28, $00, $26, $38
  15972 mark_3E88:	DEFB	 $28, $2E, $2E, $00, $29, $3A, $32, $B5
  15973 mark_3E90:	DEFB	 $29, $00, $37, $2A, $33, $3A, $32, $27
  15974 mark_3E98:	DEFB	 $2A, $B7, $2A, $00, $2E, $32, $26, $2C
  15975 mark_3EA0:	DEFB	 $2A, $B7, $2B, $00, $32, $2A, $33, $3A
  15976 mark_3EA8:	DEFB	 $00, $9E, $80, $80, $00, $00, $00, $00
  15977 mark_3EB0:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  15978 mark_3EB8:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  15979 mark_3EC0:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  15980 mark_3EC8:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  15981 mark_3ED0:	DEFB	 $31, $2E, $32, $2E, $B9, $37, $34, $3A
  15982 mark_3ED8:	DEFB	 $39, $2E, $33, $2A, $80, $38, $39, $26
  15983 mark_3EE0:	DEFB	 $37, $39, $80, $26, $29, $29, $37, $2A
  15984 mark_3EE8:	DEFB	 $38, $38, $80, $2B, $2E, $33, $2E, $38
  15985 mark_3EF0:	DEFB	 $2D, $80, $1D, $00, $2B, $34, $37, $80
  15986 mark_3EF8:	DEFB	 $35, $37, $2E, $33, $39, $2A, $37, $80
  15987 
  15988 ; addresses of routines
  15989 mark_3F00:	DEFB	 $23, $78	;, $.dw, $7823
  15990 mark_3F02:	DEFB	 $20, $79	; , $.dw, $7902
  15991 mark_3F04:	DEFB	 $53, $79	;, $.dw, $7953
  15992 mark_3F06:	DEFB	 $FF, $FF
  15993 mark_3F08:	DEFB	 $FF, $FF
  15994 mark_3F0A:	DEFB	 $FF, $FF
  15995 mark_3F0C:	DEFB	 $FF, $FF
  15996 mark_3F0E:	DEFB	 $FF, $FF
  15997 mark_3F10:	DEFB	 $FF, $FF
  15998 mark_3F12:	DEFB	 $13, $38	;, $.dw, $3813
  15999 mark_3F14:	DEFB	 $FF, $FF
  16000 mark_3F16:	DEFB	 $FF, $FF
  16001 mark_3F18:	DEFB	 $FF, $FF
  16002 mark_3F1A:	DEFB	 $FF, $FF
  16003 mark_3F1C:	DEFB	 $FF, $FF
  16004 mark_3F1E:	DEFB	 $FF, $FF
  16005 
  16006 ; Read_Keyboard
  16007 mark_3F20:	DEFB	 $D5, $C5, $E5, $2A, $25, $40, $E5, $ED
  16008 mark_3F28:	DEFB	 $4B, $25, $40, $E1, $C5, $A7, $ED, $42
  16009 mark_3F30:	DEFB	 $28, $F5, $79, $3C, $28, $F1, $E1, $CD
  16010 mark_3F38:	DEFB	 $BD, $07, $7E, $E1, $C1, $D1, $FE, $76
  16011 mark_3F40:	DEFB	 $C8, $FE, $77, $C8, $FE, $00, $20, $05
  16012 mark_3F48:	DEFB	 $CD, $2A, $0A, $CF, $0C, $FE, $1C, $38
  16013 mark_3F50:	DEFB	 $CF, $FE, $2C, $30, $CB, $C9
  16014 ;
  16015 ; Menu
  16016 ;
  16017 mark_3F56:	DEFB	 $21, $21
  16018 mark_3F58:	DEFB	 $40, $CB, $7E, $28, $04, $2A, $7B, $40
  16019 mark_3F60:	DEFB	 $E9, $21, $00, $7E, $06, $14, $3E, $03
  16020 mark_3F68:	DEFB	 $32, $21, $40, $11, $E1, $18, $CD, $9F
  16021 mark_3F70:	DEFB	 $7B, $CD, $53, $7B, $10, $F8, $01, $99
  16022 mark_3F78:	DEFB	 $7B, $CD, $3B, $7B, $2B, $7E, $D6, $1C
  16023 mark_3F80:	DEFB	 $47, $07, $6F, $26, $7F, $7E, $23, $66
  16024 mark_3F88:	DEFB	 $6F, $E5, $C5, $CD, $2A, $0A, $C1, $3E
  16025 mark_3F90:	DEFB	 $E0, $32, $3E, $7D, $78, $21, $10, $7E
  16026 mark_3F98:	DEFB	 $CD, $A5, $7B, $16, $1A, $CD, $53, $7B
  16027 mark_3FA0:	DEFB	 $3E, $76, $D7, $D7, $C9
  16028 ;
  16029 ; InputString, the heart of all routines
  16030 ;
  16031 mark_3FA5:	DEFB	 $3E, $01, $32
  16032 mark_3FA8:	DEFB	 $21, $40, $21, $E0, $7F, $36, $17, $CD
  16033 mark_3FB0:	DEFB	 $C0, $7F, $CD, $20, $7F, $FE, $76, $20
  16034 mark_3FB8:	DEFB	 $10, $3E, $E0, $BD, $28, $F4, $36, $00
  16035 mark_3FC0:	DEFB	 $23, $22, $3E, $7D, $CD, $53, $7B, $2B
  16036 mark_3FC8:	DEFB	 $C9
  16037 mark_3FC9:	DEFB	 $FE, $77, $20, $0B, $3E, $E0, $BD
  16038 mark_3FD0:	DEFB	 $28, $DB, $CD, $BE, $7F, $2B, $18, $D5
  16039 mark_3FD8:	DEFB	 $77, $7B, $BD, $28, $D0, $23, $18, $CD
  16040 ;
  16041 ; mnemonic string, ram area for mnemonic to be built up
  16042 ;
  16043 mark_3FE0:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  16044 mark_3FE8:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  16045 ;
  16046 ; spare bytes
  16047 ;
  16048 mark_3FF0:	DEFB	 $00, $00, $00, $00, $00, $00, $00, $00
  16049 ;
  16050 ; next address for routine
  16051 ;
  16052 mark_3FF8:	DEFB	 $00, $00
  16053 ;
  16054 ; finish address for routine
  16055 ;
  16056 mark_3FFA:	DEFB	 $00, $00
  16057 ;
  16058 ; spare bytes
  16059 ;
  16060 mark_3FFC:	DEFB	 $00, $00, $00
  16061 mark_3FFF:	DEFB	 $C9	;	ret
  16062 
  16063 
  16064 #else
  16065 ;
  16066 ;
  16067 ;
  16068 Input_Prompt_Data	equ	$7B93
  16069 Get_A_addresses		equ	$7902
  16070 Next_Address		equ	$7FFB
  16071 #endif
  16072 
  16073 
  16074 
  16075 
  16076 
  16077 
  16078 
  16079 
  16080 #end					; required by zasm
  16081 
  16082